ALSA: hda - Try to find an empty control index when it's occupied
When a mixer control element was already created with the given name, try to find another index for avoiding conflicts, instead of breaking with an error. This makes the driver more robust. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
2d7ec12b90
commit
1afe206ab6
|
@ -1919,6 +1919,16 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
|
EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
|
||||||
|
|
||||||
|
static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
|
||||||
|
if (!_snd_hda_find_mixer_ctl(codec, name, idx))
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_ctl_add - Add a control element and assign to the codec
|
* snd_hda_ctl_add - Add a control element and assign to the codec
|
||||||
* @codec: HD-audio codec
|
* @codec: HD-audio codec
|
||||||
|
@ -2654,8 +2664,6 @@ static struct snd_kcontrol_new dig_mixes[] = {
|
||||||
{ } /* end */
|
{ } /* end */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
|
* snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
|
||||||
* @codec: the HDA codec
|
* @codec: the HDA codec
|
||||||
|
@ -2673,12 +2681,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
|
||||||
struct snd_kcontrol_new *dig_mix;
|
struct snd_kcontrol_new *dig_mix;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
|
idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
|
||||||
if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
|
if (idx < 0) {
|
||||||
idx))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (idx >= SPDIF_MAX_IDX) {
|
|
||||||
printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
|
printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
@ -2829,12 +2833,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
|
||||||
struct snd_kcontrol_new *dig_mix;
|
struct snd_kcontrol_new *dig_mix;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
|
idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
|
||||||
if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
|
if (idx < 0) {
|
||||||
idx))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (idx >= SPDIF_MAX_IDX) {
|
|
||||||
printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
|
printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
@ -3808,21 +3808,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
|
||||||
|
|
||||||
for (; knew->name; knew++) {
|
for (; knew->name; knew++) {
|
||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
|
int addr = 0, idx = 0;
|
||||||
if (knew->iface == -1) /* skip this codec private value */
|
if (knew->iface == -1) /* skip this codec private value */
|
||||||
continue;
|
continue;
|
||||||
|
for (;;) {
|
||||||
kctl = snd_ctl_new1(knew, codec);
|
kctl = snd_ctl_new1(knew, codec);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
if (addr > 0)
|
||||||
|
kctl->id.device = addr;
|
||||||
|
if (idx > 0)
|
||||||
|
kctl->id.index = idx;
|
||||||
err = snd_hda_ctl_add(codec, 0, kctl);
|
err = snd_hda_ctl_add(codec, 0, kctl);
|
||||||
if (err < 0) {
|
if (!err)
|
||||||
if (!codec->addr)
|
break;
|
||||||
|
/* try first with another device index corresponding to
|
||||||
|
* the codec addr; if it still fails (or it's the
|
||||||
|
* primary codec), then try another control index
|
||||||
|
*/
|
||||||
|
if (!addr && codec->addr)
|
||||||
|
addr = codec->addr;
|
||||||
|
else if (!idx && !knew->index) {
|
||||||
|
idx = find_empty_mixer_ctl_idx(codec,
|
||||||
|
knew->name);
|
||||||
|
if (idx <= 0)
|
||||||
return err;
|
return err;
|
||||||
kctl = snd_ctl_new1(knew, codec);
|
} else
|
||||||
if (!kctl)
|
|
||||||
return -ENOMEM;
|
|
||||||
kctl->id.device = codec->addr;
|
|
||||||
err = snd_hda_ctl_add(codec, 0, kctl);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue