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