diff mbox series

i915: Add QUIRK_EDP_CHANNEL_EQ for Dell 7200 2-in-1

Message ID 20201023124804.11457-1-jandryuk@gmail.com (mailing list archive)
State New, archived
Headers show
Series i915: Add QUIRK_EDP_CHANNEL_EQ for Dell 7200 2-in-1 | expand

Commit Message

Jason Andryuk Oct. 23, 2020, 12:48 p.m. UTC
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@gmail.com>
Cc: <stable@vger.kernel.org>
---
 .../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(+)

Comments

Jason Andryuk Oct. 26, 2020, 1:11 p.m. UTC | #1
On Fri, Oct 23, 2020 at 8:48 AM Jason Andryuk <jandryuk@gmail.com> wrote:
>
> 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

CI reported the patch doesn't apply to drm-tip.  It was developed
against 5.4 and forward ported to 5.10-rc1-ish when I submitted it.
It applied there but not to drm-tip.

5.4 & 5.6.6 is fine until DPMS.  Then when it tries to come out, it
fails link training and gives the flashing.
5.8.16 starts flashing during boot.  I guess the driver now runs link
training during boot?

drm-tip doesn't have the flashing issue.  I guess "drm/i915: Switch to
LTTPR non-transparent mode link training"  or some of the other link
training change lets the hardware succeed?

Oh, this is interesting:
kernel: i915 0000:00:02.0: [drm:hsw_set_signal_levels [i915]] Using
signal levels 02000000
kernel: [drm:intel_dp_link_train_phy [i915]] ln0_1:0x71 ln2_3:0x0
align:0x0 sink:0x0 adj_req0_1:0x84 adj_req2_3:0x0
kernel: i915 0000:00:02.0: [drm:intel_dp_link_train_phy [i915]]
Channel equalization failed 5 times
kernel: i915 0000:00:02.0: [drm:intel_dp_link_train_phy [i915]]
[CONNECTOR:95:eDP-1] Link Training failed at link rate = 270000, lane
count = 2, at DPRX
kernel: i915 0000:00:02.0: [drm:intel_enable_pipe [i915]] enabling pipe A

Note DPRX above, so not using LTTPR.

Looks like the link training logic is wrong. :

intel_dp_link_training_channel_equalization fails, so
intel_dp_link_train_phy fails, but:

intel_dp_link_train_all_phys(struct intel_dp *intel_dp,
                             const struct intel_crtc_state *crtc_state,
                             int lttpr_count)
{
        bool ret = true;
        int i;

        intel_dp_prepare_link_train(intel_dp, crtc_state);

        for (i = lttpr_count - 1; i >= 0; i--) {
                enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i);

                ret = intel_dp_link_train_phy(intel_dp, crtc_state, dp_phy);
                intel_dp_disable_dpcd_training_pattern(intel_dp, dp_phy);

                if (!ret)
                        break;
        }

        if (ret)
                intel_dp_link_train_phy(intel_dp, crtc_state, DP_PHY_DPRX);

Here we don't update ret, so linking training "succeeds" for DPRX.

This does let the 7200 display "work", but it's probably not what you
want in general.

Regards,
Jason
diff mbox series

Patch

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;