OSDN Git Service

drm/i915/edp: modify fixed and downclock modes for MSO
authorJani Nikula <jani.nikula@intel.com>
Tue, 2 Mar 2021 11:03:01 +0000 (13:03 +0200)
committerJani Nikula <jani.nikula@intel.com>
Thu, 4 Mar 2021 05:50:15 +0000 (07:50 +0200)
In the case of MSO (Multi-SST Operation), the EDID contains the timings
for a single panel segment. We'll want to hide the fact from userspace,
and expose modes that span the entire display.

Don't modify the EDID, as the userspace should not use that for
modesetting, only modify the actual modes.

v3: Use pixel overlap if available.

v2: Rename intel_dp_mso_mode_fixup -> intel_edp_mso_mode_fixup

Cc: Nischal Varide <nischal.varide@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/2862284eb033bb0ffc96134b7d5b11bf29e4587f.1614682842.git.jani.nikula@intel.com
drivers/gpu/drm/i915/display/intel_dp.c

index 2ec82a5..2d0001e 100644 (file)
@@ -3516,6 +3516,31 @@ static void intel_dp_get_dsc_sink_cap(struct intel_dp *intel_dp)
        }
 }
 
+static void intel_edp_mso_mode_fixup(struct intel_connector *connector,
+                                    struct drm_display_mode *mode)
+{
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       int n = intel_dp->mso_link_count;
+       int overlap = intel_dp->mso_pixel_overlap;
+
+       if (!mode || !n)
+               return;
+
+       mode->hdisplay = (mode->hdisplay - overlap) * n;
+       mode->hsync_start = (mode->hsync_start - overlap) * n;
+       mode->hsync_end = (mode->hsync_end - overlap) * n;
+       mode->htotal = (mode->htotal - overlap) * n;
+       mode->clock *= n;
+
+       drm_mode_set_name(mode);
+
+       drm_dbg_kms(&i915->drm,
+                   "[CONNECTOR:%d:%s] using generated MSO mode: ",
+                   connector->base.base.id, connector->base.name);
+       drm_mode_debug_printmodeline(mode);
+}
+
 static void intel_edp_mso_init(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -6493,6 +6518,10 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        if (fixed_mode)
                downclock_mode = intel_dp_drrs_init(intel_connector, fixed_mode);
 
+       /* multiply the mode clock and horizontal timings for MSO */
+       intel_edp_mso_mode_fixup(intel_connector, fixed_mode);
+       intel_edp_mso_mode_fixup(intel_connector, downclock_mode);
+
        /* fallback to VBT if available for eDP */
        if (!fixed_mode)
                fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);