drm/rockchip: vop: add x/ymirror support
authorMark Yao <mark.yao@rock-chips.com>
Fri, 8 Jul 2016 09:24:36 +0000 (17:24 +0800)
committerMark Yao <mark.yao@rock-chips.com>
Mon, 11 Jul 2016 05:48:07 +0000 (13:48 +0800)
Change-Id: If7d1ef5f3246f467c48895aa2f54957bd59eed18
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c

index 6de51ffda32dd487dead2e342809b2f896e73d69..bee7049ebe1d5d602afc1bb7c63bfee557e52793 100644 (file)
@@ -88,6 +88,9 @@
 #define VOP_WIN_GET_YRGBADDR(vop, win) \
                vop_readl(vop, win->offset + VOP_WIN_NAME(win, yrgb_mst).offset)
 
+#define VOP_WIN_SUPPORT(win, name) \
+               (win->phy->name.mask ? true : false)
+
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
 #define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
@@ -120,6 +123,7 @@ struct vop_win {
        uint32_t nformats;
        struct vop *vop;
 
+       struct drm_property *rotation_prop;
        struct vop_plane_state state;
 };
 
@@ -721,6 +725,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        struct rockchip_gem_object *rk_obj, *rk_uv_obj;
        unsigned long offset;
        dma_addr_t dma_addr;
+       int ymirror, xmirror;
        uint32_t val;
        bool rb_swap;
 
@@ -753,11 +758,19 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
 
        offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
-       offset += (src->y1 >> 16) * fb->pitches[0];
+       if (state->rotation & BIT(DRM_REFLECT_Y))
+               offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
+       else
+               offset += (src->y1 >> 16) * fb->pitches[0];
        vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 
+       ymirror = !!(state->rotation & BIT(DRM_REFLECT_Y));
+       xmirror = !!(state->rotation & BIT(DRM_REFLECT_X));
+
        spin_lock(&vop->reg_lock);
 
+       VOP_WIN_SET(vop, win, xmirror, xmirror);
+       VOP_WIN_SET(vop, win, ymirror, ymirror);
        VOP_WIN_SET(vop, win, format, vop_plane_state->format);
        VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
        VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
@@ -877,6 +890,11 @@ static int vop_atomic_plane_set_property(struct drm_plane *plane,
                return 0;
        }
 
+       if (property == win->rotation_prop) {
+               state->rotation = val;
+               return 0;
+       }
+
        DRM_ERROR("failed to set vop plane property\n");
        return -EINVAL;
 }
@@ -894,6 +912,11 @@ static int vop_atomic_plane_get_property(struct drm_plane *plane,
                return 0;
        }
 
+       if (property == win->rotation_prop) {
+               *val = state->rotation;
+               return 0;
+       }
+
        DRM_ERROR("failed to get vop plane property\n");
        return -EINVAL;
 }
@@ -1332,6 +1355,8 @@ static int vop_plane_init(struct vop *vop, struct vop_win *win,
                          unsigned long possible_crtcs)
 {
        struct drm_plane *share = NULL;
+       unsigned int rotations = 0;
+       struct drm_property *prop;
        int ret;
 
        if (win->parent)
@@ -1347,6 +1372,26 @@ static int vop_plane_init(struct vop *vop, struct vop_win *win,
        drm_plane_helper_add(&win->base, &plane_helper_funcs);
        drm_object_attach_property(&win->base.base,
                                   vop->plane_zpos_prop, win->win_id);
+
+       if (VOP_WIN_SUPPORT(win, xmirror))
+               rotations |= BIT(DRM_REFLECT_X);
+
+       if (VOP_WIN_SUPPORT(win, ymirror))
+               rotations |= BIT(DRM_REFLECT_Y);
+
+       if (rotations) {
+               rotations |= BIT(DRM_ROTATE_0);
+               prop = drm_mode_create_rotation_property(vop->drm_dev,
+                                                        rotations);
+               if (!prop) {
+                       DRM_ERROR("failed to create zpos property\n");
+                       return -EINVAL;
+               }
+               drm_object_attach_property(&win->base.base, prop,
+                                          BIT(DRM_ROTATE_0));
+               win->rotation_prop = prop;
+       }
+
        return 0;
 }
 
index fec8e1d688c55925e1d030d0dfb0d26bb8b26580..7ae3947ef01f772d3edcda2b3cf53383dda6bc0b 100644 (file)
@@ -113,6 +113,8 @@ struct vop_win_phy {
 
        struct vop_reg enable;
        struct vop_reg format;
+       struct vop_reg xmirror;
+       struct vop_reg ymirror;
        struct vop_reg rb_swap;
        struct vop_reg act_info;
        struct vop_reg dsp_info;
index 48ec5706e0cfa8144eb973c60167da6b5ff66df5..187a478ebea4f462313fac91e21116c75ebe6afc 100644 (file)
@@ -293,11 +293,32 @@ static const struct vop_reg_data rk3399_init_reg_table[] = {
        {RK3399_WIN3_CTRL0, 0x00000001},
 };
 
+static const struct vop_win_phy rk3399_win01_data = {
+       .scl = &rk3288_win_full_scl,
+       .data_formats = formats_win_full,
+       .nformats = ARRAY_SIZE(formats_win_full),
+       .enable = VOP_REG(RK3399_WIN0_CTRL0, 0x1, 0),
+       .format = VOP_REG(RK3399_WIN0_CTRL0, 0x7, 1),
+       .xmirror = VOP_REG(RK3399_WIN0_CTRL0, 0x1, 21),
+       .ymirror = VOP_REG(RK3399_WIN0_CTRL0, 0x1, 22),
+       .rb_swap = VOP_REG(RK3399_WIN0_CTRL0, 0x1, 12),
+       .act_info = VOP_REG(RK3399_WIN0_ACT_INFO, 0x1fff1fff, 0),
+       .dsp_info = VOP_REG(RK3399_WIN0_DSP_INFO, 0x0fff0fff, 0),
+       .dsp_st = VOP_REG(RK3399_WIN0_DSP_ST, 0x1fff1fff, 0),
+       .yrgb_mst = VOP_REG(RK3399_WIN0_YRGB_MST, 0xffffffff, 0),
+       .uv_mst = VOP_REG(RK3399_WIN0_CBR_MST, 0xffffffff, 0),
+       .yrgb_vir = VOP_REG(RK3399_WIN0_VIR, 0x3fff, 0),
+       .uv_vir = VOP_REG(RK3399_WIN0_VIR, 0x3fff, 16),
+       .src_alpha_ctl = VOP_REG(RK3399_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
+       .dst_alpha_ctl = VOP_REG(RK3399_WIN0_DST_ALPHA_CTRL, 0xff, 0),
+};
+
 static const struct vop_win_phy rk3399_win23_data = {
        .data_formats = formats_win_lite,
        .nformats = ARRAY_SIZE(formats_win_lite),
        .enable = VOP_REG(RK3399_WIN2_CTRL0, 0x1, 4),
        .format = VOP_REG(RK3399_WIN2_CTRL0, 0x3, 5),
+       .ymirror = VOP_REG(RK3399_WIN2_CTRL1, 0x1, 15),
        .rb_swap = VOP_REG(RK3399_WIN2_CTRL0, 0x1, 20),
        .dsp_info = VOP_REG(RK3399_WIN2_DSP_INFO0, 0x0fff0fff, 0),
        .dsp_st = VOP_REG(RK3399_WIN2_DSP_ST0, 0x1fff1fff, 0),
@@ -344,9 +365,9 @@ static const struct vop_win_phy *rk3399_area_data[] = {
 };
 
 static const struct vop_win_data rk3399_vop_win_data[] = {
-       { .base = 0x00, .phy = &rk3288_win01_data,
+       { .base = 0x00, .phy = &rk3399_win01_data,
          .type = DRM_PLANE_TYPE_PRIMARY },
-       { .base = 0x40, .phy = &rk3288_win01_data,
+       { .base = 0x40, .phy = &rk3399_win01_data,
          .type = DRM_PLANE_TYPE_OVERLAY },
        { .base = 0x00, .phy = &rk3399_win23_data,
          .type = DRM_PLANE_TYPE_OVERLAY,
@@ -372,7 +393,7 @@ static const struct vop_data rk3399_vop_big = {
 };
 
 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
-       { .base = 0x00, .phy = &rk3288_win01_data,
+       { .base = 0x00, .phy = &rk3399_win01_data,
          .type = DRM_PLANE_TYPE_PRIMARY },
        { .phy = NULL },
        { .base = 0x00, .phy = &rk3288_win23_data,