diff mbox series

[2/6] drm/i915: Pick the first mode from EDID as the fixed mode when there is no preferred mode

Message ID 20190321132446.22394-2-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series [1/6] drm/i915: Refactor EDID fixed mode search | expand

Commit Message

Ville Syrjälä March 21, 2019, 1:24 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Some monitors apparently forget to mark any mode as preferred in the
EDID. In this particular case we have a very generic looking ID
"PNP Model 0 Serial Number 4" / "LVDS 800x600" so a specific quirk
doesn't seem particularly wise. Also the quirk we have
(EDID_QUIRK_FIRST_DETAILED_PREFERRED) is actually defunct so we'd
have to fix it first.

When there is no preferred mode we currently fall back to the VBT.
That approach fails us here as the VBT mode is 1024x768 whereas
the panel resolution is 800x600. So instead of falling back to the
VBT when there is no preferred mode let's just pick the first
probed mode. Only if the EDID provided no modes we fall back to
the VBT.

For this machine the VBIOS would appear to select the 800x600
60Hz EST mode rather than the first detailed mode (which is
the new fallback will pick). The two modes differ only by
having opposite sync polarities, which does not seem to matter
to the panel in question.

v2: Make sure the probed_modes list is not empty

Cc: Adam Jackson <ajax@redhat.com>
Cc: Roberto Viola <cagnulein@gmail.com>
Tested-by: Roberto Viola <cagnulein@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109780
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_panel.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

Comments

Adam Jackson March 21, 2019, 2:54 p.m. UTC | #1
On Thu, 2019-03-21 at 15:24 +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Some monitors apparently forget to mark any mode as preferred in the
> EDID. In this particular case we have a very generic looking ID
> "PNP Model 0 Serial Number 4" / "LVDS 800x600" so a specific quirk
> doesn't seem particularly wise. Also the quirk we have
> (EDID_QUIRK_FIRST_DETAILED_PREFERRED) is actually defunct so we'd
> have to fix it first.
> 
> When there is no preferred mode we currently fall back to the VBT.
> That approach fails us here as the VBT mode is 1024x768 whereas
> the panel resolution is 800x600. So instead of falling back to the
> VBT when there is no preferred mode let's just pick the first
> probed mode. Only if the EDID provided no modes we fall back to
> the VBT.
> 
> For this machine the VBIOS would appear to select the 800x600
> 60Hz EST mode rather than the first detailed mode (which is
> the new fallback will pick). The two modes differ only by
> having opposite sync polarities, which does not seem to matter
> to the panel in question.

Took me a moment to realize this was only about panels on i915, and not
any monitor/connector with no preferred modes. Looks sane to me though.

Reviewed-by: Adam Jackson <ajax@redhat.com>

- ajax
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index f42137512010..b9ee18c2dff5 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -104,11 +104,13 @@  intel_panel_edid_fixed_mode(struct intel_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	const struct drm_display_mode *scan;
+	struct drm_display_mode *fixed_mode;
+
+	if (list_empty(&connector->base.probed_modes))
+		return NULL;
 
 	/* prefer fixed mode from EDID if available */
 	list_for_each_entry(scan, &connector->base.probed_modes, head) {
-		struct drm_display_mode *fixed_mode;
-
 		if ((scan->type & DRM_MODE_TYPE_PREFERRED) == 0)
 			continue;
 
@@ -123,7 +125,20 @@  intel_panel_edid_fixed_mode(struct intel_connector *connector)
 		return fixed_mode;
 	}
 
-	return NULL;
+	scan = list_first_entry(&connector->base.probed_modes,
+				typeof(*scan), head);
+
+	fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
+	if (!fixed_mode)
+		return NULL;
+
+	fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using first mode from EDID: ",
+		      connector->base.base.id, connector->base.name);
+	drm_mode_debug_printmodeline(fixed_mode);
+
+	return fixed_mode;
 }
 
 /* adjusted_mode has been preset to be the panel's fixed mode */