drm/rockchip: vop2: add support cubic lut

Change-Id: Iebf89a10b4bdfe630212b393019e926b6dde0e22
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang
2021-01-28 17:15:37 +08:00
committed by Tao Huang
parent 9906f3cefd
commit f6d1c63b4d
4 changed files with 140 additions and 0 deletions

View File

@@ -601,6 +601,11 @@ struct vop2_video_port_regs {
struct vop_reg bcsh_y2r_en;
struct vop_reg bcsh_out_mode;
struct vop_reg bcsh_en;
/* 3d lut */
struct vop_reg cubic_lut_en;
struct vop_reg cubic_lut_update_en;
struct vop_reg cubic_lut_mst;
};
struct vop2_wb_regs {
@@ -675,6 +680,7 @@ struct vop2_video_port_data {
uint32_t feature;
uint64_t soc_id[VOP2_SOC_VARIANT];
uint16_t gamma_lut_len;
uint16_t cubic_lut_len;
struct vop_rect max_output;
const u8 pre_scan_max_dly[4];
const struct vop_intr *intr;
@@ -747,6 +753,7 @@ struct vop2_ctrl {
struct vop_reg version;
struct vop_reg standby;
struct vop_reg dma_stop;
struct vop_reg lut_dma_en;
struct vop_reg axi_outstanding_max_num;
struct vop_reg axi_max_outstanding_en;
struct vop_reg hdmi_dclk_out_en;

View File

@@ -454,6 +454,21 @@ struct vop2_video_port {
* @gamma_lut: atomic gamma look up table
*/
struct drm_color_lut *gamma_lut;
/**
* @cubic_lut_len: cubic look up table size
*/
u32 cubic_lut_len;
/**
* @cubic_lut_gem_obj: gem obj to store cubic lut
*/
struct rockchip_gem_object *cubic_lut_gem_obj;
/**
* @cubic_lut: cubic look up table
*/
struct drm_color_lut *cubic_lut;
};
struct vop2 {
@@ -2058,6 +2073,60 @@ static int vop2_crtc_atomic_gamma_set(struct drm_crtc *crtc,
return 0;
}
static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct drm_color_lut *lut = vp->cubic_lut;
struct vop2 *vop2 = vp->vop2;
u32 *cubic_lut_kvaddr;
dma_addr_t cubic_lut_mst;
unsigned int i;
if (!vp->cubic_lut_len) {
DRM_ERROR("Video Port%d unsupported 3D lut\n", vp->id);
return -ENODEV;
}
if (!vp->cubic_lut_gem_obj) {
size_t size = (vp->cubic_lut_len + 1) / 2 * 16;
vp->cubic_lut_gem_obj = rockchip_gem_create_object(crtc->dev, size, true, 0);
if (IS_ERR(vp->cubic_lut_gem_obj))
return -ENOMEM;
}
cubic_lut_kvaddr = (u32 *)vp->cubic_lut_gem_obj->kvaddr;
cubic_lut_mst = vp->cubic_lut_gem_obj->dma_addr;
for (i = 0; i < vp->cubic_lut_len / 2; i++) {
*cubic_lut_kvaddr++ = (lut[2 * i].red & 0xfff) +
((lut[2 * i].green & 0xfff) << 12) +
((lut[2 * i].blue & 0xff) << 24);
*cubic_lut_kvaddr++ = ((lut[2 * i].blue & 0xf00) >> 8) +
((lut[2 * i + 1].red & 0xfff) << 4) +
((lut[2 * i + 1].green & 0xfff) << 16) +
((lut[2 * i + 1].blue & 0xf) << 28);
*cubic_lut_kvaddr++ = (lut[2 * i + 1].blue & 0xff0) >> 4;
*cubic_lut_kvaddr++ = 0;
}
if (vp->cubic_lut_len % 2) {
*cubic_lut_kvaddr++ = (lut[2 * i].red & 0xfff) +
((lut[2 * i].green & 0xfff) << 12) +
((lut[2 * i].blue & 0xff) << 24);
*cubic_lut_kvaddr++ = (lut[2 * i].blue & 0xf00) >> 8;
*cubic_lut_kvaddr++ = 0;
*cubic_lut_kvaddr = 0;
}
VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst);
VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 1);
VOP_MODULE_SET(vop2, vp, cubic_lut_en, 1);
VOP_CTRL_SET(vop2, lut_dma_en, 1);
return 0;
}
static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
{
int ret;
@@ -3303,10 +3372,37 @@ static int vop2_gamma_show(struct seq_file *s, void *data)
return 0;
}
static int vop2_cubic_lut_show(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct vop2 *vop2 = node->info_ent->data;
int i, j;
for (i = 0; i < vop2->data->nr_vps; i++) {
struct vop2_video_port *vp = &vop2->vps[i];
if (!vp->cubic_lut_gem_obj || !vp->cubic_lut || !vp->crtc.state->enable) {
DEBUG_PRINT("Video port%d cubic lut disabled\n", vp->id);
continue;
}
DEBUG_PRINT("Video port%d cubic lut:\n", vp->id);
for (j = 0; j < vp->cubic_lut_len; j++) {
DEBUG_PRINT("%04d: 0x%04x 0x%04x 0x%04x\n", j,
vp->cubic_lut[j].red,
vp->cubic_lut[j].green,
vp->cubic_lut[j].blue);
}
DEBUG_PRINT("\n");
}
return 0;
}
#undef DEBUG_PRINT
static struct drm_info_list vop2_debugfs_files[] = {
{ "gamma_lut", vop2_gamma_show, 0, NULL },
{ "cubic_lut", vop2_cubic_lut_show, 0, NULL },
};
static int vop2_crtc_debugfs_init(struct drm_minor *minor, struct drm_crtc *crtc)
@@ -4707,6 +4803,14 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state
vp->gamma_lut = crtc->state->gamma_lut->data;
vop2_crtc_atomic_gamma_set(crtc, crtc->state);
}
if (crtc->state->cubic_lut || vp->cubic_lut) {
if (crtc->state->cubic_lut)
vp->cubic_lut = crtc->state->cubic_lut->data;
vop2_crtc_atomic_cubic_lut_set(crtc, crtc->state);
}
} else {
VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0);
}
spin_lock_irqsave(&vop2->irq_lock, flags);
@@ -5312,6 +5416,25 @@ static int vop2_gamma_init(struct vop2 *vop2)
return 0;
}
static void vop2_cubic_lut_init(struct vop2 *vop2)
{
const struct vop2_data *vop2_data = vop2->data;
const struct vop2_video_port_data *vp_data;
struct vop2_video_port *vp;
struct drm_crtc *crtc;
int i;
for (i = 0; i < vop2_data->nr_vps; i++) {
vp = &vop2->vps[i];
crtc = &vp->crtc;
vp_data = &vop2_data->vp[vp->id];
vp->cubic_lut_len = vp_data->cubic_lut_len;
if (vp->cubic_lut_len)
drm_crtc_enable_cubic_lut(crtc, vp->cubic_lut_len);
}
}
static int vop2_create_crtc(struct vop2 *vop2)
{
const struct vop2_data *vop2_data = vop2->data;
@@ -5672,6 +5795,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
ret = vop2_gamma_init(vop2);
if (ret)
return ret;
vop2_cubic_lut_init(vop2);
vop2_wb_connector_init(vop2);
pm_runtime_enable(&pdev->dev);

View File

@@ -501,6 +501,10 @@ static const struct vop2_video_port_regs rk3568_vop_vp0_regs = {
.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 2),
.bcsh_y2r_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 0),
.bcsh_en = VOP_REG(RK3568_VP0_BCSH_COLOR_BAR, 0x1, 31),
.cubic_lut_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 0),
.cubic_lut_update_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 2),
.cubic_lut_mst = VOP_REG(RK3568_VP0_3D_LUT_MST, 0xffffffff, 0),
};
static const struct vop2_video_port_regs rk3568_vop_vp1_regs = {
@@ -607,6 +611,7 @@ static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
.soc_id = { 0x3568, 0x3566 },
.feature = VOP_FEATURE_OUTPUT_10BIT,
.gamma_lut_len = 1024,
.cubic_lut_len = 729, /* 9x9x9 */
.max_output = { 4096, 2304 },
.pre_scan_max_dly = { 69, 53, 53, 42 },
.intr = &rk3568_vp0_intr,
@@ -1157,6 +1162,7 @@ static const struct vop2_ctrl rk3568_vop_ctrl = {
.ovl_port_mux_cfg_done_imd = VOP_REG(RK3568_OVL_CTRL, 0x1, 28),
.if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28),
.version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16),
.lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0),
.cluster0_src_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
.cluster0_dst_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
.cluster0_src_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),

View File

@@ -1054,6 +1054,7 @@
#define RK3568_VOP2_GLB_CFG_DONE_EN BIT(15)
#define RK3568_VERSION_INFO 0x004
#define RK3568_SYS_AUTO_GATING_CTRL 0x008
#define RK3568_SYS_AXI_LUT_CTRL 0x024
#define RK3568_DSP_IF_EN 0x028
#define RK3568_DSP_IF_CTRL 0x02c
#define RK3568_DSP_IF_POL 0x030
@@ -1087,6 +1088,8 @@
#define RK3568_VP0_DSP_CTRL 0xC00
#define RK3568_VP0_MIPI_CTRL 0xC04
#define RK3568_VP0_COLOR_BAR_CTRL 0xC08
#define RK3568_VP0_3D_LUT_CTRL 0xC10
#define RK3568_VP0_3D_LUT_MST 0xC20
#define RK3568_VP0_DSP_BG 0xC2C
#define RK3568_VP0_PRE_SCAN_HTIMING 0xC30
#define RK3568_VP0_POST_DSP_HACT_INFO 0xC34