aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
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:02 -0400
commit6c1f45ea89b59ad2cdbfa6779e23d77b274da0a7 (patch)
tree7af39036b6bdbcfd09fb36d3c902de011d5090af /sound/pci
parentd13bd412dce23eed8bc35a2499d7d88cb39a1581 (diff)
ALSA: hda - Add codec reconfiguration feature
Added the reconfiguration feature of any individual codec. Via the reconfiguration, the old resources are released and the patch is called again to recreate the PCM and mixers in addition to the re-initialization. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_codec.c147
-rw-r--r--sound/pci/hda/hda_codec.h1
-rw-r--r--sound/pci/hda/hda_local.h2
3 files changed, 103 insertions, 47 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index bc3ed249b0fc..5b54ac07fcbd 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -344,7 +344,7 @@ static void process_unsol_events(struct work_struct *work)
344/* 344/*
345 * initialize unsolicited queue 345 * initialize unsolicited queue
346 */ 346 */
347static int __devinit init_unsol_queue(struct hda_bus *bus) 347static int init_unsol_queue(struct hda_bus *bus)
348{ 348{
349 struct hda_bus_unsolicited *unsol; 349 struct hda_bus_unsolicited *unsol;
350 350
@@ -454,7 +454,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
454/* 454/*
455 * find a matching codec preset 455 * find a matching codec preset
456 */ 456 */
457static const struct hda_codec_preset __devinit * 457static const struct hda_codec_preset *
458find_codec_preset(struct hda_codec *codec) 458find_codec_preset(struct hda_codec *codec)
459{ 459{
460 const struct hda_codec_preset **tbl, *preset; 460 const struct hda_codec_preset **tbl, *preset;
@@ -624,6 +624,13 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
624 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); 624 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
625 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); 626 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
627 if (codec->bus->modelname) {
628 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
629 if (!codec->modelname) {
630 snd_hda_codec_free(codec);
631 return -ENODEV;
632 }
633 }
627 634
628#ifdef CONFIG_SND_HDA_POWER_SAVE 635#ifdef CONFIG_SND_HDA_POWER_SAVE
629 INIT_DELAYED_WORK(&codec->power_work, hda_power_work); 636 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
@@ -672,6 +679,30 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
672 if (bus->modelname) 679 if (bus->modelname)
673 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); 680 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
674 681
682 err = snd_hda_codec_configure(codec);
683 if (err < 0) {
684 snd_hda_codec_free(codec);
685 return err;
686 }
687 snd_hda_codec_proc_new(codec);
688
689#ifdef CONFIG_SND_HDA_HWDEP
690 snd_hda_create_hwdep(codec);
691#endif
692
693 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
694 codec->subsystem_id, codec->revision_id);
695 snd_component_add(codec->bus->card, component);
696
697 if (codecp)
698 *codecp = codec;
699 return 0;
700}
701
702int snd_hda_codec_configure(struct hda_codec *codec)
703{
704 int err;
705
675 codec->preset = find_codec_preset(codec); 706 codec->preset = find_codec_preset(codec);
676 if (!codec->name) { 707 if (!codec->name) {
677 err = get_codec_name(codec); 708 err = get_codec_name(codec);
@@ -698,25 +729,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
698 printk(KERN_ERR "hda-codec: No codec parser is available\n"); 729 printk(KERN_ERR "hda-codec: No codec parser is available\n");
699 730
700 patched: 731 patched:
701 if (err < 0) { 732 if (!err && codec->patch_ops.unsol_event)
702 snd_hda_codec_free(codec); 733 err = init_unsol_queue(codec->bus);
703 return err; 734 return err;
704 }
705
706 if (codec->patch_ops.unsol_event)
707 init_unsol_queue(bus);
708
709 snd_hda_codec_proc_new(codec);
710#ifdef CONFIG_SND_HDA_HWDEP
711 snd_hda_create_hwdep(codec);
712#endif
713
714 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id);
715 snd_component_add(codec->bus->card, component);
716
717 if (codecp)
718 *codecp = codec;
719 return 0;
720} 735}
721 736
722/** 737/**
@@ -1118,6 +1133,31 @@ void snd_hda_ctls_clear(struct hda_codec *codec)
1118 snd_array_free(&codec->mixers); 1133 snd_array_free(&codec->mixers);
1119} 1134}
1120 1135
1136void snd_hda_codec_reset(struct hda_codec *codec)
1137{
1138 int i;
1139
1140#ifdef CONFIG_SND_HDA_POWER_SAVE
1141 cancel_delayed_work(&codec->power_work);
1142 flush_scheduled_work();
1143#endif
1144 snd_hda_ctls_clear(codec);
1145 /* relase PCMs */
1146 for (i = 0; i < codec->num_pcms; i++) {
1147 if (codec->pcm_info[i].pcm)
1148 snd_device_free(codec->bus->card,
1149 codec->pcm_info[i].pcm);
1150 }
1151 if (codec->patch_ops.free)
1152 codec->patch_ops.free(codec);
1153 codec->spec = NULL;
1154 free_hda_cache(&codec->amp_cache);
1155 free_hda_cache(&codec->cmd_cache);
1156 codec->num_pcms = 0;
1157 codec->pcm_info = NULL;
1158 codec->preset = NULL;
1159}
1160
1121/* create a virtual master control and add slaves */ 1161/* create a virtual master control and add slaves */
1122int snd_hda_add_vmaster(struct hda_codec *codec, char *name, 1162int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1123 unsigned int *tlv, const char **slaves) 1163 unsigned int *tlv, const char **slaves)
@@ -1939,23 +1979,30 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus)
1939 struct hda_codec *codec; 1979 struct hda_codec *codec;
1940 1980
1941 list_for_each_entry(codec, &bus->codec_list, list) { 1981 list_for_each_entry(codec, &bus->codec_list, list) {
1942 int err = 0; 1982 int err = snd_hda_codec_build_controls(codec);
1943 /* fake as if already powered-on */
1944 hda_keep_power_on(codec);
1945 /* then fire up */
1946 hda_set_power_state(codec,
1947 codec->afg ? codec->afg : codec->mfg,
1948 AC_PWRST_D0);
1949 /* continue to initialize... */
1950 if (codec->patch_ops.init)
1951 err = codec->patch_ops.init(codec);
1952 if (!err && codec->patch_ops.build_controls)
1953 err = codec->patch_ops.build_controls(codec);
1954 snd_hda_power_down(codec);
1955 if (err < 0) 1983 if (err < 0)
1956 return err; 1984 return err;
1957 } 1985 }
1986 return 0;
1987}
1958 1988
1989int snd_hda_codec_build_controls(struct hda_codec *codec)
1990{
1991 int err = 0;
1992 /* fake as if already powered-on */
1993 hda_keep_power_on(codec);
1994 /* then fire up */
1995 hda_set_power_state(codec,
1996 codec->afg ? codec->afg : codec->mfg,
1997 AC_PWRST_D0);
1998 /* continue to initialize... */
1999 if (codec->patch_ops.init)
2000 err = codec->patch_ops.init(codec);
2001 if (!err && codec->patch_ops.build_controls)
2002 err = codec->patch_ops.build_controls(codec);
2003 snd_hda_power_down(codec);
2004 if (err < 0)
2005 return err;
1959 return 0; 2006 return 0;
1960} 2007}
1961 2008
@@ -2256,8 +2303,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2256 return 0; 2303 return 0;
2257} 2304}
2258 2305
2259static int __devinit set_pcm_default_values(struct hda_codec *codec, 2306static int set_pcm_default_values(struct hda_codec *codec,
2260 struct hda_pcm_stream *info) 2307 struct hda_pcm_stream *info)
2261{ 2308{
2262 /* query support PCM information from the given NID */ 2309 /* query support PCM information from the given NID */
2263 if (info->nid && (!info->rates || !info->formats)) { 2310 if (info->nid && (!info->rates || !info->formats)) {
@@ -2331,7 +2378,7 @@ snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
2331 * 2378 *
2332 * This function returns 0 if successfull, or a negative error code. 2379 * This function returns 0 if successfull, or a negative error code.
2333 */ 2380 */
2334int __devinit snd_hda_build_pcms(struct hda_bus *bus) 2381int snd_hda_build_pcms(struct hda_bus *bus)
2335{ 2382{
2336 static const char *dev_name[HDA_PCM_NTYPES] = { 2383 static const char *dev_name[HDA_PCM_NTYPES] = {
2337 "Audio", "SPDIF", "HDMI", "Modem" 2384 "Audio", "SPDIF", "HDMI", "Modem"
@@ -2352,14 +2399,17 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
2352 list_for_each_entry(codec, &bus->codec_list, list) { 2399 list_for_each_entry(codec, &bus->codec_list, list) {
2353 unsigned int pcm; 2400 unsigned int pcm;
2354 int err; 2401 int err;
2355 if (!codec->patch_ops.build_pcms) 2402 if (!codec->num_pcms) {
2356 continue; 2403 if (!codec->patch_ops.build_pcms)
2357 err = codec->patch_ops.build_pcms(codec); 2404 continue;
2358 if (err < 0) 2405 err = codec->patch_ops.build_pcms(codec);
2359 return err; 2406 if (err < 0)
2407 return err;
2408 }
2360 for (pcm = 0; pcm < codec->num_pcms; pcm++) { 2409 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2361 struct hda_pcm *cpcm = &codec->pcm_info[pcm]; 2410 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2362 int type = cpcm->pcm_type; 2411 int type = cpcm->pcm_type;
2412 int dev;
2363 switch (type) { 2413 switch (type) {
2364 case HDA_PCM_TYPE_AUDIO: 2414 case HDA_PCM_TYPE_AUDIO:
2365 if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { 2415 if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
@@ -2367,7 +2417,7 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
2367 "Too many audio devices\n"); 2417 "Too many audio devices\n");
2368 continue; 2418 continue;
2369 } 2419 }
2370 cpcm->device = audio_idx[num_devs[type]]; 2420 dev = audio_idx[num_devs[type]];
2371 break; 2421 break;
2372 case HDA_PCM_TYPE_SPDIF: 2422 case HDA_PCM_TYPE_SPDIF:
2373 case HDA_PCM_TYPE_HDMI: 2423 case HDA_PCM_TYPE_HDMI:
@@ -2378,7 +2428,7 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
2378 dev_name[type]); 2428 dev_name[type]);
2379 continue; 2429 continue;
2380 } 2430 }
2381 cpcm->device = dev_idx[type]; 2431 dev = dev_idx[type];
2382 break; 2432 break;
2383 default: 2433 default:
2384 snd_printk(KERN_WARNING 2434 snd_printk(KERN_WARNING
@@ -2386,9 +2436,12 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
2386 continue; 2436 continue;
2387 } 2437 }
2388 num_devs[type]++; 2438 num_devs[type]++;
2389 err = snd_hda_attach_pcm(codec, cpcm); 2439 if (!cpcm->pcm) {
2390 if (err < 0) 2440 cpcm->device = dev;
2391 return err; 2441 err = snd_hda_attach_pcm(codec, cpcm);
2442 if (err < 0)
2443 return err;
2444 }
2392 } 2445 }
2393 } 2446 }
2394 return 0; 2447 return 0;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 8813ec10ca13..ce9f69bde328 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -823,6 +823,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
823 * Mixer 823 * Mixer
824 */ 824 */
825int snd_hda_build_controls(struct hda_bus *bus); 825int snd_hda_build_controls(struct hda_bus *bus);
826int snd_hda_codec_build_controls(struct hda_codec *codec);
826 827
827/* 828/*
828 * PCM 829 * PCM
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 48faaf8cd21b..d8283f1ab21a 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -96,6 +96,8 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
96 const char *name); 96 const char *name);
97int snd_hda_add_vmaster(struct hda_codec *codec, char *name, 97int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
98 unsigned int *tlv, const char **slaves); 98 unsigned int *tlv, const char **slaves);
99void snd_hda_codec_reset(struct hda_codec *codec);
100int snd_hda_codec_configure(struct hda_codec *codec);
99 101
100/* amp value bits */ 102/* amp value bits */
101#define HDA_AMP_MUTE 0x80 103#define HDA_AMP_MUTE 0x80