1 |
From 090ddad4c7a9fefd647c762093a555870a19c8b2 Mon Sep 17 00:00:00 2001 |
2 |
From: Takashi Iwai <tiwai@suse.de> |
3 |
Date: Wed, 28 Dec 2022 13:57:14 +0100 |
4 |
Subject: ALSA: hda/hdmi: Static PCM mapping again with AMD HDMI codecs |
5 |
|
6 |
The recent code refactoring for HD-audio HDMI codec driver caused a |
7 |
regression on AMD/ATI HDMI codecs; namely, PulseAudioand pipewire |
8 |
don't recognize HDMI outputs any longer while the direct output via |
9 |
ALSA raw access still works. |
10 |
|
11 |
The problem turned out that, after the code refactoring, the driver |
12 |
assumes only the dynamic PCM assignment, and when a PCM stream that |
13 |
still isn't assigned to any pin gets opened, the driver tries to |
14 |
assign any free converter to the PCM stream. This behavior is OK for |
15 |
Intel and other codecs, as they have arbitrary connections between |
16 |
pins and converters. OTOH, on AMD chips that have a 1:1 mapping |
17 |
between pins and converters, this may end up with blocking the open of |
18 |
the next PCM stream for the pin that is tied with the formerly taken |
19 |
converter. |
20 |
|
21 |
Also, with the code refactoring, more PCM streams are exposed than |
22 |
necessary as we assume all converters can be used, while this isn't |
23 |
true for AMD case. This may change the PCM stream assignment and |
24 |
confuse users as well. |
25 |
|
26 |
This patch fixes those problems by: |
27 |
|
28 |
- Introducing a flag spec->static_pcm_mapping, and if it's set, the |
29 |
driver applies the static mapping between pins and converters at the |
30 |
probe time |
31 |
- Limiting the number of PCM streams per pins, too; this avoids the |
32 |
superfluous PCM streams |
33 |
|
34 |
Fixes: ef6f5494faf6 ("ALSA: hda/hdmi: Use only dynamic PCM device allocation") |
35 |
Cc: <stable@vger.kernel.org> |
36 |
Link: https://bugzilla.kernel.org/show_bug.cgi?id=216836 |
37 |
Co-developed-by: Jaroslav Kysela <perex@perex.cz> |
38 |
Signed-off-by: Jaroslav Kysela <perex@perex.cz> |
39 |
Link: https://lore.kernel.org/r/20221228125714.16329-1-tiwai@suse.de |
40 |
Signed-off-by: Takashi Iwai <tiwai@suse.de> |
41 |
--- |
42 |
sound/pci/hda/patch_hdmi.c | 27 +++++++++++++++++++-------- |
43 |
1 file changed, 19 insertions(+), 8 deletions(-) |
44 |
|
45 |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c |
46 |
index 8015e44712678..386dd9d9143f9 100644 |
47 |
--- a/sound/pci/hda/patch_hdmi.c |
48 |
+++ b/sound/pci/hda/patch_hdmi.c |
49 |
@@ -167,6 +167,7 @@ struct hdmi_spec { |
50 |
struct hdmi_ops ops; |
51 |
|
52 |
bool dyn_pin_out; |
53 |
+ bool static_pcm_mapping; |
54 |
/* hdmi interrupt trigger control flag for Nvidia codec */ |
55 |
bool hdmi_intr_trig_ctrl; |
56 |
bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */ |
57 |
@@ -1525,13 +1526,16 @@ static void update_eld(struct hda_codec *codec, |
58 |
*/ |
59 |
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); |
60 |
|
61 |
- if (eld->eld_valid) { |
62 |
- hdmi_attach_hda_pcm(spec, per_pin); |
63 |
- hdmi_pcm_setup_pin(spec, per_pin); |
64 |
- } else { |
65 |
- hdmi_pcm_reset_pin(spec, per_pin); |
66 |
- hdmi_detach_hda_pcm(spec, per_pin); |
67 |
+ if (!spec->static_pcm_mapping) { |
68 |
+ if (eld->eld_valid) { |
69 |
+ hdmi_attach_hda_pcm(spec, per_pin); |
70 |
+ hdmi_pcm_setup_pin(spec, per_pin); |
71 |
+ } else { |
72 |
+ hdmi_pcm_reset_pin(spec, per_pin); |
73 |
+ hdmi_detach_hda_pcm(spec, per_pin); |
74 |
+ } |
75 |
} |
76 |
+ |
77 |
/* if pcm_idx == -1, it means this is in monitor connection event |
78 |
* we can get the correct pcm_idx now. |
79 |
*/ |
80 |
@@ -2281,8 +2285,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) |
81 |
struct hdmi_spec *spec = codec->spec; |
82 |
int idx, pcm_num; |
83 |
|
84 |
- /* limit the PCM devices to the codec converters */ |
85 |
- pcm_num = spec->num_cvts; |
86 |
+ /* limit the PCM devices to the codec converters or available PINs */ |
87 |
+ pcm_num = min(spec->num_cvts, spec->num_pins); |
88 |
codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num); |
89 |
|
90 |
for (idx = 0; idx < pcm_num; idx++) { |
91 |
@@ -2379,6 +2383,11 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) |
92 |
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
93 |
struct hdmi_eld *pin_eld = &per_pin->sink_eld; |
94 |
|
95 |
+ if (spec->static_pcm_mapping) { |
96 |
+ hdmi_attach_hda_pcm(spec, per_pin); |
97 |
+ hdmi_pcm_setup_pin(spec, per_pin); |
98 |
+ } |
99 |
+ |
100 |
pin_eld->eld_valid = false; |
101 |
hdmi_present_sense(per_pin, 0); |
102 |
} |
103 |
@@ -4419,6 +4428,8 @@ static int patch_atihdmi(struct hda_codec *codec) |
104 |
|
105 |
spec = codec->spec; |
106 |
|
107 |
+ spec->static_pcm_mapping = true; |
108 |
+ |
109 |
spec->ops.pin_get_eld = atihdmi_pin_get_eld; |
110 |
spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe; |
111 |
spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup; |
112 |
-- |
113 |
cgit |
114 |
|