diff mbox

[RFC,01/11] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator()

Message ID E1YcfXV-0002uL-9O@rmk-PC.arm.linux.org.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Russell King March 30, 2015, 7:40 p.m. UTC
Clean up hdmi_set_clk_regenerator() by allowing it to take the audio
sample rate and ratio directly, rather than hiding it inside the
function.  Raise the unsupported pixel clock/sample rate message from
debug to error level as this results in audio not working correctly.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

Comments

Yakir Yang March 31, 2015, 6:55 a.m. UTC | #1
Hi Russell,

On 03/30/2015 03:40 PM, Russell King wrote:
> Clean up hdmi_set_clk_regenerator() by allowing it to take the audio
> sample rate and ratio directly, rather than hiding it inside the
> function.  Raise the unsupported pixel clock/sample rate message from
> debug to error level as this results in audio not working correctly.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>   drivers/gpu/drm/bridge/dw_hdmi.c | 32 +++++++++++++++-----------------
>   1 file changed, 15 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index cca1c3d165e2..49df6c8c4ea8 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -335,39 +335,37 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
>   }
>   
>   static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> -				     unsigned long pixel_clk)
> +	unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
>   {
> -	unsigned int clk_n, clk_cts;
> +	unsigned int n, cts;
>   
> -	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
> -			       hdmi->ratio);
> -	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
> -				   hdmi->ratio);
> -
> -	if (!clk_cts) {
> -		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
> -			__func__, pixel_clk);
> -		return;
> +	n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
> +	cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
> +	if (!cts) {
> +		dev_err(hdmi->dev,
> +			"%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
> +			__func__, pixel_clk, sample_rate);
>   	}
>   
> -	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
> -		__func__, hdmi->sample_rate, hdmi->ratio,
> -		pixel_clk, clk_n, clk_cts);
> +	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
> +		__func__, sample_rate, ratio, pixel_clk, n, cts);
>   
> -	hdmi_set_cts_n(hdmi, clk_cts, clk_n);
> +	hdmi_set_cts_n(hdmi, cts, n);
>   }
>   
>   static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
>   {
>   	mutex_lock(&hdmi->audio_mutex);
> -	hdmi_set_clk_regenerator(hdmi, 74250000);
> +	hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
> +				 hdmi->ratio);
>   	mutex_unlock(&hdmi->audio_mutex);
>   }
>   
>   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.mpixelclock,
> +				 hdmi->sample_rate, hdmi->ratio);

I'm okay with this change, and also I am preparing that collect N/CTS
setting to an array, like this :

     struct n_cts {
         unsigned int cts;
         unsigned int n;
     };

     struct tmds_n_cts {
         unsigned long tmds;
         /* 1 entry each for 32KHz, 44.1KHz, and 48KHz */
         struct n_cts n_cts[3];
     };

     static const struct tmds_n_cts n_cts_table[] = {
         { 25175000, {{ 28125,  4576}, { 31250,  7007}, { 25175, 6144} } },
     }

But I am confused by the "hdmi->ratio", this variable was modify to 100 
in bind
funciton, then nowhere would change it again. In this case "hdmi->ratio" 
seems
an unused variable, can we remove it ?

Best regards.
Yakir Yang

>   	mutex_unlock(&hdmi->audio_mutex);
>   }
>
Russell King - ARM Linux March 31, 2015, 10:35 a.m. UTC | #2
On Tue, Mar 31, 2015 at 02:55:53AM -0400, Yang Kuankuan wrote:
> Hi Russell,
> 
> I'm okay with this change, and also I am preparing that collect N/CTS
> setting to an array, like this :
> 
>     struct n_cts {
>         unsigned int cts;
>         unsigned int n;
>     };
> 
>     struct tmds_n_cts {
>         unsigned long tmds;
>         /* 1 entry each for 32KHz, 44.1KHz, and 48KHz */
>         struct n_cts n_cts[3];
>     };
> 
>     static const struct tmds_n_cts n_cts_table[] = {
>         { 25175000, {{ 28125,  4576}, { 31250,  7007}, { 25175, 6144} } },
>     }

I think this is something which should be a common helper rather than
being specific to the driver.  I believe these are the standard values
for coherent audio/video clocks which can be found in the HDMI
specifications.  Such a helper should document that it is only for
use when the audio and video clocks are coherent.

(The HDMI spec gives alternative N values for use with auto-CTS value
generation for non-coherent clocks.)

I'd also prefer the lookup to use the same units as the drm_display_mode
video clock specification, which is kHz, so we can eventually kill the
needless *1000 in dw_hdmi.

One of the issues with using a common helper is that the common helper
would include the 1.001 clocks, which are allegedly unsupported by the
FSL iMX6 implementation, and, if proven that they don't work, we would
need some way to disable audio for those devices.

> But I am confused by the "hdmi->ratio", this variable was modify to
> 100 in bind funciton, then nowhere would change it again. In this
> case "hdmi->ratio" seems an unused variable, can we remove it ?

I guess the FSL sources should be checked to find out what the intended
use for that was, and we then need to decide whether to keep it (and
implement it) or remove it.
Yakir Yang April 1, 2015, 1:54 a.m. UTC | #3
Hi Rusell,

? 2015/3/31 18:35, Russell King - ARM Linux ??:
> On Tue, Mar 31, 2015 at 02:55:53AM -0400, Yang Kuankuan wrote:
>> Hi Russell,
>>
>> I'm okay with this change, and also I am preparing that collect N/CTS
>> setting to an array, like this :
>>
>>      struct n_cts {
>>          unsigned int cts;
>>          unsigned int n;
>>      };
>>
>>      struct tmds_n_cts {
>>          unsigned long tmds;
>>          /* 1 entry each for 32KHz, 44.1KHz, and 48KHz */
>>          struct n_cts n_cts[3];
>>      };
>>
>>      static const struct tmds_n_cts n_cts_table[] = {
>>          { 25175000, {{ 28125,  4576}, { 31250,  7007}, { 25175, 6144} } },
>>      }
> I think this is something which should be a common helper rather than
> being specific to the driver.  I believe these are the standard values
> for coherent audio/video clocks which can be found in the HDMI
> specifications.  Such a helper should document that it is only for
> use when the audio and video clocks are coherent.

Yep, it will be logical to add the n/cts calcu to a common helper. And 
actually
the HDMI specifications have give the Revommended N and Expected CTS 
values for
several standard TMDS clock rates(25.2/1.001 ...).

>
> (The HDMI spec gives alternative N values for use with auto-CTS value
> generation for non-coherent clocks.)
>
> I'd also prefer the lookup to use the same units as the drm_display_mode
> video clock specification, which is kHz, so we can eventually kill the
> needless *1000 in dw_hdmi.
>
> One of the issues with using a common helper is that the common helper
> would include the 1.001 clocks, which are allegedly unsupported by the
> FSL iMX6 implementation, and, if proven that they don't work, we would
> need some way to disable audio for those devices.

Okay, but rockchip platform can handle the 1.001 clocks, so maybe we can 
call
some valid function from dw_hdmi-imx & dw_hdmi-rockchip to mark the 
effective
clock that platform support ?

>> But I am confused by the "hdmi->ratio", this variable was modify to
>> 100 in bind funciton, then nowhere would change it again. In this
>> case "hdmi->ratio" seems an unused variable, can we remove it ?
> I guess the FSL sources should be checked to find out what the intended
> use for that was, and we then need to decide whether to keep it (and
> implement it) or remove it.
Need FSL ack...

Best regards.
Yakir Yang
diff mbox

Patch

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index cca1c3d165e2..49df6c8c4ea8 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -335,39 +335,37 @@  static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 }
 
 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
-				     unsigned long pixel_clk)
+	unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
 {
-	unsigned int clk_n, clk_cts;
+	unsigned int n, cts;
 
-	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
-			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
-				   hdmi->ratio);
-
-	if (!clk_cts) {
-		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			__func__, pixel_clk);
-		return;
+	n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
+	cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
+	if (!cts) {
+		dev_err(hdmi->dev,
+			"%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
+			__func__, pixel_clk, sample_rate);
 	}
 
-	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
-		__func__, hdmi->sample_rate, hdmi->ratio,
-		pixel_clk, clk_n, clk_cts);
+	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
+		__func__, sample_rate, ratio, pixel_clk, n, cts);
 
-	hdmi_set_cts_n(hdmi, clk_cts, clk_n);
+	hdmi_set_cts_n(hdmi, cts, n);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
 {
 	mutex_lock(&hdmi->audio_mutex);
-	hdmi_set_clk_regenerator(hdmi, 74250000);
+	hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
+				 hdmi->ratio);
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
 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.mpixelclock,
+				 hdmi->sample_rate, hdmi->ratio);
 	mutex_unlock(&hdmi->audio_mutex);
 }