aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-07-30 09:01:45 -0400
committerTakashi Iwai <tiwai@suse.de>2008-10-12 20:43:01 -0400
commitd13bd412dce23eed8bc35a2499d7d88cb39a1581 (patch)
tree69d68d4db3970c0ae6239debe9c66972133173e3 /sound/pci/hda/hda_codec.c
parentf44ac8378d3d84b912b34f08afaff64182ee1b41 (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.c40
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 */
1096int 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 */
1112void 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 */
1094int snd_hda_add_vmaster(struct hda_codec *codec, char *name, 1122int 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 }