From: Mark Yao Date: Fri, 12 Aug 2016 10:10:58 +0000 (+0800) Subject: drm/rockchip: vop: support afbdc X-Git-Tag: firefly_0821_release~1418 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4afab6ba7bac61da38485cb992f4f5fb3dab6d9a;p=firefly-linux-kernel-4.4.55.git drm/rockchip: vop: support afbdc Change-Id: If22924904f6d0362ba2abef0ddfe715684aca58a Signed-off-by: Mark Yao --- diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 0b602a6452e3..821e0d1d0d0a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -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); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index d3e6c5ae0214..e7499f8f9900 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -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; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 011e7a4ade80..b5e8126fd719 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -47,10 +47,10 @@ #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; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index ce36bea4beb7..349338ed01cd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -23,6 +23,10 @@ #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; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index adfac19db8cc..85fc43d45e07 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -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, diff --git a/include/uapi/drm/rockchip_drm.h b/include/uapi/drm/rockchip_drm.h index 133d423866e2..fbc3f493cb20 100644 --- a/include/uapi/drm/rockchip_drm.h +++ b/include/uapi/drm/rockchip_drm.h @@ -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