diff mbox series

[v2] ALSA: hda: Fix Nvidia dp infoframe

Message ID 20220913065818.13015-1-mkumard@nvidia.com (mailing list archive)
State New, archived
Headers show
Series [v2] ALSA: hda: Fix Nvidia dp infoframe | expand

Commit Message

Mohan Kumar Sept. 13, 2022, 6:58 a.m. UTC
Nvidia HDA HW expects infoframe data bytes order same for both
HDMI and DP i.e infoframe data starts from 5th bytes offset. As
dp infoframe structure has 4th byte as valid infoframe data, use
hdmi infoframe structure for nvidia dp infoframe to match HW behvaior.

Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
---
 sound/pci/hda/patch_hdmi.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

Comments

Takashi Iwai Sept. 13, 2022, 7:15 a.m. UTC | #1
On Tue, 13 Sep 2022 08:58:18 +0200,
Mohan Kumar wrote:
> 
> Nvidia HDA HW expects infoframe data bytes order same for both
> HDMI and DP i.e infoframe data starts from 5th bytes offset. As
> dp infoframe structure has 4th byte as valid infoframe data, use
> hdmi infoframe structure for nvidia dp infoframe to match HW behvaior.
> 
> Signed-off-by: Mohan Kumar <mkumard@nvidia.com>

Aha, so this affects on all Nvidia devices, not only on Tegra, but
also on PC?  Then we should put cc-to-stable definitely.

(No need to resend, I can put it locally.)


Takashi

> ---
>  sound/pci/hda/patch_hdmi.c | 23 +++++++++++++++++++----
>  1 file changed, 19 insertions(+), 4 deletions(-)
> 
> diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
> index 6c209cd26c0c..9127dd1b1a9c 100644
> --- a/sound/pci/hda/patch_hdmi.c
> +++ b/sound/pci/hda/patch_hdmi.c
> @@ -170,6 +170,8 @@ struct hdmi_spec {
>  	bool dyn_pcm_no_legacy;
>  	/* hdmi interrupt trigger control flag for Nvidia codec */
>  	bool hdmi_intr_trig_ctrl;
> +	bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
> +
>  	bool intel_hsw_fixup;	/* apply Intel platform-specific fixups */
>  	/*
>  	 * Non-generic VIA/NVIDIA specific
> @@ -679,15 +681,24 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
>  				     int ca, int active_channels,
>  				     int conn_type)
>  {
> +	struct hdmi_spec *spec = codec->spec;
>  	union audio_infoframe ai;
>  
>  	memset(&ai, 0, sizeof(ai));
> -	if (conn_type == 0) { /* HDMI */
> +	if ((conn_type == 0) || /* HDMI */
> +		/* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */
> +		(conn_type == 1 && spec->nv_dp_workaround)) {
>  		struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
>  
> -		hdmi_ai->type		= 0x84;
> -		hdmi_ai->ver		= 0x01;
> -		hdmi_ai->len		= 0x0a;
> +		if (conn_type == 0) { /* HDMI */
> +			hdmi_ai->type		= 0x84;
> +			hdmi_ai->ver		= 0x01;
> +			hdmi_ai->len		= 0x0a;
> +		} else {/* Nvidia DP */
> +			hdmi_ai->type		= 0x84;
> +			hdmi_ai->ver		= 0x1b;
> +			hdmi_ai->len		= 0x11 << 2;
> +		}
>  		hdmi_ai->CC02_CT47	= active_channels - 1;
>  		hdmi_ai->CA		= ca;
>  		hdmi_checksum_audio_infoframe(hdmi_ai);
> @@ -3617,6 +3628,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
>  	spec->pcm_playback.rates = SUPPORTED_RATES;
>  	spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
>  	spec->pcm_playback.formats = SUPPORTED_FORMATS;
> +	spec->nv_dp_workaround = true;
>  	return 0;
>  }
>  
> @@ -3756,6 +3768,7 @@ static int patch_nvhdmi(struct hda_codec *codec)
>  	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
>  		nvhdmi_chmap_cea_alloc_validate_get_type;
>  	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
> +	spec->nv_dp_workaround = true;
>  
>  	codec->link_down_at_suspend = 1;
>  
> @@ -3779,6 +3792,7 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec)
>  	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
>  		nvhdmi_chmap_cea_alloc_validate_get_type;
>  	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
> +	spec->nv_dp_workaround = true;
>  
>  	codec->link_down_at_suspend = 1;
>  
> @@ -3992,6 +4006,7 @@ static int tegra_hdmi_init(struct hda_codec *codec)
>  	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
>  		nvhdmi_chmap_cea_alloc_validate_get_type;
>  	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
> +	spec->nv_dp_workaround = true;
>  
>  	return 0;
>  }
> -- 
> 2.17.1
>
Mohan Kumar Sept. 13, 2022, 7:18 a.m. UTC | #2
On 9/13/2022 12:45 PM, Takashi Iwai wrote:
> External email: Use caution opening links or attachments
>
>
> On Tue, 13 Sep 2022 08:58:18 +0200,
> Mohan Kumar wrote:
>> Nvidia HDA HW expects infoframe data bytes order same for both
>> HDMI and DP i.e infoframe data starts from 5th bytes offset. As
>> dp infoframe structure has 4th byte as valid infoframe data, use
>> hdmi infoframe structure for nvidia dp infoframe to match HW behvaior.
>>
>> Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
> Aha, so this affects on all Nvidia devices, not only on Tegra, but
> also on PC?  Then we should put cc-to-stable definitely.
Yes, The HDA HW design was common for dGPU and Tegra.
>
> (No need to resend, I can put it locally.)
Thanks!.
>
>
> Takashi
>
>> ---
>>   sound/pci/hda/patch_hdmi.c | 23 +++++++++++++++++++----
>>   1 file changed, 19 insertions(+), 4 deletions(-)
>>
>> diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
>> index 6c209cd26c0c..9127dd1b1a9c 100644
>> --- a/sound/pci/hda/patch_hdmi.c
>> +++ b/sound/pci/hda/patch_hdmi.c
>> @@ -170,6 +170,8 @@ struct hdmi_spec {
>>        bool dyn_pcm_no_legacy;
>>        /* hdmi interrupt trigger control flag for Nvidia codec */
>>        bool hdmi_intr_trig_ctrl;
>> +     bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
>> +
>>        bool intel_hsw_fixup;   /* apply Intel platform-specific fixups */
>>        /*
>>         * Non-generic VIA/NVIDIA specific
>> @@ -679,15 +681,24 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
>>                                     int ca, int active_channels,
>>                                     int conn_type)
>>   {
>> +     struct hdmi_spec *spec = codec->spec;
>>        union audio_infoframe ai;
>>
>>        memset(&ai, 0, sizeof(ai));
>> -     if (conn_type == 0) { /* HDMI */
>> +     if ((conn_type == 0) || /* HDMI */
>> +             /* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */
>> +             (conn_type == 1 && spec->nv_dp_workaround)) {
>>                struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
>>
>> -             hdmi_ai->type           = 0x84;
>> -             hdmi_ai->ver            = 0x01;
>> -             hdmi_ai->len            = 0x0a;
>> +             if (conn_type == 0) { /* HDMI */
>> +                     hdmi_ai->type           = 0x84;
>> +                     hdmi_ai->ver            = 0x01;
>> +                     hdmi_ai->len            = 0x0a;
>> +             } else {/* Nvidia DP */
>> +                     hdmi_ai->type           = 0x84;
>> +                     hdmi_ai->ver            = 0x1b;
>> +                     hdmi_ai->len            = 0x11 << 2;
>> +             }
>>                hdmi_ai->CC02_CT47      = active_channels - 1;
>>                hdmi_ai->CA             = ca;
>>                hdmi_checksum_audio_infoframe(hdmi_ai);
>> @@ -3617,6 +3628,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
>>        spec->pcm_playback.rates = SUPPORTED_RATES;
>>        spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
>>        spec->pcm_playback.formats = SUPPORTED_FORMATS;
>> +     spec->nv_dp_workaround = true;
>>        return 0;
>>   }
>>
>> @@ -3756,6 +3768,7 @@ static int patch_nvhdmi(struct hda_codec *codec)
>>        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
>>                nvhdmi_chmap_cea_alloc_validate_get_type;
>>        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
>> +     spec->nv_dp_workaround = true;
>>
>>        codec->link_down_at_suspend = 1;
>>
>> @@ -3779,6 +3792,7 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec)
>>        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
>>                nvhdmi_chmap_cea_alloc_validate_get_type;
>>        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
>> +     spec->nv_dp_workaround = true;
>>
>>        codec->link_down_at_suspend = 1;
>>
>> @@ -3992,6 +4006,7 @@ static int tegra_hdmi_init(struct hda_codec *codec)
>>        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
>>                nvhdmi_chmap_cea_alloc_validate_get_type;
>>        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
>> +     spec->nv_dp_workaround = true;
>>
>>        return 0;
>>   }
>> --
>> 2.17.1
>>
Takashi Iwai Sept. 13, 2022, 7:52 a.m. UTC | #3
On Tue, 13 Sep 2022 09:18:52 +0200,
Mohan Kumar D wrote:
> 
> 
> On 9/13/2022 12:45 PM, Takashi Iwai wrote:
> > External email: Use caution opening links or attachments
> > 
> > 
> > On Tue, 13 Sep 2022 08:58:18 +0200,
> > Mohan Kumar wrote:
> >> Nvidia HDA HW expects infoframe data bytes order same for both
> >> HDMI and DP i.e infoframe data starts from 5th bytes offset. As
> >> dp infoframe structure has 4th byte as valid infoframe data, use
> >> hdmi infoframe structure for nvidia dp infoframe to match HW behvaior.
> >> 
> >> Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
> > Aha, so this affects on all Nvidia devices, not only on Tegra, but
> > also on PC?  Then we should put cc-to-stable definitely.
> Yes, The HDA HW design was common for dGPU and Tegra.
> > 
> > (No need to resend, I can put it locally.)
> Thanks!.

OK, applied now.


thanks,

Takashi
diff mbox series

Patch

diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 6c209cd26c0c..9127dd1b1a9c 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -170,6 +170,8 @@  struct hdmi_spec {
 	bool dyn_pcm_no_legacy;
 	/* hdmi interrupt trigger control flag for Nvidia codec */
 	bool hdmi_intr_trig_ctrl;
+	bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
+
 	bool intel_hsw_fixup;	/* apply Intel platform-specific fixups */
 	/*
 	 * Non-generic VIA/NVIDIA specific
@@ -679,15 +681,24 @@  static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
 				     int ca, int active_channels,
 				     int conn_type)
 {
+	struct hdmi_spec *spec = codec->spec;
 	union audio_infoframe ai;
 
 	memset(&ai, 0, sizeof(ai));
-	if (conn_type == 0) { /* HDMI */
+	if ((conn_type == 0) || /* HDMI */
+		/* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */
+		(conn_type == 1 && spec->nv_dp_workaround)) {
 		struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
 
-		hdmi_ai->type		= 0x84;
-		hdmi_ai->ver		= 0x01;
-		hdmi_ai->len		= 0x0a;
+		if (conn_type == 0) { /* HDMI */
+			hdmi_ai->type		= 0x84;
+			hdmi_ai->ver		= 0x01;
+			hdmi_ai->len		= 0x0a;
+		} else {/* Nvidia DP */
+			hdmi_ai->type		= 0x84;
+			hdmi_ai->ver		= 0x1b;
+			hdmi_ai->len		= 0x11 << 2;
+		}
 		hdmi_ai->CC02_CT47	= active_channels - 1;
 		hdmi_ai->CA		= ca;
 		hdmi_checksum_audio_infoframe(hdmi_ai);
@@ -3617,6 +3628,7 @@  static int patch_nvhdmi_2ch(struct hda_codec *codec)
 	spec->pcm_playback.rates = SUPPORTED_RATES;
 	spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
 	spec->pcm_playback.formats = SUPPORTED_FORMATS;
+	spec->nv_dp_workaround = true;
 	return 0;
 }
 
@@ -3756,6 +3768,7 @@  static int patch_nvhdmi(struct hda_codec *codec)
 	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
 		nvhdmi_chmap_cea_alloc_validate_get_type;
 	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+	spec->nv_dp_workaround = true;
 
 	codec->link_down_at_suspend = 1;
 
@@ -3779,6 +3792,7 @@  static int patch_nvhdmi_legacy(struct hda_codec *codec)
 	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
 		nvhdmi_chmap_cea_alloc_validate_get_type;
 	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+	spec->nv_dp_workaround = true;
 
 	codec->link_down_at_suspend = 1;
 
@@ -3992,6 +4006,7 @@  static int tegra_hdmi_init(struct hda_codec *codec)
 	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
 		nvhdmi_chmap_cea_alloc_validate_get_type;
 	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+	spec->nv_dp_workaround = true;
 
 	return 0;
 }