diff options
-rw-r--r-- | sound/pci/hda/hda_codec.c | 40 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 2 |
5 files changed, 52 insertions, 15 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 53e36495fae5..bc3ed249b0fc 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -574,6 +574,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
574 | flush_scheduled_work(); | 574 | flush_scheduled_work(); |
575 | #endif | 575 | #endif |
576 | list_del(&codec->list); | 576 | list_del(&codec->list); |
577 | snd_array_free(&codec->mixers); | ||
577 | codec->bus->caddr_tbl[codec->addr] = NULL; | 578 | codec->bus->caddr_tbl[codec->addr] = NULL; |
578 | if (codec->patch_ops.free) | 579 | if (codec->patch_ops.free) |
579 | codec->patch_ops.free(codec); | 580 | codec->patch_ops.free(codec); |
@@ -622,6 +623,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
622 | mutex_init(&codec->spdif_mutex); | 623 | mutex_init(&codec->spdif_mutex); |
623 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 624 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
624 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 625 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
626 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | ||
625 | 627 | ||
626 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 628 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
627 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 629 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
@@ -1090,6 +1092,32 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1090 | return _snd_hda_find_mixer_ctl(codec, name, 0); | 1092 | return _snd_hda_find_mixer_ctl(codec, name, 0); |
1091 | } | 1093 | } |
1092 | 1094 | ||
1095 | /* Add a control element and assign to the codec */ | ||
1096 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | ||
1097 | { | ||
1098 | int err; | ||
1099 | struct snd_kcontrol **knewp; | ||
1100 | |||
1101 | err = snd_ctl_add(codec->bus->card, kctl); | ||
1102 | if (err < 0) | ||
1103 | return err; | ||
1104 | knewp = snd_array_new(&codec->mixers); | ||
1105 | if (!knewp) | ||
1106 | return -ENOMEM; | ||
1107 | *knewp = kctl; | ||
1108 | return 0; | ||
1109 | } | ||
1110 | |||
1111 | /* Clear all controls assigned to the given codec */ | ||
1112 | void snd_hda_ctls_clear(struct hda_codec *codec) | ||
1113 | { | ||
1114 | int i; | ||
1115 | struct snd_kcontrol **kctls = codec->mixers.list; | ||
1116 | for (i = 0; i < codec->mixers.used; i++) | ||
1117 | snd_ctl_remove(codec->bus->card, kctls[i]); | ||
1118 | snd_array_free(&codec->mixers); | ||
1119 | } | ||
1120 | |||
1093 | /* create a virtual master control and add slaves */ | 1121 | /* create a virtual master control and add slaves */ |
1094 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1122 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
1095 | unsigned int *tlv, const char **slaves) | 1123 | unsigned int *tlv, const char **slaves) |
@@ -1107,7 +1135,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1107 | kctl = snd_ctl_make_virtual_master(name, tlv); | 1135 | kctl = snd_ctl_make_virtual_master(name, tlv); |
1108 | if (!kctl) | 1136 | if (!kctl) |
1109 | return -ENOMEM; | 1137 | return -ENOMEM; |
1110 | err = snd_ctl_add(codec->bus->card, kctl); | 1138 | err = snd_hda_ctl_add(codec, kctl); |
1111 | if (err < 0) | 1139 | if (err < 0) |
1112 | return err; | 1140 | return err; |
1113 | 1141 | ||
@@ -1571,7 +1599,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1571 | kctl = snd_ctl_new1(dig_mix, codec); | 1599 | kctl = snd_ctl_new1(dig_mix, codec); |
1572 | kctl->id.index = idx; | 1600 | kctl->id.index = idx; |
1573 | kctl->private_value = nid; | 1601 | kctl->private_value = nid; |
1574 | err = snd_ctl_add(codec->bus->card, kctl); | 1602 | err = snd_hda_ctl_add(codec, kctl); |
1575 | if (err < 0) | 1603 | if (err < 0) |
1576 | return err; | 1604 | return err; |
1577 | } | 1605 | } |
@@ -1615,7 +1643,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec, | |||
1615 | if (!mout->dig_out_nid) | 1643 | if (!mout->dig_out_nid) |
1616 | return 0; | 1644 | return 0; |
1617 | /* ATTENTION: here mout is passed as private_data, instead of codec */ | 1645 | /* ATTENTION: here mout is passed as private_data, instead of codec */ |
1618 | return snd_ctl_add(codec->bus->card, | 1646 | return snd_hda_ctl_add(codec, |
1619 | snd_ctl_new1(&spdif_share_sw, mout)); | 1647 | snd_ctl_new1(&spdif_share_sw, mout)); |
1620 | } | 1648 | } |
1621 | 1649 | ||
@@ -1717,7 +1745,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1717 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1745 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1718 | kctl = snd_ctl_new1(dig_mix, codec); | 1746 | kctl = snd_ctl_new1(dig_mix, codec); |
1719 | kctl->private_value = nid; | 1747 | kctl->private_value = nid; |
1720 | err = snd_ctl_add(codec->bus->card, kctl); | 1748 | err = snd_hda_ctl_add(codec, kctl); |
1721 | if (err < 0) | 1749 | if (err < 0) |
1722 | return err; | 1750 | return err; |
1723 | } | 1751 | } |
@@ -2440,7 +2468,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2440 | kctl = snd_ctl_new1(knew, codec); | 2468 | kctl = snd_ctl_new1(knew, codec); |
2441 | if (!kctl) | 2469 | if (!kctl) |
2442 | return -ENOMEM; | 2470 | return -ENOMEM; |
2443 | err = snd_ctl_add(codec->bus->card, kctl); | 2471 | err = snd_hda_ctl_add(codec, kctl); |
2444 | if (err < 0) { | 2472 | if (err < 0) { |
2445 | if (!codec->addr) | 2473 | if (!codec->addr) |
2446 | return err; | 2474 | return err; |
@@ -2448,7 +2476,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2448 | if (!kctl) | 2476 | if (!kctl) |
2449 | return -ENOMEM; | 2477 | return -ENOMEM; |
2450 | kctl->id.device = codec->addr; | 2478 | kctl->id.device = codec->addr; |
2451 | err = snd_ctl_add(codec->bus->card, kctl); | 2479 | err = snd_hda_ctl_add(codec, kctl); |
2452 | if (err < 0) | 2480 | if (err < 0) |
2453 | return err; | 2481 | return err; |
2454 | } | 2482 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 53f3b08b24cd..8813ec10ca13 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -740,6 +740,8 @@ struct hda_codec { | |||
740 | hda_nid_t start_nid; | 740 | hda_nid_t start_nid; |
741 | u32 *wcaps; | 741 | u32 *wcaps; |
742 | 742 | ||
743 | struct snd_array mixers; /* list of assigned mixer elements */ | ||
744 | |||
743 | struct hda_cache_rec amp_cache; /* cache for amp access */ | 745 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
744 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | 746 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
745 | 747 | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 0ca30894f7c6..98ff010d5b95 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -723,7 +723,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
723 | if (is_loopback) | 723 | if (is_loopback) |
724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); | 724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); |
725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
726 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 726 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
727 | if (err < 0) | ||
727 | return err; | 728 | return err; |
728 | created = 1; | 729 | created = 1; |
729 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 730 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
@@ -732,7 +733,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
732 | if (is_loopback) | 733 | if (is_loopback) |
733 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); | 734 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); |
734 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 735 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
735 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 736 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
737 | if (err < 0) | ||
736 | return err; | 738 | return err; |
737 | created = 1; | 739 | created = 1; |
738 | } | 740 | } |
@@ -745,14 +747,16 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
745 | (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { | 747 | (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { |
746 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); | 748 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); |
747 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 749 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
748 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 750 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
751 | if (err < 0) | ||
749 | return err; | 752 | return err; |
750 | created = 1; | 753 | created = 1; |
751 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 754 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
752 | (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { | 755 | (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { |
753 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); | 756 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); |
754 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 757 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
755 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 758 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
759 | if (err < 0) | ||
756 | return err; | 760 | return err; |
757 | created = 1; | 761 | created = 1; |
758 | } | 762 | } |
@@ -849,8 +853,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
849 | } | 853 | } |
850 | 854 | ||
851 | /* create input MUX if multiple sources are available */ | 855 | /* create input MUX if multiple sources are available */ |
852 | if ((err = snd_ctl_add(codec->bus->card, | 856 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec)); |
853 | snd_ctl_new1(&cap_sel, codec))) < 0) | 857 | if (err < 0) |
854 | return err; | 858 | return err; |
855 | 859 | ||
856 | /* no volume control? */ | 860 | /* no volume control? */ |
@@ -867,8 +871,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
867 | HDA_CODEC_VOLUME(name, adc_node->nid, | 871 | HDA_CODEC_VOLUME(name, adc_node->nid, |
868 | spec->input_mux.items[i].index, | 872 | spec->input_mux.items[i].index, |
869 | HDA_INPUT); | 873 | HDA_INPUT); |
870 | if ((err = snd_ctl_add(codec->bus->card, | 874 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
871 | snd_ctl_new1(&knew, codec))) < 0) | 875 | if (err < 0) |
872 | return err; | 876 | return err; |
873 | } | 877 | } |
874 | 878 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7957fefda730..48faaf8cd21b 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -393,6 +393,9 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | |||
393 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 393 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
394 | unsigned int caps); | 394 | unsigned int caps); |
395 | 395 | ||
396 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | ||
397 | void snd_hda_ctls_clear(struct hda_codec *codec); | ||
398 | |||
396 | /* | 399 | /* |
397 | * hwdep interface | 400 | * hwdep interface |
398 | */ | 401 | */ |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3db39adad79a..9c67af8e2089 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1250,7 +1250,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1250 | } | 1250 | } |
1251 | if (spec->num_dmuxes > 0) { | 1251 | if (spec->num_dmuxes > 0) { |
1252 | stac_dmux_mixer.count = spec->num_dmuxes; | 1252 | stac_dmux_mixer.count = spec->num_dmuxes; |
1253 | err = snd_ctl_add(codec->bus->card, | 1253 | err = snd_hda_ctl_add(codec, |
1254 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1254 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1255 | if (err < 0) | 1255 | if (err < 0) |
1256 | return err; | 1256 | return err; |