diff options
| -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 644e3f14f8c..98b6d02a36c 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 | } |
| 1920 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | 1920 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); |
| 1921 | 1921 | ||
| 1922 | static 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 | } |
