summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/display/intel_panel.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2022-05-31 22:18:41 +0300
committerVille Syrjälä <ville.syrjala@linux.intel.com>2022-06-01 16:45:42 +0300
commit6e939738da208bcc0e4dc794519e18cad85bca73 (patch)
tree582f09d440346f2c7e40bc4a495db8f1e2cfe6f4 /drivers/gpu/drm/i915/display/intel_panel.c
parent2db7d421cc5ca86bdcf57f2634f6eefdf349f998 (diff)
downloadlinux-6e939738da208bcc0e4dc794519e18cad85bca73.tar.gz
linux-6e939738da208bcc0e4dc794519e18cad85bca73.tar.bz2
linux-6e939738da208bcc0e4dc794519e18cad85bca73.zip
drm/i915: Accept more fixed modes with VRR panels
It seem that when dealing with VRR capable eDP panels we need to accept fixed modes with variable vblank length (which is what VRR varies dynamically). Typically the preferred mode seems to be a non-VRR more (lowish dotclock/refresh rate + short vblank). We also have examples where it looks like even the hblank length is a bit different between the preferred mode vs. VRR mode(s). So let's just accept anything that has matching hdisp+vdisp+flags. v2: Document that is_alt_drrs_mode() is a subset of is_alt_vrr_mode() (Jani) Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/125 Reviewed-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220531191844.11313-4-ville.syrjala@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_panel.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index f55e4eafd74e..237a40623dd7 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -71,6 +71,27 @@ intel_panel_fixed_mode(struct intel_connector *connector,
return best_mode;
}
+static bool is_alt_drrs_mode(const struct drm_display_mode *mode,
+ const struct drm_display_mode *preferred_mode)
+{
+ return drm_mode_match(mode, preferred_mode,
+ DRM_MODE_MATCH_TIMINGS |
+ DRM_MODE_MATCH_FLAGS |
+ DRM_MODE_MATCH_3D_FLAGS) &&
+ mode->clock != preferred_mode->clock;
+}
+
+static bool is_alt_vrr_mode(const struct drm_display_mode *mode,
+ const struct drm_display_mode *preferred_mode)
+{
+ return drm_mode_match(mode, preferred_mode,
+ DRM_MODE_MATCH_FLAGS |
+ DRM_MODE_MATCH_3D_FLAGS) &&
+ mode->hdisplay == preferred_mode->hdisplay &&
+ mode->vdisplay == preferred_mode->vdisplay &&
+ mode->clock != preferred_mode->clock;
+}
+
const struct drm_display_mode *
intel_panel_downclock_mode(struct intel_connector *connector,
const struct drm_display_mode *adjusted_mode)
@@ -83,7 +104,8 @@ intel_panel_downclock_mode(struct intel_connector *connector,
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
int vrefresh = drm_mode_vrefresh(fixed_mode);
- if (vrefresh >= min_vrefresh && vrefresh < max_vrefresh) {
+ if (is_alt_drrs_mode(fixed_mode, adjusted_mode) &&
+ vrefresh >= min_vrefresh && vrefresh < max_vrefresh) {
max_vrefresh = vrefresh;
best_mode = fixed_mode;
}
@@ -151,16 +173,18 @@ int intel_panel_compute_config(struct intel_connector *connector,
}
static bool is_alt_fixed_mode(const struct drm_display_mode *mode,
- const struct drm_display_mode *preferred_mode)
+ const struct drm_display_mode *preferred_mode,
+ bool has_vrr)
{
- return drm_mode_match(mode, preferred_mode,
- DRM_MODE_MATCH_TIMINGS |
- DRM_MODE_MATCH_FLAGS |
- DRM_MODE_MATCH_3D_FLAGS) &&
- mode->clock != preferred_mode->clock;
+ /* is_alt_drrs_mode() is a subset of is_alt_vrr_mode() */
+ if (has_vrr)
+ return is_alt_vrr_mode(mode, preferred_mode);
+ else
+ return is_alt_drrs_mode(mode, preferred_mode);
}
-static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector)
+static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector,
+ bool has_vrr)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
const struct drm_display_mode *preferred_mode =
@@ -168,7 +192,7 @@ static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connect
struct drm_display_mode *mode, *next;
list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
- if (!is_alt_fixed_mode(mode, preferred_mode))
+ if (!is_alt_fixed_mode(mode, preferred_mode, has_vrr))
continue;
drm_dbg_kms(&dev_priv->drm,
@@ -226,11 +250,12 @@ static void intel_panel_destroy_probed_modes(struct intel_connector *connector)
}
}
-void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs)
+void intel_panel_add_edid_fixed_modes(struct intel_connector *connector,
+ bool has_drrs, bool has_vrr)
{
intel_panel_add_edid_preferred_mode(connector);
- if (intel_panel_preferred_fixed_mode(connector) && has_drrs)
- intel_panel_add_edid_alt_fixed_modes(connector);
+ if (intel_panel_preferred_fixed_mode(connector) && (has_drrs || has_vrr))
+ intel_panel_add_edid_alt_fixed_modes(connector, has_vrr);
intel_panel_destroy_probed_modes(connector);
}