From e70565e1cb2133e87d424a119ee235e40f027933 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 15 Mar 2019 10:54:14 +0100 Subject: [PATCH] UPSTREAM: drm/bridge: dw-hdmi: disable SCDC configuration for invalid setups This patch is an attempt to limit HDMI 2.0 SCDC setup when : - the SoC embeds an HDMI 1.4 only controller - the EDID supports SCDC but not scrambling - the EDID supports SCDC scrambling but not for low TMDS bit rates, while only supporting low TMDS bit rates This to avoid communicating with the SCDC DDC slave uncessary, and setting the DW-HDMI TMDS Scrambler setup when not supported by the underlying hardware. Change-Id: I8ec1b7c33f49e4a63196335589d11396c8b9fe0e Reported-by: Rob Herring Fixes: 264fce6cc2c1 ("drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support") Signed-off-by: Neil Armstrong Tested-by: Rob Herring Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20190315095414.28520-1-narmstrong@baylibre.com (cherry picked from commit 836f90f9e2d11263f9c6d7610c82f3bc7335d9a6) --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 34 ++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index bc9fddd0b7d2..66dad5a2a6e3 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1310,6 +1310,31 @@ static int hdmi_phy_i2c_read(struct dw_hdmi *hdmi, unsigned char addr) return val; } +/* Filter out invalid setups to avoid configuring SCDC and scrambling */ +static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi) +{ + struct drm_display_info *display = &hdmi->connector.display_info; + + /* Completely disable SCDC support for older controllers */ + if (hdmi->version < 0x200a) + return false; + + /* Disable if SCDC is not supported, or if an HF-VSDB block is absent */ + if (!display->hdmi.scdc.supported || + !display->hdmi.scdc.scrambling.supported) + return false; + + /* + * Disable if display only support low TMDS rates and scrambling + * for low rates is not supported either + */ + if (!display->hdmi.scdc.scrambling.low_rates && + display->max_tmds_clock <= 340000) + return false; + + return true; +} + /* * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates: * - The Source shall suspend transmission of the TMDS clock and data @@ -1328,7 +1353,7 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) 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) { + if (dw_hdmi_support_scdc(hdmi)) { if (mtmdsclock > HDMI14_MAX_TMDSCLK) drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); else @@ -2015,8 +2040,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, /* Set up HDMI_FC_INVIDCONF */ inv_val = (hdmi->hdmi_data.hdcp_enable || - vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || - hdmi_info->scdc.scrambling.low_rates ? + (dw_hdmi_support_scdc(hdmi) && + (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || + hdmi_info->scdc.scrambling.low_rates)) ? HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); @@ -2085,7 +2111,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, } /* Scrambling Control */ - if (hdmi_info->scdc.supported) { + if (dw_hdmi_support_scdc(hdmi)) { if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || hdmi_info->scdc.scrambling.low_rates) { /*