drm/rockchip: vop: support afbdc
authorMark Yao <mark.yao@rock-chips.com>
Fri, 12 Aug 2016 10:10:58 +0000 (18:10 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 13 Oct 2016 03:28:52 +0000 (11:28 +0800)
Change-Id: If22924904f6d0362ba2abef0ddfe715684aca58a
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.h
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
include/uapi/drm/rockchip_drm.h

index 0b602a6452e3ffbe56ee31e645cd7651890b6bc3..821e0d1d0d0a7ffccd15ca019d893828dacf6fb2 100644 (file)
@@ -787,6 +787,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
        if (ret)
                goto err_vblank_cleanup;
 
+       drm_dev->mode_config.allow_fb_modifiers = true;
+
        return 0;
 err_vblank_cleanup:
        drm_vblank_cleanup(drm_dev);
index d3e6c5ae0214f338fad113fddc2a378bd7d071fc..e7499f8f990089f3739d432c439c181714ceb64d 100644 (file)
@@ -63,6 +63,12 @@ struct rockchip_atomic_commit {
 
 struct rockchip_crtc_state {
        struct drm_crtc_state base;
+       int afbdc_win_format;
+       int afbdc_win_width;
+       int afbdc_win_height;
+       int afbdc_win_ptr;
+       int afbdc_win_id;
+       int afbdc_en;
        int dsp_layer_sel;
        int output_type;
        int output_mode;
index 011e7a4ade8076f1641bc36f7860631370320a28..b5e8126fd7199f37ea85baa08e6e042d90f6fe62 100644 (file)
 #define VOP_WIN_SUPPORT(vop, win, name) \
                VOP_REG_SUPPORT(vop, win->phy->name)
 
-#define VOP_CTRL_SUPPORT(vop, win, name) \
+#define VOP_CTRL_SUPPORT(vop, name) \
                VOP_REG_SUPPORT(vop, vop->data->ctrl->name)
 
-#define VOP_INTR_SUPPORT(vop, win, name) \
+#define VOP_INTR_SUPPORT(vop, name) \
                VOP_REG_SUPPORT(vop, vop->data->intr->name)
 
 #define __REG_SET(x, off, mask, shift, v, write_mask, relaxed) \
@@ -162,6 +162,7 @@ struct vop {
        struct drm_device *drm_dev;
        struct drm_property *plane_zpos_prop;
        struct drm_property *plane_feature_prop;
+       struct drm_property *feature_prop;
        bool is_iommu_enabled;
        bool is_iommu_needed;
        bool is_enabled;
@@ -732,6 +733,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
                VOP_WIN_SET(vop, win, enable, 0);
                spin_unlock(&vop->reg_lock);
        }
+       VOP_CTRL_SET(vop, afbdc_en, 0);
        vop_cfg_done(vop);
 
        drm_crtc_vblank_off(crtc);
@@ -1328,6 +1330,78 @@ static int vop_zpos_cmp(const void *a, const void *b)
        return pa->zpos - pb->zpos;
 }
 
+static int vop_afbdc_atomic_check(struct drm_crtc *crtc,
+                                 struct drm_crtc_state *crtc_state)
+{
+       struct vop *vop = to_vop(crtc);
+       const struct vop_data *vop_data = vop->data;
+       struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+       struct drm_atomic_state *state = crtc_state->state;
+       struct drm_plane *plane;
+       struct drm_plane_state *pstate;
+       struct vop_plane_state *plane_state;
+       struct vop_win *win;
+       int afbdc_format;
+       int i;
+
+       s->afbdc_en = 0;
+
+       for_each_plane_in_state(state, plane, pstate, i) {
+               struct drm_framebuffer *fb = pstate->fb;
+               struct drm_rect *src;
+
+               win = to_vop_win(plane);
+               plane_state = to_vop_plane_state(pstate);
+
+               if (pstate->crtc != crtc || !fb)
+                       continue;
+
+               if (fb->modifier[0] != DRM_FORMAT_MOD_ARM_AFBC)
+                       continue;
+
+               if (!(vop_data->feature & VOP_FEATURE_AFBDC)) {
+                       DRM_ERROR("not support afbdc\n");
+                       return -EINVAL;
+               }
+
+               switch (plane_state->format) {
+               case VOP_FMT_ARGB8888:
+                       afbdc_format = AFBDC_FMT_U8U8U8U8;
+                       break;
+               case VOP_FMT_RGB888:
+                       afbdc_format = AFBDC_FMT_U8U8U8;
+                       break;
+               case VOP_FMT_RGB565:
+                       afbdc_format = AFBDC_FMT_RGB565;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               if (s->afbdc_en) {
+                       DRM_ERROR("vop only support one afbc layer\n");
+                       return -EINVAL;
+               }
+
+               src = &plane_state->src;
+               if (src->x1 || src->y1 || fb->offsets[0]) {
+                       DRM_ERROR("win[%d] afbdc not support offset display\n",
+                                 win->win_id);
+                       DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n",
+                                 src->x1, src->y1, fb->offsets[0]);
+                       return -EINVAL;
+               }
+               s->afbdc_win_format = afbdc_format;
+               s->afbdc_win_width = pstate->fb->width - 1;
+               s->afbdc_win_height = (drm_rect_height(src) >> 16) - 1;
+               s->afbdc_win_id = win->win_id;
+               s->afbdc_win_ptr = plane_state->yrgb_mst;
+               s->afbdc_en = 1;
+       }
+
+       return 0;
+}
+
 static int vop_crtc_atomic_check(struct drm_crtc *crtc,
                                 struct drm_crtc_state *crtc_state)
 {
@@ -1342,6 +1416,10 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc,
        int dsp_layer_sel = 0;
        int i, j, cnt = 0, ret = 0;
 
+       ret = vop_afbdc_atomic_check(crtc, crtc_state);
+       if (ret)
+               return ret;
+
        ret = vop_csc_atomic_check(crtc, crtc_state);
        if (ret)
                return ret;
@@ -1412,6 +1490,19 @@ static void vop_cfg_update(struct drm_crtc *crtc,
 
        spin_lock(&vop->reg_lock);
 
+       if (s->afbdc_en) {
+               uint32_t pic_size;
+
+               VOP_CTRL_SET(vop, afbdc_format, s->afbdc_win_format | 1 << 4);
+               VOP_CTRL_SET(vop, afbdc_hreg_block_split, 0);
+               VOP_CTRL_SET(vop, afbdc_sel, s->afbdc_win_id);
+               VOP_CTRL_SET(vop, afbdc_hdr_ptr, s->afbdc_win_ptr);
+               pic_size = (s->afbdc_win_width & 0xffff);
+               pic_size |= s->afbdc_win_height << 16;
+               VOP_CTRL_SET(vop, afbdc_pic_size, pic_size);
+       }
+
+       VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
        VOP_CTRL_SET(vop, dsp_layer_sel, s->dsp_layer_sel);
        vop_cfg_done(vop);
 
@@ -1634,6 +1725,7 @@ static int vop_create_crtc(struct vop *vop)
        struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
        struct drm_crtc *crtc = &vop->crtc;
        struct device_node *port;
+       uint64_t feature = 0;
        int ret;
        int i;
 
@@ -1697,6 +1789,11 @@ static int vop_create_crtc(struct vop *vop)
        crtc->port = port;
        rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
 
+       if (VOP_CTRL_SUPPORT(vop, afbdc_en))
+               feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC);
+       drm_object_attach_property(&crtc->base, vop->feature_prop,
+                                  feature);
+
        return 0;
 
 err_cleanup_crtc:
@@ -1749,6 +1846,9 @@ static int vop_win_init(struct vop *vop)
                { ROCKCHIP_DRM_PLANE_FEATURE_SCALE, "scale" },
                { ROCKCHIP_DRM_PLANE_FEATURE_ALPHA, "alpha" },
        };
+       static const struct drm_prop_enum_list crtc_props[] = {
+               { ROCKCHIP_DRM_CRTC_FEATURE_AFBDC, "afbdc" },
+       };
 
        for (i = 0; i < vop_data->win_size; i++) {
                struct vop_win *vop_win = &vop->win[num_wins];
@@ -1805,6 +1905,15 @@ static int vop_win_init(struct vop *vop)
                return -EINVAL;
        }
 
+       vop->feature_prop = drm_property_create_bitmask(vop->drm_dev,
+                               DRM_MODE_PROP_IMMUTABLE, "FEATURE",
+                               props, ARRAY_SIZE(crtc_props),
+                               BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC));
+       if (!vop->feature_prop) {
+               DRM_ERROR("failed to create vop feature property\n");
+               return -EINVAL;
+       }
+
        return 0;
 }
 
index ce36bea4beb7c2e45d23f915d9aeba0861e35636..349338ed01cd8cb5016b732de2708d021f6097b6 100644 (file)
 #define VOP_MAJOR(version)     ((version) >> 8)
 #define VOP_MINOR(version)     ((version) & 0xff)
 
+#define AFBDC_FMT_RGB565       0x0
+#define AFBDC_FMT_U8U8U8U8     0x5
+#define AFBDC_FMT_U8U8U8       0x4
+
 enum vop_csc_format {
        CSC_BT601,
        CSC_BT709,
@@ -113,6 +117,15 @@ struct vop_ctrl {
        struct vop_reg ymirror;
        struct vop_reg dsp_background;
 
+       /* AFBDC */
+       struct vop_reg afbdc_en;
+       struct vop_reg afbdc_sel;
+       struct vop_reg afbdc_format;
+       struct vop_reg afbdc_hreg_block_split;
+       struct vop_reg afbdc_pic_size;
+       struct vop_reg afbdc_hdr_ptr;
+       struct vop_reg afbdc_rstn;
+
        struct vop_reg cfg_done;
 };
 
@@ -227,7 +240,8 @@ struct vop_win_data {
        unsigned int area_size;
 };
 
-#define VOP_FEATURE_OUTPUT_10BIT BIT(0)
+#define VOP_FEATURE_OUTPUT_10BIT       BIT(0)
+#define VOP_FEATURE_AFBDC              BIT(1)
 
 struct vop_data {
        const struct vop_reg_data *init_table;
index adfac19db8cc5582118348fb921a38b38ec6820f..85fc43d45e0730f53c1ae1ac5575ff3975adf055 100644 (file)
@@ -201,6 +201,14 @@ static const struct vop_ctrl rk3288_ctrl_data = {
        .dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
        .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
 
+       .afbdc_rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
+       .afbdc_en = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
+       .afbdc_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
+       .afbdc_format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
+       .afbdc_hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
+       .afbdc_hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
+       .afbdc_pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
+
        .xmirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 22),
        .ymirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 23),
 
@@ -473,7 +481,7 @@ static const struct vop_win_data rk3399_vop_win_data[] = {
 
 static const struct vop_data rk3399_vop_big = {
        .version = VOP_VERSION(3, 5),
-       .feature = VOP_FEATURE_OUTPUT_10BIT,
+       .feature = VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_AFBDC,
        .intr = &rk3366_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3399_vop_win_data,
index 133d423866e21b4fc7f3e882ed5fb261a7b1a183..fbc3f493cb20fa9d0838119bef8b95d5b57fd7d3 100644 (file)
@@ -104,6 +104,10 @@ enum rockchip_plane_feture {
        ROCKCHIP_DRM_PLANE_FEATURE_MAX,
 };
 
+enum rockchip_crtc_feture {
+       ROCKCHIP_DRM_CRTC_FEATURE_AFBDC,
+};
+
 #define DRM_ROCKCHIP_GEM_CREATE                0x00
 #define DRM_ROCKCHIP_GEM_MAP_OFFSET    0x01
 #define DRM_ROCKCHIP_GEM_CPU_ACQUIRE   0x02