}
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
* @codec: HD-audio codec
{ } /* end */
};
-#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
-
/**
* snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
* @codec: the HDA codec
struct snd_kcontrol_new *dig_mix;
int idx;
- for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
- if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
- idx))
- break;
- }
- if (idx >= SPDIF_MAX_IDX) {
+ idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
+ if (idx < 0) {
printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
return -EBUSY;
}
struct snd_kcontrol_new *dig_mix;
int idx;
- for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
- if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
- idx))
- break;
- }
- if (idx >= SPDIF_MAX_IDX) {
+ idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
+ if (idx < 0) {
printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
return -EBUSY;
}
for (; knew->name; knew++) {
struct snd_kcontrol *kctl;
+ int addr = 0, idx = 0;
if (knew->iface == -1) /* skip this codec private value */
continue;
- kctl = snd_ctl_new1(knew, codec);
- if (!kctl)
- return -ENOMEM;
- err = snd_hda_ctl_add(codec, 0, kctl);
- if (err < 0) {
- if (!codec->addr)
- return err;
+ for (;;) {
kctl = snd_ctl_new1(knew, codec);
if (!kctl)
return -ENOMEM;
- kctl->id.device = codec->addr;
+ if (addr > 0)
+ kctl->id.device = addr;
+ if (idx > 0)
+ kctl->id.index = idx;
err = snd_hda_ctl_add(codec, 0, kctl);
- if (err < 0)
+ if (!err)
+ 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;
+ } else
return err;
}
}