[1/5] drm/i915: Fix eDP DPCD aux max backlight calculations

Perr Yuan pyuan at redhat.com
Fri Dec 20 10:05:02 UTC 2019


On 11/22/19 6:15 PM, Lyude Paul wrote:
> Max backlight value for the panel was being calculated using byte
> count i.e. 0xffff if 2 bytes are supported for backlight brightness
> and 0xff if 1 byte is supported. However, EDP_PWMGEN_BIT_COUNT
> determines the number of active control bits used for the brightness
> setting. Thus, even if the panel uses 2 byte setting, it might not use
> all the control bits. Thus, max backlight should be set based on the
> value of EDP_PWMGEN_BIT_COUNT instead of assuming 65535 or 255.
> 
> Additionally, EDP_PWMGEN_BIT_COUNT was being updated based on the VBT
> frequency which results in a different max backlight value. Thus,
> setting of EDP_PWMGEN_BIT_COUNT is moved to setup phase instead of
> enable so that max backlight can be calculated correctly. Only the
> frequency divider is set during the enable phase using the value of
> EDP_PWMGEN_BIT_COUNT.
> 
> This is based off the original patch series from Furquan Shaikh
> <furquan at google.com>:
> 
> https://patchwork.freedesktop.org/patch/317255/?series=62326&rev=3
> 
> Changes since original patch:
> * Remove unused intel_dp variable in intel_dp_aux_setup_backlight()
> * Fix checkpatch issues
> * Make sure that we rewrite the pwmgen bit count whenever we bring the
>    panel out of D3 mode
> 
> Cc: Furquan Shaikh <furquan at google.com>
> Signed-off-by: Lyude Paul <lyude at redhat.com>
> ---
>   .../drm/i915/display/intel_display_types.h    |   3 +
>   .../drm/i915/display/intel_dp_aux_backlight.c | 139 ++++++++++++------
>   2 files changed, 95 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 83ea04149b77..2a8d8cae638e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -214,6 +214,9 @@ struct intel_panel {
>   		u8 controller;		/* bxt+ only */
>   		struct pwm_device *pwm;
>   
> +		/* DPCD backlight */
> +		u8 pwmgen_bit_count;
> +
>   		struct backlight_device *device;
>   
>   		/* Connector and platform specific backlight functions */
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> index 020422da2ae2..fad470553cf9 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> @@ -111,61 +111,28 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector)
>   {
>   	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>   	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
> -	int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
> -	u8 pn, pn_min, pn_max;
> +	const u8 pn = connector->panel.backlight.pwmgen_bit_count;
> +	int freq, fxp, f, fxp_actual, fxp_min, fxp_max;
>   
> -	/* Find desired value of (F x P)
> -	 * Note that, if F x P is out of supported range, the maximum value or
> -	 * minimum value will applied automatically. So no need to check that.
> -	 */
>   	freq = dev_priv->vbt.backlight.pwm_freq_hz;
> -	DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq);
>   	if (!freq) {
>   		DRM_DEBUG_KMS("Use panel default backlight frequency\n");
>   		return false;
>   	}
>   
>   	fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
> +	f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
> +	fxp_actual = f << pn;
>   
> -	/* Use highest possible value of Pn for more granularity of brightness
> -	 * adjustment while satifying the conditions below.
> -	 * - Pn is in the range of Pn_min and Pn_max
> -	 * - F is in the range of 1 and 255
> -	 * - FxP is within 25% of desired value.
> -	 *   Note: 25% is arbitrary value and may need some tweak.
> -	 */
> -	if (drm_dp_dpcd_readb(&intel_dp->aux,
> -			       DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
> -		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n");
> -		return false;
> -	}
> -	if (drm_dp_dpcd_readb(&intel_dp->aux,
> -			       DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
> -		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n");
> -		return false;
> -	}
> -	pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
> -	pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
> -
> +	/* Ensure frequency is within 25% of desired value */
>   	fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
>   	fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
> -	if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
> -		DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n");
> -		return false;
> -	}
> -
> -	for (pn = pn_max; pn >= pn_min; pn--) {
> -		f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
> -		fxp_actual = f << pn;
> -		if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
> -			break;
> -	}
>   
> -	if (drm_dp_dpcd_writeb(&intel_dp->aux,
> -			       DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
> -		DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
> +	if (fxp_min > fxp_actual || fxp_actual > fxp_max) {
> +		DRM_DEBUG_KMS("Actual frequency out of range\n");
>   		return false;
>   	}
> +
>   	if (drm_dp_dpcd_writeb(&intel_dp->aux,
>   			       DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) {
>   		DRM_DEBUG_KMS("Failed to write aux backlight freq\n");
> @@ -178,6 +145,7 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
>   					  const struct drm_connector_state *conn_state)
>   {
>   	struct intel_connector *connector = to_intel_connector(conn_state->connector);
> +	struct intel_panel *panel = &connector->panel;
>   	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
>   	u8 dpcd_buf, new_dpcd_buf, edp_backlight_mode;
>   
> @@ -197,6 +165,12 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
>   	case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT:
>   		new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
>   		new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
> +
> +		if (drm_dp_dpcd_writeb(&intel_dp->aux,
> +				       DP_EDP_PWMGEN_BIT_COUNT,
> +				       panel->backlight.pwmgen_bit_count) < 0)
> +			DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
> +
>   		break;
>   
>   	/* Do nothing when it is already DPCD mode */
> @@ -225,20 +199,91 @@ static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old
>   	set_aux_backlight_enable(enc_to_intel_dp(old_conn_state->best_encoder), false);
>   }
>   
> +static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
> +	struct intel_panel *panel = &connector->panel;
> +	u32 max_backlight = 0;
> +	int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
> +	u8 pn, pn_min, pn_max;
> +
> +	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, &pn)) {
> +		pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
> +		max_backlight = (1 << pn) - 1;
> +	}
> +
> +	/* Find desired value of (F x P)
> +	 * Note that, if F x P is out of supported range, the maximum value or
> +	 * minimum value will applied automatically. So no need to check that.
> +	 */
> +	freq = dev_priv->vbt.backlight.pwm_freq_hz;
> +	DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq);
> +	if (!freq) {
> +		DRM_DEBUG_KMS("Use panel default backlight frequency\n");
> +		return max_backlight;
> +	}
> +
> +	fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
> +
> +	/* Use highest possible value of Pn for more granularity of brightness
> +	 * adjustment while satifying the conditions below.
> +	 * - Pn is in the range of Pn_min and Pn_max
> +	 * - F is in the range of 1 and 255
> +	 * - FxP is within 25% of desired value.
> +	 *   Note: 25% is arbitrary value and may need some tweak.
> +	 */
> +	if (drm_dp_dpcd_readb(&intel_dp->aux,
> +			      DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
> +		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n");
> +		return max_backlight;
> +	}
> +	if (drm_dp_dpcd_readb(&intel_dp->aux,
> +			      DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
> +		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n");
> +		return max_backlight;
> +	}
> +	pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
> +	pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
> +
> +	fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
> +	fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
> +	if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
> +		DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n");
> +		return max_backlight;
> +	}
> +
> +	for (pn = pn_max; pn >= pn_min; pn--) {
> +		f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
> +		fxp_actual = f << pn;
> +		if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
> +			break;
> +	}
> +
> +	DRM_DEBUG_KMS("Using eDP pwmgen bit count of %d\n", pn);
> +	if (drm_dp_dpcd_writeb(&intel_dp->aux,
> +			       DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
> +		DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
> +		return max_backlight;
> +	}
> +	panel->backlight.pwmgen_bit_count = pn;
> +
> +	max_backlight = (1 << pn) - 1;
> +
> +	return max_backlight;
> +}
> +
>   static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
>   					enum pipe pipe)
>   {
> -	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
>   	struct intel_panel *panel = &connector->panel;
>   
> -	if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
> -		panel->backlight.max = 0xFFFF;
> -	else
> -		panel->backlight.max = 0xFF;
> +	panel->backlight.max = intel_dp_aux_calc_max_backlight(connector);
> +	if (!panel->backlight.max)
> +		return -ENODEV;
>   
>   	panel->backlight.min = 0;
>   	panel->backlight.level = intel_dp_aux_get_backlight(connector);
> -
>   	panel->backlight.enabled = panel->backlight.level != 0;
>   
>   	return 0;
> 
>  From patchwork Tue Dec  3 22:42:35 2019
> Content-Type: text/plain; charset="utf-8"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Subject: [v2] drm/i915: Assume 100% brightness when not in DPCD control mode
> From: Lyude Paul <lyude at redhat.com>
> X-Patchwork-Id: 343592
> Message-Id: <20191203224236.230930-1-lyude at redhat.com>
> To: intel-gfx at lists.freedesktop.org
> Cc: David Airlie <airlied at linux.ie>, linux-kernel at vger.kernel.org,
>   dri-devel at lists.freedesktop.org
> Date: Tue,  3 Dec 2019 17:42:35 -0500
> 
> Currently we always determine the initial panel brightness level by
> simply reading the value from DP_EDP_BACKLIGHT_BRIGHTNESS_MSB/LSB. This
> seems wrong though, because if the panel is not currently in DPCD
> control mode there's not really any reason why there would be any
> brightness value programmed in the first place.
> 
> This appears to be the case on the Lenovo ThinkPad X1 Extreme 2nd
> Generation, where the default value in these registers is always 0 on
> boot despite the fact the panel runs at max brightness by default.
> Getting the initial brightness value correct here is important as well,
> since the panel on this laptop doesn't behave well if it's ever put into
> DPCD control mode while the brightness level is programmed to 0.
> 
> So, let's fix this by checking what the current backlight control mode
> is before reading the brightness level. If it's in DPCD control mode, we
> return the programmed brightness level. Otherwise we assume 100%
> brightness and return the highest possible brightness level. This also
> prevents us from accidentally programming a brightness level of 0.
> 
> This is one of the many fixes that gets backlight controls working on
> the ThinkPad X1 Extreme 2nd Generation with optional 4K AMOLED screen.
> 
> Changes since v1:
> * s/DP_EDP_DISPLAY_CONTROL_REGISTER/DP_EDP_BACKLIGHT_MODE_SET_REGISTER/
>    - Jani
> 
> Signed-off-by: Lyude Paul <lyude at redhat.com>
> ---
>   .../drm/i915/display/intel_dp_aux_backlight.c   | 17 +++++++++++++++++
>   1 file changed, 17 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> index fad470553cf9..4d467e7d29eb 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> @@ -59,8 +59,25 @@ static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
>   {
>   	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
>   	u8 read_val[2] = { 0x0 };
> +	u8 mode_reg;
>   	u16 level = 0;
>   
> +	if (drm_dp_dpcd_readb(&intel_dp->aux,
> +			      DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
> +			      &mode_reg) != 1) {
> +		DRM_DEBUG_KMS("Failed to read the DPCD register 0x%x\n",
> +			      DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
> +		return 0;
> +	}
> +
> +	/*
> +	 * If we're not in DPCD control mode yet, the programmed brightness
> +	 * value is meaningless and we should assume max brightness
> +	 */
> +	if ((mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) !=
> +	    DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD)
> +		return connector->panel.backlight.max;
> +
>   	if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
>   			     &read_val, sizeof(read_val)) < 0) {
>   		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
> 
>  From patchwork Fri Nov 22 23:16:01 2019
> Content-Type: text/plain; charset="utf-8"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Subject: [3/5] drm/i915: Fix DPCD register order in intel_dp_aux_enable_backlight()
> From: Lyude Paul <lyude at redhat.com>
> X-Patchwork-Id: 342164
> Message-Id: <20191122231616.2574-4-lyude at redhat.com>
> To: intel-gfx at lists.freedesktop.org
> Cc: David Airlie <airlied at linux.ie>, linux-kernel at vger.kernel.org,
>   dri-devel at lists.freedesktop.org
> Date: Fri, 22 Nov 2019 18:16:01 -0500
> 
> For eDP panels, it appears it's expected that so long as the panel is in
> DPCD control mode that the brightness value is never set to 0. Instead,
> if the desired effect is to set the panel's backlight to 0 we're
> expected to simply turn off the backlight through the
> DP_EDP_DISPLAY_CONTROL_REGISTER.
> 
> We already do the latter correctly in intel_dp_aux_disable_backlight().
> But, we make the mistake of writing the DPCD registers in the wrong
> order when enabling the backlight in intel_dp_aux_enable_backlight()
> since we currently enable the backlight through
> DP_EDP_DISPLAY_CONTROL_REGISTER before writing the brightness level. On
> the X1 Extreme 2nd Generation, this appears to have the potential of
> confusing the panel in such a way that further attempts to set the
> brightness don't actually change the backlight as expected and leave it
> off. Presumably, this happens because the incorrect register writing
> order briefly leaves the panel with DPCD mode enabled and a 0 brightness
> level set.
> 
> So, reverse the order we write the DPCD registers when enabling the
> panel backlight so that we write the brightness value first, and enable
> the backlight second. This fix appears to be the final bit needed to get
> the backlight on the ThinkPad X1 Extreme 2nd Generation's AMOLED screen
> working.
> 
> Signed-off-by: Lyude Paul <lyude at redhat.com>
> Reviewed-by: Jani Nikula <jani.nikula at intel.com>
> ---
>   drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> index 0bf8772bc7bb..87b59db9ffe3 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> @@ -205,8 +205,9 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
>   		}
>   	}
>   
> +	intel_dp_aux_set_backlight(conn_state,
> +				   connector->panel.backlight.level);
>   	set_aux_backlight_enable(intel_dp, true);
> -	intel_dp_aux_set_backlight(conn_state, connector->panel.backlight.level);
>   }
>   
>   static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old_conn_state)
> 
>  From patchwork Fri Nov 22 23:16:02 2019
> Content-Type: text/plain; charset="utf-8"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Subject: [4/5] drm/i915: Auto detect DPCD backlight support by default
> From: Lyude Paul <lyude at redhat.com>
> X-Patchwork-Id: 342165
> Message-Id: <20191122231616.2574-5-lyude at redhat.com>
> To: intel-gfx at lists.freedesktop.org
> Cc: David Airlie <airlied at linux.ie>, linux-kernel at vger.kernel.org,
>   dri-devel at lists.freedesktop.org
> Date: Fri, 22 Nov 2019 18:16:02 -0500
> 
> Turns out we actually already have some companies, such as Lenovo,
> shipping machines with AMOLED screens that don't allow controlling the
> backlight through the usual PWM interface and only allow controlling it
> through the standard EDP DPCD interface. One example of one of these
> laptops is the X1 Extreme 2nd Generation.
> 
> Since we've got systems that need this turned on by default now to have
> backlight controls working out of the box, let's start auto-detecting it
> for systems by default based on what the VBT tells us. We do this by
> changing the default value for the enable_dpcd_backlight module param
> from 0 to -1.
> 
> Signed-off-by: Lyude Paul <lyude at redhat.com>
> Reviewed-by: Jani Nikula <jani.nikula at intel.com>
> ---
>   drivers/gpu/drm/i915/i915_params.c | 2 +-
>   drivers/gpu/drm/i915/i915_params.h | 2 +-
>   2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index 1dd1f3652795..31eed60c167e 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -172,7 +172,7 @@ i915_param_named_unsafe(inject_probe_failure, uint, 0400,
>   
>   i915_param_named(enable_dpcd_backlight, int, 0600,
>   	"Enable support for DPCD backlight control"
> -	"(-1=use per-VBT LFP backlight type setting, 0=disabled [default], 1=enabled)");
> +	"(-1=use per-VBT LFP backlight type setting [default], 0=disabled, 1=enabled)");
>   
>   #if IS_ENABLED(CONFIG_DRM_I915_GVT)
>   i915_param_named(enable_gvt, bool, 0400,
> diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
> index 31b88f297fbc..a79d0867f77a 100644
> --- a/drivers/gpu/drm/i915/i915_params.h
> +++ b/drivers/gpu/drm/i915/i915_params.h
> @@ -64,7 +64,7 @@ struct drm_printer;
>   	param(int, reset, 3) \
>   	param(unsigned int, inject_probe_failure, 0) \
>   	param(int, fastboot, -1) \
> -	param(int, enable_dpcd_backlight, 0) \
> +	param(int, enable_dpcd_backlight, -1) \
>   	param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE) \
>   	param(unsigned long, fake_lmem_start, 0) \
>   	/* leave bools at the end to not create holes */ \
> 
>  From patchwork Fri Nov 22 23:16:03 2019
> Content-Type: text/plain; charset="utf-8"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Subject: [5/5] drm/i915: Force DPCD backlight mode on X1 Extreme 2nd Gen 4K AMOLED panel
> From: Lyude Paul <lyude at redhat.com>
> X-Patchwork-Id: 342166
> Message-Id: <20191122231616.2574-6-lyude at redhat.com>
> To: intel-gfx at lists.freedesktop.org
> Cc: David Airlie <airlied at linux.ie>, dri-devel at lists.freedesktop.org,
>   linux-kernel at vger.kernel.org, Maxime Ripard <mripard at kernel.org>
> Date: Fri, 22 Nov 2019 18:16:03 -0500
> 
> Annoyingly, the VBT on the ThinkPad X1 Extreme 2nd Gen indicates that
> the system uses plain PWM based backlight controls, when in reality the
> only backlight controls that work are the standard VESA eDP DPCD
> backlight controls.
> 
> Honestly, this makes me wonder how many other systems have these issues
> or lie about this in their VBT. Not sure we have any good way of finding
> out until panels like this become more common place in the laptop
> market. For now, just add a DRM DP quirk to indicate that this panel is
> telling the truth and is being a good LCD.
> 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376
> Signed-off-by: Lyude Paul <lyude at redhat.com>
> Acked-by: Jani Nikula <jani.nikula at intel.com>
> ---
>   drivers/gpu/drm/drm_dp_helper.c                       |  4 ++++
>   drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 10 ++++++++--
>   include/drm/drm_dp_helper.h                           |  8 ++++++++
>   3 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index 2c7870aef469..ec7061e3a99b 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -1155,6 +1155,10 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
>   	{ OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) },
>   	/* CH7511 seems to leave SINK_COUNT zeroed */
>   	{ OUI(0x00, 0x00, 0x00), DEVICE_ID('C', 'H', '7', '5', '1', '1'), false, BIT(DP_DPCD_QUIRK_NO_SINK_COUNT) },
> +	/* Optional 4K AMOLED panel in the ThinkPad X1 Extreme 2nd Generation
> +	 * only supports DPCD backlight controls, despite advertising otherwise
> +	 */
> +	{ OUI(0xba, 0x41, 0x59), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_FORCE_DPCD_BACKLIGHT) },
>   };
>   
>   #undef OUI
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> index 87b59db9ffe3..3d61260b08ad 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> @@ -325,11 +325,17 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector)
>   int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
>   {
>   	struct intel_panel *panel = &intel_connector->panel;
> -	struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
> +	struct intel_dp *intel_dp =
> +		enc_to_intel_dp(&intel_connector->encoder->base);
> +	struct drm_i915_private *dev_priv =
> +		to_i915(intel_connector->base.dev);
>   
>   	if (i915_modparams.enable_dpcd_backlight == 0 ||
>   	    (i915_modparams.enable_dpcd_backlight == -1 &&
> -	    dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
> +	     dev_priv->vbt.backlight.type !=
> +		     INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE &&
> +	     !drm_dp_has_quirk(&intel_dp->desc,
> +			       DP_DPCD_QUIRK_FORCE_DPCD_BACKLIGHT)))
>   		return -ENODEV;
>   
>   	if (!intel_dp_aux_display_control_capable(intel_connector))
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 51ecb5112ef8..a444209cd54b 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1520,6 +1520,14 @@ enum drm_dp_quirk {
>   	 * The driver should ignore SINK_COUNT during detection.
>   	 */
>   	DP_DPCD_QUIRK_NO_SINK_COUNT,
> +	/**
> +	 * @DP_DPCD_QUIRK_FORCE_DPCD_BACKLIGHT:
> +	 *
> +	 * The device is telling the truth when it says that it uses DPCD
> +	 * backlight controls, even if the system's firmware disagrees.
> +	 * The driver should honor the DPCD backlight capabilities advertised.
> +	 */
> +	DP_DPCD_QUIRK_FORCE_DPCD_BACKLIGHT,
>   };
>   
>   /**
> 
Tested-by:Perry Yuan <pyuan at redhat.com>



More information about the dri-devel mailing list