History

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.

Jaroslav Kysela committed 3 years ago

Commit d045bce1 parent 372a0d76 files · +32 −3Browse files

Unified · Split

6 files
  1. include/sound/hda_codec.h +1 −0
  2. sound/pci/hda/Kconfig +14 −0
  3. sound/pci/hda/hda_codec.c +10 −3
  4. sound/pci/hda/hda_controller.c +1 −0
  5. sound/pci/hda/hda_controller.h +1 −0
  6. sound/pci/hda/hda_intel.c +5 −0
include/sound/hda_codec.h+1−0
@@ -259,6 +259,7 @@ struct hda_codec { · 258 unmodified lines
259259 unsigned int relaxed_resume:1; /* don't resume forcibly for jack */
260260 unsigned int forced_resume:1; /* forced resume for jack */
261261 unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */
262+ unsigned int ctl_dev_id:1; /* old control element id build behaviour */
262263
263264 #ifdef CONFIG_PM
264265 unsigned long power_on_acct;
sound/pci/hda/Kconfig+14−0
@@ -302,6 +302,20 @@ config SND_HDA_INTEL_HDMI_SILENT_STREAM · 301 unmodified lines
302302 This feature can impact power consumption as resources
303303 are kept reserved both at transmitter and receiver.
304304
305+config SND_HDA_CTL_DEV_ID
306+ bool "Use the device identifier field for controls"
307+ depends on SND_HDA_INTEL
308+ help
309+ Say Y to use the device identifier field for (mixer)
310+ controls (old behaviour until this option is available).
311+
312+ When enabled, the multiple HDA codecs may set the device
313+ field in control (mixer) element identifiers. The use
314+ of this field is not recommended and defined for mixer controls.
315+
316+ The old behaviour (Y) is obsolete and will be removed. Consider
317+ to not enable this option.
318+
305319 endif
306320
307321 endmenu
sound/pci/hda/hda_codec.c+10−3
@@ -3389,7 +3389,12 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, · 3388 unmodified lines
33893389 kctl = snd_ctl_new1(knew, codec);
33903390 if (!kctl)
33913391 return -ENOMEM;
3392− if (addr > 0)
3392+ /* Do not use the id.device field for MIXER elements.
3393+ * This field is for real device numbers (like PCM) but codecs
3394+ * are hidden components from the user space view (unrelated
3395+ * to the mixer element identification).
3396+ */
3397+ if (addr > 0 && codec->ctl_dev_id)
33933398 kctl->id.device = addr;
33943399 if (idx > 0)
33953400 kctl->id.index = idx;
@@ -3400,9 +3405,11 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, · 4 unmodified lines
34003405 * the codec addr; if it still fails (or it's the
34013406 * primary codec), then try another control index
34023407 */
3403− if (!addr && codec->core.addr)
3408+ if (!addr && codec->core.addr) {
34043409 addr = codec->core.addr;
3405− else if (!idx && !knew->index) {
3410+ if (!codec->ctl_dev_id)
3411+ idx += 10 * addr;
3412+ } else if (!idx && !knew->index) {
34063413 idx = find_empty_mixer_ctl_idx(codec,
34073414 knew->name, 0);
34083415 if (idx <= 0)
sound/pci/hda/hda_controller.c+1−0
@@ -1231,6 +1231,7 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) · 1230 unmodified lines
12311231 continue;
12321232 codec->jackpoll_interval = chip->jackpoll_interval;
12331233 codec->beep_mode = chip->beep_mode;
1234+ codec->ctl_dev_id = chip->ctl_dev_id;
12341235 codecs++;
12351236 }
12361237 }
sound/pci/hda/hda_controller.h+1−0
@@ -124,6 +124,7 @@ struct azx { · 123 unmodified lines
124124 /* HD codec */
125125 int codec_probe_mask; /* copied from probe_mask option */
126126 unsigned int beep_mode;
127+ bool ctl_dev_id;
127128
128129 #ifdef CONFIG_SND_HDA_PATCH_LOADER
129130 const struct firmware *fw;
sound/pci/hda/hda_intel.c+5−0
@@ -119,6 +119,7 @@ static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = · 118 unmodified lines
119119 CONFIG_SND_HDA_INPUT_BEEP_MODE};
120120 #endif
121121 static bool dmic_detect = 1;
122+static bool ctl_dev_id = IS_ENABLED(CONFIG_SND_HDA_CTL_DEV_ID) ? 1 : 0;
122123
123124 module_param_array(index, int, NULL, 0444);
124125 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -157,6 +158,8 @@ module_param(dmic_detect, bool, 0444); · 32 unmodified lines
157158 MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) "
158159 "(0=off, 1=on) (default=1); "
159160 "deprecated, use snd-intel-dspcfg.dsp_driver option instead");
161+module_param(ctl_dev_id, bool, 0444);
162+MODULE_PARM_DESC(ctl_dev_id, "Use control device identifier (based on codec address).");
160163
161164 #ifdef CONFIG_PM
162165 static int param_set_xint(const char *val, const struct kernel_param *kp);
@@ -2278,6 +2281,8 @@ static int azx_probe_continue(struct azx *chip) · 2115 unmodified lines
22782281 chip->beep_mode = beep_mode[dev];
22792282 #endif
22802283
2284+ chip->ctl_dev_id = ctl_dev_id;
2285+
22812286 /* create codec instances */
22822287 if (bus->codec_mask) {
22832288 err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t