diff options
-rw-r--r-- | sound/pci/hda/hda_codec.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 37c413923db8..ab3bb7997cd2 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1037,16 +1037,24 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
1037 | } | 1037 | } |
1038 | 1038 | ||
1039 | /* find a mixer control element with the given name */ | 1039 | /* find a mixer control element with the given name */ |
1040 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | 1040 | static struct snd_kcontrol * |
1041 | const char *name) | 1041 | _snd_hda_find_mixer_ctl(struct hda_codec *codec, |
1042 | const char *name, int idx) | ||
1042 | { | 1043 | { |
1043 | struct snd_ctl_elem_id id; | 1044 | struct snd_ctl_elem_id id; |
1044 | memset(&id, 0, sizeof(id)); | 1045 | memset(&id, 0, sizeof(id)); |
1045 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 1046 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
1047 | id.index = idx; | ||
1046 | strcpy(id.name, name); | 1048 | strcpy(id.name, name); |
1047 | return snd_ctl_find_id(codec->bus->card, &id); | 1049 | return snd_ctl_find_id(codec->bus->card, &id); |
1048 | } | 1050 | } |
1049 | 1051 | ||
1052 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | ||
1053 | const char *name) | ||
1054 | { | ||
1055 | return _snd_hda_find_mixer_ctl(codec, name, 0); | ||
1056 | } | ||
1057 | |||
1050 | /* create a virtual master control and add slaves */ | 1058 | /* create a virtual master control and add slaves */ |
1051 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1059 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
1052 | unsigned int *tlv, const char **slaves) | 1060 | unsigned int *tlv, const char **slaves) |
@@ -1481,6 +1489,8 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
1481 | { } /* end */ | 1489 | { } /* end */ |
1482 | }; | 1490 | }; |
1483 | 1491 | ||
1492 | #define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */ | ||
1493 | |||
1484 | /** | 1494 | /** |
1485 | * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls | 1495 | * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls |
1486 | * @codec: the HDA codec | 1496 | * @codec: the HDA codec |
@@ -1496,9 +1506,20 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1496 | int err; | 1506 | int err; |
1497 | struct snd_kcontrol *kctl; | 1507 | struct snd_kcontrol *kctl; |
1498 | struct snd_kcontrol_new *dig_mix; | 1508 | struct snd_kcontrol_new *dig_mix; |
1509 | int idx; | ||
1499 | 1510 | ||
1511 | for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { | ||
1512 | if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch", | ||
1513 | idx)) | ||
1514 | break; | ||
1515 | } | ||
1516 | if (idx >= SPDIF_MAX_IDX) { | ||
1517 | printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); | ||
1518 | return -EBUSY; | ||
1519 | } | ||
1500 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { | 1520 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { |
1501 | kctl = snd_ctl_new1(dig_mix, codec); | 1521 | kctl = snd_ctl_new1(dig_mix, codec); |
1522 | kctl->id.index = idx; | ||
1502 | kctl->private_value = nid; | 1523 | kctl->private_value = nid; |
1503 | err = snd_ctl_add(codec->bus->card, kctl); | 1524 | err = snd_ctl_add(codec->bus->card, kctl); |
1504 | if (err < 0) | 1525 | if (err < 0) |
@@ -1595,7 +1616,17 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1595 | int err; | 1616 | int err; |
1596 | struct snd_kcontrol *kctl; | 1617 | struct snd_kcontrol *kctl; |
1597 | struct snd_kcontrol_new *dig_mix; | 1618 | struct snd_kcontrol_new *dig_mix; |
1619 | int idx; | ||
1598 | 1620 | ||
1621 | for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { | ||
1622 | if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch", | ||
1623 | idx)) | ||
1624 | break; | ||
1625 | } | ||
1626 | if (idx >= SPDIF_MAX_IDX) { | ||
1627 | printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); | ||
1628 | return -EBUSY; | ||
1629 | } | ||
1599 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1630 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1600 | kctl = snd_ctl_new1(dig_mix, codec); | 1631 | kctl = snd_ctl_new1(dig_mix, codec); |
1601 | kctl->private_value = nid; | 1632 | kctl->private_value = nid; |