[PATCH] i915: Add QUIRK_EDP_CHANNEL_EQ for Dell 7200 2-in-1
From: Jason Andryuk
Date: Fri Oct 23 2020 - 08:48:20 EST
We're seeing channel equalization "fail" consistently coming out of DPMS
on the eDP of a Dell Latitude 7200 2-in-1. When the display tries to
come out of DPMS, it briefly flashes on before going dark. This repeats
once per second, and the system is unusable. ssh-ing into the system,
it also seems to be sluggish when in this state. You have to reboot to
get the display back.
In intel_dp_link_training_channel_equalization, lane 0 can get to state
0x7 by the 3rd pattern, but lane 1 never gets further than 0x1.
[drm] ln0_1:0x0 ln2_3:0x0 align:0x0 sink:0x0 adj_req0_1:0x0 adj_req2_3:0x0
[drm] ln0_1:0x11 ln2_3:0x0 align:0x80 sink:0x0 adj_req0_1:0x44 adj_req2_3:0x0
[drm] ln0_1:0x11 ln2_3:0x0 align:0x80 sink:0x0 adj_req0_1:0x88 adj_req2_3:0x0
[drm] ln0_1:0x71 ln2_3:0x0 align:0x80 sink:0x0 adj_req0_1:0x84 adj_req2_3:0x0
[drm] ln0_1:0x71 ln2_3:0x0 align:0x0 sink:0x0 adj_req0_1:0x84 adj_req2_3:0x0
[drm] ln0_1:0x71 ln2_3:0x0 align:0x0 sink:0x0 adj_req0_1:0x84 adj_req2_3:0x0
Narrow fast vs. wide slow is not an option because the max clock is
270000 and the 1920x1280 resolution requires 2x270000.
[drm] DP link computation with lane count min/max 1/2 270000/270000 bpp
min/max 18/24 pixel clock 164250KHz
The display is functional even though lane 1 is in state 0x1, so just
return success for channel equalization on eDP.
Introduce QUIRK_EDP_CHANNEL_EQ and match the DMI for a Dell Latitude
7200 2-in-1. This quirk allows channel equalization to succeed even
though it failed.
Workaround for https://gitlab.freedesktop.org/drm/intel/-/issues/1378
Signed-off-by: Jason Andryuk <jandryuk@xxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx>
---
.../drm/i915/display/intel_dp_link_training.c | 7 +++++
drivers/gpu/drm/i915/display/intel_quirks.c | 30 +++++++++++++++++++
drivers/gpu/drm/i915/i915_drv.h | 1 +
3 files changed, 38 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index a23ed7290843..2dd441a94fda 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -375,6 +375,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
intel_dp_set_idle_link_train(intel_dp);
+ if (channel_eq == false &&
+ intel_dp_is_edp(intel_dp) &&
+ i915->quirks & QUIRK_EDP_CHANNEL_EQ) {
+ DRM_NOTE("Forcing channel_eq success for eDP\n");
+ channel_eq = true;
+ }
+
return channel_eq;
}
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
index 46beb155d835..b45b23680321 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -53,6 +53,17 @@ static void quirk_increase_ddi_disabled_time(struct drm_i915_private *i915)
drm_info(&i915->drm, "Applying Increase DDI Disabled quirk\n");
}
+/*
+ * Some machines (Dell Latitude 7200 2-in-1) fail channel equalization
+ * on their eDP when it is actually usable. This lets channel_eq
+ * report success.
+ */
+static void quirk_edp_channel_eq(struct drm_i915_private *i915)
+{
+ i915->quirks |= QUIRK_EDP_CHANNEL_EQ;
+ drm_info(&i915->drm, "applying eDP channel_eq quirk\n");
+}
+
struct intel_quirk {
int device;
int subsystem_vendor;
@@ -72,6 +83,12 @@ static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
return 1;
}
+static int intel_dmi_edp_channel_eq(const struct dmi_system_id *id)
+{
+ DRM_INFO("eDP channel_eq workaround on %s\n", id->ident);
+ return 1;
+}
+
static const struct intel_dmi_quirk intel_dmi_quirks[] = {
{
.dmi_id_list = &(const struct dmi_system_id[]) {
@@ -96,6 +113,19 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = {
},
.hook = quirk_invert_brightness,
},
+ {
+ .dmi_id_list = &(const struct dmi_system_id[]) {
+ {
+ .callback = intel_dmi_edp_channel_eq,
+ .ident = "Dell Latitude 7200 2-in-1",
+ .matches = {DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 7200 2-in-1"),
+ },
+ },
+ { } /* terminating entry */
+ },
+ .hook = quirk_edp_channel_eq,
+ },
};
static struct intel_quirk intel_quirks[] = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e4f7f6518945..fc32ea7380b7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -525,6 +525,7 @@ struct i915_psr {
#define QUIRK_PIN_SWIZZLED_PAGES (1<<5)
#define QUIRK_INCREASE_T12_DELAY (1<<6)
#define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7)
+#define QUIRK_EDP_CHANNEL_EQ (1<<8)
struct intel_fbdev;
struct intel_fbc_work;
--
2.26.2