summarylogtreecommitdiffstats
path: root/0003-ALSA-hda-Fix-DP-MST-support-for-NVIDIA-codecs.patch
diff options
context:
space:
mode:
Diffstat (limited to '0003-ALSA-hda-Fix-DP-MST-support-for-NVIDIA-codecs.patch')
-rw-r--r--0003-ALSA-hda-Fix-DP-MST-support-for-NVIDIA-codecs.patch182
1 files changed, 182 insertions, 0 deletions
diff --git a/0003-ALSA-hda-Fix-DP-MST-support-for-NVIDIA-codecs.patch b/0003-ALSA-hda-Fix-DP-MST-support-for-NVIDIA-codecs.patch
new file mode 100644
index 000000000000..665022cd6a0b
--- /dev/null
+++ b/0003-ALSA-hda-Fix-DP-MST-support-for-NVIDIA-codecs.patch
@@ -0,0 +1,182 @@
+From 6b43b6519a752c51657b9afa4eb844cad29d2b8c Mon Sep 17 00:00:00 2001
+From: Nikhil Mahale <nmahale@nvidia.com>
+Date: Mon, 3 Feb 2020 15:36:17 +0530
+Subject: [PATCH 3/5] ALSA: hda - Fix DP-MST support for NVIDIA codecs
+
+If dyn_pcm_assign is set, different jack objects are being created
+for pcm and pins.
+
+If dyn_pcm_assign is set, generic_hdmi_build_jack() calls into
+add_hdmi_jack_kctl() to create and track separate jack object for
+pcm. Like sync_eld_via_acomp(), hdmi_present_sense_via_verbs() also
+need to report status change of the pcm jack.
+
+Rename pin_idx_to_jack() to pin_idx_to_pcm_jack(). The code to
+report status change of pcm jack, move it to update_eld() which is
+common for acomp and !acomp code paths.
+
+Fixes: 5398e94fb753 ALSA: hda - Add DP-MST support for NVIDIA codecs
+Signed-off-by: Nikhil Mahale <nmahale@nvidia.com>
+---
+ sound/pci/hda/patch_hdmi.c | 94 +++++++++++++++++++-------------------
+ 1 file changed, 47 insertions(+), 47 deletions(-)
+
+diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
+index 630b1f5c276d..469b25065643 100644
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -1477,6 +1477,35 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec,
+ per_pin->channels = 0;
+ }
+
++static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
++ struct hdmi_spec_per_pin *per_pin)
++{
++ struct hdmi_spec *spec = codec->spec;
++ struct snd_jack *jack = NULL;
++ struct hda_jack_tbl *jack_tbl;
++
++ /* if !dyn_pcm_assign, get jack from hda_jack_tbl
++ * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
++ * NULL even after snd_hda_jack_tbl_clear() is called to
++ * free snd_jack. This may cause access invalid memory
++ * when calling snd_jack_report
++ */
++ if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign) {
++ jack = spec->pcm_rec[per_pin->pcm_idx].jack;
++ } else if (!spec->dyn_pcm_assign) {
++ /*
++ * jack tbl doesn't support DP MST
++ * DP MST will use dyn_pcm_assign,
++ * so DP MST will never come here
++ */
++ jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
++ per_pin->dev_id);
++ if (jack_tbl)
++ jack = jack_tbl->jack;
++ }
++ return jack;
++}
++
+ /* update per_pin ELD from the given new ELD;
+ * setup info frame and notification accordingly
+ */
+@@ -1487,9 +1516,15 @@ static bool update_eld(struct hda_codec *codec,
+ struct hdmi_eld *pin_eld = &per_pin->sink_eld;
+ struct hdmi_spec *spec = codec->spec;
+ bool old_eld_valid = pin_eld->eld_valid;
++ struct snd_jack *pcm_jack;
+ bool eld_changed;
+ int pcm_idx;
+
++ /* pcm_idx >=0 before update_eld() means it is in monitor
++ * disconnected event. Jack must be fetched before update_eld()
++ */
++ pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
++
+ /* for monitor disconnection, save pcm_idx firstly */
+ pcm_idx = per_pin->pcm_idx;
+ if (spec->dyn_pcm_assign) {
+@@ -1544,6 +1579,14 @@ static bool update_eld(struct hda_codec *codec,
+ SNDRV_CTL_EVENT_MASK_VALUE |
+ SNDRV_CTL_EVENT_MASK_INFO,
+ &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
++
++ if (!pcm_jack)
++ pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
++ if (eld_changed && pcm_jack)
++ snd_jack_report(pcm_jack,
++ (eld->monitor_present && eld->eld_valid) ?
++ SND_JACK_AVOUT : 0);
++
+ return eld_changed;
+ }
+
+@@ -1566,7 +1609,6 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
+ * the unsolicited response to avoid custom WARs.
+ */
+ int present;
+- bool ret;
+ bool do_repoll = false;
+
+ present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id);
+@@ -1600,45 +1642,14 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
+ else
+ update_eld(codec, per_pin, eld);
+
+- ret = !repoll || !eld->monitor_present || eld->eld_valid;
+-
+ jack = snd_hda_jack_tbl_get_mst(codec, pin_nid, per_pin->dev_id);
+ if (jack) {
+- jack->block_report = !ret;
++ jack->block_report = do_repoll;
+ jack->pin_sense = (eld->monitor_present && eld->eld_valid) ?
+ AC_PINSENSE_PRESENCE : 0;
+ }
+ mutex_unlock(&per_pin->lock);
+- return ret;
+-}
+-
+-static struct snd_jack *pin_idx_to_jack(struct hda_codec *codec,
+- struct hdmi_spec_per_pin *per_pin)
+-{
+- struct hdmi_spec *spec = codec->spec;
+- struct snd_jack *jack = NULL;
+- struct hda_jack_tbl *jack_tbl;
+-
+- /* if !dyn_pcm_assign, get jack from hda_jack_tbl
+- * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
+- * NULL even after snd_hda_jack_tbl_clear() is called to
+- * free snd_jack. This may cause access invalid memory
+- * when calling snd_jack_report
+- */
+- if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign)
+- jack = spec->pcm_rec[per_pin->pcm_idx].jack;
+- else if (!spec->dyn_pcm_assign) {
+- /*
+- * jack tbl doesn't support DP MST
+- * DP MST will use dyn_pcm_assign,
+- * so DP MST will never come here
+- */
+- jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
+- per_pin->dev_id);
+- if (jack_tbl)
+- jack = jack_tbl->jack;
+- }
+- return jack;
++ return !do_repoll;
+ }
+
+ /* update ELD and jack state via audio component */
+@@ -1647,8 +1658,6 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
+ {
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld = &spec->temp_eld;
+- struct snd_jack *jack = NULL;
+- bool changed;
+ int size;
+
+ mutex_lock(&per_pin->lock);
+@@ -1671,17 +1680,8 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
+ eld->eld_size = 0;
+ }
+
+- /* pcm_idx >=0 before update_eld() means it is in monitor
+- * disconnected event. Jack must be fetched before update_eld()
+- */
+- jack = pin_idx_to_jack(codec, per_pin);
+- changed = update_eld(codec, per_pin, eld);
+- if (jack == NULL)
+- jack = pin_idx_to_jack(codec, per_pin);
+- if (changed && jack)
+- snd_jack_report(jack,
+- (eld->monitor_present && eld->eld_valid) ?
+- SND_JACK_AVOUT : 0);
++ update_eld(codec, per_pin, eld);
++
+ mutex_unlock(&per_pin->lock);
+ }
+
+--
+2.25.0
+