diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-02-04 06:31:13 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:06 -0400 |
commit | 09f99701393c7b66bde01df6c292fe5d9f843033 (patch) | |
tree | 0b312161cb903b036f1dd5d679e4d7a1e55b5149 /sound | |
parent | bf277785d6921b8a9f8339ad5ad632aef6cae73c (diff) |
[ALSA] hda-codec - Allow multiple SPDIF devices
The current code doesn't allow multiple SPDIF devices, and causes
errors when multiple SPDIF devices are found (e.g. SPDIF out and HDMI).
This patch allows multiple SPDIF devices by incrementing the index
automatically.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-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; |