Re: [PATCH RFC v2 1/8] drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support
On 18/12/2018 13:25, Andrzej Hajda wrote: > Hi Neil, > > > On 30.11.2018 14:42, Neil Armstrong wrote: >> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS >> Scrambling when supported or mandatory. >> >> This patch also adds an helper to setup the control bit to support >> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with >> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes. >> >> These changes were based on work done by Huicong Xu >> and Nickey Yang to support HDMI2.0 modes >> on the Rockchip 4.4 BSP kernel at [1] >> >> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4 >> >> Cc: Nickey Yang >> Cc: Huicong Xu >> Signed-off-by: Neil Armstrong >> --- >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 88 ++- >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 + >> include/drm/bridge/dw_hdmi.h | 1 + >> 3 files changed, 87 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> index 64c3cf027518..fcd941d52753 100644 >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> @@ -28,6 +28,7 @@ >> #include >> #include >> #include >> +#include >> #include >> >> #include >> @@ -43,6 +44,11 @@ >> >> #define HDMI_EDID_LEN 512 >> >> +/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 >> */ >> +#define SCDC_MIN_SOURCE_VERSION 0x1 >> + >> +#define HDMI14_MAX_TMDSCLK 34000 >> + >> enum hdmi_datamap { >> RGB444_8B = 0x01, >> RGB444_10B = 0x03, >> @@ -1015,6 +1021,33 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, >> unsigned short data, >> } >> EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); >> >> +/* >> + * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates: >> + * - The Source shall suspend transmission of the TMDS clock and data >> + * - The Source shall write to the TMDS_Bit_Clock_Ratio bit to change it >> + * from a 0 to a 1 or from a 1 to a 0 >> + * - The Source shall allow a minimum of 1 ms and a maximum of 100 ms from >> + * the time the TMDS_Bit_Clock_Ratio bit is written until resuming >> + * transmission of TMDS clock and data >> + * >> + * To respect the 100ms maximum delay, the >> dw_hdmi_set_high_tmds_clock_ratio() >> + * helper should called right before enabling the TMDS Clock and Data in >> + * the PHY configuration callback. >> + */ >> +void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) >> +{ >> +unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mpixelclock; >> + >> +/* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ >> +if (hdmi->connector.display_info.hdmi.scdc.supported) { >> +if (mtmdsclock > HDMI14_MAX_TMDSCLK) >> +drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); >> +else >> +drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 0); >> +} >> +} >> +EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio); >> + >> static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) >> { >> hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0, >> @@ -1216,6 +1249,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) >> >> dw_hdmi_phy_power_off(hdmi); >> >> +dw_hdmi_set_high_tmds_clock_ratio(hdmi); >> + >> /* Leave low power consumption mode by asserting SVSRET. */ >> if (phy->has_svsret) >> dw_hdmi_phy_enable_svsret(hdmi, 1); >> @@ -1237,6 +1272,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) >> return ret; >> } >> >> +/* Wait for resuming transmission of TMDS clock and data */ >> +if (mpixelclock > HDMI14_MAX_TMDSCLK) >> +msleep(100); >> + >> return dw_hdmi_phy_power_on(hdmi); >> } >> >> @@ -1340,11 +1379,12 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) >> >> static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode >> *mode) >> { >> +bool is_hdmi2_sink = hdmi->connector.display_info.hdmi.scdc.supported; >> struct hdmi_avi_infoframe frame; >> u8 val; >> >> /* Initialise info frame from DRM mode */ >> -drm_hdmi_avi_infoframe_from_display_mode(, mode, false); >> +drm_hdmi_avi_infoframe_from_display_mode(, mode, is_hdmi2_sink); >> >> if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) >> frame.colorspace = HDMI_COLORSPACE_YUV444; >> @@ -1503,7 +1543,8 @@ static void >> hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, >> static void hdmi_av_composer(struct dw_hdmi *hdmi, >> const struct drm_display_mode *mode) >> { >> -u8 inv_val; >> +u8 inv_val, bytes; >> +struct drm_hdmi_info *hdmi_info = >connector.display_info.hdmi; >> struct hdmi_vmode *vmode = >hdmi_data.video_mode; >> int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; >> unsigned
Re: [PATCH RFC v2 1/8] drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support
Hi Neil, On 30.11.2018 14:42, Neil Armstrong wrote: > Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS > Scrambling when supported or mandatory. > > This patch also adds an helper to setup the control bit to support > the high TMDS Bit Period/TMDS Clock-Period Ratio as required with > TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes. > > These changes were based on work done by Huicong Xu > and Nickey Yang to support HDMI2.0 modes > on the Rockchip 4.4 BSP kernel at [1] > > [1] https://github.com/rockchip-linux/kernel/tree/release-4.4 > > Cc: Nickey Yang > Cc: Huicong Xu > Signed-off-by: Neil Armstrong > --- > drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 88 ++- > drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 + > include/drm/bridge/dw_hdmi.h | 1 + > 3 files changed, 87 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > index 64c3cf027518..fcd941d52753 100644 > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > @@ -28,6 +28,7 @@ > #include > #include > #include > +#include > #include > > #include > @@ -43,6 +44,11 @@ > > #define HDMI_EDID_LEN512 > > +/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */ > +#define SCDC_MIN_SOURCE_VERSION 0x1 > + > +#define HDMI14_MAX_TMDSCLK 34000 > + > enum hdmi_datamap { > RGB444_8B = 0x01, > RGB444_10B = 0x03, > @@ -1015,6 +1021,33 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, > unsigned short data, > } > EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); > > +/* > + * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates: > + * - The Source shall suspend transmission of the TMDS clock and data > + * - The Source shall write to the TMDS_Bit_Clock_Ratio bit to change it > + * from a 0 to a 1 or from a 1 to a 0 > + * - The Source shall allow a minimum of 1 ms and a maximum of 100 ms from > + * the time the TMDS_Bit_Clock_Ratio bit is written until resuming > + * transmission of TMDS clock and data > + * > + * To respect the 100ms maximum delay, the > dw_hdmi_set_high_tmds_clock_ratio() > + * helper should called right before enabling the TMDS Clock and Data in > + * the PHY configuration callback. > + */ > +void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) > +{ > + unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mpixelclock; > + > + /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ > + if (hdmi->connector.display_info.hdmi.scdc.supported) { > + if (mtmdsclock > HDMI14_MAX_TMDSCLK) > + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); > + else > + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 0); > + } > +} > +EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio); > + > static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) > { > hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0, > @@ -1216,6 +1249,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) > > dw_hdmi_phy_power_off(hdmi); > > + dw_hdmi_set_high_tmds_clock_ratio(hdmi); > + > /* Leave low power consumption mode by asserting SVSRET. */ > if (phy->has_svsret) > dw_hdmi_phy_enable_svsret(hdmi, 1); > @@ -1237,6 +1272,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) > return ret; > } > > + /* Wait for resuming transmission of TMDS clock and data */ > + if (mpixelclock > HDMI14_MAX_TMDSCLK) > + msleep(100); > + > return dw_hdmi_phy_power_on(hdmi); > } > > @@ -1340,11 +1379,12 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) > > static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode > *mode) > { > + bool is_hdmi2_sink = hdmi->connector.display_info.hdmi.scdc.supported; > struct hdmi_avi_infoframe frame; > u8 val; > > /* Initialise info frame from DRM mode */ > - drm_hdmi_avi_infoframe_from_display_mode(, mode, false); > + drm_hdmi_avi_infoframe_from_display_mode(, mode, is_hdmi2_sink); > > if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) > frame.colorspace = HDMI_COLORSPACE_YUV444; > @@ -1503,7 +1543,8 @@ static void > hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, > static void hdmi_av_composer(struct dw_hdmi *hdmi, >const struct drm_display_mode *mode) > { > - u8 inv_val; > + u8 inv_val, bytes; > + struct drm_hdmi_info *hdmi_info = >connector.display_info.hdmi; > struct hdmi_vmode *vmode = >hdmi_data.video_mode; > int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; > unsigned int vdisplay; > @@ -1513,7 +1554,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, > dev_dbg(hdmi->dev, "final pixclk = %d\n",
Re: [PATCH RFC v2 1/8] drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support
Am Freitag, 30. November 2018, 14:42:54 CET schrieb Neil Armstrong: > Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS > Scrambling when supported or mandatory. > > This patch also adds an helper to setup the control bit to support > the high TMDS Bit Period/TMDS Clock-Period Ratio as required with > TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes. > > These changes were based on work done by Huicong Xu > and Nickey Yang to support HDMI2.0 modes > on the Rockchip 4.4 BSP kernel at [1] > > [1] https://github.com/rockchip-linux/kernel/tree/release-4.4 > > Cc: Nickey Yang > Cc: Huicong Xu > Signed-off-by: Neil Armstrong sorry this took a bit longer, but I can confirm that the 4 relevant patches (1, 4, 5, 6) at least still provide 1080p hdmi output on rk3288 (with internal hdmiphy) and rk3328 (with external innosilicon hdmiphy). I don't know how to test newly added features, but at least the patches don't seem to break existing users, so on rk3288 and rk3328 Tested-by: Heiko Stuebner ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH RFC v2 1/8] drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support
Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS Scrambling when supported or mandatory. This patch also adds an helper to setup the control bit to support the high TMDS Bit Period/TMDS Clock-Period Ratio as required with TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes. These changes were based on work done by Huicong Xu and Nickey Yang to support HDMI2.0 modes on the Rockchip 4.4 BSP kernel at [1] [1] https://github.com/rockchip-linux/kernel/tree/release-4.4 Cc: Nickey Yang Cc: Huicong Xu Signed-off-by: Neil Armstrong --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 88 ++- drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 + include/drm/bridge/dw_hdmi.h | 1 + 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 64c3cf027518..fcd941d52753 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,11 @@ #define HDMI_EDID_LEN 512 +/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */ +#define SCDC_MIN_SOURCE_VERSION0x1 + +#define HDMI14_MAX_TMDSCLK 34000 + enum hdmi_datamap { RGB444_8B = 0x01, RGB444_10B = 0x03, @@ -1015,6 +1021,33 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, } EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); +/* + * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates: + * - The Source shall suspend transmission of the TMDS clock and data + * - The Source shall write to the TMDS_Bit_Clock_Ratio bit to change it + * from a 0 to a 1 or from a 1 to a 0 + * - The Source shall allow a minimum of 1 ms and a maximum of 100 ms from + * the time the TMDS_Bit_Clock_Ratio bit is written until resuming + * transmission of TMDS clock and data + * + * To respect the 100ms maximum delay, the dw_hdmi_set_high_tmds_clock_ratio() + * helper should called right before enabling the TMDS Clock and Data in + * the PHY configuration callback. + */ +void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) +{ + unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mpixelclock; + + /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ + if (hdmi->connector.display_info.hdmi.scdc.supported) { + if (mtmdsclock > HDMI14_MAX_TMDSCLK) + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); + else + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 0); + } +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio); + static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) { hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0, @@ -1216,6 +1249,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) dw_hdmi_phy_power_off(hdmi); + dw_hdmi_set_high_tmds_clock_ratio(hdmi); + /* Leave low power consumption mode by asserting SVSRET. */ if (phy->has_svsret) dw_hdmi_phy_enable_svsret(hdmi, 1); @@ -1237,6 +1272,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) return ret; } + /* Wait for resuming transmission of TMDS clock and data */ + if (mpixelclock > HDMI14_MAX_TMDSCLK) + msleep(100); + return dw_hdmi_phy_power_on(hdmi); } @@ -1340,11 +1379,12 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) { + bool is_hdmi2_sink = hdmi->connector.display_info.hdmi.scdc.supported; struct hdmi_avi_infoframe frame; u8 val; /* Initialise info frame from DRM mode */ - drm_hdmi_avi_infoframe_from_display_mode(, mode, false); + drm_hdmi_avi_infoframe_from_display_mode(, mode, is_hdmi2_sink); if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) frame.colorspace = HDMI_COLORSPACE_YUV444; @@ -1503,7 +1543,8 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, static void hdmi_av_composer(struct dw_hdmi *hdmi, const struct drm_display_mode *mode) { - u8 inv_val; + u8 inv_val, bytes; + struct drm_hdmi_info *hdmi_info = >connector.display_info.hdmi; struct hdmi_vmode *vmode = >hdmi_data.video_mode; int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; unsigned int vdisplay; @@ -1513,7 +1554,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); /* Set up HDMI_FC_INVIDCONF */ - inv_val = (hdmi->hdmi_data.hdcp_enable ? + inv_val = (hdmi->hdmi_data.hdcp_enable || + vmode->mpixelclock > HDMI14_MAX_TMDSCLK || +