Commit 87eb7a24 authored by Ezequiel Garcia's avatar Ezequiel Garcia

AFBC WIP

Signed-off-by: Ezequiel Garcia's avatarEzequiel Garcia <ezequiel@collabora.com>
parent 317144be
......@@ -521,9 +521,9 @@
status = "okay";
};
&vopl {
status = "okay";
};
//&vopl {
// status = "okay";
//};
&vopl_mmu {
status = "okay";
......
......@@ -41,6 +41,27 @@ static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
.dirty = rockchip_drm_fb_dirty,
};
static int
rockchip_verify_afbc_mod(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
if (mode_cmd->modifier[0] &
~DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP)) {
DRM_DEV_ERROR(dev->dev,
"Unsupported format modifier 0%x\n",
mode_cmd->modifier[0]);
return -EINVAL;
}
if (mode_cmd->width > 2560) {
DRM_DEV_ERROR(dev->dev,
"Unsupported width %d\n", mode_cmd->width);
return -EINVAL;
}
return 0;
}
static struct drm_framebuffer *
rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **obj, unsigned int num_planes)
......@@ -49,6 +70,12 @@ rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cm
int ret;
int i;
if (mode_cmd->modifier[0]) {
ret = rockchip_verify_afbc_mod(dev, mode_cmd);
if (ret)
return ERR_PTR(ret);
}
fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if (!fb)
return ERR_PTR(-ENOMEM);
......
......@@ -54,6 +54,10 @@
vop_reg_set(vop, &win->phy->scl->ext->name, \
win->base, ~0, v, #name)
#define VOP_AFBC_SET(x, name, v) \
if (vop->data->afbc) \
vop_reg_set(vop, &vop->data->afbc->name, 0, ~0, v, #name)
#define VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, name, v) \
do { \
if (win_yuv2yuv && win_yuv2yuv->name.mask) \
......@@ -131,6 +135,8 @@ struct vop {
struct drm_device *drm_dev;
bool is_enabled;
struct vop_win *afbc_win;
struct completion dsp_hold_completion;
/* protected by dev->event_lock */
......@@ -253,6 +259,30 @@ static bool has_rb_swapped(uint32_t format)
}
}
#define AFBC_FMT_RGB565 0x0
#define AFBC_FMT_U8U8U8U8 0x5
#define AFBC_FMT_U8U8U8 0x4
static int vop_convert_afbc_format(uint32_t format)
{
switch (format) {
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
return AFBC_FMT_U8U8U8U8;
case DRM_FORMAT_RGB888:
case DRM_FORMAT_BGR888:
return AFBC_FMT_U8U8U8;
case DRM_FORMAT_RGB565:
case DRM_FORMAT_BGR565:
return AFBC_FMT_RGB565;
default:
DRM_ERROR("unsupported afbc format[%08x]\n", format);
return -EINVAL;
}
}
static enum vop_data_format vop_convert_format(uint32_t format)
{
switch (format) {
......@@ -590,6 +620,11 @@ static int vop_enable(struct drm_crtc *crtc)
}
spin_unlock(&vop->reg_lock);
if (vop->data->afbc) {
VOP_AFBC_SET(vop, enable, 0);
vop->afbc_win = NULL;
}
vop_cfg_done(vop);
/*
......@@ -720,6 +755,32 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
if (fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP)) {
struct vop *vop = to_vop(crtc);
if (!vop->data->afbc) {
DRM_ERROR("VOP does not support AFBC\n");
return -EINVAL;
}
ret = vop_convert_afbc_format(fb->format->format);
if (ret < 0)
return ret;
if (state->src.x1 || state->src.y1) {
DRM_ERROR("AFBC does not support offset display\n");
DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n",
state->src.x1, state->src.y1, fb->offsets[0]);
return -EINVAL;
}
if (state->rotation && state->rotation != DRM_MODE_ROTATE_0) {
DRM_ERROR("AFBC does not support rotation\n");
DRM_ERROR("rotation=%d\n", state->rotation);
return -EINVAL;
}
}
return 0;
}
......@@ -735,6 +796,8 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
spin_lock(&vop->reg_lock);
if (vop->afbc_win == vop_win)
vop->afbc_win = NULL;
VOP_WIN_SET(vop, win, enable, 0);
spin_unlock(&vop->reg_lock);
......@@ -775,6 +838,9 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
if (WARN_ON(!vop->is_enabled))
return;
if (vop->afbc_win == vop_win)
vop->afbc_win = NULL;
if (!state->visible) {
vop_plane_atomic_disable(plane, old_state);
return;
......@@ -809,6 +875,20 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
spin_lock(&vop->reg_lock);
if (fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP)) {
int afbc_format = vop_convert_afbc_format(fb->format->format);
VOP_AFBC_SET(vop, format, afbc_format | 1 << 4);
VOP_AFBC_SET(vop, hreg_block_split, 0);
VOP_AFBC_SET(vop, win_sel, win_index);
VOP_AFBC_SET(vop, hdr_ptr, dma_addr);
VOP_AFBC_SET(vop, pic_size, act_info);
vop->afbc_win = vop_win;
pr_info("AFBC on plane %s\n", plane->name);
}
VOP_WIN_SET(vop, win, format, format);
VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
......@@ -1153,6 +1233,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
spin_lock(&vop->reg_lock);
VOP_AFBC_SET(vop, enable, vop->afbc_win ? 0x1 : 0);
vop_cfg_done(vop);
spin_unlock(&vop->reg_lock);
......@@ -1444,7 +1525,8 @@ static int vop_create_crtc(struct vop *vop)
0, &vop_plane_funcs,
win_data->phy->data_formats,
win_data->phy->nformats,
NULL, win_data->type, NULL);
win_data->phy->format_modifiers,
win_data->type, NULL);
if (ret) {
DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
ret);
......@@ -1484,7 +1566,8 @@ static int vop_create_crtc(struct vop *vop)
&vop_plane_funcs,
win_data->phy->data_formats,
win_data->phy->nformats,
NULL, win_data->type, NULL);
win_data->phy->format_modifiers,
win_data->type, NULL);
if (ret) {
DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
ret);
......
......@@ -83,6 +83,16 @@ struct vop_misc {
struct vop_reg global_regdone_en;
};
struct vop_afbc {
struct vop_reg enable;
struct vop_reg win_sel;
struct vop_reg format;
struct vop_reg hreg_block_split;
struct vop_reg pic_size;
struct vop_reg hdr_ptr;
struct vop_reg rstn;
};
struct vop_intr {
const int *intrs;
uint32_t nintrs;
......@@ -134,6 +144,7 @@ struct vop_win_phy {
const struct vop_scl_regs *scl;
const uint32_t *data_formats;
uint32_t nformats;
const uint64_t *format_modifiers;
struct vop_reg enable;
struct vop_reg gate;
......@@ -175,6 +186,7 @@ struct vop_data {
const struct vop_output *output;
const struct vop_win_yuv2yuv_data *win_yuv2yuv;
const struct vop_win_data *win;
const struct vop_afbc *afbc;
unsigned int win_size;
#define VOP_FEATURE_OUTPUT_RGB10 BIT(0)
......
......@@ -38,6 +38,12 @@
#define VOP_REG_MASK_SYNC(off, _mask, _shift) \
_VOP_REG(off, _mask, _shift, true, false)
static const uint64_t format_modifiers_afbc[] = {
DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP),
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static const uint32_t formats_win_full[] = {
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB8888,
......@@ -662,6 +668,7 @@ static const struct vop_win_phy rk3368_win01_data = {
.scl = &rk3288_win_full_scl,
.data_formats = formats_win_full,
.nformats = ARRAY_SIZE(formats_win_full),
.format_modifiers = format_modifiers_afbc,
.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
......@@ -753,6 +760,16 @@ static const struct vop_data rk3366_vop = {
.win_size = ARRAY_SIZE(rk3368_vop_win_data),
};
static const struct vop_afbc rk3399_afbc = {
.rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
.enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
.win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
.format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
.hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
.hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
.pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
};
static const struct vop_output rk3399_output = {
.dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16),
......@@ -803,6 +820,7 @@ static const struct vop_data rk3399_vop_big = {
.modeset = &rk3288_modeset,
.output = &rk3399_output,
.misc = &rk3368_misc,
.afbc = &rk3399_afbc,
.win = rk3368_vop_win_data,
.win_size = ARRAY_SIZE(rk3368_vop_win_data),
.win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
......
......@@ -647,6 +647,9 @@ extern "C" {
*/
#define AFBC_FORMAT_MOD_SC (1ULL << 9)
/* TODO: Define properly */
#define AFBC_FORMAT_MOD_ROCKCHIP (1ULL << 20)
#if defined(__cplusplus)
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment