aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-02-12 11:02:41 -0500
committerTakashi Iwai <tiwai@suse.de>2013-02-12 11:09:19 -0500
commitea9b43addc4d90ca5b029f47f85ca152320a1e8d (patch)
tree58c8b75cd440b48d71acea7cafc9e6e8689f9aa1
parent9958922a320d6ee9e9f96b30110bc3765b3e8299 (diff)
ALSA: hda - Fix broken workaround for HDMI/SPDIF conflicts
The commit [dcda58061: ALSA: hda - Add workaround for conflicting IEC958 controls] introduced a workaround for cards that have both SPDIF and HDMI devices for giving device=1 to SPDIF control elements. It turned out, however, that this workaround doesn't work well - - The workaround checks only conflicts in a single codec, but SPDIF and HDMI are provided by multiple codecs in many cases, and - ALSA mixer abstraction doesn't care about the device number in ctl elements, thus you'll get errors from amixer such as % amixer scontrols -c 0 ALSA lib simple_none.c:1551:(simple_add1) helem (MIXER,'IEC958 Playback Switch',0,1,0) appears twice or more amixer: Mixer hw:0 load error: Invalid argument This patch fixes the previous broken workaround. Instead of changing the device number of SPDIF ctl elements, shift the element indices of such controls up to 16. Also, the conflict check is performed over all codecs found on the bus. HDMI devices will be put to dev=0,index=0 as before. Only the conflicting SPDIF device is moved to a different place. The new place of SPDIF device is supposed by the updated alsa-lib HDA-Intel.conf, respectively. Reported-by: Stephan Raue <stephan@openelec.tv> Reported-by: Anssi Hannula <anssi.hannula@iki.fi> Cc: <stable@vger.kernel.org> [v3.8] Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_codec.c43
-rw-r--r--sound/pci/hda/hda_codec.h3
2 files changed, 23 insertions, 23 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e80f83568291..04b57383e8cb 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2332,11 +2332,12 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
2332EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); 2332EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
2333 2333
2334static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name, 2334static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
2335 int dev) 2335 int start_idx)
2336{ 2336{
2337 int idx; 2337 int i, idx;
2338 for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ 2338 /* 16 ctlrs should be large enough */
2339 if (!find_mixer_ctl(codec, name, dev, idx)) 2339 for (i = 0, idx = start_idx; i < 16; i++, idx++) {
2340 if (!find_mixer_ctl(codec, name, 0, idx))
2340 return idx; 2341 return idx;
2341 } 2342 }
2342 return -EBUSY; 2343 return -EBUSY;
@@ -3305,30 +3306,29 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
3305 int err; 3306 int err;
3306 struct snd_kcontrol *kctl; 3307 struct snd_kcontrol *kctl;
3307 struct snd_kcontrol_new *dig_mix; 3308 struct snd_kcontrol_new *dig_mix;
3308 int idx, dev = 0; 3309 int idx = 0;
3309 const int spdif_pcm_dev = 1; 3310 const int spdif_index = 16;
3310 struct hda_spdif_out *spdif; 3311 struct hda_spdif_out *spdif;
3312 struct hda_bus *bus = codec->bus;
3311 3313
3312 if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI && 3314 if (bus->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
3313 type == HDA_PCM_TYPE_SPDIF) { 3315 type == HDA_PCM_TYPE_SPDIF) {
3314 dev = spdif_pcm_dev; 3316 idx = spdif_index;
3315 } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF && 3317 } else if (bus->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
3316 type == HDA_PCM_TYPE_HDMI) { 3318 type == HDA_PCM_TYPE_HDMI) {
3317 for (idx = 0; idx < codec->spdif_out.used; idx++) { 3319 /* suppose a single SPDIF device */
3318 spdif = snd_array_elem(&codec->spdif_out, idx); 3320 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
3319 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { 3321 kctl = find_mixer_ctl(codec, dig_mix->name, 0, 0);
3320 kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx); 3322 if (!kctl)
3321 if (!kctl) 3323 break;
3322 break; 3324 kctl->id.index = spdif_index;
3323 kctl->id.device = spdif_pcm_dev;
3324 }
3325 } 3325 }
3326 codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI; 3326 bus->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
3327 } 3327 }
3328 if (!codec->primary_dig_out_type) 3328 if (!bus->primary_dig_out_type)
3329 codec->primary_dig_out_type = type; 3329 bus->primary_dig_out_type = type;
3330 3330
3331 idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev); 3331 idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", idx);
3332 if (idx < 0) { 3332 if (idx < 0) {
3333 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); 3333 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
3334 return -EBUSY; 3334 return -EBUSY;
@@ -3338,7 +3338,6 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
3338 kctl = snd_ctl_new1(dig_mix, codec); 3338 kctl = snd_ctl_new1(dig_mix, codec);
3339 if (!kctl) 3339 if (!kctl)
3340 return -ENOMEM; 3340 return -ENOMEM;
3341 kctl->id.device = dev;
3342 kctl->id.index = idx; 3341 kctl->id.index = idx;
3343 kctl->private_value = codec->spdif_out.used - 1; 3342 kctl->private_value = codec->spdif_out.used - 1;
3344 err = snd_hda_ctl_add(codec, associated_nid, kctl); 3343 err = snd_hda_ctl_add(codec, associated_nid, kctl);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index e8c9442d27ad..23ca1722aff1 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -679,6 +679,8 @@ struct hda_bus {
679 unsigned int response_reset:1; /* controller was reset */ 679 unsigned int response_reset:1; /* controller was reset */
680 unsigned int in_reset:1; /* during reset operation */ 680 unsigned int in_reset:1; /* during reset operation */
681 unsigned int power_keep_link_on:1; /* don't power off HDA link */ 681 unsigned int power_keep_link_on:1; /* don't power off HDA link */
682
683 int primary_dig_out_type; /* primary digital out PCM type */
682}; 684};
683 685
684/* 686/*
@@ -846,7 +848,6 @@ struct hda_codec {
846 struct mutex hash_mutex; 848 struct mutex hash_mutex;
847 struct snd_array spdif_out; 849 struct snd_array spdif_out;
848 unsigned int spdif_in_enable; /* SPDIF input enable? */ 850 unsigned int spdif_in_enable; /* SPDIF input enable? */
849 int primary_dig_out_type; /* primary digital out PCM type */
850 const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ 851 const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
851 struct snd_array init_pins; /* initial (BIOS) pin configurations */ 852 struct snd_array init_pins; /* initial (BIOS) pin configurations */
852 struct snd_array driver_pins; /* pin configs set by codec parser */ 853 struct snd_array driver_pins; /* pin configs set by codec parser */