diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-10-16 10:39:46 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-10-16 10:39:46 -0400 |
commit | dd125b28c1523a857b7657b5d8aa774ed1563687 (patch) | |
tree | c6f1c747c653a96668fc1bc947b4db8e5f004b5c | |
parent | 45a6ac16c2136e4b902b09bf0b6192b940e8d732 (diff) | |
parent | 1e1be4329f2aec6a8ec63737a69258fedf34c55d (diff) |
Merge branch 'topic/hda-reconfig' into topic/hda-next
-rw-r--r-- | sound/pci/hda/hda_codec.c | 382 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 39 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 228 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 121 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 10 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 5 | ||||
-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 | 57 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 71 |
12 files changed, 731 insertions, 355 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6447754ae56e..9a8adc600a57 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -344,7 +344,7 @@ static void process_unsol_events(struct work_struct *work) | |||
344 | /* | 344 | /* |
345 | * initialize unsolicited queue | 345 | * initialize unsolicited queue |
346 | */ | 346 | */ |
347 | static int __devinit init_unsol_queue(struct hda_bus *bus) | 347 | static int init_unsol_queue(struct hda_bus *bus) |
348 | { | 348 | { |
349 | struct hda_bus_unsolicited *unsol; | 349 | struct hda_bus_unsolicited *unsol; |
350 | 350 | ||
@@ -393,6 +393,20 @@ static int snd_hda_bus_dev_free(struct snd_device *device) | |||
393 | return snd_hda_bus_free(bus); | 393 | return snd_hda_bus_free(bus); |
394 | } | 394 | } |
395 | 395 | ||
396 | #ifdef CONFIG_SND_HDA_HWDEP | ||
397 | static int snd_hda_bus_dev_register(struct snd_device *device) | ||
398 | { | ||
399 | struct hda_bus *bus = device->device_data; | ||
400 | struct hda_codec *codec; | ||
401 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
402 | snd_hda_hwdep_add_sysfs(codec); | ||
403 | } | ||
404 | return 0; | ||
405 | } | ||
406 | #else | ||
407 | #define snd_hda_bus_dev_register NULL | ||
408 | #endif | ||
409 | |||
396 | /** | 410 | /** |
397 | * snd_hda_bus_new - create a HDA bus | 411 | * snd_hda_bus_new - create a HDA bus |
398 | * @card: the card entry | 412 | * @card: the card entry |
@@ -408,6 +422,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
408 | struct hda_bus *bus; | 422 | struct hda_bus *bus; |
409 | int err; | 423 | int err; |
410 | static struct snd_device_ops dev_ops = { | 424 | static struct snd_device_ops dev_ops = { |
425 | .dev_register = snd_hda_bus_dev_register, | ||
411 | .dev_free = snd_hda_bus_dev_free, | 426 | .dev_free = snd_hda_bus_dev_free, |
412 | }; | 427 | }; |
413 | 428 | ||
@@ -446,7 +461,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
446 | 461 | ||
447 | #ifdef CONFIG_SND_HDA_GENERIC | 462 | #ifdef CONFIG_SND_HDA_GENERIC |
448 | #define is_generic_config(codec) \ | 463 | #define is_generic_config(codec) \ |
449 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 464 | (codec->modelname && !strcmp(codec->modelname, "generic")) |
450 | #else | 465 | #else |
451 | #define is_generic_config(codec) 0 | 466 | #define is_generic_config(codec) 0 |
452 | #endif | 467 | #endif |
@@ -454,7 +469,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
454 | /* | 469 | /* |
455 | * find a matching codec preset | 470 | * find a matching codec preset |
456 | */ | 471 | */ |
457 | static const struct hda_codec_preset __devinit * | 472 | static const struct hda_codec_preset * |
458 | find_codec_preset(struct hda_codec *codec) | 473 | find_codec_preset(struct hda_codec *codec) |
459 | { | 474 | { |
460 | const struct hda_codec_preset **tbl, *preset; | 475 | const struct hda_codec_preset **tbl, *preset; |
@@ -481,15 +496,14 @@ find_codec_preset(struct hda_codec *codec) | |||
481 | } | 496 | } |
482 | 497 | ||
483 | /* | 498 | /* |
484 | * snd_hda_get_codec_name - store the codec name | 499 | * get_codec_name - store the codec name |
485 | */ | 500 | */ |
486 | void snd_hda_get_codec_name(struct hda_codec *codec, | 501 | static int get_codec_name(struct hda_codec *codec) |
487 | char *name, int namelen) | ||
488 | { | 502 | { |
489 | const struct hda_vendor_id *c; | 503 | const struct hda_vendor_id *c; |
490 | const char *vendor = NULL; | 504 | const char *vendor = NULL; |
491 | u16 vendor_id = codec->vendor_id >> 16; | 505 | u16 vendor_id = codec->vendor_id >> 16; |
492 | char tmp[16]; | 506 | char tmp[16], name[32]; |
493 | 507 | ||
494 | for (c = hda_vendor_ids; c->id; c++) { | 508 | for (c = hda_vendor_ids; c->id; c++) { |
495 | if (c->id == vendor_id) { | 509 | if (c->id == vendor_id) { |
@@ -502,10 +516,15 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
502 | vendor = tmp; | 516 | vendor = tmp; |
503 | } | 517 | } |
504 | if (codec->preset && codec->preset->name) | 518 | if (codec->preset && codec->preset->name) |
505 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); | 519 | snprintf(name, sizeof(name), "%s %s", vendor, |
520 | codec->preset->name); | ||
506 | else | 521 | else |
507 | snprintf(name, namelen, "%s ID %x", vendor, | 522 | snprintf(name, sizeof(name), "%s ID %x", vendor, |
508 | codec->vendor_id & 0xffff); | 523 | codec->vendor_id & 0xffff); |
524 | codec->name = kstrdup(name, GFP_KERNEL); | ||
525 | if (!codec->name) | ||
526 | return -ENOMEM; | ||
527 | return 0; | ||
509 | } | 528 | } |
510 | 529 | ||
511 | /* | 530 | /* |
@@ -570,11 +589,14 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
570 | flush_scheduled_work(); | 589 | flush_scheduled_work(); |
571 | #endif | 590 | #endif |
572 | list_del(&codec->list); | 591 | list_del(&codec->list); |
592 | snd_array_free(&codec->mixers); | ||
573 | codec->bus->caddr_tbl[codec->addr] = NULL; | 593 | codec->bus->caddr_tbl[codec->addr] = NULL; |
574 | if (codec->patch_ops.free) | 594 | if (codec->patch_ops.free) |
575 | codec->patch_ops.free(codec); | 595 | codec->patch_ops.free(codec); |
576 | free_hda_cache(&codec->amp_cache); | 596 | free_hda_cache(&codec->amp_cache); |
577 | free_hda_cache(&codec->cmd_cache); | 597 | free_hda_cache(&codec->cmd_cache); |
598 | kfree(codec->name); | ||
599 | kfree(codec->modelname); | ||
578 | kfree(codec->wcaps); | 600 | kfree(codec->wcaps); |
579 | kfree(codec); | 601 | kfree(codec); |
580 | } | 602 | } |
@@ -616,6 +638,14 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
616 | mutex_init(&codec->spdif_mutex); | 638 | mutex_init(&codec->spdif_mutex); |
617 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 639 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
618 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 640 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
641 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | ||
642 | if (codec->bus->modelname) { | ||
643 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | ||
644 | if (!codec->modelname) { | ||
645 | snd_hda_codec_free(codec); | ||
646 | return -ENODEV; | ||
647 | } | ||
648 | } | ||
619 | 649 | ||
620 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 650 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
621 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 651 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
@@ -661,12 +691,41 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
661 | snd_hda_codec_read(codec, nid, 0, | 691 | snd_hda_codec_read(codec, nid, 0, |
662 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 692 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
663 | } | 693 | } |
694 | if (bus->modelname) | ||
695 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | ||
696 | |||
697 | err = snd_hda_codec_configure(codec); | ||
698 | if (err < 0) { | ||
699 | snd_hda_codec_free(codec); | ||
700 | return err; | ||
701 | } | ||
702 | snd_hda_codec_proc_new(codec); | ||
703 | |||
704 | snd_hda_create_hwdep(codec); | ||
705 | |||
706 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, | ||
707 | codec->subsystem_id, codec->revision_id); | ||
708 | snd_component_add(codec->bus->card, component); | ||
709 | |||
710 | if (codecp) | ||
711 | *codecp = codec; | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | int snd_hda_codec_configure(struct hda_codec *codec) | ||
716 | { | ||
717 | int err; | ||
664 | 718 | ||
665 | codec->preset = find_codec_preset(codec); | 719 | codec->preset = find_codec_preset(codec); |
720 | if (!codec->name) { | ||
721 | err = get_codec_name(codec); | ||
722 | if (err < 0) | ||
723 | return err; | ||
724 | } | ||
666 | /* audio codec should override the mixer name */ | 725 | /* audio codec should override the mixer name */ |
667 | if (codec->afg || !*bus->card->mixername) | 726 | if (codec->afg || !*codec->bus->card->mixername) |
668 | snd_hda_get_codec_name(codec, bus->card->mixername, | 727 | strlcpy(codec->bus->card->mixername, codec->name, |
669 | sizeof(bus->card->mixername)); | 728 | sizeof(codec->bus->card->mixername)); |
670 | 729 | ||
671 | if (is_generic_config(codec)) { | 730 | if (is_generic_config(codec)) { |
672 | err = snd_hda_parse_generic_codec(codec); | 731 | err = snd_hda_parse_generic_codec(codec); |
@@ -683,25 +742,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
683 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 742 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); |
684 | 743 | ||
685 | patched: | 744 | patched: |
686 | if (err < 0) { | 745 | if (!err && codec->patch_ops.unsol_event) |
687 | snd_hda_codec_free(codec); | 746 | err = init_unsol_queue(codec->bus); |
688 | return err; | 747 | return err; |
689 | } | ||
690 | |||
691 | if (codec->patch_ops.unsol_event) | ||
692 | init_unsol_queue(bus); | ||
693 | |||
694 | snd_hda_codec_proc_new(codec); | ||
695 | #ifdef CONFIG_SND_HDA_HWDEP | ||
696 | snd_hda_create_hwdep(codec); | ||
697 | #endif | ||
698 | |||
699 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id); | ||
700 | snd_component_add(codec->bus->card, component); | ||
701 | |||
702 | if (codecp) | ||
703 | *codecp = codec; | ||
704 | return 0; | ||
705 | } | 748 | } |
706 | 749 | ||
707 | /** | 750 | /** |
@@ -756,12 +799,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache, | |||
756 | { | 799 | { |
757 | memset(cache, 0, sizeof(*cache)); | 800 | memset(cache, 0, sizeof(*cache)); |
758 | memset(cache->hash, 0xff, sizeof(cache->hash)); | 801 | memset(cache->hash, 0xff, sizeof(cache->hash)); |
759 | cache->record_size = record_size; | 802 | snd_array_init(&cache->buf, record_size, 64); |
760 | } | 803 | } |
761 | 804 | ||
762 | static void free_hda_cache(struct hda_cache_rec *cache) | 805 | static void free_hda_cache(struct hda_cache_rec *cache) |
763 | { | 806 | { |
764 | kfree(cache->buffer); | 807 | snd_array_free(&cache->buf); |
765 | } | 808 | } |
766 | 809 | ||
767 | /* query the hash. allocate an entry if not found. */ | 810 | /* query the hash. allocate an entry if not found. */ |
@@ -770,38 +813,18 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
770 | { | 813 | { |
771 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 814 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
772 | u16 cur = cache->hash[idx]; | 815 | u16 cur = cache->hash[idx]; |
816 | struct hda_cache_head *info_head = cache->buf.list; | ||
773 | struct hda_cache_head *info; | 817 | struct hda_cache_head *info; |
774 | 818 | ||
775 | while (cur != 0xffff) { | 819 | while (cur != 0xffff) { |
776 | info = (struct hda_cache_head *)(cache->buffer + | 820 | info = &info_head[cur]; |
777 | cur * cache->record_size); | ||
778 | if (info->key == key) | 821 | if (info->key == key) |
779 | return info; | 822 | return info; |
780 | cur = info->next; | 823 | cur = info->next; |
781 | } | 824 | } |
782 | 825 | ||
783 | /* add a new hash entry */ | 826 | /* add a new hash entry */ |
784 | if (cache->num_entries >= cache->size) { | 827 | info = snd_array_new(&cache->buf); |
785 | /* reallocate the array */ | ||
786 | unsigned int new_size = cache->size + 64; | ||
787 | void *new_buffer; | ||
788 | new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL); | ||
789 | if (!new_buffer) { | ||
790 | snd_printk(KERN_ERR "hda_codec: " | ||
791 | "can't malloc amp_info\n"); | ||
792 | return NULL; | ||
793 | } | ||
794 | if (cache->buffer) { | ||
795 | memcpy(new_buffer, cache->buffer, | ||
796 | cache->size * cache->record_size); | ||
797 | kfree(cache->buffer); | ||
798 | } | ||
799 | cache->size = new_size; | ||
800 | cache->buffer = new_buffer; | ||
801 | } | ||
802 | cur = cache->num_entries++; | ||
803 | info = (struct hda_cache_head *)(cache->buffer + | ||
804 | cur * cache->record_size); | ||
805 | info->key = key; | 828 | info->key = key; |
806 | info->val = 0; | 829 | info->val = 0; |
807 | info->next = cache->hash[idx]; | 830 | info->next = cache->hash[idx]; |
@@ -942,10 +965,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
942 | /* resume the all amp commands from the cache */ | 965 | /* resume the all amp commands from the cache */ |
943 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | 966 | void snd_hda_codec_resume_amp(struct hda_codec *codec) |
944 | { | 967 | { |
945 | struct hda_amp_info *buffer = codec->amp_cache.buffer; | 968 | struct hda_amp_info *buffer = codec->amp_cache.buf.list; |
946 | int i; | 969 | int i; |
947 | 970 | ||
948 | for (i = 0; i < codec->amp_cache.size; i++, buffer++) { | 971 | for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) { |
949 | u32 key = buffer->head.key; | 972 | u32 key = buffer->head.key; |
950 | hda_nid_t nid; | 973 | hda_nid_t nid; |
951 | unsigned int idx, dir, ch; | 974 | unsigned int idx, dir, ch; |
@@ -1097,6 +1120,57 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1097 | return _snd_hda_find_mixer_ctl(codec, name, 0); | 1120 | return _snd_hda_find_mixer_ctl(codec, name, 0); |
1098 | } | 1121 | } |
1099 | 1122 | ||
1123 | /* Add a control element and assign to the codec */ | ||
1124 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | ||
1125 | { | ||
1126 | int err; | ||
1127 | struct snd_kcontrol **knewp; | ||
1128 | |||
1129 | err = snd_ctl_add(codec->bus->card, kctl); | ||
1130 | if (err < 0) | ||
1131 | return err; | ||
1132 | knewp = snd_array_new(&codec->mixers); | ||
1133 | if (!knewp) | ||
1134 | return -ENOMEM; | ||
1135 | *knewp = kctl; | ||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | /* Clear all controls assigned to the given codec */ | ||
1140 | void snd_hda_ctls_clear(struct hda_codec *codec) | ||
1141 | { | ||
1142 | int i; | ||
1143 | struct snd_kcontrol **kctls = codec->mixers.list; | ||
1144 | for (i = 0; i < codec->mixers.used; i++) | ||
1145 | snd_ctl_remove(codec->bus->card, kctls[i]); | ||
1146 | snd_array_free(&codec->mixers); | ||
1147 | } | ||
1148 | |||
1149 | void snd_hda_codec_reset(struct hda_codec *codec) | ||
1150 | { | ||
1151 | int i; | ||
1152 | |||
1153 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1154 | cancel_delayed_work(&codec->power_work); | ||
1155 | flush_scheduled_work(); | ||
1156 | #endif | ||
1157 | snd_hda_ctls_clear(codec); | ||
1158 | /* relase PCMs */ | ||
1159 | for (i = 0; i < codec->num_pcms; i++) { | ||
1160 | if (codec->pcm_info[i].pcm) | ||
1161 | snd_device_free(codec->bus->card, | ||
1162 | codec->pcm_info[i].pcm); | ||
1163 | } | ||
1164 | if (codec->patch_ops.free) | ||
1165 | codec->patch_ops.free(codec); | ||
1166 | codec->spec = NULL; | ||
1167 | free_hda_cache(&codec->amp_cache); | ||
1168 | free_hda_cache(&codec->cmd_cache); | ||
1169 | codec->num_pcms = 0; | ||
1170 | codec->pcm_info = NULL; | ||
1171 | codec->preset = NULL; | ||
1172 | } | ||
1173 | |||
1100 | /* create a virtual master control and add slaves */ | 1174 | /* create a virtual master control and add slaves */ |
1101 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1175 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
1102 | unsigned int *tlv, const char **slaves) | 1176 | unsigned int *tlv, const char **slaves) |
@@ -1114,7 +1188,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1114 | kctl = snd_ctl_make_virtual_master(name, tlv); | 1188 | kctl = snd_ctl_make_virtual_master(name, tlv); |
1115 | if (!kctl) | 1189 | if (!kctl) |
1116 | return -ENOMEM; | 1190 | return -ENOMEM; |
1117 | err = snd_ctl_add(codec->bus->card, kctl); | 1191 | err = snd_hda_ctl_add(codec, kctl); |
1118 | if (err < 0) | 1192 | if (err < 0) |
1119 | return err; | 1193 | return err; |
1120 | 1194 | ||
@@ -1578,7 +1652,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1578 | kctl = snd_ctl_new1(dig_mix, codec); | 1652 | kctl = snd_ctl_new1(dig_mix, codec); |
1579 | kctl->id.index = idx; | 1653 | kctl->id.index = idx; |
1580 | kctl->private_value = nid; | 1654 | kctl->private_value = nid; |
1581 | err = snd_ctl_add(codec->bus->card, kctl); | 1655 | err = snd_hda_ctl_add(codec, kctl); |
1582 | if (err < 0) | 1656 | if (err < 0) |
1583 | return err; | 1657 | return err; |
1584 | } | 1658 | } |
@@ -1622,7 +1696,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec, | |||
1622 | if (!mout->dig_out_nid) | 1696 | if (!mout->dig_out_nid) |
1623 | return 0; | 1697 | return 0; |
1624 | /* ATTENTION: here mout is passed as private_data, instead of codec */ | 1698 | /* ATTENTION: here mout is passed as private_data, instead of codec */ |
1625 | return snd_ctl_add(codec->bus->card, | 1699 | return snd_hda_ctl_add(codec, |
1626 | snd_ctl_new1(&spdif_share_sw, mout)); | 1700 | snd_ctl_new1(&spdif_share_sw, mout)); |
1627 | } | 1701 | } |
1628 | 1702 | ||
@@ -1724,7 +1798,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1724 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1798 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1725 | kctl = snd_ctl_new1(dig_mix, codec); | 1799 | kctl = snd_ctl_new1(dig_mix, codec); |
1726 | kctl->private_value = nid; | 1800 | kctl->private_value = nid; |
1727 | err = snd_ctl_add(codec->bus->card, kctl); | 1801 | err = snd_hda_ctl_add(codec, kctl); |
1728 | if (err < 0) | 1802 | if (err < 0) |
1729 | return err; | 1803 | return err; |
1730 | } | 1804 | } |
@@ -1779,10 +1853,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1779 | /* resume the all commands from the cache */ | 1853 | /* resume the all commands from the cache */ |
1780 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | 1854 | void snd_hda_codec_resume_cache(struct hda_codec *codec) |
1781 | { | 1855 | { |
1782 | struct hda_cache_head *buffer = codec->cmd_cache.buffer; | 1856 | struct hda_cache_head *buffer = codec->cmd_cache.buf.list; |
1783 | int i; | 1857 | int i; |
1784 | 1858 | ||
1785 | for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { | 1859 | for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) { |
1786 | u32 key = buffer->key; | 1860 | u32 key = buffer->key; |
1787 | if (!key) | 1861 | if (!key) |
1788 | continue; | 1862 | continue; |
@@ -1867,6 +1941,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
1867 | } | 1941 | } |
1868 | } | 1942 | } |
1869 | 1943 | ||
1944 | #ifdef CONFIG_SND_HDA_HWDEP | ||
1945 | /* execute additional init verbs */ | ||
1946 | static void hda_exec_init_verbs(struct hda_codec *codec) | ||
1947 | { | ||
1948 | if (codec->init_verbs.list) | ||
1949 | snd_hda_sequence_write(codec, codec->init_verbs.list); | ||
1950 | } | ||
1951 | #else | ||
1952 | static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | ||
1953 | #endif | ||
1954 | |||
1870 | #ifdef SND_HDA_NEEDS_RESUME | 1955 | #ifdef SND_HDA_NEEDS_RESUME |
1871 | /* | 1956 | /* |
1872 | * call suspend and power-down; used both from PM and power-save | 1957 | * call suspend and power-down; used both from PM and power-save |
@@ -1893,6 +1978,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
1893 | hda_set_power_state(codec, | 1978 | hda_set_power_state(codec, |
1894 | codec->afg ? codec->afg : codec->mfg, | 1979 | codec->afg ? codec->afg : codec->mfg, |
1895 | AC_PWRST_D0); | 1980 | AC_PWRST_D0); |
1981 | hda_exec_init_verbs(codec); | ||
1896 | if (codec->patch_ops.resume) | 1982 | if (codec->patch_ops.resume) |
1897 | codec->patch_ops.resume(codec); | 1983 | codec->patch_ops.resume(codec); |
1898 | else { | 1984 | else { |
@@ -1918,23 +2004,31 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1918 | struct hda_codec *codec; | 2004 | struct hda_codec *codec; |
1919 | 2005 | ||
1920 | list_for_each_entry(codec, &bus->codec_list, list) { | 2006 | list_for_each_entry(codec, &bus->codec_list, list) { |
1921 | int err = 0; | 2007 | int err = snd_hda_codec_build_controls(codec); |
1922 | /* fake as if already powered-on */ | ||
1923 | hda_keep_power_on(codec); | ||
1924 | /* then fire up */ | ||
1925 | hda_set_power_state(codec, | ||
1926 | codec->afg ? codec->afg : codec->mfg, | ||
1927 | AC_PWRST_D0); | ||
1928 | /* continue to initialize... */ | ||
1929 | if (codec->patch_ops.init) | ||
1930 | err = codec->patch_ops.init(codec); | ||
1931 | if (!err && codec->patch_ops.build_controls) | ||
1932 | err = codec->patch_ops.build_controls(codec); | ||
1933 | snd_hda_power_down(codec); | ||
1934 | if (err < 0) | 2008 | if (err < 0) |
1935 | return err; | 2009 | return err; |
1936 | } | 2010 | } |
2011 | return 0; | ||
2012 | } | ||
1937 | 2013 | ||
2014 | int snd_hda_codec_build_controls(struct hda_codec *codec) | ||
2015 | { | ||
2016 | int err = 0; | ||
2017 | /* fake as if already powered-on */ | ||
2018 | hda_keep_power_on(codec); | ||
2019 | /* then fire up */ | ||
2020 | hda_set_power_state(codec, | ||
2021 | codec->afg ? codec->afg : codec->mfg, | ||
2022 | AC_PWRST_D0); | ||
2023 | hda_exec_init_verbs(codec); | ||
2024 | /* continue to initialize... */ | ||
2025 | if (codec->patch_ops.init) | ||
2026 | err = codec->patch_ops.init(codec); | ||
2027 | if (!err && codec->patch_ops.build_controls) | ||
2028 | err = codec->patch_ops.build_controls(codec); | ||
2029 | snd_hda_power_down(codec); | ||
2030 | if (err < 0) | ||
2031 | return err; | ||
1938 | return 0; | 2032 | return 0; |
1939 | } | 2033 | } |
1940 | 2034 | ||
@@ -2235,8 +2329,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2235 | return 0; | 2329 | return 0; |
2236 | } | 2330 | } |
2237 | 2331 | ||
2238 | static int __devinit set_pcm_default_values(struct hda_codec *codec, | 2332 | static int set_pcm_default_values(struct hda_codec *codec, |
2239 | struct hda_pcm_stream *info) | 2333 | struct hda_pcm_stream *info) |
2240 | { | 2334 | { |
2241 | /* query support PCM information from the given NID */ | 2335 | /* query support PCM information from the given NID */ |
2242 | if (info->nid && (!info->rates || !info->formats)) { | 2336 | if (info->nid && (!info->rates || !info->formats)) { |
@@ -2262,6 +2356,28 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2262 | return 0; | 2356 | return 0; |
2263 | } | 2357 | } |
2264 | 2358 | ||
2359 | /* | ||
2360 | * attach a new PCM stream | ||
2361 | */ | ||
2362 | static int __devinit | ||
2363 | snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | ||
2364 | { | ||
2365 | struct hda_pcm_stream *info; | ||
2366 | int stream, err; | ||
2367 | |||
2368 | if (!pcm->name) | ||
2369 | return -EINVAL; | ||
2370 | for (stream = 0; stream < 2; stream++) { | ||
2371 | info = &pcm->stream[stream]; | ||
2372 | if (info->substreams) { | ||
2373 | err = set_pcm_default_values(codec, info); | ||
2374 | if (err < 0) | ||
2375 | return err; | ||
2376 | } | ||
2377 | } | ||
2378 | return codec->bus->ops.attach_pcm(codec, pcm); | ||
2379 | } | ||
2380 | |||
2265 | /** | 2381 | /** |
2266 | * snd_hda_build_pcms - build PCM information | 2382 | * snd_hda_build_pcms - build PCM information |
2267 | * @bus: the BUS | 2383 | * @bus: the BUS |
@@ -2288,25 +2404,67 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2288 | * | 2404 | * |
2289 | * This function returns 0 if successfull, or a negative error code. | 2405 | * This function returns 0 if successfull, or a negative error code. |
2290 | */ | 2406 | */ |
2291 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) | 2407 | int snd_hda_build_pcms(struct hda_bus *bus) |
2292 | { | 2408 | { |
2409 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2410 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2411 | }; | ||
2412 | /* starting device index for each PCM type */ | ||
2413 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2414 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2415 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2416 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2417 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2418 | }; | ||
2419 | /* normal audio device indices; not linear to keep compatibility */ | ||
2420 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2293 | struct hda_codec *codec; | 2421 | struct hda_codec *codec; |
2422 | int num_devs[HDA_PCM_NTYPES]; | ||
2294 | 2423 | ||
2424 | memset(num_devs, 0, sizeof(num_devs)); | ||
2295 | list_for_each_entry(codec, &bus->codec_list, list) { | 2425 | list_for_each_entry(codec, &bus->codec_list, list) { |
2296 | unsigned int pcm, s; | 2426 | unsigned int pcm; |
2297 | int err; | 2427 | int err; |
2298 | if (!codec->patch_ops.build_pcms) | 2428 | if (!codec->num_pcms) { |
2299 | continue; | 2429 | if (!codec->patch_ops.build_pcms) |
2300 | err = codec->patch_ops.build_pcms(codec); | 2430 | continue; |
2301 | if (err < 0) | 2431 | err = codec->patch_ops.build_pcms(codec); |
2302 | return err; | 2432 | if (err < 0) |
2433 | return err; | ||
2434 | } | ||
2303 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2435 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2304 | for (s = 0; s < 2; s++) { | 2436 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2305 | struct hda_pcm_stream *info; | 2437 | int type = cpcm->pcm_type; |
2306 | info = &codec->pcm_info[pcm].stream[s]; | 2438 | int dev; |
2307 | if (!info->substreams) | 2439 | switch (type) { |
2440 | case HDA_PCM_TYPE_AUDIO: | ||
2441 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
2442 | snd_printk(KERN_WARNING | ||
2443 | "Too many audio devices\n"); | ||
2444 | continue; | ||
2445 | } | ||
2446 | dev = audio_idx[num_devs[type]]; | ||
2447 | break; | ||
2448 | case HDA_PCM_TYPE_SPDIF: | ||
2449 | case HDA_PCM_TYPE_HDMI: | ||
2450 | case HDA_PCM_TYPE_MODEM: | ||
2451 | if (num_devs[type]) { | ||
2452 | snd_printk(KERN_WARNING | ||
2453 | "%s already defined\n", | ||
2454 | dev_name[type]); | ||
2308 | continue; | 2455 | continue; |
2309 | err = set_pcm_default_values(codec, info); | 2456 | } |
2457 | dev = dev_idx[type]; | ||
2458 | break; | ||
2459 | default: | ||
2460 | snd_printk(KERN_WARNING | ||
2461 | "Invalid PCM type %d\n", type); | ||
2462 | continue; | ||
2463 | } | ||
2464 | num_devs[type]++; | ||
2465 | if (!cpcm->pcm) { | ||
2466 | cpcm->device = dev; | ||
2467 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2310 | if (err < 0) | 2468 | if (err < 0) |
2311 | return err; | 2469 | return err; |
2312 | } | 2470 | } |
@@ -2332,11 +2490,11 @@ int snd_hda_check_board_config(struct hda_codec *codec, | |||
2332 | int num_configs, const char **models, | 2490 | int num_configs, const char **models, |
2333 | const struct snd_pci_quirk *tbl) | 2491 | const struct snd_pci_quirk *tbl) |
2334 | { | 2492 | { |
2335 | if (codec->bus->modelname && models) { | 2493 | if (codec->modelname && models) { |
2336 | int i; | 2494 | int i; |
2337 | for (i = 0; i < num_configs; i++) { | 2495 | for (i = 0; i < num_configs; i++) { |
2338 | if (models[i] && | 2496 | if (models[i] && |
2339 | !strcmp(codec->bus->modelname, models[i])) { | 2497 | !strcmp(codec->modelname, models[i])) { |
2340 | snd_printd(KERN_INFO "hda_codec: model '%s' is " | 2498 | snd_printd(KERN_INFO "hda_codec: model '%s' is " |
2341 | "selected\n", models[i]); | 2499 | "selected\n", models[i]); |
2342 | return i; | 2500 | return i; |
@@ -2389,7 +2547,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2389 | kctl = snd_ctl_new1(knew, codec); | 2547 | kctl = snd_ctl_new1(knew, codec); |
2390 | if (!kctl) | 2548 | if (!kctl) |
2391 | return -ENOMEM; | 2549 | return -ENOMEM; |
2392 | err = snd_ctl_add(codec->bus->card, kctl); | 2550 | err = snd_hda_ctl_add(codec, kctl); |
2393 | if (err < 0) { | 2551 | if (err < 0) { |
2394 | if (!codec->addr) | 2552 | if (!codec->addr) |
2395 | return err; | 2553 | return err; |
@@ -2397,7 +2555,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2397 | if (!kctl) | 2555 | if (!kctl) |
2398 | return -ENOMEM; | 2556 | return -ENOMEM; |
2399 | kctl->id.device = codec->addr; | 2557 | kctl->id.device = codec->addr; |
2400 | err = snd_ctl_add(codec->bus->card, kctl); | 2558 | err = snd_hda_ctl_add(codec, kctl); |
2401 | if (err < 0) | 2559 | if (err < 0) |
2402 | return err; | 2560 | return err; |
2403 | } | 2561 | } |
@@ -3138,3 +3296,37 @@ int snd_hda_codecs_inuse(struct hda_bus *bus) | |||
3138 | } | 3296 | } |
3139 | #endif | 3297 | #endif |
3140 | #endif | 3298 | #endif |
3299 | |||
3300 | /* | ||
3301 | * generic arrays | ||
3302 | */ | ||
3303 | |||
3304 | /* get a new element from the given array | ||
3305 | * if it exceeds the pre-allocated array size, re-allocate the array | ||
3306 | */ | ||
3307 | void *snd_array_new(struct snd_array *array) | ||
3308 | { | ||
3309 | if (array->used >= array->alloced) { | ||
3310 | int num = array->alloced + array->alloc_align; | ||
3311 | void *nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL); | ||
3312 | if (!nlist) | ||
3313 | return NULL; | ||
3314 | if (array->list) { | ||
3315 | memcpy(nlist, array->list, | ||
3316 | array->elem_size * array->alloced); | ||
3317 | kfree(array->list); | ||
3318 | } | ||
3319 | array->list = nlist; | ||
3320 | array->alloced = num; | ||
3321 | } | ||
3322 | return array->list + (array->used++ * array->elem_size); | ||
3323 | } | ||
3324 | |||
3325 | /* free the given array elements */ | ||
3326 | void snd_array_free(struct snd_array *array) | ||
3327 | { | ||
3328 | kfree(array->list); | ||
3329 | array->used = 0; | ||
3330 | array->alloced = 0; | ||
3331 | array->list = NULL; | ||
3332 | } | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 60468f562400..a77ba223af40 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 |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 0ca30894f7c6..98ff010d5b95 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -723,7 +723,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
723 | if (is_loopback) | 723 | if (is_loopback) |
724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); | 724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); |
725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
726 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 726 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
727 | if (err < 0) | ||
727 | return err; | 728 | return err; |
728 | created = 1; | 729 | created = 1; |
729 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 730 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
@@ -732,7 +733,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
732 | if (is_loopback) | 733 | if (is_loopback) |
733 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); | 734 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); |
734 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 735 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
735 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 736 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
737 | if (err < 0) | ||
736 | return err; | 738 | return err; |
737 | created = 1; | 739 | created = 1; |
738 | } | 740 | } |
@@ -745,14 +747,16 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
745 | (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { | 747 | (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { |
746 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); | 748 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); |
747 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 749 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
748 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 750 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
751 | if (err < 0) | ||
749 | return err; | 752 | return err; |
750 | created = 1; | 753 | created = 1; |
751 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 754 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
752 | (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { | 755 | (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { |
753 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); | 756 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); |
754 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 757 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
755 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 758 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
759 | if (err < 0) | ||
756 | return err; | 760 | return err; |
757 | created = 1; | 761 | created = 1; |
758 | } | 762 | } |
@@ -849,8 +853,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
849 | } | 853 | } |
850 | 854 | ||
851 | /* create input MUX if multiple sources are available */ | 855 | /* create input MUX if multiple sources are available */ |
852 | if ((err = snd_ctl_add(codec->bus->card, | 856 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec)); |
853 | snd_ctl_new1(&cap_sel, codec))) < 0) | 857 | if (err < 0) |
854 | return err; | 858 | return err; |
855 | 859 | ||
856 | /* no volume control? */ | 860 | /* no volume control? */ |
@@ -867,8 +871,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
867 | HDA_CODEC_VOLUME(name, adc_node->nid, | 871 | HDA_CODEC_VOLUME(name, adc_node->nid, |
868 | spec->input_mux.items[i].index, | 872 | spec->input_mux.items[i].index, |
869 | HDA_INPUT); | 873 | HDA_INPUT); |
870 | if ((err = snd_ctl_add(codec->bus->card, | 874 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
871 | snd_ctl_new1(&knew, codec))) < 0) | 875 | if (err < 0) |
872 | return err; | 876 | return err; |
873 | } | 877 | } |
874 | 878 | ||
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 6e18a422d993..653da1d3e4df 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -23,10 +23,12 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/compat.h> | 24 | #include <linux/compat.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/ctype.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include "hda_codec.h" | 28 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 29 | #include "hda_local.h" |
29 | #include <sound/hda_hwdep.h> | 30 | #include <sound/hda_hwdep.h> |
31 | #include <sound/minors.h> | ||
30 | 32 | ||
31 | /* | 33 | /* |
32 | * write/read an out-of-bound verb | 34 | * write/read an out-of-bound verb |
@@ -95,6 +97,25 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
95 | return 0; | 97 | return 0; |
96 | } | 98 | } |
97 | 99 | ||
100 | static void clear_hwdep_elements(struct hda_codec *codec) | ||
101 | { | ||
102 | char **head; | ||
103 | int i; | ||
104 | |||
105 | /* clear init verbs */ | ||
106 | snd_array_free(&codec->init_verbs); | ||
107 | /* clear hints */ | ||
108 | head = codec->hints.list; | ||
109 | for (i = 0; i < codec->hints.used; i++, head++) | ||
110 | kfree(*head); | ||
111 | snd_array_free(&codec->hints); | ||
112 | } | ||
113 | |||
114 | static void hwdep_free(struct snd_hwdep *hwdep) | ||
115 | { | ||
116 | clear_hwdep_elements(hwdep->private_data); | ||
117 | } | ||
118 | |||
98 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | 119 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) |
99 | { | 120 | { |
100 | char hwname[16]; | 121 | char hwname[16]; |
@@ -109,6 +130,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
109 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); | 130 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); |
110 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | 131 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; |
111 | hwdep->private_data = codec; | 132 | hwdep->private_data = codec; |
133 | hwdep->private_free = hwdep_free; | ||
112 | hwdep->exclusive = 1; | 134 | hwdep->exclusive = 1; |
113 | 135 | ||
114 | hwdep->ops.open = hda_hwdep_open; | 136 | hwdep->ops.open = hda_hwdep_open; |
@@ -117,5 +139,211 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
117 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | 139 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; |
118 | #endif | 140 | #endif |
119 | 141 | ||
142 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | ||
143 | snd_array_init(&codec->hints, sizeof(char *), 32); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * sysfs interface | ||
150 | */ | ||
151 | |||
152 | static int clear_codec(struct hda_codec *codec) | ||
153 | { | ||
154 | snd_hda_codec_reset(codec); | ||
155 | clear_hwdep_elements(codec); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int reconfig_codec(struct hda_codec *codec) | ||
160 | { | ||
161 | int err; | ||
162 | |||
163 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); | ||
164 | snd_hda_codec_reset(codec); | ||
165 | err = snd_hda_codec_configure(codec); | ||
166 | if (err < 0) | ||
167 | return err; | ||
168 | /* rebuild PCMs */ | ||
169 | err = snd_hda_build_pcms(codec->bus); | ||
170 | if (err < 0) | ||
171 | return err; | ||
172 | /* rebuild mixers */ | ||
173 | err = snd_hda_codec_build_controls(codec); | ||
174 | if (err < 0) | ||
175 | return err; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * allocate a string at most len chars, and remove the trailing EOL | ||
181 | */ | ||
182 | static char *kstrndup_noeol(const char *src, size_t len) | ||
183 | { | ||
184 | char *s = kstrndup(src, len, GFP_KERNEL); | ||
185 | char *p; | ||
186 | if (!s) | ||
187 | return NULL; | ||
188 | p = strchr(s, '\n'); | ||
189 | if (p) | ||
190 | *p = 0; | ||
191 | return s; | ||
192 | } | ||
193 | |||
194 | #define CODEC_INFO_SHOW(type) \ | ||
195 | static ssize_t type##_show(struct device *dev, \ | ||
196 | struct device_attribute *attr, \ | ||
197 | char *buf) \ | ||
198 | { \ | ||
199 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
200 | struct hda_codec *codec = hwdep->private_data; \ | ||
201 | return sprintf(buf, "0x%x\n", codec->type); \ | ||
202 | } | ||
203 | |||
204 | #define CODEC_INFO_STR_SHOW(type) \ | ||
205 | static ssize_t type##_show(struct device *dev, \ | ||
206 | struct device_attribute *attr, \ | ||
207 | char *buf) \ | ||
208 | { \ | ||
209 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
210 | struct hda_codec *codec = hwdep->private_data; \ | ||
211 | return sprintf(buf, "%s\n", \ | ||
212 | codec->type ? codec->type : ""); \ | ||
213 | } | ||
214 | |||
215 | CODEC_INFO_SHOW(vendor_id); | ||
216 | CODEC_INFO_SHOW(subsystem_id); | ||
217 | CODEC_INFO_SHOW(revision_id); | ||
218 | CODEC_INFO_SHOW(afg); | ||
219 | CODEC_INFO_SHOW(mfg); | ||
220 | CODEC_INFO_STR_SHOW(name); | ||
221 | CODEC_INFO_STR_SHOW(modelname); | ||
222 | |||
223 | #define CODEC_INFO_STORE(type) \ | ||
224 | static ssize_t type##_store(struct device *dev, \ | ||
225 | struct device_attribute *attr, \ | ||
226 | const char *buf, size_t count) \ | ||
227 | { \ | ||
228 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
229 | struct hda_codec *codec = hwdep->private_data; \ | ||
230 | char *after; \ | ||
231 | codec->type = simple_strtoul(buf, &after, 0); \ | ||
232 | return count; \ | ||
233 | } | ||
234 | |||
235 | #define CODEC_INFO_STR_STORE(type) \ | ||
236 | static ssize_t type##_store(struct device *dev, \ | ||
237 | struct device_attribute *attr, \ | ||
238 | const char *buf, size_t count) \ | ||
239 | { \ | ||
240 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
241 | struct hda_codec *codec = hwdep->private_data; \ | ||
242 | char *s = kstrndup_noeol(buf, 64); \ | ||
243 | if (!s) \ | ||
244 | return -ENOMEM; \ | ||
245 | kfree(codec->type); \ | ||
246 | codec->type = s; \ | ||
247 | return count; \ | ||
248 | } | ||
249 | |||
250 | CODEC_INFO_STORE(vendor_id); | ||
251 | CODEC_INFO_STORE(subsystem_id); | ||
252 | CODEC_INFO_STORE(revision_id); | ||
253 | CODEC_INFO_STR_STORE(name); | ||
254 | CODEC_INFO_STR_STORE(modelname); | ||
255 | |||
256 | #define CODEC_ACTION_STORE(type) \ | ||
257 | static ssize_t type##_store(struct device *dev, \ | ||
258 | struct device_attribute *attr, \ | ||
259 | const char *buf, size_t count) \ | ||
260 | { \ | ||
261 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
262 | struct hda_codec *codec = hwdep->private_data; \ | ||
263 | int err = 0; \ | ||
264 | if (*buf) \ | ||
265 | err = type##_codec(codec); \ | ||
266 | return err < 0 ? err : count; \ | ||
267 | } | ||
268 | |||
269 | CODEC_ACTION_STORE(reconfig); | ||
270 | CODEC_ACTION_STORE(clear); | ||
271 | |||
272 | static ssize_t init_verbs_store(struct device *dev, | ||
273 | struct device_attribute *attr, | ||
274 | const char *buf, size_t count) | ||
275 | { | ||
276 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
277 | struct hda_codec *codec = hwdep->private_data; | ||
278 | char *p; | ||
279 | struct hda_verb verb, *v; | ||
280 | |||
281 | verb.nid = simple_strtoul(buf, &p, 0); | ||
282 | verb.verb = simple_strtoul(p, &p, 0); | ||
283 | verb.param = simple_strtoul(p, &p, 0); | ||
284 | if (!verb.nid || !verb.verb || !verb.param) | ||
285 | return -EINVAL; | ||
286 | v = snd_array_new(&codec->init_verbs); | ||
287 | if (!v) | ||
288 | return -ENOMEM; | ||
289 | *v = verb; | ||
290 | return count; | ||
291 | } | ||
292 | |||
293 | static ssize_t hints_store(struct device *dev, | ||
294 | struct device_attribute *attr, | ||
295 | const char *buf, size_t count) | ||
296 | { | ||
297 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
298 | struct hda_codec *codec = hwdep->private_data; | ||
299 | char *p; | ||
300 | char **hint; | ||
301 | |||
302 | if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') | ||
303 | return count; | ||
304 | p = kstrndup_noeol(buf, 1024); | ||
305 | if (!p) | ||
306 | return -ENOMEM; | ||
307 | hint = snd_array_new(&codec->hints); | ||
308 | if (!hint) { | ||
309 | kfree(p); | ||
310 | return -ENOMEM; | ||
311 | } | ||
312 | *hint = p; | ||
313 | return count; | ||
314 | } | ||
315 | |||
316 | #define CODEC_ATTR_RW(type) \ | ||
317 | __ATTR(type, 0644, type##_show, type##_store) | ||
318 | #define CODEC_ATTR_RO(type) \ | ||
319 | __ATTR_RO(type) | ||
320 | #define CODEC_ATTR_WO(type) \ | ||
321 | __ATTR(type, 0200, NULL, type##_store) | ||
322 | |||
323 | static struct device_attribute codec_attrs[] = { | ||
324 | CODEC_ATTR_RW(vendor_id), | ||
325 | CODEC_ATTR_RW(subsystem_id), | ||
326 | CODEC_ATTR_RW(revision_id), | ||
327 | CODEC_ATTR_RO(afg), | ||
328 | CODEC_ATTR_RO(mfg), | ||
329 | CODEC_ATTR_RW(name), | ||
330 | CODEC_ATTR_RW(modelname), | ||
331 | CODEC_ATTR_WO(init_verbs), | ||
332 | CODEC_ATTR_WO(hints), | ||
333 | CODEC_ATTR_WO(reconfig), | ||
334 | CODEC_ATTR_WO(clear), | ||
335 | }; | ||
336 | |||
337 | /* | ||
338 | * create sysfs files on hwdep directory | ||
339 | */ | ||
340 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | ||
341 | { | ||
342 | struct snd_hwdep *hwdep = codec->hwdep; | ||
343 | int i; | ||
344 | |||
345 | for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) | ||
346 | snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, | ||
347 | hwdep->device, &codec_attrs[i]); | ||
120 | return 0; | 348 | return 0; |
121 | } | 349 | } |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9f316c1b2790..7b0abf08a583 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1180,6 +1180,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1180 | return 0; | 1180 | return 0; |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | static int azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm); | ||
1183 | 1184 | ||
1184 | /* | 1185 | /* |
1185 | * Codec initialization | 1186 | * Codec initialization |
@@ -1212,6 +1213,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1212 | bus_temp.pci = chip->pci; | 1213 | bus_temp.pci = chip->pci; |
1213 | bus_temp.ops.command = azx_send_cmd; | 1214 | bus_temp.ops.command = azx_send_cmd; |
1214 | bus_temp.ops.get_response = azx_get_response; | 1215 | bus_temp.ops.get_response = azx_get_response; |
1216 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; | ||
1215 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1217 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1216 | bus_temp.ops.pm_notify = azx_power_notify; | 1218 | bus_temp.ops.pm_notify = azx_power_notify; |
1217 | #endif | 1219 | #endif |
@@ -1718,111 +1720,58 @@ static struct snd_pcm_ops azx_pcm_ops = { | |||
1718 | 1720 | ||
1719 | static void azx_pcm_free(struct snd_pcm *pcm) | 1721 | static void azx_pcm_free(struct snd_pcm *pcm) |
1720 | { | 1722 | { |
1721 | kfree(pcm->private_data); | 1723 | struct azx_pcm *apcm = pcm->private_data; |
1724 | if (apcm) { | ||
1725 | apcm->chip->pcm[pcm->device] = NULL; | ||
1726 | kfree(apcm); | ||
1727 | } | ||
1722 | } | 1728 | } |
1723 | 1729 | ||
1724 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | 1730 | static int |
1725 | struct hda_pcm *cpcm) | 1731 | azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm) |
1726 | { | 1732 | { |
1727 | int err; | 1733 | struct azx *chip = codec->bus->private_data; |
1728 | struct snd_pcm *pcm; | 1734 | struct snd_pcm *pcm; |
1729 | struct azx_pcm *apcm; | 1735 | struct azx_pcm *apcm; |
1736 | int pcm_dev = cpcm->device; | ||
1737 | int s, err; | ||
1730 | 1738 | ||
1731 | /* if no substreams are defined for both playback and capture, | 1739 | if (pcm_dev >= AZX_MAX_PCMS) { |
1732 | * it's just a placeholder. ignore it. | 1740 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1733 | */ | 1741 | pcm_dev); |
1734 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | ||
1735 | return 0; | ||
1736 | |||
1737 | if (snd_BUG_ON(!cpcm->name)) | ||
1738 | return -EINVAL; | 1742 | return -EINVAL; |
1739 | 1743 | } | |
1740 | err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, | 1744 | if (chip->pcm[pcm_dev]) { |
1741 | cpcm->stream[0].substreams, | 1745 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); |
1742 | cpcm->stream[1].substreams, | 1746 | return -EBUSY; |
1747 | } | ||
1748 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | ||
1749 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, | ||
1750 | cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, | ||
1743 | &pcm); | 1751 | &pcm); |
1744 | if (err < 0) | 1752 | if (err < 0) |
1745 | return err; | 1753 | return err; |
1746 | strcpy(pcm->name, cpcm->name); | 1754 | strcpy(pcm->name, cpcm->name); |
1747 | apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); | 1755 | apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); |
1748 | if (apcm == NULL) | 1756 | if (apcm == NULL) |
1749 | return -ENOMEM; | 1757 | return -ENOMEM; |
1750 | apcm->chip = chip; | 1758 | apcm->chip = chip; |
1751 | apcm->codec = codec; | 1759 | apcm->codec = codec; |
1752 | apcm->hinfo[0] = &cpcm->stream[0]; | ||
1753 | apcm->hinfo[1] = &cpcm->stream[1]; | ||
1754 | pcm->private_data = apcm; | 1760 | pcm->private_data = apcm; |
1755 | pcm->private_free = azx_pcm_free; | 1761 | pcm->private_free = azx_pcm_free; |
1756 | if (cpcm->stream[0].substreams) | 1762 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
1757 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); | 1763 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; |
1758 | if (cpcm->stream[1].substreams) | 1764 | chip->pcm[pcm_dev] = pcm; |
1759 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); | 1765 | cpcm->pcm = pcm; |
1766 | for (s = 0; s < 2; s++) { | ||
1767 | apcm->hinfo[s] = &cpcm->stream[s]; | ||
1768 | if (cpcm->stream[s].substreams) | ||
1769 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); | ||
1770 | } | ||
1771 | /* buffer pre-allocation */ | ||
1760 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1772 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1761 | snd_dma_pci_data(chip->pci), | 1773 | snd_dma_pci_data(chip->pci), |
1762 | 1024 * 64, 32 * 1024 * 1024); | 1774 | 1024 * 64, 32 * 1024 * 1024); |
1763 | chip->pcm[cpcm->device] = pcm; | ||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1767 | static int __devinit azx_pcm_create(struct azx *chip) | ||
1768 | { | ||
1769 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
1770 | "Audio", "SPDIF", "HDMI", "Modem" | ||
1771 | }; | ||
1772 | /* starting device index for each PCM type */ | ||
1773 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
1774 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
1775 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
1776 | [HDA_PCM_TYPE_HDMI] = 3, | ||
1777 | [HDA_PCM_TYPE_MODEM] = 6 | ||
1778 | }; | ||
1779 | /* normal audio device indices; not linear to keep compatibility */ | ||
1780 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
1781 | struct hda_codec *codec; | ||
1782 | int c, err; | ||
1783 | int num_devs[HDA_PCM_NTYPES]; | ||
1784 | |||
1785 | err = snd_hda_build_pcms(chip->bus); | ||
1786 | if (err < 0) | ||
1787 | return err; | ||
1788 | |||
1789 | /* create audio PCMs */ | ||
1790 | memset(num_devs, 0, sizeof(num_devs)); | ||
1791 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1792 | for (c = 0; c < codec->num_pcms; c++) { | ||
1793 | struct hda_pcm *cpcm = &codec->pcm_info[c]; | ||
1794 | int type = cpcm->pcm_type; | ||
1795 | switch (type) { | ||
1796 | case HDA_PCM_TYPE_AUDIO: | ||
1797 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
1798 | snd_printk(KERN_WARNING | ||
1799 | "Too many audio devices\n"); | ||
1800 | continue; | ||
1801 | } | ||
1802 | cpcm->device = audio_idx[num_devs[type]]; | ||
1803 | break; | ||
1804 | case HDA_PCM_TYPE_SPDIF: | ||
1805 | case HDA_PCM_TYPE_HDMI: | ||
1806 | case HDA_PCM_TYPE_MODEM: | ||
1807 | if (num_devs[type]) { | ||
1808 | snd_printk(KERN_WARNING | ||
1809 | "%s already defined\n", | ||
1810 | dev_name[type]); | ||
1811 | continue; | ||
1812 | } | ||
1813 | cpcm->device = dev_idx[type]; | ||
1814 | break; | ||
1815 | default: | ||
1816 | snd_printk(KERN_WARNING | ||
1817 | "Invalid PCM type %d\n", type); | ||
1818 | continue; | ||
1819 | } | ||
1820 | num_devs[type]++; | ||
1821 | err = create_codec_pcm(chip, codec, cpcm); | ||
1822 | if (err < 0) | ||
1823 | return err; | ||
1824 | } | ||
1825 | } | ||
1826 | return 0; | 1775 | return 0; |
1827 | } | 1776 | } |
1828 | 1777 | ||
@@ -2324,7 +2273,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2324 | } | 2273 | } |
2325 | 2274 | ||
2326 | /* create PCM streams */ | 2275 | /* create PCM streams */ |
2327 | err = azx_pcm_create(chip); | 2276 | err = snd_hda_build_pcms(chip->bus); |
2328 | if (err < 0) { | 2277 | if (err < 0) { |
2329 | snd_card_free(card); | 2278 | snd_card_free(card); |
2330 | return err; | 2279 | return err; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7957fefda730..4a08c31b498a 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -96,6 +96,8 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
96 | const char *name); | 96 | const char *name); |
97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
98 | unsigned int *tlv, const char **slaves); | 98 | unsigned int *tlv, const char **slaves); |
99 | void snd_hda_codec_reset(struct hda_codec *codec); | ||
100 | int snd_hda_codec_configure(struct hda_codec *codec); | ||
99 | 101 | ||
100 | /* amp value bits */ | 102 | /* amp value bits */ |
101 | #define HDA_AMP_MUTE 0x80 | 103 | #define HDA_AMP_MUTE 0x80 |
@@ -393,10 +395,18 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | |||
393 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 395 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
394 | unsigned int caps); | 396 | unsigned int caps); |
395 | 397 | ||
398 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | ||
399 | void snd_hda_ctls_clear(struct hda_codec *codec); | ||
400 | |||
396 | /* | 401 | /* |
397 | * hwdep interface | 402 | * hwdep interface |
398 | */ | 403 | */ |
404 | #ifdef CONFIG_SND_HDA_HWDEP | ||
399 | int snd_hda_create_hwdep(struct hda_codec *codec); | 405 | int snd_hda_create_hwdep(struct hda_codec *codec); |
406 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); | ||
407 | #else | ||
408 | static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } | ||
409 | #endif | ||
400 | 410 | ||
401 | /* | 411 | /* |
402 | * power-management | 412 | * power-management |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 743d77922bce..64ab19f14f79 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -511,12 +511,11 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
511 | struct snd_info_buffer *buffer) | 511 | struct snd_info_buffer *buffer) |
512 | { | 512 | { |
513 | struct hda_codec *codec = entry->private_data; | 513 | struct hda_codec *codec = entry->private_data; |
514 | char buf[32]; | ||
515 | hda_nid_t nid; | 514 | hda_nid_t nid; |
516 | int i, nodes; | 515 | int i, nodes; |
517 | 516 | ||
518 | snd_hda_get_codec_name(codec, buf, sizeof(buf)); | 517 | snd_iprintf(buffer, "Codec: %s\n", |
519 | snd_iprintf(buffer, "Codec: %s\n", buf); | 518 | codec->name ? codec->name : "Not Set"); |
520 | snd_iprintf(buffer, "Address: %d\n", codec->addr); | 519 | snd_iprintf(buffer, "Address: %d\n", codec->addr); |
521 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 520 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); |
522 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 521 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2b00c4afdf97..02643bce5634 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -67,8 +67,7 @@ struct ad198x_spec { | |||
67 | 67 | ||
68 | /* dynamic controls, init_verbs and input_mux */ | 68 | /* dynamic controls, init_verbs and input_mux */ |
69 | struct auto_pin_cfg autocfg; | 69 | struct auto_pin_cfg autocfg; |
70 | unsigned int num_kctl_alloc, num_kctl_used; | 70 | struct snd_array kctls; |
71 | struct snd_kcontrol_new *kctl_alloc; | ||
72 | struct hda_input_mux private_imux; | 71 | struct hda_input_mux private_imux; |
73 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
74 | 73 | ||
@@ -154,6 +153,8 @@ static const char *ad_slave_sws[] = { | |||
154 | NULL | 153 | NULL |
155 | }; | 154 | }; |
156 | 155 | ||
156 | static void ad198x_free_kctls(struct hda_codec *codec); | ||
157 | |||
157 | static int ad198x_build_controls(struct hda_codec *codec) | 158 | static int ad198x_build_controls(struct hda_codec *codec) |
158 | { | 159 | { |
159 | struct ad198x_spec *spec = codec->spec; | 160 | struct ad198x_spec *spec = codec->spec; |
@@ -202,6 +203,7 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
202 | return err; | 203 | return err; |
203 | } | 204 | } |
204 | 205 | ||
206 | ad198x_free_kctls(codec); /* no longer needed */ | ||
205 | return 0; | 207 | return 0; |
206 | } | 208 | } |
207 | 209 | ||
@@ -375,16 +377,27 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
375 | return 0; | 377 | return 0; |
376 | } | 378 | } |
377 | 379 | ||
378 | static void ad198x_free(struct hda_codec *codec) | 380 | static void ad198x_free_kctls(struct hda_codec *codec) |
379 | { | 381 | { |
380 | struct ad198x_spec *spec = codec->spec; | 382 | struct ad198x_spec *spec = codec->spec; |
381 | unsigned int i; | ||
382 | 383 | ||
383 | if (spec->kctl_alloc) { | 384 | if (spec->kctls.list) { |
384 | for (i = 0; i < spec->num_kctl_used; i++) | 385 | struct snd_kcontrol_new *kctl = spec->kctls.list; |
385 | kfree(spec->kctl_alloc[i].name); | 386 | int i; |
386 | kfree(spec->kctl_alloc); | 387 | for (i = 0; i < spec->kctls.used; i++) |
388 | kfree(kctl[i].name); | ||
387 | } | 389 | } |
390 | snd_array_free(&spec->kctls); | ||
391 | } | ||
392 | |||
393 | static void ad198x_free(struct hda_codec *codec) | ||
394 | { | ||
395 | struct ad198x_spec *spec = codec->spec; | ||
396 | |||
397 | if (!spec) | ||
398 | return; | ||
399 | |||
400 | ad198x_free_kctls(codec); | ||
388 | kfree(codec->spec); | 401 | kfree(codec->spec); |
389 | } | 402 | } |
390 | 403 | ||
@@ -2452,9 +2465,6 @@ static struct hda_amp_list ad1988_loopbacks[] = { | |||
2452 | * Automatic parse of I/O pins from the BIOS configuration | 2465 | * Automatic parse of I/O pins from the BIOS configuration |
2453 | */ | 2466 | */ |
2454 | 2467 | ||
2455 | #define NUM_CONTROL_ALLOC 32 | ||
2456 | #define NUM_VERB_ALLOC 32 | ||
2457 | |||
2458 | enum { | 2468 | enum { |
2459 | AD_CTL_WIDGET_VOL, | 2469 | AD_CTL_WIDGET_VOL, |
2460 | AD_CTL_WIDGET_MUTE, | 2470 | AD_CTL_WIDGET_MUTE, |
@@ -2472,27 +2482,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2472 | { | 2482 | { |
2473 | struct snd_kcontrol_new *knew; | 2483 | struct snd_kcontrol_new *knew; |
2474 | 2484 | ||
2475 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2485 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2476 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2486 | knew = snd_array_new(&spec->kctls); |
2477 | 2487 | if (!knew) | |
2478 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2488 | return -ENOMEM; |
2479 | if (! knew) | ||
2480 | return -ENOMEM; | ||
2481 | if (spec->kctl_alloc) { | ||
2482 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2483 | kfree(spec->kctl_alloc); | ||
2484 | } | ||
2485 | spec->kctl_alloc = knew; | ||
2486 | spec->num_kctl_alloc = num; | ||
2487 | } | ||
2488 | |||
2489 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2490 | *knew = ad1988_control_templates[type]; | 2489 | *knew = ad1988_control_templates[type]; |
2491 | knew->name = kstrdup(name, GFP_KERNEL); | 2490 | knew->name = kstrdup(name, GFP_KERNEL); |
2492 | if (! knew->name) | 2491 | if (! knew->name) |
2493 | return -ENOMEM; | 2492 | return -ENOMEM; |
2494 | knew->private_value = val; | 2493 | knew->private_value = val; |
2495 | spec->num_kctl_used++; | ||
2496 | return 0; | 2494 | return 0; |
2497 | } | 2495 | } |
2498 | 2496 | ||
@@ -2846,8 +2844,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2846 | if (spec->autocfg.dig_in_pin) | 2844 | if (spec->autocfg.dig_in_pin) |
2847 | spec->dig_in_nid = AD1988_SPDIF_IN; | 2845 | spec->dig_in_nid = AD1988_SPDIF_IN; |
2848 | 2846 | ||
2849 | if (spec->kctl_alloc) | 2847 | if (spec->kctls.list) |
2850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2848 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2851 | 2849 | ||
2852 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; | 2850 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; |
2853 | 2851 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 7c1eb23f0cec..076010708152 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -86,8 +86,6 @@ struct conexant_spec { | |||
86 | 86 | ||
87 | /* dynamic controls, init_verbs and input_mux */ | 87 | /* dynamic controls, init_verbs and input_mux */ |
88 | struct auto_pin_cfg autocfg; | 88 | struct auto_pin_cfg autocfg; |
89 | unsigned int num_kctl_alloc, num_kctl_used; | ||
90 | struct snd_kcontrol_new *kctl_alloc; | ||
91 | struct hda_input_mux private_imux; | 89 | struct hda_input_mux private_imux; |
92 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 90 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
93 | 91 | ||
@@ -344,15 +342,6 @@ static int conexant_init(struct hda_codec *codec) | |||
344 | 342 | ||
345 | static void conexant_free(struct hda_codec *codec) | 343 | static void conexant_free(struct hda_codec *codec) |
346 | { | 344 | { |
347 | struct conexant_spec *spec = codec->spec; | ||
348 | unsigned int i; | ||
349 | |||
350 | if (spec->kctl_alloc) { | ||
351 | for (i = 0; i < spec->num_kctl_used; i++) | ||
352 | kfree(spec->kctl_alloc[i].name); | ||
353 | kfree(spec->kctl_alloc); | ||
354 | } | ||
355 | |||
356 | kfree(codec->spec); | 345 | kfree(codec->spec); |
357 | } | 346 | } |
358 | 347 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e72707cb60a3..6db74f0e1205 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -284,8 +284,7 @@ struct alc_spec { | |||
284 | 284 | ||
285 | /* dynamic controls, init_verbs and input_mux */ | 285 | /* dynamic controls, init_verbs and input_mux */ |
286 | struct auto_pin_cfg autocfg; | 286 | struct auto_pin_cfg autocfg; |
287 | unsigned int num_kctl_alloc, num_kctl_used; | 287 | struct snd_array kctls; |
288 | struct snd_kcontrol_new *kctl_alloc; | ||
289 | struct hda_input_mux private_imux; | 288 | struct hda_input_mux private_imux; |
290 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 289 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
291 | 290 | ||
@@ -1625,6 +1624,9 @@ static const char *alc_slave_sws[] = { | |||
1625 | /* | 1624 | /* |
1626 | * build control elements | 1625 | * build control elements |
1627 | */ | 1626 | */ |
1627 | |||
1628 | static void alc_free_kctls(struct hda_codec *codec); | ||
1629 | |||
1628 | static int alc_build_controls(struct hda_codec *codec) | 1630 | static int alc_build_controls(struct hda_codec *codec) |
1629 | { | 1631 | { |
1630 | struct alc_spec *spec = codec->spec; | 1632 | struct alc_spec *spec = codec->spec; |
@@ -1671,6 +1673,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1671 | return err; | 1673 | return err; |
1672 | } | 1674 | } |
1673 | 1675 | ||
1676 | alc_free_kctls(codec); /* no longer needed */ | ||
1674 | return 0; | 1677 | return 0; |
1675 | } | 1678 | } |
1676 | 1679 | ||
@@ -2761,19 +2764,27 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2761 | return 0; | 2764 | return 0; |
2762 | } | 2765 | } |
2763 | 2766 | ||
2767 | static void alc_free_kctls(struct hda_codec *codec) | ||
2768 | { | ||
2769 | struct alc_spec *spec = codec->spec; | ||
2770 | |||
2771 | if (spec->kctls.list) { | ||
2772 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
2773 | int i; | ||
2774 | for (i = 0; i < spec->kctls.used; i++) | ||
2775 | kfree(kctl[i].name); | ||
2776 | } | ||
2777 | snd_array_free(&spec->kctls); | ||
2778 | } | ||
2779 | |||
2764 | static void alc_free(struct hda_codec *codec) | 2780 | static void alc_free(struct hda_codec *codec) |
2765 | { | 2781 | { |
2766 | struct alc_spec *spec = codec->spec; | 2782 | struct alc_spec *spec = codec->spec; |
2767 | unsigned int i; | ||
2768 | 2783 | ||
2769 | if (!spec) | 2784 | if (!spec) |
2770 | return; | 2785 | return; |
2771 | 2786 | ||
2772 | if (spec->kctl_alloc) { | 2787 | alc_free_kctls(codec); |
2773 | for (i = 0; i < spec->num_kctl_used; i++) | ||
2774 | kfree(spec->kctl_alloc[i].name); | ||
2775 | kfree(spec->kctl_alloc); | ||
2776 | } | ||
2777 | kfree(spec); | 2788 | kfree(spec); |
2778 | codec->spec = NULL; /* to be sure */ | 2789 | codec->spec = NULL; /* to be sure */ |
2779 | } | 2790 | } |
@@ -3458,9 +3469,6 @@ static struct alc_config_preset alc880_presets[] = { | |||
3458 | * Automatic parse of I/O pins from the BIOS configuration | 3469 | * Automatic parse of I/O pins from the BIOS configuration |
3459 | */ | 3470 | */ |
3460 | 3471 | ||
3461 | #define NUM_CONTROL_ALLOC 32 | ||
3462 | #define NUM_VERB_ALLOC 32 | ||
3463 | |||
3464 | enum { | 3472 | enum { |
3465 | ALC_CTL_WIDGET_VOL, | 3473 | ALC_CTL_WIDGET_VOL, |
3466 | ALC_CTL_WIDGET_MUTE, | 3474 | ALC_CTL_WIDGET_MUTE, |
@@ -3478,29 +3486,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
3478 | { | 3486 | { |
3479 | struct snd_kcontrol_new *knew; | 3487 | struct snd_kcontrol_new *knew; |
3480 | 3488 | ||
3481 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 3489 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
3482 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 3490 | knew = snd_array_new(&spec->kctls); |
3483 | 3491 | if (!knew) | |
3484 | /* array + terminator */ | 3492 | return -ENOMEM; |
3485 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); | ||
3486 | if (!knew) | ||
3487 | return -ENOMEM; | ||
3488 | if (spec->kctl_alloc) { | ||
3489 | memcpy(knew, spec->kctl_alloc, | ||
3490 | sizeof(*knew) * spec->num_kctl_alloc); | ||
3491 | kfree(spec->kctl_alloc); | ||
3492 | } | ||
3493 | spec->kctl_alloc = knew; | ||
3494 | spec->num_kctl_alloc = num; | ||
3495 | } | ||
3496 | |||
3497 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
3498 | *knew = alc880_control_templates[type]; | 3493 | *knew = alc880_control_templates[type]; |
3499 | knew->name = kstrdup(name, GFP_KERNEL); | 3494 | knew->name = kstrdup(name, GFP_KERNEL); |
3500 | if (!knew->name) | 3495 | if (!knew->name) |
3501 | return -ENOMEM; | 3496 | return -ENOMEM; |
3502 | knew->private_value = val; | 3497 | knew->private_value = val; |
3503 | spec->num_kctl_used++; | ||
3504 | return 0; | 3498 | return 0; |
3505 | } | 3499 | } |
3506 | 3500 | ||
@@ -3824,8 +3818,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
3824 | if (spec->autocfg.dig_in_pin) | 3818 | if (spec->autocfg.dig_in_pin) |
3825 | spec->dig_in_nid = ALC880_DIGIN_NID; | 3819 | spec->dig_in_nid = ALC880_DIGIN_NID; |
3826 | 3820 | ||
3827 | if (spec->kctl_alloc) | 3821 | if (spec->kctls.list) |
3828 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3822 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3829 | 3823 | ||
3830 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 3824 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; |
3831 | 3825 | ||
@@ -5212,7 +5206,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5212 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); | 5206 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); |
5213 | if (err < 0) | 5207 | if (err < 0) |
5214 | return err; | 5208 | return err; |
5215 | if (!spec->kctl_alloc) | 5209 | if (!spec->kctls.list) |
5216 | return 0; /* can't find valid BIOS pin config */ | 5210 | return 0; /* can't find valid BIOS pin config */ |
5217 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5211 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); |
5218 | if (err < 0) | 5212 | if (err < 0) |
@@ -5222,8 +5216,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5222 | 5216 | ||
5223 | if (spec->autocfg.dig_out_pin) | 5217 | if (spec->autocfg.dig_out_pin) |
5224 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5218 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5225 | if (spec->kctl_alloc) | 5219 | if (spec->kctls.list) |
5226 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 5220 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
5227 | 5221 | ||
5228 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 5222 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; |
5229 | 5223 | ||
@@ -10296,8 +10290,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10296 | if (spec->autocfg.dig_in_pin) | 10290 | if (spec->autocfg.dig_in_pin) |
10297 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10291 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10298 | 10292 | ||
10299 | if (spec->kctl_alloc) | 10293 | if (spec->kctls.list) |
10300 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 10294 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
10301 | 10295 | ||
10302 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 10296 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; |
10303 | spec->num_mux_defs = 1; | 10297 | spec->num_mux_defs = 1; |
@@ -11427,8 +11421,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11427 | if (spec->autocfg.dig_out_pin) | 11421 | if (spec->autocfg.dig_out_pin) |
11428 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11422 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11429 | 11423 | ||
11430 | if (spec->kctl_alloc) | 11424 | if (spec->kctls.list) |
11431 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 11425 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
11432 | 11426 | ||
11433 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11427 | if (spec->autocfg.speaker_pins[0] != 0x1d) |
11434 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; | 11428 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; |
@@ -12199,8 +12193,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12199 | if (spec->autocfg.dig_out_pin) | 12193 | if (spec->autocfg.dig_out_pin) |
12200 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12194 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12201 | 12195 | ||
12202 | if (spec->kctl_alloc) | 12196 | if (spec->kctls.list) |
12203 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 12197 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
12204 | 12198 | ||
12205 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | 12199 | /* create a beep mixer control if the pin 0x1d isn't assigned */ |
12206 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | 12200 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) |
@@ -13297,8 +13291,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13297 | if (spec->autocfg.dig_out_pin) | 13291 | if (spec->autocfg.dig_out_pin) |
13298 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13292 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13299 | 13293 | ||
13300 | if (spec->kctl_alloc) | 13294 | if (spec->kctls.list) |
13301 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 13295 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
13302 | 13296 | ||
13303 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 13297 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; |
13304 | 13298 | ||
@@ -14408,8 +14402,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14408 | if (spec->autocfg.dig_out_pin) | 14402 | if (spec->autocfg.dig_out_pin) |
14409 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 14403 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14410 | 14404 | ||
14411 | if (spec->kctl_alloc) | 14405 | if (spec->kctls.list) |
14412 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 14406 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
14413 | 14407 | ||
14414 | spec->init_verbs[spec->num_init_verbs++] | 14408 | spec->init_verbs[spec->num_init_verbs++] |
14415 | = alc861vd_volume_init_verbs; | 14409 | = alc861vd_volume_init_verbs; |
@@ -16235,8 +16229,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16235 | if (spec->autocfg.dig_out_pin) | 16229 | if (spec->autocfg.dig_out_pin) |
16236 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16230 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16237 | 16231 | ||
16238 | if (spec->kctl_alloc) | 16232 | if (spec->kctls.list) |
16239 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 16233 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
16240 | 16234 | ||
16241 | spec->num_mux_defs = 1; | 16235 | spec->num_mux_defs = 1; |
16242 | spec->input_mux = &spec->private_imux; | 16236 | spec->input_mux = &spec->private_imux; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ec88ba881482..579b32817836 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include "hda_patch.h" | 36 | #include "hda_patch.h" |
37 | #include "hda_beep.h" | 37 | #include "hda_beep.h" |
38 | 38 | ||
39 | #define NUM_CONTROL_ALLOC 32 | ||
40 | #define STAC_PWR_EVENT 0x20 | 39 | #define STAC_PWR_EVENT 0x20 |
41 | #define STAC_HP_EVENT 0x30 | 40 | #define STAC_HP_EVENT 0x30 |
42 | #define STAC_VREF_EVENT 0x40 | 41 | #define STAC_VREF_EVENT 0x40 |
@@ -222,8 +221,7 @@ struct sigmatel_spec { | |||
222 | 221 | ||
223 | /* dynamic controls and input_mux */ | 222 | /* dynamic controls and input_mux */ |
224 | struct auto_pin_cfg autocfg; | 223 | struct auto_pin_cfg autocfg; |
225 | unsigned int num_kctl_alloc, num_kctl_used; | 224 | struct snd_array kctls; |
226 | struct snd_kcontrol_new *kctl_alloc; | ||
227 | struct hda_input_mux private_dimux; | 225 | struct hda_input_mux private_dimux; |
228 | struct hda_input_mux private_imux; | 226 | struct hda_input_mux private_imux; |
229 | struct hda_input_mux private_smux; | 227 | struct hda_input_mux private_smux; |
@@ -1237,6 +1235,8 @@ static const char *slave_sws[] = { | |||
1237 | NULL | 1235 | NULL |
1238 | }; | 1236 | }; |
1239 | 1237 | ||
1238 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1239 | |||
1240 | static int stac92xx_build_controls(struct hda_codec *codec) | 1240 | static int stac92xx_build_controls(struct hda_codec *codec) |
1241 | { | 1241 | { |
1242 | struct sigmatel_spec *spec = codec->spec; | 1242 | struct sigmatel_spec *spec = codec->spec; |
@@ -1254,7 +1254,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1254 | } | 1254 | } |
1255 | if (spec->num_dmuxes > 0) { | 1255 | if (spec->num_dmuxes > 0) { |
1256 | stac_dmux_mixer.count = spec->num_dmuxes; | 1256 | stac_dmux_mixer.count = spec->num_dmuxes; |
1257 | err = snd_ctl_add(codec->bus->card, | 1257 | err = snd_hda_ctl_add(codec, |
1258 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1258 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1259 | if (err < 0) | 1259 | if (err < 0) |
1260 | return err; | 1260 | return err; |
@@ -1309,6 +1309,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1309 | return err; | 1309 | return err; |
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1312 | return 0; | 1313 | return 0; |
1313 | } | 1314 | } |
1314 | 1315 | ||
@@ -2596,28 +2597,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, | |||
2596 | { | 2597 | { |
2597 | struct snd_kcontrol_new *knew; | 2598 | struct snd_kcontrol_new *knew; |
2598 | 2599 | ||
2599 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2600 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2600 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2601 | knew = snd_array_new(&spec->kctls); |
2601 | 2602 | if (!knew) | |
2602 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2603 | return -ENOMEM; |
2603 | if (! knew) | ||
2604 | return -ENOMEM; | ||
2605 | if (spec->kctl_alloc) { | ||
2606 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2607 | kfree(spec->kctl_alloc); | ||
2608 | } | ||
2609 | spec->kctl_alloc = knew; | ||
2610 | spec->num_kctl_alloc = num; | ||
2611 | } | ||
2612 | |||
2613 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2614 | *knew = stac92xx_control_templates[type]; | 2604 | *knew = stac92xx_control_templates[type]; |
2615 | knew->index = idx; | 2605 | knew->index = idx; |
2616 | knew->name = kstrdup(name, GFP_KERNEL); | 2606 | knew->name = kstrdup(name, GFP_KERNEL); |
2617 | if (! knew->name) | 2607 | if (! knew->name) |
2618 | return -ENOMEM; | 2608 | return -ENOMEM; |
2619 | knew->private_value = val; | 2609 | knew->private_value = val; |
2620 | spec->num_kctl_used++; | ||
2621 | return 0; | 2610 | return 0; |
2622 | } | 2611 | } |
2623 | 2612 | ||
@@ -3438,8 +3427,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3438 | if (dig_in && spec->autocfg.dig_in_pin) | 3427 | if (dig_in && spec->autocfg.dig_in_pin) |
3439 | spec->dig_in_nid = dig_in; | 3428 | spec->dig_in_nid = dig_in; |
3440 | 3429 | ||
3441 | if (spec->kctl_alloc) | 3430 | if (spec->kctls.list) |
3442 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3431 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3443 | 3432 | ||
3444 | spec->input_mux = &spec->private_imux; | 3433 | spec->input_mux = &spec->private_imux; |
3445 | spec->dinput_mux = &spec->private_dimux; | 3434 | spec->dinput_mux = &spec->private_dimux; |
@@ -3540,8 +3529,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3540 | if (spec->autocfg.dig_in_pin) | 3529 | if (spec->autocfg.dig_in_pin) |
3541 | spec->dig_in_nid = 0x04; | 3530 | spec->dig_in_nid = 0x04; |
3542 | 3531 | ||
3543 | if (spec->kctl_alloc) | 3532 | if (spec->kctls.list) |
3544 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3533 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3545 | 3534 | ||
3546 | spec->input_mux = &spec->private_imux; | 3535 | spec->input_mux = &spec->private_imux; |
3547 | spec->dinput_mux = &spec->private_dimux; | 3536 | spec->dinput_mux = &spec->private_dimux; |
@@ -3708,20 +3697,26 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3708 | return 0; | 3697 | return 0; |
3709 | } | 3698 | } |
3710 | 3699 | ||
3700 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
3701 | { | ||
3702 | struct sigmatel_spec *spec = codec->spec; | ||
3703 | |||
3704 | if (spec->kctls.list) { | ||
3705 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
3706 | int i; | ||
3707 | for (i = 0; i < spec->kctls.used; i++) | ||
3708 | kfree(kctl[i].name); | ||
3709 | } | ||
3710 | snd_array_free(&spec->kctls); | ||
3711 | } | ||
3712 | |||
3711 | static void stac92xx_free(struct hda_codec *codec) | 3713 | static void stac92xx_free(struct hda_codec *codec) |
3712 | { | 3714 | { |
3713 | struct sigmatel_spec *spec = codec->spec; | 3715 | struct sigmatel_spec *spec = codec->spec; |
3714 | int i; | ||
3715 | 3716 | ||
3716 | if (! spec) | 3717 | if (! spec) |
3717 | return; | 3718 | return; |
3718 | 3719 | ||
3719 | if (spec->kctl_alloc) { | ||
3720 | for (i = 0; i < spec->num_kctl_used; i++) | ||
3721 | kfree(spec->kctl_alloc[i].name); | ||
3722 | kfree(spec->kctl_alloc); | ||
3723 | } | ||
3724 | |||
3725 | if (spec->bios_pin_configs) | 3720 | if (spec->bios_pin_configs) |
3726 | kfree(spec->bios_pin_configs); | 3721 | kfree(spec->bios_pin_configs); |
3727 | 3722 | ||
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 | ||