diff options
author | Jaroslav Kysela <perex@perex.cz> | 2023-02-02 10:20:13 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2023-02-03 17:19:20 +0100 |
commit | d045bceff5a904bd79d71dede9f927c00ce4906f (patch) | |
tree | 2f26ead820165b7b0cffa2df3bfb2ccc444c6322 /sound/pci/hda/hda_codec.c | |
parent | 372a0d7856be29671fc03e2f28ac27114e8c6805 (diff) |
ALSA: hda: Fix the control element identification for multiple codecs
Some motherboards have multiple HDA codecs connected to the serial bus.
The current code may create multiple mixer controls with the almost
identical identification.
The current code use id.device field from the control element structure
to store the codec address to avoid such clashes for multiple codecs.
Unfortunately, the user space do not handle this correctly. For mixer
controls, only name and index are used for the identifiers.
This patch fixes this problem to compose the index using the codec
address as an offset in case, when the control already exists. It is
really unlikely that one codec will create 10 similar controls.
This patch adds new kernel module parameter 'ctl_dev_id' to allow
select the old behaviour, too. The CONFIG_SND_HDA_CTL_DEV_ID Kconfig
option sets the default value.
BugLink: https://github.com/alsa-project/alsa-lib/issues/294
BugLink: https://github.com/alsa-project/alsa-lib/issues/205
Fixes: 54d174031576 ("[ALSA] hda-codec - Fix connection list parsing")
Fixes: 1afe206ab699 ("ALSA: hda - Try to find an empty control index when it's occupied")
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20230202092013.4066998-1-perex@perex.cz
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ac1cc7c5290e..dc4a042b3ac1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3389,7 +3389,12 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, kctl = snd_ctl_new1(knew, codec); if (!kctl) return -ENOMEM; - if (addr > 0) + /* Do not use the id.device field for MIXER elements. + * This field is for real device numbers (like PCM) but codecs + * are hidden components from the user space view (unrelated + * to the mixer element identification). + */ + if (addr > 0 && codec->ctl_dev_id) kctl->id.device = addr; if (idx > 0) kctl->id.index = idx; @@ -3400,9 +3405,11 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, * the codec addr; if it still fails (or it's the * primary codec), then try another control index */ - if (!addr && codec->core.addr) + if (!addr && codec->core.addr) { addr = codec->core.addr; - else if (!idx && !knew->index) { + if (!codec->ctl_dev_id) + idx += 10 * addr; + } else if (!idx && !knew->index) { idx = find_empty_mixer_ctl_idx(codec, knew->name, 0); if (idx <= 0) |