Jeremy Cline c74a033
From 0fdb20f83f9962a3501e9cbdbfcc37ed5e721ab8 Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:31 -0400
Jeremy Cline c74a033
Subject: [PATCH 1/7] drm/i915: Fix eDP DPCD aux max backlight calculations
Jeremy Cline c74a033
Jeremy Cline c74a033
Max backlight value for the panel was being calculated using byte
Jeremy Cline c74a033
count i.e. 0xffff if 2 bytes are supported for backlight brightness
Jeremy Cline c74a033
and 0xff if 1 byte is supported. However, EDP_PWMGEN_BIT_COUNT
Jeremy Cline c74a033
determines the number of active control bits used for the brightness
Jeremy Cline c74a033
setting. Thus, even if the panel uses 2 byte setting, it might not use
Jeremy Cline c74a033
all the control bits. Thus, max backlight should be set based on the
Jeremy Cline c74a033
value of EDP_PWMGEN_BIT_COUNT instead of assuming 65535 or 255.
Jeremy Cline c74a033
Jeremy Cline c74a033
Additionally, EDP_PWMGEN_BIT_COUNT was being updated based on the VBT
Jeremy Cline c74a033
frequency which results in a different max backlight value. Thus,
Jeremy Cline c74a033
setting of EDP_PWMGEN_BIT_COUNT is moved to setup phase instead of
Jeremy Cline c74a033
enable so that max backlight can be calculated correctly. Only the
Jeremy Cline c74a033
frequency divider is set during the enable phase using the value of
Jeremy Cline c74a033
EDP_PWMGEN_BIT_COUNT.
Jeremy Cline c74a033
Jeremy Cline c74a033
This is based off the original patch series from Furquan Shaikh
Jeremy Cline c74a033
<furquan@google.com>:
Jeremy Cline c74a033
Jeremy Cline c74a033
https://patchwork.freedesktop.org/patch/317255/?series=62326&rev=3
Jeremy Cline c74a033
Jeremy Cline c74a033
Changes since original patch:
Jeremy Cline c74a033
* Remove unused intel_dp variable in intel_dp_aux_setup_backlight()
Jeremy Cline c74a033
* Fix checkpatch issues
Jeremy Cline c74a033
* Make sure that we rewrite the pwmgen bit count whenever we bring the
Jeremy Cline c74a033
  panel out of D3 mode
Jeremy Cline c74a033
Jeremy Cline c74a033
v2 by Jani:
Jeremy Cline c74a033
* rebase
Jeremy Cline c74a033
* fix readb return value check
Jeremy Cline c74a033
Jeremy Cline c74a033
Cc: Furquan Shaikh <furquan@google.com>
Jeremy Cline c74a033
Tested-by: AceLan Kao <acelan.kao@canonical.com>
Jeremy Cline c74a033
Tested-by: Perry Yuan <pyuan@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
Link: https://patchwork.freedesktop.org/patch/msgid/20200116211623.53799-2-lyude@redhat.com
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 .../drm/i915/display/intel_display_types.h    |   3 +
Jeremy Cline c74a033
 .../drm/i915/display/intel_dp_aux_backlight.c | 139 ++++++++++++------
Jeremy Cline c74a033
 2 files changed, 95 insertions(+), 47 deletions(-)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
Jeremy Cline c74a033
index 888ea8a170d1..778bd30743e5 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
Jeremy Cline c74a033
@@ -214,6 +214,9 @@ struct intel_panel {
Jeremy Cline c74a033
 		u8 controller;		/* bxt+ only */
Jeremy Cline c74a033
 		struct pwm_device *pwm;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
+		/* DPCD backlight */
Jeremy Cline c74a033
+		u8 pwmgen_bit_count;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 		struct backlight_device *device;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 		/* Connector and platform specific backlight functions */
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
index 7c653f8c307f..345eed641455 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
@@ -111,61 +111,28 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector)
Jeremy Cline c74a033
 {
Jeremy Cline c74a033
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
Jeremy Cline c74a033
 	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
Jeremy Cline c74a033
-	int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
Jeremy Cline c74a033
-	u8 pn, pn_min, pn_max;
Jeremy Cline c74a033
+	const u8 pn = connector->panel.backlight.pwmgen_bit_count;
Jeremy Cline c74a033
+	int freq, fxp, f, fxp_actual, fxp_min, fxp_max;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	/* Find desired value of (F x P)
Jeremy Cline c74a033
-	 * Note that, if F x P is out of supported range, the maximum value or
Jeremy Cline c74a033
-	 * minimum value will applied automatically. So no need to check that.
Jeremy Cline c74a033
-	 */
Jeremy Cline c74a033
 	freq = dev_priv->vbt.backlight.pwm_freq_hz;
Jeremy Cline c74a033
-	DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq);
Jeremy Cline c74a033
 	if (!freq) {
Jeremy Cline c74a033
 		DRM_DEBUG_KMS("Use panel default backlight frequency\n");
Jeremy Cline c74a033
 		return false;
Jeremy Cline c74a033
 	}
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
Jeremy Cline c74a033
+	f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
Jeremy Cline c74a033
+	fxp_actual = f << pn;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	/* Use highest possible value of Pn for more granularity of brightness
Jeremy Cline c74a033
-	 * adjustment while satifying the conditions below.
Jeremy Cline c74a033
-	 * - Pn is in the range of Pn_min and Pn_max
Jeremy Cline c74a033
-	 * - F is in the range of 1 and 255
Jeremy Cline c74a033
-	 * - FxP is within 25% of desired value.
Jeremy Cline c74a033
-	 *   Note: 25% is arbitrary value and may need some tweak.
Jeremy Cline c74a033
-	 */
Jeremy Cline c74a033
-	if (drm_dp_dpcd_readb(&intel_dp->aux,
Jeremy Cline c74a033
-			       DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
Jeremy Cline c74a033
-		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n");
Jeremy Cline c74a033
-		return false;
Jeremy Cline c74a033
-	}
Jeremy Cline c74a033
-	if (drm_dp_dpcd_readb(&intel_dp->aux,
Jeremy Cline c74a033
-			       DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
Jeremy Cline c74a033
-		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n");
Jeremy Cline c74a033
-		return false;
Jeremy Cline c74a033
-	}
Jeremy Cline c74a033
-	pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
Jeremy Cline c74a033
-	pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
Jeremy Cline c74a033
-
Jeremy Cline c74a033
+	/* Ensure frequency is within 25% of desired value */
Jeremy Cline c74a033
 	fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
Jeremy Cline c74a033
 	fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
Jeremy Cline c74a033
-	if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
Jeremy Cline c74a033
-		DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n");
Jeremy Cline c74a033
-		return false;
Jeremy Cline c74a033
-	}
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	for (pn = pn_max; pn >= pn_min; pn--) {
Jeremy Cline c74a033
-		f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
Jeremy Cline c74a033
-		fxp_actual = f << pn;
Jeremy Cline c74a033
-		if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
Jeremy Cline c74a033
-			break;
Jeremy Cline c74a033
-	}
Jeremy Cline c74a033
-
Jeremy Cline c74a033
-	if (drm_dp_dpcd_writeb(&intel_dp->aux,
Jeremy Cline c74a033
-			       DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
Jeremy Cline c74a033
-		DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
Jeremy Cline c74a033
+	if (fxp_min > fxp_actual || fxp_actual > fxp_max) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("Actual frequency out of range\n");
Jeremy Cline c74a033
 		return false;
Jeremy Cline c74a033
 	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 	if (drm_dp_dpcd_writeb(&intel_dp->aux,
Jeremy Cline c74a033
 			       DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) {
Jeremy Cline c74a033
 		DRM_DEBUG_KMS("Failed to write aux backlight freq\n");
Jeremy Cline c74a033
@@ -179,6 +146,7 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
Jeremy Cline c74a033
 {
Jeremy Cline c74a033
 	struct intel_connector *connector = to_intel_connector(conn_state->connector);
Jeremy Cline c74a033
 	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
Jeremy Cline c74a033
+	struct intel_panel *panel = &connector->panel;
Jeremy Cline c74a033
 	u8 dpcd_buf, new_dpcd_buf, edp_backlight_mode;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	if (drm_dp_dpcd_readb(&intel_dp->aux,
Jeremy Cline c74a033
@@ -197,6 +165,12 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
Jeremy Cline c74a033
 	case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT:
Jeremy Cline c74a033
 		new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
Jeremy Cline c74a033
 		new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+		if (drm_dp_dpcd_writeb(&intel_dp->aux,
Jeremy Cline c74a033
+				       DP_EDP_PWMGEN_BIT_COUNT,
Jeremy Cline c74a033
+				       panel->backlight.pwmgen_bit_count) < 0)
Jeremy Cline c74a033
+			DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 		break;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	/* Do nothing when it is already DPCD mode */
Jeremy Cline c74a033
@@ -226,20 +200,91 @@ static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old
Jeremy Cline c74a033
 				 false);
Jeremy Cline c74a033
 }
Jeremy Cline c74a033
 
Jeremy Cline c74a033
+static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector)
Jeremy Cline c74a033
+{
Jeremy Cline c74a033
+	struct drm_i915_private *i915 = to_i915(connector->base.dev);
Jeremy Cline c74a033
+	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
Jeremy Cline c74a033
+	struct intel_panel *panel = &connector->panel;
Jeremy Cline c74a033
+	u32 max_backlight = 0;
Jeremy Cline c74a033
+	int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
Jeremy Cline c74a033
+	u8 pn, pn_min, pn_max;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, &pn) == 1) {
Jeremy Cline c74a033
+		pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
Jeremy Cline c74a033
+		max_backlight = (1 << pn) - 1;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	/* Find desired value of (F x P)
Jeremy Cline c74a033
+	 * Note that, if F x P is out of supported range, the maximum value or
Jeremy Cline c74a033
+	 * minimum value will applied automatically. So no need to check that.
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	freq = i915->vbt.backlight.pwm_freq_hz;
Jeremy Cline c74a033
+	DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq);
Jeremy Cline c74a033
+	if (!freq) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("Use panel default backlight frequency\n");
Jeremy Cline c74a033
+		return max_backlight;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	/* Use highest possible value of Pn for more granularity of brightness
Jeremy Cline c74a033
+	 * adjustment while satifying the conditions below.
Jeremy Cline c74a033
+	 * - Pn is in the range of Pn_min and Pn_max
Jeremy Cline c74a033
+	 * - F is in the range of 1 and 255
Jeremy Cline c74a033
+	 * - FxP is within 25% of desired value.
Jeremy Cline c74a033
+	 *   Note: 25% is arbitrary value and may need some tweak.
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	if (drm_dp_dpcd_readb(&intel_dp->aux,
Jeremy Cline c74a033
+			      DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n");
Jeremy Cline c74a033
+		return max_backlight;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+	if (drm_dp_dpcd_readb(&intel_dp->aux,
Jeremy Cline c74a033
+			      DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n");
Jeremy Cline c74a033
+		return max_backlight;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+	pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
Jeremy Cline c74a033
+	pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
Jeremy Cline c74a033
+	fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
Jeremy Cline c74a033
+	if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n");
Jeremy Cline c74a033
+		return max_backlight;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	for (pn = pn_max; pn >= pn_min; pn--) {
Jeremy Cline c74a033
+		f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
Jeremy Cline c74a033
+		fxp_actual = f << pn;
Jeremy Cline c74a033
+		if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
Jeremy Cline c74a033
+			break;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	DRM_DEBUG_KMS("Using eDP pwmgen bit count of %d\n", pn);
Jeremy Cline c74a033
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
Jeremy Cline c74a033
+			       DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
Jeremy Cline c74a033
+		return max_backlight;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+	panel->backlight.pwmgen_bit_count = pn;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	max_backlight = (1 << pn) - 1;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	return max_backlight;
Jeremy Cline c74a033
+}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
Jeremy Cline c74a033
 					enum pipe pipe)
Jeremy Cline c74a033
 {
Jeremy Cline c74a033
-	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
Jeremy Cline c74a033
 	struct intel_panel *panel = &connector->panel;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
Jeremy Cline c74a033
-		panel->backlight.max = 0xFFFF;
Jeremy Cline c74a033
-	else
Jeremy Cline c74a033
-		panel->backlight.max = 0xFF;
Jeremy Cline c74a033
+	panel->backlight.max = intel_dp_aux_calc_max_backlight(connector);
Jeremy Cline c74a033
+	if (!panel->backlight.max)
Jeremy Cline c74a033
+		return -ENODEV;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	panel->backlight.min = 0;
Jeremy Cline c74a033
 	panel->backlight.level = intel_dp_aux_get_backlight(connector);
Jeremy Cline c74a033
-
Jeremy Cline c74a033
 	panel->backlight.enabled = panel->backlight.level != 0;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	return 0;
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033
Jeremy Cline c74a033
From 7dbe3f659d364de34b210baf0598913dc8c3cabd Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:32 -0400
Jeremy Cline c74a033
Subject: [PATCH 2/7] drm/i915: Assume 100% brightness when not in DPCD control
Jeremy Cline c74a033
 mode
Jeremy Cline c74a033
Jeremy Cline c74a033
Currently we always determine the initial panel brightness level by
Jeremy Cline c74a033
simply reading the value from DP_EDP_BACKLIGHT_BRIGHTNESS_MSB/LSB. This
Jeremy Cline c74a033
seems wrong though, because if the panel is not currently in DPCD
Jeremy Cline c74a033
control mode there's not really any reason why there would be any
Jeremy Cline c74a033
brightness value programmed in the first place.
Jeremy Cline c74a033
Jeremy Cline c74a033
This appears to be the case on the Lenovo ThinkPad X1 Extreme 2nd
Jeremy Cline c74a033
Generation, where the default value in these registers is always 0 on
Jeremy Cline c74a033
boot despite the fact the panel runs at max brightness by default.
Jeremy Cline c74a033
Getting the initial brightness value correct here is important as well,
Jeremy Cline c74a033
since the panel on this laptop doesn't behave well if it's ever put into
Jeremy Cline c74a033
DPCD control mode while the brightness level is programmed to 0.
Jeremy Cline c74a033
Jeremy Cline c74a033
So, let's fix this by checking what the current backlight control mode
Jeremy Cline c74a033
is before reading the brightness level. If it's in DPCD control mode, we
Jeremy Cline c74a033
return the programmed brightness level. Otherwise we assume 100%
Jeremy Cline c74a033
brightness and return the highest possible brightness level. This also
Jeremy Cline c74a033
prevents us from accidentally programming a brightness level of 0.
Jeremy Cline c74a033
Jeremy Cline c74a033
This is one of the many fixes that gets backlight controls working on
Jeremy Cline c74a033
the ThinkPad X1 Extreme 2nd Generation with optional 4K AMOLED screen.
Jeremy Cline c74a033
Jeremy Cline c74a033
Changes since v1:
Jeremy Cline c74a033
* s/DP_EDP_DISPLAY_CONTROL_REGISTER/DP_EDP_BACKLIGHT_MODE_SET_REGISTER/
Jeremy Cline c74a033
  - Jani
Jeremy Cline c74a033
Jeremy Cline c74a033
Tested-by: AceLan Kao <acelan.kao@canonical.com>
Jeremy Cline c74a033
Tested-by: Perry Yuan <pyuan@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
Link: https://patchwork.freedesktop.org/patch/msgid/20200116211623.53799-3-lyude@redhat.com
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 .../drm/i915/display/intel_dp_aux_backlight.c   | 17 +++++++++++++++++
Jeremy Cline c74a033
 1 file changed, 17 insertions(+)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
index 345eed641455..5d4db5f8a165 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
@@ -59,8 +59,25 @@ static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
Jeremy Cline c74a033
 {
Jeremy Cline c74a033
 	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
Jeremy Cline c74a033
 	u8 read_val[2] = { 0x0 };
Jeremy Cline c74a033
+	u8 mode_reg;
Jeremy Cline c74a033
 	u16 level = 0;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
+	if (drm_dp_dpcd_readb(&intel_dp->aux,
Jeremy Cline c74a033
+			      DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
Jeremy Cline c74a033
+			      &mode_reg) != 1) {
Jeremy Cline c74a033
+		DRM_DEBUG_KMS("Failed to read the DPCD register 0x%x\n",
Jeremy Cline c74a033
+			      DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
Jeremy Cline c74a033
+		return 0;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	/*
Jeremy Cline c74a033
+	 * If we're not in DPCD control mode yet, the programmed brightness
Jeremy Cline c74a033
+	 * value is meaningless and we should assume max brightness
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	if ((mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) !=
Jeremy Cline c74a033
+	    DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD)
Jeremy Cline c74a033
+		return connector->panel.backlight.max;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
Jeremy Cline c74a033
 			     &read_val, sizeof(read_val)) < 0) {
Jeremy Cline c74a033
 		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033
Jeremy Cline c74a033
From b2a29a70e386c2fbd92e1b7980091e7980495211 Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:33 -0400
Jeremy Cline c74a033
Subject: [PATCH 3/7] drm/i915: Fix DPCD register order in
Jeremy Cline c74a033
 intel_dp_aux_enable_backlight()
Jeremy Cline c74a033
Jeremy Cline c74a033
For eDP panels, it appears it's expected that so long as the panel is in
Jeremy Cline c74a033
DPCD control mode that the brightness value is never set to 0. Instead,
Jeremy Cline c74a033
if the desired effect is to set the panel's backlight to 0 we're
Jeremy Cline c74a033
expected to simply turn off the backlight through the
Jeremy Cline c74a033
DP_EDP_DISPLAY_CONTROL_REGISTER.
Jeremy Cline c74a033
Jeremy Cline c74a033
We already do the latter correctly in intel_dp_aux_disable_backlight().
Jeremy Cline c74a033
But, we make the mistake of writing the DPCD registers in the wrong
Jeremy Cline c74a033
order when enabling the backlight in intel_dp_aux_enable_backlight()
Jeremy Cline c74a033
since we currently enable the backlight through
Jeremy Cline c74a033
DP_EDP_DISPLAY_CONTROL_REGISTER before writing the brightness level. On
Jeremy Cline c74a033
the X1 Extreme 2nd Generation, this appears to have the potential of
Jeremy Cline c74a033
confusing the panel in such a way that further attempts to set the
Jeremy Cline c74a033
brightness don't actually change the backlight as expected and leave it
Jeremy Cline c74a033
off. Presumably, this happens because the incorrect register writing
Jeremy Cline c74a033
order briefly leaves the panel with DPCD mode enabled and a 0 brightness
Jeremy Cline c74a033
level set.
Jeremy Cline c74a033
Jeremy Cline c74a033
So, reverse the order we write the DPCD registers when enabling the
Jeremy Cline c74a033
panel backlight so that we write the brightness value first, and enable
Jeremy Cline c74a033
the backlight second. This fix appears to be the final bit needed to get
Jeremy Cline c74a033
the backlight on the ThinkPad X1 Extreme 2nd Generation's AMOLED screen
Jeremy Cline c74a033
working.
Jeremy Cline c74a033
Jeremy Cline c74a033
Tested-by: AceLan Kao <acelan.kao@canonical.com>
Jeremy Cline c74a033
Tested-by: Perry Yuan <pyuan@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
Link: https://patchwork.freedesktop.org/patch/msgid/20200116211623.53799-4-lyude@redhat.com
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 3 ++-
Jeremy Cline c74a033
 1 file changed, 2 insertions(+), 1 deletion(-)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
index 5d4db5f8a165..77a759361c5c 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
@@ -207,8 +207,9 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
Jeremy Cline c74a033
 		}
Jeremy Cline c74a033
 	}
Jeremy Cline c74a033
 
Jeremy Cline c74a033
+	intel_dp_aux_set_backlight(conn_state,
Jeremy Cline c74a033
+				   connector->panel.backlight.level);
Jeremy Cline c74a033
 	set_aux_backlight_enable(intel_dp, true);
Jeremy Cline c74a033
-	intel_dp_aux_set_backlight(conn_state, connector->panel.backlight.level);
Jeremy Cline c74a033
 }
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old_conn_state)
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033
Jeremy Cline c74a033
From 8b2e6f450c1f8d34632d4789369030008e874a75 Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:34 -0400
Jeremy Cline c74a033
Subject: [PATCH 4/7] drm/i915: Auto detect DPCD backlight support by default
Jeremy Cline c74a033
Jeremy Cline c74a033
Turns out we actually already have some companies, such as Lenovo,
Jeremy Cline c74a033
shipping machines with AMOLED screens that don't allow controlling the
Jeremy Cline c74a033
backlight through the usual PWM interface and only allow controlling it
Jeremy Cline c74a033
through the standard EDP DPCD interface. One example of one of these
Jeremy Cline c74a033
laptops is the X1 Extreme 2nd Generation.
Jeremy Cline c74a033
Jeremy Cline c74a033
Since we've got systems that need this turned on by default now to have
Jeremy Cline c74a033
backlight controls working out of the box, let's start auto-detecting it
Jeremy Cline c74a033
for systems by default based on what the VBT tells us. We do this by
Jeremy Cline c74a033
changing the default value for the enable_dpcd_backlight module param
Jeremy Cline c74a033
from 0 to -1.
Jeremy Cline c74a033
Jeremy Cline c74a033
Tested-by: AceLan Kao <acelan.kao@canonical.com>
Jeremy Cline c74a033
Tested-by: Perry Yuan <pyuan@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
Link: https://patchwork.freedesktop.org/patch/msgid/20200116211623.53799-6-lyude@redhat.com
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 drivers/gpu/drm/i915/i915_params.c | 2 +-
Jeremy Cline c74a033
 drivers/gpu/drm/i915/i915_params.h | 2 +-
Jeremy Cline c74a033
 2 files changed, 2 insertions(+), 2 deletions(-)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
Jeremy Cline c74a033
index 1dd1f3652795..31eed60c167e 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/i915_params.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/i915_params.c
Jeremy Cline c74a033
@@ -172,7 +172,7 @@ i915_param_named_unsafe(inject_probe_failure, uint, 0400,
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 i915_param_named(enable_dpcd_backlight, int, 0600,
Jeremy Cline c74a033
 	"Enable support for DPCD backlight control"
Jeremy Cline c74a033
-	"(-1=use per-VBT LFP backlight type setting, 0=disabled [default], 1=enabled)");
Jeremy Cline c74a033
+	"(-1=use per-VBT LFP backlight type setting [default], 0=disabled, 1=enabled)");
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 #if IS_ENABLED(CONFIG_DRM_I915_GVT)
Jeremy Cline c74a033
 i915_param_named(enable_gvt, bool, 0400,
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
Jeremy Cline c74a033
index 31b88f297fbc..a79d0867f77a 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/i915_params.h
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/i915_params.h
Jeremy Cline c74a033
@@ -64,7 +64,7 @@ struct drm_printer;
Jeremy Cline c74a033
 	param(int, reset, 3) \
Jeremy Cline c74a033
 	param(unsigned int, inject_probe_failure, 0) \
Jeremy Cline c74a033
 	param(int, fastboot, -1) \
Jeremy Cline c74a033
-	param(int, enable_dpcd_backlight, 0) \
Jeremy Cline c74a033
+	param(int, enable_dpcd_backlight, -1) \
Jeremy Cline c74a033
 	param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE) \
Jeremy Cline c74a033
 	param(unsigned long, fake_lmem_start, 0) \
Jeremy Cline c74a033
 	/* leave bools at the end to not create holes */ \
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033
Jeremy Cline c74a033
From c10b0dfaac8385f9b712a552c9a5eed9976aacf2 Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:35 -0400
Jeremy Cline c74a033
Subject: [PATCH 5/7] drm/dp: Introduce EDID-based quirks
Jeremy Cline c74a033
Jeremy Cline c74a033
The whole point of using OUIs is so that we can recognize certain
Jeremy Cline c74a033
devices and potentially apply quirks for them. Normally this should work
Jeremy Cline c74a033
quite well, but there appears to be quite a number of laptop panels out
Jeremy Cline c74a033
there that will fill the OUI but not the device ID. As such, for devices
Jeremy Cline c74a033
like this I can't imagine it's a very good idea to try relying on OUIs
Jeremy Cline c74a033
for applying quirks. As well, some laptop vendors have confirmed to us
Jeremy Cline c74a033
that their panels have this exact issue.
Jeremy Cline c74a033
Jeremy Cline c74a033
So, let's introduce the ability to apply DP quirks based on EDID
Jeremy Cline c74a033
identification. We reuse the same quirk bits for OUI-based quirks, so
Jeremy Cline c74a033
that callers can simply check all possible quirks using
Jeremy Cline c74a033
drm_dp_has_quirk().
Jeremy Cline c74a033
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Reviewed-by: Adam Jackson <ajax@redhat.com>
Jeremy Cline c74a033
Cc: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 drivers/gpu/drm/drm_dp_helper.c               | 61 +++++++++++++++++++
Jeremy Cline c74a033
 drivers/gpu/drm/drm_dp_mst_topology.c         |  3 +-
Jeremy Cline c74a033
 .../drm/i915/display/intel_display_types.h    |  1 +
Jeremy Cline c74a033
 drivers/gpu/drm/i915/display/intel_dp.c       | 11 ++--
Jeremy Cline c74a033
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  2 +-
Jeremy Cline c74a033
 drivers/gpu/drm/i915/display/intel_psr.c      |  2 +-
Jeremy Cline c74a033
 include/drm/drm_dp_helper.h                   | 11 +++-
Jeremy Cline c74a033
 7 files changed, 81 insertions(+), 10 deletions(-)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
index a5364b5192b8..9b2ea2ae0204 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
@@ -1222,6 +1222,67 @@ drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch)
Jeremy Cline c74a033
 #undef DEVICE_ID_ANY
Jeremy Cline c74a033
 #undef DEVICE_ID
Jeremy Cline c74a033
 
Jeremy Cline c74a033
+struct edid_quirk {
Jeremy Cline c74a033
+	u8 mfg_id[2];
Jeremy Cline c74a033
+	u8 prod_id[2];
Jeremy Cline c74a033
+	u32 quirks;
Jeremy Cline c74a033
+};
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+#define MFG(first, second) { (first), (second) }
Jeremy Cline c74a033
+#define PROD_ID(first, second) { (first), (second) }
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+/*
Jeremy Cline c74a033
+ * Some devices have unreliable OUIDs where they don't set the device ID
Jeremy Cline c74a033
+ * correctly, and as a result we need to use the EDID for finding additional
Jeremy Cline c74a033
+ * DP quirks in such cases.
Jeremy Cline c74a033
+ */
Jeremy Cline c74a033
+static const struct edid_quirk edid_quirk_list[] = {
Jeremy Cline c74a033
+};
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+#undef MFG
Jeremy Cline c74a033
+#undef PROD_ID
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+/**
Jeremy Cline c74a033
+ * drm_dp_get_edid_quirks() - Check the EDID of a DP device to find additional
Jeremy Cline c74a033
+ * DP-specific quirks
Jeremy Cline c74a033
+ * @edid: The EDID to check
Jeremy Cline c74a033
+ *
Jeremy Cline c74a033
+ * While OUIDs are meant to be used to recognize a DisplayPort device, a lot
Jeremy Cline c74a033
+ * of manufacturers don't seem to like following standards and neglect to fill
Jeremy Cline c74a033
+ * the dev-ID in, making it impossible to only use OUIDs for determining
Jeremy Cline c74a033
+ * quirks in some cases. This function can be used to check the EDID and look
Jeremy Cline c74a033
+ * up any additional DP quirks. The bits returned by this function correspond
Jeremy Cline c74a033
+ * to the quirk bits in &drm_dp_quirk.
Jeremy Cline c74a033
+ *
Jeremy Cline c74a033
+ * Returns: a bitmask of quirks, if any. The driver can check this using
Jeremy Cline c74a033
+ * drm_dp_has_quirk().
Jeremy Cline c74a033
+ */
Jeremy Cline c74a033
+u32 drm_dp_get_edid_quirks(const struct edid *edid)
Jeremy Cline c74a033
+{
Jeremy Cline c74a033
+	const struct edid_quirk *quirk;
Jeremy Cline c74a033
+	u32 quirks = 0;
Jeremy Cline c74a033
+	int i;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	if (!edid)
Jeremy Cline c74a033
+		return 0;
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
Jeremy Cline c74a033
+		quirk = &edid_quirk_list[i];
Jeremy Cline c74a033
+		if (memcmp(quirk->mfg_id, edid->mfg_id,
Jeremy Cline c74a033
+			   sizeof(edid->mfg_id)) == 0 &&
Jeremy Cline c74a033
+		    memcmp(quirk->prod_id, edid->prod_code,
Jeremy Cline c74a033
+			   sizeof(edid->prod_code)) == 0)
Jeremy Cline c74a033
+			quirks |= quirk->quirks;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	DRM_DEBUG_KMS("DP sink: EDID mfg %*phD prod-ID %*phD quirks: 0x%04x\n",
Jeremy Cline c74a033
+		      (int)sizeof(edid->mfg_id), edid->mfg_id,
Jeremy Cline c74a033
+		      (int)sizeof(edid->prod_code), edid->prod_code, quirks);
Jeremy Cline c74a033
+
Jeremy Cline c74a033
+	return quirks;
Jeremy Cline c74a033
+}
Jeremy Cline c74a033
+EXPORT_SYMBOL(drm_dp_get_edid_quirks);
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 /**
Jeremy Cline c74a033
  * drm_dp_read_desc - read sink/branch descriptor from DPCD
Jeremy Cline c74a033
  * @aux: DisplayPort AUX channel
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
Jeremy Cline c74a033
index cce0b1bba591..685c35e67144 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
Jeremy Cline c74a033
@@ -5461,7 +5461,8 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port)
Jeremy Cline c74a033
 	if (drm_dp_read_desc(port->mgr->aux, &desc, true))
Jeremy Cline c74a033
 		return NULL;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	if (drm_dp_has_quirk(&desc, DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
Jeremy Cline c74a033
+	if (drm_dp_has_quirk(&desc, 0,
Jeremy Cline c74a033
+			     DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
Jeremy Cline c74a033
 	    port->mgr->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14 &&
Jeremy Cline c74a033
 	    port->parent == port->mgr->mst_primary) {
Jeremy Cline c74a033
 		u8 downstreamport;
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
Jeremy Cline c74a033
index 778bd30743e5..8e3c5569603b 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
Jeremy Cline c74a033
@@ -1253,6 +1253,7 @@ struct intel_dp {
Jeremy Cline c74a033
 	int max_link_rate;
Jeremy Cline c74a033
 	/* sink or branch descriptor */
Jeremy Cline c74a033
 	struct drm_dp_desc desc;
Jeremy Cline c74a033
+	u32 edid_quirks;
Jeremy Cline c74a033
 	struct drm_dp_aux aux;
Jeremy Cline c74a033
 	u32 aux_busy_last_status;
Jeremy Cline c74a033
 	u8 train_set[4];
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
Jeremy Cline c74a033
index c7424e2a04a3..e20b85ff937d 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_dp.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
Jeremy Cline c74a033
@@ -2373,7 +2373,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
Jeremy Cline c74a033
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
Jeremy Cline c74a033
 	struct intel_digital_connector_state *intel_conn_state =
Jeremy Cline c74a033
 		to_intel_digital_connector_state(conn_state);
Jeremy Cline c74a033
-	bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
Jeremy Cline c74a033
+	bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
Jeremy Cline c74a033
 					   DP_DPCD_QUIRK_CONSTANT_N);
Jeremy Cline c74a033
 	int ret = 0, output_bpp;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
@@ -4466,7 +4466,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
Jeremy Cline c74a033
 	 * it don't care about read it here and in intel_edp_init_dpcd().
Jeremy Cline c74a033
 	 */
Jeremy Cline c74a033
 	if (!intel_dp_is_edp(intel_dp) &&
Jeremy Cline c74a033
-	    !drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_SINK_COUNT)) {
Jeremy Cline c74a033
+	    !drm_dp_has_quirk(&intel_dp->desc, 0,
Jeremy Cline c74a033
+			      DP_DPCD_QUIRK_NO_SINK_COUNT)) {
Jeremy Cline c74a033
 		u8 count;
Jeremy Cline c74a033
 		ssize_t r;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
@@ -5631,6 +5632,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	intel_dp->has_audio = drm_detect_monitor_audio(edid);
Jeremy Cline c74a033
 	drm_dp_cec_set_edid(&intel_dp->aux, edid);
Jeremy Cline c74a033
+	intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
Jeremy Cline c74a033
 }
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 static void
Jeremy Cline c74a033
@@ -5643,6 +5645,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
Jeremy Cline c74a033
 	intel_connector->detect_edid = NULL;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	intel_dp->has_audio = false;
Jeremy Cline c74a033
+	intel_dp->edid_quirks = 0;
Jeremy Cline c74a033
 }
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 static int
Jeremy Cline c74a033
@@ -7356,8 +7359,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
Jeremy Cline c74a033
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
Jeremy Cline c74a033
 	if (edid) {
Jeremy Cline c74a033
 		if (drm_add_edid_modes(connector, edid)) {
Jeremy Cline c74a033
-			drm_connector_update_edid_property(connector,
Jeremy Cline c74a033
-								edid);
Jeremy Cline c74a033
+			drm_connector_update_edid_property(connector, edid);
Jeremy Cline c74a033
+			intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
Jeremy Cline c74a033
 		} else {
Jeremy Cline c74a033
 			kfree(edid);
Jeremy Cline c74a033
 			edid = ERR_PTR(-EINVAL);
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
Jeremy Cline c74a033
index cba68c5a80fa..4a1a2f868423 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
Jeremy Cline c74a033
@@ -50,7 +50,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
Jeremy Cline c74a033
 	const struct drm_display_mode *adjusted_mode =
Jeremy Cline c74a033
 		&crtc_state->hw.adjusted_mode;
Jeremy Cline c74a033
 	void *port = connector->port;
Jeremy Cline c74a033
-	bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
Jeremy Cline c74a033
+	bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
Jeremy Cline c74a033
 					   DP_DPCD_QUIRK_CONSTANT_N);
Jeremy Cline c74a033
 	int bpp, slots = -EINVAL;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
Jeremy Cline c74a033
index 83025052c965..82ba5624d14f 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_psr.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
Jeremy Cline c74a033
@@ -282,7 +282,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
Jeremy Cline c74a033
 	DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
Jeremy Cline c74a033
 		      intel_dp->psr_dpcd[0]);
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
Jeremy Cline c74a033
+	if (drm_dp_has_quirk(&intel_dp->desc, 0, DP_DPCD_QUIRK_NO_PSR)) {
Jeremy Cline c74a033
 		DRM_DEBUG_KMS("PSR support not currently available for this panel\n");
Jeremy Cline c74a033
 		return;
Jeremy Cline c74a033
 	}
Jeremy Cline c74a033
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
Jeremy Cline c74a033
index bc04467f7c3a..1fe49e202dfb 100644
Jeremy Cline c74a033
--- a/include/drm/drm_dp_helper.h
Jeremy Cline c74a033
+++ b/include/drm/drm_dp_helper.h
Jeremy Cline c74a033
@@ -1493,13 +1493,16 @@ struct drm_dp_desc {
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,
Jeremy Cline c74a033
 		     bool is_branch);
Jeremy Cline c74a033
+u32 drm_dp_get_edid_quirks(const struct edid *edid);
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 /**
Jeremy Cline c74a033
  * enum drm_dp_quirk - Display Port sink/branch device specific quirks
Jeremy Cline c74a033
  *
Jeremy Cline c74a033
  * Display Port sink and branch devices in the wild have a variety of bugs, try
Jeremy Cline c74a033
  * to collect them here. The quirks are shared, but it's up to the drivers to
Jeremy Cline c74a033
- * implement workarounds for them.
Jeremy Cline c74a033
+ * implement workarounds for them. Note that because some devices have
Jeremy Cline c74a033
+ * unreliable OUIDs, the EDID of sinks should also be checked for quirks using
Jeremy Cline c74a033
+ * drm_dp_get_edid_quirks().
Jeremy Cline c74a033
  */
Jeremy Cline c74a033
 enum drm_dp_quirk {
Jeremy Cline c74a033
 	/**
Jeremy Cline c74a033
@@ -1535,14 +1538,16 @@ enum drm_dp_quirk {
Jeremy Cline c74a033
 /**
Jeremy Cline c74a033
  * drm_dp_has_quirk() - does the DP device have a specific quirk
Jeremy Cline c74a033
  * @desc: Device decriptor filled by drm_dp_read_desc()
Jeremy Cline c74a033
+ * @edid_quirks: Optional quirk bitmask filled by drm_dp_get_edid_quirks()
Jeremy Cline c74a033
  * @quirk: Quirk to query for
Jeremy Cline c74a033
  *
Jeremy Cline c74a033
  * Return true if DP device identified by @desc has @quirk.
Jeremy Cline c74a033
  */
Jeremy Cline c74a033
 static inline bool
Jeremy Cline c74a033
-drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
Jeremy Cline c74a033
+drm_dp_has_quirk(const struct drm_dp_desc *desc, u32 edid_quirks,
Jeremy Cline c74a033
+		 enum drm_dp_quirk quirk)
Jeremy Cline c74a033
 {
Jeremy Cline c74a033
-	return desc->quirks & BIT(quirk);
Jeremy Cline c74a033
+	return (desc->quirks | edid_quirks) & BIT(quirk);
Jeremy Cline c74a033
 }
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 #ifdef CONFIG_DRM_DP_CEC
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033
Jeremy Cline c74a033
From a21ec8aec8452de788d6b1fc175dc8281a57d5de Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:36 -0400
Jeremy Cline c74a033
Subject: [PATCH 6/7] drm/i915: Force DPCD backlight mode on X1 Extreme 2nd Gen
Jeremy Cline c74a033
 4K AMOLED panel
Jeremy Cline c74a033
Jeremy Cline c74a033
The X1 Extreme is one of the systems that lies about which backlight
Jeremy Cline c74a033
interface that it uses in its VBIOS as PWM backlight controls don't work
Jeremy Cline c74a033
at all on this machine. It's possible that this panel could be one of
Jeremy Cline c74a033
the infamous ones that can switch between PWM mode and DPCD backlight
Jeremy Cline c74a033
control mode, but we haven't gotten any more details on this from Lenovo
Jeremy Cline c74a033
just yet. For the time being though, making sure the backlight 'just
Jeremy Cline c74a033
works' is a bit more important.
Jeremy Cline c74a033
Jeremy Cline c74a033
So, add a quirk to force DPCD backlight controls on for these systems
Jeremy Cline c74a033
based on EDID (since this panel doesn't appear to fill in the device ID).
Jeremy Cline c74a033
Hopefully in the future we'll figure out a better way of probing this.
Jeremy Cline c74a033
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Reviewed-by: Adam Jackson <ajax@redhat.com>
Jeremy Cline c74a033
Cc: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
Jeremy Cline c74a033
Changes since v2:
Jeremy Cline c74a033
* The bugzilla URL is deprecated, bug reporting happens on gitlab now.
Jeremy Cline c74a033
  Update the messages we print to reflect this
Jeremy Cline c74a033
* Also, take the opportunity to move FDO_BUG_URL out of i915_utils.c and
Jeremy Cline c74a033
  into i915_utils.h so that other places which print things that aren't
Jeremy Cline c74a033
  traditional errors but are worth filing bugs about, can actually use
Jeremy Cline c74a033
  it.
Jeremy Cline c74a033
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 drivers/gpu/drm/drm_dp_helper.c               |  4 ++++
Jeremy Cline c74a033
 .../drm/i915/display/intel_dp_aux_backlight.c | 24 +++++++++++++++----
Jeremy Cline c74a033
 drivers/gpu/drm/i915/i915_utils.c             |  1 -
Jeremy Cline c74a033
 drivers/gpu/drm/i915/i915_utils.h             |  2 ++
Jeremy Cline c74a033
 include/drm/drm_dp_helper.h                   | 10 ++++++++
Jeremy Cline c74a033
 5 files changed, 36 insertions(+), 5 deletions(-)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
index 9b2ea2ae0204..026f701eac69 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
@@ -1237,6 +1237,10 @@ struct edid_quirk {
Jeremy Cline c74a033
  * DP quirks in such cases.
Jeremy Cline c74a033
  */
Jeremy Cline c74a033
 static const struct edid_quirk edid_quirk_list[] = {
Jeremy Cline c74a033
+	/* Optional 4K AMOLED panel in the ThinkPad X1 Extreme 2nd Generation
Jeremy Cline c74a033
+	 * only supports DPCD backlight controls
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	{ MFG(0x4c, 0x83), PROD_ID(0x41, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
Jeremy Cline c74a033
 };
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 #undef MFG
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
index 77a759361c5c..a7c94c201b38 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
Jeremy Cline c74a033
@@ -328,15 +328,31 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector)
Jeremy Cline c74a033
 int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
Jeremy Cline c74a033
 {
Jeremy Cline c74a033
 	struct intel_panel *panel = &intel_connector->panel;
Jeremy Cline c74a033
-	struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
Jeremy Cline c74a033
+	struct intel_dp *intel_dp = enc_to_intel_dp(intel_connector->encoder);
Jeremy Cline c74a033
+	struct drm_device *dev = intel_connector->base.dev;
Jeremy Cline c74a033
+	struct drm_i915_private *dev_priv = to_i915(dev);
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	if (i915_modparams.enable_dpcd_backlight == 0 ||
Jeremy Cline c74a033
-	    (i915_modparams.enable_dpcd_backlight == -1 &&
Jeremy Cline c74a033
-	    dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
Jeremy Cline c74a033
+	    !intel_dp_aux_display_control_capable(intel_connector))
Jeremy Cline c74a033
 		return -ENODEV;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-	if (!intel_dp_aux_display_control_capable(intel_connector))
Jeremy Cline c74a033
+	/*
Jeremy Cline c74a033
+	 * There are a lot of machines that don't advertise the backlight
Jeremy Cline c74a033
+	 * control interface to use properly in their VBIOS, :\
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	if (dev_priv->vbt.backlight.type !=
Jeremy Cline c74a033
+	    INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE &&
Jeremy Cline c74a033
+	    !drm_dp_has_quirk(&intel_dp->desc, intel_dp->edid_quirks,
Jeremy Cline c74a033
+			      DP_QUIRK_FORCE_DPCD_BACKLIGHT)) {
Jeremy Cline c74a033
+		DRM_DEV_INFO(dev->dev,
Jeremy Cline c74a033
+			     "Panel advertises DPCD backlight support, but "
Jeremy Cline c74a033
+			     "VBT disagrees. If your backlight controls "
Jeremy Cline c74a033
+			     "don't work try booting with "
Jeremy Cline c74a033
+			     "i915.enable_dpcd_backlight=1. If your machine "
Jeremy Cline c74a033
+			     "needs this, please file a _new_ bug report on "
Jeremy Cline c74a033
+			     "drm/i915, see " FDO_BUG_URL " for details.\n");
Jeremy Cline c74a033
 		return -ENODEV;
Jeremy Cline c74a033
+	}
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 	panel->backlight.setup = intel_dp_aux_setup_backlight;
Jeremy Cline c74a033
 	panel->backlight.enable = intel_dp_aux_enable_backlight;
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/i915_utils.c b/drivers/gpu/drm/i915/i915_utils.c
Jeremy Cline c74a033
index 632d6953c78d..029854ae65fc 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/i915_utils.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/i915_utils.c
Jeremy Cline c74a033
@@ -8,7 +8,6 @@
Jeremy Cline c74a033
 #include "i915_drv.h"
Jeremy Cline c74a033
 #include "i915_utils.h"
Jeremy Cline c74a033
 
Jeremy Cline c74a033
-#define FDO_BUG_URL "https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs"
Jeremy Cline c74a033
 #define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 void
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
Jeremy Cline c74a033
index b0ade76bec90..cae0ae520398 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/i915/i915_utils.h
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/i915/i915_utils.h
Jeremy Cline c74a033
@@ -34,6 +34,8 @@
Jeremy Cline c74a033
 struct drm_i915_private;
Jeremy Cline c74a033
 struct timer_list;
Jeremy Cline c74a033
 
Jeremy Cline c74a033
+#define FDO_BUG_URL "https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs"
Jeremy Cline c74a033
+
Jeremy Cline c74a033
 #undef WARN_ON
Jeremy Cline c74a033
 /* Many gcc seem to no see through this and fall over :( */
Jeremy Cline c74a033
 #if 0
Jeremy Cline c74a033
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
Jeremy Cline c74a033
index 1fe49e202dfb..eff5a69051d6 100644
Jeremy Cline c74a033
--- a/include/drm/drm_dp_helper.h
Jeremy Cline c74a033
+++ b/include/drm/drm_dp_helper.h
Jeremy Cline c74a033
@@ -1533,6 +1533,16 @@ enum drm_dp_quirk {
Jeremy Cline c74a033
 	 * The DSC caps can be read from the physical aux instead.
Jeremy Cline c74a033
 	 */
Jeremy Cline c74a033
 	DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD,
Jeremy Cline c74a033
+	/**
Jeremy Cline c74a033
+	 * @DP_QUIRK_FORCE_DPCD_BACKLIGHT:
Jeremy Cline c74a033
+	 *
Jeremy Cline c74a033
+	 * The device is telling the truth when it says that it uses DPCD
Jeremy Cline c74a033
+	 * backlight controls, even if the system's firmware disagrees. This
Jeremy Cline c74a033
+	 * quirk should be checked against both the ident and panel EDID.
Jeremy Cline c74a033
+	 * When present, the driver should honor the DPCD backlight
Jeremy Cline c74a033
+	 * capabilities advertised.
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	DP_QUIRK_FORCE_DPCD_BACKLIGHT,
Jeremy Cline c74a033
 };
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 /**
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033
Jeremy Cline c74a033
From 057e7f8db05c2382b666270b1fbf986fdd172769 Mon Sep 17 00:00:00 2001
Jeremy Cline c74a033
From: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Date: Tue, 10 Mar 2020 14:07:37 -0400
Jeremy Cline c74a033
Subject: [PATCH 7/7] drm/i915: Force DPCD backlight mode for some Dell CML
Jeremy Cline c74a033
 2020 panels
Jeremy Cline c74a033
Jeremy Cline c74a033
According to Dell, trying to match their panels via OUI is not reliable
Jeremy Cline c74a033
enough and we've been told that we should check against the EDID
Jeremy Cline c74a033
instead. As well, Dell seems to have some panels that are actually
Jeremy Cline c74a033
intended to switch between using PWM for backlight controls and DPCD for
Jeremy Cline c74a033
backlight controls depending on whether or not the panel is in HDR or
Jeremy Cline c74a033
SDR mode. Yikes.
Jeremy Cline c74a033
Jeremy Cline c74a033
Regardless, we need to add quirks for these so that DPCD backlight
Jeremy Cline c74a033
controls get enabled by default, since without additional driver support
Jeremy Cline c74a033
that's the only form of brightness control that will work. Hopefully in
Jeremy Cline c74a033
the future we can remove these quirks once we have a better way of
Jeremy Cline c74a033
probing for this.
Jeremy Cline c74a033
Jeremy Cline c74a033
Changes since v1:
Jeremy Cline c74a033
* Add one more EDID per Dell's request
Jeremy Cline c74a033
* Remove model number (which is possibly wrong) and replace with Dell
Jeremy Cline c74a033
  CML 2020 systems
Jeremy Cline c74a033
Jeremy Cline c74a033
Signed-off-by: Lyude Paul <lyude@redhat.com>
Jeremy Cline c74a033
Reviewed-by: Adam Jackson <ajax@redhat.com>
Jeremy Cline c74a033
Cc: Jani Nikula <jani.nikula@intel.com>
Jeremy Cline c74a033
---
Jeremy Cline c74a033
 drivers/gpu/drm/drm_dp_helper.c | 14 ++++++++++++++
Jeremy Cline c74a033
 1 file changed, 14 insertions(+)
Jeremy Cline c74a033
Jeremy Cline c74a033
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
index 026f701eac69..d3a636a925d4 100644
Jeremy Cline c74a033
--- a/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
+++ b/drivers/gpu/drm/drm_dp_helper.c
Jeremy Cline c74a033
@@ -1241,6 +1241,20 @@ static const struct edid_quirk edid_quirk_list[] = {
Jeremy Cline c74a033
 	 * only supports DPCD backlight controls
Jeremy Cline c74a033
 	 */
Jeremy Cline c74a033
 	{ MFG(0x4c, 0x83), PROD_ID(0x41, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
Jeremy Cline c74a033
+	/*
Jeremy Cline c74a033
+	 * Some Dell CML 2020 systems have panels support both AUX and PWM
Jeremy Cline c74a033
+	 * backlight control, and some only support AUX backlight control. All
Jeremy Cline c74a033
+	 * said panels start up in AUX mode by default, and we don't have any
Jeremy Cline c74a033
+	 * support for disabling HDR mode on these panels which would be
Jeremy Cline c74a033
+	 * required to switch to PWM backlight control mode (plus, I'm not
Jeremy Cline c74a033
+	 * even sure we want PWM backlight controls over DPCD backlight
Jeremy Cline c74a033
+	 * controls anyway...). Until we have a better way of detecting these,
Jeremy Cline c74a033
+	 * force DPCD backlight mode on all of them.
Jeremy Cline c74a033
+	 */
Jeremy Cline c74a033
+	{ MFG(0x06, 0xaf), PROD_ID(0x9b, 0x32), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
Jeremy Cline c74a033
+	{ MFG(0x06, 0xaf), PROD_ID(0xeb, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
Jeremy Cline c74a033
+	{ MFG(0x4d, 0x10), PROD_ID(0xc7, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
Jeremy Cline c74a033
+	{ MFG(0x4d, 0x10), PROD_ID(0xe6, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
Jeremy Cline c74a033
 };
Jeremy Cline c74a033
 
Jeremy Cline c74a033
 #undef MFG
Jeremy Cline c74a033
-- 
Jeremy Cline c74a033
2.25.1
Jeremy Cline c74a033