summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/rcar-du
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/rcar-du')
-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)
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
unsigned int j;
- if (plane->plane.state->crtc != &rcrtc->crtc)
+ if (plane->plane.state->crtc != &rcrtc->crtc ||
+ !plane->plane.state->visible)
continue;
/* 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,
static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state)
{
- unsigned int src_x = state->state.src_x >> 16;
- unsigned int src_y = state->state.src_y >> 16;
+ unsigned int src_x = state->state.src.x1 >> 16;
+ unsigned int src_y = state->state.src.y1 >> 16;
unsigned int index = state->hwindex;
unsigned int pitch;
bool interlaced;
@@ -357,7 +357,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) >> 16;
dma[0] = 0;
dma[1] = 0;
}
@@ -521,6 +521,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state)
{
struct rcar_du_device *rcdu = rgrp->dev;
+ const struct drm_rect *dst = &state->state.dst;
if (rcdu->info->gen < 3)
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,
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 */
@@ -570,16 +571,39 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
const struct rcar_du_format_info **format)
{
struct drm_device *dev = plane->dev;
+ struct drm_crtc_state *crtc_state;
+ struct drm_rect clip;
+ int ret;
- if (!state->fb || !state->crtc) {
+ if (!state->crtc) {
+ /*
+ * The visible field is not reset by the DRM core but only
+ * updated by drm_plane_helper_check_state(), set it manually.
+ */
+ state->visible = false;
*format = NULL;
return 0;
}
- if (state->src_w >> 16 != state->crtc_w ||
- state->src_h >> 16 != state->crtc_h) {
- dev_dbg(dev->dev, "%s: scaling not supported\n", __func__);
- return -EINVAL;
+ crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ clip.x1 = 0;
+ clip.y1 = 0;
+ clip.x2 = crtc_state->mode.hdisplay;
+ clip.y2 = crtc_state->mode.vdisplay;
+
+ ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true);
+ if (ret < 0)
+ return ret;
+
+ if (!state->visible) {
+ *format = NULL;
+ return 0;
}
*format = rcar_du_format_info(state->fb->format->format);
@@ -607,7 +631,7 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
struct rcar_du_plane_state *old_rstate;
struct rcar_du_plane_state *new_rstate;
- if (!plane->state->crtc)
+ if (!plane->state->visible)
return;
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)
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,