video/rockchip: vop: add support CSC function for HDMI YUV output

add CSC config for YUV output mode

Change-Id: I9b53c3b3bdc0fc1a733897474c126042d17c3ac9
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
(Cherry-pick from commit 34d6280a1ae02cc3c98aa8e6d32151b37fd849c6)
This commit is contained in:
Sandy Huang 2018-02-26 19:49:43 +08:00 committed by Kever Yang
parent 7130fbf68d
commit 79feefb115
9 changed files with 204 additions and 0 deletions

View File

@ -961,6 +961,7 @@ static int rockchip_dw_mipi_dsi_init(struct display_state *state)
dsi->node = mipi_node;
conn_state->private = dsi;
conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
panel = dev_read_subnode(conn_state->dev, "panel");
if (!ofnode_valid(panel)) {

View File

@ -883,6 +883,7 @@ static int rockchip_analogix_dp_init(struct display_state *state)
conn_state->private = dp;
conn_state->type = DRM_MODE_CONNECTOR_eDP;
conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
#if 0
if (pdata->chip_type == RK3399_EDP) {

View File

@ -35,6 +35,9 @@ enum display_mode {
#define ROCKCHIP_OUT_MODE_P888 0
#define ROCKCHIP_OUT_MODE_P666 1
#define ROCKCHIP_OUT_MODE_P565 2
#define ROCKCHIP_OUT_MODE_S888 8
#define ROCKCHIP_OUT_MODE_S888_DUMMY 12
#define ROCKCHIP_OUT_MODE_YUV420 14
/* for use special outface */
#define ROCKCHIP_OUT_MODE_AAAA 15
@ -86,6 +89,7 @@ struct connector_state {
int output_mode;
int type;
int output_type;
int color_space;
struct {
u32 *lut;

View File

@ -642,6 +642,7 @@ static int rockchip_lvds_init(struct display_state *state)
conn_state->output_mode = ROCKCHIP_OUT_MODE_P666;
else
conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
return 0;
}

View File

@ -30,6 +30,56 @@ static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
return us * mode->clock / mode->htotal / 1000;
}
static int to_vop_csc_mode(int csc_mode)
{
switch (csc_mode) {
case V4L2_COLORSPACE_SMPTE170M:
return CSC_BT601L;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_DEFAULT:
return CSC_BT709L;
case V4L2_COLORSPACE_JPEG:
return CSC_BT601F;
case V4L2_COLORSPACE_BT2020:
return CSC_BT2020;
default:
return CSC_BT709L;
}
}
static bool is_yuv_output(uint32_t bus_format)
{
switch (bus_format) {
case MEDIA_BUS_FMT_YUV8_1X24:
case MEDIA_BUS_FMT_YUV10_1X30:
case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
return true;
default:
return false;
}
}
static bool is_uv_swap(uint32_t bus_format, uint32_t output_mode)
{
/*
* FIXME:
*
* There is no media type for YUV444 output,
* so when out_mode is AAAA or P888, assume output is YUV444 on
* yuv format.
*
* From H/W testing, YUV444 mode need a rb swap.
*/
if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
(output_mode == ROCKCHIP_OUT_MODE_AAAA ||
output_mode == ROCKCHIP_OUT_MODE_P888))
return true;
else
return false;
}
static int rockchip_vop_init_gamma(struct vop *vop, struct display_state *state)
{
struct crtc_state *crtc_state = &state->crtc_state;
@ -103,6 +153,8 @@ static int rockchip_vop_init(struct display_state *state)
struct clk dclk, aclk;
u32 val;
int ret;
bool yuv_overlay = false, post_r2y_en = false, post_y2r_en = false;
u16 post_csc_mode;
vop = malloc(sizeof(*vop));
if (!vop)
@ -188,6 +240,14 @@ static int rockchip_vop_init(struct display_state *state)
case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
val = DITHER_DOWN_EN(1) | DITHER_DOWN_MODE(RGB888_TO_RGB666);
break;
case MEDIA_BUS_FMT_YUV8_1X24:
case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
val = DITHER_DOWN_EN(0) | PRE_DITHER_DOWN_EN(1);
break;
case MEDIA_BUS_FMT_YUV10_1X30:
case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
val = DITHER_DOWN_EN(0) | PRE_DITHER_DOWN_EN(0);
break;
case MEDIA_BUS_FMT_RGB888_1X24:
default:
val = DITHER_DOWN_EN(0) | PRE_DITHER_DOWN_EN(0);
@ -200,7 +260,53 @@ static int rockchip_vop_init(struct display_state *state)
val |= DITHER_DOWN_MODE_SEL(DITHER_DOWN_ALLEGRO);
VOP_CTRL_SET(vop, dither_down, val);
VOP_CTRL_SET(vop, dclk_ddr,
conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0);
VOP_CTRL_SET(vop, hdmi_dclk_out_en,
conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0);
if (is_uv_swap(conn_state->bus_format, conn_state->output_mode))
VOP_CTRL_SET(vop, dsp_data_swap, DSP_RB_SWAP);
else
VOP_CTRL_SET(vop, dsp_data_swap, 0);
VOP_CTRL_SET(vop, out_mode, conn_state->output_mode);
if (VOP_CTRL_SUPPORT(vop, overlay_mode)) {
yuv_overlay = is_yuv_output(conn_state->bus_format);
VOP_CTRL_SET(vop, overlay_mode, yuv_overlay);
}
/*
* todo: r2y for win csc
*/
VOP_CTRL_SET(vop, dsp_out_yuv, is_yuv_output(conn_state->bus_format));
if (yuv_overlay) {
if (!is_yuv_output(conn_state->bus_format))
post_y2r_en = true;
} else {
if (is_yuv_output(conn_state->bus_format))
post_r2y_en = true;
}
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);
VOP_CTRL_SET(vop, bcsh_r2y_csc_mode, post_csc_mode);
VOP_CTRL_SET(vop, bcsh_y2r_csc_mode, post_csc_mode);
/*
* Background color is 10bit depth if vop version >= 3.5
*/
if (!is_yuv_output(conn_state->bus_format))
val = 0;
else if (VOP_MAJOR(vop->version) == 3 &&
VOP_MINOR(vop->version) >= 5)
val = 0x20010200;
else
val = 0x801080;
VOP_CTRL_SET(vop, dsp_background, val);
VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
val = hact_st << 16;
val |= hact_end;

View File

@ -128,6 +128,18 @@ enum dither_down_mode_sel {
DITHER_DOWN_FRC = 0x1
};
enum vop_csc_format {
CSC_BT601L,
CSC_BT709L,
CSC_BT601F,
CSC_BT2020,
};
#define DSP_BG_SWAP 0x1
#define DSP_RB_SWAP 0x2
#define DSP_RG_SWAP 0x4
#define DSP_DELTA_SWAP 0x8
#define PRE_DITHER_DOWN_EN(x) ((x) << 0)
#define DITHER_DOWN_EN(x) ((x) << 1)
#define DITHER_DOWN_MODE(x) ((x) << 2)
@ -238,6 +250,7 @@ struct vop_ctrl {
struct vop_reg core_dclk_div;
struct vop_reg dclk_ddr;
struct vop_reg p2i_en;
struct vop_reg hdmi_dclk_out_en;
struct vop_reg rgb_en;
struct vop_reg lvds_en;
struct vop_reg edp_en;

View File

@ -219,6 +219,9 @@ static const struct vop_ctrl rk3328_ctrl_data = {
.hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
.vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
.vpost_st_end_f1 = VOP_REG(RK3328_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
.post_scl_factor = VOP_REG(RK3328_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
.post_scl_ctrl = VOP_REG(RK3328_POST_SCL_CTRL, 0x3, 0),
.dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2),
.dsp_interlace = VOP_REG(RK3328_DSP_CTRL0, 0x1, 10),
.dsp_layer_sel = VOP_REG(RK3328_DSP_CTRL1, 0xff, 8),
.post_lb_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 18),
@ -249,6 +252,19 @@ static const struct vop_ctrl rk3328_ctrl_data = {
.dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0),
.bcsh_brightness = VOP_REG(RK3328_BCSH_BCS, 0xff, 0),
.bcsh_contrast = VOP_REG(RK3328_BCSH_BCS, 0x1ff, 8),
.bcsh_sat_con = VOP_REG(RK3328_BCSH_BCS, 0x3ff, 20),
.bcsh_out_mode = VOP_REG(RK3328_BCSH_BCS, 0x3, 30),
.bcsh_sin_hue = VOP_REG(RK3328_BCSH_H, 0x1ff, 0),
.bcsh_cos_hue = VOP_REG(RK3328_BCSH_H, 0x1ff, 16),
.bcsh_r2y_csc_mode = VOP_REG(RK3328_BCSH_CTRL, 0x3, 6),
.bcsh_r2y_en = VOP_REG(RK3328_BCSH_CTRL, 0x1, 4),
.bcsh_y2r_csc_mode = VOP_REG(RK3328_BCSH_CTRL, 0x3, 2),
.bcsh_y2r_en = VOP_REG(RK3328_BCSH_CTRL, 0x1, 0),
.bcsh_color_bar = VOP_REG(RK3328_BCSH_COLOR_BAR, 0xffffff, 8),
.bcsh_en = VOP_REG(RK3328_BCSH_COLOR_BAR, 0x1, 0),
.cfg_done = VOP_REG(RK3328_REG_CFG_DONE, 0x1, 0),
};

View File

@ -112,6 +112,10 @@
#define RK3288_DSP_VACT_ST_END 0x0194
#define RK3288_DSP_VS_ST_END_F1 0x0198
#define RK3288_DSP_VACT_ST_END_F1 0x019c
#define RK3288_BCSH_COLOR_BAR 0x01b0
#define RK3288_BCSH_BCS 0x01b4
#define RK3288_BCSH_H 0x01b8
/* register definition end */
/* rk3368 register definition */

View File

@ -56,6 +56,64 @@
#define DRM_EDID_PT_STEREO (1 << 5)
#define DRM_EDID_PT_INTERLACED (1 << 7)
/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
enum v4l2_colorspace {
/*
* Default colorspace, i.e. let the driver figure it out.
* Can only be used with video capture.
*/
V4L2_COLORSPACE_DEFAULT = 0,
/* SMPTE 170M: used for broadcast NTSC/PAL SDTV */
V4L2_COLORSPACE_SMPTE170M = 1,
/* Obsolete pre-1998 SMPTE 240M HDTV standard, superseded by Rec 709 */
V4L2_COLORSPACE_SMPTE240M = 2,
/* Rec.709: used for HDTV */
V4L2_COLORSPACE_REC709 = 3,
/*
* Deprecated, do not use. No driver will ever return this. This was
* based on a misunderstanding of the bt878 datasheet.
*/
V4L2_COLORSPACE_BT878 = 4,
/*
* NTSC 1953 colorspace. This only makes sense when dealing with
* really, really old NTSC recordings. Superseded by SMPTE 170M.
*/
V4L2_COLORSPACE_470_SYSTEM_M = 5,
/*
* EBU Tech 3213 PAL/SECAM colorspace. This only makes sense when
* dealing with really old PAL/SECAM recordings. Superseded by
* SMPTE 170M.
*/
V4L2_COLORSPACE_470_SYSTEM_BG = 6,
/*
* Effectively shorthand for V4L2_COLORSPACE_SRGB, V4L2_YCBCR_ENC_601
* and V4L2_QUANTIZATION_FULL_RANGE. To be used for (Motion-)JPEG.
*/
V4L2_COLORSPACE_JPEG = 7,
/* For RGB colorspaces such as produces by most webcams. */
V4L2_COLORSPACE_SRGB = 8,
/* AdobeRGB colorspace */
V4L2_COLORSPACE_ADOBERGB = 9,
/* BT.2020 colorspace, used for UHDTV. */
V4L2_COLORSPACE_BT2020 = 10,
/* Raw colorspace: for RAW unprocessed images */
V4L2_COLORSPACE_RAW = 11,
/* DCI-P3 colorspace, used by cinema projectors */
V4L2_COLORSPACE_DCI_P3 = 12,
};
struct drm_display_mode {
/* Proposed mode values */
int clock; /* in kHz */