diff mbox series

drm: bridge/dw_hdmi: add audio sample channel status setting

Message ID 20190903055103.134764-1-cychiang@chromium.org (mailing list archive)
State New, archived
Headers show
Series drm: bridge/dw_hdmi: add audio sample channel status setting | expand

Commit Message

Cheng-yi Chiang Sept. 3, 2019, 5:51 a.m. UTC
From: Yakir Yang <ykk@rock-chips.com>

When transmitting IEC60985 linear PCM audio, we configure the
Audio Sample Channel Status information of all the channel
status bits in the IEC60958 frame.
Refer to 60958-3 page 10 for frequency, original frequency, and
wordlength setting.

This fix the issue that audio does not come out on some monitors
(e.g. LG 22CV241)

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
 2 files changed, 79 insertions(+)

Comments

Neil Armstrong Sept. 3, 2019, 9:53 a.m. UTC | #1
Hi,

On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> From: Yakir Yang <ykk@rock-chips.com>
> 
> When transmitting IEC60985 linear PCM audio, we configure the
> Audio Sample Channel Status information of all the channel
> status bits in the IEC60958 frame.
> Refer to 60958-3 page 10 for frequency, original frequency, and
> wordlength setting.
> 
> This fix the issue that audio does not come out on some monitors
> (e.g. LG 22CV241)
> 
> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> ---
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
>  2 files changed, 79 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index bd65d0479683..34d46e25d610 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
>  	return n;
>  }
>  
> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> +{
> +	u8 aud_schnl_samplerate;
> +	u8 aud_schnl_8;
> +
> +	/* These registers are on RK3288 using version 2.0a. */
> +	if (hdmi->version != 0x200a)
> +		return;

Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
SoCs ?

> +
> +	switch (hdmi->sample_rate) {
> +	case 32000:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> +		break;
> +	case 44100:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> +		break;
> +	case 48000:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> +		break;
> +	case 88200:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> +		break;
> +	case 96000:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> +		break;
> +	case 176400:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> +		break;
> +	case 192000:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> +		break;
> +	case 768000:
> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> +		break;
> +	default:
> +		dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> +			 hdmi->sample_rate);
> +		return;
> +	}
> +
> +	/* set channel status register */
> +	hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> +		  HDMI_FC_AUDSCHNLS7);
> +
> +	/*
> +	 * Set original frequency to be the same as frequency.
> +	 * Use one-complement value as stated in IEC60958-3 page 13.
> +	 */
> +	aud_schnl_8 = (~aud_schnl_samplerate) <<
> +			HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> +
> +	/* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> +	aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> +
> +	hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> +}
> +
>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>  	unsigned long pixel_clk, unsigned int sample_rate)
>  {
> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>  	hdmi->audio_cts = cts;
>  	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
>  	spin_unlock_irq(&hdmi->audio_lock);
> +
> +	hdmi_set_schnl(hdmi);
>  }
>  
>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> index 6988f12d89d9..619ebc1c8354 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> @@ -158,6 +158,17 @@
>  #define HDMI_FC_SPDDEVICEINF                    0x1062
>  #define HDMI_FC_AUDSCONF                        0x1063
>  #define HDMI_FC_AUDSSTAT                        0x1064
> +#define HDMI_FC_AUDSV                           0x1065
> +#define HDMI_FC_AUDSU                           0x1066
> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> +#define HDMI_FC_AUDSCHNLS8                      0x106f
>  #define HDMI_FC_DATACH0FILL                     0x1070
>  #define HDMI_FC_DATACH1FILL                     0x1071
>  #define HDMI_FC_DATACH2FILL                     0x1072
> @@ -706,6 +717,15 @@ enum {
>  /* HDMI_FC_AUDSCHNLS7 field values */
>  	HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
>  	HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> +	HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
>  
>  /* HDMI_FC_AUDSCHNLS8 field values */
>  	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
>
Neil Armstrong Sept. 3, 2019, 6 p.m. UTC | #2
Hi,

Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
> Hi,
> 
> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
>> From: Yakir Yang <ykk@rock-chips.com>
>>
>> When transmitting IEC60985 linear PCM audio, we configure the
>> Audio Sample Channel Status information of all the channel
>> status bits in the IEC60958 frame.
>> Refer to 60958-3 page 10 for frequency, original frequency, and
>> wordlength setting.
>>
>> This fix the issue that audio does not come out on some monitors
>> (e.g. LG 22CV241)
>>
>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
>> ---
>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
>>  2 files changed, 79 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> index bd65d0479683..34d46e25d610 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
>>  	return n;
>>  }
>>  
>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
>> +{
>> +	u8 aud_schnl_samplerate;
>> +	u8 aud_schnl_8;
>> +
>> +	/* These registers are on RK3288 using version 2.0a. */
>> +	if (hdmi->version != 0x200a)
>> +		return;
> 
> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> SoCs ?

After investigations, Amlogic sets these registers on their 2.0a version
aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
< 2.0a and > 2.0a IPs versions.

Can you check on the Rockchip IP versions in RK3399 ?

For reference, the HDMI 1.4a IP version allwinner setups is:
https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539
(registers a "scrambled" but a custom bit can reset to the original mapping,
0x1066 ... 0x106f)

Neil

> 
>> +
>> +	switch (hdmi->sample_rate) {
>> +	case 32000:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
>> +		break;
>> +	case 44100:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
>> +		break;
>> +	case 48000:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
>> +		break;
>> +	case 88200:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
>> +		break;
>> +	case 96000:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
>> +		break;
>> +	case 176400:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
>> +		break;
>> +	case 192000:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
>> +		break;
>> +	case 768000:
>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
>> +		break;
>> +	default:
>> +		dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
>> +			 hdmi->sample_rate);
>> +		return;
>> +	}
>> +
>> +	/* set channel status register */
>> +	hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
>> +		  HDMI_FC_AUDSCHNLS7);
>> +
>> +	/*
>> +	 * Set original frequency to be the same as frequency.
>> +	 * Use one-complement value as stated in IEC60958-3 page 13.
>> +	 */
>> +	aud_schnl_8 = (~aud_schnl_samplerate) <<
>> +			HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
>> +
>> +	/* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
>> +	aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
>> +
>> +	hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
>> +}
>> +
>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>>  	unsigned long pixel_clk, unsigned int sample_rate)
>>  {
>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>>  	hdmi->audio_cts = cts;
>>  	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
>>  	spin_unlock_irq(&hdmi->audio_lock);
>> +
>> +	hdmi_set_schnl(hdmi);
>>  }
>>  
>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>> index 6988f12d89d9..619ebc1c8354 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>> @@ -158,6 +158,17 @@
>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
>>  #define HDMI_FC_AUDSCONF                        0x1063
>>  #define HDMI_FC_AUDSSTAT                        0x1064
>> +#define HDMI_FC_AUDSV                           0x1065
>> +#define HDMI_FC_AUDSU                           0x1066
>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
>>  #define HDMI_FC_DATACH0FILL                     0x1070
>>  #define HDMI_FC_DATACH1FILL                     0x1071
>>  #define HDMI_FC_DATACH2FILL                     0x1072
>> @@ -706,6 +717,15 @@ enum {
>>  /* HDMI_FC_AUDSCHNLS7 field values */
>>  	HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
>>  	HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
>>  
>>  /* HDMI_FC_AUDSCHNLS8 field values */
>>  	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
>>
>
Jernej Škrabec Sept. 3, 2019, 6:08 p.m. UTC | #3
Hi!

Dne torek, 03. september 2019 ob 20:00:33 CEST je Neil Armstrong napisal(a):
> Hi,
> 
> Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
> > Hi,
> > 
> > On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> >> From: Yakir Yang <ykk@rock-chips.com>
> >> 
> >> When transmitting IEC60985 linear PCM audio, we configure the
> >> Audio Sample Channel Status information of all the channel
> >> status bits in the IEC60958 frame.
> >> Refer to 60958-3 page 10 for frequency, original frequency, and
> >> wordlength setting.
> >> 
> >> This fix the issue that audio does not come out on some monitors
> >> (e.g. LG 22CV241)
> >> 
> >> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> >> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> >> ---
> >> 
> >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> >>  2 files changed, 79 insertions(+)
> >> 
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index
> >> bd65d0479683..34d46e25d610 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int
> >> freq, unsigned long pixel_clk)>> 
> >>  	return n;
> >>  
> >>  }
> >> 
> >> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> >> +{
> >> +	u8 aud_schnl_samplerate;
> >> +	u8 aud_schnl_8;
> >> +
> >> +	/* These registers are on RK3288 using version 2.0a. */
> >> +	if (hdmi->version != 0x200a)
> >> +		return;
> > 
> > Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > SoCs ?
> 
> After investigations, Amlogic sets these registers on their 2.0a version
> aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
> < 2.0a and > 2.0a IPs versions.
> 
> Can you check on the Rockchip IP versions in RK3399 ?
> 
> For reference, the HDMI 1.4a IP version allwinner setups is:
> https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/vide
> o/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539 (registers a
> "scrambled" but a custom bit can reset to the original mapping, 0x1066 ...
> 0x106f)

For easier reading, here is similar, but annotated version: http://ix.io/1Ub6
Check function bsp_hdmi_audio().

Unless there is a special reason, you can just remove that check.

Best regards,
Jernej

> 
> Neil
> 
> >> +
> >> +	switch (hdmi->sample_rate) {
> >> +	case 32000:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> >> +		break;
> >> +	case 44100:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> >> +		break;
> >> +	case 48000:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> >> +		break;
> >> +	case 88200:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> >> +		break;
> >> +	case 96000:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> >> +		break;
> >> +	case 176400:
> >> +		aud_schnl_samplerate = 
HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> >> +		break;
> >> +	case 192000:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> >> +		break;
> >> +	case 768000:
> >> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> >> +		break;
> >> +	default:
> >> +		dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)
\n",
> >> +			 hdmi->sample_rate);
> >> +		return;
> >> +	}
> >> +
> >> +	/* set channel status register */
> >> +	hdmi_modb(hdmi, aud_schnl_samplerate, 
HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> >> +		  HDMI_FC_AUDSCHNLS7);
> >> +
> >> +	/*
> >> +	 * Set original frequency to be the same as frequency.
> >> +	 * Use one-complement value as stated in IEC60958-3 page 13.
> >> +	 */
> >> +	aud_schnl_8 = (~aud_schnl_samplerate) <<
> >> +			HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> >> +
> >> +	/* This means word length is 16 bit. Refer to IEC60958-3 page 12. 
*/
> >> +	aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> >> +
> >> +	hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> >> +}
> >> +
> >> 
> >>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >>  
> >>  	unsigned long pixel_clk, unsigned int sample_rate)
> >>  
> >>  {
> >> 
> >> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi
> >> *hdmi,>> 
> >>  	hdmi->audio_cts = cts;
> >>  	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> >>  	spin_unlock_irq(&hdmi->audio_lock);
> >> 
> >> +
> >> +	hdmi_set_schnl(hdmi);
> >> 
> >>  }
> >>  
> >>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> >> 
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index
> >> 6988f12d89d9..619ebc1c8354 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >> @@ -158,6 +158,17 @@
> >> 
> >>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> >>  #define HDMI_FC_AUDSCONF                        0x1063
> >>  #define HDMI_FC_AUDSSTAT                        0x1064
> >> 
> >> +#define HDMI_FC_AUDSV                           0x1065
> >> +#define HDMI_FC_AUDSU                           0x1066
> >> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> >> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> >> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> >> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> >> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> >> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> >> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> >> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> >> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> >> 
> >>  #define HDMI_FC_DATACH0FILL                     0x1070
> >>  #define HDMI_FC_DATACH1FILL                     0x1071
> >>  #define HDMI_FC_DATACH2FILL                     0x1072
> >> 
> >> @@ -706,6 +717,15 @@ enum {
> >> 
> >>  /* HDMI_FC_AUDSCHNLS7 field values */
> >>  
> >>  	HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> >>  	HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> >> 
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> >> +	HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> >> 
> >>  /* HDMI_FC_AUDSCHNLS8 field values */
> >>  
> >>  	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
Jonas Karlman Sept. 3, 2019, 8:33 p.m. UTC | #4
On 2019-09-03 20:08, Jernej Škrabec wrote:
> Hi!
>
> Dne torek, 03. september 2019 ob 20:00:33 CEST je Neil Armstrong napisal(a):
>> Hi,
>>
>> Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
>>> Hi,
>>>
>>> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
>>>> From: Yakir Yang <ykk@rock-chips.com>
>>>>
>>>> When transmitting IEC60985 linear PCM audio, we configure the
>>>> Audio Sample Channel Status information of all the channel
>>>> status bits in the IEC60958 frame.
>>>> Refer to 60958-3 page 10 for frequency, original frequency, and
>>>> wordlength setting.
>>>>
>>>> This fix the issue that audio does not come out on some monitors
>>>> (e.g. LG 22CV241)
>>>>
>>>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
>>>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
>>>> ---
>>>>
>>>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
>>>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
>>>>  2 files changed, 79 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>>> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index
>>>> bd65d0479683..34d46e25d610 100644
>>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int
>>>> freq, unsigned long pixel_clk)>> 
>>>>  	return n;
>>>>  
>>>>  }
>>>>
>>>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
>>>> +{
>>>> +	u8 aud_schnl_samplerate;
>>>> +	u8 aud_schnl_8;
>>>> +
>>>> +	/* These registers are on RK3288 using version 2.0a. */
>>>> +	if (hdmi->version != 0x200a)
>>>> +		return;
>>> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
>>> SoCs ?
>> After investigations, Amlogic sets these registers on their 2.0a version
>> aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
>> < 2.0a and > 2.0a IPs versions.
>>
>> Can you check on the Rockchip IP versions in RK3399 ?
>>
>> For reference, the HDMI 1.4a IP version allwinner setups is:
>> https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/vide
>> o/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539 (registers a
>> "scrambled" but a custom bit can reset to the original mapping, 0x1066 ...
>> 0x106f)
> For easier reading, here is similar, but annotated version: http://ix.io/1Ub6
> Check function bsp_hdmi_audio().
>
> Unless there is a special reason, you can just remove that check.

Agree, this check should not be needed, AUDSCHNLS7 used to be configured in my old
multi-channel patches that have seen lot of testing on Amlogic, Allwinner and Rockchip SoCs.

>
> Best regards,
> Jernej
>
>> Neil
>>
>>>> +
>>>> +	switch (hdmi->sample_rate) {
>>>> +	case 32000:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
>>>> +		break;
>>>> +	case 44100:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
>>>> +		break;
>>>> +	case 48000:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
>>>> +		break;
>>>> +	case 88200:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
>>>> +		break;
>>>> +	case 96000:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
>>>> +		break;
>>>> +	case 176400:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
>>>> +		break;
>>>> +	case 192000:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
>>>> +		break;
>>>> +	case 768000:
>>>> +		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
>>>> +		break;
>>>> +	default:
>>>> +		dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
>>>> +			 hdmi->sample_rate);
>>>> +		return;
>>>> +	}
>>>> +
>>>> +	/* set channel status register */
>>>> +	hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
>>>> +		  HDMI_FC_AUDSCHNLS7);
>>>> +
>>>> +	/*
>>>> +	 * Set original frequency to be the same as frequency.
>>>> +	 * Use one-complement value as stated in IEC60958-3 page 13.
>>>> +	 */
>>>> +	aud_schnl_8 = (~aud_schnl_samplerate) <<
>>>> +			HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
>>>> +
>>>> +	/* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
>>>> +	aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;

This looks wrong, user can use 16 and 24 bit wide audio streams.

>>>> +
>>>> +	hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
>>>> +}
>>>> +
>>>>
>>>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>>>>  
>>>>  	unsigned long pixel_clk, unsigned int sample_rate)
>>>>  
>>>>  {
>>>>
>>>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi
>>>> *hdmi,>> 
>>>>  	hdmi->audio_cts = cts;
>>>>  	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
>>>>  	spin_unlock_irq(&hdmi->audio_lock);
>>>>
>>>> +
>>>> +	hdmi_set_schnl(hdmi);

I will suggest this function is called from or merged with dw_hdmi_set_sample_rate().
Similar to how AUDSCONF and AUDICONF0 is configured from dw_hdmi_set_channel_count().

Regards,
Jonas

>>>>
>>>>  }
>>>>  
>>>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
>>>>
>>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>>>> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index
>>>> 6988f12d89d9..619ebc1c8354 100644
>>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>>>> @@ -158,6 +158,17 @@
>>>>
>>>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
>>>>  #define HDMI_FC_AUDSCONF                        0x1063
>>>>  #define HDMI_FC_AUDSSTAT                        0x1064
>>>>
>>>> +#define HDMI_FC_AUDSV                           0x1065
>>>> +#define HDMI_FC_AUDSU                           0x1066
>>>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
>>>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
>>>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
>>>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
>>>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
>>>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
>>>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
>>>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
>>>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
>>>>
>>>>  #define HDMI_FC_DATACH0FILL                     0x1070
>>>>  #define HDMI_FC_DATACH1FILL                     0x1071
>>>>  #define HDMI_FC_DATACH2FILL                     0x1072
>>>>
>>>> @@ -706,6 +717,15 @@ enum {
>>>>
>>>>  /* HDMI_FC_AUDSCHNLS7 field values */
>>>>  
>>>>  	HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
>>>>  	HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
>>>>
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
>>>> +	HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
>>>>
>>>>  /* HDMI_FC_AUDSCHNLS8 field values */
>>>>  
>>>>  	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
Cheng-yi Chiang Sept. 4, 2019, 9:09 a.m. UTC | #5
Hi,

On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Hi,
>
> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> > From: Yakir Yang <ykk@rock-chips.com>
> >
> > When transmitting IEC60985 linear PCM audio, we configure the
> > Audio Sample Channel Status information of all the channel
> > status bits in the IEC60958 frame.
> > Refer to 60958-3 page 10 for frequency, original frequency, and
> > wordlength setting.
> >
> > This fix the issue that audio does not come out on some monitors
> > (e.g. LG 22CV241)
> >
> > Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > ---
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> >  2 files changed, 79 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > index bd65d0479683..34d46e25d610 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
> >       return n;
> >  }
> >
> > +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> > +{
> > +     u8 aud_schnl_samplerate;
> > +     u8 aud_schnl_8;
> > +
> > +     /* These registers are on RK3288 using version 2.0a. */
> > +     if (hdmi->version != 0x200a)
> > +             return;
>
> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> SoCs ?
>

In the original patch by Yakir,

https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
have added this link in the "after the cut" note)

The fix is limited to version 2.0.
Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
I can not test 2.0a version on other SoCs.
The databook I have at hand is 2.0a (not specific to RK3288) so I
think all 2.0a should have this register.

As for other version like version 1.3 on iMX6, there is no such
register, as stated by Russell

http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.

So at least we should check the version.
Maybe we can set the criteria as version 2.0 or above to make it a safe patch ?
If there is the same need on other SoC with version < 2.0, it can be
added later.
Presumably, there will be databook of that version to help confirming
this setting.

Thanks!
> > +
> > +     switch (hdmi->sample_rate) {
> > +     case 32000:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> > +             break;
> > +     case 44100:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> > +             break;
> > +     case 48000:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> > +             break;
> > +     case 88200:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> > +             break;
> > +     case 96000:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> > +             break;
> > +     case 176400:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> > +             break;
> > +     case 192000:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> > +             break;
> > +     case 768000:
> > +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> > +             break;
> > +     default:
> > +             dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> > +                      hdmi->sample_rate);
> > +             return;
> > +     }
> > +
> > +     /* set channel status register */
> > +     hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> > +               HDMI_FC_AUDSCHNLS7);
> > +
> > +     /*
> > +      * Set original frequency to be the same as frequency.
> > +      * Use one-complement value as stated in IEC60958-3 page 13.
> > +      */
> > +     aud_schnl_8 = (~aud_schnl_samplerate) <<
> > +                     HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> > +
> > +     /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> > +     aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> > +
> > +     hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> > +}
> > +
> >  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >       unsigned long pixel_clk, unsigned int sample_rate)
> >  {
> > @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >       hdmi->audio_cts = cts;
> >       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> >       spin_unlock_irq(&hdmi->audio_lock);
> > +
> > +     hdmi_set_schnl(hdmi);
> >  }
> >
> >  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > index 6988f12d89d9..619ebc1c8354 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > @@ -158,6 +158,17 @@
> >  #define HDMI_FC_SPDDEVICEINF                    0x1062
> >  #define HDMI_FC_AUDSCONF                        0x1063
> >  #define HDMI_FC_AUDSSTAT                        0x1064
> > +#define HDMI_FC_AUDSV                           0x1065
> > +#define HDMI_FC_AUDSU                           0x1066
> > +#define HDMI_FC_AUDSCHNLS0                      0x1067
> > +#define HDMI_FC_AUDSCHNLS1                      0x1068
> > +#define HDMI_FC_AUDSCHNLS2                      0x1069
> > +#define HDMI_FC_AUDSCHNLS3                      0x106a
> > +#define HDMI_FC_AUDSCHNLS4                      0x106b
> > +#define HDMI_FC_AUDSCHNLS5                      0x106c
> > +#define HDMI_FC_AUDSCHNLS6                      0x106d
> > +#define HDMI_FC_AUDSCHNLS7                      0x106e
> > +#define HDMI_FC_AUDSCHNLS8                      0x106f
> >  #define HDMI_FC_DATACH0FILL                     0x1070
> >  #define HDMI_FC_DATACH1FILL                     0x1071
> >  #define HDMI_FC_DATACH2FILL                     0x1072
> > @@ -706,6 +717,15 @@ enum {
> >  /* HDMI_FC_AUDSCHNLS7 field values */
> >       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> >       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> > +     HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> >
> >  /* HDMI_FC_AUDSCHNLS8 field values */
> >       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
> >
>
Cheng-yi Chiang Sept. 4, 2019, 9:13 a.m. UTC | #6
On Wed, Sep 4, 2019 at 2:00 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Hi,
>
> Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
> > Hi,
> >
> > On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> >> From: Yakir Yang <ykk@rock-chips.com>
> >>
> >> When transmitting IEC60985 linear PCM audio, we configure the
> >> Audio Sample Channel Status information of all the channel
> >> status bits in the IEC60958 frame.
> >> Refer to 60958-3 page 10 for frequency, original frequency, and
> >> wordlength setting.
> >>
> >> This fix the issue that audio does not come out on some monitors
> >> (e.g. LG 22CV241)
> >>
> >> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> >> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> >> ---
> >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> >>  2 files changed, 79 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> index bd65d0479683..34d46e25d610 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
> >>      return n;
> >>  }
> >>
> >> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> >> +{
> >> +    u8 aud_schnl_samplerate;
> >> +    u8 aud_schnl_8;
> >> +
> >> +    /* These registers are on RK3288 using version 2.0a. */
> >> +    if (hdmi->version != 0x200a)
> >> +            return;
> >
> > Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > SoCs ?
>
> After investigations, Amlogic sets these registers on their 2.0a version
> aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
> < 2.0a and > 2.0a IPs versions.
>
> Can you check on the Rockchip IP versions in RK3399 ?
>
Sorry, the RK3399 board I am using is using DP, not HDMI.
But I found that on rockchip's tree at

https://github.com/rockchip-linux/kernel/commit/924f480383c982da9908fb96d6bbb580b25545a5#diff-f74b4cfb23436a137a9338a5af3fbb3dR172

There is such register setting, so I think RK3399 should have the same register.


> For reference, the HDMI 1.4a IP version allwinner setups is:
> https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539
> (registers a "scrambled" but a custom bit can reset to the original mapping,
> 0x1066 ... 0x106f)

I see.. so 1.4 has this register.
I can modify the check to be >= 1.4 then.
Will fix in v2.

Thanks!

>
> Neil
>
> >
> >> +
> >> +    switch (hdmi->sample_rate) {
> >> +    case 32000:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> >> +            break;
> >> +    case 44100:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> >> +            break;
> >> +    case 48000:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> >> +            break;
> >> +    case 88200:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> >> +            break;
> >> +    case 96000:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> >> +            break;
> >> +    case 176400:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> >> +            break;
> >> +    case 192000:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> >> +            break;
> >> +    case 768000:
> >> +            aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> >> +            break;
> >> +    default:
> >> +            dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> >> +                     hdmi->sample_rate);
> >> +            return;
> >> +    }
> >> +
> >> +    /* set channel status register */
> >> +    hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> >> +              HDMI_FC_AUDSCHNLS7);
> >> +
> >> +    /*
> >> +     * Set original frequency to be the same as frequency.
> >> +     * Use one-complement value as stated in IEC60958-3 page 13.
> >> +     */
> >> +    aud_schnl_8 = (~aud_schnl_samplerate) <<
> >> +                    HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> >> +
> >> +    /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> >> +    aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> >> +
> >> +    hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> >> +}
> >> +
> >>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >>      unsigned long pixel_clk, unsigned int sample_rate)
> >>  {
> >> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >>      hdmi->audio_cts = cts;
> >>      hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> >>      spin_unlock_irq(&hdmi->audio_lock);
> >> +
> >> +    hdmi_set_schnl(hdmi);
> >>  }
> >>
> >>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >> index 6988f12d89d9..619ebc1c8354 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >> @@ -158,6 +158,17 @@
> >>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> >>  #define HDMI_FC_AUDSCONF                        0x1063
> >>  #define HDMI_FC_AUDSSTAT                        0x1064
> >> +#define HDMI_FC_AUDSV                           0x1065
> >> +#define HDMI_FC_AUDSU                           0x1066
> >> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> >> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> >> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> >> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> >> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> >> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> >> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> >> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> >> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> >>  #define HDMI_FC_DATACH0FILL                     0x1070
> >>  #define HDMI_FC_DATACH1FILL                     0x1071
> >>  #define HDMI_FC_DATACH2FILL                     0x1072
> >> @@ -706,6 +717,15 @@ enum {
> >>  /* HDMI_FC_AUDSCHNLS7 field values */
> >>      HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> >>      HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> >> +    HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> >>
> >>  /* HDMI_FC_AUDSCHNLS8 field values */
> >>      HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
> >>
> >
Cheng-yi Chiang Sept. 4, 2019, 9:24 a.m. UTC | #7
On Wed, Sep 4, 2019 at 2:08 AM Jernej Škrabec <jernej.skrabec@siol.net> wrote:
>
> Hi!
>
> Dne torek, 03. september 2019 ob 20:00:33 CEST je Neil Armstrong napisal(a):
> > Hi,
> >
> > Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
> > > Hi,
> > >
> > > On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> > >> From: Yakir Yang <ykk@rock-chips.com>
> > >>
> > >> When transmitting IEC60985 linear PCM audio, we configure the
> > >> Audio Sample Channel Status information of all the channel
> > >> status bits in the IEC60958 frame.
> > >> Refer to 60958-3 page 10 for frequency, original frequency, and
> > >> wordlength setting.
> > >>
> > >> This fix the issue that audio does not come out on some monitors
> > >> (e.g. LG 22CV241)
> > >>
> > >> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> > >> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > >> ---
> > >>
> > >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> > >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> > >>  2 files changed, 79 insertions(+)
> > >>
> > >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > >> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index
> > >> bd65d0479683..34d46e25d610 100644
> > >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > >> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int
> > >> freq, unsigned long pixel_clk)>>
> > >>    return n;
> > >>
> > >>  }
> > >>
> > >> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> > >> +{
> > >> +  u8 aud_schnl_samplerate;
> > >> +  u8 aud_schnl_8;
> > >> +
> > >> +  /* These registers are on RK3288 using version 2.0a. */
> > >> +  if (hdmi->version != 0x200a)
> > >> +          return;
> > >
> > > Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > > SoCs ?
> >
> > After investigations, Amlogic sets these registers on their 2.0a version
> > aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
> > < 2.0a and > 2.0a IPs versions.
> >
> > Can you check on the Rockchip IP versions in RK3399 ?
> >
> > For reference, the HDMI 1.4a IP version allwinner setups is:
> > https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/vide
> > o/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539 (registers a
> > "scrambled" but a custom bit can reset to the original mapping, 0x1066 ...
> > 0x106f)
>
> For easier reading, here is similar, but annotated version: http://ix.io/1Ub6
> Check function bsp_hdmi_audio().
>
> Unless there is a special reason, you can just remove that check.
>

Thanks for the great reference.
I also see that I need to set the word length according to the desired
value passed by dw_hdmi_i2s_hw_params in dw-hdmi-i2s-audio.c.
Will fix in v2.

> Best regards,
> Jernej
>
> >
> > Neil
> >
> > >> +
> > >> +  switch (hdmi->sample_rate) {
> > >> +  case 32000:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> > >> +          break;
> > >> +  case 44100:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> > >> +          break;
> > >> +  case 48000:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> > >> +          break;
> > >> +  case 88200:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> > >> +          break;
> > >> +  case 96000:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> > >> +          break;
> > >> +  case 176400:
> > >> +          aud_schnl_samplerate =
> HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> > >> +          break;
> > >> +  case 192000:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> > >> +          break;
> > >> +  case 768000:
> > >> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> > >> +          break;
> > >> +  default:
> > >> +          dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)
> \n",
> > >> +                   hdmi->sample_rate);
> > >> +          return;
> > >> +  }
> > >> +
> > >> +  /* set channel status register */
> > >> +  hdmi_modb(hdmi, aud_schnl_samplerate,
> HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> > >> +            HDMI_FC_AUDSCHNLS7);
> > >> +
> > >> +  /*
> > >> +   * Set original frequency to be the same as frequency.
> > >> +   * Use one-complement value as stated in IEC60958-3 page 13.
> > >> +   */
> > >> +  aud_schnl_8 = (~aud_schnl_samplerate) <<
> > >> +                  HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> > >> +
> > >> +  /* This means word length is 16 bit. Refer to IEC60958-3 page 12.
> */
> > >> +  aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> > >> +
> > >> +  hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> > >> +}
> > >> +
> > >>
> > >>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> > >>
> > >>    unsigned long pixel_clk, unsigned int sample_rate)
> > >>
> > >>  {
> > >>
> > >> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi
> > >> *hdmi,>>
> > >>    hdmi->audio_cts = cts;
> > >>    hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> > >>    spin_unlock_irq(&hdmi->audio_lock);
> > >>
> > >> +
> > >> +  hdmi_set_schnl(hdmi);
> > >>
> > >>  }
> > >>
> > >>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> > >>
> > >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > >> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index
> > >> 6988f12d89d9..619ebc1c8354 100644
> > >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > >> @@ -158,6 +158,17 @@
> > >>
> > >>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> > >>  #define HDMI_FC_AUDSCONF                        0x1063
> > >>  #define HDMI_FC_AUDSSTAT                        0x1064
> > >>
> > >> +#define HDMI_FC_AUDSV                           0x1065
> > >> +#define HDMI_FC_AUDSU                           0x1066
> > >> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> > >> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> > >> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> > >> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> > >> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> > >> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> > >> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> > >> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> > >> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> > >>
> > >>  #define HDMI_FC_DATACH0FILL                     0x1070
> > >>  #define HDMI_FC_DATACH1FILL                     0x1071
> > >>  #define HDMI_FC_DATACH2FILL                     0x1072
> > >>
> > >> @@ -706,6 +717,15 @@ enum {
> > >>
> > >>  /* HDMI_FC_AUDSCHNLS7 field values */
> > >>
> > >>    HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> > >>    HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> > >>
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> > >> +  HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> > >>
> > >>  /* HDMI_FC_AUDSCHNLS8 field values */
> > >>
> > >>    HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
>
>
>
>
Russell King (Oracle) Sept. 4, 2019, 9:27 a.m. UTC | #8
On Wed, Sep 04, 2019 at 05:09:29PM +0800, Cheng-yi Chiang wrote:
> Hi,
> 
> On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
> >
> > Hi,
> >
> > On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> > > From: Yakir Yang <ykk@rock-chips.com>
> > >
> > > When transmitting IEC60985 linear PCM audio, we configure the
> > > Audio Sample Channel Status information of all the channel
> > > status bits in the IEC60958 frame.
> > > Refer to 60958-3 page 10 for frequency, original frequency, and
> > > wordlength setting.
> > >
> > > This fix the issue that audio does not come out on some monitors
> > > (e.g. LG 22CV241)
> > >
> > > Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > ---
> > >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> > >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> > >  2 files changed, 79 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > > index bd65d0479683..34d46e25d610 100644
> > > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > > @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
> > >       return n;
> > >  }
> > >
> > > +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> > > +{
> > > +     u8 aud_schnl_samplerate;
> > > +     u8 aud_schnl_8;
> > > +
> > > +     /* These registers are on RK3288 using version 2.0a. */
> > > +     if (hdmi->version != 0x200a)
> > > +             return;
> >
> > Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > SoCs ?
> >
> 
> In the original patch by Yakir,
> 
> https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
> have added this link in the "after the cut" note)
> 
> The fix is limited to version 2.0.
> Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
> I can not test 2.0a version on other SoCs.
> The databook I have at hand is 2.0a (not specific to RK3288) so I
> think all 2.0a should have this register.
> 
> As for other version like version 1.3 on iMX6, there is no such
> register, as stated by Russell
> 
> http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.

It's likely more to do with how the IP is configured rather than the
version.  The big difference between dw-hdmi used in iMX6 and elsewhere
is that iMX6 uses a built-in AHB audio interface and not I2S.  Elsewhere
uses I2S.

I2S does not have the capability to convey channel status information
(which is required by HDMI).  With AHB, it is encoded into the data in
memory.

So, I think this setup should be done in the I2S driver and not in the
core driver.
Neil Armstrong Sept. 4, 2019, 9:28 a.m. UTC | #9
Hi,

On 04/09/2019 11:09, Cheng-yi Chiang wrote:
> Hi,
> 
> On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
>>
>> Hi,
>>
>> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
>>> From: Yakir Yang <ykk@rock-chips.com>
>>>
>>> When transmitting IEC60985 linear PCM audio, we configure the
>>> Audio Sample Channel Status information of all the channel
>>> status bits in the IEC60958 frame.
>>> Refer to 60958-3 page 10 for frequency, original frequency, and
>>> wordlength setting.
>>>
>>> This fix the issue that audio does not come out on some monitors
>>> (e.g. LG 22CV241)
>>>
>>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
>>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
>>> ---
>>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
>>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
>>>  2 files changed, 79 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>> index bd65d0479683..34d46e25d610 100644
>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
>>>       return n;
>>>  }
>>>
>>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
>>> +{
>>> +     u8 aud_schnl_samplerate;
>>> +     u8 aud_schnl_8;
>>> +
>>> +     /* These registers are on RK3288 using version 2.0a. */
>>> +     if (hdmi->version != 0x200a)
>>> +             return;
>>
>> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
>> SoCs ?
>>
> 
> In the original patch by Yakir,
> 
> https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
> have added this link in the "after the cut" note)
> 
> The fix is limited to version 2.0.
> Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
> I can not test 2.0a version on other SoCs.
> The databook I have at hand is 2.0a (not specific to RK3288) so I
> think all 2.0a should have this register.
> 
> As for other version like version 1.3 on iMX6, there is no such
> register, as stated by Russell
> 
> http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.

Russell assumes the registers are not present on the iMX6 IP not having
the I2S registers, but they are present on the IPs configured with I2S
at any versions.

My databook version (1.40.a) specifies :

fc_audschnls0 to fc_audschnls8

```
When transmitting IEC60958 linear PCM audio, this registers allow to configure the channel status
information of all the channel status bits in the IEC60958 frame. For the moment this configuration is only
used when the I2S audio interface, General Purpose Audio (GPA), or AHB audio DMA (AHBAUDDMA)
interface is active (for S/PDIF interface this information comes from the stream).
```

But the databook Revision History shows these registers were present since version 1.10a.

I propose you remove the version check, but you only setup these registers when I2S is enabled:
(hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) until a AHBAUDDMA user needs this,
with a small comment explaining the situation.

Neil

> 
> So at least we should check the version.
> Maybe we can set the criteria as version 2.0 or above to make it a safe patch ?
> If there is the same need on other SoC with version < 2.0, it can be
> added later.
> Presumably, there will be databook of that version to help confirming
> this setting.
> 
> Thanks!
>>> +
>>> +     switch (hdmi->sample_rate) {
>>> +     case 32000:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
>>> +             break;
>>> +     case 44100:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
>>> +             break;
>>> +     case 48000:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
>>> +             break;
>>> +     case 88200:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
>>> +             break;
>>> +     case 96000:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
>>> +             break;
>>> +     case 176400:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
>>> +             break;
>>> +     case 192000:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
>>> +             break;
>>> +     case 768000:
>>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
>>> +             break;
>>> +     default:
>>> +             dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
>>> +                      hdmi->sample_rate);
>>> +             return;
>>> +     }
>>> +
>>> +     /* set channel status register */
>>> +     hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
>>> +               HDMI_FC_AUDSCHNLS7);
>>> +
>>> +     /*
>>> +      * Set original frequency to be the same as frequency.
>>> +      * Use one-complement value as stated in IEC60958-3 page 13.
>>> +      */
>>> +     aud_schnl_8 = (~aud_schnl_samplerate) <<
>>> +                     HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
>>> +
>>> +     /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
>>> +     aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
>>> +
>>> +     hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
>>> +}
>>> +
>>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>>>       unsigned long pixel_clk, unsigned int sample_rate)
>>>  {
>>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>>>       hdmi->audio_cts = cts;
>>>       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
>>>       spin_unlock_irq(&hdmi->audio_lock);
>>> +
>>> +     hdmi_set_schnl(hdmi);
>>>  }
>>>
>>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>>> index 6988f12d89d9..619ebc1c8354 100644
>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
>>> @@ -158,6 +158,17 @@
>>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
>>>  #define HDMI_FC_AUDSCONF                        0x1063
>>>  #define HDMI_FC_AUDSSTAT                        0x1064
>>> +#define HDMI_FC_AUDSV                           0x1065
>>> +#define HDMI_FC_AUDSU                           0x1066
>>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
>>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
>>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
>>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
>>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
>>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
>>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
>>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
>>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
>>>  #define HDMI_FC_DATACH0FILL                     0x1070
>>>  #define HDMI_FC_DATACH1FILL                     0x1071
>>>  #define HDMI_FC_DATACH2FILL                     0x1072
>>> @@ -706,6 +717,15 @@ enum {
>>>  /* HDMI_FC_AUDSCHNLS7 field values */
>>>       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
>>>       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
>>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
>>>
>>>  /* HDMI_FC_AUDSCHNLS8 field values */
>>>       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
>>>
>>
Cheng-yi Chiang Sept. 4, 2019, 9:35 a.m. UTC | #10
On Wed, Sep 4, 2019 at 4:33 AM Jonas Karlman <jonas@kwiboo.se> wrote:
>
> On 2019-09-03 20:08, Jernej Škrabec wrote:
> > Hi!
> >
> > Dne torek, 03. september 2019 ob 20:00:33 CEST je Neil Armstrong napisal(a):
> >> Hi,
> >>
> >> Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
> >>> Hi,
> >>>
> >>> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> >>>> From: Yakir Yang <ykk@rock-chips.com>
> >>>>
> >>>> When transmitting IEC60985 linear PCM audio, we configure the
> >>>> Audio Sample Channel Status information of all the channel
> >>>> status bits in the IEC60958 frame.
> >>>> Refer to 60958-3 page 10 for frequency, original frequency, and
> >>>> wordlength setting.
> >>>>
> >>>> This fix the issue that audio does not come out on some monitors
> >>>> (e.g. LG 22CV241)
> >>>>
> >>>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> >>>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> >>>> ---
> >>>>
> >>>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> >>>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> >>>>  2 files changed, 79 insertions(+)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >>>> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index
> >>>> bd65d0479683..34d46e25d610 100644
> >>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >>>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int
> >>>> freq, unsigned long pixel_clk)>>
> >>>>    return n;
> >>>>
> >>>>  }
> >>>>
> >>>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> >>>> +{
> >>>> +  u8 aud_schnl_samplerate;
> >>>> +  u8 aud_schnl_8;
> >>>> +
> >>>> +  /* These registers are on RK3288 using version 2.0a. */
> >>>> +  if (hdmi->version != 0x200a)
> >>>> +          return;
> >>> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> >>> SoCs ?
> >> After investigations, Amlogic sets these registers on their 2.0a version
> >> aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
> >> < 2.0a and > 2.0a IPs versions.
> >>
> >> Can you check on the Rockchip IP versions in RK3399 ?
> >>
> >> For reference, the HDMI 1.4a IP version allwinner setups is:
> >> https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/vide
> >> o/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539 (registers a
> >> "scrambled" but a custom bit can reset to the original mapping, 0x1066 ...
> >> 0x106f)
> > For easier reading, here is similar, but annotated version: http://ix.io/1Ub6
> > Check function bsp_hdmi_audio().
> >
> > Unless there is a special reason, you can just remove that check.
>
> Agree, this check should not be needed, AUDSCHNLS7 used to be configured in my old
> multi-channel patches that have seen lot of testing on Amlogic, Allwinner and Rockchip SoCs.
>

As stated in previous mail, I will modify the check for version >=1.4
since I know that 1.3 does not have such register, at least on iMX6.

> >
> > Best regards,
> > Jernej
> >
> >> Neil
> >>
> >>>> +
> >>>> +  switch (hdmi->sample_rate) {
> >>>> +  case 32000:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> >>>> +          break;
> >>>> +  case 44100:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> >>>> +          break;
> >>>> +  case 48000:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> >>>> +          break;
> >>>> +  case 88200:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> >>>> +          break;
> >>>> +  case 96000:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> >>>> +          break;
> >>>> +  case 176400:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> >>>> +          break;
> >>>> +  case 192000:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> >>>> +          break;
> >>>> +  case 768000:
> >>>> +          aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> >>>> +          break;
> >>>> +  default:
> >>>> +          dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> >>>> +                   hdmi->sample_rate);
> >>>> +          return;
> >>>> +  }
> >>>> +
> >>>> +  /* set channel status register */
> >>>> +  hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> >>>> +            HDMI_FC_AUDSCHNLS7);
> >>>> +
> >>>> +  /*
> >>>> +   * Set original frequency to be the same as frequency.
> >>>> +   * Use one-complement value as stated in IEC60958-3 page 13.
> >>>> +   */
> >>>> +  aud_schnl_8 = (~aud_schnl_samplerate) <<
> >>>> +                  HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> >>>> +
> >>>> +  /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> >>>> +  aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
>
> This looks wrong, user can use 16 and 24 bit wide audio streams.
>

Thanks for spotting this issue.
I will fix it in v2 (following how http://ix.io/1Ub6 set it for 16 and 24 bit)

> >>>> +
> >>>> +  hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> >>>> +}
> >>>> +
> >>>>
> >>>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >>>>
> >>>>    unsigned long pixel_clk, unsigned int sample_rate)
> >>>>
> >>>>  {
> >>>>
> >>>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi
> >>>> *hdmi,>>
> >>>>    hdmi->audio_cts = cts;
> >>>>    hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> >>>>    spin_unlock_irq(&hdmi->audio_lock);
> >>>>
> >>>> +
> >>>> +  hdmi_set_schnl(hdmi);
>
> I will suggest this function is called from or merged with dw_hdmi_set_sample_rate().
> Similar to how AUDSCONF and AUDICONF0 is configured from dw_hdmi_set_channel_count().
>

I see. I think it will make sense to add a function
set_channel_status() for dw-hdmi-i2s-audio.c to call,
since this function is more than just setting rate.
Will fix in v2.

Thanks!

> Regards,
> Jonas
>
> >>>>
> >>>>  }
> >>>>
> >>>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >>>> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index
> >>>> 6988f12d89d9..619ebc1c8354 100644
> >>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >>>> @@ -158,6 +158,17 @@
> >>>>
> >>>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> >>>>  #define HDMI_FC_AUDSCONF                        0x1063
> >>>>  #define HDMI_FC_AUDSSTAT                        0x1064
> >>>>
> >>>> +#define HDMI_FC_AUDSV                           0x1065
> >>>> +#define HDMI_FC_AUDSU                           0x1066
> >>>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> >>>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> >>>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> >>>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> >>>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> >>>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> >>>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> >>>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> >>>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> >>>>
> >>>>  #define HDMI_FC_DATACH0FILL                     0x1070
> >>>>  #define HDMI_FC_DATACH1FILL                     0x1071
> >>>>  #define HDMI_FC_DATACH2FILL                     0x1072
> >>>>
> >>>> @@ -706,6 +717,15 @@ enum {
> >>>>
> >>>>  /* HDMI_FC_AUDSCHNLS7 field values */
> >>>>
> >>>>    HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> >>>>    HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> >>>>
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> >>>> +  HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> >>>>
> >>>>  /* HDMI_FC_AUDSCHNLS8 field values */
> >>>>
> >>>>    HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
Cheng-yi Chiang Sept. 4, 2019, 9:45 a.m. UTC | #11
On Wed, Sep 4, 2019 at 5:28 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Hi,
>
> On 04/09/2019 11:09, Cheng-yi Chiang wrote:
> > Hi,
> >
> > On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
> >>
> >> Hi,
> >>
> >> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> >>> From: Yakir Yang <ykk@rock-chips.com>
> >>>
> >>> When transmitting IEC60985 linear PCM audio, we configure the
> >>> Audio Sample Channel Status information of all the channel
> >>> status bits in the IEC60958 frame.
> >>> Refer to 60958-3 page 10 for frequency, original frequency, and
> >>> wordlength setting.
> >>>
> >>> This fix the issue that audio does not come out on some monitors
> >>> (e.g. LG 22CV241)
> >>>
> >>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> >>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> >>> ---
> >>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> >>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> >>>  2 files changed, 79 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >>> index bd65d0479683..34d46e25d610 100644
> >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
> >>>       return n;
> >>>  }
> >>>
> >>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> >>> +{
> >>> +     u8 aud_schnl_samplerate;
> >>> +     u8 aud_schnl_8;
> >>> +
> >>> +     /* These registers are on RK3288 using version 2.0a. */
> >>> +     if (hdmi->version != 0x200a)
> >>> +             return;
> >>
> >> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> >> SoCs ?
> >>
> >
> > In the original patch by Yakir,
> >
> > https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
> > have added this link in the "after the cut" note)
> >
> > The fix is limited to version 2.0.
> > Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
> > I can not test 2.0a version on other SoCs.
> > The databook I have at hand is 2.0a (not specific to RK3288) so I
> > think all 2.0a should have this register.
> >
> > As for other version like version 1.3 on iMX6, there is no such
> > register, as stated by Russell
> >
> > http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.
>
> Russell assumes the registers are not present on the iMX6 IP not having
> the I2S registers, but they are present on the IPs configured with I2S
> at any versions.

I see. Thanks for the check.

>
> My databook version (1.40.a) specifies :
>
> fc_audschnls0 to fc_audschnls8
>
> ```
> When transmitting IEC60958 linear PCM audio, this registers allow to configure the channel status
> information of all the channel status bits in the IEC60958 frame. For the moment this configuration is only
> used when the I2S audio interface, General Purpose Audio (GPA), or AHB audio DMA (AHBAUDDMA)
> interface is active (for S/PDIF interface this information comes from the stream).
> ```
>
> But the databook Revision History shows these registers were present since version 1.10a.
>
> I propose you remove the version check, but you only setup these registers when I2S is enabled:
> (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) until a AHBAUDDMA user needs this,
> with a small comment explaining the situation.

I see. Sound like a good plan.
In sum, I will add
set_channel_status()
in dw_hdmi.c
And in the beginning of this function,
check it is using I2S
 (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S)
with a comment explaining the situation.

And let dw-hdmi-audio-i2s dw_hdmi_i2s_hw_params() to call this
function after dw_hdmi_set_sample_rate, with word length (or
sample_bit) passed it as argument.
I have not tested setting this register here as in the original patch
it was set in hdmi_set_clk_regenerator.
I will test it and update in my v2.

Thanks again to everyone for the prompt reply and help.

>
> Neil
>
> >
> > So at least we should check the version.
> > Maybe we can set the criteria as version 2.0 or above to make it a safe patch ?
> > If there is the same need on other SoC with version < 2.0, it can be
> > added later.
> > Presumably, there will be databook of that version to help confirming
> > this setting.
> >
> > Thanks!
> >>> +
> >>> +     switch (hdmi->sample_rate) {
> >>> +     case 32000:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> >>> +             break;
> >>> +     case 44100:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> >>> +             break;
> >>> +     case 48000:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> >>> +             break;
> >>> +     case 88200:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> >>> +             break;
> >>> +     case 96000:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> >>> +             break;
> >>> +     case 176400:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> >>> +             break;
> >>> +     case 192000:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> >>> +             break;
> >>> +     case 768000:
> >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> >>> +             break;
> >>> +     default:
> >>> +             dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> >>> +                      hdmi->sample_rate);
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     /* set channel status register */
> >>> +     hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> >>> +               HDMI_FC_AUDSCHNLS7);
> >>> +
> >>> +     /*
> >>> +      * Set original frequency to be the same as frequency.
> >>> +      * Use one-complement value as stated in IEC60958-3 page 13.
> >>> +      */
> >>> +     aud_schnl_8 = (~aud_schnl_samplerate) <<
> >>> +                     HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> >>> +
> >>> +     /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> >>> +     aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> >>> +
> >>> +     hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> >>> +}
> >>> +
> >>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >>>       unsigned long pixel_clk, unsigned int sample_rate)
> >>>  {
> >>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >>>       hdmi->audio_cts = cts;
> >>>       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> >>>       spin_unlock_irq(&hdmi->audio_lock);
> >>> +
> >>> +     hdmi_set_schnl(hdmi);
> >>>  }
> >>>
> >>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >>> index 6988f12d89d9..619ebc1c8354 100644
> >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> >>> @@ -158,6 +158,17 @@
> >>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> >>>  #define HDMI_FC_AUDSCONF                        0x1063
> >>>  #define HDMI_FC_AUDSSTAT                        0x1064
> >>> +#define HDMI_FC_AUDSV                           0x1065
> >>> +#define HDMI_FC_AUDSU                           0x1066
> >>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> >>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> >>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> >>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> >>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> >>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> >>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> >>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> >>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> >>>  #define HDMI_FC_DATACH0FILL                     0x1070
> >>>  #define HDMI_FC_DATACH1FILL                     0x1071
> >>>  #define HDMI_FC_DATACH2FILL                     0x1072
> >>> @@ -706,6 +717,15 @@ enum {
> >>>  /* HDMI_FC_AUDSCHNLS7 field values */
> >>>       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> >>>       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> >>>
> >>>  /* HDMI_FC_AUDSCHNLS8 field values */
> >>>       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
> >>>
> >>
>
Russell King (Oracle) Sept. 4, 2019, 10:31 a.m. UTC | #12
On Wed, Sep 04, 2019 at 05:45:20PM +0800, Cheng-yi Chiang wrote:
> On Wed, Sep 4, 2019 at 5:28 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
> >
> > Hi,
> >
> > On 04/09/2019 11:09, Cheng-yi Chiang wrote:
> > > Hi,
> > >
> > > On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
> > >>
> > >> Hi,
> > >>
> > >> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> > >>> From: Yakir Yang <ykk@rock-chips.com>
> > >>>
> > >>> When transmitting IEC60985 linear PCM audio, we configure the
> > >>> Audio Sample Channel Status information of all the channel
> > >>> status bits in the IEC60958 frame.
> > >>> Refer to 60958-3 page 10 for frequency, original frequency, and
> > >>> wordlength setting.
> > >>>
> > >>> This fix the issue that audio does not come out on some monitors
> > >>> (e.g. LG 22CV241)
> > >>>
> > >>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> > >>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > >>> ---
> > >>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> > >>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> > >>>  2 files changed, 79 insertions(+)
> > >>>
> > >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > >>> index bd65d0479683..34d46e25d610 100644
> > >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > >>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
> > >>>       return n;
> > >>>  }
> > >>>
> > >>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> > >>> +{
> > >>> +     u8 aud_schnl_samplerate;
> > >>> +     u8 aud_schnl_8;
> > >>> +
> > >>> +     /* These registers are on RK3288 using version 2.0a. */
> > >>> +     if (hdmi->version != 0x200a)
> > >>> +             return;
> > >>
> > >> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > >> SoCs ?
> > >>
> > >
> > > In the original patch by Yakir,
> > >
> > > https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
> > > have added this link in the "after the cut" note)
> > >
> > > The fix is limited to version 2.0.
> > > Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
> > > I can not test 2.0a version on other SoCs.
> > > The databook I have at hand is 2.0a (not specific to RK3288) so I
> > > think all 2.0a should have this register.
> > >
> > > As for other version like version 1.3 on iMX6, there is no such
> > > register, as stated by Russell
> > >
> > > http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.
> >
> > Russell assumes the registers are not present on the iMX6 IP not having
> > the I2S registers, but they are present on the IPs configured with I2S
> > at any versions.
> 
> I see. Thanks for the check.
> 
> >
> > My databook version (1.40.a) specifies :
> >
> > fc_audschnls0 to fc_audschnls8
> >
> > ```
> > When transmitting IEC60958 linear PCM audio, this registers allow to configure the channel status
> > information of all the channel status bits in the IEC60958 frame. For the moment this configuration is only
> > used when the I2S audio interface, General Purpose Audio (GPA), or AHB audio DMA (AHBAUDDMA)
> > interface is active (for S/PDIF interface this information comes from the stream).
> > ```
> >
> > But the databook Revision History shows these registers were present since version 1.10a.
> >
> > I propose you remove the version check, but you only setup these registers when I2S is enabled:
> > (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) until a AHBAUDDMA user needs this,
> > with a small comment explaining the situation.
> 
> I see. Sound like a good plan.
> In sum, I will add
> set_channel_status()
> in dw_hdmi.c
> And in the beginning of this function,
> check it is using I2S
>  (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S)
> with a comment explaining the situation.
> 
> And let dw-hdmi-audio-i2s dw_hdmi_i2s_hw_params() to call this
> function after dw_hdmi_set_sample_rate, with word length (or
> sample_bit) passed it as argument.

If you're going to do it this way, there's little point having the
check.  The dw-hdmi-audio-i2s device will only be created if that
ID bit is already set.  So, provided set_channel_status() (which
should probably be dw_hdmi_set_channel_status()) is only called from
the I2S driver, then everything should be fine without such a check.
However, it is worth noting in the docbook comments above the function
that it is only for I2S setups.

> I have not tested setting this register here as in the original patch
> it was set in hdmi_set_clk_regenerator.
> I will test it and update in my v2.
> 
> Thanks again to everyone for the prompt reply and help.
> 
> >
> > Neil
> >
> > >
> > > So at least we should check the version.
> > > Maybe we can set the criteria as version 2.0 or above to make it a safe patch ?
> > > If there is the same need on other SoC with version < 2.0, it can be
> > > added later.
> > > Presumably, there will be databook of that version to help confirming
> > > this setting.
> > >
> > > Thanks!
> > >>> +
> > >>> +     switch (hdmi->sample_rate) {
> > >>> +     case 32000:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> > >>> +             break;
> > >>> +     case 44100:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> > >>> +             break;
> > >>> +     case 48000:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> > >>> +             break;
> > >>> +     case 88200:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> > >>> +             break;
> > >>> +     case 96000:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> > >>> +             break;
> > >>> +     case 176400:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> > >>> +             break;
> > >>> +     case 192000:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> > >>> +             break;
> > >>> +     case 768000:
> > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> > >>> +             break;
> > >>> +     default:
> > >>> +             dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> > >>> +                      hdmi->sample_rate);
> > >>> +             return;
> > >>> +     }
> > >>> +
> > >>> +     /* set channel status register */
> > >>> +     hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> > >>> +               HDMI_FC_AUDSCHNLS7);
> > >>> +
> > >>> +     /*
> > >>> +      * Set original frequency to be the same as frequency.
> > >>> +      * Use one-complement value as stated in IEC60958-3 page 13.
> > >>> +      */
> > >>> +     aud_schnl_8 = (~aud_schnl_samplerate) <<
> > >>> +                     HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> > >>> +
> > >>> +     /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> > >>> +     aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> > >>> +
> > >>> +     hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> > >>> +}
> > >>> +
> > >>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> > >>>       unsigned long pixel_clk, unsigned int sample_rate)
> > >>>  {
> > >>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> > >>>       hdmi->audio_cts = cts;
> > >>>       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> > >>>       spin_unlock_irq(&hdmi->audio_lock);
> > >>> +
> > >>> +     hdmi_set_schnl(hdmi);
> > >>>  }
> > >>>
> > >>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> > >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > >>> index 6988f12d89d9..619ebc1c8354 100644
> > >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > >>> @@ -158,6 +158,17 @@
> > >>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> > >>>  #define HDMI_FC_AUDSCONF                        0x1063
> > >>>  #define HDMI_FC_AUDSSTAT                        0x1064
> > >>> +#define HDMI_FC_AUDSV                           0x1065
> > >>> +#define HDMI_FC_AUDSU                           0x1066
> > >>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> > >>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> > >>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> > >>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> > >>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> > >>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> > >>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> > >>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> > >>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> > >>>  #define HDMI_FC_DATACH0FILL                     0x1070
> > >>>  #define HDMI_FC_DATACH1FILL                     0x1071
> > >>>  #define HDMI_FC_DATACH2FILL                     0x1072
> > >>> @@ -706,6 +717,15 @@ enum {
> > >>>  /* HDMI_FC_AUDSCHNLS7 field values */
> > >>>       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> > >>>       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> > >>>
> > >>>  /* HDMI_FC_AUDSCHNLS8 field values */
> > >>>       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
> > >>>
> > >>
> >
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
Cheng-yi Chiang Sept. 4, 2019, 10:52 a.m. UTC | #13
On Wed, Sep 4, 2019 at 6:32 PM Russell King - ARM Linux admin
<linux@armlinux.org.uk> wrote:
>
> On Wed, Sep 04, 2019 at 05:45:20PM +0800, Cheng-yi Chiang wrote:
> > On Wed, Sep 4, 2019 at 5:28 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
> > >
> > > Hi,
> > >
> > > On 04/09/2019 11:09, Cheng-yi Chiang wrote:
> > > > Hi,
> > > >
> > > > On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
> > > >>
> > > >> Hi,
> > > >>
> > > >> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> > > >>> From: Yakir Yang <ykk@rock-chips.com>
> > > >>>
> > > >>> When transmitting IEC60985 linear PCM audio, we configure the
> > > >>> Audio Sample Channel Status information of all the channel
> > > >>> status bits in the IEC60958 frame.
> > > >>> Refer to 60958-3 page 10 for frequency, original frequency, and
> > > >>> wordlength setting.
> > > >>>
> > > >>> This fix the issue that audio does not come out on some monitors
> > > >>> (e.g. LG 22CV241)
> > > >>>
> > > >>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> > > >>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > >>> ---
> > > >>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++++++++++++++++++++++
> > > >>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 ++++++++
> > > >>>  2 files changed, 79 insertions(+)
> > > >>>
> > > >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > > >>> index bd65d0479683..34d46e25d610 100644
> > > >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > > >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > > >>> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
> > > >>>       return n;
> > > >>>  }
> > > >>>
> > > >>> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> > > >>> +{
> > > >>> +     u8 aud_schnl_samplerate;
> > > >>> +     u8 aud_schnl_8;
> > > >>> +
> > > >>> +     /* These registers are on RK3288 using version 2.0a. */
> > > >>> +     if (hdmi->version != 0x200a)
> > > >>> +             return;
> > > >>
> > > >> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > > >> SoCs ?
> > > >>
> > > >
> > > > In the original patch by Yakir,
> > > >
> > > > https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
> > > > have added this link in the "after the cut" note)
> > > >
> > > > The fix is limited to version 2.0.
> > > > Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
> > > > I can not test 2.0a version on other SoCs.
> > > > The databook I have at hand is 2.0a (not specific to RK3288) so I
> > > > think all 2.0a should have this register.
> > > >
> > > > As for other version like version 1.3 on iMX6, there is no such
> > > > register, as stated by Russell
> > > >
> > > > http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.
> > >
> > > Russell assumes the registers are not present on the iMX6 IP not having
> > > the I2S registers, but they are present on the IPs configured with I2S
> > > at any versions.
> >
> > I see. Thanks for the check.
> >
> > >
> > > My databook version (1.40.a) specifies :
> > >
> > > fc_audschnls0 to fc_audschnls8
> > >
> > > ```
> > > When transmitting IEC60958 linear PCM audio, this registers allow to configure the channel status
> > > information of all the channel status bits in the IEC60958 frame. For the moment this configuration is only
> > > used when the I2S audio interface, General Purpose Audio (GPA), or AHB audio DMA (AHBAUDDMA)
> > > interface is active (for S/PDIF interface this information comes from the stream).
> > > ```
> > >
> > > But the databook Revision History shows these registers were present since version 1.10a.
> > >
> > > I propose you remove the version check, but you only setup these registers when I2S is enabled:
> > > (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) until a AHBAUDDMA user needs this,
> > > with a small comment explaining the situation.
> >
> > I see. Sound like a good plan.
> > In sum, I will add
> > set_channel_status()
> > in dw_hdmi.c
> > And in the beginning of this function,
> > check it is using I2S
> >  (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S)
> > with a comment explaining the situation.
> >
> > And let dw-hdmi-audio-i2s dw_hdmi_i2s_hw_params() to call this
> > function after dw_hdmi_set_sample_rate, with word length (or
> > sample_bit) passed it as argument.
>
> If you're going to do it this way, there's little point having the
> check.  The dw-hdmi-audio-i2s device will only be created if that
> ID bit is already set.  So, provided set_channel_status() (which
> should probably be dw_hdmi_set_channel_status()) is only called from
> the I2S driver, then everything should be fine without such a check.
> However, it is worth noting in the docbook comments above the function
> that it is only for I2S setups.
>
I see. Yes it is simpler.
Thanks for the suggestion!
Will fix in v2.


> > I have not tested setting this register here as in the original patch
> > it was set in hdmi_set_clk_regenerator.
> > I will test it and update in my v2.
> >
> > Thanks again to everyone for the prompt reply and help.
> >
> > >
> > > Neil
> > >
> > > >
> > > > So at least we should check the version.
> > > > Maybe we can set the criteria as version 2.0 or above to make it a safe patch ?
> > > > If there is the same need on other SoC with version < 2.0, it can be
> > > > added later.
> > > > Presumably, there will be databook of that version to help confirming
> > > > this setting.
> > > >
> > > > Thanks!
> > > >>> +
> > > >>> +     switch (hdmi->sample_rate) {
> > > >>> +     case 32000:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> > > >>> +             break;
> > > >>> +     case 44100:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> > > >>> +             break;
> > > >>> +     case 48000:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> > > >>> +             break;
> > > >>> +     case 88200:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> > > >>> +             break;
> > > >>> +     case 96000:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> > > >>> +             break;
> > > >>> +     case 176400:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> > > >>> +             break;
> > > >>> +     case 192000:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> > > >>> +             break;
> > > >>> +     case 768000:
> > > >>> +             aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> > > >>> +             break;
> > > >>> +     default:
> > > >>> +             dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> > > >>> +                      hdmi->sample_rate);
> > > >>> +             return;
> > > >>> +     }
> > > >>> +
> > > >>> +     /* set channel status register */
> > > >>> +     hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> > > >>> +               HDMI_FC_AUDSCHNLS7);
> > > >>> +
> > > >>> +     /*
> > > >>> +      * Set original frequency to be the same as frequency.
> > > >>> +      * Use one-complement value as stated in IEC60958-3 page 13.
> > > >>> +      */
> > > >>> +     aud_schnl_8 = (~aud_schnl_samplerate) <<
> > > >>> +                     HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> > > >>> +
> > > >>> +     /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> > > >>> +     aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> > > >>> +
> > > >>> +     hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> > > >>> +}
> > > >>> +
> > > >>>  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> > > >>>       unsigned long pixel_clk, unsigned int sample_rate)
> > > >>>  {
> > > >>> @@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> > > >>>       hdmi->audio_cts = cts;
> > > >>>       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> > > >>>       spin_unlock_irq(&hdmi->audio_lock);
> > > >>> +
> > > >>> +     hdmi_set_schnl(hdmi);
> > > >>>  }
> > > >>>
> > > >>>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> > > >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > > >>> index 6988f12d89d9..619ebc1c8354 100644
> > > >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > > >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> > > >>> @@ -158,6 +158,17 @@
> > > >>>  #define HDMI_FC_SPDDEVICEINF                    0x1062
> > > >>>  #define HDMI_FC_AUDSCONF                        0x1063
> > > >>>  #define HDMI_FC_AUDSSTAT                        0x1064
> > > >>> +#define HDMI_FC_AUDSV                           0x1065
> > > >>> +#define HDMI_FC_AUDSU                           0x1066
> > > >>> +#define HDMI_FC_AUDSCHNLS0                      0x1067
> > > >>> +#define HDMI_FC_AUDSCHNLS1                      0x1068
> > > >>> +#define HDMI_FC_AUDSCHNLS2                      0x1069
> > > >>> +#define HDMI_FC_AUDSCHNLS3                      0x106a
> > > >>> +#define HDMI_FC_AUDSCHNLS4                      0x106b
> > > >>> +#define HDMI_FC_AUDSCHNLS5                      0x106c
> > > >>> +#define HDMI_FC_AUDSCHNLS6                      0x106d
> > > >>> +#define HDMI_FC_AUDSCHNLS7                      0x106e
> > > >>> +#define HDMI_FC_AUDSCHNLS8                      0x106f
> > > >>>  #define HDMI_FC_DATACH0FILL                     0x1070
> > > >>>  #define HDMI_FC_DATACH1FILL                     0x1071
> > > >>>  #define HDMI_FC_DATACH2FILL                     0x1072
> > > >>> @@ -706,6 +717,15 @@ enum {
> > > >>>  /* HDMI_FC_AUDSCHNLS7 field values */
> > > >>>       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
> > > >>>       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
> > > >>> +     HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
> > > >>>
> > > >>>  /* HDMI_FC_AUDSCHNLS8 field values */
> > > >>>       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
> > > >>>
> > > >>
> > >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
>
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
> According to speedtest.net: 11.9Mbps down 500kbps up
diff mbox series

Patch

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index bd65d0479683..34d46e25d610 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -582,6 +582,63 @@  static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
 	return n;
 }
 
+static void hdmi_set_schnl(struct dw_hdmi *hdmi)
+{
+	u8 aud_schnl_samplerate;
+	u8 aud_schnl_8;
+
+	/* These registers are on RK3288 using version 2.0a. */
+	if (hdmi->version != 0x200a)
+		return;
+
+	switch (hdmi->sample_rate) {
+	case 32000:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
+		break;
+	case 44100:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
+		break;
+	case 48000:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
+		break;
+	case 88200:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
+		break;
+	case 96000:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
+		break;
+	case 176400:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
+		break;
+	case 192000:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
+		break;
+	case 768000:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
+		break;
+	default:
+		dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
+			 hdmi->sample_rate);
+		return;
+	}
+
+	/* set channel status register */
+	hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
+		  HDMI_FC_AUDSCHNLS7);
+
+	/*
+	 * Set original frequency to be the same as frequency.
+	 * Use one-complement value as stated in IEC60958-3 page 13.
+	 */
+	aud_schnl_8 = (~aud_schnl_samplerate) <<
+			HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
+
+	/* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
+	aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
+
+	hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
+}
+
 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 	unsigned long pixel_clk, unsigned int sample_rate)
 {
@@ -620,6 +677,8 @@  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 	hdmi->audio_cts = cts;
 	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
 	spin_unlock_irq(&hdmi->audio_lock);
+
+	hdmi_set_schnl(hdmi);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
index 6988f12d89d9..619ebc1c8354 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
@@ -158,6 +158,17 @@ 
 #define HDMI_FC_SPDDEVICEINF                    0x1062
 #define HDMI_FC_AUDSCONF                        0x1063
 #define HDMI_FC_AUDSSTAT                        0x1064
+#define HDMI_FC_AUDSV                           0x1065
+#define HDMI_FC_AUDSU                           0x1066
+#define HDMI_FC_AUDSCHNLS0                      0x1067
+#define HDMI_FC_AUDSCHNLS1                      0x1068
+#define HDMI_FC_AUDSCHNLS2                      0x1069
+#define HDMI_FC_AUDSCHNLS3                      0x106a
+#define HDMI_FC_AUDSCHNLS4                      0x106b
+#define HDMI_FC_AUDSCHNLS5                      0x106c
+#define HDMI_FC_AUDSCHNLS6                      0x106d
+#define HDMI_FC_AUDSCHNLS7                      0x106e
+#define HDMI_FC_AUDSCHNLS8                      0x106f
 #define HDMI_FC_DATACH0FILL                     0x1070
 #define HDMI_FC_DATACH1FILL                     0x1071
 #define HDMI_FC_DATACH2FILL                     0x1072
@@ -706,6 +717,15 @@  enum {
 /* HDMI_FC_AUDSCHNLS7 field values */
 	HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
 	HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
 
 /* HDMI_FC_AUDSCHNLS8 field values */
 	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,