diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 6b84508a5339..a0d0cd4c1c1b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1767,10 +1767,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane, struct drm_display_mode *mode = NULL; struct vop_win *win = to_vop_win(plane); struct vop_plane_state *vop_plane_state = to_vop_plane_state(state); + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; struct rockchip_crtc_state *s; struct vop *vop = to_vop(state->crtc); struct drm_framebuffer *fb = state->fb; - unsigned int actual_w, actual_h; + unsigned int actual_w, actual_h, dsp_w, dsp_h; unsigned int dsp_stx, dsp_sty; uint32_t act_info, dsp_info, dsp_st; struct drm_rect *src = &vop_plane_state->src; @@ -1823,10 +1824,30 @@ static void vop_plane_atomic_update(struct drm_plane *plane, mode = &crtc->state->adjusted_mode; actual_w = drm_rect_width(src) >> 16; actual_h = drm_rect_height(src) >> 16; + + dsp_w = drm_rect_width(dest); + if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { + DRM_ERROR("%s win%d dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", + crtc->name, win->win_id, dest->x1, dsp_w, adjusted_mode->hdisplay); + dsp_w = adjusted_mode->hdisplay - dest->x1; + if (dsp_w < 4) + dsp_w = 4; + actual_w = dsp_w * actual_w / drm_rect_width(dest); + } + dsp_h = drm_rect_height(dest); + if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { + DRM_ERROR("%s win%d dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", + crtc->name, win->win_id, dest->y1, dsp_h, adjusted_mode->vdisplay); + dsp_h = adjusted_mode->vdisplay - dest->y1; + if (dsp_h < 4) + dsp_h = 4; + actual_h = dsp_h * actual_h / drm_rect_height(dest); + } + act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); - dsp_info = (drm_rect_height(dest) - 1) << 16; - dsp_info |= (drm_rect_width(dest) - 1) & 0xffff; + dsp_info = (dsp_h - 1) << 16; + dsp_info |= (dsp_w - 1) & 0xffff; dsp_stx = dest->x1 + mode->crtc_htotal - mode->crtc_hsync_start; dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start;