drm/rockchip: vop: support afbdc

Change-Id: If22924904f6d0362ba2abef0ddfe715684aca58a
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
Mark Yao
2016-08-12 18:10:58 +08:00
committed by Huang, Tao
parent ccc954ee9f
commit 4afab6ba7b
6 changed files with 147 additions and 4 deletions

View 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);

View 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;

View File

@@ -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;
}

View File

@@ -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;

View 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,

View 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