drm/sti: adapt YUV colorspace in display pipeline
Use BT601 for SD/ED resolution and BT709 for HD resolution Signed-off-by: Bich Hemon <bich.hemon@st.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Reviewed-by: Vincent Abriou <vincent.abriou@st.com>
This commit is contained in:
parent
dd86dc2f9a
commit
05a142c2bd
|
@ -95,6 +95,8 @@
|
|||
|
||||
#define ENCODER_CRTC_MASK (BIT(0) | BIT(1))
|
||||
|
||||
#define TVO_MIN_HD_HEIGHT 720
|
||||
|
||||
/* enum listing the supported output data format */
|
||||
enum sti_tvout_video_out_type {
|
||||
STI_TVOUT_VIDEO_OUT_RGB,
|
||||
|
@ -257,6 +259,31 @@ static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout,
|
|||
tvout_write(tvout, val, reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set preformatter matrix
|
||||
*
|
||||
* @tvout: tvout structure
|
||||
* @mode: display mode structure
|
||||
*/
|
||||
static void tvout_preformatter_set_matrix(struct sti_tvout *tvout,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
unsigned int i;
|
||||
const u32 *pf_matrix;
|
||||
|
||||
if (mode->vdisplay >= TVO_MIN_HD_HEIGHT)
|
||||
pf_matrix = rgb_to_ycbcr_709;
|
||||
else
|
||||
pf_matrix = rgb_to_ycbcr_601;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tvout_write(tvout, *(pf_matrix + i),
|
||||
TVO_CSC_MAIN_M0 + (i * 4));
|
||||
tvout_write(tvout, *(pf_matrix + i),
|
||||
TVO_CSC_AUX_M0 + (i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start VIP block for DVO output
|
||||
*
|
||||
|
@ -447,10 +474,6 @@ static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder,
|
|||
{
|
||||
}
|
||||
|
||||
static void sti_tvout_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
}
|
||||
|
||||
static void sti_tvout_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sti_tvout_encoder *sti_encoder = to_sti_tvout_encoder(encoder);
|
||||
|
@ -463,10 +486,12 @@ static const struct drm_encoder_funcs sti_tvout_encoder_funcs = {
|
|||
.destroy = sti_tvout_encoder_destroy,
|
||||
};
|
||||
|
||||
static void sti_dvo_encoder_commit(struct drm_encoder *encoder)
|
||||
static void sti_dvo_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sti_tvout *tvout = to_sti_tvout(encoder);
|
||||
|
||||
tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode);
|
||||
|
||||
tvout_dvo_start(tvout, sti_crtc_is_main(encoder->crtc));
|
||||
}
|
||||
|
||||
|
@ -481,8 +506,7 @@ static void sti_dvo_encoder_disable(struct drm_encoder *encoder)
|
|||
static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = {
|
||||
.dpms = sti_tvout_encoder_dpms,
|
||||
.mode_set = sti_tvout_encoder_mode_set,
|
||||
.prepare = sti_tvout_encoder_prepare,
|
||||
.commit = sti_dvo_encoder_commit,
|
||||
.enable = sti_dvo_encoder_enable,
|
||||
.disable = sti_dvo_encoder_disable,
|
||||
};
|
||||
|
||||
|
@ -513,10 +537,12 @@ sti_tvout_create_dvo_encoder(struct drm_device *dev,
|
|||
return drm_encoder;
|
||||
}
|
||||
|
||||
static void sti_hda_encoder_commit(struct drm_encoder *encoder)
|
||||
static void sti_hda_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sti_tvout *tvout = to_sti_tvout(encoder);
|
||||
|
||||
tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode);
|
||||
|
||||
tvout_hda_start(tvout, sti_crtc_is_main(encoder->crtc));
|
||||
}
|
||||
|
||||
|
@ -534,8 +560,7 @@ static void sti_hda_encoder_disable(struct drm_encoder *encoder)
|
|||
static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = {
|
||||
.dpms = sti_tvout_encoder_dpms,
|
||||
.mode_set = sti_tvout_encoder_mode_set,
|
||||
.prepare = sti_tvout_encoder_prepare,
|
||||
.commit = sti_hda_encoder_commit,
|
||||
.commit = sti_hda_encoder_enable,
|
||||
.disable = sti_hda_encoder_disable,
|
||||
};
|
||||
|
||||
|
@ -564,10 +589,12 @@ static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
|
|||
return drm_encoder;
|
||||
}
|
||||
|
||||
static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
|
||||
static void sti_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sti_tvout *tvout = to_sti_tvout(encoder);
|
||||
|
||||
tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode);
|
||||
|
||||
tvout_hdmi_start(tvout, sti_crtc_is_main(encoder->crtc));
|
||||
}
|
||||
|
||||
|
@ -582,8 +609,7 @@ static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
|
|||
static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = {
|
||||
.dpms = sti_tvout_encoder_dpms,
|
||||
.mode_set = sti_tvout_encoder_mode_set,
|
||||
.prepare = sti_tvout_encoder_prepare,
|
||||
.commit = sti_hdmi_encoder_commit,
|
||||
.commit = sti_hdmi_encoder_enable,
|
||||
.disable = sti_hdmi_encoder_disable,
|
||||
};
|
||||
|
||||
|
@ -635,18 +661,9 @@ static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
|
|||
{
|
||||
struct sti_tvout *tvout = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
unsigned int i;
|
||||
|
||||
tvout->drm_dev = drm_dev;
|
||||
|
||||
/* set preformatter matrix */
|
||||
for (i = 0; i < 8; i++) {
|
||||
tvout_write(tvout, rgb_to_ycbcr_601[i],
|
||||
TVO_CSC_MAIN_M0 + (i * 4));
|
||||
tvout_write(tvout, rgb_to_ycbcr_601[i],
|
||||
TVO_CSC_AUX_M0 + (i * 4));
|
||||
}
|
||||
|
||||
sti_tvout_create_encoders(drm_dev, tvout);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -42,6 +42,17 @@
|
|||
#define VID_MPR1_BT709 0x0AC50000
|
||||
#define VID_MPR2_BT709 0x07150545
|
||||
#define VID_MPR3_BT709 0x00000AE8
|
||||
/* YCbCr to RGB BT709:
|
||||
* R = Y+1.3711Cr
|
||||
* G = Y-0.6992Cr-0.3359Cb
|
||||
* B = Y+1.7344Cb
|
||||
*/
|
||||
#define VID_MPR0_BT601 0x0A800000
|
||||
#define VID_MPR1_BT601 0x0AAF0000
|
||||
#define VID_MPR2_BT601 0x094E0754
|
||||
#define VID_MPR3_BT601 0x00000ADD
|
||||
|
||||
#define VID_MIN_HD_HEIGHT 720
|
||||
|
||||
void sti_vid_commit(struct sti_vid *vid,
|
||||
struct drm_plane_state *state)
|
||||
|
@ -52,6 +63,7 @@ void sti_vid_commit(struct sti_vid *vid,
|
|||
int dst_y = state->crtc_y;
|
||||
int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
|
||||
int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
|
||||
int src_h = state->src_h >> 16;
|
||||
u32 val, ydo, xdo, yds, xds;
|
||||
|
||||
/* Input / output size
|
||||
|
@ -71,6 +83,19 @@ void sti_vid_commit(struct sti_vid *vid,
|
|||
|
||||
writel((ydo << 16) | xdo, vid->regs + VID_VPO);
|
||||
writel((yds << 16) | xds, vid->regs + VID_VPS);
|
||||
|
||||
/* Color conversion parameters */
|
||||
if (src_h >= VID_MIN_HD_HEIGHT) {
|
||||
writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
|
||||
writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
|
||||
writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
|
||||
writel(VID_MPR3_BT709, vid->regs + VID_MPR3);
|
||||
} else {
|
||||
writel(VID_MPR0_BT601, vid->regs + VID_MPR0);
|
||||
writel(VID_MPR1_BT601, vid->regs + VID_MPR1);
|
||||
writel(VID_MPR2_BT601, vid->regs + VID_MPR2);
|
||||
writel(VID_MPR3_BT601, vid->regs + VID_MPR3);
|
||||
}
|
||||
}
|
||||
|
||||
void sti_vid_disable(struct sti_vid *vid)
|
||||
|
@ -91,12 +116,6 @@ static void sti_vid_init(struct sti_vid *vid)
|
|||
/* Opaque */
|
||||
writel(VID_ALP_OPAQUE, vid->regs + VID_ALP);
|
||||
|
||||
/* Color conversion parameters */
|
||||
writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
|
||||
writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
|
||||
writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
|
||||
writel(VID_MPR3_BT709, vid->regs + VID_MPR3);
|
||||
|
||||
/* Brightness, contrast, tint, saturation */
|
||||
writel(VID_BC_DFLT, vid->regs + VID_BC);
|
||||
writel(VID_TINT_DFLT, vid->regs + VID_TINT);
|
||||
|
|
Loading…
Reference in New Issue