Skip to content

Commit 090ddad

Browse files
committed
ALSA: hda/hdmi: Static PCM mapping again with AMD HDMI codecs
The recent code refactoring for HD-audio HDMI codec driver caused a regression on AMD/ATI HDMI codecs; namely, PulseAudioand pipewire don't recognize HDMI outputs any longer while the direct output via ALSA raw access still works. The problem turned out that, after the code refactoring, the driver assumes only the dynamic PCM assignment, and when a PCM stream that still isn't assigned to any pin gets opened, the driver tries to assign any free converter to the PCM stream. This behavior is OK for Intel and other codecs, as they have arbitrary connections between pins and converters. OTOH, on AMD chips that have a 1:1 mapping between pins and converters, this may end up with blocking the open of the next PCM stream for the pin that is tied with the formerly taken converter. Also, with the code refactoring, more PCM streams are exposed than necessary as we assume all converters can be used, while this isn't true for AMD case. This may change the PCM stream assignment and confuse users as well. This patch fixes those problems by: - Introducing a flag spec->static_pcm_mapping, and if it's set, the driver applies the static mapping between pins and converters at the probe time - Limiting the number of PCM streams per pins, too; this avoids the superfluous PCM streams Fixes: ef6f549 ("ALSA: hda/hdmi: Use only dynamic PCM device allocation") Cc: <stable@vger.kernel.org> Link: https://bugzilla.kernel.org/show_bug.cgi?id=216836 Co-developed-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20221228125714.16329-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent a4517c4 commit 090ddad

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

sound/pci/hda/patch_hdmi.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ struct hdmi_spec {
167167
struct hdmi_ops ops;
168168

169169
bool dyn_pin_out;
170+
bool static_pcm_mapping;
170171
/* hdmi interrupt trigger control flag for Nvidia codec */
171172
bool hdmi_intr_trig_ctrl;
172173
bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
@@ -1525,13 +1526,16 @@ static void update_eld(struct hda_codec *codec,
15251526
*/
15261527
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
15271528

1528-
if (eld->eld_valid) {
1529-
hdmi_attach_hda_pcm(spec, per_pin);
1530-
hdmi_pcm_setup_pin(spec, per_pin);
1531-
} else {
1532-
hdmi_pcm_reset_pin(spec, per_pin);
1533-
hdmi_detach_hda_pcm(spec, per_pin);
1529+
if (!spec->static_pcm_mapping) {
1530+
if (eld->eld_valid) {
1531+
hdmi_attach_hda_pcm(spec, per_pin);
1532+
hdmi_pcm_setup_pin(spec, per_pin);
1533+
} else {
1534+
hdmi_pcm_reset_pin(spec, per_pin);
1535+
hdmi_detach_hda_pcm(spec, per_pin);
1536+
}
15341537
}
1538+
15351539
/* if pcm_idx == -1, it means this is in monitor connection event
15361540
* we can get the correct pcm_idx now.
15371541
*/
@@ -2281,8 +2285,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
22812285
struct hdmi_spec *spec = codec->spec;
22822286
int idx, pcm_num;
22832287

2284-
/* limit the PCM devices to the codec converters */
2285-
pcm_num = spec->num_cvts;
2288+
/* limit the PCM devices to the codec converters or available PINs */
2289+
pcm_num = min(spec->num_cvts, spec->num_pins);
22862290
codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num);
22872291

22882292
for (idx = 0; idx < pcm_num; idx++) {
@@ -2379,6 +2383,11 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
23792383
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
23802384
struct hdmi_eld *pin_eld = &per_pin->sink_eld;
23812385

2386+
if (spec->static_pcm_mapping) {
2387+
hdmi_attach_hda_pcm(spec, per_pin);
2388+
hdmi_pcm_setup_pin(spec, per_pin);
2389+
}
2390+
23822391
pin_eld->eld_valid = false;
23832392
hdmi_present_sense(per_pin, 0);
23842393
}
@@ -4419,6 +4428,8 @@ static int patch_atihdmi(struct hda_codec *codec)
44194428

44204429
spec = codec->spec;
44214430

4431+
spec->static_pcm_mapping = true;
4432+
44224433
spec->ops.pin_get_eld = atihdmi_pin_get_eld;
44234434
spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe;
44244435
spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup;

0 commit comments

Comments
 (0)