Commit 677e8bbc authored by Daniele Castagna's avatar Daniele Castagna Committed by Heiko Stuebner

drm/rockchip: Add reflection properties

Add the KMS plane rotation property to the DRM rockchip driver,
for SoCs RK3328, RK3368 and RK3399.

RK3288 only supports rotation at the display level (i.e. CRTC),
but for now we are only interested in plane rotation.

This commit only adds support for the value of reflect-y
and reflect-x (i.e. mirroring).

Note that y-mirroring is not compatible with YUV.

The following modetest commands would test this feature,
where 30 is the plane ID, and 49 = rotate_0 + relect_y + reflect_x.

X mirror:
modetest -s 43@33:1920x1080@XR24 -w 30:rotation:17

Y mirror:
modetest -s 43@33:1920x1080@XR24 -w 30:rotation:33

XY mirror:
modetest -s 43@33:1920x1080@XR24 -w 30:rotation:49
Signed-off-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Signed-off-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20190109185639.5093-4-ezequiel@collabora.com
parent fbb1c738
...@@ -89,6 +89,9 @@ ...@@ -89,6 +89,9 @@
#define VOP_WIN_GET(vop, win, name) \ #define VOP_WIN_GET(vop, win, name) \
vop_read_reg(vop, win->offset, win->phy->name) vop_read_reg(vop, win->offset, win->phy->name)
#define VOP_WIN_HAS_REG(win, name) \
(!!(win->phy->name.mask))
#define VOP_WIN_GET_YRGBADDR(vop, win) \ #define VOP_WIN_GET_YRGBADDR(vop, win) \
vop_readl(vop, win->base + win->phy->yrgb_mst.offset) vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
...@@ -712,6 +715,11 @@ static int vop_plane_atomic_check(struct drm_plane *plane, ...@@ -712,6 +715,11 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
return -EINVAL; return -EINVAL;
} }
if (fb->format->is_yuv && state->rotation & DRM_MODE_REFLECT_Y) {
DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
return -EINVAL;
}
return 0; return 0;
} }
...@@ -790,6 +798,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane, ...@@ -790,6 +798,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
offset += (src->y1 >> 16) * fb->pitches[0]; offset += (src->y1 >> 16) * fb->pitches[0];
dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
/*
* For y-mirroring we need to move address
* to the beginning of the last line.
*/
if (state->rotation & DRM_MODE_REFLECT_Y)
dma_addr += (actual_h - 1) * fb->pitches[0];
format = vop_convert_format(fb->format->format); format = vop_convert_format(fb->format->format);
spin_lock(&vop->reg_lock); spin_lock(&vop->reg_lock);
...@@ -798,6 +813,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane, ...@@ -798,6 +813,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv);
VOP_WIN_SET(vop, win, y_mir_en,
(state->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0);
VOP_WIN_SET(vop, win, x_mir_en,
(state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);
if (is_yuv) { if (is_yuv) {
int hsub = drm_format_horz_chroma_subsampling(fb->format->format); int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
...@@ -1385,6 +1404,18 @@ static irqreturn_t vop_isr(int irq, void *data) ...@@ -1385,6 +1404,18 @@ static irqreturn_t vop_isr(int irq, void *data)
return ret; return ret;
} }
static void vop_plane_add_properties(struct drm_plane *plane,
const struct vop_win_data *win_data)
{
unsigned int flags = 0;
flags |= VOP_WIN_HAS_REG(win_data, x_mir_en) ? DRM_MODE_REFLECT_X : 0;
flags |= VOP_WIN_HAS_REG(win_data, y_mir_en) ? DRM_MODE_REFLECT_Y : 0;
if (flags)
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 | flags);
}
static int vop_create_crtc(struct vop *vop) static int vop_create_crtc(struct vop *vop)
{ {
const struct vop_data *vop_data = vop->data; const struct vop_data *vop_data = vop->data;
...@@ -1422,6 +1453,7 @@ static int vop_create_crtc(struct vop *vop) ...@@ -1422,6 +1453,7 @@ static int vop_create_crtc(struct vop *vop)
plane = &vop_win->base; plane = &vop_win->base;
drm_plane_helper_add(plane, &plane_helper_funcs); drm_plane_helper_add(plane, &plane_helper_funcs);
vop_plane_add_properties(plane, win_data);
if (plane->type == DRM_PLANE_TYPE_PRIMARY) if (plane->type == DRM_PLANE_TYPE_PRIMARY)
primary = plane; primary = plane;
else if (plane->type == DRM_PLANE_TYPE_CURSOR) else if (plane->type == DRM_PLANE_TYPE_CURSOR)
...@@ -1459,6 +1491,7 @@ static int vop_create_crtc(struct vop *vop) ...@@ -1459,6 +1491,7 @@ static int vop_create_crtc(struct vop *vop)
goto err_cleanup_crtc; goto err_cleanup_crtc;
} }
drm_plane_helper_add(&vop_win->base, &plane_helper_funcs); drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
vop_plane_add_properties(&vop_win->base, win_data);
} }
port = of_get_child_by_name(dev->of_node, "port"); port = of_get_child_by_name(dev->of_node, "port");
......
...@@ -146,6 +146,8 @@ struct vop_win_phy { ...@@ -146,6 +146,8 @@ struct vop_win_phy {
struct vop_reg uv_mst; struct vop_reg uv_mst;
struct vop_reg yrgb_vir; struct vop_reg yrgb_vir;
struct vop_reg uv_vir; struct vop_reg uv_vir;
struct vop_reg y_mir_en;
struct vop_reg x_mir_en;
struct vop_reg dst_alpha_ctl; struct vop_reg dst_alpha_ctl;
struct vop_reg src_alpha_ctl; struct vop_reg src_alpha_ctl;
......
...@@ -557,6 +557,8 @@ static const struct vop_win_phy rk3368_win01_data = { ...@@ -557,6 +557,8 @@ static const struct vop_win_phy rk3368_win01_data = {
.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
.x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
.y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
.act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0), .act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
.dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0), .dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
.dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0), .dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
...@@ -576,6 +578,7 @@ static const struct vop_win_phy rk3368_win23_data = { ...@@ -576,6 +578,7 @@ static const struct vop_win_phy rk3368_win23_data = {
.enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
.format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
.rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
.y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
.dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
.dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
.yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment