mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
UPSTREAM: drm/bridge: dw-hdmi: add support for YUV420 output
In order to support the HDMI2.0 YUV420 display modes, this patch
adds support for the YUV420 TMDS Clock divided by 2 and the controller
passthrough mode.
YUV420 Synopsys PHY support will need some specific configuration table
to support these modes.
This patch is based on work from Zheng Yang <zhengyang@rock-chips.com> in
the Rockchip Linux 4.4 BSP at [1]
[1] https://github.com/rockchip-linux/kernel/tree/release-4.4
Change-Id: I41733e40ac1a528c8a0e0dadb79c4e3b31ea5f6b
Cc: Zheng Yang <zhengyang@rock-chips.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1549022873-40549-5-git-send-email-narmstrong@baylibre.com
(cherry picked from commit ba9877e236)
This commit is contained in:
committed by
Algea Cao
parent
50f1e72b05
commit
28850f6ab7
@@ -154,6 +154,7 @@ struct hdmi_vmode {
|
||||
unsigned int mpixelclock;
|
||||
unsigned int mpixelrepetitioninput;
|
||||
unsigned int mpixelrepetitionoutput;
|
||||
unsigned int mtmdsclock;
|
||||
};
|
||||
|
||||
struct hdmi_data_info {
|
||||
@@ -656,7 +657,7 @@ static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
|
||||
static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
|
||||
{
|
||||
mutex_lock(&hdmi->audio_mutex);
|
||||
hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
|
||||
hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mtmdsclock,
|
||||
hdmi->sample_rate);
|
||||
mutex_unlock(&hdmi->audio_mutex);
|
||||
}
|
||||
@@ -665,7 +666,7 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
|
||||
{
|
||||
mutex_lock(&hdmi->audio_mutex);
|
||||
hdmi->sample_rate = rate;
|
||||
hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
|
||||
hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mtmdsclock,
|
||||
hdmi->sample_rate);
|
||||
mutex_unlock(&hdmi->audio_mutex);
|
||||
}
|
||||
@@ -1164,7 +1165,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
|
||||
*/
|
||||
void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi)
|
||||
{
|
||||
unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mpixelclock;
|
||||
unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock;
|
||||
|
||||
/* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
|
||||
if (hdmi->connector.display_info.hdmi.scdc.supported) {
|
||||
@@ -1330,6 +1331,8 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
|
||||
pdata->mpll_cfg_420)
|
||||
mpll_config = pdata->mpll_cfg_420;
|
||||
|
||||
/* TOFIX Will need 420 specific PHY configuration tables */
|
||||
|
||||
/* PLL/MPLL Cfg - always match on final entry */
|
||||
for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
|
||||
if (mpixelclock <= mpll_config->mpixelclock)
|
||||
@@ -1377,6 +1380,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
|
||||
unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock;
|
||||
int ret;
|
||||
|
||||
dw_hdmi_phy_power_off(hdmi);
|
||||
@@ -1405,7 +1409,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
}
|
||||
|
||||
/* Wait for resuming transmission of TMDS clock and data */
|
||||
if (mpixelclock > HDMI14_MAX_TMDSCLK)
|
||||
if (mtmdsclock > HDMI14_MAX_TMDSCLK)
|
||||
msleep(100);
|
||||
|
||||
return dw_hdmi_phy_power_on(hdmi);
|
||||
@@ -1680,16 +1684,20 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
struct drm_hdmi_info *hdmi_info = &hdmi->connector.display_info.hdmi;
|
||||
struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
|
||||
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
|
||||
unsigned int hdisplay, vdisplay;
|
||||
unsigned int vdisplay, hdisplay;
|
||||
|
||||
vmode->mtmdsclock = vmode->mpixelclock = mode->crtc_clock * 1000;
|
||||
|
||||
vmode->mpixelclock = mode->crtc_clock * 1000;
|
||||
if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format))
|
||||
vmode->mpixelclock /= 2;
|
||||
dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
|
||||
|
||||
if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format))
|
||||
vmode->mtmdsclock /= 2;
|
||||
|
||||
/* Set up HDMI_FC_INVIDCONF */
|
||||
inv_val = (hdmi->hdmi_data.hdcp_enable ||
|
||||
vmode->mpixelclock > HDMI14_MAX_TMDSCLK ||
|
||||
vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
|
||||
hdmi_info->scdc.scrambling.low_rates ?
|
||||
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
|
||||
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
|
||||
@@ -1757,7 +1765,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
|
||||
/* Scrambling Control */
|
||||
if (hdmi_info->scdc.supported) {
|
||||
if (vmode->mpixelclock > HDMI14_MAX_TMDSCLK ||
|
||||
if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
|
||||
hdmi_info->scdc.scrambling.low_rates) {
|
||||
/*
|
||||
* HDMI2.0 Specifies the following procedure:
|
||||
@@ -1803,7 +1811,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
|
||||
|
||||
/* Set up horizontal blanking pixel region width */
|
||||
hblank = mode->htotal - mode->hdisplay;
|
||||
hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
|
||||
hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
|
||||
|
||||
@@ -1811,7 +1818,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
|
||||
|
||||
/* Set up HSYNC active edge delay width (in pixel clks) */
|
||||
h_de_hs = mode->hsync_start - mode->hdisplay;
|
||||
hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1);
|
||||
hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
|
||||
|
||||
@@ -1819,7 +1825,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
|
||||
|
||||
/* Set up HSYNC active pulse width (in pixel clks) */
|
||||
hsync_len = mode->hsync_end - mode->hsync_start;
|
||||
hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
|
||||
hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user