diff options
author | David S. Miller <davem@davemloft.net> | 2010-12-27 07:37:05 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-27 07:37:05 +0100 |
commit | 17f7f4d9fcce8f1b75b5f735569309dee7665968 (patch) | |
tree | 14d7e49ca0053a0fcab3c33b5023bf3f90c5c08a /sound/pci/hda/hda_codec.c | |
parent | Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/jkirsher... (diff) | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6 (diff) | |
download | linux-17f7f4d9fcce8f1b75b5f735569309dee7665968.tar.xz linux-17f7f4d9fcce8f1b75b5f735569309dee7665968.zip |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
net/ipv4/fib_frontend.c
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 644e3f14f8ca..98b6d02a36c9 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1919,6 +1919,16 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, } 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 @@ -2654,8 +2664,6 @@ static struct snd_kcontrol_new dig_mixes[] = { { } /* 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 @@ -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; 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; } @@ -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; 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; } @@ -3808,21 +3808,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) 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; } } |