video: rockchip: hdmi: improve hdr function when out of sink tmds clk

If output tmdsclk is out of sink max tmds clk, we need to set output
mode to 8bit or YCbCr422.

For example, sink max tmds clk is 600M, but 3840x2160p-60 10bit tmdsclk
is 594*1.25 > 600, we set output mode to YCbCr422 10bit which tmds clk
is 594, so we can get max picture quality.

Change-Id: I13fe30dad06757ec52de8d367f1e10a56e63ad92
Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
(cherry picked from commit 0c3397a9b8b4da4ca3a67e5a6d88abf20f00f184)
This commit is contained in:
Zheng Yang
2016-11-16 17:05:47 +08:00
committed by Huang, Tao
parent ea7b3fd24c
commit c227098074
2 changed files with 92 additions and 14 deletions

View File

@@ -76,6 +76,63 @@ static inline void hdmi_wq_set_audio(struct hdmi *hdmi)
hdmi->ops->setaudio(hdmi, &hdmi->audio);
}
static int hdmi_check_format(struct hdmi *hdmi, struct hdmi_video *vpara)
{
struct hdmi_video_timing *timing;
struct fb_videomode *mode;
int tmdsclk;
if (!vpara)
return -ENOENT;
timing = (struct hdmi_video_timing *)hdmi_vic2timing(vpara->vic);
if (!timing) {
pr_err("[%s] not found vic %d\n", __func__, vpara->vic);
return -ENOENT;
}
mode = &timing->mode;
if (vpara->color_input == HDMI_COLOR_YCBCR420)
tmdsclk = mode->pixclock / 2;
else if (vpara->format_3d == HDMI_3D_FRAME_PACKING)
tmdsclk = 2 * mode->pixclock;
else
tmdsclk = mode->pixclock;
if (vpara->color_output != HDMI_COLOR_YCBCR422) {
switch (vpara->color_output_depth) {
case 10:
tmdsclk += tmdsclk / 4;
break;
case 12:
tmdsclk += tmdsclk / 2;
break;
case 16:
tmdsclk += tmdsclk;
break;
case 8:
default:
break;
}
} else if (vpara->color_output_depth > 12) {
/* YCbCr422 mode only support up to 12bit */
vpara->color_output_depth = 12;
}
if ((tmdsclk > 594000000) ||
(tmdsclk > 340000000 &&
tmdsclk > hdmi->edid.maxtmdsclock)) {
if (vpara->format_3d == HDMI_3D_FRAME_PACKING) {
pr_err("out of max tmdsclk, disable 3d\n");
vpara->format_3d = 0;
} else if (vpara->color_output == HDMI_COLOR_YCBCR444 &&
hdmi->edid.ycbcr422) {
pr_warn("out of max tmdsclk, down to YCbCr422");
vpara->color_output = HDMI_COLOR_YCBCR422;
} else {
pr_warn("out of max tmds clock, limit to 8bit\n");
vpara->color_output_depth = 8;
}
}
return 0;
}
static void hdmi_wq_set_video(struct hdmi *hdmi)
{
struct hdmi_video *video = &hdmi->video;
@@ -144,10 +201,19 @@ static void hdmi_wq_set_video(struct hdmi *hdmi)
video->eotf = 0;
} else {
video->vic = hdmi->vic & HDMI_VIC_MASK;
video->eotf = hdmi->eotf;
video->eotf = 0;
if (hdmi->eotf) {
if (hdmi->eotf & hdmi->edid.hdr.hdrinfo.eotf)
video->eotf = hdmi->eotf;
else
pr_err("sink eotf %x not support eotf %x\n",
hdmi->edid.hdr.hdrinfo.eotf,
hdmi->eotf);
}
/* ST_2084 must be 10bit and bt2020 */
if (video->eotf & EOTF_ST_2084) {
video->color_output_depth = 10;
if (deepcolor & HDMI_DEEP_COLOR_30BITS)
video->color_output_depth = 10;
if (video->color_output > HDMI_COLOR_RGB_16_235)
video->colorimetry =
HDMI_COLORIMETRY_EXTEND_BT_2020_YCC;
@@ -156,7 +222,7 @@ static void hdmi_wq_set_video(struct hdmi *hdmi)
HDMI_COLORIMETRY_EXTEND_BT_2020_RGB;
}
}
hdmi_check_format(hdmi, video);
if (hdmi->uboot) {
if ((uboot_vic & HDMI_UBOOT_VIC_MASK) != hdmi->vic)
hdmi->uboot = 0;
@@ -459,6 +525,7 @@ static void hdmi_work_queue(struct work_struct *work)
HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
msleep(100);
hdmi_wq_set_video(hdmi);
hdmi_wq_set_audio(hdmi);
hdmi_wq_set_output(hdmi, hdmi->mute);
break;
case HDMI_ENABLE_HDCP:

View File

@@ -901,14 +901,22 @@ static int rockchip_hdmiv2_video_framecomposer(struct hdmi *hdmi_drv,
if ((tmdsclk > 594000000) ||
(tmdsclk > 340000000 &&
tmdsclk > hdmi_drv->edid.maxtmdsclock)) {
pr_warn("out of max tmds clock, limit to 8bit\n");
vpara->color_output_depth = 8;
if (vpara->color_input == HDMI_COLOR_YCBCR420)
tmdsclk = mode->pixclock / 2;
else if (vpara->format_3d != HDMI_3D_FRAME_PACKING)
tmdsclk = mode->pixclock;
else
if (vpara->format_3d == HDMI_3D_FRAME_PACKING) {
pr_err("3d frame packing mode out of max tmdsclk\n");
return -1;
} else if (vpara->color_output == HDMI_COLOR_YCBCR444 &&
hdmi_drv->edid.ycbcr422) {
pr_warn("out of max tmdsclk, down to YCbCr422");
vpara->color_output = HDMI_COLOR_YCBCR422;
tmdsclk = mode->pixclock;
} else {
pr_warn("out of max tmds clock, limit to 8bit\n");
vpara->color_output_depth = 8;
if (vpara->color_input == HDMI_COLOR_YCBCR420)
tmdsclk = mode->pixclock / 2;
else
tmdsclk = mode->pixclock;
}
}
if ((tmdsclk > 340000000) ||
@@ -1346,7 +1354,7 @@ static int rockchip_hdmiv2_video_csc(struct hdmi_dev *hdmi_dev,
csc_scale = 0;
}
switch (vpara->color_output_depth) {
switch (vpara->color_output_depth && mode != CSC_BYPASS) {
case 10:
color_depth = COLOR_DEPTH_30BIT;
mode += 1;
@@ -1376,9 +1384,12 @@ static int rockchip_hdmiv2_video_csc(struct hdmi_dev *hdmi_dev,
m_CSC_COLOR_DEPTH, v_CSC_COLOR_DEPTH(color_depth));
/* enable CSC */
hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL,
m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(1));
if (mode == CSC_BYPASS)
hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL,
m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(0));
else
hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL,
m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(1));
return 0;
}