diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c index e6aa989e1660..70aa0ff0d238 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c @@ -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: diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c index 1d14209de973..e364897d7dca 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c @@ -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; }