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; |
