diff options
-rw-r--r-- | include/linux/input.h | 1 | ||||
-rw-r--r-- | include/sound/jack.h | 1 | ||||
-rw-r--r-- | sound/core/jack.c | 9 | ||||
-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 | 154 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 24 | ||||
-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 |
16 files changed, 981 insertions, 448 deletions
diff --git a/include/linux/input.h b/include/linux/input.h index a5802c9c81a4..7323d2ff5151 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -644,6 +644,7 @@ struct input_absinfo { | |||
644 | #define SW_RADIO SW_RFKILL_ALL /* deprecated */ | 644 | #define SW_RADIO SW_RFKILL_ALL /* deprecated */ |
645 | #define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ | 645 | #define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ |
646 | #define SW_DOCK 0x05 /* set = plugged into dock */ | 646 | #define SW_DOCK 0x05 /* set = plugged into dock */ |
647 | #define SW_LINEOUT_INSERT 0x06 /* set = inserted */ | ||
647 | #define SW_MAX 0x0f | 648 | #define SW_MAX 0x0f |
648 | #define SW_CNT (SW_MAX+1) | 649 | #define SW_CNT (SW_MAX+1) |
649 | 650 | ||
diff --git a/include/sound/jack.h b/include/sound/jack.h index b1b2b8b59adb..7cb25f4b50bb 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h | |||
@@ -35,6 +35,7 @@ enum snd_jack_types { | |||
35 | SND_JACK_HEADPHONE = 0x0001, | 35 | SND_JACK_HEADPHONE = 0x0001, |
36 | SND_JACK_MICROPHONE = 0x0002, | 36 | SND_JACK_MICROPHONE = 0x0002, |
37 | SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, | 37 | SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, |
38 | SND_JACK_LINEOUT = 0x0004, | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | struct snd_jack { | 41 | struct snd_jack { |
diff --git a/sound/core/jack.c b/sound/core/jack.c index 8133a2b173a5..438445f77d6d 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
@@ -34,6 +34,7 @@ static int snd_jack_dev_free(struct snd_device *device) | |||
34 | else | 34 | else |
35 | input_free_device(jack->input_dev); | 35 | input_free_device(jack->input_dev); |
36 | 36 | ||
37 | kfree(jack->id); | ||
37 | kfree(jack); | 38 | kfree(jack); |
38 | 39 | ||
39 | return 0; | 40 | return 0; |
@@ -87,7 +88,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
87 | if (jack == NULL) | 88 | if (jack == NULL) |
88 | return -ENOMEM; | 89 | return -ENOMEM; |
89 | 90 | ||
90 | jack->id = id; | 91 | jack->id = kstrdup(id, GFP_KERNEL); |
91 | 92 | ||
92 | jack->input_dev = input_allocate_device(); | 93 | jack->input_dev = input_allocate_device(); |
93 | if (jack->input_dev == NULL) { | 94 | if (jack->input_dev == NULL) { |
@@ -102,6 +103,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
102 | if (type & SND_JACK_HEADPHONE) | 103 | if (type & SND_JACK_HEADPHONE) |
103 | input_set_capability(jack->input_dev, EV_SW, | 104 | input_set_capability(jack->input_dev, EV_SW, |
104 | SW_HEADPHONE_INSERT); | 105 | SW_HEADPHONE_INSERT); |
106 | if (type & SND_JACK_LINEOUT) | ||
107 | input_set_capability(jack->input_dev, EV_SW, | ||
108 | SW_LINEOUT_INSERT); | ||
105 | if (type & SND_JACK_MICROPHONE) | 109 | if (type & SND_JACK_MICROPHONE) |
106 | input_set_capability(jack->input_dev, EV_SW, | 110 | input_set_capability(jack->input_dev, EV_SW, |
107 | SW_MICROPHONE_INSERT); | 111 | SW_MICROPHONE_INSERT); |
@@ -150,6 +154,9 @@ void snd_jack_report(struct snd_jack *jack, int status) | |||
150 | if (jack->type & SND_JACK_HEADPHONE) | 154 | if (jack->type & SND_JACK_HEADPHONE) |
151 | input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, | 155 | input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, |
152 | status & SND_JACK_HEADPHONE); | 156 | status & SND_JACK_HEADPHONE); |
157 | if (jack->type & SND_JACK_LINEOUT) | ||
158 | input_report_switch(jack->input_dev, SW_LINEOUT_INSERT, | ||
159 | status & SND_JACK_LINEOUT); | ||
153 | if (jack->type & SND_JACK_MICROPHONE) | 160 | if (jack->type & SND_JACK_MICROPHONE) |
154 | input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, | 161 | input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, |
155 | status & SND_JACK_MICROPHONE); | 162 | status & SND_JACK_MICROPHONE); |
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 ba1ab737b55f..8991db78fb67 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -108,6 +108,52 @@ static void hda_keep_power_on(struct hda_codec *codec); | |||
108 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | 108 | static inline void hda_keep_power_on(struct hda_codec *codec) {} |
109 | #endif | 109 | #endif |
110 | 110 | ||
111 | const char *snd_hda_get_jack_location(u32 cfg) | ||
112 | { | ||
113 | static char *bases[7] = { | ||
114 | "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", | ||
115 | }; | ||
116 | static unsigned char specials_idx[] = { | ||
117 | 0x07, 0x08, | ||
118 | 0x17, 0x18, 0x19, | ||
119 | 0x37, 0x38 | ||
120 | }; | ||
121 | static char *specials[] = { | ||
122 | "Rear Panel", "Drive Bar", | ||
123 | "Riser", "HDMI", "ATAPI", | ||
124 | "Mobile-In", "Mobile-Out" | ||
125 | }; | ||
126 | int i; | ||
127 | cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; | ||
128 | if ((cfg & 0x0f) < 7) | ||
129 | return bases[cfg & 0x0f]; | ||
130 | for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { | ||
131 | if (cfg == specials_idx[i]) | ||
132 | return specials[i]; | ||
133 | } | ||
134 | return "UNKNOWN"; | ||
135 | } | ||
136 | |||
137 | const char *snd_hda_get_jack_connectivity(u32 cfg) | ||
138 | { | ||
139 | static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; | ||
140 | |||
141 | return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; | ||
142 | } | ||
143 | |||
144 | const char *snd_hda_get_jack_type(u32 cfg) | ||
145 | { | ||
146 | static char *jack_types[16] = { | ||
147 | "Line Out", "Speaker", "HP Out", "CD", | ||
148 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | ||
149 | "Line In", "Aux", "Mic", "Telephony", | ||
150 | "SPDIF In", "Digitial In", "Reserved", "Other" | ||
151 | }; | ||
152 | |||
153 | return jack_types[(cfg & AC_DEFCFG_DEVICE) | ||
154 | >> AC_DEFCFG_DEVICE_SHIFT]; | ||
155 | } | ||
156 | |||
111 | /** | 157 | /** |
112 | * snd_hda_codec_read - send a command and get the response | 158 | * snd_hda_codec_read - send a command and get the response |
113 | * @codec: the HDA codec | 159 | * @codec: the HDA codec |
@@ -345,7 +391,7 @@ static void process_unsol_events(struct work_struct *work) | |||
345 | /* | 391 | /* |
346 | * initialize unsolicited queue | 392 | * initialize unsolicited queue |
347 | */ | 393 | */ |
348 | static int __devinit init_unsol_queue(struct hda_bus *bus) | 394 | static int init_unsol_queue(struct hda_bus *bus) |
349 | { | 395 | { |
350 | struct hda_bus_unsolicited *unsol; | 396 | struct hda_bus_unsolicited *unsol; |
351 | 397 | ||
@@ -394,6 +440,20 @@ static int snd_hda_bus_dev_free(struct snd_device *device) | |||
394 | return snd_hda_bus_free(bus); | 440 | return snd_hda_bus_free(bus); |
395 | } | 441 | } |
396 | 442 | ||
443 | #ifdef CONFIG_SND_HDA_HWDEP | ||
444 | static int snd_hda_bus_dev_register(struct snd_device *device) | ||
445 | { | ||
446 | struct hda_bus *bus = device->device_data; | ||
447 | struct hda_codec *codec; | ||
448 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
449 | snd_hda_hwdep_add_sysfs(codec); | ||
450 | } | ||
451 | return 0; | ||
452 | } | ||
453 | #else | ||
454 | #define snd_hda_bus_dev_register NULL | ||
455 | #endif | ||
456 | |||
397 | /** | 457 | /** |
398 | * snd_hda_bus_new - create a HDA bus | 458 | * snd_hda_bus_new - create a HDA bus |
399 | * @card: the card entry | 459 | * @card: the card entry |
@@ -409,6 +469,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
409 | struct hda_bus *bus; | 469 | struct hda_bus *bus; |
410 | int err; | 470 | int err; |
411 | static struct snd_device_ops dev_ops = { | 471 | static struct snd_device_ops dev_ops = { |
472 | .dev_register = snd_hda_bus_dev_register, | ||
412 | .dev_free = snd_hda_bus_dev_free, | 473 | .dev_free = snd_hda_bus_dev_free, |
413 | }; | 474 | }; |
414 | 475 | ||
@@ -447,7 +508,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
447 | 508 | ||
448 | #ifdef CONFIG_SND_HDA_GENERIC | 509 | #ifdef CONFIG_SND_HDA_GENERIC |
449 | #define is_generic_config(codec) \ | 510 | #define is_generic_config(codec) \ |
450 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 511 | (codec->modelname && !strcmp(codec->modelname, "generic")) |
451 | #else | 512 | #else |
452 | #define is_generic_config(codec) 0 | 513 | #define is_generic_config(codec) 0 |
453 | #endif | 514 | #endif |
@@ -455,7 +516,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
455 | /* | 516 | /* |
456 | * find a matching codec preset | 517 | * find a matching codec preset |
457 | */ | 518 | */ |
458 | static const struct hda_codec_preset __devinit * | 519 | static const struct hda_codec_preset * |
459 | find_codec_preset(struct hda_codec *codec) | 520 | find_codec_preset(struct hda_codec *codec) |
460 | { | 521 | { |
461 | const struct hda_codec_preset **tbl, *preset; | 522 | const struct hda_codec_preset **tbl, *preset; |
@@ -482,15 +543,14 @@ find_codec_preset(struct hda_codec *codec) | |||
482 | } | 543 | } |
483 | 544 | ||
484 | /* | 545 | /* |
485 | * snd_hda_get_codec_name - store the codec name | 546 | * get_codec_name - store the codec name |
486 | */ | 547 | */ |
487 | void snd_hda_get_codec_name(struct hda_codec *codec, | 548 | static int get_codec_name(struct hda_codec *codec) |
488 | char *name, int namelen) | ||
489 | { | 549 | { |
490 | const struct hda_vendor_id *c; | 550 | const struct hda_vendor_id *c; |
491 | const char *vendor = NULL; | 551 | const char *vendor = NULL; |
492 | u16 vendor_id = codec->vendor_id >> 16; | 552 | u16 vendor_id = codec->vendor_id >> 16; |
493 | char tmp[16]; | 553 | char tmp[16], name[32]; |
494 | 554 | ||
495 | for (c = hda_vendor_ids; c->id; c++) { | 555 | for (c = hda_vendor_ids; c->id; c++) { |
496 | if (c->id == vendor_id) { | 556 | if (c->id == vendor_id) { |
@@ -503,10 +563,15 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
503 | vendor = tmp; | 563 | vendor = tmp; |
504 | } | 564 | } |
505 | if (codec->preset && codec->preset->name) | 565 | if (codec->preset && codec->preset->name) |
506 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); | 566 | snprintf(name, sizeof(name), "%s %s", vendor, |
567 | codec->preset->name); | ||
507 | else | 568 | else |
508 | snprintf(name, namelen, "%s ID %x", vendor, | 569 | snprintf(name, sizeof(name), "%s ID %x", vendor, |
509 | codec->vendor_id & 0xffff); | 570 | codec->vendor_id & 0xffff); |
571 | codec->name = kstrdup(name, GFP_KERNEL); | ||
572 | if (!codec->name) | ||
573 | return -ENOMEM; | ||
574 | return 0; | ||
510 | } | 575 | } |
511 | 576 | ||
512 | /* | 577 | /* |
@@ -571,11 +636,14 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
571 | flush_scheduled_work(); | 636 | flush_scheduled_work(); |
572 | #endif | 637 | #endif |
573 | list_del(&codec->list); | 638 | list_del(&codec->list); |
639 | snd_array_free(&codec->mixers); | ||
574 | codec->bus->caddr_tbl[codec->addr] = NULL; | 640 | codec->bus->caddr_tbl[codec->addr] = NULL; |
575 | if (codec->patch_ops.free) | 641 | if (codec->patch_ops.free) |
576 | codec->patch_ops.free(codec); | 642 | codec->patch_ops.free(codec); |
577 | free_hda_cache(&codec->amp_cache); | 643 | free_hda_cache(&codec->amp_cache); |
578 | free_hda_cache(&codec->cmd_cache); | 644 | free_hda_cache(&codec->cmd_cache); |
645 | kfree(codec->name); | ||
646 | kfree(codec->modelname); | ||
579 | kfree(codec->wcaps); | 647 | kfree(codec->wcaps); |
580 | kfree(codec); | 648 | kfree(codec); |
581 | } | 649 | } |
@@ -617,6 +685,14 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
617 | mutex_init(&codec->spdif_mutex); | 685 | mutex_init(&codec->spdif_mutex); |
618 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 686 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
619 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 687 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
688 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | ||
689 | if (codec->bus->modelname) { | ||
690 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | ||
691 | if (!codec->modelname) { | ||
692 | snd_hda_codec_free(codec); | ||
693 | return -ENODEV; | ||
694 | } | ||
695 | } | ||
620 | 696 | ||
621 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 697 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
622 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 698 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
@@ -662,12 +738,41 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
662 | snd_hda_codec_read(codec, nid, 0, | 738 | snd_hda_codec_read(codec, nid, 0, |
663 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 739 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
664 | } | 740 | } |
741 | if (bus->modelname) | ||
742 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | ||
743 | |||
744 | err = snd_hda_codec_configure(codec); | ||
745 | if (err < 0) { | ||
746 | snd_hda_codec_free(codec); | ||
747 | return err; | ||
748 | } | ||
749 | snd_hda_codec_proc_new(codec); | ||
750 | |||
751 | snd_hda_create_hwdep(codec); | ||
752 | |||
753 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, | ||
754 | codec->subsystem_id, codec->revision_id); | ||
755 | snd_component_add(codec->bus->card, component); | ||
756 | |||
757 | if (codecp) | ||
758 | *codecp = codec; | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | int snd_hda_codec_configure(struct hda_codec *codec) | ||
763 | { | ||
764 | int err; | ||
665 | 765 | ||
666 | codec->preset = find_codec_preset(codec); | 766 | codec->preset = find_codec_preset(codec); |
767 | if (!codec->name) { | ||
768 | err = get_codec_name(codec); | ||
769 | if (err < 0) | ||
770 | return err; | ||
771 | } | ||
667 | /* audio codec should override the mixer name */ | 772 | /* audio codec should override the mixer name */ |
668 | if (codec->afg || !*bus->card->mixername) | 773 | if (codec->afg || !*codec->bus->card->mixername) |
669 | snd_hda_get_codec_name(codec, bus->card->mixername, | 774 | strlcpy(codec->bus->card->mixername, codec->name, |
670 | sizeof(bus->card->mixername)); | 775 | sizeof(codec->bus->card->mixername)); |
671 | 776 | ||
672 | if (is_generic_config(codec)) { | 777 | if (is_generic_config(codec)) { |
673 | err = snd_hda_parse_generic_codec(codec); | 778 | err = snd_hda_parse_generic_codec(codec); |
@@ -684,25 +789,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
684 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 789 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); |
685 | 790 | ||
686 | patched: | 791 | patched: |
687 | if (err < 0) { | 792 | if (!err && codec->patch_ops.unsol_event) |
688 | snd_hda_codec_free(codec); | 793 | err = init_unsol_queue(codec->bus); |
689 | return err; | 794 | return err; |
690 | } | ||
691 | |||
692 | if (codec->patch_ops.unsol_event) | ||
693 | init_unsol_queue(bus); | ||
694 | |||
695 | snd_hda_codec_proc_new(codec); | ||
696 | #ifdef CONFIG_SND_HDA_HWDEP | ||
697 | snd_hda_create_hwdep(codec); | ||
698 | #endif | ||
699 | |||
700 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id); | ||
701 | snd_component_add(codec->bus->card, component); | ||
702 | |||
703 | if (codecp) | ||
704 | *codecp = codec; | ||
705 | return 0; | ||
706 | } | 795 | } |
707 | 796 | ||
708 | /** | 797 | /** |
@@ -757,12 +846,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache, | |||
757 | { | 846 | { |
758 | memset(cache, 0, sizeof(*cache)); | 847 | memset(cache, 0, sizeof(*cache)); |
759 | memset(cache->hash, 0xff, sizeof(cache->hash)); | 848 | memset(cache->hash, 0xff, sizeof(cache->hash)); |
760 | cache->record_size = record_size; | 849 | snd_array_init(&cache->buf, record_size, 64); |
761 | } | 850 | } |
762 | 851 | ||
763 | static void free_hda_cache(struct hda_cache_rec *cache) | 852 | static void free_hda_cache(struct hda_cache_rec *cache) |
764 | { | 853 | { |
765 | kfree(cache->buffer); | 854 | snd_array_free(&cache->buf); |
766 | } | 855 | } |
767 | 856 | ||
768 | /* query the hash. allocate an entry if not found. */ | 857 | /* query the hash. allocate an entry if not found. */ |
@@ -771,38 +860,18 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
771 | { | 860 | { |
772 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 861 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
773 | u16 cur = cache->hash[idx]; | 862 | u16 cur = cache->hash[idx]; |
863 | struct hda_cache_head *info_head = cache->buf.list; | ||
774 | struct hda_cache_head *info; | 864 | struct hda_cache_head *info; |
775 | 865 | ||
776 | while (cur != 0xffff) { | 866 | while (cur != 0xffff) { |
777 | info = (struct hda_cache_head *)(cache->buffer + | 867 | info = &info_head[cur]; |
778 | cur * cache->record_size); | ||
779 | if (info->key == key) | 868 | if (info->key == key) |
780 | return info; | 869 | return info; |
781 | cur = info->next; | 870 | cur = info->next; |
782 | } | 871 | } |
783 | 872 | ||
784 | /* add a new hash entry */ | 873 | /* add a new hash entry */ |
785 | if (cache->num_entries >= cache->size) { | 874 | info = snd_array_new(&cache->buf); |
786 | /* reallocate the array */ | ||
787 | unsigned int new_size = cache->size + 64; | ||
788 | void *new_buffer; | ||
789 | new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL); | ||
790 | if (!new_buffer) { | ||
791 | snd_printk(KERN_ERR "hda_codec: " | ||
792 | "can't malloc amp_info\n"); | ||
793 | return NULL; | ||
794 | } | ||
795 | if (cache->buffer) { | ||
796 | memcpy(new_buffer, cache->buffer, | ||
797 | cache->size * cache->record_size); | ||
798 | kfree(cache->buffer); | ||
799 | } | ||
800 | cache->size = new_size; | ||
801 | cache->buffer = new_buffer; | ||
802 | } | ||
803 | cur = cache->num_entries++; | ||
804 | info = (struct hda_cache_head *)(cache->buffer + | ||
805 | cur * cache->record_size); | ||
806 | info->key = key; | 875 | info->key = key; |
807 | info->val = 0; | 876 | info->val = 0; |
808 | info->next = cache->hash[idx]; | 877 | info->next = cache->hash[idx]; |
@@ -943,10 +1012,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
943 | /* resume the all amp commands from the cache */ | 1012 | /* resume the all amp commands from the cache */ |
944 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | 1013 | void snd_hda_codec_resume_amp(struct hda_codec *codec) |
945 | { | 1014 | { |
946 | struct hda_amp_info *buffer = codec->amp_cache.buffer; | 1015 | struct hda_amp_info *buffer = codec->amp_cache.buf.list; |
947 | int i; | 1016 | int i; |
948 | 1017 | ||
949 | for (i = 0; i < codec->amp_cache.size; i++, buffer++) { | 1018 | for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) { |
950 | u32 key = buffer->head.key; | 1019 | u32 key = buffer->head.key; |
951 | hda_nid_t nid; | 1020 | hda_nid_t nid; |
952 | unsigned int idx, dir, ch; | 1021 | unsigned int idx, dir, ch; |
@@ -1098,6 +1167,57 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1098 | return _snd_hda_find_mixer_ctl(codec, name, 0); | 1167 | return _snd_hda_find_mixer_ctl(codec, name, 0); |
1099 | } | 1168 | } |
1100 | 1169 | ||
1170 | /* Add a control element and assign to the codec */ | ||
1171 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | ||
1172 | { | ||
1173 | int err; | ||
1174 | struct snd_kcontrol **knewp; | ||
1175 | |||
1176 | err = snd_ctl_add(codec->bus->card, kctl); | ||
1177 | if (err < 0) | ||
1178 | return err; | ||
1179 | knewp = snd_array_new(&codec->mixers); | ||
1180 | if (!knewp) | ||
1181 | return -ENOMEM; | ||
1182 | *knewp = kctl; | ||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1186 | /* Clear all controls assigned to the given codec */ | ||
1187 | void snd_hda_ctls_clear(struct hda_codec *codec) | ||
1188 | { | ||
1189 | int i; | ||
1190 | struct snd_kcontrol **kctls = codec->mixers.list; | ||
1191 | for (i = 0; i < codec->mixers.used; i++) | ||
1192 | snd_ctl_remove(codec->bus->card, kctls[i]); | ||
1193 | snd_array_free(&codec->mixers); | ||
1194 | } | ||
1195 | |||
1196 | void snd_hda_codec_reset(struct hda_codec *codec) | ||
1197 | { | ||
1198 | int i; | ||
1199 | |||
1200 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1201 | cancel_delayed_work(&codec->power_work); | ||
1202 | flush_scheduled_work(); | ||
1203 | #endif | ||
1204 | snd_hda_ctls_clear(codec); | ||
1205 | /* relase PCMs */ | ||
1206 | for (i = 0; i < codec->num_pcms; i++) { | ||
1207 | if (codec->pcm_info[i].pcm) | ||
1208 | snd_device_free(codec->bus->card, | ||
1209 | codec->pcm_info[i].pcm); | ||
1210 | } | ||
1211 | if (codec->patch_ops.free) | ||
1212 | codec->patch_ops.free(codec); | ||
1213 | codec->spec = NULL; | ||
1214 | free_hda_cache(&codec->amp_cache); | ||
1215 | free_hda_cache(&codec->cmd_cache); | ||
1216 | codec->num_pcms = 0; | ||
1217 | codec->pcm_info = NULL; | ||
1218 | codec->preset = NULL; | ||
1219 | } | ||
1220 | |||
1101 | /* create a virtual master control and add slaves */ | 1221 | /* create a virtual master control and add slaves */ |
1102 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1222 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
1103 | unsigned int *tlv, const char **slaves) | 1223 | unsigned int *tlv, const char **slaves) |
@@ -1115,7 +1235,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1115 | kctl = snd_ctl_make_virtual_master(name, tlv); | 1235 | kctl = snd_ctl_make_virtual_master(name, tlv); |
1116 | if (!kctl) | 1236 | if (!kctl) |
1117 | return -ENOMEM; | 1237 | return -ENOMEM; |
1118 | err = snd_ctl_add(codec->bus->card, kctl); | 1238 | err = snd_hda_ctl_add(codec, kctl); |
1119 | if (err < 0) | 1239 | if (err < 0) |
1120 | return err; | 1240 | return err; |
1121 | 1241 | ||
@@ -1579,7 +1699,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1579 | kctl = snd_ctl_new1(dig_mix, codec); | 1699 | kctl = snd_ctl_new1(dig_mix, codec); |
1580 | kctl->id.index = idx; | 1700 | kctl->id.index = idx; |
1581 | kctl->private_value = nid; | 1701 | kctl->private_value = nid; |
1582 | err = snd_ctl_add(codec->bus->card, kctl); | 1702 | err = snd_hda_ctl_add(codec, kctl); |
1583 | if (err < 0) | 1703 | if (err < 0) |
1584 | return err; | 1704 | return err; |
1585 | } | 1705 | } |
@@ -1623,7 +1743,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec, | |||
1623 | if (!mout->dig_out_nid) | 1743 | if (!mout->dig_out_nid) |
1624 | return 0; | 1744 | return 0; |
1625 | /* ATTENTION: here mout is passed as private_data, instead of codec */ | 1745 | /* ATTENTION: here mout is passed as private_data, instead of codec */ |
1626 | return snd_ctl_add(codec->bus->card, | 1746 | return snd_hda_ctl_add(codec, |
1627 | snd_ctl_new1(&spdif_share_sw, mout)); | 1747 | snd_ctl_new1(&spdif_share_sw, mout)); |
1628 | } | 1748 | } |
1629 | 1749 | ||
@@ -1725,7 +1845,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1725 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1845 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1726 | kctl = snd_ctl_new1(dig_mix, codec); | 1846 | kctl = snd_ctl_new1(dig_mix, codec); |
1727 | kctl->private_value = nid; | 1847 | kctl->private_value = nid; |
1728 | err = snd_ctl_add(codec->bus->card, kctl); | 1848 | err = snd_hda_ctl_add(codec, kctl); |
1729 | if (err < 0) | 1849 | if (err < 0) |
1730 | return err; | 1850 | return err; |
1731 | } | 1851 | } |
@@ -1780,10 +1900,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1780 | /* resume the all commands from the cache */ | 1900 | /* resume the all commands from the cache */ |
1781 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | 1901 | void snd_hda_codec_resume_cache(struct hda_codec *codec) |
1782 | { | 1902 | { |
1783 | struct hda_cache_head *buffer = codec->cmd_cache.buffer; | 1903 | struct hda_cache_head *buffer = codec->cmd_cache.buf.list; |
1784 | int i; | 1904 | int i; |
1785 | 1905 | ||
1786 | for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { | 1906 | for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) { |
1787 | u32 key = buffer->key; | 1907 | u32 key = buffer->key; |
1788 | if (!key) | 1908 | if (!key) |
1789 | continue; | 1909 | continue; |
@@ -1868,6 +1988,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
1868 | } | 1988 | } |
1869 | } | 1989 | } |
1870 | 1990 | ||
1991 | #ifdef CONFIG_SND_HDA_HWDEP | ||
1992 | /* execute additional init verbs */ | ||
1993 | static void hda_exec_init_verbs(struct hda_codec *codec) | ||
1994 | { | ||
1995 | if (codec->init_verbs.list) | ||
1996 | snd_hda_sequence_write(codec, codec->init_verbs.list); | ||
1997 | } | ||
1998 | #else | ||
1999 | static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | ||
2000 | #endif | ||
2001 | |||
1871 | #ifdef SND_HDA_NEEDS_RESUME | 2002 | #ifdef SND_HDA_NEEDS_RESUME |
1872 | /* | 2003 | /* |
1873 | * call suspend and power-down; used both from PM and power-save | 2004 | * call suspend and power-down; used both from PM and power-save |
@@ -1894,6 +2025,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
1894 | hda_set_power_state(codec, | 2025 | hda_set_power_state(codec, |
1895 | codec->afg ? codec->afg : codec->mfg, | 2026 | codec->afg ? codec->afg : codec->mfg, |
1896 | AC_PWRST_D0); | 2027 | AC_PWRST_D0); |
2028 | hda_exec_init_verbs(codec); | ||
1897 | if (codec->patch_ops.resume) | 2029 | if (codec->patch_ops.resume) |
1898 | codec->patch_ops.resume(codec); | 2030 | codec->patch_ops.resume(codec); |
1899 | else { | 2031 | else { |
@@ -1919,23 +2051,31 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1919 | struct hda_codec *codec; | 2051 | struct hda_codec *codec; |
1920 | 2052 | ||
1921 | list_for_each_entry(codec, &bus->codec_list, list) { | 2053 | list_for_each_entry(codec, &bus->codec_list, list) { |
1922 | int err = 0; | 2054 | int err = snd_hda_codec_build_controls(codec); |
1923 | /* fake as if already powered-on */ | ||
1924 | hda_keep_power_on(codec); | ||
1925 | /* then fire up */ | ||
1926 | hda_set_power_state(codec, | ||
1927 | codec->afg ? codec->afg : codec->mfg, | ||
1928 | AC_PWRST_D0); | ||
1929 | /* continue to initialize... */ | ||
1930 | if (codec->patch_ops.init) | ||
1931 | err = codec->patch_ops.init(codec); | ||
1932 | if (!err && codec->patch_ops.build_controls) | ||
1933 | err = codec->patch_ops.build_controls(codec); | ||
1934 | snd_hda_power_down(codec); | ||
1935 | if (err < 0) | 2055 | if (err < 0) |
1936 | return err; | 2056 | return err; |
1937 | } | 2057 | } |
2058 | return 0; | ||
2059 | } | ||
1938 | 2060 | ||
2061 | int snd_hda_codec_build_controls(struct hda_codec *codec) | ||
2062 | { | ||
2063 | int err = 0; | ||
2064 | /* fake as if already powered-on */ | ||
2065 | hda_keep_power_on(codec); | ||
2066 | /* then fire up */ | ||
2067 | hda_set_power_state(codec, | ||
2068 | codec->afg ? codec->afg : codec->mfg, | ||
2069 | AC_PWRST_D0); | ||
2070 | hda_exec_init_verbs(codec); | ||
2071 | /* continue to initialize... */ | ||
2072 | if (codec->patch_ops.init) | ||
2073 | err = codec->patch_ops.init(codec); | ||
2074 | if (!err && codec->patch_ops.build_controls) | ||
2075 | err = codec->patch_ops.build_controls(codec); | ||
2076 | snd_hda_power_down(codec); | ||
2077 | if (err < 0) | ||
2078 | return err; | ||
1939 | return 0; | 2079 | return 0; |
1940 | } | 2080 | } |
1941 | 2081 | ||
@@ -2236,8 +2376,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2236 | return 0; | 2376 | return 0; |
2237 | } | 2377 | } |
2238 | 2378 | ||
2239 | static int __devinit set_pcm_default_values(struct hda_codec *codec, | 2379 | static int set_pcm_default_values(struct hda_codec *codec, |
2240 | struct hda_pcm_stream *info) | 2380 | struct hda_pcm_stream *info) |
2241 | { | 2381 | { |
2242 | /* query support PCM information from the given NID */ | 2382 | /* query support PCM information from the given NID */ |
2243 | if (info->nid && (!info->rates || !info->formats)) { | 2383 | if (info->nid && (!info->rates || !info->formats)) { |
@@ -2263,6 +2403,28 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2263 | return 0; | 2403 | return 0; |
2264 | } | 2404 | } |
2265 | 2405 | ||
2406 | /* | ||
2407 | * attach a new PCM stream | ||
2408 | */ | ||
2409 | static int __devinit | ||
2410 | snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | ||
2411 | { | ||
2412 | struct hda_pcm_stream *info; | ||
2413 | int stream, err; | ||
2414 | |||
2415 | if (!pcm->name) | ||
2416 | return -EINVAL; | ||
2417 | for (stream = 0; stream < 2; stream++) { | ||
2418 | info = &pcm->stream[stream]; | ||
2419 | if (info->substreams) { | ||
2420 | err = set_pcm_default_values(codec, info); | ||
2421 | if (err < 0) | ||
2422 | return err; | ||
2423 | } | ||
2424 | } | ||
2425 | return codec->bus->ops.attach_pcm(codec, pcm); | ||
2426 | } | ||
2427 | |||
2266 | /** | 2428 | /** |
2267 | * snd_hda_build_pcms - build PCM information | 2429 | * snd_hda_build_pcms - build PCM information |
2268 | * @bus: the BUS | 2430 | * @bus: the BUS |
@@ -2289,25 +2451,67 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2289 | * | 2451 | * |
2290 | * This function returns 0 if successfull, or a negative error code. | 2452 | * This function returns 0 if successfull, or a negative error code. |
2291 | */ | 2453 | */ |
2292 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) | 2454 | int snd_hda_build_pcms(struct hda_bus *bus) |
2293 | { | 2455 | { |
2456 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2457 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2458 | }; | ||
2459 | /* starting device index for each PCM type */ | ||
2460 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2461 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2462 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2463 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2464 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2465 | }; | ||
2466 | /* normal audio device indices; not linear to keep compatibility */ | ||
2467 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2294 | struct hda_codec *codec; | 2468 | struct hda_codec *codec; |
2469 | int num_devs[HDA_PCM_NTYPES]; | ||
2295 | 2470 | ||
2471 | memset(num_devs, 0, sizeof(num_devs)); | ||
2296 | list_for_each_entry(codec, &bus->codec_list, list) { | 2472 | list_for_each_entry(codec, &bus->codec_list, list) { |
2297 | unsigned int pcm, s; | 2473 | unsigned int pcm; |
2298 | int err; | 2474 | int err; |
2299 | if (!codec->patch_ops.build_pcms) | 2475 | if (!codec->num_pcms) { |
2300 | continue; | 2476 | if (!codec->patch_ops.build_pcms) |
2301 | err = codec->patch_ops.build_pcms(codec); | 2477 | continue; |
2302 | if (err < 0) | 2478 | err = codec->patch_ops.build_pcms(codec); |
2303 | return err; | 2479 | if (err < 0) |
2480 | return err; | ||
2481 | } | ||
2304 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2482 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2305 | for (s = 0; s < 2; s++) { | 2483 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2306 | struct hda_pcm_stream *info; | 2484 | int type = cpcm->pcm_type; |
2307 | info = &codec->pcm_info[pcm].stream[s]; | 2485 | int dev; |
2308 | if (!info->substreams) | 2486 | switch (type) { |
2487 | case HDA_PCM_TYPE_AUDIO: | ||
2488 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
2489 | snd_printk(KERN_WARNING | ||
2490 | "Too many audio devices\n"); | ||
2309 | continue; | 2491 | continue; |
2310 | err = set_pcm_default_values(codec, info); | 2492 | } |
2493 | dev = audio_idx[num_devs[type]]; | ||
2494 | break; | ||
2495 | case HDA_PCM_TYPE_SPDIF: | ||
2496 | case HDA_PCM_TYPE_HDMI: | ||
2497 | case HDA_PCM_TYPE_MODEM: | ||
2498 | if (num_devs[type]) { | ||
2499 | snd_printk(KERN_WARNING | ||
2500 | "%s already defined\n", | ||
2501 | dev_name[type]); | ||
2502 | continue; | ||
2503 | } | ||
2504 | dev = dev_idx[type]; | ||
2505 | break; | ||
2506 | default: | ||
2507 | snd_printk(KERN_WARNING | ||
2508 | "Invalid PCM type %d\n", type); | ||
2509 | continue; | ||
2510 | } | ||
2511 | num_devs[type]++; | ||
2512 | if (!cpcm->pcm) { | ||
2513 | cpcm->device = dev; | ||
2514 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2311 | if (err < 0) | 2515 | if (err < 0) |
2312 | return err; | 2516 | return err; |
2313 | } | 2517 | } |
@@ -2333,11 +2537,11 @@ int snd_hda_check_board_config(struct hda_codec *codec, | |||
2333 | int num_configs, const char **models, | 2537 | int num_configs, const char **models, |
2334 | const struct snd_pci_quirk *tbl) | 2538 | const struct snd_pci_quirk *tbl) |
2335 | { | 2539 | { |
2336 | if (codec->bus->modelname && models) { | 2540 | if (codec->modelname && models) { |
2337 | int i; | 2541 | int i; |
2338 | for (i = 0; i < num_configs; i++) { | 2542 | for (i = 0; i < num_configs; i++) { |
2339 | if (models[i] && | 2543 | if (models[i] && |
2340 | !strcmp(codec->bus->modelname, models[i])) { | 2544 | !strcmp(codec->modelname, models[i])) { |
2341 | snd_printd(KERN_INFO "hda_codec: model '%s' is " | 2545 | snd_printd(KERN_INFO "hda_codec: model '%s' is " |
2342 | "selected\n", models[i]); | 2546 | "selected\n", models[i]); |
2343 | return i; | 2547 | return i; |
@@ -2390,7 +2594,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2390 | kctl = snd_ctl_new1(knew, codec); | 2594 | kctl = snd_ctl_new1(knew, codec); |
2391 | if (!kctl) | 2595 | if (!kctl) |
2392 | return -ENOMEM; | 2596 | return -ENOMEM; |
2393 | err = snd_ctl_add(codec->bus->card, kctl); | 2597 | err = snd_hda_ctl_add(codec, kctl); |
2394 | if (err < 0) { | 2598 | if (err < 0) { |
2395 | if (!codec->addr) | 2599 | if (!codec->addr) |
2396 | return err; | 2600 | return err; |
@@ -2398,7 +2602,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2398 | if (!kctl) | 2602 | if (!kctl) |
2399 | return -ENOMEM; | 2603 | return -ENOMEM; |
2400 | kctl->id.device = codec->addr; | 2604 | kctl->id.device = codec->addr; |
2401 | err = snd_ctl_add(codec->bus->card, kctl); | 2605 | err = snd_hda_ctl_add(codec, kctl); |
2402 | if (err < 0) | 2606 | if (err < 0) |
2403 | return err; | 2607 | return err; |
2404 | } | 2608 | } |
@@ -3139,3 +3343,37 @@ int snd_hda_codecs_inuse(struct hda_bus *bus) | |||
3139 | } | 3343 | } |
3140 | #endif | 3344 | #endif |
3141 | #endif | 3345 | #endif |
3346 | |||
3347 | /* | ||
3348 | * generic arrays | ||
3349 | */ | ||
3350 | |||
3351 | /* get a new element from the given array | ||
3352 | * if it exceeds the pre-allocated array size, re-allocate the array | ||
3353 | */ | ||
3354 | void *snd_array_new(struct snd_array *array) | ||
3355 | { | ||
3356 | if (array->used >= array->alloced) { | ||
3357 | int num = array->alloced + array->alloc_align; | ||
3358 | void *nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL); | ||
3359 | if (!nlist) | ||
3360 | return NULL; | ||
3361 | if (array->list) { | ||
3362 | memcpy(nlist, array->list, | ||
3363 | array->elem_size * array->alloced); | ||
3364 | kfree(array->list); | ||
3365 | } | ||
3366 | array->list = nlist; | ||
3367 | array->alloced = num; | ||
3368 | } | ||
3369 | return array->list + (array->used++ * array->elem_size); | ||
3370 | } | ||
3371 | |||
3372 | /* free the given array elements */ | ||
3373 | void snd_array_free(struct snd_array *array) | ||
3374 | { | ||
3375 | kfree(array->list); | ||
3376 | array->used = 0; | ||
3377 | array->alloced = 0; | ||
3378 | array->list = NULL; | ||
3379 | } | ||
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..a13169cc95a2 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 |
@@ -1190,21 +1191,12 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | |||
1190 | [AZX_DRIVER_TERA] = 1, | 1191 | [AZX_DRIVER_TERA] = 1, |
1191 | }; | 1192 | }; |
1192 | 1193 | ||
1193 | /* number of slots to probe as default | ||
1194 | * this can be different from azx_max_codecs[] -- e.g. some boards | ||
1195 | * report wrongly the non-existing 4th slot availability | ||
1196 | */ | ||
1197 | static unsigned int azx_default_codecs[AZX_NUM_DRIVERS] __devinitdata = { | ||
1198 | [AZX_DRIVER_ICH] = 3, | ||
1199 | [AZX_DRIVER_ATI] = 3, | ||
1200 | }; | ||
1201 | |||
1202 | static int __devinit azx_codec_create(struct azx *chip, const char *model, | 1194 | static int __devinit azx_codec_create(struct azx *chip, const char *model, |
1203 | unsigned int codec_probe_mask) | 1195 | unsigned int codec_probe_mask) |
1204 | { | 1196 | { |
1205 | struct hda_bus_template bus_temp; | 1197 | struct hda_bus_template bus_temp; |
1206 | int c, codecs, audio_codecs, err; | 1198 | int c, codecs, err; |
1207 | int def_slots, max_slots; | 1199 | int max_slots; |
1208 | 1200 | ||
1209 | memset(&bus_temp, 0, sizeof(bus_temp)); | 1201 | memset(&bus_temp, 0, sizeof(bus_temp)); |
1210 | bus_temp.private_data = chip; | 1202 | bus_temp.private_data = chip; |
@@ -1212,6 +1204,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1212 | bus_temp.pci = chip->pci; | 1204 | bus_temp.pci = chip->pci; |
1213 | bus_temp.ops.command = azx_send_cmd; | 1205 | bus_temp.ops.command = azx_send_cmd; |
1214 | bus_temp.ops.get_response = azx_get_response; | 1206 | bus_temp.ops.get_response = azx_get_response; |
1207 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; | ||
1215 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1208 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1216 | bus_temp.ops.pm_notify = azx_power_notify; | 1209 | bus_temp.ops.pm_notify = azx_power_notify; |
1217 | #endif | 1210 | #endif |
@@ -1223,33 +1216,17 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1223 | if (chip->driver_type == AZX_DRIVER_NVIDIA) | 1216 | if (chip->driver_type == AZX_DRIVER_NVIDIA) |
1224 | chip->bus->needs_damn_long_delay = 1; | 1217 | chip->bus->needs_damn_long_delay = 1; |
1225 | 1218 | ||
1226 | codecs = audio_codecs = 0; | 1219 | codecs = 0; |
1227 | max_slots = azx_max_codecs[chip->driver_type]; | 1220 | max_slots = azx_max_codecs[chip->driver_type]; |
1228 | if (!max_slots) | 1221 | if (!max_slots) |
1229 | max_slots = AZX_MAX_CODECS; | 1222 | max_slots = AZX_MAX_CODECS; |
1230 | def_slots = azx_default_codecs[chip->driver_type]; | 1223 | for (c = 0; c < max_slots; c++) { |
1231 | if (!def_slots) | ||
1232 | def_slots = max_slots; | ||
1233 | for (c = 0; c < def_slots; c++) { | ||
1234 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1224 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { |
1235 | struct hda_codec *codec; | 1225 | struct hda_codec *codec; |
1236 | err = snd_hda_codec_new(chip->bus, c, &codec); | 1226 | err = snd_hda_codec_new(chip->bus, c, &codec); |
1237 | if (err < 0) | 1227 | if (err < 0) |
1238 | continue; | 1228 | continue; |
1239 | codecs++; | 1229 | codecs++; |
1240 | if (codec->afg) | ||
1241 | audio_codecs++; | ||
1242 | } | ||
1243 | } | ||
1244 | if (!audio_codecs) { | ||
1245 | /* probe additional slots if no codec is found */ | ||
1246 | for (; c < max_slots; c++) { | ||
1247 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | ||
1248 | err = snd_hda_codec_new(chip->bus, c, NULL); | ||
1249 | if (err < 0) | ||
1250 | continue; | ||
1251 | codecs++; | ||
1252 | } | ||
1253 | } | 1230 | } |
1254 | } | 1231 | } |
1255 | if (!codecs) { | 1232 | if (!codecs) { |
@@ -1718,111 +1695,58 @@ static struct snd_pcm_ops azx_pcm_ops = { | |||
1718 | 1695 | ||
1719 | static void azx_pcm_free(struct snd_pcm *pcm) | 1696 | static void azx_pcm_free(struct snd_pcm *pcm) |
1720 | { | 1697 | { |
1721 | kfree(pcm->private_data); | 1698 | struct azx_pcm *apcm = pcm->private_data; |
1699 | if (apcm) { | ||
1700 | apcm->chip->pcm[pcm->device] = NULL; | ||
1701 | kfree(apcm); | ||
1702 | } | ||
1722 | } | 1703 | } |
1723 | 1704 | ||
1724 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | 1705 | static int |
1725 | struct hda_pcm *cpcm) | 1706 | azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm) |
1726 | { | 1707 | { |
1727 | int err; | 1708 | struct azx *chip = codec->bus->private_data; |
1728 | struct snd_pcm *pcm; | 1709 | struct snd_pcm *pcm; |
1729 | struct azx_pcm *apcm; | 1710 | struct azx_pcm *apcm; |
1711 | int pcm_dev = cpcm->device; | ||
1712 | int s, err; | ||
1730 | 1713 | ||
1731 | /* if no substreams are defined for both playback and capture, | 1714 | if (pcm_dev >= AZX_MAX_PCMS) { |
1732 | * it's just a placeholder. ignore it. | 1715 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1733 | */ | 1716 | 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; | 1717 | return -EINVAL; |
1739 | 1718 | } | |
1740 | err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, | 1719 | if (chip->pcm[pcm_dev]) { |
1741 | cpcm->stream[0].substreams, | 1720 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); |
1742 | cpcm->stream[1].substreams, | 1721 | return -EBUSY; |
1722 | } | ||
1723 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | ||
1724 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, | ||
1725 | cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, | ||
1743 | &pcm); | 1726 | &pcm); |
1744 | if (err < 0) | 1727 | if (err < 0) |
1745 | return err; | 1728 | return err; |
1746 | strcpy(pcm->name, cpcm->name); | 1729 | strcpy(pcm->name, cpcm->name); |
1747 | apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); | 1730 | apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); |
1748 | if (apcm == NULL) | 1731 | if (apcm == NULL) |
1749 | return -ENOMEM; | 1732 | return -ENOMEM; |
1750 | apcm->chip = chip; | 1733 | apcm->chip = chip; |
1751 | apcm->codec = codec; | 1734 | apcm->codec = codec; |
1752 | apcm->hinfo[0] = &cpcm->stream[0]; | ||
1753 | apcm->hinfo[1] = &cpcm->stream[1]; | ||
1754 | pcm->private_data = apcm; | 1735 | pcm->private_data = apcm; |
1755 | pcm->private_free = azx_pcm_free; | 1736 | pcm->private_free = azx_pcm_free; |
1756 | if (cpcm->stream[0].substreams) | 1737 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
1757 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); | 1738 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; |
1758 | if (cpcm->stream[1].substreams) | 1739 | chip->pcm[pcm_dev] = pcm; |
1759 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); | 1740 | cpcm->pcm = pcm; |
1741 | for (s = 0; s < 2; s++) { | ||
1742 | apcm->hinfo[s] = &cpcm->stream[s]; | ||
1743 | if (cpcm->stream[s].substreams) | ||
1744 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); | ||
1745 | } | ||
1746 | /* buffer pre-allocation */ | ||
1760 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1747 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1761 | snd_dma_pci_data(chip->pci), | 1748 | snd_dma_pci_data(chip->pci), |
1762 | 1024 * 64, 32 * 1024 * 1024); | 1749 | 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; | 1750 | return 0; |
1827 | } | 1751 | } |
1828 | 1752 | ||
@@ -2324,7 +2248,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2324 | } | 2248 | } |
2325 | 2249 | ||
2326 | /* create PCM streams */ | 2250 | /* create PCM streams */ |
2327 | err = azx_pcm_create(chip); | 2251 | err = snd_hda_build_pcms(chip->bus); |
2328 | if (err < 0) { | 2252 | if (err < 0) { |
2329 | snd_card_free(card); | 2253 | snd_card_free(card); |
2330 | return err; | 2254 | return err; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7957fefda730..aac569b05599 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 |
@@ -364,17 +366,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
364 | /* amp values */ | 366 | /* amp values */ |
365 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | 367 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) |
366 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | 368 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) |
367 | #define AMP_OUT_MUTE 0xb080 | 369 | #define AMP_OUT_MUTE 0xb080 |
368 | #define AMP_OUT_UNMUTE 0xb000 | 370 | #define AMP_OUT_UNMUTE 0xb000 |
369 | #define AMP_OUT_ZERO 0xb000 | 371 | #define AMP_OUT_ZERO 0xb000 |
370 | /* pinctl values */ | 372 | /* pinctl values */ |
371 | #define PIN_IN (AC_PINCTL_IN_EN) | 373 | #define PIN_IN (AC_PINCTL_IN_EN) |
372 | #define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) | 374 | #define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) |
373 | #define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) | 375 | #define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) |
374 | #define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) | 376 | #define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) |
375 | #define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) | 377 | #define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) |
376 | #define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) | 378 | #define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) |
377 | #define PIN_OUT (AC_PINCTL_OUT_EN) | 379 | #define PIN_OUT (AC_PINCTL_OUT_EN) |
378 | #define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) | 380 | #define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) |
379 | #define PIN_HP_AMP (AC_PINCTL_HP_EN) | 381 | #define PIN_HP_AMP (AC_PINCTL_HP_EN) |
380 | 382 | ||
@@ -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 d3fd432cb3ea..d0d66f341cda 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 4eceab9bd109..b60187688bd0 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 | ||
@@ -1632,6 +1631,9 @@ static const char *alc_slave_sws[] = { | |||
1632 | /* | 1631 | /* |
1633 | * build control elements | 1632 | * build control elements |
1634 | */ | 1633 | */ |
1634 | |||
1635 | static void alc_free_kctls(struct hda_codec *codec); | ||
1636 | |||
1635 | static int alc_build_controls(struct hda_codec *codec) | 1637 | static int alc_build_controls(struct hda_codec *codec) |
1636 | { | 1638 | { |
1637 | struct alc_spec *spec = codec->spec; | 1639 | struct alc_spec *spec = codec->spec; |
@@ -1678,6 +1680,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1678 | return err; | 1680 | return err; |
1679 | } | 1681 | } |
1680 | 1682 | ||
1683 | alc_free_kctls(codec); /* no longer needed */ | ||
1681 | return 0; | 1684 | return 0; |
1682 | } | 1685 | } |
1683 | 1686 | ||
@@ -2768,19 +2771,27 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2768 | return 0; | 2771 | return 0; |
2769 | } | 2772 | } |
2770 | 2773 | ||
2774 | static void alc_free_kctls(struct hda_codec *codec) | ||
2775 | { | ||
2776 | struct alc_spec *spec = codec->spec; | ||
2777 | |||
2778 | if (spec->kctls.list) { | ||
2779 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
2780 | int i; | ||
2781 | for (i = 0; i < spec->kctls.used; i++) | ||
2782 | kfree(kctl[i].name); | ||
2783 | } | ||
2784 | snd_array_free(&spec->kctls); | ||
2785 | } | ||
2786 | |||
2771 | static void alc_free(struct hda_codec *codec) | 2787 | static void alc_free(struct hda_codec *codec) |
2772 | { | 2788 | { |
2773 | struct alc_spec *spec = codec->spec; | 2789 | struct alc_spec *spec = codec->spec; |
2774 | unsigned int i; | ||
2775 | 2790 | ||
2776 | if (!spec) | 2791 | if (!spec) |
2777 | return; | 2792 | return; |
2778 | 2793 | ||
2779 | if (spec->kctl_alloc) { | 2794 | alc_free_kctls(codec); |
2780 | for (i = 0; i < spec->num_kctl_used; i++) | ||
2781 | kfree(spec->kctl_alloc[i].name); | ||
2782 | kfree(spec->kctl_alloc); | ||
2783 | } | ||
2784 | kfree(spec); | 2795 | kfree(spec); |
2785 | codec->spec = NULL; /* to be sure */ | 2796 | codec->spec = NULL; /* to be sure */ |
2786 | } | 2797 | } |
@@ -3526,9 +3537,6 @@ static struct alc_config_preset alc880_presets[] = { | |||
3526 | * Automatic parse of I/O pins from the BIOS configuration | 3537 | * Automatic parse of I/O pins from the BIOS configuration |
3527 | */ | 3538 | */ |
3528 | 3539 | ||
3529 | #define NUM_CONTROL_ALLOC 32 | ||
3530 | #define NUM_VERB_ALLOC 32 | ||
3531 | |||
3532 | enum { | 3540 | enum { |
3533 | ALC_CTL_WIDGET_VOL, | 3541 | ALC_CTL_WIDGET_VOL, |
3534 | ALC_CTL_WIDGET_MUTE, | 3542 | ALC_CTL_WIDGET_MUTE, |
@@ -3546,29 +3554,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
3546 | { | 3554 | { |
3547 | struct snd_kcontrol_new *knew; | 3555 | struct snd_kcontrol_new *knew; |
3548 | 3556 | ||
3549 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 3557 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
3550 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 3558 | knew = snd_array_new(&spec->kctls); |
3551 | 3559 | if (!knew) | |
3552 | /* array + terminator */ | 3560 | return -ENOMEM; |
3553 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); | ||
3554 | if (!knew) | ||
3555 | return -ENOMEM; | ||
3556 | if (spec->kctl_alloc) { | ||
3557 | memcpy(knew, spec->kctl_alloc, | ||
3558 | sizeof(*knew) * spec->num_kctl_alloc); | ||
3559 | kfree(spec->kctl_alloc); | ||
3560 | } | ||
3561 | spec->kctl_alloc = knew; | ||
3562 | spec->num_kctl_alloc = num; | ||
3563 | } | ||
3564 | |||
3565 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
3566 | *knew = alc880_control_templates[type]; | 3561 | *knew = alc880_control_templates[type]; |
3567 | knew->name = kstrdup(name, GFP_KERNEL); | 3562 | knew->name = kstrdup(name, GFP_KERNEL); |
3568 | if (!knew->name) | 3563 | if (!knew->name) |
3569 | return -ENOMEM; | 3564 | return -ENOMEM; |
3570 | knew->private_value = val; | 3565 | knew->private_value = val; |
3571 | spec->num_kctl_used++; | ||
3572 | return 0; | 3566 | return 0; |
3573 | } | 3567 | } |
3574 | 3568 | ||
@@ -3892,8 +3886,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
3892 | if (spec->autocfg.dig_in_pin) | 3886 | if (spec->autocfg.dig_in_pin) |
3893 | spec->dig_in_nid = ALC880_DIGIN_NID; | 3887 | spec->dig_in_nid = ALC880_DIGIN_NID; |
3894 | 3888 | ||
3895 | if (spec->kctl_alloc) | 3889 | if (spec->kctls.list) |
3896 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3890 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3897 | 3891 | ||
3898 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 3892 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; |
3899 | 3893 | ||
@@ -5287,7 +5281,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5287 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); | 5281 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); |
5288 | if (err < 0) | 5282 | if (err < 0) |
5289 | return err; | 5283 | return err; |
5290 | if (!spec->kctl_alloc) | 5284 | if (!spec->kctls.list) |
5291 | return 0; /* can't find valid BIOS pin config */ | 5285 | return 0; /* can't find valid BIOS pin config */ |
5292 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5286 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); |
5293 | if (err < 0) | 5287 | if (err < 0) |
@@ -5297,8 +5291,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5297 | 5291 | ||
5298 | if (spec->autocfg.dig_out_pin) | 5292 | if (spec->autocfg.dig_out_pin) |
5299 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5293 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5300 | if (spec->kctl_alloc) | 5294 | if (spec->kctls.list) |
5301 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 5295 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
5302 | 5296 | ||
5303 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 5297 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; |
5304 | 5298 | ||
@@ -10372,8 +10366,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10372 | if (spec->autocfg.dig_in_pin) | 10366 | if (spec->autocfg.dig_in_pin) |
10373 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10367 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10374 | 10368 | ||
10375 | if (spec->kctl_alloc) | 10369 | if (spec->kctls.list) |
10376 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 10370 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
10377 | 10371 | ||
10378 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 10372 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; |
10379 | spec->num_mux_defs = 1; | 10373 | spec->num_mux_defs = 1; |
@@ -11504,8 +11498,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11504 | if (spec->autocfg.dig_out_pin) | 11498 | if (spec->autocfg.dig_out_pin) |
11505 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11499 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11506 | 11500 | ||
11507 | if (spec->kctl_alloc) | 11501 | if (spec->kctls.list) |
11508 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 11502 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
11509 | 11503 | ||
11510 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11504 | if (spec->autocfg.speaker_pins[0] != 0x1d) |
11511 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; | 11505 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; |
@@ -12277,8 +12271,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12277 | if (spec->autocfg.dig_out_pin) | 12271 | if (spec->autocfg.dig_out_pin) |
12278 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12272 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12279 | 12273 | ||
12280 | if (spec->kctl_alloc) | 12274 | if (spec->kctls.list) |
12281 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 12275 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
12282 | 12276 | ||
12283 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | 12277 | /* create a beep mixer control if the pin 0x1d isn't assigned */ |
12284 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | 12278 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) |
@@ -13376,8 +13370,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13376 | if (spec->autocfg.dig_out_pin) | 13370 | if (spec->autocfg.dig_out_pin) |
13377 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13371 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13378 | 13372 | ||
13379 | if (spec->kctl_alloc) | 13373 | if (spec->kctls.list) |
13380 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 13374 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
13381 | 13375 | ||
13382 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 13376 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; |
13383 | 13377 | ||
@@ -14488,8 +14482,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14488 | if (spec->autocfg.dig_out_pin) | 14482 | if (spec->autocfg.dig_out_pin) |
14489 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 14483 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14490 | 14484 | ||
14491 | if (spec->kctl_alloc) | 14485 | if (spec->kctls.list) |
14492 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 14486 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
14493 | 14487 | ||
14494 | spec->init_verbs[spec->num_init_verbs++] | 14488 | spec->init_verbs[spec->num_init_verbs++] |
14495 | = alc861vd_volume_init_verbs; | 14489 | = alc861vd_volume_init_verbs; |
@@ -16316,8 +16310,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16316 | if (spec->autocfg.dig_out_pin) | 16310 | if (spec->autocfg.dig_out_pin) |
16317 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16311 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16318 | 16312 | ||
16319 | if (spec->kctl_alloc) | 16313 | if (spec->kctls.list) |
16320 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 16314 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
16321 | 16315 | ||
16322 | spec->num_mux_defs = 1; | 16316 | spec->num_mux_defs = 1; |
16323 | spec->input_mux = &spec->private_imux; | 16317 | spec->input_mux = &spec->private_imux; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index df9b0bc7f878..f8f85d6717a9 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; |
@@ -1231,6 +1248,8 @@ static const char *slave_sws[] = { | |||
1231 | NULL | 1248 | NULL |
1232 | }; | 1249 | }; |
1233 | 1250 | ||
1251 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1252 | |||
1234 | static int stac92xx_build_controls(struct hda_codec *codec) | 1253 | static int stac92xx_build_controls(struct hda_codec *codec) |
1235 | { | 1254 | { |
1236 | struct sigmatel_spec *spec = codec->spec; | 1255 | struct sigmatel_spec *spec = codec->spec; |
@@ -1248,7 +1267,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1248 | } | 1267 | } |
1249 | if (spec->num_dmuxes > 0) { | 1268 | if (spec->num_dmuxes > 0) { |
1250 | stac_dmux_mixer.count = spec->num_dmuxes; | 1269 | stac_dmux_mixer.count = spec->num_dmuxes; |
1251 | err = snd_ctl_add(codec->bus->card, | 1270 | err = snd_hda_ctl_add(codec, |
1252 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1271 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1253 | if (err < 0) | 1272 | if (err < 0) |
1254 | return err; | 1273 | return err; |
@@ -1303,6 +1322,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1303 | return err; | 1322 | return err; |
1304 | } | 1323 | } |
1305 | 1324 | ||
1325 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1306 | return 0; | 1326 | return 0; |
1307 | } | 1327 | } |
1308 | 1328 | ||
@@ -2451,13 +2471,15 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2451 | { | 2471 | { |
2452 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2472 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2453 | struct sigmatel_spec *spec = codec->spec; | 2473 | struct sigmatel_spec *spec = codec->spec; |
2474 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
2475 | int nid = cfg->hp_pins[cfg->hp_outs - 1]; | ||
2454 | 2476 | ||
2455 | spec->hp_switch = ucontrol->value.integer.value[0]; | 2477 | spec->hp_switch = ucontrol->value.integer.value[0]; |
2456 | 2478 | ||
2457 | /* check to be sure that the ports are upto date with | 2479 | /* check to be sure that the ports are upto date with |
2458 | * switch changes | 2480 | * switch changes |
2459 | */ | 2481 | */ |
2460 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2482 | codec->patch_ops.unsol_event(codec, (STAC_HP_EVENT | nid) << 26); |
2461 | 2483 | ||
2462 | return 1; | 2484 | return 1; |
2463 | } | 2485 | } |
@@ -2497,7 +2519,8 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
2497 | * appropriately according to the pin direction | 2519 | * appropriately according to the pin direction |
2498 | */ | 2520 | */ |
2499 | if (spec->hp_detect) | 2521 | if (spec->hp_detect) |
2500 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2522 | codec->patch_ops.unsol_event(codec, |
2523 | (STAC_HP_EVENT | nid) << 26); | ||
2501 | 2524 | ||
2502 | return 1; | 2525 | return 1; |
2503 | } | 2526 | } |
@@ -2590,28 +2613,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, | |||
2590 | { | 2613 | { |
2591 | struct snd_kcontrol_new *knew; | 2614 | struct snd_kcontrol_new *knew; |
2592 | 2615 | ||
2593 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2616 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2594 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2617 | knew = snd_array_new(&spec->kctls); |
2595 | 2618 | if (!knew) | |
2596 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2619 | return -ENOMEM; |
2597 | if (! knew) | ||
2598 | return -ENOMEM; | ||
2599 | if (spec->kctl_alloc) { | ||
2600 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2601 | kfree(spec->kctl_alloc); | ||
2602 | } | ||
2603 | spec->kctl_alloc = knew; | ||
2604 | spec->num_kctl_alloc = num; | ||
2605 | } | ||
2606 | |||
2607 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2608 | *knew = stac92xx_control_templates[type]; | 2620 | *knew = stac92xx_control_templates[type]; |
2609 | knew->index = idx; | 2621 | knew->index = idx; |
2610 | knew->name = kstrdup(name, GFP_KERNEL); | 2622 | knew->name = kstrdup(name, GFP_KERNEL); |
2611 | if (! knew->name) | 2623 | if (! knew->name) |
2612 | return -ENOMEM; | 2624 | return -ENOMEM; |
2613 | knew->private_value = val; | 2625 | knew->private_value = val; |
2614 | spec->num_kctl_used++; | ||
2615 | return 0; | 2626 | return 0; |
2616 | } | 2627 | } |
2617 | 2628 | ||
@@ -3432,8 +3443,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3432 | if (dig_in && spec->autocfg.dig_in_pin) | 3443 | if (dig_in && spec->autocfg.dig_in_pin) |
3433 | spec->dig_in_nid = dig_in; | 3444 | spec->dig_in_nid = dig_in; |
3434 | 3445 | ||
3435 | if (spec->kctl_alloc) | 3446 | if (spec->kctls.list) |
3436 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3447 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3437 | 3448 | ||
3438 | spec->input_mux = &spec->private_imux; | 3449 | spec->input_mux = &spec->private_imux; |
3439 | spec->dinput_mux = &spec->private_dimux; | 3450 | spec->dinput_mux = &spec->private_dimux; |
@@ -3534,8 +3545,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3534 | if (spec->autocfg.dig_in_pin) | 3545 | if (spec->autocfg.dig_in_pin) |
3535 | spec->dig_in_nid = 0x04; | 3546 | spec->dig_in_nid = 0x04; |
3536 | 3547 | ||
3537 | if (spec->kctl_alloc) | 3548 | if (spec->kctls.list) |
3538 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3549 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3539 | 3550 | ||
3540 | spec->input_mux = &spec->private_imux; | 3551 | spec->input_mux = &spec->private_imux; |
3541 | spec->dinput_mux = &spec->private_dimux; | 3552 | spec->dinput_mux = &spec->private_dimux; |
@@ -3579,13 +3590,70 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
3579 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 3590 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
3580 | } | 3591 | } |
3581 | 3592 | ||
3593 | static int stac92xx_add_jack(struct hda_codec *codec, | ||
3594 | hda_nid_t nid, int type) | ||
3595 | { | ||
3596 | struct sigmatel_spec *spec = codec->spec; | ||
3597 | struct sigmatel_jack *jack; | ||
3598 | int def_conf = snd_hda_codec_read(codec, nid, | ||
3599 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3600 | int connectivity = get_defcfg_connect(def_conf); | ||
3601 | char name[32]; | ||
3602 | |||
3603 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | ||
3604 | return 0; | ||
3605 | |||
3606 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
3607 | jack = snd_array_new(&spec->jacks); | ||
3608 | if (!jack) | ||
3609 | return -ENOMEM; | ||
3610 | jack->nid = nid; | ||
3611 | jack->type = type; | ||
3612 | |||
3613 | sprintf(name, "%s at %s %s Jack", | ||
3614 | snd_hda_get_jack_type(def_conf), | ||
3615 | snd_hda_get_jack_connectivity(def_conf), | ||
3616 | snd_hda_get_jack_location(def_conf)); | ||
3617 | |||
3618 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
3619 | } | ||
3620 | |||
3621 | static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | ||
3622 | int data) | ||
3623 | { | ||
3624 | struct sigmatel_event *event; | ||
3625 | |||
3626 | snd_array_init(&spec->events, sizeof(*event), 32); | ||
3627 | event = snd_array_new(&spec->events); | ||
3628 | if (!event) | ||
3629 | return -ENOMEM; | ||
3630 | event->nid = nid; | ||
3631 | event->data = data; | ||
3632 | |||
3633 | return 0; | ||
3634 | } | ||
3635 | |||
3636 | static int stac92xx_event_data(struct hda_codec *codec, hda_nid_t nid) | ||
3637 | { | ||
3638 | struct sigmatel_spec *spec = codec->spec; | ||
3639 | struct sigmatel_event *events = spec->events.list; | ||
3640 | if (events) { | ||
3641 | int i; | ||
3642 | for (i = 0; i < spec->events.used; i++) | ||
3643 | if (events[i].nid == nid) | ||
3644 | return events[i].data; | ||
3645 | } | ||
3646 | return 0; | ||
3647 | } | ||
3648 | |||
3582 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 3649 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
3583 | unsigned int event) | 3650 | unsigned int event) |
3584 | { | 3651 | { |
3585 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 3652 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
3586 | snd_hda_codec_write_cache(codec, nid, 0, | 3653 | snd_hda_codec_write_cache(codec, nid, 0, |
3587 | AC_VERB_SET_UNSOLICITED_ENABLE, | 3654 | AC_VERB_SET_UNSOLICITED_ENABLE, |
3588 | (AC_USRSP_EN | event)); | 3655 | (AC_USRSP_EN | event | nid)); |
3656 | } | ||
3589 | } | 3657 | } |
3590 | 3658 | ||
3591 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 3659 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) |
@@ -3615,7 +3683,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3615 | { | 3683 | { |
3616 | struct sigmatel_spec *spec = codec->spec; | 3684 | struct sigmatel_spec *spec = codec->spec; |
3617 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3685 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3618 | int i; | 3686 | int i, err; |
3619 | 3687 | ||
3620 | snd_hda_sequence_write(codec, spec->init); | 3688 | snd_hda_sequence_write(codec, spec->init); |
3621 | 3689 | ||
@@ -3628,21 +3696,36 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3628 | /* set up pins */ | 3696 | /* set up pins */ |
3629 | if (spec->hp_detect) { | 3697 | if (spec->hp_detect) { |
3630 | /* Enable unsolicited responses on the HP widget */ | 3698 | /* Enable unsolicited responses on the HP widget */ |
3631 | for (i = 0; i < cfg->hp_outs; i++) | 3699 | for (i = 0; i < cfg->hp_outs; i++) { |
3632 | enable_pin_detect(codec, cfg->hp_pins[i], | 3700 | int type = SND_JACK_HEADPHONE; |
3633 | STAC_HP_EVENT); | 3701 | hda_nid_t nid = cfg->hp_pins[i]; |
3702 | enable_pin_detect(codec, nid, STAC_HP_EVENT | nid); | ||
3703 | /* jack detection */ | ||
3704 | if (cfg->hp_outs == i) | ||
3705 | type |= SND_JACK_LINEOUT; | ||
3706 | err = stac92xx_add_jack(codec, nid, type); | ||
3707 | if (err < 0) | ||
3708 | return err; | ||
3709 | |||
3710 | } | ||
3634 | /* force to enable the first line-out; the others are set up | 3711 | /* force to enable the first line-out; the others are set up |
3635 | * in unsol_event | 3712 | * in unsol_event |
3636 | */ | 3713 | */ |
3637 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 3714 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], |
3638 | AC_PINCTL_OUT_EN); | 3715 | AC_PINCTL_OUT_EN); |
3639 | stac92xx_auto_init_hp_out(codec); | ||
3640 | /* fake event to set up pins */ | 3716 | /* fake event to set up pins */ |
3641 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 3717 | codec->patch_ops.unsol_event(codec, |
3718 | (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); | ||
3642 | } else { | 3719 | } else { |
3643 | stac92xx_auto_init_multi_out(codec); | 3720 | stac92xx_auto_init_multi_out(codec); |
3644 | stac92xx_auto_init_hp_out(codec); | 3721 | stac92xx_auto_init_hp_out(codec); |
3645 | } | 3722 | } |
3723 | for (i = 0; i < cfg->line_outs; i++) { | ||
3724 | err = stac92xx_add_jack(codec, | ||
3725 | cfg->line_out_pins[i], SND_JACK_LINEOUT); | ||
3726 | if (err < 0) | ||
3727 | return err; | ||
3728 | } | ||
3646 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3729 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
3647 | hda_nid_t nid = cfg->input_pins[i]; | 3730 | hda_nid_t nid = cfg->input_pins[i]; |
3648 | if (nid) { | 3731 | if (nid) { |
@@ -3655,6 +3738,11 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3655 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) | 3738 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) |
3656 | pinctl |= stac92xx_get_vref(codec, nid); | 3739 | pinctl |= stac92xx_get_vref(codec, nid); |
3657 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 3740 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
3741 | err = stac92xx_add_jack(codec, nid, | ||
3742 | SND_JACK_MICROPHONE); | ||
3743 | if (err < 0) | ||
3744 | return err; | ||
3745 | enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid); | ||
3658 | } | 3746 | } |
3659 | } | 3747 | } |
3660 | for (i = 0; i < spec->num_dmics; i++) | 3748 | for (i = 0; i < spec->num_dmics; i++) |
@@ -3696,22 +3784,42 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3696 | return 0; | 3784 | return 0; |
3697 | } | 3785 | } |
3698 | 3786 | ||
3787 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
3788 | { | ||
3789 | struct sigmatel_spec *spec = codec->spec; | ||
3790 | if (spec->jacks.list) { | ||
3791 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3792 | int i; | ||
3793 | for (i = 0; i < spec->jacks.used; i++) | ||
3794 | snd_device_free(codec->bus->card, &jacks[i].jack); | ||
3795 | } | ||
3796 | snd_array_free(&spec->jacks); | ||
3797 | } | ||
3798 | |||
3799 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
3800 | { | ||
3801 | struct sigmatel_spec *spec = codec->spec; | ||
3802 | |||
3803 | if (spec->kctls.list) { | ||
3804 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
3805 | int i; | ||
3806 | for (i = 0; i < spec->kctls.used; i++) | ||
3807 | kfree(kctl[i].name); | ||
3808 | } | ||
3809 | snd_array_free(&spec->kctls); | ||
3810 | } | ||
3811 | |||
3699 | static void stac92xx_free(struct hda_codec *codec) | 3812 | static void stac92xx_free(struct hda_codec *codec) |
3700 | { | 3813 | { |
3701 | struct sigmatel_spec *spec = codec->spec; | 3814 | struct sigmatel_spec *spec = codec->spec; |
3702 | int i; | ||
3703 | 3815 | ||
3704 | if (! spec) | 3816 | if (! spec) |
3705 | return; | 3817 | return; |
3706 | 3818 | ||
3707 | if (spec->kctl_alloc) { | ||
3708 | for (i = 0; i < spec->num_kctl_used; i++) | ||
3709 | kfree(spec->kctl_alloc[i].name); | ||
3710 | kfree(spec->kctl_alloc); | ||
3711 | } | ||
3712 | |||
3713 | if (spec->bios_pin_configs) | 3819 | if (spec->bios_pin_configs) |
3714 | kfree(spec->bios_pin_configs); | 3820 | kfree(spec->bios_pin_configs); |
3821 | stac92xx_free_jacks(codec); | ||
3822 | snd_array_free(&spec->events); | ||
3715 | 3823 | ||
3716 | kfree(spec); | 3824 | kfree(spec); |
3717 | snd_hda_detach_beep_device(codec); | 3825 | snd_hda_detach_beep_device(codec); |
@@ -3850,24 +3958,57 @@ static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | |||
3850 | 3958 | ||
3851 | /* power down unused output ports */ | 3959 | /* power down unused output ports */ |
3852 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); | 3960 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); |
3853 | }; | 3961 | } |
3962 | |||
3963 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
3964 | { | ||
3965 | struct sigmatel_spec *spec = codec->spec; | ||
3966 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3967 | |||
3968 | if (jacks) { | ||
3969 | int i; | ||
3970 | for (i = 0; i < spec->jacks.used; i++) { | ||
3971 | if (jacks->nid == nid) { | ||
3972 | unsigned int pin_ctl = | ||
3973 | snd_hda_codec_read(codec, nid, | ||
3974 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
3975 | 0x00); | ||
3976 | int type = jacks->type; | ||
3977 | if (type == (SND_JACK_LINEOUT | ||
3978 | | SND_JACK_HEADPHONE)) | ||
3979 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
3980 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
3981 | snd_jack_report(jacks->jack, | ||
3982 | get_hp_pin_presence(codec, nid) | ||
3983 | ? type : 0); | ||
3984 | } | ||
3985 | jacks++; | ||
3986 | } | ||
3987 | } | ||
3988 | } | ||
3854 | 3989 | ||
3855 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 3990 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) |
3856 | { | 3991 | { |
3857 | struct sigmatel_spec *spec = codec->spec; | 3992 | struct sigmatel_spec *spec = codec->spec; |
3858 | int idx = res >> 26 & 0x0f; | 3993 | int event = (res >> 26) & 0x70; |
3994 | int nid = res >> 26 & 0x0f; | ||
3859 | 3995 | ||
3860 | switch ((res >> 26) & 0x70) { | 3996 | switch (event) { |
3861 | case STAC_HP_EVENT: | 3997 | case STAC_HP_EVENT: |
3862 | stac92xx_hp_detect(codec, res); | 3998 | stac92xx_hp_detect(codec, res); |
3863 | /* fallthru */ | 3999 | /* fallthru */ |
4000 | case STAC_INSERT_EVENT: | ||
3864 | case STAC_PWR_EVENT: | 4001 | case STAC_PWR_EVENT: |
3865 | if (spec->num_pwrs > 0) | 4002 | if (nid) { |
3866 | stac92xx_pin_sense(codec, idx); | 4003 | if (spec->num_pwrs > 0) |
4004 | stac92xx_pin_sense(codec, nid); | ||
4005 | stac92xx_report_jack(codec, nid); | ||
4006 | } | ||
3867 | break; | 4007 | break; |
3868 | case STAC_VREF_EVENT: { | 4008 | case STAC_VREF_EVENT: { |
3869 | int data = snd_hda_codec_read(codec, codec->afg, 0, | 4009 | int data = snd_hda_codec_read(codec, codec->afg, 0, |
3870 | AC_VERB_GET_GPIO_DATA, 0); | 4010 | AC_VERB_GET_GPIO_DATA, 0); |
4011 | int idx = stac92xx_event_data(codec, nid); | ||
3871 | /* toggle VREF state based on GPIOx status */ | 4012 | /* toggle VREF state based on GPIOx status */ |
3872 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 4013 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
3873 | !!(data & (1 << idx))); | 4014 | !!(data & (1 << idx))); |
@@ -4390,8 +4531,11 @@ again: | |||
4390 | snd_hda_codec_write(codec, codec->afg, 0, | 4531 | snd_hda_codec_write(codec, codec->afg, 0, |
4391 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 4532 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
4392 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4533 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4393 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4534 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4394 | (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | 4535 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4536 | err = stac92xx_add_event(spec, codec->afg, 0x02); | ||
4537 | if (err < 0) | ||
4538 | return err; | ||
4395 | spec->gpio_mask |= 0x02; | 4539 | spec->gpio_mask |= 0x02; |
4396 | break; | 4540 | break; |
4397 | } | 4541 | } |
@@ -4790,8 +4934,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4790 | snd_hda_codec_write(codec, codec->afg, 0, | 4934 | snd_hda_codec_write(codec, codec->afg, 0, |
4791 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 4935 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4792 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4936 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4793 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4937 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4794 | (AC_USRSP_EN | STAC_HP_EVENT)); | 4938 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4939 | err = stac92xx_add_event(spec, codec->afg, 0x01); | ||
4940 | if (err < 0) | ||
4941 | return err; | ||
4795 | 4942 | ||
4796 | spec->gpio_dir = 0x0b; | 4943 | spec->gpio_dir = 0x0b; |
4797 | spec->eapd_mask = 0x01; | 4944 | 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 | ||