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 <zhengyang@rock-chips.com>
This commit is contained in:
Zheng Yang
2019-08-16 14:30:59 +08:00
committed by Tao Huang
parent d706ee35bb
commit ac488736d3

View File

@@ -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 ||