diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 90 | 
1 files changed, 77 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2b6ce9b2674..4154bcd7a07 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)  	if (HAS_PCH_CPT(dev))  		intel_cpt_verify_modeset(dev, intel_crtc->pipe); + +	/* +	 * There seems to be a race in PCH platform hw (at least on some +	 * outputs) where an enabled pipe still completes any pageflip right +	 * away (as if the pipe is off) instead of waiting for vblank. As soon +	 * as the first vblank happend, everything works as expected. Hence just +	 * wait for one vblank before returning to avoid strange things +	 * happening. +	 */ +	intel_wait_for_vblank(dev, intel_crtc->pipe);  }  static void ironlake_crtc_disable(struct drm_crtc *crtc) @@ -3831,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  			}  		} +		if (intel_encoder->type == INTEL_OUTPUT_EDP) { +			/* Use VBT settings if we have an eDP panel */ +			unsigned int edp_bpc = dev_priv->edp.bpp / 3; + +			if (edp_bpc < display_bpc) { +				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); +				display_bpc = edp_bpc; +			} +			continue; +		} +  		/*  		 * HDMI is either 12 or 8, so if the display lets 10bpc sneak  		 * through, clamp it down.  (Note: >12bpc will be caught below.) @@ -7882,6 +7903,34 @@ struct intel_quirk {  	void (*hook)(struct drm_device *dev);  }; +/* For systems that don't have a meaningful PCI subdevice/subvendor ID */ +struct intel_dmi_quirk { +	void (*hook)(struct drm_device *dev); +	const struct dmi_system_id (*dmi_id_list)[]; +}; + +static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) +{ +	DRM_INFO("Backlight polarity reversed on %s\n", id->ident); +	return 1; +} + +static const struct intel_dmi_quirk intel_dmi_quirks[] = { +	{ +		.dmi_id_list = &(const struct dmi_system_id[]) { +			{ +				.callback = intel_dmi_reverse_brightness, +				.ident = "NCR Corporation", +				.matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), +					    DMI_MATCH(DMI_PRODUCT_NAME, ""), +				}, +			}, +			{ }  /* terminating entry */ +		}, +		.hook = quirk_invert_brightness, +	}, +}; +  static struct intel_quirk intel_quirks[] = {  	/* HP Mini needs pipe A force quirk (LP: #322104) */  	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, @@ -7892,8 +7941,7 @@ static struct intel_quirk intel_quirks[] = {  	/* ThinkPad T60 needs pipe A force quirk (bug #16494) */  	{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, -	/* 855 & before need to leave pipe A & dpll A up */ -	{ 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, +	/* 830/845 need to leave pipe A & dpll A up */  	{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },  	{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, @@ -7922,6 +7970,10 @@ static void intel_init_quirks(struct drm_device *dev)  		     q->subsystem_device == PCI_ANY_ID))  			q->hook(dev);  	} +	for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { +		if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) +			intel_dmi_quirks[i].hook(dev); +	}  }  /* Disable the VGA plane that we never use */ @@ -8049,29 +8101,42 @@ static void intel_enable_pipe_a(struct drm_device *dev)  } +static bool +intel_check_plane_mapping(struct intel_crtc *crtc) +{ +	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; +	u32 reg, val; + +	if (dev_priv->num_pipe == 1) +		return true; + +	reg = DSPCNTR(!crtc->plane); +	val = I915_READ(reg); + +	if ((val & DISPLAY_PLANE_ENABLE) && +	    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) +		return false; + +	return true; +} +  static void intel_sanitize_crtc(struct intel_crtc *crtc)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 reg, val; +	u32 reg;  	/* Clear any frame start delays used for debugging left by the BIOS */  	reg = PIPECONF(crtc->pipe);  	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);  	/* We need to sanitize the plane -> pipe mapping first because this will -	 * disable the crtc (and hence change the state) if it is wrong. */ -	if (!HAS_PCH_SPLIT(dev)) { +	 * disable the crtc (and hence change the state) if it is wrong. Note +	 * that gen4+ has a fixed plane -> pipe mapping.  */ +	if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {  		struct intel_connector *connector;  		bool plane; -		reg = DSPCNTR(crtc->plane); -		val = I915_READ(reg); - -		if ((val & DISPLAY_PLANE_ENABLE) == 0 && -		    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) -			goto ok; -  		DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",  			      crtc->base.base.id); @@ -8095,7 +8160,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)  		WARN_ON(crtc->active);  		crtc->base.enabled = false;  	} -ok:  	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&  	    crtc->pipe == PIPE_A && !crtc->active) {  |