[PATCH 3/3] drm: rcar-du: Clip planes to screen boundaries
Laurent Pinchart
laurent.pinchart+renesas at ideasonboard.com
Tue Aug 15 23:03:38 UTC 2017
Unlike the KMS API, the hardware doesn't support planes exceeding the
screen boundaries. Clip plane coordinates to support the use case.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 66 +++++++++++++++++++++++++--------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 4 ++
drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 21 +++++++----
3 files changed, 67 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 714e02960635..7944790bac25 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -19,6 +19,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_rect.h>
#include "rcar_du_drv.h"
#include "rcar_du_group.h"
@@ -329,11 +330,39 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
data);
}
+void rcar_du_plane_clip(const struct drm_plane_state *state,
+ struct drm_rect *src, struct drm_rect *dst)
+{
+ const struct drm_display_mode *mode;
+
+ /*
+ * The hardware requires all planes to be fully contained in the output
+ * rectangle. Crop the destination rectangle to fit in the CRTC.
+ */
+ mode = &state->crtc->state->adjusted_mode;
+
+ dst->x1 = max(0, state->crtc_x);
+ dst->y1 = max(0, state->crtc_y);
+ dst->x2 = min_t(unsigned int, mode->hdisplay,
+ state->crtc_x + state->crtc_w);
+ dst->y2 = min_t(unsigned int, mode->vdisplay,
+ state->crtc_y + state->crtc_h);
+
+ /*
+ * Offset the left and top source coordinates by the same displacement
+ * we have applied to the destination rectangle. Copy the width and
+ * height as the hardware can't scale.
+ */
+ src->x1 = (state->src_x >> 16) + (dst->x1 - state->crtc_x);
+ src->y1 = (state->src_y >> 16) + (dst->y1 - state->crtc_y);
+ src->x2 = src->x1 + (dst->x2 - dst->x1);
+ src->y2 = src->y1 + (dst->y2 - dst->y1);
+}
+
static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
- const struct rcar_du_plane_state *state)
+ const struct rcar_du_plane_state *state,
+ const struct drm_rect *src)
{
- unsigned int src_x = state->state.src_x >> 16;
- unsigned int src_y = state->state.src_y >> 16;
unsigned int index = state->hwindex;
unsigned int pitch;
bool interlaced;
@@ -357,7 +386,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
dma[i] = gem->paddr + fb->offsets[i];
}
} else {
- pitch = state->state.src_w >> 16;
+ pitch = drm_rect_width(&state->state.src);
dma[0] = 0;
dma[1] = 0;
}
@@ -383,8 +412,8 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
* require a halved Y position value, in both progressive and interlaced
* modes.
*/
- rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
- rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
+ rcar_du_plane_write(rgrp, index, PnSPXR, src->x1);
+ rcar_du_plane_write(rgrp, index, PnSPYR, src->y1 *
(!interlaced && state->format->bpp == 32 ? 2 : 1));
rcar_du_plane_write(rgrp, index, PnDSA0R, dma[0]);
@@ -394,8 +423,8 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
rcar_du_plane_write(rgrp, index, PnMWR, pitch);
- rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
- rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
+ rcar_du_plane_write(rgrp, index, PnSPXR, src->x1);
+ rcar_du_plane_write(rgrp, index, PnSPYR, src->y1 *
(state->format->bpp == 16 ? 2 : 1) / 2);
rcar_du_plane_write(rgrp, index, PnDSA0R, dma[1]);
@@ -518,7 +547,8 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
unsigned int index,
- const struct rcar_du_plane_state *state)
+ const struct rcar_du_plane_state *state,
+ const struct drm_rect *dst)
{
struct rcar_du_device *rcdu = rgrp->dev;
@@ -528,10 +558,10 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
rcar_du_plane_setup_format_gen3(rgrp, index, state);
/* Destination position and size */
- rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
- rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
- rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
- rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
+ rcar_du_plane_write(rgrp, index, PnDSXR, drm_rect_width(dst));
+ rcar_du_plane_write(rgrp, index, PnDSYR, drm_rect_height(dst));
+ rcar_du_plane_write(rgrp, index, PnDPXR, dst->x1);
+ rcar_du_plane_write(rgrp, index, PnDPYR, dst->y1);
if (rcdu->info->gen < 3) {
/* Wrap-around and blinking, disabled */
@@ -546,14 +576,18 @@ void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state)
{
struct rcar_du_device *rcdu = rgrp->dev;
+ struct drm_rect src;
+ struct drm_rect dst;
+
+ rcar_du_plane_clip(&state->state, &src, &dst);
- rcar_du_plane_setup_format(rgrp, state->hwindex, state);
+ rcar_du_plane_setup_format(rgrp, state->hwindex, state, &dst);
if (state->format->planes == 2)
rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
- state);
+ state, &dst);
if (rcdu->info->gen < 3)
- rcar_du_plane_setup_scanout(rgrp, state);
+ rcar_du_plane_setup_scanout(rgrp, state, &src);
if (state->source == RCAR_DU_PLANE_VSPD1) {
unsigned int vspd1_sink = rgrp->index ? 2 : 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 890321b4665d..ec52a2af7cd4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -17,6 +17,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
+struct drm_rect;
struct rcar_du_format_info;
struct rcar_du_group;
@@ -79,6 +80,9 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
int rcar_du_planes_init(struct rcar_du_group *rgrp);
+void rcar_du_plane_clip(const struct drm_plane_state *state,
+ struct drm_rect *src, struct drm_rect *dst);
+
void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index dd66dcb8da23..e62a8d7ee0c5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -18,6 +18,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_rect.h>
#include <linux/bitops.h>
#include <linux/dma-mapping.h>
@@ -176,17 +177,21 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
.alpha = state->alpha,
.zpos = state->state.zpos,
};
+ struct drm_rect src;
+ struct drm_rect dst;
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;
+ rcar_du_plane_clip(&state->state, &src, &dst);
- 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.src.left = src.x1;
+ cfg.src.top = src.y1;
+ cfg.src.width = drm_rect_width(&src);
+ cfg.src.height = drm_rect_height(&src);
+
+ cfg.dst.left = dst.x1;
+ cfg.dst.top = dst.y1;
+ cfg.dst.width = drm_rect_width(&dst);
+ cfg.dst.height = drm_rect_height(&dst);
for (i = 0; i < state->format->planes; ++i)
cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl)
--
Regards,
Laurent Pinchart
More information about the dri-devel
mailing list