]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/pfit: Prevent negative coordinates in center mode
authorNemesa Garg <nemesa.garg@intel.com>
Thu, 2 Apr 2026 06:13:10 +0000 (11:43 +0530)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 7 Apr 2026 15:21:26 +0000 (18:21 +0300)
When the pipe_src width or height are greater than adjusted_mode hdisplay
and vdisplay, computed x and y offsets for center mode can be negative.
Writing negative values into the pch_fit registers result in a state error.
Add a check to clamp these values so that they are never negative.

v2: Compare in terms of pipe_src width and height.[Ville]
v3: Change width/height to pipe_src_w/h in logging. [Ville]

Signed-off-by: Nemesa Garg <nemesa.garg@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/20260402061310.111073-1-nemesa.garg@intel.com
drivers/gpu/drm/i915/display/intel_pfit.c

index 6dda496190e07d18b009d313d2e518216de48909..2dec4ccf74ced3bf07bf3a2a40b3278c0b910b07 100644 (file)
@@ -186,6 +186,7 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
                             const struct drm_connector_state *conn_state)
 {
        struct intel_display *display = to_intel_display(crtc_state);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        const struct drm_display_mode *adjusted_mode =
                &crtc_state->hw.adjusted_mode;
        int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
@@ -200,6 +201,16 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
 
        switch (conn_state->scaling_mode) {
        case DRM_MODE_SCALE_CENTER:
+               if (adjusted_mode->crtc_hdisplay < pipe_src_w ||
+                   adjusted_mode->crtc_vdisplay < pipe_src_h) {
+                       drm_dbg_kms(display->drm,
+                                   "[CRTC:%d:%s] pfit center mode source (%dx%d) exceeds display (%dx%d)\n",
+                                   crtc->base.base.id, crtc->base.name,
+                                   pipe_src_w, pipe_src_h,
+                                   adjusted_mode->crtc_hdisplay,
+                                   adjusted_mode->crtc_vdisplay);
+                       return -EINVAL;
+               }
                width = pipe_src_w;
                height = pipe_src_h;
                x = (adjusted_mode->crtc_hdisplay - width + 1)/2;