drm/rockchip: rk3399 vop: add support win csc

support rgb2yuv for yuv output, the csc matrix maybe
bt601,bt601l,bt709 and bt2020, depend on connect output
color space.

Change-Id: Ibd8defc9a2519f850d8f3af7ee350022e5ee2ee4
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang 2018-07-13 10:17:35 +08:00 committed by Jianhong Chen
parent 543c0e7848
commit b7618fd33c
4 changed files with 116 additions and 0 deletions

View File

@ -82,6 +82,7 @@ struct crtc_state {
int crtc_y;
int crtc_w;
int crtc_h;
bool yuv_overlay;
struct rockchip_mcu_timing mcu_timing;
};

View File

@ -236,6 +236,8 @@ static int rockchip_vop_init(struct display_state *state)
vop->grf_ctrl = vop_data->grf_ctrl;
vop->line_flag = vop_data->line_flag;
vop->csc_table = vop_data->csc_table;
vop->win_csc = vop_data->win_csc;
vop->version = vop_data->version;
vop->max_output = vop_data->max_output;
@ -388,6 +390,7 @@ static int rockchip_vop_init(struct display_state *state)
post_r2y_en = true;
}
crtc_state->yuv_overlay = yuv_overlay;
post_csc_mode = to_vop_csc_mode(conn_state->color_space);
VOP_CTRL_SET(vop, bcsh_r2y_en, post_r2y_en);
VOP_CTRL_SET(vop, bcsh_y2r_en, post_y2r_en);
@ -584,6 +587,54 @@ static void scl_vop_cal_scl_fac(struct vop *vop,
}
}
static void vop_load_csc_table(struct vop *vop, u32 offset, const u32 *table)
{
int i;
/*
* so far the csc offset is not 0 and in the feature the csc offset
* impossible be 0, so when the offset is 0, should return here.
*/
if (!table || offset == 0)
return;
for (i = 0; i < 8; i++)
vop_writel(vop, offset + i * 4, table[i]);
}
static int rockchip_vop_setup_csc_table(struct display_state *state)
{
struct crtc_state *crtc_state = &state->crtc_state;
struct connector_state *conn_state = &state->conn_state;
struct vop *vop = crtc_state->private;
const uint32_t *csc_table = NULL;
if (!vop->csc_table || !crtc_state->yuv_overlay)
return 0;
/* todo: only implement r2y*/
switch (conn_state->color_space) {
case V4L2_COLORSPACE_SMPTE170M:
csc_table = vop->csc_table->r2y_bt601_12_235;
break;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_DEFAULT:
case V4L2_COLORSPACE_JPEG:
csc_table = vop->csc_table->r2y_bt709;
break;
case V4L2_COLORSPACE_BT2020:
csc_table = vop->csc_table->r2y_bt2020;
break;
default:
csc_table = vop->csc_table->r2y_bt601;
break;
}
vop_load_csc_table(vop, vop->win_csc->r2y_offset, csc_table);
VOP_WIN_CSC_SET(vop, r2y_en, 1);
return 0;
}
static int rockchip_vop_set_plane(struct display_state *state)
{
struct crtc_state *crtc_state = &state->crtc_state;
@ -630,6 +681,7 @@ static int rockchip_vop_set_plane(struct display_state *state)
VOP_WIN_SET(vop, src_alpha_ctl, 0);
rockchip_vop_setup_csc_table(state);
VOP_WIN_SET(vop, enable, 1);
vop_cfg_done(vop);

View File

@ -58,6 +58,8 @@
REG_SET(x, name, 0, (x)->ctrl->name, v)
#define VOP_LINE_FLAG_SET(x, name, v) \
REG_SET(x, name, 0, (x)->line_flag->name, v)
#define VOP_WIN_CSC_SET(x, name, v) \
REG_SET(x, name, 0, (x)->win_csc->name, v)
#define VOP_CTRL_GET(x, name) \
vop_read_reg(x, 0, &vop->ctrl->name)
@ -429,6 +431,23 @@ struct vop_rect {
int height;
};
struct vop_csc_table {
const uint32_t *r2y_bt601;
const uint32_t *r2y_bt601_12_235;
const uint32_t *r2y_bt709;
const uint32_t *r2y_bt2020;
};
struct vop_csc {
struct vop_reg y2r_en;
struct vop_reg r2r_en;
struct vop_reg r2y_en;
uint32_t y2r_offset;
uint32_t r2r_offset;
uint32_t r2y_offset;
};
#define VOP_FEATURE_OUTPUT_10BIT BIT(0)
struct vop_data {
@ -437,6 +456,8 @@ struct vop_data {
const struct vop_win *win;
const struct vop_line_flag *line_flag;
const struct vop_grf_ctrl *grf_ctrl;
const struct vop_csc_table *csc_table;
const struct vop_csc *win_csc;
int win_offset;
int reg_len;
u64 feature;
@ -453,6 +474,8 @@ struct vop {
const struct vop_win *win;
const struct vop_line_flag *line_flag;
const struct vop_grf_ctrl *grf_ctrl;
const struct vop_csc_table *csc_table;
const struct vop_csc *win_csc;
int win_offset;
struct vop_rect max_output;
};

View File

@ -235,6 +235,42 @@ const struct vop_data rk3366_vop = {
.reg_len = RK3366_DSP_VACT_ST_END_F1 * 4,
};
static const uint32_t vop_csc_r2y_bt601[] = {
0x02590132, 0xff530075, 0x0200fead, 0xfe530200,
0x0000ffad, 0x00000200, 0x00080200, 0x00080200,
};
static const uint32_t vop_csc_r2y_bt601_12_235[] = {
0x02040107, 0xff680064, 0x01c2fed6, 0xffb7fe87,
0x0000ffb7, 0x00010200, 0x00080200, 0x00080200,
};
static const uint32_t vop_csc_r2y_bt709[] = {
0x027500bb, 0xff99003f, 0x01c2fea5, 0xfe6801c2,
0x0000ffd7, 0x00010200, 0x00080200, 0x00080200,
};
static const uint32_t vop_csc_r2y_bt2020[] = {
0x025300e6, 0xff830034, 0x01c1febd, 0xfe6401c1,
0x0000ffdc, 0x00010200, 0x00080200, 0x00080200,
};
static const struct vop_csc_table rk3399_csc_table = {
.r2y_bt601 = vop_csc_r2y_bt601,
.r2y_bt601_12_235 = vop_csc_r2y_bt601_12_235,
.r2y_bt709 = vop_csc_r2y_bt709,
.r2y_bt2020 = vop_csc_r2y_bt2020,
};
static const struct vop_csc rk3399_win0_csc = {
.r2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 0),
.y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1),
.r2y_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 2),
.y2r_offset = RK3399_WIN0_YUV2YUV_Y2R,
.r2r_offset = RK3399_WIN0_YUV2YUV_3X3,
.r2y_offset = RK3399_WIN0_YUV2YUV_R2Y,
};
const struct vop_data rk3399_vop_big = {
.version = VOP_VERSION(3, 5),
.max_output = {4096, 2160},
@ -242,6 +278,8 @@ const struct vop_data rk3399_vop_big = {
.ctrl = &rk3288_ctrl_data,
.win = &rk3288_win01_data,
.line_flag = &rk3366_vop_line_flag,
.csc_table = &rk3399_csc_table,
.win_csc = &rk3399_win0_csc,
.reg_len = RK3399_DSP_VACT_ST_END_F1 * 4,
};
@ -251,6 +289,8 @@ const struct vop_data rk3399_vop_lit = {
.ctrl = &rk3288_ctrl_data,
.win = &rk3288_win01_data,
.line_flag = &rk3366_vop_line_flag,
.csc_table = &rk3399_csc_table,
.win_csc = &rk3399_win0_csc,
.reg_len = RK3399_DSP_VACT_ST_END_F1 * 4,
};