diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-07-30 09:01:45 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-10-12 20:43:01 -0400 |
commit | d13bd412dce23eed8bc35a2499d7d88cb39a1581 (patch) | |
tree | 69d68d4db3970c0ae6239debe9c66972133173e3 /sound/pci/hda/hda_codec.c | |
parent | f44ac8378d3d84b912b34f08afaff64182ee1b41 (diff) |
ALSA: hda - Manage kcontrol lists
Manage all kcontrol elements created in the hda-intel driver.
This makes it possible to remove and reconfigure the controls
of each codec.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 40 |
1 files changed, 34 insertions, 6 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 | } |