diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/Kconfig | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 428 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 46 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 228 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 121 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 10 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 44 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 56 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 11 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 86 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 249 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 71 |
13 files changed, 960 insertions, 411 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 7003711f4fcc..7e408908b755 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -501,6 +501,7 @@ config SND_HDA_INTEL | |||
501 | tristate "Intel HD Audio" | 501 | tristate "Intel HD Audio" |
502 | select SND_PCM | 502 | select SND_PCM |
503 | select SND_VMASTER | 503 | select SND_VMASTER |
504 | select SND_JACK if INPUT=y || INPUT=SND | ||
504 | help | 505 | help |
505 | Say Y here to include support for Intel "High Definition | 506 | Say Y here to include support for Intel "High Definition |
506 | Audio" (Azalia) motherboard devices. | 507 | Audio" (Azalia) motherboard devices. |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6447754ae56e..eaa8b5676eae 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -107,6 +107,52 @@ static void hda_keep_power_on(struct hda_codec *codec); | |||
107 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | 107 | static inline void hda_keep_power_on(struct hda_codec *codec) {} |
108 | #endif | 108 | #endif |
109 | 109 | ||
110 | const char *snd_hda_get_jack_location(u32 cfg) | ||
111 | { | ||
112 | static char *bases[7] = { | ||
113 | "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", | ||
114 | }; | ||
115 | static unsigned char specials_idx[] = { | ||
116 | 0x07, 0x08, | ||
117 | 0x17, 0x18, 0x19, | ||
118 | 0x37, 0x38 | ||
119 | }; | ||
120 | static char *specials[] = { | ||
121 | "Rear Panel", "Drive Bar", | ||
122 | "Riser", "HDMI", "ATAPI", | ||
123 | "Mobile-In", "Mobile-Out" | ||
124 | }; | ||
125 | int i; | ||
126 | cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; | ||
127 | if ((cfg & 0x0f) < 7) | ||
128 | return bases[cfg & 0x0f]; | ||
129 | for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { | ||
130 | if (cfg == specials_idx[i]) | ||
131 | return specials[i]; | ||
132 | } | ||
133 | return "UNKNOWN"; | ||
134 | } | ||
135 | |||
136 | const char *snd_hda_get_jack_connectivity(u32 cfg) | ||
137 | { | ||
138 | static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; | ||
139 | |||
140 | return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; | ||
141 | } | ||
142 | |||
143 | const char *snd_hda_get_jack_type(u32 cfg) | ||
144 | { | ||
145 | static char *jack_types[16] = { | ||
146 | "Line Out", "Speaker", "HP Out", "CD", | ||
147 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | ||
148 | "Line In", "Aux", "Mic", "Telephony", | ||
149 | "SPDIF In", "Digitial In", "Reserved", "Other" | ||
150 | }; | ||
151 | |||
152 | return jack_types[(cfg & AC_DEFCFG_DEVICE) | ||
153 | >> AC_DEFCFG_DEVICE_SHIFT]; | ||
154 | } | ||
155 | |||
110 | /** | 156 | /** |
111 | * snd_hda_codec_read - send a command and get the response | 157 | * snd_hda_codec_read - send a command and get the response |
112 | * @codec: the HDA codec | 158 | * @codec: the HDA codec |
@@ -344,7 +390,7 @@ static void process_unsol_events(struct work_struct *work) | |||
344 | /* | 390 | /* |
345 | * initialize unsolicited queue | 391 | * initialize unsolicited queue |
346 | */ | 392 | */ |
347 | static int __devinit init_unsol_queue(struct hda_bus *bus) | 393 | static int init_unsol_queue(struct hda_bus *bus) |
348 | { | 394 | { |
349 | struct hda_bus_unsolicited *unsol; | 395 | struct hda_bus_unsolicited *unsol; |
350 | 396 | ||
@@ -393,6 +439,20 @@ static int snd_hda_bus_dev_free(struct snd_device *device) | |||
393 | return snd_hda_bus_free(bus); | 439 | return snd_hda_bus_free(bus); |
394 | } | 440 | } |
395 | 441 | ||
442 | #ifdef CONFIG_SND_HDA_HWDEP | ||
443 | static int snd_hda_bus_dev_register(struct snd_device *device) | ||
444 | { | ||
445 | struct hda_bus *bus = device->device_data; | ||
446 | struct hda_codec *codec; | ||
447 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
448 | snd_hda_hwdep_add_sysfs(codec); | ||
449 | } | ||
450 | return 0; | ||
451 | } | ||
452 | #else | ||
453 | #define snd_hda_bus_dev_register NULL | ||
454 | #endif | ||
455 | |||
396 | /** | 456 | /** |
397 | * snd_hda_bus_new - create a HDA bus | 457 | * snd_hda_bus_new - create a HDA bus |
398 | * @card: the card entry | 458 | * @card: the card entry |
@@ -408,6 +468,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
408 | struct hda_bus *bus; | 468 | struct hda_bus *bus; |
409 | int err; | 469 | int err; |
410 | static struct snd_device_ops dev_ops = { | 470 | static struct snd_device_ops dev_ops = { |
471 | .dev_register = snd_hda_bus_dev_register, | ||
411 | .dev_free = snd_hda_bus_dev_free, | 472 | .dev_free = snd_hda_bus_dev_free, |
412 | }; | 473 | }; |
413 | 474 | ||
@@ -446,7 +507,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
446 | 507 | ||
447 | #ifdef CONFIG_SND_HDA_GENERIC | 508 | #ifdef CONFIG_SND_HDA_GENERIC |
448 | #define is_generic_config(codec) \ | 509 | #define is_generic_config(codec) \ |
449 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 510 | (codec->modelname && !strcmp(codec->modelname, "generic")) |
450 | #else | 511 | #else |
451 | #define is_generic_config(codec) 0 | 512 | #define is_generic_config(codec) 0 |
452 | #endif | 513 | #endif |
@@ -454,7 +515,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
454 | /* | 515 | /* |
455 | * find a matching codec preset | 516 | * find a matching codec preset |
456 | */ | 517 | */ |
457 | static const struct hda_codec_preset __devinit * | 518 | static const struct hda_codec_preset * |
458 | find_codec_preset(struct hda_codec *codec) | 519 | find_codec_preset(struct hda_codec *codec) |
459 | { | 520 | { |
460 | const struct hda_codec_preset **tbl, *preset; | 521 | const struct hda_codec_preset **tbl, *preset; |
@@ -481,15 +542,14 @@ find_codec_preset(struct hda_codec *codec) | |||
481 | } | 542 | } |
482 | 543 | ||
483 | /* | 544 | /* |
484 | * snd_hda_get_codec_name - store the codec name | 545 | * get_codec_name - store the codec name |
485 | */ | 546 | */ |
486 | void snd_hda_get_codec_name(struct hda_codec *codec, | 547 | static int get_codec_name(struct hda_codec *codec) |
487 | char *name, int namelen) | ||
488 | { | 548 | { |
489 | const struct hda_vendor_id *c; | 549 | const struct hda_vendor_id *c; |
490 | const char *vendor = NULL; | 550 | const char *vendor = NULL; |
491 | u16 vendor_id = codec->vendor_id >> 16; | 551 | u16 vendor_id = codec->vendor_id >> 16; |
492 | char tmp[16]; | 552 | char tmp[16], name[32]; |
493 | 553 | ||
494 | for (c = hda_vendor_ids; c->id; c++) { | 554 | for (c = hda_vendor_ids; c->id; c++) { |
495 | if (c->id == vendor_id) { | 555 | if (c->id == vendor_id) { |
@@ -502,10 +562,15 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
502 | vendor = tmp; | 562 | vendor = tmp; |
503 | } | 563 | } |
504 | if (codec->preset && codec->preset->name) | 564 | if (codec->preset && codec->preset->name) |
505 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); | 565 | snprintf(name, sizeof(name), "%s %s", vendor, |
566 | codec->preset->name); | ||
506 | else | 567 | else |
507 | snprintf(name, namelen, "%s ID %x", vendor, | 568 | snprintf(name, sizeof(name), "%s ID %x", vendor, |
508 | codec->vendor_id & 0xffff); | 569 | codec->vendor_id & 0xffff); |
570 | codec->name = kstrdup(name, GFP_KERNEL); | ||
571 | if (!codec->name) | ||
572 | return -ENOMEM; | ||
573 | return 0; | ||
509 | } | 574 | } |
510 | 575 | ||
511 | /* | 576 | /* |
@@ -570,11 +635,14 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
570 | flush_scheduled_work(); | 635 | flush_scheduled_work(); |
571 | #endif | 636 | #endif |
572 | list_del(&codec->list); | 637 | list_del(&codec->list); |
638 | snd_array_free(&codec->mixers); | ||
573 | codec->bus->caddr_tbl[codec->addr] = NULL; | 639 | codec->bus->caddr_tbl[codec->addr] = NULL; |
574 | if (codec->patch_ops.free) | 640 | if (codec->patch_ops.free) |
575 | codec->patch_ops.free(codec); | 641 | codec->patch_ops.free(codec); |
576 | free_hda_cache(&codec->amp_cache); | 642 | free_hda_cache(&codec->amp_cache); |
577 | free_hda_cache(&codec->cmd_cache); | 643 | free_hda_cache(&codec->cmd_cache); |
644 | kfree(codec->name); | ||
645 | kfree(codec->modelname); | ||
578 | kfree(codec->wcaps); | 646 | kfree(codec->wcaps); |
579 | kfree(codec); | 647 | kfree(codec); |
580 | } | 648 | } |
@@ -616,6 +684,14 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
616 | mutex_init(&codec->spdif_mutex); | 684 | mutex_init(&codec->spdif_mutex); |
617 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 685 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
618 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 686 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
687 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | ||
688 | if (codec->bus->modelname) { | ||
689 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | ||
690 | if (!codec->modelname) { | ||
691 | snd_hda_codec_free(codec); | ||
692 | return -ENODEV; | ||
693 | } | ||
694 | } | ||
619 | 695 | ||
620 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 696 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
621 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 697 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
@@ -661,12 +737,41 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
661 | snd_hda_codec_read(codec, nid, 0, | 737 | snd_hda_codec_read(codec, nid, 0, |
662 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 738 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
663 | } | 739 | } |
740 | if (bus->modelname) | ||
741 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | ||
742 | |||
743 | err = snd_hda_codec_configure(codec); | ||
744 | if (err < 0) { | ||
745 | snd_hda_codec_free(codec); | ||
746 | return err; | ||
747 | } | ||
748 | snd_hda_codec_proc_new(codec); | ||
749 | |||
750 | snd_hda_create_hwdep(codec); | ||
751 | |||
752 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, | ||
753 | codec->subsystem_id, codec->revision_id); | ||
754 | snd_component_add(codec->bus->card, component); | ||
755 | |||
756 | if (codecp) | ||
757 | *codecp = codec; | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | int snd_hda_codec_configure(struct hda_codec *codec) | ||
762 | { | ||
763 | int err; | ||
664 | 764 | ||
665 | codec->preset = find_codec_preset(codec); | 765 | codec->preset = find_codec_preset(codec); |
766 | if (!codec->name) { | ||
767 | err = get_codec_name(codec); | ||
768 | if (err < 0) | ||
769 | return err; | ||
770 | } | ||
666 | /* audio codec should override the mixer name */ | 771 | /* audio codec should override the mixer name */ |
667 | if (codec->afg || !*bus->card->mixername) | 772 | if (codec->afg || !*codec->bus->card->mixername) |
668 | snd_hda_get_codec_name(codec, bus->card->mixername, | 773 | strlcpy(codec->bus->card->mixername, codec->name, |
669 | sizeof(bus->card->mixername)); | 774 | sizeof(codec->bus->card->mixername)); |
670 | 775 | ||
671 | if (is_generic_config(codec)) { | 776 | if (is_generic_config(codec)) { |
672 | err = snd_hda_parse_generic_codec(codec); | 777 | err = snd_hda_parse_generic_codec(codec); |
@@ -683,25 +788,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
683 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 788 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); |
684 | 789 | ||
685 | patched: | 790 | patched: |
686 | if (err < 0) { | 791 | if (!err && codec->patch_ops.unsol_event) |
687 | snd_hda_codec_free(codec); | 792 | err = init_unsol_queue(codec->bus); |
688 | return err; | 793 | return err; |
689 | } | ||
690 | |||
691 | if (codec->patch_ops.unsol_event) | ||
692 | init_unsol_queue(bus); | ||
693 | |||
694 | snd_hda_codec_proc_new(codec); | ||
695 | #ifdef CONFIG_SND_HDA_HWDEP | ||
696 | snd_hda_create_hwdep(codec); | ||
697 | #endif | ||
698 | |||
699 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id); | ||
700 | snd_component_add(codec->bus->card, component); | ||
701 | |||
702 | if (codecp) | ||
703 | *codecp = codec; | ||
704 | return 0; | ||
705 | } | 794 | } |
706 | 795 | ||
707 | /** | 796 | /** |
@@ -756,12 +845,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache, | |||
756 | { | 845 | { |
757 | memset(cache, 0, sizeof(*cache)); | 846 | memset(cache, 0, sizeof(*cache)); |
758 | memset(cache->hash, 0xff, sizeof(cache->hash)); | 847 | memset(cache->hash, 0xff, sizeof(cache->hash)); |
759 | cache->record_size = record_size; | 848 | snd_array_init(&cache->buf, record_size, 64); |
760 | } | 849 | } |
761 | 850 | ||
762 | static void free_hda_cache(struct hda_cache_rec *cache) | 851 | static void free_hda_cache(struct hda_cache_rec *cache) |
763 | { | 852 | { |
764 | kfree(cache->buffer); | 853 | snd_array_free(&cache->buf); |
765 | } | 854 | } |
766 | 855 | ||
767 | /* query the hash. allocate an entry if not found. */ | 856 | /* query the hash. allocate an entry if not found. */ |
@@ -770,38 +859,18 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
770 | { | 859 | { |
771 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 860 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
772 | u16 cur = cache->hash[idx]; | 861 | u16 cur = cache->hash[idx]; |
862 | struct hda_cache_head *info_head = cache->buf.list; | ||
773 | struct hda_cache_head *info; | 863 | struct hda_cache_head *info; |
774 | 864 | ||
775 | while (cur != 0xffff) { | 865 | while (cur != 0xffff) { |
776 | info = (struct hda_cache_head *)(cache->buffer + | 866 | info = &info_head[cur]; |
777 | cur * cache->record_size); | ||
778 | if (info->key == key) | 867 | if (info->key == key) |
779 | return info; | 868 | return info; |
780 | cur = info->next; | 869 | cur = info->next; |
781 | } | 870 | } |
782 | 871 | ||
783 | /* add a new hash entry */ | 872 | /* add a new hash entry */ |
784 | if (cache->num_entries >= cache->size) { | 873 | info = snd_array_new(&cache->buf); |
785 | /* reallocate the array */ | ||
786 | unsigned int new_size = cache->size + 64; | ||
787 | void *new_buffer; | ||
788 | new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL); | ||
789 | if (!new_buffer) { | ||
790 | snd_printk(KERN_ERR "hda_codec: " | ||
791 | "can't malloc amp_info\n"); | ||
792 | return NULL; | ||
793 | } | ||
794 | if (cache->buffer) { | ||
795 | memcpy(new_buffer, cache->buffer, | ||
796 | cache->size * cache->record_size); | ||
797 | kfree(cache->buffer); | ||
798 | } | ||
799 | cache->size = new_size; | ||
800 | cache->buffer = new_buffer; | ||
801 | } | ||
802 | cur = cache->num_entries++; | ||
803 | info = (struct hda_cache_head *)(cache->buffer + | ||
804 | cur * cache->record_size); | ||
805 | info->key = key; | 874 | info->key = key; |
806 | info->val = 0; | 875 | info->val = 0; |
807 | info->next = cache->hash[idx]; | 876 | info->next = cache->hash[idx]; |
@@ -942,10 +1011,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
942 | /* resume the all amp commands from the cache */ | 1011 | /* resume the all amp commands from the cache */ |
943 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | 1012 | void snd_hda_codec_resume_amp(struct hda_codec *codec) |
944 | { | 1013 | { |
945 | struct hda_amp_info *buffer = codec->amp_cache.buffer; | 1014 | struct hda_amp_info *buffer = codec->amp_cache.buf.list; |
946 | int i; | 1015 | int i; |
947 | 1016 | ||
948 | for (i = 0; i < codec->amp_cache.size; i++, buffer++) { | 1017 | for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) { |
949 | u32 key = buffer->head.key; | 1018 | u32 key = buffer->head.key; |
950 | hda_nid_t nid; | 1019 | hda_nid_t nid; |
951 | unsigned int idx, dir, ch; | 1020 | unsigned int idx, dir, ch; |
@@ -1097,6 +1166,57 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1097 | return _snd_hda_find_mixer_ctl(codec, name, 0); | 1166 | return _snd_hda_find_mixer_ctl(codec, name, 0); |
1098 | } | 1167 | } |
1099 | 1168 | ||
1169 | /* Add a control element and assign to the codec */ | ||
1170 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | ||
1171 | { | ||
1172 | int err; | ||
1173 | struct snd_kcontrol **knewp; | ||
1174 | |||
1175 | err = snd_ctl_add(codec->bus->card, kctl); | ||
1176 | if (err < 0) | ||
1177 | return err; | ||
1178 | knewp = snd_array_new(&codec->mixers); | ||
1179 | if (!knewp) | ||
1180 | return -ENOMEM; | ||
1181 | *knewp = kctl; | ||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | /* Clear all controls assigned to the given codec */ | ||
1186 | void snd_hda_ctls_clear(struct hda_codec *codec) | ||
1187 | { | ||
1188 | int i; | ||
1189 | struct snd_kcontrol **kctls = codec->mixers.list; | ||
1190 | for (i = 0; i < codec->mixers.used; i++) | ||
1191 | snd_ctl_remove(codec->bus->card, kctls[i]); | ||
1192 | snd_array_free(&codec->mixers); | ||
1193 | } | ||
1194 | |||
1195 | void snd_hda_codec_reset(struct hda_codec *codec) | ||
1196 | { | ||
1197 | int i; | ||
1198 | |||
1199 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1200 | cancel_delayed_work(&codec->power_work); | ||
1201 | flush_scheduled_work(); | ||
1202 | #endif | ||
1203 | snd_hda_ctls_clear(codec); | ||
1204 | /* relase PCMs */ | ||
1205 | for (i = 0; i < codec->num_pcms; i++) { | ||
1206 | if (codec->pcm_info[i].pcm) | ||
1207 | snd_device_free(codec->bus->card, | ||
1208 | codec->pcm_info[i].pcm); | ||
1209 | } | ||
1210 | if (codec->patch_ops.free) | ||
1211 | codec->patch_ops.free(codec); | ||
1212 | codec->spec = NULL; | ||
1213 | free_hda_cache(&codec->amp_cache); | ||
1214 | free_hda_cache(&codec->cmd_cache); | ||
1215 | codec->num_pcms = 0; | ||
1216 | codec->pcm_info = NULL; | ||
1217 | codec->preset = NULL; | ||
1218 | } | ||
1219 | |||
1100 | /* create a virtual master control and add slaves */ | 1220 | /* create a virtual master control and add slaves */ |
1101 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1221 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
1102 | unsigned int *tlv, const char **slaves) | 1222 | unsigned int *tlv, const char **slaves) |
@@ -1114,7 +1234,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1114 | kctl = snd_ctl_make_virtual_master(name, tlv); | 1234 | kctl = snd_ctl_make_virtual_master(name, tlv); |
1115 | if (!kctl) | 1235 | if (!kctl) |
1116 | return -ENOMEM; | 1236 | return -ENOMEM; |
1117 | err = snd_ctl_add(codec->bus->card, kctl); | 1237 | err = snd_hda_ctl_add(codec, kctl); |
1118 | if (err < 0) | 1238 | if (err < 0) |
1119 | return err; | 1239 | return err; |
1120 | 1240 | ||
@@ -1578,7 +1698,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1578 | kctl = snd_ctl_new1(dig_mix, codec); | 1698 | kctl = snd_ctl_new1(dig_mix, codec); |
1579 | kctl->id.index = idx; | 1699 | kctl->id.index = idx; |
1580 | kctl->private_value = nid; | 1700 | kctl->private_value = nid; |
1581 | err = snd_ctl_add(codec->bus->card, kctl); | 1701 | err = snd_hda_ctl_add(codec, kctl); |
1582 | if (err < 0) | 1702 | if (err < 0) |
1583 | return err; | 1703 | return err; |
1584 | } | 1704 | } |
@@ -1622,7 +1742,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec, | |||
1622 | if (!mout->dig_out_nid) | 1742 | if (!mout->dig_out_nid) |
1623 | return 0; | 1743 | return 0; |
1624 | /* ATTENTION: here mout is passed as private_data, instead of codec */ | 1744 | /* ATTENTION: here mout is passed as private_data, instead of codec */ |
1625 | return snd_ctl_add(codec->bus->card, | 1745 | return snd_hda_ctl_add(codec, |
1626 | snd_ctl_new1(&spdif_share_sw, mout)); | 1746 | snd_ctl_new1(&spdif_share_sw, mout)); |
1627 | } | 1747 | } |
1628 | 1748 | ||
@@ -1724,7 +1844,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1724 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1844 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1725 | kctl = snd_ctl_new1(dig_mix, codec); | 1845 | kctl = snd_ctl_new1(dig_mix, codec); |
1726 | kctl->private_value = nid; | 1846 | kctl->private_value = nid; |
1727 | err = snd_ctl_add(codec->bus->card, kctl); | 1847 | err = snd_hda_ctl_add(codec, kctl); |
1728 | if (err < 0) | 1848 | if (err < 0) |
1729 | return err; | 1849 | return err; |
1730 | } | 1850 | } |
@@ -1779,10 +1899,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1779 | /* resume the all commands from the cache */ | 1899 | /* resume the all commands from the cache */ |
1780 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | 1900 | void snd_hda_codec_resume_cache(struct hda_codec *codec) |
1781 | { | 1901 | { |
1782 | struct hda_cache_head *buffer = codec->cmd_cache.buffer; | 1902 | struct hda_cache_head *buffer = codec->cmd_cache.buf.list; |
1783 | int i; | 1903 | int i; |
1784 | 1904 | ||
1785 | for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { | 1905 | for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) { |
1786 | u32 key = buffer->key; | 1906 | u32 key = buffer->key; |
1787 | if (!key) | 1907 | if (!key) |
1788 | continue; | 1908 | continue; |
@@ -1867,6 +1987,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
1867 | } | 1987 | } |
1868 | } | 1988 | } |
1869 | 1989 | ||
1990 | #ifdef CONFIG_SND_HDA_HWDEP | ||
1991 | /* execute additional init verbs */ | ||
1992 | static void hda_exec_init_verbs(struct hda_codec *codec) | ||
1993 | { | ||
1994 | if (codec->init_verbs.list) | ||
1995 | snd_hda_sequence_write(codec, codec->init_verbs.list); | ||
1996 | } | ||
1997 | #else | ||
1998 | static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | ||
1999 | #endif | ||
2000 | |||
1870 | #ifdef SND_HDA_NEEDS_RESUME | 2001 | #ifdef SND_HDA_NEEDS_RESUME |
1871 | /* | 2002 | /* |
1872 | * call suspend and power-down; used both from PM and power-save | 2003 | * call suspend and power-down; used both from PM and power-save |
@@ -1893,6 +2024,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
1893 | hda_set_power_state(codec, | 2024 | hda_set_power_state(codec, |
1894 | codec->afg ? codec->afg : codec->mfg, | 2025 | codec->afg ? codec->afg : codec->mfg, |
1895 | AC_PWRST_D0); | 2026 | AC_PWRST_D0); |
2027 | hda_exec_init_verbs(codec); | ||
1896 | if (codec->patch_ops.resume) | 2028 | if (codec->patch_ops.resume) |
1897 | codec->patch_ops.resume(codec); | 2029 | codec->patch_ops.resume(codec); |
1898 | else { | 2030 | else { |
@@ -1918,23 +2050,31 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1918 | struct hda_codec *codec; | 2050 | struct hda_codec *codec; |
1919 | 2051 | ||
1920 | list_for_each_entry(codec, &bus->codec_list, list) { | 2052 | list_for_each_entry(codec, &bus->codec_list, list) { |
1921 | int err = 0; | 2053 | int err = snd_hda_codec_build_controls(codec); |
1922 | /* fake as if already powered-on */ | ||
1923 | hda_keep_power_on(codec); | ||
1924 | /* then fire up */ | ||
1925 | hda_set_power_state(codec, | ||
1926 | codec->afg ? codec->afg : codec->mfg, | ||
1927 | AC_PWRST_D0); | ||
1928 | /* continue to initialize... */ | ||
1929 | if (codec->patch_ops.init) | ||
1930 | err = codec->patch_ops.init(codec); | ||
1931 | if (!err && codec->patch_ops.build_controls) | ||
1932 | err = codec->patch_ops.build_controls(codec); | ||
1933 | snd_hda_power_down(codec); | ||
1934 | if (err < 0) | 2054 | if (err < 0) |
1935 | return err; | 2055 | return err; |
1936 | } | 2056 | } |
2057 | return 0; | ||
2058 | } | ||
1937 | 2059 | ||
2060 | int snd_hda_codec_build_controls(struct hda_codec *codec) | ||
2061 | { | ||
2062 | int err = 0; | ||
2063 | /* fake as if already powered-on */ | ||
2064 | hda_keep_power_on(codec); | ||
2065 | /* then fire up */ | ||
2066 | hda_set_power_state(codec, | ||
2067 | codec->afg ? codec->afg : codec->mfg, | ||
2068 | AC_PWRST_D0); | ||
2069 | hda_exec_init_verbs(codec); | ||
2070 | /* continue to initialize... */ | ||
2071 | if (codec->patch_ops.init) | ||
2072 | err = codec->patch_ops.init(codec); | ||
2073 | if (!err && codec->patch_ops.build_controls) | ||
2074 | err = codec->patch_ops.build_controls(codec); | ||
2075 | snd_hda_power_down(codec); | ||
2076 | if (err < 0) | ||
2077 | return err; | ||
1938 | return 0; | 2078 | return 0; |
1939 | } | 2079 | } |
1940 | 2080 | ||
@@ -2235,8 +2375,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2235 | return 0; | 2375 | return 0; |
2236 | } | 2376 | } |
2237 | 2377 | ||
2238 | static int __devinit set_pcm_default_values(struct hda_codec *codec, | 2378 | static int set_pcm_default_values(struct hda_codec *codec, |
2239 | struct hda_pcm_stream *info) | 2379 | struct hda_pcm_stream *info) |
2240 | { | 2380 | { |
2241 | /* query support PCM information from the given NID */ | 2381 | /* query support PCM information from the given NID */ |
2242 | if (info->nid && (!info->rates || !info->formats)) { | 2382 | if (info->nid && (!info->rates || !info->formats)) { |
@@ -2262,6 +2402,28 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2262 | return 0; | 2402 | return 0; |
2263 | } | 2403 | } |
2264 | 2404 | ||
2405 | /* | ||
2406 | * attach a new PCM stream | ||
2407 | */ | ||
2408 | static int __devinit | ||
2409 | snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | ||
2410 | { | ||
2411 | struct hda_pcm_stream *info; | ||
2412 | int stream, err; | ||
2413 | |||
2414 | if (!pcm->name) | ||
2415 | return -EINVAL; | ||
2416 | for (stream = 0; stream < 2; stream++) { | ||
2417 | info = &pcm->stream[stream]; | ||
2418 | if (info->substreams) { | ||
2419 | err = set_pcm_default_values(codec, info); | ||
2420 | if (err < 0) | ||
2421 | return err; | ||
2422 | } | ||
2423 | } | ||
2424 | return codec->bus->ops.attach_pcm(codec, pcm); | ||
2425 | } | ||
2426 | |||
2265 | /** | 2427 | /** |
2266 | * snd_hda_build_pcms - build PCM information | 2428 | * snd_hda_build_pcms - build PCM information |
2267 | * @bus: the BUS | 2429 | * @bus: the BUS |
@@ -2288,25 +2450,67 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2288 | * | 2450 | * |
2289 | * This function returns 0 if successfull, or a negative error code. | 2451 | * This function returns 0 if successfull, or a negative error code. |
2290 | */ | 2452 | */ |
2291 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) | 2453 | int snd_hda_build_pcms(struct hda_bus *bus) |
2292 | { | 2454 | { |
2455 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2456 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2457 | }; | ||
2458 | /* starting device index for each PCM type */ | ||
2459 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2460 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2461 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2462 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2463 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2464 | }; | ||
2465 | /* normal audio device indices; not linear to keep compatibility */ | ||
2466 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2293 | struct hda_codec *codec; | 2467 | struct hda_codec *codec; |
2468 | int num_devs[HDA_PCM_NTYPES]; | ||
2294 | 2469 | ||
2470 | memset(num_devs, 0, sizeof(num_devs)); | ||
2295 | list_for_each_entry(codec, &bus->codec_list, list) { | 2471 | list_for_each_entry(codec, &bus->codec_list, list) { |
2296 | unsigned int pcm, s; | 2472 | unsigned int pcm; |
2297 | int err; | 2473 | int err; |
2298 | if (!codec->patch_ops.build_pcms) | 2474 | if (!codec->num_pcms) { |
2299 | continue; | 2475 | if (!codec->patch_ops.build_pcms) |
2300 | err = codec->patch_ops.build_pcms(codec); | 2476 | continue; |
2301 | if (err < 0) | 2477 | err = codec->patch_ops.build_pcms(codec); |
2302 | return err; | 2478 | if (err < 0) |
2479 | return err; | ||
2480 | } | ||
2303 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2481 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2304 | for (s = 0; s < 2; s++) { | 2482 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2305 | struct hda_pcm_stream *info; | 2483 | int type = cpcm->pcm_type; |
2306 | info = &codec->pcm_info[pcm].stream[s]; | 2484 | int dev; |
2307 | if (!info->substreams) | 2485 | switch (type) { |
2486 | case HDA_PCM_TYPE_AUDIO: | ||
2487 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
2488 | snd_printk(KERN_WARNING | ||
2489 | "Too many audio devices\n"); | ||
2308 | continue; | 2490 | continue; |
2309 | err = set_pcm_default_values(codec, info); | 2491 | } |
2492 | dev = audio_idx[num_devs[type]]; | ||
2493 | break; | ||
2494 | case HDA_PCM_TYPE_SPDIF: | ||
2495 | case HDA_PCM_TYPE_HDMI: | ||
2496 | case HDA_PCM_TYPE_MODEM: | ||
2497 | if (num_devs[type]) { | ||
2498 | snd_printk(KERN_WARNING | ||
2499 | "%s already defined\n", | ||
2500 | dev_name[type]); | ||
2501 | continue; | ||
2502 | } | ||
2503 | dev = dev_idx[type]; | ||
2504 | break; | ||
2505 | default: | ||
2506 | snd_printk(KERN_WARNING | ||
2507 | "Invalid PCM type %d\n", type); | ||
2508 | continue; | ||
2509 | } | ||
2510 | num_devs[type]++; | ||
2511 | if (!cpcm->pcm) { | ||
2512 | cpcm->device = dev; | ||
2513 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2310 | if (err < 0) | 2514 | if (err < 0) |
2311 | return err; | 2515 | return err; |
2312 | } | 2516 | } |
@@ -2332,11 +2536,11 @@ int snd_hda_check_board_config(struct hda_codec *codec, | |||
2332 | int num_configs, const char **models, | 2536 | int num_configs, const char **models, |
2333 | const struct snd_pci_quirk *tbl) | 2537 | const struct snd_pci_quirk *tbl) |
2334 | { | 2538 | { |
2335 | if (codec->bus->modelname && models) { | 2539 | if (codec->modelname && models) { |
2336 | int i; | 2540 | int i; |
2337 | for (i = 0; i < num_configs; i++) { | 2541 | for (i = 0; i < num_configs; i++) { |
2338 | if (models[i] && | 2542 | if (models[i] && |
2339 | !strcmp(codec->bus->modelname, models[i])) { | 2543 | !strcmp(codec->modelname, models[i])) { |
2340 | snd_printd(KERN_INFO "hda_codec: model '%s' is " | 2544 | snd_printd(KERN_INFO "hda_codec: model '%s' is " |
2341 | "selected\n", models[i]); | 2545 | "selected\n", models[i]); |
2342 | return i; | 2546 | return i; |
@@ -2389,7 +2593,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2389 | kctl = snd_ctl_new1(knew, codec); | 2593 | kctl = snd_ctl_new1(knew, codec); |
2390 | if (!kctl) | 2594 | if (!kctl) |
2391 | return -ENOMEM; | 2595 | return -ENOMEM; |
2392 | err = snd_ctl_add(codec->bus->card, kctl); | 2596 | err = snd_hda_ctl_add(codec, kctl); |
2393 | if (err < 0) { | 2597 | if (err < 0) { |
2394 | if (!codec->addr) | 2598 | if (!codec->addr) |
2395 | return err; | 2599 | return err; |
@@ -2397,7 +2601,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2397 | if (!kctl) | 2601 | if (!kctl) |
2398 | return -ENOMEM; | 2602 | return -ENOMEM; |
2399 | kctl->id.device = codec->addr; | 2603 | kctl->id.device = codec->addr; |
2400 | err = snd_ctl_add(codec->bus->card, kctl); | 2604 | err = snd_hda_ctl_add(codec, kctl); |
2401 | if (err < 0) | 2605 | if (err < 0) |
2402 | return err; | 2606 | return err; |
2403 | } | 2607 | } |
@@ -3138,3 +3342,37 @@ int snd_hda_codecs_inuse(struct hda_bus *bus) | |||
3138 | } | 3342 | } |
3139 | #endif | 3343 | #endif |
3140 | #endif | 3344 | #endif |
3345 | |||
3346 | /* | ||
3347 | * generic arrays | ||
3348 | */ | ||
3349 | |||
3350 | /* get a new element from the given array | ||
3351 | * if it exceeds the pre-allocated array size, re-allocate the array | ||
3352 | */ | ||
3353 | void *snd_array_new(struct snd_array *array) | ||
3354 | { | ||
3355 | if (array->used >= array->alloced) { | ||
3356 | int num = array->alloced + array->alloc_align; | ||
3357 | void *nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL); | ||
3358 | if (!nlist) | ||
3359 | return NULL; | ||
3360 | if (array->list) { | ||
3361 | memcpy(nlist, array->list, | ||
3362 | array->elem_size * array->alloced); | ||
3363 | kfree(array->list); | ||
3364 | } | ||
3365 | array->list = nlist; | ||
3366 | array->alloced = num; | ||
3367 | } | ||
3368 | return array->list + (array->used++ * array->elem_size); | ||
3369 | } | ||
3370 | |||
3371 | /* free the given array elements */ | ||
3372 | void snd_array_free(struct snd_array *array) | ||
3373 | { | ||
3374 | kfree(array->list); | ||
3375 | array->used = 0; | ||
3376 | array->alloced = 0; | ||
3377 | array->list = NULL; | ||
3378 | } | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 60468f562400..c5f91c918d19 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -520,6 +520,26 @@ enum { | |||
520 | #define HDA_MAX_CODEC_ADDRESS 0x0f | 520 | #define HDA_MAX_CODEC_ADDRESS 0x0f |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * generic arrays | ||
524 | */ | ||
525 | struct snd_array { | ||
526 | unsigned int used; | ||
527 | unsigned int alloced; | ||
528 | unsigned int elem_size; | ||
529 | unsigned int alloc_align; | ||
530 | void *list; | ||
531 | }; | ||
532 | |||
533 | void *snd_array_new(struct snd_array *array); | ||
534 | void snd_array_free(struct snd_array *array); | ||
535 | static inline void snd_array_init(struct snd_array *array, unsigned int size, | ||
536 | unsigned int align) | ||
537 | { | ||
538 | array->elem_size = size; | ||
539 | array->alloc_align = align; | ||
540 | } | ||
541 | |||
542 | /* | ||
523 | * Structures | 543 | * Structures |
524 | */ | 544 | */ |
525 | 545 | ||
@@ -542,6 +562,8 @@ struct hda_bus_ops { | |||
542 | unsigned int (*get_response)(struct hda_codec *codec); | 562 | unsigned int (*get_response)(struct hda_codec *codec); |
543 | /* free the private data */ | 563 | /* free the private data */ |
544 | void (*private_free)(struct hda_bus *); | 564 | void (*private_free)(struct hda_bus *); |
565 | /* attach a PCM stream */ | ||
566 | int (*attach_pcm)(struct hda_codec *codec, struct hda_pcm *pcm); | ||
545 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 567 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
546 | /* notify power-up/down from codec to controller */ | 568 | /* notify power-up/down from codec to controller */ |
547 | void (*pm_notify)(struct hda_codec *codec); | 569 | void (*pm_notify)(struct hda_codec *codec); |
@@ -635,10 +657,7 @@ struct hda_amp_info { | |||
635 | 657 | ||
636 | struct hda_cache_rec { | 658 | struct hda_cache_rec { |
637 | u16 hash[64]; /* hash table for index */ | 659 | u16 hash[64]; /* hash table for index */ |
638 | unsigned int num_entries; /* number of assigned entries */ | 660 | struct snd_array buf; /* record entries */ |
639 | unsigned int size; /* allocated size */ | ||
640 | unsigned int record_size; /* record size (including header) */ | ||
641 | void *buffer; /* hash table entries */ | ||
642 | }; | 661 | }; |
643 | 662 | ||
644 | /* PCM callbacks */ | 663 | /* PCM callbacks */ |
@@ -680,7 +699,8 @@ struct hda_pcm { | |||
680 | char *name; | 699 | char *name; |
681 | struct hda_pcm_stream stream[2]; | 700 | struct hda_pcm_stream stream[2]; |
682 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ | 701 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ |
683 | int device; /* assigned device number */ | 702 | int device; /* device number to assign */ |
703 | struct snd_pcm *pcm; /* assigned PCM instance */ | ||
684 | }; | 704 | }; |
685 | 705 | ||
686 | /* codec information */ | 706 | /* codec information */ |
@@ -699,6 +719,8 @@ struct hda_codec { | |||
699 | 719 | ||
700 | /* detected preset */ | 720 | /* detected preset */ |
701 | const struct hda_codec_preset *preset; | 721 | const struct hda_codec_preset *preset; |
722 | const char *name; /* codec name */ | ||
723 | const char *modelname; /* model name for preset */ | ||
702 | 724 | ||
703 | /* set by patch */ | 725 | /* set by patch */ |
704 | struct hda_codec_ops patch_ops; | 726 | struct hda_codec_ops patch_ops; |
@@ -718,6 +740,8 @@ struct hda_codec { | |||
718 | hda_nid_t start_nid; | 740 | hda_nid_t start_nid; |
719 | u32 *wcaps; | 741 | u32 *wcaps; |
720 | 742 | ||
743 | struct snd_array mixers; /* list of assigned mixer elements */ | ||
744 | |||
721 | struct hda_cache_rec amp_cache; /* cache for amp access */ | 745 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
722 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | 746 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
723 | 747 | ||
@@ -727,7 +751,11 @@ struct hda_codec { | |||
727 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 751 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
728 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 752 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
729 | 753 | ||
754 | #ifdef CONFIG_SND_HDA_HWDEP | ||
730 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 755 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
756 | struct snd_array init_verbs; /* additional init verbs */ | ||
757 | struct snd_array hints; /* additional hints */ | ||
758 | #endif | ||
731 | 759 | ||
732 | /* misc flags */ | 760 | /* misc flags */ |
733 | unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each | 761 | unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each |
@@ -799,6 +827,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); | |||
799 | * Mixer | 827 | * Mixer |
800 | */ | 828 | */ |
801 | int snd_hda_build_controls(struct hda_bus *bus); | 829 | int snd_hda_build_controls(struct hda_bus *bus); |
830 | int snd_hda_codec_build_controls(struct hda_codec *codec); | ||
802 | 831 | ||
803 | /* | 832 | /* |
804 | * PCM | 833 | * PCM |
@@ -831,6 +860,13 @@ int snd_hda_resume(struct hda_bus *bus); | |||
831 | #endif | 860 | #endif |
832 | 861 | ||
833 | /* | 862 | /* |
863 | * get widget information | ||
864 | */ | ||
865 | const char *snd_hda_get_jack_connectivity(u32 cfg); | ||
866 | const char *snd_hda_get_jack_type(u32 cfg); | ||
867 | const char *snd_hda_get_jack_location(u32 cfg); | ||
868 | |||
869 | /* | ||
834 | * power saving | 870 | * power saving |
835 | */ | 871 | */ |
836 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 872 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
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_hwdep.c b/sound/pci/hda/hda_hwdep.c index 6e18a422d993..653da1d3e4df 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -23,10 +23,12 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/compat.h> | 24 | #include <linux/compat.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/ctype.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include "hda_codec.h" | 28 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 29 | #include "hda_local.h" |
29 | #include <sound/hda_hwdep.h> | 30 | #include <sound/hda_hwdep.h> |
31 | #include <sound/minors.h> | ||
30 | 32 | ||
31 | /* | 33 | /* |
32 | * write/read an out-of-bound verb | 34 | * write/read an out-of-bound verb |
@@ -95,6 +97,25 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
95 | return 0; | 97 | return 0; |
96 | } | 98 | } |
97 | 99 | ||
100 | static void clear_hwdep_elements(struct hda_codec *codec) | ||
101 | { | ||
102 | char **head; | ||
103 | int i; | ||
104 | |||
105 | /* clear init verbs */ | ||
106 | snd_array_free(&codec->init_verbs); | ||
107 | /* clear hints */ | ||
108 | head = codec->hints.list; | ||
109 | for (i = 0; i < codec->hints.used; i++, head++) | ||
110 | kfree(*head); | ||
111 | snd_array_free(&codec->hints); | ||
112 | } | ||
113 | |||
114 | static void hwdep_free(struct snd_hwdep *hwdep) | ||
115 | { | ||
116 | clear_hwdep_elements(hwdep->private_data); | ||
117 | } | ||
118 | |||
98 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | 119 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) |
99 | { | 120 | { |
100 | char hwname[16]; | 121 | char hwname[16]; |
@@ -109,6 +130,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
109 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); | 130 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); |
110 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | 131 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; |
111 | hwdep->private_data = codec; | 132 | hwdep->private_data = codec; |
133 | hwdep->private_free = hwdep_free; | ||
112 | hwdep->exclusive = 1; | 134 | hwdep->exclusive = 1; |
113 | 135 | ||
114 | hwdep->ops.open = hda_hwdep_open; | 136 | hwdep->ops.open = hda_hwdep_open; |
@@ -117,5 +139,211 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
117 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | 139 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; |
118 | #endif | 140 | #endif |
119 | 141 | ||
142 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | ||
143 | snd_array_init(&codec->hints, sizeof(char *), 32); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * sysfs interface | ||
150 | */ | ||
151 | |||
152 | static int clear_codec(struct hda_codec *codec) | ||
153 | { | ||
154 | snd_hda_codec_reset(codec); | ||
155 | clear_hwdep_elements(codec); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int reconfig_codec(struct hda_codec *codec) | ||
160 | { | ||
161 | int err; | ||
162 | |||
163 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); | ||
164 | snd_hda_codec_reset(codec); | ||
165 | err = snd_hda_codec_configure(codec); | ||
166 | if (err < 0) | ||
167 | return err; | ||
168 | /* rebuild PCMs */ | ||
169 | err = snd_hda_build_pcms(codec->bus); | ||
170 | if (err < 0) | ||
171 | return err; | ||
172 | /* rebuild mixers */ | ||
173 | err = snd_hda_codec_build_controls(codec); | ||
174 | if (err < 0) | ||
175 | return err; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * allocate a string at most len chars, and remove the trailing EOL | ||
181 | */ | ||
182 | static char *kstrndup_noeol(const char *src, size_t len) | ||
183 | { | ||
184 | char *s = kstrndup(src, len, GFP_KERNEL); | ||
185 | char *p; | ||
186 | if (!s) | ||
187 | return NULL; | ||
188 | p = strchr(s, '\n'); | ||
189 | if (p) | ||
190 | *p = 0; | ||
191 | return s; | ||
192 | } | ||
193 | |||
194 | #define CODEC_INFO_SHOW(type) \ | ||
195 | static ssize_t type##_show(struct device *dev, \ | ||
196 | struct device_attribute *attr, \ | ||
197 | char *buf) \ | ||
198 | { \ | ||
199 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
200 | struct hda_codec *codec = hwdep->private_data; \ | ||
201 | return sprintf(buf, "0x%x\n", codec->type); \ | ||
202 | } | ||
203 | |||
204 | #define CODEC_INFO_STR_SHOW(type) \ | ||
205 | static ssize_t type##_show(struct device *dev, \ | ||
206 | struct device_attribute *attr, \ | ||
207 | char *buf) \ | ||
208 | { \ | ||
209 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
210 | struct hda_codec *codec = hwdep->private_data; \ | ||
211 | return sprintf(buf, "%s\n", \ | ||
212 | codec->type ? codec->type : ""); \ | ||
213 | } | ||
214 | |||
215 | CODEC_INFO_SHOW(vendor_id); | ||
216 | CODEC_INFO_SHOW(subsystem_id); | ||
217 | CODEC_INFO_SHOW(revision_id); | ||
218 | CODEC_INFO_SHOW(afg); | ||
219 | CODEC_INFO_SHOW(mfg); | ||
220 | CODEC_INFO_STR_SHOW(name); | ||
221 | CODEC_INFO_STR_SHOW(modelname); | ||
222 | |||
223 | #define CODEC_INFO_STORE(type) \ | ||
224 | static ssize_t type##_store(struct device *dev, \ | ||
225 | struct device_attribute *attr, \ | ||
226 | const char *buf, size_t count) \ | ||
227 | { \ | ||
228 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
229 | struct hda_codec *codec = hwdep->private_data; \ | ||
230 | char *after; \ | ||
231 | codec->type = simple_strtoul(buf, &after, 0); \ | ||
232 | return count; \ | ||
233 | } | ||
234 | |||
235 | #define CODEC_INFO_STR_STORE(type) \ | ||
236 | static ssize_t type##_store(struct device *dev, \ | ||
237 | struct device_attribute *attr, \ | ||
238 | const char *buf, size_t count) \ | ||
239 | { \ | ||
240 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
241 | struct hda_codec *codec = hwdep->private_data; \ | ||
242 | char *s = kstrndup_noeol(buf, 64); \ | ||
243 | if (!s) \ | ||
244 | return -ENOMEM; \ | ||
245 | kfree(codec->type); \ | ||
246 | codec->type = s; \ | ||
247 | return count; \ | ||
248 | } | ||
249 | |||
250 | CODEC_INFO_STORE(vendor_id); | ||
251 | CODEC_INFO_STORE(subsystem_id); | ||
252 | CODEC_INFO_STORE(revision_id); | ||
253 | CODEC_INFO_STR_STORE(name); | ||
254 | CODEC_INFO_STR_STORE(modelname); | ||
255 | |||
256 | #define CODEC_ACTION_STORE(type) \ | ||
257 | static ssize_t type##_store(struct device *dev, \ | ||
258 | struct device_attribute *attr, \ | ||
259 | const char *buf, size_t count) \ | ||
260 | { \ | ||
261 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
262 | struct hda_codec *codec = hwdep->private_data; \ | ||
263 | int err = 0; \ | ||
264 | if (*buf) \ | ||
265 | err = type##_codec(codec); \ | ||
266 | return err < 0 ? err : count; \ | ||
267 | } | ||
268 | |||
269 | CODEC_ACTION_STORE(reconfig); | ||
270 | CODEC_ACTION_STORE(clear); | ||
271 | |||
272 | static ssize_t init_verbs_store(struct device *dev, | ||
273 | struct device_attribute *attr, | ||
274 | const char *buf, size_t count) | ||
275 | { | ||
276 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
277 | struct hda_codec *codec = hwdep->private_data; | ||
278 | char *p; | ||
279 | struct hda_verb verb, *v; | ||
280 | |||
281 | verb.nid = simple_strtoul(buf, &p, 0); | ||
282 | verb.verb = simple_strtoul(p, &p, 0); | ||
283 | verb.param = simple_strtoul(p, &p, 0); | ||
284 | if (!verb.nid || !verb.verb || !verb.param) | ||
285 | return -EINVAL; | ||
286 | v = snd_array_new(&codec->init_verbs); | ||
287 | if (!v) | ||
288 | return -ENOMEM; | ||
289 | *v = verb; | ||
290 | return count; | ||
291 | } | ||
292 | |||
293 | static ssize_t hints_store(struct device *dev, | ||
294 | struct device_attribute *attr, | ||
295 | const char *buf, size_t count) | ||
296 | { | ||
297 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
298 | struct hda_codec *codec = hwdep->private_data; | ||
299 | char *p; | ||
300 | char **hint; | ||
301 | |||
302 | if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') | ||
303 | return count; | ||
304 | p = kstrndup_noeol(buf, 1024); | ||
305 | if (!p) | ||
306 | return -ENOMEM; | ||
307 | hint = snd_array_new(&codec->hints); | ||
308 | if (!hint) { | ||
309 | kfree(p); | ||
310 | return -ENOMEM; | ||
311 | } | ||
312 | *hint = p; | ||
313 | return count; | ||
314 | } | ||
315 | |||
316 | #define CODEC_ATTR_RW(type) \ | ||
317 | __ATTR(type, 0644, type##_show, type##_store) | ||
318 | #define CODEC_ATTR_RO(type) \ | ||
319 | __ATTR_RO(type) | ||
320 | #define CODEC_ATTR_WO(type) \ | ||
321 | __ATTR(type, 0200, NULL, type##_store) | ||
322 | |||
323 | static struct device_attribute codec_attrs[] = { | ||
324 | CODEC_ATTR_RW(vendor_id), | ||
325 | CODEC_ATTR_RW(subsystem_id), | ||
326 | CODEC_ATTR_RW(revision_id), | ||
327 | CODEC_ATTR_RO(afg), | ||
328 | CODEC_ATTR_RO(mfg), | ||
329 | CODEC_ATTR_RW(name), | ||
330 | CODEC_ATTR_RW(modelname), | ||
331 | CODEC_ATTR_WO(init_verbs), | ||
332 | CODEC_ATTR_WO(hints), | ||
333 | CODEC_ATTR_WO(reconfig), | ||
334 | CODEC_ATTR_WO(clear), | ||
335 | }; | ||
336 | |||
337 | /* | ||
338 | * create sysfs files on hwdep directory | ||
339 | */ | ||
340 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | ||
341 | { | ||
342 | struct snd_hwdep *hwdep = codec->hwdep; | ||
343 | int i; | ||
344 | |||
345 | for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) | ||
346 | snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, | ||
347 | hwdep->device, &codec_attrs[i]); | ||
120 | return 0; | 348 | return 0; |
121 | } | 349 | } |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9f316c1b2790..7b0abf08a583 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1180,6 +1180,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1180 | return 0; | 1180 | return 0; |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | static int azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm); | ||
1183 | 1184 | ||
1184 | /* | 1185 | /* |
1185 | * Codec initialization | 1186 | * Codec initialization |
@@ -1212,6 +1213,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1212 | bus_temp.pci = chip->pci; | 1213 | bus_temp.pci = chip->pci; |
1213 | bus_temp.ops.command = azx_send_cmd; | 1214 | bus_temp.ops.command = azx_send_cmd; |
1214 | bus_temp.ops.get_response = azx_get_response; | 1215 | bus_temp.ops.get_response = azx_get_response; |
1216 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; | ||
1215 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1217 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1216 | bus_temp.ops.pm_notify = azx_power_notify; | 1218 | bus_temp.ops.pm_notify = azx_power_notify; |
1217 | #endif | 1219 | #endif |
@@ -1718,111 +1720,58 @@ static struct snd_pcm_ops azx_pcm_ops = { | |||
1718 | 1720 | ||
1719 | static void azx_pcm_free(struct snd_pcm *pcm) | 1721 | static void azx_pcm_free(struct snd_pcm *pcm) |
1720 | { | 1722 | { |
1721 | kfree(pcm->private_data); | 1723 | struct azx_pcm *apcm = pcm->private_data; |
1724 | if (apcm) { | ||
1725 | apcm->chip->pcm[pcm->device] = NULL; | ||
1726 | kfree(apcm); | ||
1727 | } | ||
1722 | } | 1728 | } |
1723 | 1729 | ||
1724 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | 1730 | static int |
1725 | struct hda_pcm *cpcm) | 1731 | azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm) |
1726 | { | 1732 | { |
1727 | int err; | 1733 | struct azx *chip = codec->bus->private_data; |
1728 | struct snd_pcm *pcm; | 1734 | struct snd_pcm *pcm; |
1729 | struct azx_pcm *apcm; | 1735 | struct azx_pcm *apcm; |
1736 | int pcm_dev = cpcm->device; | ||
1737 | int s, err; | ||
1730 | 1738 | ||
1731 | /* if no substreams are defined for both playback and capture, | 1739 | if (pcm_dev >= AZX_MAX_PCMS) { |
1732 | * it's just a placeholder. ignore it. | 1740 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1733 | */ | 1741 | pcm_dev); |
1734 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | ||
1735 | return 0; | ||
1736 | |||
1737 | if (snd_BUG_ON(!cpcm->name)) | ||
1738 | return -EINVAL; | 1742 | return -EINVAL; |
1739 | 1743 | } | |
1740 | err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, | 1744 | if (chip->pcm[pcm_dev]) { |
1741 | cpcm->stream[0].substreams, | 1745 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); |
1742 | cpcm->stream[1].substreams, | 1746 | return -EBUSY; |
1747 | } | ||
1748 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | ||
1749 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, | ||
1750 | cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, | ||
1743 | &pcm); | 1751 | &pcm); |
1744 | if (err < 0) | 1752 | if (err < 0) |
1745 | return err; | 1753 | return err; |
1746 | strcpy(pcm->name, cpcm->name); | 1754 | strcpy(pcm->name, cpcm->name); |
1747 | apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); | 1755 | apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); |
1748 | if (apcm == NULL) | 1756 | if (apcm == NULL) |
1749 | return -ENOMEM; | 1757 | return -ENOMEM; |
1750 | apcm->chip = chip; | 1758 | apcm->chip = chip; |
1751 | apcm->codec = codec; | 1759 | apcm->codec = codec; |
1752 | apcm->hinfo[0] = &cpcm->stream[0]; | ||
1753 | apcm->hinfo[1] = &cpcm->stream[1]; | ||
1754 | pcm->private_data = apcm; | 1760 | pcm->private_data = apcm; |
1755 | pcm->private_free = azx_pcm_free; | 1761 | pcm->private_free = azx_pcm_free; |
1756 | if (cpcm->stream[0].substreams) | 1762 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
1757 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); | 1763 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; |
1758 | if (cpcm->stream[1].substreams) | 1764 | chip->pcm[pcm_dev] = pcm; |
1759 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); | 1765 | cpcm->pcm = pcm; |
1766 | for (s = 0; s < 2; s++) { | ||
1767 | apcm->hinfo[s] = &cpcm->stream[s]; | ||
1768 | if (cpcm->stream[s].substreams) | ||
1769 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); | ||
1770 | } | ||
1771 | /* buffer pre-allocation */ | ||
1760 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1772 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1761 | snd_dma_pci_data(chip->pci), | 1773 | snd_dma_pci_data(chip->pci), |
1762 | 1024 * 64, 32 * 1024 * 1024); | 1774 | 1024 * 64, 32 * 1024 * 1024); |
1763 | chip->pcm[cpcm->device] = pcm; | ||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1767 | static int __devinit azx_pcm_create(struct azx *chip) | ||
1768 | { | ||
1769 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
1770 | "Audio", "SPDIF", "HDMI", "Modem" | ||
1771 | }; | ||
1772 | /* starting device index for each PCM type */ | ||
1773 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
1774 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
1775 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
1776 | [HDA_PCM_TYPE_HDMI] = 3, | ||
1777 | [HDA_PCM_TYPE_MODEM] = 6 | ||
1778 | }; | ||
1779 | /* normal audio device indices; not linear to keep compatibility */ | ||
1780 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
1781 | struct hda_codec *codec; | ||
1782 | int c, err; | ||
1783 | int num_devs[HDA_PCM_NTYPES]; | ||
1784 | |||
1785 | err = snd_hda_build_pcms(chip->bus); | ||
1786 | if (err < 0) | ||
1787 | return err; | ||
1788 | |||
1789 | /* create audio PCMs */ | ||
1790 | memset(num_devs, 0, sizeof(num_devs)); | ||
1791 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1792 | for (c = 0; c < codec->num_pcms; c++) { | ||
1793 | struct hda_pcm *cpcm = &codec->pcm_info[c]; | ||
1794 | int type = cpcm->pcm_type; | ||
1795 | switch (type) { | ||
1796 | case HDA_PCM_TYPE_AUDIO: | ||
1797 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
1798 | snd_printk(KERN_WARNING | ||
1799 | "Too many audio devices\n"); | ||
1800 | continue; | ||
1801 | } | ||
1802 | cpcm->device = audio_idx[num_devs[type]]; | ||
1803 | break; | ||
1804 | case HDA_PCM_TYPE_SPDIF: | ||
1805 | case HDA_PCM_TYPE_HDMI: | ||
1806 | case HDA_PCM_TYPE_MODEM: | ||
1807 | if (num_devs[type]) { | ||
1808 | snd_printk(KERN_WARNING | ||
1809 | "%s already defined\n", | ||
1810 | dev_name[type]); | ||
1811 | continue; | ||
1812 | } | ||
1813 | cpcm->device = dev_idx[type]; | ||
1814 | break; | ||
1815 | default: | ||
1816 | snd_printk(KERN_WARNING | ||
1817 | "Invalid PCM type %d\n", type); | ||
1818 | continue; | ||
1819 | } | ||
1820 | num_devs[type]++; | ||
1821 | err = create_codec_pcm(chip, codec, cpcm); | ||
1822 | if (err < 0) | ||
1823 | return err; | ||
1824 | } | ||
1825 | } | ||
1826 | return 0; | 1775 | return 0; |
1827 | } | 1776 | } |
1828 | 1777 | ||
@@ -2324,7 +2273,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2324 | } | 2273 | } |
2325 | 2274 | ||
2326 | /* create PCM streams */ | 2275 | /* create PCM streams */ |
2327 | err = azx_pcm_create(chip); | 2276 | err = snd_hda_build_pcms(chip->bus); |
2328 | if (err < 0) { | 2277 | if (err < 0) { |
2329 | snd_card_free(card); | 2278 | snd_card_free(card); |
2330 | return err; | 2279 | return err; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7957fefda730..4a08c31b498a 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); |
97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
98 | unsigned int *tlv, const char **slaves); | 98 | unsigned int *tlv, const char **slaves); |
99 | void snd_hda_codec_reset(struct hda_codec *codec); | ||
100 | int 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 |
@@ -393,10 +395,18 @@ 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, | 395 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
394 | unsigned int caps); | 396 | unsigned int caps); |
395 | 397 | ||
398 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | ||
399 | void snd_hda_ctls_clear(struct hda_codec *codec); | ||
400 | |||
396 | /* | 401 | /* |
397 | * hwdep interface | 402 | * hwdep interface |
398 | */ | 403 | */ |
404 | #ifdef CONFIG_SND_HDA_HWDEP | ||
399 | int snd_hda_create_hwdep(struct hda_codec *codec); | 405 | int snd_hda_create_hwdep(struct hda_codec *codec); |
406 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); | ||
407 | #else | ||
408 | static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } | ||
409 | #endif | ||
400 | 410 | ||
401 | /* | 411 | /* |
402 | * power-management | 412 | * power-management |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 743d77922bce..b36d4d06485d 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -145,32 +145,6 @@ static void print_pcm_caps(struct snd_info_buffer *buffer, | |||
145 | print_pcm_formats(buffer, stream); | 145 | print_pcm_formats(buffer, stream); |
146 | } | 146 | } |
147 | 147 | ||
148 | static const char *get_jack_location(u32 cfg) | ||
149 | { | ||
150 | static char *bases[7] = { | ||
151 | "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", | ||
152 | }; | ||
153 | static unsigned char specials_idx[] = { | ||
154 | 0x07, 0x08, | ||
155 | 0x17, 0x18, 0x19, | ||
156 | 0x37, 0x38 | ||
157 | }; | ||
158 | static char *specials[] = { | ||
159 | "Rear Panel", "Drive Bar", | ||
160 | "Riser", "HDMI", "ATAPI", | ||
161 | "Mobile-In", "Mobile-Out" | ||
162 | }; | ||
163 | int i; | ||
164 | cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; | ||
165 | if ((cfg & 0x0f) < 7) | ||
166 | return bases[cfg & 0x0f]; | ||
167 | for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { | ||
168 | if (cfg == specials_idx[i]) | ||
169 | return specials[i]; | ||
170 | } | ||
171 | return "UNKNOWN"; | ||
172 | } | ||
173 | |||
174 | static const char *get_jack_connection(u32 cfg) | 148 | static const char *get_jack_connection(u32 cfg) |
175 | { | 149 | { |
176 | static char *names[16] = { | 150 | static char *names[16] = { |
@@ -206,13 +180,6 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
206 | int *supports_vref) | 180 | int *supports_vref) |
207 | { | 181 | { |
208 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | 182 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; |
209 | static char *jack_types[16] = { | ||
210 | "Line Out", "Speaker", "HP Out", "CD", | ||
211 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | ||
212 | "Line In", "Aux", "Mic", "Telephony", | ||
213 | "SPDIF In", "Digitial In", "Reserved", "Other" | ||
214 | }; | ||
215 | static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; | ||
216 | unsigned int caps, val; | 183 | unsigned int caps, val; |
217 | 184 | ||
218 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 185 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
@@ -274,9 +241,9 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
274 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 241 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); |
275 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, | 242 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, |
276 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], | 243 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], |
277 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], | 244 | snd_hda_get_jack_type(caps), |
278 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], | 245 | snd_hda_get_jack_connectivity(caps), |
279 | get_jack_location(caps)); | 246 | snd_hda_get_jack_location(caps)); |
280 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", | 247 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", |
281 | get_jack_connection(caps), | 248 | get_jack_connection(caps), |
282 | get_jack_color(caps)); | 249 | get_jack_color(caps)); |
@@ -511,12 +478,11 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
511 | struct snd_info_buffer *buffer) | 478 | struct snd_info_buffer *buffer) |
512 | { | 479 | { |
513 | struct hda_codec *codec = entry->private_data; | 480 | struct hda_codec *codec = entry->private_data; |
514 | char buf[32]; | ||
515 | hda_nid_t nid; | 481 | hda_nid_t nid; |
516 | int i, nodes; | 482 | int i, nodes; |
517 | 483 | ||
518 | snd_hda_get_codec_name(codec, buf, sizeof(buf)); | 484 | snd_iprintf(buffer, "Codec: %s\n", |
519 | snd_iprintf(buffer, "Codec: %s\n", buf); | 485 | codec->name ? codec->name : "Not Set"); |
520 | snd_iprintf(buffer, "Address: %d\n", codec->addr); | 486 | snd_iprintf(buffer, "Address: %d\n", codec->addr); |
521 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 487 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); |
522 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 488 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2b00c4afdf97..02643bce5634 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -67,8 +67,7 @@ struct ad198x_spec { | |||
67 | 67 | ||
68 | /* dynamic controls, init_verbs and input_mux */ | 68 | /* dynamic controls, init_verbs and input_mux */ |
69 | struct auto_pin_cfg autocfg; | 69 | struct auto_pin_cfg autocfg; |
70 | unsigned int num_kctl_alloc, num_kctl_used; | 70 | struct snd_array kctls; |
71 | struct snd_kcontrol_new *kctl_alloc; | ||
72 | struct hda_input_mux private_imux; | 71 | struct hda_input_mux private_imux; |
73 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
74 | 73 | ||
@@ -154,6 +153,8 @@ static const char *ad_slave_sws[] = { | |||
154 | NULL | 153 | NULL |
155 | }; | 154 | }; |
156 | 155 | ||
156 | static void ad198x_free_kctls(struct hda_codec *codec); | ||
157 | |||
157 | static int ad198x_build_controls(struct hda_codec *codec) | 158 | static int ad198x_build_controls(struct hda_codec *codec) |
158 | { | 159 | { |
159 | struct ad198x_spec *spec = codec->spec; | 160 | struct ad198x_spec *spec = codec->spec; |
@@ -202,6 +203,7 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
202 | return err; | 203 | return err; |
203 | } | 204 | } |
204 | 205 | ||
206 | ad198x_free_kctls(codec); /* no longer needed */ | ||
205 | return 0; | 207 | return 0; |
206 | } | 208 | } |
207 | 209 | ||
@@ -375,16 +377,27 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
375 | return 0; | 377 | return 0; |
376 | } | 378 | } |
377 | 379 | ||
378 | static void ad198x_free(struct hda_codec *codec) | 380 | static void ad198x_free_kctls(struct hda_codec *codec) |
379 | { | 381 | { |
380 | struct ad198x_spec *spec = codec->spec; | 382 | struct ad198x_spec *spec = codec->spec; |
381 | unsigned int i; | ||
382 | 383 | ||
383 | if (spec->kctl_alloc) { | 384 | if (spec->kctls.list) { |
384 | for (i = 0; i < spec->num_kctl_used; i++) | 385 | struct snd_kcontrol_new *kctl = spec->kctls.list; |
385 | kfree(spec->kctl_alloc[i].name); | 386 | int i; |
386 | kfree(spec->kctl_alloc); | 387 | for (i = 0; i < spec->kctls.used; i++) |
388 | kfree(kctl[i].name); | ||
387 | } | 389 | } |
390 | snd_array_free(&spec->kctls); | ||
391 | } | ||
392 | |||
393 | static void ad198x_free(struct hda_codec *codec) | ||
394 | { | ||
395 | struct ad198x_spec *spec = codec->spec; | ||
396 | |||
397 | if (!spec) | ||
398 | return; | ||
399 | |||
400 | ad198x_free_kctls(codec); | ||
388 | kfree(codec->spec); | 401 | kfree(codec->spec); |
389 | } | 402 | } |
390 | 403 | ||
@@ -2452,9 +2465,6 @@ static struct hda_amp_list ad1988_loopbacks[] = { | |||
2452 | * Automatic parse of I/O pins from the BIOS configuration | 2465 | * Automatic parse of I/O pins from the BIOS configuration |
2453 | */ | 2466 | */ |
2454 | 2467 | ||
2455 | #define NUM_CONTROL_ALLOC 32 | ||
2456 | #define NUM_VERB_ALLOC 32 | ||
2457 | |||
2458 | enum { | 2468 | enum { |
2459 | AD_CTL_WIDGET_VOL, | 2469 | AD_CTL_WIDGET_VOL, |
2460 | AD_CTL_WIDGET_MUTE, | 2470 | AD_CTL_WIDGET_MUTE, |
@@ -2472,27 +2482,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2472 | { | 2482 | { |
2473 | struct snd_kcontrol_new *knew; | 2483 | struct snd_kcontrol_new *knew; |
2474 | 2484 | ||
2475 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2485 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2476 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2486 | knew = snd_array_new(&spec->kctls); |
2477 | 2487 | if (!knew) | |
2478 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2488 | return -ENOMEM; |
2479 | if (! knew) | ||
2480 | return -ENOMEM; | ||
2481 | if (spec->kctl_alloc) { | ||
2482 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2483 | kfree(spec->kctl_alloc); | ||
2484 | } | ||
2485 | spec->kctl_alloc = knew; | ||
2486 | spec->num_kctl_alloc = num; | ||
2487 | } | ||
2488 | |||
2489 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2490 | *knew = ad1988_control_templates[type]; | 2489 | *knew = ad1988_control_templates[type]; |
2491 | knew->name = kstrdup(name, GFP_KERNEL); | 2490 | knew->name = kstrdup(name, GFP_KERNEL); |
2492 | if (! knew->name) | 2491 | if (! knew->name) |
2493 | return -ENOMEM; | 2492 | return -ENOMEM; |
2494 | knew->private_value = val; | 2493 | knew->private_value = val; |
2495 | spec->num_kctl_used++; | ||
2496 | return 0; | 2494 | return 0; |
2497 | } | 2495 | } |
2498 | 2496 | ||
@@ -2846,8 +2844,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2846 | if (spec->autocfg.dig_in_pin) | 2844 | if (spec->autocfg.dig_in_pin) |
2847 | spec->dig_in_nid = AD1988_SPDIF_IN; | 2845 | spec->dig_in_nid = AD1988_SPDIF_IN; |
2848 | 2846 | ||
2849 | if (spec->kctl_alloc) | 2847 | if (spec->kctls.list) |
2850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2848 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2851 | 2849 | ||
2852 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; | 2850 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; |
2853 | 2851 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 7c1eb23f0cec..076010708152 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -86,8 +86,6 @@ struct conexant_spec { | |||
86 | 86 | ||
87 | /* dynamic controls, init_verbs and input_mux */ | 87 | /* dynamic controls, init_verbs and input_mux */ |
88 | struct auto_pin_cfg autocfg; | 88 | struct auto_pin_cfg autocfg; |
89 | unsigned int num_kctl_alloc, num_kctl_used; | ||
90 | struct snd_kcontrol_new *kctl_alloc; | ||
91 | struct hda_input_mux private_imux; | 89 | struct hda_input_mux private_imux; |
92 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 90 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
93 | 91 | ||
@@ -344,15 +342,6 @@ static int conexant_init(struct hda_codec *codec) | |||
344 | 342 | ||
345 | static void conexant_free(struct hda_codec *codec) | 343 | static void conexant_free(struct hda_codec *codec) |
346 | { | 344 | { |
347 | struct conexant_spec *spec = codec->spec; | ||
348 | unsigned int i; | ||
349 | |||
350 | if (spec->kctl_alloc) { | ||
351 | for (i = 0; i < spec->num_kctl_used; i++) | ||
352 | kfree(spec->kctl_alloc[i].name); | ||
353 | kfree(spec->kctl_alloc); | ||
354 | } | ||
355 | |||
356 | kfree(codec->spec); | 345 | kfree(codec->spec); |
357 | } | 346 | } |
358 | 347 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ef4955c73c88..fb8fae9f702d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -284,8 +284,7 @@ struct alc_spec { | |||
284 | 284 | ||
285 | /* dynamic controls, init_verbs and input_mux */ | 285 | /* dynamic controls, init_verbs and input_mux */ |
286 | struct auto_pin_cfg autocfg; | 286 | struct auto_pin_cfg autocfg; |
287 | unsigned int num_kctl_alloc, num_kctl_used; | 287 | struct snd_array kctls; |
288 | struct snd_kcontrol_new *kctl_alloc; | ||
289 | struct hda_input_mux private_imux; | 288 | struct hda_input_mux private_imux; |
290 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 289 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
291 | 290 | ||
@@ -1625,6 +1624,9 @@ static const char *alc_slave_sws[] = { | |||
1625 | /* | 1624 | /* |
1626 | * build control elements | 1625 | * build control elements |
1627 | */ | 1626 | */ |
1627 | |||
1628 | static void alc_free_kctls(struct hda_codec *codec); | ||
1629 | |||
1628 | static int alc_build_controls(struct hda_codec *codec) | 1630 | static int alc_build_controls(struct hda_codec *codec) |
1629 | { | 1631 | { |
1630 | struct alc_spec *spec = codec->spec; | 1632 | struct alc_spec *spec = codec->spec; |
@@ -1671,6 +1673,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1671 | return err; | 1673 | return err; |
1672 | } | 1674 | } |
1673 | 1675 | ||
1676 | alc_free_kctls(codec); /* no longer needed */ | ||
1674 | return 0; | 1677 | return 0; |
1675 | } | 1678 | } |
1676 | 1679 | ||
@@ -2761,19 +2764,27 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2761 | return 0; | 2764 | return 0; |
2762 | } | 2765 | } |
2763 | 2766 | ||
2767 | static void alc_free_kctls(struct hda_codec *codec) | ||
2768 | { | ||
2769 | struct alc_spec *spec = codec->spec; | ||
2770 | |||
2771 | if (spec->kctls.list) { | ||
2772 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
2773 | int i; | ||
2774 | for (i = 0; i < spec->kctls.used; i++) | ||
2775 | kfree(kctl[i].name); | ||
2776 | } | ||
2777 | snd_array_free(&spec->kctls); | ||
2778 | } | ||
2779 | |||
2764 | static void alc_free(struct hda_codec *codec) | 2780 | static void alc_free(struct hda_codec *codec) |
2765 | { | 2781 | { |
2766 | struct alc_spec *spec = codec->spec; | 2782 | struct alc_spec *spec = codec->spec; |
2767 | unsigned int i; | ||
2768 | 2783 | ||
2769 | if (!spec) | 2784 | if (!spec) |
2770 | return; | 2785 | return; |
2771 | 2786 | ||
2772 | if (spec->kctl_alloc) { | 2787 | alc_free_kctls(codec); |
2773 | for (i = 0; i < spec->num_kctl_used; i++) | ||
2774 | kfree(spec->kctl_alloc[i].name); | ||
2775 | kfree(spec->kctl_alloc); | ||
2776 | } | ||
2777 | kfree(spec); | 2788 | kfree(spec); |
2778 | codec->spec = NULL; /* to be sure */ | 2789 | codec->spec = NULL; /* to be sure */ |
2779 | } | 2790 | } |
@@ -3458,9 +3469,6 @@ static struct alc_config_preset alc880_presets[] = { | |||
3458 | * Automatic parse of I/O pins from the BIOS configuration | 3469 | * Automatic parse of I/O pins from the BIOS configuration |
3459 | */ | 3470 | */ |
3460 | 3471 | ||
3461 | #define NUM_CONTROL_ALLOC 32 | ||
3462 | #define NUM_VERB_ALLOC 32 | ||
3463 | |||
3464 | enum { | 3472 | enum { |
3465 | ALC_CTL_WIDGET_VOL, | 3473 | ALC_CTL_WIDGET_VOL, |
3466 | ALC_CTL_WIDGET_MUTE, | 3474 | ALC_CTL_WIDGET_MUTE, |
@@ -3478,29 +3486,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
3478 | { | 3486 | { |
3479 | struct snd_kcontrol_new *knew; | 3487 | struct snd_kcontrol_new *knew; |
3480 | 3488 | ||
3481 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 3489 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
3482 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 3490 | knew = snd_array_new(&spec->kctls); |
3483 | 3491 | if (!knew) | |
3484 | /* array + terminator */ | 3492 | return -ENOMEM; |
3485 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); | ||
3486 | if (!knew) | ||
3487 | return -ENOMEM; | ||
3488 | if (spec->kctl_alloc) { | ||
3489 | memcpy(knew, spec->kctl_alloc, | ||
3490 | sizeof(*knew) * spec->num_kctl_alloc); | ||
3491 | kfree(spec->kctl_alloc); | ||
3492 | } | ||
3493 | spec->kctl_alloc = knew; | ||
3494 | spec->num_kctl_alloc = num; | ||
3495 | } | ||
3496 | |||
3497 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
3498 | *knew = alc880_control_templates[type]; | 3493 | *knew = alc880_control_templates[type]; |
3499 | knew->name = kstrdup(name, GFP_KERNEL); | 3494 | knew->name = kstrdup(name, GFP_KERNEL); |
3500 | if (!knew->name) | 3495 | if (!knew->name) |
3501 | return -ENOMEM; | 3496 | return -ENOMEM; |
3502 | knew->private_value = val; | 3497 | knew->private_value = val; |
3503 | spec->num_kctl_used++; | ||
3504 | return 0; | 3498 | return 0; |
3505 | } | 3499 | } |
3506 | 3500 | ||
@@ -3824,8 +3818,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
3824 | if (spec->autocfg.dig_in_pin) | 3818 | if (spec->autocfg.dig_in_pin) |
3825 | spec->dig_in_nid = ALC880_DIGIN_NID; | 3819 | spec->dig_in_nid = ALC880_DIGIN_NID; |
3826 | 3820 | ||
3827 | if (spec->kctl_alloc) | 3821 | if (spec->kctls.list) |
3828 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3822 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3829 | 3823 | ||
3830 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 3824 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; |
3831 | 3825 | ||
@@ -5218,7 +5212,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5218 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); | 5212 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); |
5219 | if (err < 0) | 5213 | if (err < 0) |
5220 | return err; | 5214 | return err; |
5221 | if (!spec->kctl_alloc) | 5215 | if (!spec->kctls.list) |
5222 | return 0; /* can't find valid BIOS pin config */ | 5216 | return 0; /* can't find valid BIOS pin config */ |
5223 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5217 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); |
5224 | if (err < 0) | 5218 | if (err < 0) |
@@ -5228,8 +5222,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5228 | 5222 | ||
5229 | if (spec->autocfg.dig_out_pin) | 5223 | if (spec->autocfg.dig_out_pin) |
5230 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5224 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5231 | if (spec->kctl_alloc) | 5225 | if (spec->kctls.list) |
5232 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 5226 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
5233 | 5227 | ||
5234 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 5228 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; |
5235 | 5229 | ||
@@ -10302,8 +10296,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10302 | if (spec->autocfg.dig_in_pin) | 10296 | if (spec->autocfg.dig_in_pin) |
10303 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10297 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10304 | 10298 | ||
10305 | if (spec->kctl_alloc) | 10299 | if (spec->kctls.list) |
10306 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 10300 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
10307 | 10301 | ||
10308 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 10302 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; |
10309 | spec->num_mux_defs = 1; | 10303 | spec->num_mux_defs = 1; |
@@ -11433,8 +11427,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11433 | if (spec->autocfg.dig_out_pin) | 11427 | if (spec->autocfg.dig_out_pin) |
11434 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11428 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11435 | 11429 | ||
11436 | if (spec->kctl_alloc) | 11430 | if (spec->kctls.list) |
11437 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 11431 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
11438 | 11432 | ||
11439 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11433 | if (spec->autocfg.speaker_pins[0] != 0x1d) |
11440 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; | 11434 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; |
@@ -12205,8 +12199,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12205 | if (spec->autocfg.dig_out_pin) | 12199 | if (spec->autocfg.dig_out_pin) |
12206 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12200 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12207 | 12201 | ||
12208 | if (spec->kctl_alloc) | 12202 | if (spec->kctls.list) |
12209 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 12203 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
12210 | 12204 | ||
12211 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | 12205 | /* create a beep mixer control if the pin 0x1d isn't assigned */ |
12212 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | 12206 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) |
@@ -13303,8 +13297,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13303 | if (spec->autocfg.dig_out_pin) | 13297 | if (spec->autocfg.dig_out_pin) |
13304 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13298 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13305 | 13299 | ||
13306 | if (spec->kctl_alloc) | 13300 | if (spec->kctls.list) |
13307 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 13301 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
13308 | 13302 | ||
13309 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 13303 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; |
13310 | 13304 | ||
@@ -14414,8 +14408,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14414 | if (spec->autocfg.dig_out_pin) | 14408 | if (spec->autocfg.dig_out_pin) |
14415 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 14409 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14416 | 14410 | ||
14417 | if (spec->kctl_alloc) | 14411 | if (spec->kctls.list) |
14418 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 14412 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
14419 | 14413 | ||
14420 | spec->init_verbs[spec->num_init_verbs++] | 14414 | spec->init_verbs[spec->num_init_verbs++] |
14421 | = alc861vd_volume_init_verbs; | 14415 | = alc861vd_volume_init_verbs; |
@@ -16241,8 +16235,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16241 | if (spec->autocfg.dig_out_pin) | 16235 | if (spec->autocfg.dig_out_pin) |
16242 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16236 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16243 | 16237 | ||
16244 | if (spec->kctl_alloc) | 16238 | if (spec->kctls.list) |
16245 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 16239 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
16246 | 16240 | ||
16247 | spec->num_mux_defs = 1; | 16241 | spec->num_mux_defs = 1; |
16248 | spec->input_mux = &spec->private_imux; | 16242 | spec->input_mux = &spec->private_imux; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 788fdc6f3264..c2f900f39466 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -30,12 +30,13 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/asoundef.h> | 32 | #include <sound/asoundef.h> |
33 | #include <sound/jack.h> | ||
33 | #include "hda_codec.h" | 34 | #include "hda_codec.h" |
34 | #include "hda_local.h" | 35 | #include "hda_local.h" |
35 | #include "hda_patch.h" | 36 | #include "hda_patch.h" |
36 | #include "hda_beep.h" | 37 | #include "hda_beep.h" |
37 | 38 | ||
38 | #define NUM_CONTROL_ALLOC 32 | 39 | #define STAC_INSERT_EVENT 0x10 |
39 | #define STAC_PWR_EVENT 0x20 | 40 | #define STAC_PWR_EVENT 0x20 |
40 | #define STAC_HP_EVENT 0x30 | 41 | #define STAC_HP_EVENT 0x30 |
41 | #define STAC_VREF_EVENT 0x40 | 42 | #define STAC_VREF_EVENT 0x40 |
@@ -129,6 +130,17 @@ enum { | |||
129 | STAC_927X_MODELS | 130 | STAC_927X_MODELS |
130 | }; | 131 | }; |
131 | 132 | ||
133 | struct sigmatel_event { | ||
134 | hda_nid_t nid; | ||
135 | int data; | ||
136 | }; | ||
137 | |||
138 | struct sigmatel_jack { | ||
139 | hda_nid_t nid; | ||
140 | int type; | ||
141 | struct snd_jack *jack; | ||
142 | }; | ||
143 | |||
132 | struct sigmatel_spec { | 144 | struct sigmatel_spec { |
133 | struct snd_kcontrol_new *mixers[4]; | 145 | struct snd_kcontrol_new *mixers[4]; |
134 | unsigned int num_mixers; | 146 | unsigned int num_mixers; |
@@ -161,6 +173,12 @@ struct sigmatel_spec { | |||
161 | hda_nid_t *pwr_nids; | 173 | hda_nid_t *pwr_nids; |
162 | hda_nid_t *dac_list; | 174 | hda_nid_t *dac_list; |
163 | 175 | ||
176 | /* jack detection */ | ||
177 | struct snd_array jacks; | ||
178 | |||
179 | /* events */ | ||
180 | struct snd_array events; | ||
181 | |||
164 | /* playback */ | 182 | /* playback */ |
165 | struct hda_input_mux *mono_mux; | 183 | struct hda_input_mux *mono_mux; |
166 | struct hda_input_mux *amp_mux; | 184 | struct hda_input_mux *amp_mux; |
@@ -218,8 +236,7 @@ struct sigmatel_spec { | |||
218 | 236 | ||
219 | /* dynamic controls and input_mux */ | 237 | /* dynamic controls and input_mux */ |
220 | struct auto_pin_cfg autocfg; | 238 | struct auto_pin_cfg autocfg; |
221 | unsigned int num_kctl_alloc, num_kctl_used; | 239 | struct snd_array kctls; |
222 | struct snd_kcontrol_new *kctl_alloc; | ||
223 | struct hda_input_mux private_dimux; | 240 | struct hda_input_mux private_dimux; |
224 | struct hda_input_mux private_imux; | 241 | struct hda_input_mux private_imux; |
225 | struct hda_input_mux private_smux; | 242 | struct hda_input_mux private_smux; |
@@ -1233,6 +1250,8 @@ static const char *slave_sws[] = { | |||
1233 | NULL | 1250 | NULL |
1234 | }; | 1251 | }; |
1235 | 1252 | ||
1253 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1254 | |||
1236 | static int stac92xx_build_controls(struct hda_codec *codec) | 1255 | static int stac92xx_build_controls(struct hda_codec *codec) |
1237 | { | 1256 | { |
1238 | struct sigmatel_spec *spec = codec->spec; | 1257 | struct sigmatel_spec *spec = codec->spec; |
@@ -1250,7 +1269,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1250 | } | 1269 | } |
1251 | if (spec->num_dmuxes > 0) { | 1270 | if (spec->num_dmuxes > 0) { |
1252 | stac_dmux_mixer.count = spec->num_dmuxes; | 1271 | stac_dmux_mixer.count = spec->num_dmuxes; |
1253 | err = snd_ctl_add(codec->bus->card, | 1272 | err = snd_hda_ctl_add(codec, |
1254 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1273 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1255 | if (err < 0) | 1274 | if (err < 0) |
1256 | return err; | 1275 | return err; |
@@ -1305,6 +1324,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1305 | return err; | 1324 | return err; |
1306 | } | 1325 | } |
1307 | 1326 | ||
1327 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1308 | return 0; | 1328 | return 0; |
1309 | } | 1329 | } |
1310 | 1330 | ||
@@ -2453,13 +2473,15 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2453 | { | 2473 | { |
2454 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2474 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2455 | struct sigmatel_spec *spec = codec->spec; | 2475 | struct sigmatel_spec *spec = codec->spec; |
2476 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
2477 | int nid = cfg->hp_pins[cfg->hp_outs - 1]; | ||
2456 | 2478 | ||
2457 | spec->hp_switch = ucontrol->value.integer.value[0]; | 2479 | spec->hp_switch = ucontrol->value.integer.value[0]; |
2458 | 2480 | ||
2459 | /* check to be sure that the ports are upto date with | 2481 | /* check to be sure that the ports are upto date with |
2460 | * switch changes | 2482 | * switch changes |
2461 | */ | 2483 | */ |
2462 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2484 | codec->patch_ops.unsol_event(codec, (STAC_HP_EVENT | nid) << 26); |
2463 | 2485 | ||
2464 | return 1; | 2486 | return 1; |
2465 | } | 2487 | } |
@@ -2499,7 +2521,8 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
2499 | * appropriately according to the pin direction | 2521 | * appropriately according to the pin direction |
2500 | */ | 2522 | */ |
2501 | if (spec->hp_detect) | 2523 | if (spec->hp_detect) |
2502 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2524 | codec->patch_ops.unsol_event(codec, |
2525 | (STAC_HP_EVENT | nid) << 26); | ||
2503 | 2526 | ||
2504 | return 1; | 2527 | return 1; |
2505 | } | 2528 | } |
@@ -2592,28 +2615,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, | |||
2592 | { | 2615 | { |
2593 | struct snd_kcontrol_new *knew; | 2616 | struct snd_kcontrol_new *knew; |
2594 | 2617 | ||
2595 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2618 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2596 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2619 | knew = snd_array_new(&spec->kctls); |
2597 | 2620 | if (!knew) | |
2598 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2621 | return -ENOMEM; |
2599 | if (! knew) | ||
2600 | return -ENOMEM; | ||
2601 | if (spec->kctl_alloc) { | ||
2602 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2603 | kfree(spec->kctl_alloc); | ||
2604 | } | ||
2605 | spec->kctl_alloc = knew; | ||
2606 | spec->num_kctl_alloc = num; | ||
2607 | } | ||
2608 | |||
2609 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2610 | *knew = stac92xx_control_templates[type]; | 2622 | *knew = stac92xx_control_templates[type]; |
2611 | knew->index = idx; | 2623 | knew->index = idx; |
2612 | knew->name = kstrdup(name, GFP_KERNEL); | 2624 | knew->name = kstrdup(name, GFP_KERNEL); |
2613 | if (! knew->name) | 2625 | if (! knew->name) |
2614 | return -ENOMEM; | 2626 | return -ENOMEM; |
2615 | knew->private_value = val; | 2627 | knew->private_value = val; |
2616 | spec->num_kctl_used++; | ||
2617 | return 0; | 2628 | return 0; |
2618 | } | 2629 | } |
2619 | 2630 | ||
@@ -3434,8 +3445,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3434 | if (dig_in && spec->autocfg.dig_in_pin) | 3445 | if (dig_in && spec->autocfg.dig_in_pin) |
3435 | spec->dig_in_nid = dig_in; | 3446 | spec->dig_in_nid = dig_in; |
3436 | 3447 | ||
3437 | if (spec->kctl_alloc) | 3448 | if (spec->kctls.list) |
3438 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3449 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3439 | 3450 | ||
3440 | spec->input_mux = &spec->private_imux; | 3451 | spec->input_mux = &spec->private_imux; |
3441 | spec->dinput_mux = &spec->private_dimux; | 3452 | spec->dinput_mux = &spec->private_dimux; |
@@ -3536,8 +3547,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3536 | if (spec->autocfg.dig_in_pin) | 3547 | if (spec->autocfg.dig_in_pin) |
3537 | spec->dig_in_nid = 0x04; | 3548 | spec->dig_in_nid = 0x04; |
3538 | 3549 | ||
3539 | if (spec->kctl_alloc) | 3550 | if (spec->kctls.list) |
3540 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3551 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3541 | 3552 | ||
3542 | spec->input_mux = &spec->private_imux; | 3553 | spec->input_mux = &spec->private_imux; |
3543 | spec->dinput_mux = &spec->private_dimux; | 3554 | spec->dinput_mux = &spec->private_dimux; |
@@ -3581,13 +3592,70 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
3581 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 3592 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
3582 | } | 3593 | } |
3583 | 3594 | ||
3595 | static int stac92xx_add_jack(struct hda_codec *codec, | ||
3596 | hda_nid_t nid, int type) | ||
3597 | { | ||
3598 | struct sigmatel_spec *spec = codec->spec; | ||
3599 | struct sigmatel_jack *jack; | ||
3600 | int def_conf = snd_hda_codec_read(codec, nid, | ||
3601 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3602 | int connectivity = get_defcfg_connect(def_conf); | ||
3603 | char name[32]; | ||
3604 | |||
3605 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | ||
3606 | return 0; | ||
3607 | |||
3608 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
3609 | jack = snd_array_new(&spec->jacks); | ||
3610 | if (!jack) | ||
3611 | return -ENOMEM; | ||
3612 | jack->nid = nid; | ||
3613 | jack->type = type; | ||
3614 | |||
3615 | sprintf(name, "%s at %s %s Jack", | ||
3616 | snd_hda_get_jack_type(def_conf), | ||
3617 | snd_hda_get_jack_connectivity(def_conf), | ||
3618 | snd_hda_get_jack_location(def_conf)); | ||
3619 | |||
3620 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
3621 | } | ||
3622 | |||
3623 | static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | ||
3624 | int data) | ||
3625 | { | ||
3626 | struct sigmatel_event *event; | ||
3627 | |||
3628 | snd_array_init(&spec->events, sizeof(*event), 32); | ||
3629 | event = snd_array_new(&spec->events); | ||
3630 | if (!event) | ||
3631 | return -ENOMEM; | ||
3632 | event->nid = nid; | ||
3633 | event->data = data; | ||
3634 | |||
3635 | return 0; | ||
3636 | } | ||
3637 | |||
3638 | static int stac92xx_event_data(struct hda_codec *codec, hda_nid_t nid) | ||
3639 | { | ||
3640 | struct sigmatel_spec *spec = codec->spec; | ||
3641 | struct sigmatel_event *events = spec->events.list; | ||
3642 | if (events) { | ||
3643 | int i; | ||
3644 | for (i = 0; i < spec->events.used; i++) | ||
3645 | if (events[i].nid == nid) | ||
3646 | return events[i].data; | ||
3647 | } | ||
3648 | return 0; | ||
3649 | } | ||
3650 | |||
3584 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 3651 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
3585 | unsigned int event) | 3652 | unsigned int event) |
3586 | { | 3653 | { |
3587 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 3654 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
3588 | snd_hda_codec_write_cache(codec, nid, 0, | 3655 | snd_hda_codec_write_cache(codec, nid, 0, |
3589 | AC_VERB_SET_UNSOLICITED_ENABLE, | 3656 | AC_VERB_SET_UNSOLICITED_ENABLE, |
3590 | (AC_USRSP_EN | event)); | 3657 | (AC_USRSP_EN | event | nid)); |
3658 | } | ||
3591 | } | 3659 | } |
3592 | 3660 | ||
3593 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 3661 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) |
@@ -3617,7 +3685,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3617 | { | 3685 | { |
3618 | struct sigmatel_spec *spec = codec->spec; | 3686 | struct sigmatel_spec *spec = codec->spec; |
3619 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3687 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3620 | int i; | 3688 | int i, err; |
3621 | 3689 | ||
3622 | snd_hda_sequence_write(codec, spec->init); | 3690 | snd_hda_sequence_write(codec, spec->init); |
3623 | 3691 | ||
@@ -3630,21 +3698,36 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3630 | /* set up pins */ | 3698 | /* set up pins */ |
3631 | if (spec->hp_detect) { | 3699 | if (spec->hp_detect) { |
3632 | /* Enable unsolicited responses on the HP widget */ | 3700 | /* Enable unsolicited responses on the HP widget */ |
3633 | for (i = 0; i < cfg->hp_outs; i++) | 3701 | for (i = 0; i < cfg->hp_outs; i++) { |
3634 | enable_pin_detect(codec, cfg->hp_pins[i], | 3702 | int type = SND_JACK_HEADPHONE; |
3635 | STAC_HP_EVENT); | 3703 | hda_nid_t nid = cfg->hp_pins[i]; |
3704 | enable_pin_detect(codec, nid, STAC_HP_EVENT | nid); | ||
3705 | /* jack detection */ | ||
3706 | if (cfg->hp_outs == i) | ||
3707 | type |= SND_JACK_LINEOUT; | ||
3708 | err = stac92xx_add_jack(codec, nid, type); | ||
3709 | if (err < 0) | ||
3710 | return err; | ||
3711 | |||
3712 | } | ||
3636 | /* force to enable the first line-out; the others are set up | 3713 | /* force to enable the first line-out; the others are set up |
3637 | * in unsol_event | 3714 | * in unsol_event |
3638 | */ | 3715 | */ |
3639 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 3716 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], |
3640 | AC_PINCTL_OUT_EN); | 3717 | AC_PINCTL_OUT_EN); |
3641 | stac92xx_auto_init_hp_out(codec); | ||
3642 | /* fake event to set up pins */ | 3718 | /* fake event to set up pins */ |
3643 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 3719 | codec->patch_ops.unsol_event(codec, |
3720 | (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); | ||
3644 | } else { | 3721 | } else { |
3645 | stac92xx_auto_init_multi_out(codec); | 3722 | stac92xx_auto_init_multi_out(codec); |
3646 | stac92xx_auto_init_hp_out(codec); | 3723 | stac92xx_auto_init_hp_out(codec); |
3647 | } | 3724 | } |
3725 | for (i = 0; i < cfg->line_outs; i++) { | ||
3726 | err = stac92xx_add_jack(codec, | ||
3727 | cfg->line_out_pins[i], SND_JACK_LINEOUT); | ||
3728 | if (err < 0) | ||
3729 | return err; | ||
3730 | } | ||
3648 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3731 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
3649 | hda_nid_t nid = cfg->input_pins[i]; | 3732 | hda_nid_t nid = cfg->input_pins[i]; |
3650 | if (nid) { | 3733 | if (nid) { |
@@ -3657,6 +3740,11 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3657 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) | 3740 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) |
3658 | pinctl |= stac92xx_get_vref(codec, nid); | 3741 | pinctl |= stac92xx_get_vref(codec, nid); |
3659 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 3742 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
3743 | err = stac92xx_add_jack(codec, nid, | ||
3744 | SND_JACK_MICROPHONE); | ||
3745 | if (err < 0) | ||
3746 | return err; | ||
3747 | enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid); | ||
3660 | } | 3748 | } |
3661 | } | 3749 | } |
3662 | for (i = 0; i < spec->num_dmics; i++) | 3750 | for (i = 0; i < spec->num_dmics; i++) |
@@ -3698,22 +3786,42 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3698 | return 0; | 3786 | return 0; |
3699 | } | 3787 | } |
3700 | 3788 | ||
3789 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
3790 | { | ||
3791 | struct sigmatel_spec *spec = codec->spec; | ||
3792 | if (spec->jacks.list) { | ||
3793 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3794 | int i; | ||
3795 | for (i = 0; i < spec->jacks.used; i++) | ||
3796 | snd_device_free(codec->bus->card, &jacks[i].jack); | ||
3797 | } | ||
3798 | snd_array_free(&spec->jacks); | ||
3799 | } | ||
3800 | |||
3801 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
3802 | { | ||
3803 | struct sigmatel_spec *spec = codec->spec; | ||
3804 | |||
3805 | if (spec->kctls.list) { | ||
3806 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
3807 | int i; | ||
3808 | for (i = 0; i < spec->kctls.used; i++) | ||
3809 | kfree(kctl[i].name); | ||
3810 | } | ||
3811 | snd_array_free(&spec->kctls); | ||
3812 | } | ||
3813 | |||
3701 | static void stac92xx_free(struct hda_codec *codec) | 3814 | static void stac92xx_free(struct hda_codec *codec) |
3702 | { | 3815 | { |
3703 | struct sigmatel_spec *spec = codec->spec; | 3816 | struct sigmatel_spec *spec = codec->spec; |
3704 | int i; | ||
3705 | 3817 | ||
3706 | if (! spec) | 3818 | if (! spec) |
3707 | return; | 3819 | return; |
3708 | 3820 | ||
3709 | if (spec->kctl_alloc) { | ||
3710 | for (i = 0; i < spec->num_kctl_used; i++) | ||
3711 | kfree(spec->kctl_alloc[i].name); | ||
3712 | kfree(spec->kctl_alloc); | ||
3713 | } | ||
3714 | |||
3715 | if (spec->bios_pin_configs) | 3821 | if (spec->bios_pin_configs) |
3716 | kfree(spec->bios_pin_configs); | 3822 | kfree(spec->bios_pin_configs); |
3823 | stac92xx_free_jacks(codec); | ||
3824 | snd_array_free(&spec->events); | ||
3717 | 3825 | ||
3718 | kfree(spec); | 3826 | kfree(spec); |
3719 | snd_hda_detach_beep_device(codec); | 3827 | snd_hda_detach_beep_device(codec); |
@@ -3852,24 +3960,57 @@ static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | |||
3852 | 3960 | ||
3853 | /* power down unused output ports */ | 3961 | /* power down unused output ports */ |
3854 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); | 3962 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); |
3855 | }; | 3963 | } |
3964 | |||
3965 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
3966 | { | ||
3967 | struct sigmatel_spec *spec = codec->spec; | ||
3968 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3969 | |||
3970 | if (jacks) { | ||
3971 | int i; | ||
3972 | for (i = 0; i < spec->jacks.used; i++) { | ||
3973 | if (jacks->nid == nid) { | ||
3974 | unsigned int pin_ctl = | ||
3975 | snd_hda_codec_read(codec, nid, | ||
3976 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
3977 | 0x00); | ||
3978 | int type = jacks->type; | ||
3979 | if (type == (SND_JACK_LINEOUT | ||
3980 | | SND_JACK_HEADPHONE)) | ||
3981 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
3982 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
3983 | snd_jack_report(jacks->jack, | ||
3984 | get_hp_pin_presence(codec, nid) | ||
3985 | ? type : 0); | ||
3986 | } | ||
3987 | jacks++; | ||
3988 | } | ||
3989 | } | ||
3990 | } | ||
3856 | 3991 | ||
3857 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 3992 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) |
3858 | { | 3993 | { |
3859 | struct sigmatel_spec *spec = codec->spec; | 3994 | struct sigmatel_spec *spec = codec->spec; |
3860 | int idx = res >> 26 & 0x0f; | 3995 | int event = (res >> 26) & 0x70; |
3996 | int nid = res >> 26 & 0x0f; | ||
3861 | 3997 | ||
3862 | switch ((res >> 26) & 0x70) { | 3998 | switch (event) { |
3863 | case STAC_HP_EVENT: | 3999 | case STAC_HP_EVENT: |
3864 | stac92xx_hp_detect(codec, res); | 4000 | stac92xx_hp_detect(codec, res); |
3865 | /* fallthru */ | 4001 | /* fallthru */ |
4002 | case STAC_INSERT_EVENT: | ||
3866 | case STAC_PWR_EVENT: | 4003 | case STAC_PWR_EVENT: |
3867 | if (spec->num_pwrs > 0) | 4004 | if (nid) { |
3868 | stac92xx_pin_sense(codec, idx); | 4005 | if (spec->num_pwrs > 0) |
4006 | stac92xx_pin_sense(codec, nid); | ||
4007 | stac92xx_report_jack(codec, nid); | ||
4008 | } | ||
3869 | break; | 4009 | break; |
3870 | case STAC_VREF_EVENT: { | 4010 | case STAC_VREF_EVENT: { |
3871 | int data = snd_hda_codec_read(codec, codec->afg, 0, | 4011 | int data = snd_hda_codec_read(codec, codec->afg, 0, |
3872 | AC_VERB_GET_GPIO_DATA, 0); | 4012 | AC_VERB_GET_GPIO_DATA, 0); |
4013 | int idx = stac92xx_event_data(codec, nid); | ||
3873 | /* toggle VREF state based on GPIOx status */ | 4014 | /* toggle VREF state based on GPIOx status */ |
3874 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 4015 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
3875 | !!(data & (1 << idx))); | 4016 | !!(data & (1 << idx))); |
@@ -4392,8 +4533,11 @@ again: | |||
4392 | snd_hda_codec_write(codec, codec->afg, 0, | 4533 | snd_hda_codec_write(codec, codec->afg, 0, |
4393 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 4534 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
4394 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4535 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4395 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4536 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4396 | (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | 4537 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4538 | err = stac92xx_add_event(spec, codec->afg, 0x02); | ||
4539 | if (err < 0) | ||
4540 | return err; | ||
4397 | spec->gpio_mask |= 0x02; | 4541 | spec->gpio_mask |= 0x02; |
4398 | break; | 4542 | break; |
4399 | } | 4543 | } |
@@ -4792,8 +4936,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4792 | snd_hda_codec_write(codec, codec->afg, 0, | 4936 | snd_hda_codec_write(codec, codec->afg, 0, |
4793 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 4937 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4794 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4938 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4795 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4939 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4796 | (AC_USRSP_EN | STAC_HP_EVENT)); | 4940 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4941 | err = stac92xx_add_event(spec, codec->afg, 0x01); | ||
4942 | if (err < 0) | ||
4943 | return err; | ||
4797 | 4944 | ||
4798 | spec->gpio_dir = 0x0b; | 4945 | spec->gpio_dir = 0x0b; |
4799 | spec->eapd_mask = 0x01; | 4946 | spec->eapd_mask = 0x01; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 63e4871e5d8f..760e14ae3bff 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -53,9 +53,6 @@ | |||
53 | #define AMP_VAL_IDX_SHIFT 19 | 53 | #define AMP_VAL_IDX_SHIFT 19 |
54 | #define AMP_VAL_IDX_MASK (0x0f<<19) | 54 | #define AMP_VAL_IDX_MASK (0x0f<<19) |
55 | 55 | ||
56 | #define NUM_CONTROL_ALLOC 32 | ||
57 | #define NUM_VERB_ALLOC 32 | ||
58 | |||
59 | /* Pin Widget NID */ | 56 | /* Pin Widget NID */ |
60 | #define VT1708_HP_NID 0x13 | 57 | #define VT1708_HP_NID 0x13 |
61 | #define VT1708_DIGOUT_NID 0x14 | 58 | #define VT1708_DIGOUT_NID 0x14 |
@@ -227,8 +224,7 @@ struct via_spec { | |||
227 | 224 | ||
228 | /* dynamic controls, init_verbs and input_mux */ | 225 | /* dynamic controls, init_verbs and input_mux */ |
229 | struct auto_pin_cfg autocfg; | 226 | struct auto_pin_cfg autocfg; |
230 | unsigned int num_kctl_alloc, num_kctl_used; | 227 | struct snd_array kctls; |
231 | struct snd_kcontrol_new *kctl_alloc; | ||
232 | struct hda_input_mux private_imux[2]; | 228 | struct hda_input_mux private_imux[2]; |
233 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 229 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
234 | 230 | ||
@@ -272,33 +268,31 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
272 | { | 268 | { |
273 | struct snd_kcontrol_new *knew; | 269 | struct snd_kcontrol_new *knew; |
274 | 270 | ||
275 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 271 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
276 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 272 | knew = snd_array_new(&spec->kctls); |
277 | 273 | if (!knew) | |
278 | /* array + terminator */ | 274 | return -ENOMEM; |
279 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); | ||
280 | if (!knew) | ||
281 | return -ENOMEM; | ||
282 | if (spec->kctl_alloc) { | ||
283 | memcpy(knew, spec->kctl_alloc, | ||
284 | sizeof(*knew) * spec->num_kctl_alloc); | ||
285 | kfree(spec->kctl_alloc); | ||
286 | } | ||
287 | spec->kctl_alloc = knew; | ||
288 | spec->num_kctl_alloc = num; | ||
289 | } | ||
290 | |||
291 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
292 | *knew = vt1708_control_templates[type]; | 275 | *knew = vt1708_control_templates[type]; |
293 | knew->name = kstrdup(name, GFP_KERNEL); | 276 | knew->name = kstrdup(name, GFP_KERNEL); |
294 | |||
295 | if (!knew->name) | 277 | if (!knew->name) |
296 | return -ENOMEM; | 278 | return -ENOMEM; |
297 | knew->private_value = val; | 279 | knew->private_value = val; |
298 | spec->num_kctl_used++; | ||
299 | return 0; | 280 | return 0; |
300 | } | 281 | } |
301 | 282 | ||
283 | static void via_free_kctls(struct hda_codec *codec) | ||
284 | { | ||
285 | struct via_spec *spec = codec->spec; | ||
286 | |||
287 | if (spec->kctls.list) { | ||
288 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
289 | int i; | ||
290 | for (i = 0; i < spec->kctls.used; i++) | ||
291 | kfree(kctl[i].name); | ||
292 | } | ||
293 | snd_array_free(&spec->kctls); | ||
294 | } | ||
295 | |||
302 | /* create input playback/capture controls for the given pin */ | 296 | /* create input playback/capture controls for the given pin */ |
303 | static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, | 297 | static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, |
304 | const char *ctlname, int idx, int mix_nid) | 298 | const char *ctlname, int idx, int mix_nid) |
@@ -896,6 +890,7 @@ static int via_build_controls(struct hda_codec *codec) | |||
896 | if (err < 0) | 890 | if (err < 0) |
897 | return err; | 891 | return err; |
898 | } | 892 | } |
893 | via_free_kctls(codec); /* no longer needed */ | ||
899 | return 0; | 894 | return 0; |
900 | } | 895 | } |
901 | 896 | ||
@@ -941,17 +936,11 @@ static int via_build_pcms(struct hda_codec *codec) | |||
941 | static void via_free(struct hda_codec *codec) | 936 | static void via_free(struct hda_codec *codec) |
942 | { | 937 | { |
943 | struct via_spec *spec = codec->spec; | 938 | struct via_spec *spec = codec->spec; |
944 | unsigned int i; | ||
945 | 939 | ||
946 | if (!spec) | 940 | if (!spec) |
947 | return; | 941 | return; |
948 | 942 | ||
949 | if (spec->kctl_alloc) { | 943 | via_free_kctls(codec); |
950 | for (i = 0; i < spec->num_kctl_used; i++) | ||
951 | kfree(spec->kctl_alloc[i].name); | ||
952 | kfree(spec->kctl_alloc); | ||
953 | } | ||
954 | |||
955 | kfree(codec->spec); | 944 | kfree(codec->spec); |
956 | } | 945 | } |
957 | 946 | ||
@@ -1373,8 +1362,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
1373 | if (spec->autocfg.dig_in_pin) | 1362 | if (spec->autocfg.dig_in_pin) |
1374 | spec->dig_in_nid = VT1708_DIGIN_NID; | 1363 | spec->dig_in_nid = VT1708_DIGIN_NID; |
1375 | 1364 | ||
1376 | if (spec->kctl_alloc) | 1365 | if (spec->kctls.list) |
1377 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1366 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
1378 | 1367 | ||
1379 | spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; | 1368 | spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; |
1380 | 1369 | ||
@@ -1846,8 +1835,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1846 | if (spec->autocfg.dig_in_pin) | 1835 | if (spec->autocfg.dig_in_pin) |
1847 | spec->dig_in_nid = VT1709_DIGIN_NID; | 1836 | spec->dig_in_nid = VT1709_DIGIN_NID; |
1848 | 1837 | ||
1849 | if (spec->kctl_alloc) | 1838 | if (spec->kctls.list) |
1850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1839 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
1851 | 1840 | ||
1852 | spec->input_mux = &spec->private_imux[0]; | 1841 | spec->input_mux = &spec->private_imux[0]; |
1853 | 1842 | ||
@@ -2390,8 +2379,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
2390 | if (spec->autocfg.dig_in_pin) | 2379 | if (spec->autocfg.dig_in_pin) |
2391 | spec->dig_in_nid = VT1708B_DIGIN_NID; | 2380 | spec->dig_in_nid = VT1708B_DIGIN_NID; |
2392 | 2381 | ||
2393 | if (spec->kctl_alloc) | 2382 | if (spec->kctls.list) |
2394 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2383 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2395 | 2384 | ||
2396 | spec->input_mux = &spec->private_imux[0]; | 2385 | spec->input_mux = &spec->private_imux[0]; |
2397 | 2386 | ||
@@ -2855,8 +2844,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
2855 | 2844 | ||
2856 | spec->extra_dig_out_nid = 0x15; | 2845 | spec->extra_dig_out_nid = 0x15; |
2857 | 2846 | ||
2858 | if (spec->kctl_alloc) | 2847 | if (spec->kctls.list) |
2859 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2848 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2860 | 2849 | ||
2861 | spec->input_mux = &spec->private_imux[0]; | 2850 | spec->input_mux = &spec->private_imux[0]; |
2862 | 2851 | ||
@@ -3174,8 +3163,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3174 | 3163 | ||
3175 | spec->extra_dig_out_nid = 0x1B; | 3164 | spec->extra_dig_out_nid = 0x1B; |
3176 | 3165 | ||
3177 | if (spec->kctl_alloc) | 3166 | if (spec->kctls.list) |
3178 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3167 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3179 | 3168 | ||
3180 | spec->input_mux = &spec->private_imux[0]; | 3169 | spec->input_mux = &spec->private_imux[0]; |
3181 | 3170 | ||