mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
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:
@@ -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 ||
|
||||
|
||||
Reference in New Issue
Block a user