drm/i915: Check timings against hardware maximums
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Fri, 15 Jun 2018 17:44:05 +0000 (20:44 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 19 Jun 2018 14:18:24 +0000 (17:18 +0300)
Validate that all display timings fit within the number of bits
we have in the transcoder timing registers.

The limits are:
hsw+:
 4k: vdisplay, vblank_start
 8k: everything else
gen3+:
 4k: h/vdisplay, h/vblank_start
 8k: everything else
gen2:
 2k: h/vdisplay, h/vblank_start
 4k: everything else

Also document the fact that the mode_config.max_width/height limits
refer to just the max framebuffer dimensions we support. Which may
be larger than the max hdisplay/vdisplay.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180615174406.12258-2-ville.syrjala@linux.intel.com
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
drivers/gpu/drm/i915/intel_display.c

index aa7fed31ccda04edf3ff483c779490803571fa47..b2a5a9ed940401ca0aec4406df1959acd2512f57 100644 (file)
@@ -14570,6 +14570,10 @@ static enum drm_mode_status
 intel_mode_valid(struct drm_device *dev,
                 const struct drm_display_mode *mode)
 {
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       int hdisplay_max, htotal_max;
+       int vdisplay_max, vtotal_max;
+
        /*
         * Can't reject DBLSCAN here because Xorg ddxen can add piles
         * of DBLSCAN modes to the output's mode list when they detect
@@ -14599,6 +14603,36 @@ intel_mode_valid(struct drm_device *dev,
                           DRM_MODE_FLAG_CLKDIV2))
                return MODE_BAD;
 
+       if (INTEL_GEN(dev_priv) >= 9 ||
+           IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
+               hdisplay_max = 8192; /* FDI max 4096 handled elsewhere */
+               vdisplay_max = 4096;
+               htotal_max = 8192;
+               vtotal_max = 8192;
+       } else if (INTEL_GEN(dev_priv) >= 3) {
+               hdisplay_max = 4096;
+               vdisplay_max = 4096;
+               htotal_max = 8192;
+               vtotal_max = 8192;
+       } else {
+               hdisplay_max = 2048;
+               vdisplay_max = 2048;
+               htotal_max = 4096;
+               vtotal_max = 4096;
+       }
+
+       if (mode->hdisplay > hdisplay_max ||
+           mode->hsync_start > htotal_max ||
+           mode->hsync_end > htotal_max ||
+           mode->htotal > htotal_max)
+               return MODE_H_ILLEGAL;
+
+       if (mode->vdisplay > vdisplay_max ||
+           mode->vsync_start > vtotal_max ||
+           mode->vsync_end > vtotal_max ||
+           mode->vtotal > vtotal_max)
+               return MODE_V_ILLEGAL;
+
        return MODE_OK;
 }
 
@@ -15037,6 +15071,7 @@ int intel_modeset_init(struct drm_device *dev)
                }
        }
 
+       /* maximum framebuffer dimensions */
        if (IS_GEN2(dev_priv)) {
                dev->mode_config.max_width = 2048;
                dev->mode_config.max_height = 2048;