aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-12-23 04:17:52 -0500
committerTakashi Iwai <tiwai@suse.de>2010-12-23 04:22:55 -0500
commit1afe206ab6998ecd5f5485e02006b0578720a691 (patch)
tree37e8adc9f85e963cbd218e8662c5390ad2f9491b /sound
parent2d7ec12b902ae00920cee50d98757376b2fa9467 (diff)
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>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c57
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,
1919} 1919}
1920EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); 1920EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
1921 1921
1922static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name)
1923{
1924 int idx;
1925 for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
1926 if (!_snd_hda_find_mixer_ctl(codec, name, idx))
1927 return idx;
1928 }
1929 return -EBUSY;
1930}
1931
1922/** 1932/**
1923 * snd_hda_ctl_add - Add a control element and assign to the codec 1933 * snd_hda_ctl_add - Add a control element and assign to the codec
1924 * @codec: HD-audio codec 1934 * @codec: HD-audio codec
@@ -2654,8 +2664,6 @@ static struct snd_kcontrol_new dig_mixes[] = {
2654 { } /* end */ 2664 { } /* end */
2655}; 2665};
2656 2666
2657#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2658
2659/** 2667/**
2660 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls 2668 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2661 * @codec: the HDA codec 2669 * @codec: the HDA codec
@@ -2673,12 +2681,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
2673 struct snd_kcontrol_new *dig_mix; 2681 struct snd_kcontrol_new *dig_mix;
2674 int idx; 2682 int idx;
2675 2683
2676 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { 2684 idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
2677 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch", 2685 if (idx < 0) {
2678 idx))
2679 break;
2680 }
2681 if (idx >= SPDIF_MAX_IDX) {
2682 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); 2686 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2683 return -EBUSY; 2687 return -EBUSY;
2684 } 2688 }
@@ -2829,12 +2833,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
2829 struct snd_kcontrol_new *dig_mix; 2833 struct snd_kcontrol_new *dig_mix;
2830 int idx; 2834 int idx;
2831 2835
2832 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { 2836 idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
2833 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch", 2837 if (idx < 0) {
2834 idx))
2835 break;
2836 }
2837 if (idx >= SPDIF_MAX_IDX) {
2838 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); 2838 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2839 return -EBUSY; 2839 return -EBUSY;
2840 } 2840 }
@@ -3808,21 +3808,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
3808 3808
3809 for (; knew->name; knew++) { 3809 for (; knew->name; knew++) {
3810 struct snd_kcontrol *kctl; 3810 struct snd_kcontrol *kctl;
3811 int addr = 0, idx = 0;
3811 if (knew->iface == -1) /* skip this codec private value */ 3812 if (knew->iface == -1) /* skip this codec private value */
3812 continue; 3813 continue;
3813 kctl = snd_ctl_new1(knew, codec); 3814 for (;;) {
3814 if (!kctl)
3815 return -ENOMEM;
3816 err = snd_hda_ctl_add(codec, 0, kctl);
3817 if (err < 0) {
3818 if (!codec->addr)
3819 return err;
3820 kctl = snd_ctl_new1(knew, codec); 3815 kctl = snd_ctl_new1(knew, codec);
3821 if (!kctl) 3816 if (!kctl)
3822 return -ENOMEM; 3817 return -ENOMEM;
3823 kctl->id.device = codec->addr; 3818 if (addr > 0)
3819 kctl->id.device = addr;
3820 if (idx > 0)
3821 kctl->id.index = idx;
3824 err = snd_hda_ctl_add(codec, 0, kctl); 3822 err = snd_hda_ctl_add(codec, 0, kctl);
3825 if (err < 0) 3823 if (!err)
3824 break;
3825 /* try first with another device index corresponding to
3826 * the codec addr; if it still fails (or it's the
3827 * primary codec), then try another control index
3828 */
3829 if (!addr && codec->addr)
3830 addr = codec->addr;
3831 else if (!idx && !knew->index) {
3832 idx = find_empty_mixer_ctl_idx(codec,
3833 knew->name);
3834 if (idx <= 0)
3835 return err;
3836 } else
3826 return err; 3837 return err;
3827 } 3838 }
3828 } 3839 }