aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2017-08-15 11:52:04 -0400
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2017-12-04 11:38:31 -0500
commit401712e035c699d569dbd37024f4b21dc76cc870 (patch)
treee7c934c91b19b7f89ad107199513f298b16edb7e /drivers
parent9c893a61b79d38b8997cc417a6b359222cf92414 (diff)
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')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c3
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c50
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.c42
3 files changed, 62 insertions, 33 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index b492063a6e1f..5685d5af6998 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -319,7 +319,8 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
319 struct rcar_du_plane *plane = &rcrtc->group->planes[i]; 319 struct rcar_du_plane *plane = &rcrtc->group->planes[i];
320 unsigned int j; 320 unsigned int j;
321 321
322 if (plane->plane.state->crtc != &rcrtc->crtc) 322 if (plane->plane.state->crtc != &rcrtc->crtc ||
323 !plane->plane.state->visible)
323 continue; 324 continue;
324 325
325 /* Insert the plane in the sorted planes array. */ 326 /* Insert the plane in the sorted planes array. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 4f076c364f25..4a3d16cf3ed6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -332,8 +332,8 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
332static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, 332static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
333 const struct rcar_du_plane_state *state) 333 const struct rcar_du_plane_state *state)
334{ 334{
335 unsigned int src_x = state->state.src_x >> 16; 335 unsigned int src_x = state->state.src.x1 >> 16;
336 unsigned int src_y = state->state.src_y >> 16; 336 unsigned int src_y = state->state.src.y1 >> 16;
337 unsigned int index = state->hwindex; 337 unsigned int index = state->hwindex;
338 unsigned int pitch; 338 unsigned int pitch;
339 bool interlaced; 339 bool interlaced;
@@ -357,7 +357,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
357 dma[i] = gem->paddr + fb->offsets[i]; 357 dma[i] = gem->paddr + fb->offsets[i];
358 } 358 }
359 } else { 359 } else {
360 pitch = state->state.src_w >> 16; 360 pitch = drm_rect_width(&state->state.src) >> 16;
361 dma[0] = 0; 361 dma[0] = 0;
362 dma[1] = 0; 362 dma[1] = 0;
363 } 363 }
@@ -521,6 +521,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
521 const struct rcar_du_plane_state *state) 521 const struct rcar_du_plane_state *state)
522{ 522{
523 struct rcar_du_device *rcdu = rgrp->dev; 523 struct rcar_du_device *rcdu = rgrp->dev;
524 const struct drm_rect *dst = &state->state.dst;
524 525
525 if (rcdu->info->gen < 3) 526 if (rcdu->info->gen < 3)
526 rcar_du_plane_setup_format_gen2(rgrp, index, state); 527 rcar_du_plane_setup_format_gen2(rgrp, index, state);
@@ -528,10 +529,10 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
528 rcar_du_plane_setup_format_gen3(rgrp, index, state); 529 rcar_du_plane_setup_format_gen3(rgrp, index, state);
529 530
530 /* Destination position and size */ 531 /* Destination position and size */
531 rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w); 532 rcar_du_plane_write(rgrp, index, PnDSXR, drm_rect_width(dst));
532 rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h); 533 rcar_du_plane_write(rgrp, index, PnDSYR, drm_rect_height(dst));
533 rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x); 534 rcar_du_plane_write(rgrp, index, PnDPXR, dst->x1);
534 rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y); 535 rcar_du_plane_write(rgrp, index, PnDPYR, dst->y1);
535 536
536 if (rcdu->info->gen < 3) { 537 if (rcdu->info->gen < 3) {
537 /* Wrap-around and blinking, disabled */ 538 /* Wrap-around and blinking, disabled */
@@ -570,16 +571,39 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
570 const struct rcar_du_format_info **format) 571 const struct rcar_du_format_info **format)
571{ 572{
572 struct drm_device *dev = plane->dev; 573 struct drm_device *dev = plane->dev;
574 struct drm_crtc_state *crtc_state;
575 struct drm_rect clip;
576 int ret;
573 577
574 if (!state->fb || !state->crtc) { 578 if (!state->crtc) {
579 /*
580 * The visible field is not reset by the DRM core but only
581 * updated by drm_plane_helper_check_state(), set it manually.
582 */
583 state->visible = false;
575 *format = NULL; 584 *format = NULL;
576 return 0; 585 return 0;
577 } 586 }
578 587
579 if (state->src_w >> 16 != state->crtc_w || 588 crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
580 state->src_h >> 16 != state->crtc_h) { 589 if (IS_ERR(crtc_state))
581 dev_dbg(dev->dev, "%s: scaling not supported\n", __func__); 590 return PTR_ERR(crtc_state);
582 return -EINVAL; 591
592 clip.x1 = 0;
593 clip.y1 = 0;
594 clip.x2 = crtc_state->mode.hdisplay;
595 clip.y2 = crtc_state->mode.vdisplay;
596
597 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
598 DRM_PLANE_HELPER_NO_SCALING,
599 DRM_PLANE_HELPER_NO_SCALING,
600 true, true);
601 if (ret < 0)
602 return ret;
603
604 if (!state->visible) {
605 *format = NULL;
606 return 0;
583 } 607 }
584 608
585 *format = rcar_du_format_info(state->fb->format->format); 609 *format = rcar_du_format_info(state->fb->format->format);
@@ -607,7 +631,7 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
607 struct rcar_du_plane_state *old_rstate; 631 struct rcar_du_plane_state *old_rstate;
608 struct rcar_du_plane_state *new_rstate; 632 struct rcar_du_plane_state *new_rstate;
609 633
610 if (!plane->state->crtc) 634 if (!plane->state->visible)
611 return; 635 return;
612 636
613 rcar_du_plane_setup(rplane); 637 rcar_du_plane_setup(rplane);
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)
55 struct rcar_du_plane_state state = { 55 struct rcar_du_plane_state state = {
56 .state = { 56 .state = {
57 .crtc = &crtc->crtc, 57 .crtc = &crtc->crtc,
58 .crtc_x = 0, 58 .dst.x1 = 0,
59 .crtc_y = 0, 59 .dst.y1 = 0,
60 .crtc_w = mode->hdisplay, 60 .dst.x2 = mode->hdisplay,
61 .crtc_h = mode->vdisplay, 61 .dst.y2 = mode->vdisplay,
62 .src_x = 0, 62 .src.x1 = 0,
63 .src_y = 0, 63 .src.y1 = 0,
64 .src_w = mode->hdisplay << 16, 64 .src.x2 = mode->hdisplay << 16,
65 .src_h = mode->vdisplay << 16, 65 .src.y2 = mode->vdisplay << 16,
66 .zpos = 0, 66 .zpos = 0,
67 }, 67 },
68 .format = rcar_du_format_info(DRM_FORMAT_ARGB8888), 68 .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)
178 }; 178 };
179 unsigned int i; 179 unsigned int i;
180 180
181 cfg.src.left = state->state.src_x >> 16; 181 cfg.src.left = state->state.src.x1 >> 16;
182 cfg.src.top = state->state.src_y >> 16; 182 cfg.src.top = state->state.src.y1 >> 16;
183 cfg.src.width = state->state.src_w >> 16; 183 cfg.src.width = drm_rect_width(&state->state.src) >> 16;
184 cfg.src.height = state->state.src_h >> 16; 184 cfg.src.height = drm_rect_height(&state->state.src) >> 16;
185 185
186 cfg.dst.left = state->state.crtc_x; 186 cfg.dst.left = state->state.dst.x1;
187 cfg.dst.top = state->state.crtc_y; 187 cfg.dst.top = state->state.dst.y1;
188 cfg.dst.width = state->state.crtc_w; 188 cfg.dst.width = drm_rect_width(&state->state.dst);
189 cfg.dst.height = state->state.crtc_h; 189 cfg.dst.height = drm_rect_height(&state->state.dst);
190 190
191 for (i = 0; i < state->format->planes; ++i) 191 for (i = 0; i < state->format->planes; ++i)
192 cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl) 192 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,
212 unsigned int i; 212 unsigned int i;
213 int ret; 213 int ret;
214 214
215 if (!state->fb) 215 /*
216 * There's no need to prepare (and unprepare) the framebuffer when the
217 * plane is not visible, as it will not be displayed.
218 */
219 if (!state->visible)
216 return 0; 220 return 0;
217 221
218 for (i = 0; i < rstate->format->planes; ++i) { 222 for (i = 0; i < rstate->format->planes; ++i) {
@@ -253,7 +257,7 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane,
253 struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp; 257 struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
254 unsigned int i; 258 unsigned int i;
255 259
256 if (!state->fb) 260 if (!state->visible)
257 return; 261 return;
258 262
259 for (i = 0; i < rstate->format->planes; ++i) { 263 for (i = 0; i < rstate->format->planes; ++i) {
@@ -278,7 +282,7 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
278 struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane); 282 struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
279 struct rcar_du_crtc *crtc = to_rcar_crtc(old_state->crtc); 283 struct rcar_du_crtc *crtc = to_rcar_crtc(old_state->crtc);
280 284
281 if (plane->state->crtc) 285 if (plane->state->visible)
282 rcar_du_vsp_plane_setup(rplane); 286 rcar_du_vsp_plane_setup(rplane);
283 else 287 else
284 vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe, 288 vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe,