2022-02-09 12:36:45

by Mohan Kumar

[permalink] [raw]
Subject: [PATCH v1 3/6] ALSA: hda/tegra: Update scratch reg. communication

Tegra234 chip scratch register communication between audio
and hdmi driver differs slightly in the way it triggers the
interrupt compared to legacy chips. Interrupt is triggered
by writing non-zero values to verb 0xF80 instead of 31st bit
of scratch register.

DP MST support changed the NID to be used for scratch register
read/write from audio function group NID to Converter widget NID.

Signed-off-by: Mohan Kumar <[email protected]>
---
include/sound/hda_codec.h | 4 +++
sound/pci/hda/patch_hdmi.c | 61 ++++++++++++++++++++++++++++----------
2 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
index 82d9daa17851..c1c19dd4c423 100644
--- a/include/sound/hda_codec.h
+++ b/include/sound/hda_codec.h
@@ -240,6 +240,10 @@ struct hda_codec {
unsigned int single_adc_amp:1; /* adc in-amp takes no index
* (e.g. CX20549 codec)
*/
+ unsigned int hdmi_intr_trig_ctrl:1; /* hdmi interrupt trigger
+ * control flag
+ * (e.g. Nvidia codecs)
+ */
unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
unsigned int pins_shutup:1; /* pins are shut up */
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 879f886d2406..f0e87e39c53e 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -3721,8 +3721,11 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec)
* +-----------------------------------|
*
* Note that for the trigger bit to take effect it needs to change value
- * (i.e. it needs to be toggled).
+ * (i.e. it needs to be toggled). The trigger bit is not applicable from
+ * TEGRA234 chip onwards, as new verb id 0xf80 will be used for interrupt
+ * trigger to hdmi.
*/
+#define NVIDIA_SET_HOST_INTR 0xf80
#define NVIDIA_GET_SCRATCH0 0xfa6
#define NVIDIA_SET_SCRATCH0_BYTE0 0xfa7
#define NVIDIA_SET_SCRATCH0_BYTE1 0xfa8
@@ -3741,25 +3744,37 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec)
* The format parameter is the HDA audio format (see AC_FMT_*). If set to 0,
* the format is invalidated so that the HDMI codec can be disabled.
*/
-static void tegra_hdmi_set_format(struct hda_codec *codec, unsigned int format)
+static void tegra_hdmi_set_format(struct hda_codec *codec,
+ hda_nid_t cvt_nid,
+ unsigned int format)
{
unsigned int value;
+ unsigned int nid = NVIDIA_AFG_NID;
+
+ /*
+ * Tegra HDA codec design from TEGRA234 chip onwards support DP MST.
+ * This resulted in moving scratch registers from audio function
+ * group to converter widget context. So CVT NID should be used for
+ * scratch register read/write for DP MST supported Tegra HDA codec.
+ */
+ if (codec->dp_mst)
+ nid = cvt_nid;

/* bits [31:30] contain the trigger and valid bits */
- value = snd_hda_codec_read(codec, NVIDIA_AFG_NID, 0,
+ value = snd_hda_codec_read(codec, nid, 0,
NVIDIA_GET_SCRATCH0, 0);
value = (value >> 24) & 0xff;

/* bits [15:0] are used to store the HDA format */
- snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
+ snd_hda_codec_write(codec, nid, 0,
NVIDIA_SET_SCRATCH0_BYTE0,
(format >> 0) & 0xff);
- snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
+ snd_hda_codec_write(codec, nid, 0,
NVIDIA_SET_SCRATCH0_BYTE1,
(format >> 8) & 0xff);

/* bits [16:24] are unused */
- snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
+ snd_hda_codec_write(codec, nid, 0,
NVIDIA_SET_SCRATCH0_BYTE2, 0);

/*
@@ -3771,15 +3786,28 @@ static void tegra_hdmi_set_format(struct hda_codec *codec, unsigned int format)
else
value |= NVIDIA_SCRATCH_VALID;

- /*
- * Whenever the trigger bit is toggled, an interrupt is raised in the
- * HDMI codec. The HDMI driver will use that as trigger to update its
- * configuration.
- */
- value ^= NVIDIA_SCRATCH_TRIGGER;
+ if (codec->hdmi_intr_trig_ctrl) {
+ /*
+ * For Tegra HDA Codec design from TEGRA234 onwards, the
+ * Interrupt to hdmi driver is triggered by writing
+ * non-zero values to verb 0xF80 instead of 31st bit of
+ * scratch register.
+ */
+ snd_hda_codec_write(codec, nid, 0,
+ NVIDIA_SET_SCRATCH0_BYTE3, value);
+ snd_hda_codec_write(codec, nid, 0,
+ NVIDIA_SET_HOST_INTR, 0x1);
+ } else {
+ /*
+ * Whenever the 31st trigger bit is toggled, an interrupt is raised
+ * in the HDMI codec. The HDMI driver will use that as trigger
+ * to update its configuration.
+ */
+ value ^= NVIDIA_SCRATCH_TRIGGER;

- snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
- NVIDIA_SET_SCRATCH0_BYTE3, value);
+ snd_hda_codec_write(codec, nid, 0,
+ NVIDIA_SET_SCRATCH0_BYTE3, value);
+ }
}

static int tegra_hdmi_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -3796,7 +3824,7 @@ static int tegra_hdmi_pcm_prepare(struct hda_pcm_stream *hinfo,
return err;

/* notify the HDMI codec of the format change */
- tegra_hdmi_set_format(codec, format);
+ tegra_hdmi_set_format(codec, hinfo->nid, format);

return 0;
}
@@ -3806,7 +3834,7 @@ static int tegra_hdmi_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
/* invalidate the format in the HDMI codec */
- tegra_hdmi_set_format(codec, 0);
+ tegra_hdmi_set_format(codec, hinfo->nid, 0);

return generic_hdmi_playback_pcm_cleanup(hinfo, codec, substream);
}
@@ -3903,6 +3931,7 @@ static int patch_tegra234_hdmi(struct hda_codec *codec)

codec->dp_mst = true;
codec->mst_no_extra_pcms = true;
+ codec->hdmi_intr_trig_ctrl = true;
spec = codec->spec;
spec->dyn_pin_out = true;
spec->dyn_pcm_assign = true;
--
2.17.1



2022-02-09 12:46:58

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH v1 3/6] ALSA: hda/tegra: Update scratch reg. communication

On Wed, 09 Feb 2022 05:23:23 +0100,
Mohan Kumar wrote:
>
> --- a/include/sound/hda_codec.h
> +++ b/include/sound/hda_codec.h
> @@ -240,6 +240,10 @@ struct hda_codec {
> unsigned int single_adc_amp:1; /* adc in-amp takes no index
> * (e.g. CX20549 codec)
> */
> + unsigned int hdmi_intr_trig_ctrl:1; /* hdmi interrupt trigger
> + * control flag
> + * (e.g. Nvidia codecs)
> + */

This flag is specific to (Nvidia) HDMI codec and referred only from
patch_hdmi.c, right? If so, the flag would be better put locally to
struct hdmi_spec instead of a global hda_codec.


thanks,

Takashi