mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
drm/rockchip: vop2: add support cubic lut
Change-Id: Iebf89a10b4bdfe630212b393019e926b6dde0e22 Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user