From ac488736d3b249972bb914fdcbb92182a2f25590 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Fri, 16 Aug 2019 14:30:59 +0800 Subject: [PATCH] drm: bridge: dw-hdmi: support deep color mode Introduce mtmdsclock to record tmds clock, which is different to mpixelclock in deep color mode. Use this variable to select synopsys phy curr_ctrl/phy_config, and audio N/CTS. Change-Id: Ia78dee9c4901d2f1ca7f339dfb030d65bbf6861d Signed-off-by: Zheng Yang --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 72 +++++++++++++++-------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 2268db900232..05e9655698c9 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1649,6 +1649,9 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; + unsigned int tmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock; + unsigned int depth = + hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) && pdata->mpll_cfg_420) @@ -1662,11 +1665,11 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, break; for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) - if (mpixelclock <= curr_ctrl->mpixelclock) + if (tmdsclock <= curr_ctrl->mpixelclock) break; for (; phy_config->mpixelclock != ~0UL; phy_config++) - if (mpixelclock <= phy_config->mpixelclock) + if (tmdsclock <= phy_config->mpixelclock) break; if (mpll_config->mpixelclock == ~0UL || @@ -1674,11 +1677,18 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, phy_config->mpixelclock == ~0UL) return -EINVAL; - dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, + if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) + depth = fls(depth - 8); + else + depth = 0; + if (depth) + depth--; + + dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].cpce, HDMI_3D_TX_PHY_CPCE_CTRL); - dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, + dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].gmp, HDMI_3D_TX_PHY_GMPCTRL); - dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], + dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[depth], HDMI_3D_TX_PHY_CURRCTRL); dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); @@ -2060,6 +2070,32 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); } +static unsigned int +hdmi_get_tmdsclock(struct dw_hdmi *hdmi, unsigned long mpixelclock) +{ + unsigned int tmdsclock = mpixelclock; + unsigned int depth = + hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); + + if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { + switch (depth) { + case 16: + tmdsclock = mpixelclock * 2; + break; + case 12: + tmdsclock = mpixelclock * 3 / 2; + break; + case 10: + tmdsclock = mpixelclock * 5 / 4; + break; + default: + break; + } + } + + return tmdsclock; +} + static void hdmi_av_composer(struct dw_hdmi *hdmi, const struct drm_display_info *display, const struct drm_display_mode *mode) @@ -2072,32 +2108,16 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, vmode->previous_pixelclock = vmode->mpixelclock; vmode->mpixelclock = mode->crtc_clock * 1000; - if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) - vmode->mpixelclock /= 2; + if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == + DRM_MODE_FLAG_3D_FRAME_PACKING) + vmode->mpixelclock *= 2; dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); - vmode->mtmdsclock = vmode->mpixelclock; - - if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { - switch (hdmi_bus_fmt_color_depth( - hdmi->hdmi_data.enc_out_bus_format)) { - case 16: - vmode->mtmdsclock = vmode->mpixelclock * 2; - break; - case 12: - vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; - break; - case 10: - vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; - break; - } - } - + vmode->previous_tmdsclock = vmode->mtmdsclock; + vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, vmode->mpixelclock); if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) vmode->mtmdsclock /= 2; - dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); - vmode->previous_tmdsclock = vmode->mtmdsclock; /* Set up HDMI_FC_INVIDCONF */ inv_val = (hdmi->hdmi_data.hdcp_enable ||