diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2017-08-15 18:52:04 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2017-12-04 19:38:31 +0300 |
commit | 401712e035c699d569dbd37024f4b21dc76cc870 (patch) | |
tree | e7c934c91b19b7f89ad107199513f298b16edb7e /drivers/gpu/drm/rcar-du/rcar_du_vsp.c | |
parent | 9c893a61b79d38b8997cc417a6b359222cf92414 (diff) | |
download | linux-401712e035c699d569dbd37024f4b21dc76cc870.tar.xz |
drm: rcar-du: Clip planes to screen boundaries
Unlike the KMS API, the hardware doesn't support planes exceeding the
screen boundaries or planes being located fully off-screen. We need to
clip plane coordinates to support the use case.
Fortunately the DRM core offers a drm_atomic_helper_check_plane_state()
helper that validates the scaling factor and clips the plane
coordinates. Use it to implement the plane atomic check and use the
clipped source and destination rectangles from the plane state instead
of the unclipped source and CRTC coordinates to configure the device.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Diffstat (limited to 'drivers/gpu/drm/rcar-du/rcar_du_vsp.c')
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index dd66dcb8da23..2c260c33840b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -55,14 +55,14 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) struct rcar_du_plane_state state = { .state = { .crtc = &crtc->crtc, - .crtc_x = 0, - .crtc_y = 0, - .crtc_w = mode->hdisplay, - .crtc_h = mode->vdisplay, - .src_x = 0, - .src_y = 0, - .src_w = mode->hdisplay << 16, - .src_h = mode->vdisplay << 16, + .dst.x1 = 0, + .dst.y1 = 0, + .dst.x2 = mode->hdisplay, + .dst.y2 = mode->vdisplay, + .src.x1 = 0, + .src.y1 = 0, + .src.x2 = mode->hdisplay << 16, + .src.y2 = mode->vdisplay << 16, .zpos = 0, }, .format = rcar_du_format_info(DRM_FORMAT_ARGB8888), @@ -178,15 +178,15 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) }; unsigned int i; - cfg.src.left = state->state.src_x >> 16; - cfg.src.top = state->state.src_y >> 16; - cfg.src.width = state->state.src_w >> 16; - cfg.src.height = state->state.src_h >> 16; + cfg.src.left = state->state.src.x1 >> 16; + cfg.src.top = state->state.src.y1 >> 16; + cfg.src.width = drm_rect_width(&state->state.src) >> 16; + cfg.src.height = drm_rect_height(&state->state.src) >> 16; - cfg.dst.left = state->state.crtc_x; - cfg.dst.top = state->state.crtc_y; - cfg.dst.width = state->state.crtc_w; - cfg.dst.height = state->state.crtc_h; + cfg.dst.left = state->state.dst.x1; + cfg.dst.top = state->state.dst.y1; + cfg.dst.width = drm_rect_width(&state->state.dst); + cfg.dst.height = drm_rect_height(&state->state.dst); for (i = 0; i < state->format->planes; ++i) cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl) @@ -212,7 +212,11 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, unsigned int i; int ret; - if (!state->fb) + /* + * There's no need to prepare (and unprepare) the framebuffer when the + * plane is not visible, as it will not be displayed. + */ + if (!state->visible) return 0; for (i = 0; i < rstate->format->planes; ++i) { @@ -253,7 +257,7 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp; unsigned int i; - if (!state->fb) + if (!state->visible) return; for (i = 0; i < rstate->format->planes; ++i) { @@ -278,7 +282,7 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane, struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane); struct rcar_du_crtc *crtc = to_rcar_crtc(old_state->crtc); - if (plane->state->crtc) + if (plane->state->visible) rcar_du_vsp_plane_setup(rplane); else vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe, |