[PATCH] ALSA: hda/hdmi: Use only dynamic PCM device allocation
Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters.
Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed.
I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected.
[1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@pere...
Cc: Kai Vehmanen kai.vehmanen@linux.intel.com Signed-off-by: Jaroslav Kysela perex@perex.cz --- include/sound/hda_codec.h | 1 - sound/pci/hda/patch_hdmi.c | 153 +++++++----------------------------- sound/soc/codecs/hda.c | 3 - sound/soc/codecs/hdac_hda.c | 3 - 4 files changed, 28 insertions(+), 132 deletions(-)
diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 6d3c82c4b6ac..684e6131737e 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -258,7 +258,6 @@ struct hda_codec { unsigned int link_down_at_suspend:1; /* link down at runtime suspend */ unsigned int relaxed_resume:1; /* don't resume forcibly for jack */ unsigned int forced_resume:1; /* forced resume for jack */ - unsigned int mst_no_extra_pcms:1; /* no backup PCMs for DP-MST */
#ifdef CONFIG_PM unsigned long power_on_acct; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index f27a4ee810e3..ac520c62ee70 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -167,8 +167,6 @@ struct hdmi_spec { struct hdmi_ops ops;
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 */ @@ -1177,9 +1175,7 @@ static void pin_cvt_fixup(struct hda_codec *codec, spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid); }
-/* called in hdmi_pcm_open when no pin is assigned to the PCM - * in dyn_pcm_assign mode. - */ +/* called in hdmi_pcm_open when no pin is assigned to the PCM */ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) @@ -1247,19 +1243,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (!spec->dyn_pcm_assign) { - if (snd_BUG_ON(pin_idx < 0)) { - err = -EINVAL; - goto unlock; - } - } else { - /* no pin is assigned to the PCM - * PA need pcm open successfully when probe - */ - if (pin_idx < 0) { - err = hdmi_pcm_open_no_pin(hinfo, codec, substream); - goto unlock; - } + /* no pin is assigned to the PCM + * PA need pcm open successfully when probe + */ + if (pin_idx < 0) { + err = hdmi_pcm_open_no_pin(hinfo, codec, substream); + goto unlock; }
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false); @@ -1364,43 +1353,6 @@ static int hdmi_find_pcm_slot(struct hdmi_spec *spec, { int i;
- /* on the new machines, try to assign the pcm slot dynamically, - * not use the preferred fixed map (legacy way) anymore. - */ - if (spec->dyn_pcm_no_legacy) - goto last_try; - - /* - * generic_hdmi_build_pcms() may allocate extra PCMs on some - * platforms (with maximum of 'num_nids + dev_num - 1') - * - * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n - * if m==0. This guarantees that dynamic pcm assignments are compatible - * with the legacy static per_pin-pcm assignment that existed in the - * days before DP-MST. - * - * Intel DP-MST prefers this legacy behavior for compatibility, too. - * - * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)). - */ - - if (per_pin->dev_id == 0 || spec->intel_hsw_fixup) { - if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) - return per_pin->pin_nid_idx; - } else { - i = spec->num_nids + (per_pin->dev_id - 1); - if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap))) - return i; - } - - /* have a second try; check the area over num_nids */ - for (i = spec->num_nids; i < spec->pcm_used; i++) { - if (!test_bit(i, &spec->pcm_bitmap)) - return i; - } - - last_try: - /* the last try; check the empty slots in pins */ for (i = 0; i < spec->pcm_used; i++) { if (!test_bit(i, &spec->pcm_bitmap)) return i; @@ -1562,14 +1514,12 @@ static void update_eld(struct hda_codec *codec, */ pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
- if (spec->dyn_pcm_assign) { - if (eld->eld_valid) { - hdmi_attach_hda_pcm(spec, per_pin); - hdmi_pcm_setup_pin(spec, per_pin); - } else { - hdmi_pcm_reset_pin(spec, per_pin); - hdmi_detach_hda_pcm(spec, per_pin); - } + if (eld->eld_valid) { + hdmi_attach_hda_pcm(spec, per_pin); + hdmi_pcm_setup_pin(spec, per_pin); + } else { + hdmi_pcm_reset_pin(spec, per_pin); + hdmi_detach_hda_pcm(spec, per_pin); } /* if pcm_idx == -1, it means this is in monitor connection event * we can get the correct pcm_idx now. @@ -1931,7 +1881,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) * structures based on worst case. */ dev_num = spec->dev_num; - } else if (spec->dyn_pcm_assign && codec->dp_mst) { + } else if (codec->dp_mst) { dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1; /* * spec->dev_num is the maxinum number of device entries @@ -1956,13 +1906,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) if (!per_pin) return -ENOMEM;
- if (spec->dyn_pcm_assign) { - per_pin->pcm = NULL; - per_pin->pcm_idx = -1; - } else { - per_pin->pcm = get_hdmi_pcm(spec, pin_idx); - per_pin->pcm_idx = pin_idx; - } + per_pin->pcm = NULL; + per_pin->pcm_idx = -1; per_pin->pin_nid = pin_nid; per_pin->pin_nid_idx = spec->num_nids; per_pin->dev_id = i; @@ -1971,6 +1916,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) err = hdmi_read_pin_conn(codec, pin_idx); if (err < 0) return err; + if (!is_jack_detectable(codec, pin_nid)) + codec_warn(codec, "HDMI: pin NID 0x%x - jack not detectable\n", pin_nid); spec->num_pins++; } spec->num_nids++; @@ -2118,10 +2065,9 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) { - /* when dyn_pcm_assign and pcm is not bound to a pin - * skip pin setup and return 0 to make audio playback - * be ongoing + if (pin_idx < 0) { + /* when pcm is not bound to a pin skip pin setup and return 0 + * to make audio playback be ongoing */ pin_cvt_fixup(codec, NULL, cvt_nid); snd_hda_codec_setup_stream(codec, cvt_nid, @@ -2224,7 +2170,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) + if (pin_idx < 0) goto unlock;
if (snd_BUG_ON(pin_idx < 0)) { @@ -2322,21 +2268,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int idx, pcm_num;
- /* - * for non-mst mode, pcm number is the same as before - * for DP MST mode without extra PCM, pcm number is same - * for DP MST mode with extra PCMs, pcm number is - * (nid number + dev_num - 1) - * dev_num is the device entry number in a pin - */ - - if (spec->dyn_pcm_no_legacy && codec->mst_no_extra_pcms) - pcm_num = spec->num_cvts; - else if (codec->mst_no_extra_pcms) - pcm_num = spec->num_nids; - else - pcm_num = spec->num_nids + spec->dev_num - 1; - + /* limit the PCM devices to the codec converters */ + pcm_num = spec->num_cvts; codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num);
for (idx = 0; idx < pcm_num; idx++) { @@ -2375,17 +2308,12 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) { char hdmi_str[32] = "HDMI/DP"; struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pcm_idx); struct snd_jack *jack; int pcmdev = get_pcm_rec(spec, pcm_idx)->device; int err;
if (pcmdev > 0) sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); - if (!spec->dyn_pcm_assign && - !is_jack_detectable(codec, per_pin->pin_nid)) - strncat(hdmi_str, " Phantom", - sizeof(hdmi_str) - strlen(hdmi_str) - 1);
err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack, true, false); @@ -2418,18 +2346,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) /* create the spdif for each pcm * pin will be bound when monitor is connected */ - if (spec->dyn_pcm_assign) - err = snd_hda_create_dig_out_ctls(codec, + err = snd_hda_create_dig_out_ctls(codec, 0, spec->cvt_nids[0], HDA_PCM_TYPE_HDMI); - else { - struct hdmi_spec_per_pin *per_pin = - get_pin(spec, pcm_idx); - err = snd_hda_create_dig_out_ctls(codec, - per_pin->pin_nid, - per_pin->mux_nids[0], - HDA_PCM_TYPE_HDMI); - } if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pcm_idx); @@ -2549,11 +2468,7 @@ static void generic_hdmi_free(struct hda_codec *codec) for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { if (spec->pcm_rec[pcm_idx].jack == NULL) continue; - if (spec->dyn_pcm_assign) - snd_device_free(codec->card, - spec->pcm_rec[pcm_idx].jack); - else - spec->pcm_rec[pcm_idx].jack = NULL; + snd_device_free(codec->card, spec->pcm_rec[pcm_idx].jack); }
generic_spec_free(codec); @@ -3033,7 +2948,6 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, return err; spec = codec->spec; codec->dp_mst = true; - spec->dyn_pcm_assign = true; spec->vendor_nid = vendor_nid; spec->port_map = port_map; spec->port_num = port_num; @@ -3097,17 +3011,9 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec) * the index indicate the port number. */ static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; - int ret; - - ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, - enable_silent_stream); - if (!ret) { - struct hdmi_spec *spec = codec->spec;
- spec->dyn_pcm_no_legacy = true; - } - - return ret; + return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, + enable_silent_stream); }
static int patch_i915_adlp_hdmi(struct hda_codec *codec) @@ -3746,7 +3652,6 @@ static int patch_nvhdmi(struct hda_codec *codec) codec->dp_mst = true;
spec = codec->spec; - spec->dyn_pcm_assign = true;
err = hdmi_parse_codec(codec); if (err < 0) { @@ -4022,10 +3927,8 @@ static int patch_tegra234_hdmi(struct hda_codec *codec) return err;
codec->dp_mst = true; - codec->mst_no_extra_pcms = true; spec = codec->spec; spec->dyn_pin_out = true; - spec->dyn_pcm_assign = true; spec->hdmi_intr_trig_ctrl = true;
return tegra_hdmi_init(codec); diff --git a/sound/soc/codecs/hda.c b/sound/soc/codecs/hda.c index ad20a3dff9b7..61e8e9be6b8d 100644 --- a/sound/soc/codecs/hda.c +++ b/sound/soc/codecs/hda.c @@ -224,9 +224,6 @@ static int hda_codec_probe(struct snd_soc_component *component) goto err; }
- /* configure codec for 1:1 PCM:DAI mapping */ - codec->mst_no_extra_pcms = 1; - ret = snd_hda_codec_parse_pcms(codec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 8debcee59224..7876bdd558a7 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -461,9 +461,6 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) dev_dbg(&hdev->dev, "no patch file found\n"); }
- /* configure codec for 1:1 PCM:DAI mapping */ - hcodec->mst_no_extra_pcms = 1; - ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
On Thu, 22 Sep 2022 10:40:17 +0200, Jaroslav Kysela wrote:
Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters.
Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed.
I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected.
[1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@pere...
Cc: Kai Vehmanen kai.vehmanen@linux.intel.com Signed-off-by: Jaroslav Kysela perex@perex.cz
Applied now. Thanks.
Takashi
CC'ing amd-gfx as this might be an issue in the amd driver.
This change causes a regression in Linux 6.1 at least on some AMD APUs. There are reports from users with Ryzen 4750U, 5800U and 5850U chips where the HDMI sound devices don't show up anymore. I'm affected by this as well.
Reverting this commit (ef6f5494) makes the HDMI audio devices show up again. I verified that this is still an issue in current Linux git (72a85e2b).
Am Donnerstag, dem 22.09.2022 um 10:40 +0200 schrieb Jaroslav Kysela:
Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters.
Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed.
I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected.
The corresponding message ("jack not detectable") is not shown on the affected system.
[1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@pere...
Links to some reports of this issue: https://bugzilla.kernel.org/show_bug.cgi?id=216836 https://bbs.archlinux.org/viewtopic.php?pid=2075700 https://bugs.archlinux.org/task/76917 https://www.reddit.com/r/archlinux/comments/zsqq7i/hdmi_audio_is_broken_afte...
Best regards, Michael
On Sun, 25 Dec 2022 13:14:28 +0100, Michael Laß wrote:
CC'ing amd-gfx as this might be an issue in the amd driver.
This change causes a regression in Linux 6.1 at least on some AMD APUs. There are reports from users with Ryzen 4750U, 5800U and 5850U chips where the HDMI sound devices don't show up anymore. I'm affected by this as well.
Reverting this commit (ef6f5494) makes the HDMI audio devices show up again. I verified that this is still an issue in current Linux git (72a85e2b).
Am Donnerstag, dem 22.09.2022 um 10:40 +0200 schrieb Jaroslav Kysela:
Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters.
Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed.
I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected.
The corresponding message ("jack not detectable") is not shown on the affected system.
[1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@pere...
Links to some reports of this issue: https://bugzilla.kernel.org/show_bug.cgi?id=216836 https://bbs.archlinux.org/viewtopic.php?pid=2075700 https://bugs.archlinux.org/task/76917 https://www.reddit.com/r/archlinux/comments/zsqq7i/hdmi_audio_is_broken_afte...
Could you give alsa-info.sh outputs from both working and non-working cases? Run the script with --no-upload option during the playback of HDMI stream, and attach the outputs.
thanks,
Takashi
On 25. 12. 22 19:52, Takashi Iwai wrote:
On Sun, 25 Dec 2022 13:14:28 +0100, Michael Laß wrote:
CC'ing amd-gfx as this might be an issue in the amd driver.
This change causes a regression in Linux 6.1 at least on some AMD APUs. There are reports from users with Ryzen 4750U, 5800U and 5850U chips where the HDMI sound devices don't show up anymore. I'm affected by this as well.
Reverting this commit (ef6f5494) makes the HDMI audio devices show up again. I verified that this is still an issue in current Linux git (72a85e2b).
Am Donnerstag, dem 22.09.2022 um 10:40 +0200 schrieb Jaroslav Kysela:
Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters.
Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed.
I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected.
The corresponding message ("jack not detectable") is not shown on the affected system.
[1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@pere...
Links to some reports of this issue: https://bugzilla.kernel.org/show_bug.cgi?id=216836 https://bbs.archlinux.org/viewtopic.php?pid=2075700 https://bugs.archlinux.org/task/76917 https://www.reddit.com/r/archlinux/comments/zsqq7i/hdmi_audio_is_broken_afte...
Could you give alsa-info.sh outputs from both working and non-working cases? Run the script with --no-upload option during the playback of HDMI stream, and attach the outputs.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216836
Jaroslav
[Note: this mail contains only information for Linux kernel regression tracking. Mails like these contain '#forregzbot' in the subject to make then easy to spot and filter out. The author also tried to remove most or all individuals from the list of recipients to spare them the hassle.]
On 25.12.22 13:14, Michael Laß wrote:
CC'ing amd-gfx as this might be an issue in the amd driver.
This change causes a regression in Linux 6.1 at least on some AMD APUs. There are reports from users with Ryzen 4750U, 5800U and 5850U chips where the HDMI sound devices don't show up anymore. I'm affected by this as well.
Reverting this commit (ef6f5494) makes the HDMI audio devices show up again. I verified that this is still an issue in current Linux git (72a85e2b).
Thanks for the report. To be sure below issue doesn't fall through the cracks unnoticed, I'm adding it to regzbot, my Linux kernel regression tracking bot:
#regzbot ^introduced ef6f5494faf6a37c74990689a #regzbot title alsa: hda/hdmi: HDMI sound devices don't show up anymore with some AMD APUs #regzbot ignore-activity
Ciao, Thorsten (wearing his 'the Linux kernel's regression tracker' hat)
P.S.: As the Linux kernel's regression tracker I deal with a lot of reports and sometimes miss something important when writing mails like this. If that's the case here, don't hesitate to tell me in a public reply, it's in everyone's interest to set the public record straight.
Am Donnerstag, dem 22.09.2022 um 10:40 +0200 schrieb Jaroslav Kysela:
Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters.
Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed.
I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected.
The corresponding message ("jack not detectable") is not shown on the affected system.
[1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@pere...
Links to some reports of this issue: https://bugzilla.kernel.org/show_bug.cgi?id=216836 https://bbs.archlinux.org/viewtopic.php?pid=2075700 https://bugs.archlinux.org/task/76917 https://www.reddit.com/r/archlinux/comments/zsqq7i/hdmi_audio_is_broken_afte...
Best regards, Michael
[TLDR: This mail in primarily relevant for Linux kernel regression tracking. See link in footer if these mails annoy you.]
On 26.12.22 14:26, Thorsten Leemhuis wrote:
On 25.12.22 13:14, Michael Laß wrote:
CC'ing amd-gfx as this might be an issue in the amd driver.
This change causes a regression in Linux 6.1 at least on some AMD APUs. There are reports from users with Ryzen 4750U, 5800U and 5850U chips where the HDMI sound devices don't show up anymore. I'm affected by this as well.
Reverting this commit (ef6f5494) makes the HDMI audio devices show up again. I verified that this is still an issue in current Linux git (72a85e2b).
Thanks for the report. To be sure below issue doesn't fall through the cracks unnoticed, I'm adding it to regzbot, my Linux kernel regression tracking bot:
#regzbot ^introduced ef6f5494faf6a37c74990689a #regzbot title alsa: hda/hdmi: HDMI sound devices don't show up anymore with some AMD APUs #regzbot ignore-activity
#regzbot fix: 090ddad4c7a9 #regzbot ignore-activity
Ciao, Thorsten (wearing his 'the Linux kernel's regression tracker' hat) -- Everything you wanna know about Linux kernel regression tracking: https://linux-regtracking.leemhuis.info/about/#tldr That page also explains what to do if mails like this annoy you.
participants (5)
-
Jaroslav Kysela
-
Linux kernel regression tracking (#update)
-
Michael Laß
-
Takashi Iwai
-
Thorsten Leemhuis