summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMohan Kumar <mkumard@nvidia.com>2022-02-16 14:52:37 +0530
committerTakashi Iwai <tiwai@suse.de>2022-02-21 11:03:37 +0100
commit85f29492929bd52dc3b05876c7ae0362608475ce (patch)
tree32f601b03f58963ea7f9828782842c2da1956fca /sound
parentb58d511ded88ebfc14381eb9fe6e66080e8ed10f (diff)
downloadlinux-85f29492929bd52dc3b05876c7ae0362608475ce.tar.bz2
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 <mkumard@nvidia.com> Link: https://lore.kernel.org/r/20220216092240.26464-4-mkumard@nvidia.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_hdmi.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index a134d91db5ff..c85ed7bc121e 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -168,6 +168,8 @@ struct hdmi_spec {
bool dyn_pin_out;
bool dyn_pcm_assign;
bool dyn_pcm_no_legacy;
+ /* hdmi interrupt trigger control flag for Nvidia codec */
+ bool hdmi_intr_trig_ctrl;
bool intel_hsw_fixup; /* apply Intel platform-specific fixups */
/*
* Non-generic VIA/NVIDIA specific
@@ -3797,8 +3799,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
@@ -3817,25 +3822,38 @@ 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;
+ struct hdmi_spec *spec = codec->spec;
+
+ /*
+ * 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);
/*
@@ -3847,15 +3865,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 (spec->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,
@@ -3872,7 +3903,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;
}
@@ -3882,7 +3913,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);
}
@@ -3982,6 +4013,7 @@ static int patch_tegra234_hdmi(struct hda_codec *codec)
spec = codec->spec;
spec->dyn_pin_out = true;
spec->dyn_pcm_assign = true;
+ spec->hdmi_intr_trig_ctrl = true;
return tegra_hdmi_init(codec);
}