Re: [PATCH RFC v2 1/8] drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support

2018-12-18 Thread Neil Armstrong
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

2018-12-18 Thread Andrzej Hajda
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

2018-12-14 Thread Heiko Stuebner
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

2018-11-30 Thread 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 
---
 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 ||
+