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:
parent
7130fbf68d
commit
79feefb115
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue