mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
drm/rockchip: vop: support afbdc
Change-Id: If22924904f6d0362ba2abef0ddfe715684aca58a Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user