aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-07-30 09:01:44 -0400
committerTakashi Iwai <tiwai@suse.de>2008-10-12 20:42:59 -0400
commit603c40199252f0c3b91fca02fd3283c4f8e55179 (patch)
treedbd8643b288a1d3088d6f5af30e58d699e2761b4 /sound/pci/hda
parentb2e1859745b783922533d29e3b03af29378a23f0 (diff)
ALSA: hda - Use generic array helpers
Use generic array helpers to simplify array handling in snd-hda-intel. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c38
-rw-r--r--sound/pci/hda/hda_codec.h5
-rw-r--r--sound/pci/hda/patch_analog.c56
-rw-r--r--sound/pci/hda/patch_conexant.c11
-rw-r--r--sound/pci/hda/patch_realtek.c86
-rw-r--r--sound/pci/hda/patch_sigmatel.c55
-rw-r--r--sound/pci/hda/patch_via.c71
7 files changed, 132 insertions, 190 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e70303183c3c..39a49d4a864a 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -756,12 +756,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache,
756{ 756{
757 memset(cache, 0, sizeof(*cache)); 757 memset(cache, 0, sizeof(*cache));
758 memset(cache->hash, 0xff, sizeof(cache->hash)); 758 memset(cache->hash, 0xff, sizeof(cache->hash));
759 cache->record_size = record_size; 759 snd_array_init(&cache->buf, record_size, 64);
760} 760}
761 761
762static void free_hda_cache(struct hda_cache_rec *cache) 762static void free_hda_cache(struct hda_cache_rec *cache)
763{ 763{
764 kfree(cache->buffer); 764 snd_array_free(&cache->buf);
765} 765}
766 766
767/* query the hash. allocate an entry if not found. */ 767/* query the hash. allocate an entry if not found. */
@@ -770,38 +770,18 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
770{ 770{
771 u16 idx = key % (u16)ARRAY_SIZE(cache->hash); 771 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
772 u16 cur = cache->hash[idx]; 772 u16 cur = cache->hash[idx];
773 struct hda_cache_head *info_head = cache->buf.list;
773 struct hda_cache_head *info; 774 struct hda_cache_head *info;
774 775
775 while (cur != 0xffff) { 776 while (cur != 0xffff) {
776 info = (struct hda_cache_head *)(cache->buffer + 777 info = &info_head[cur];
777 cur * cache->record_size);
778 if (info->key == key) 778 if (info->key == key)
779 return info; 779 return info;
780 cur = info->next; 780 cur = info->next;
781 } 781 }
782 782
783 /* add a new hash entry */ 783 /* add a new hash entry */
784 if (cache->num_entries >= cache->size) { 784 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; 785 info->key = key;
806 info->val = 0; 786 info->val = 0;
807 info->next = cache->hash[idx]; 787 info->next = cache->hash[idx];
@@ -942,10 +922,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
942/* resume the all amp commands from the cache */ 922/* resume the all amp commands from the cache */
943void snd_hda_codec_resume_amp(struct hda_codec *codec) 923void snd_hda_codec_resume_amp(struct hda_codec *codec)
944{ 924{
945 struct hda_amp_info *buffer = codec->amp_cache.buffer; 925 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
946 int i; 926 int i;
947 927
948 for (i = 0; i < codec->amp_cache.size; i++, buffer++) { 928 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
949 u32 key = buffer->head.key; 929 u32 key = buffer->head.key;
950 hda_nid_t nid; 930 hda_nid_t nid;
951 unsigned int idx, dir, ch; 931 unsigned int idx, dir, ch;
@@ -1779,10 +1759,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
1779/* resume the all commands from the cache */ 1759/* resume the all commands from the cache */
1780void snd_hda_codec_resume_cache(struct hda_codec *codec) 1760void snd_hda_codec_resume_cache(struct hda_codec *codec)
1781{ 1761{
1782 struct hda_cache_head *buffer = codec->cmd_cache.buffer; 1762 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
1783 int i; 1763 int i;
1784 1764
1785 for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { 1765 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
1786 u32 key = buffer->key; 1766 u32 key = buffer->key;
1787 if (!key) 1767 if (!key)
1788 continue; 1768 continue;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index b9b21766b730..77064b0cb821 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -657,10 +657,7 @@ struct hda_amp_info {
657 657
658struct hda_cache_rec { 658struct hda_cache_rec {
659 u16 hash[64]; /* hash table for index */ 659 u16 hash[64]; /* hash table for index */
660 unsigned int num_entries; /* number of assigned entries */ 660 struct snd_array buf; /* record entries */
661 unsigned int size; /* allocated size */
662 unsigned int record_size; /* record size (including header) */
663 void *buffer; /* hash table entries */
664}; 661};
665 662
666/* PCM callbacks */ 663/* PCM callbacks */
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
156static void ad198x_free_kctls(struct hda_codec *codec);
157
157static int ad198x_build_controls(struct hda_codec *codec) 158static 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
378static void ad198x_free(struct hda_codec *codec) 380static 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
393static 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
2458enum { 2468enum {
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
345static void conexant_free(struct hda_codec *codec) 343static 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 0b6e682c46d0..3e21a7198656 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
@@ -1590,6 +1589,9 @@ static const char *alc_slave_sws[] = {
1590/* 1589/*
1591 * build control elements 1590 * build control elements
1592 */ 1591 */
1592
1593static void alc_free_kctls(struct hda_codec *codec);
1594
1593static int alc_build_controls(struct hda_codec *codec) 1595static int alc_build_controls(struct hda_codec *codec)
1594{ 1596{
1595 struct alc_spec *spec = codec->spec; 1597 struct alc_spec *spec = codec->spec;
@@ -1636,6 +1638,7 @@ static int alc_build_controls(struct hda_codec *codec)
1636 return err; 1638 return err;
1637 } 1639 }
1638 1640
1641 alc_free_kctls(codec); /* no longer needed */
1639 return 0; 1642 return 0;
1640} 1643}
1641 1644
@@ -2726,19 +2729,27 @@ static int alc_build_pcms(struct hda_codec *codec)
2726 return 0; 2729 return 0;
2727} 2730}
2728 2731
2732static void alc_free_kctls(struct hda_codec *codec)
2733{
2734 struct alc_spec *spec = codec->spec;
2735
2736 if (spec->kctls.list) {
2737 struct snd_kcontrol_new *kctl = spec->kctls.list;
2738 int i;
2739 for (i = 0; i < spec->kctls.used; i++)
2740 kfree(kctl[i].name);
2741 }
2742 snd_array_free(&spec->kctls);
2743}
2744
2729static void alc_free(struct hda_codec *codec) 2745static void alc_free(struct hda_codec *codec)
2730{ 2746{
2731 struct alc_spec *spec = codec->spec; 2747 struct alc_spec *spec = codec->spec;
2732 unsigned int i;
2733 2748
2734 if (!spec) 2749 if (!spec)
2735 return; 2750 return;
2736 2751
2737 if (spec->kctl_alloc) { 2752 alc_free_kctls(codec);
2738 for (i = 0; i < spec->num_kctl_used; i++)
2739 kfree(spec->kctl_alloc[i].name);
2740 kfree(spec->kctl_alloc);
2741 }
2742 kfree(spec); 2753 kfree(spec);
2743 codec->spec = NULL; /* to be sure */ 2754 codec->spec = NULL; /* to be sure */
2744} 2755}
@@ -3423,9 +3434,6 @@ static struct alc_config_preset alc880_presets[] = {
3423 * Automatic parse of I/O pins from the BIOS configuration 3434 * Automatic parse of I/O pins from the BIOS configuration
3424 */ 3435 */
3425 3436
3426#define NUM_CONTROL_ALLOC 32
3427#define NUM_VERB_ALLOC 32
3428
3429enum { 3437enum {
3430 ALC_CTL_WIDGET_VOL, 3438 ALC_CTL_WIDGET_VOL,
3431 ALC_CTL_WIDGET_MUTE, 3439 ALC_CTL_WIDGET_MUTE,
@@ -3443,29 +3451,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
3443{ 3451{
3444 struct snd_kcontrol_new *knew; 3452 struct snd_kcontrol_new *knew;
3445 3453
3446 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 3454 snd_array_init(&spec->kctls, sizeof(*knew), 32);
3447 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 3455 knew = snd_array_new(&spec->kctls);
3448 3456 if (!knew)
3449 /* array + terminator */ 3457 return -ENOMEM;
3450 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
3451 if (!knew)
3452 return -ENOMEM;
3453 if (spec->kctl_alloc) {
3454 memcpy(knew, spec->kctl_alloc,
3455 sizeof(*knew) * spec->num_kctl_alloc);
3456 kfree(spec->kctl_alloc);
3457 }
3458 spec->kctl_alloc = knew;
3459 spec->num_kctl_alloc = num;
3460 }
3461
3462 knew = &spec->kctl_alloc[spec->num_kctl_used];
3463 *knew = alc880_control_templates[type]; 3458 *knew = alc880_control_templates[type];
3464 knew->name = kstrdup(name, GFP_KERNEL); 3459 knew->name = kstrdup(name, GFP_KERNEL);
3465 if (!knew->name) 3460 if (!knew->name)
3466 return -ENOMEM; 3461 return -ENOMEM;
3467 knew->private_value = val; 3462 knew->private_value = val;
3468 spec->num_kctl_used++;
3469 return 0; 3463 return 0;
3470} 3464}
3471 3465
@@ -3789,8 +3783,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
3789 if (spec->autocfg.dig_in_pin) 3783 if (spec->autocfg.dig_in_pin)
3790 spec->dig_in_nid = ALC880_DIGIN_NID; 3784 spec->dig_in_nid = ALC880_DIGIN_NID;
3791 3785
3792 if (spec->kctl_alloc) 3786 if (spec->kctls.list)
3793 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3787 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3794 3788
3795 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; 3789 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
3796 3790
@@ -5177,7 +5171,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
5177 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); 5171 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
5178 if (err < 0) 5172 if (err < 0)
5179 return err; 5173 return err;
5180 if (!spec->kctl_alloc) 5174 if (!spec->kctls.list)
5181 return 0; /* can't find valid BIOS pin config */ 5175 return 0; /* can't find valid BIOS pin config */
5182 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); 5176 err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
5183 if (err < 0) 5177 if (err < 0)
@@ -5187,8 +5181,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
5187 5181
5188 if (spec->autocfg.dig_out_pin) 5182 if (spec->autocfg.dig_out_pin)
5189 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; 5183 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
5190 if (spec->kctl_alloc) 5184 if (spec->kctls.list)
5191 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 5185 spec->mixers[spec->num_mixers++] = spec->kctls.list;
5192 5186
5193 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; 5187 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
5194 5188
@@ -10256,8 +10250,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
10256 if (spec->autocfg.dig_in_pin) 10250 if (spec->autocfg.dig_in_pin)
10257 spec->dig_in_nid = ALC262_DIGIN_NID; 10251 spec->dig_in_nid = ALC262_DIGIN_NID;
10258 10252
10259 if (spec->kctl_alloc) 10253 if (spec->kctls.list)
10260 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 10254 spec->mixers[spec->num_mixers++] = spec->kctls.list;
10261 10255
10262 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; 10256 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
10263 spec->num_mux_defs = 1; 10257 spec->num_mux_defs = 1;
@@ -11387,8 +11381,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
11387 if (spec->autocfg.dig_out_pin) 11381 if (spec->autocfg.dig_out_pin)
11388 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; 11382 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
11389 11383
11390 if (spec->kctl_alloc) 11384 if (spec->kctls.list)
11391 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 11385 spec->mixers[spec->num_mixers++] = spec->kctls.list;
11392 11386
11393 if (spec->autocfg.speaker_pins[0] != 0x1d) 11387 if (spec->autocfg.speaker_pins[0] != 0x1d)
11394 spec->mixers[spec->num_mixers++] = alc268_beep_mixer; 11388 spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
@@ -12159,8 +12153,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
12159 if (spec->autocfg.dig_out_pin) 12153 if (spec->autocfg.dig_out_pin)
12160 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; 12154 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
12161 12155
12162 if (spec->kctl_alloc) 12156 if (spec->kctls.list)
12163 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 12157 spec->mixers[spec->num_mixers++] = spec->kctls.list;
12164 12158
12165 /* create a beep mixer control if the pin 0x1d isn't assigned */ 12159 /* create a beep mixer control if the pin 0x1d isn't assigned */
12166 for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) 12160 for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++)
@@ -13257,8 +13251,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
13257 if (spec->autocfg.dig_out_pin) 13251 if (spec->autocfg.dig_out_pin)
13258 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; 13252 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
13259 13253
13260 if (spec->kctl_alloc) 13254 if (spec->kctls.list)
13261 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 13255 spec->mixers[spec->num_mixers++] = spec->kctls.list;
13262 13256
13263 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; 13257 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
13264 13258
@@ -14368,8 +14362,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
14368 if (spec->autocfg.dig_out_pin) 14362 if (spec->autocfg.dig_out_pin)
14369 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; 14363 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
14370 14364
14371 if (spec->kctl_alloc) 14365 if (spec->kctls.list)
14372 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 14366 spec->mixers[spec->num_mixers++] = spec->kctls.list;
14373 14367
14374 spec->init_verbs[spec->num_init_verbs++] 14368 spec->init_verbs[spec->num_init_verbs++]
14375 = alc861vd_volume_init_verbs; 14369 = alc861vd_volume_init_verbs;
@@ -16194,8 +16188,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
16194 if (spec->autocfg.dig_out_pin) 16188 if (spec->autocfg.dig_out_pin)
16195 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 16189 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
16196 16190
16197 if (spec->kctl_alloc) 16191 if (spec->kctls.list)
16198 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 16192 spec->mixers[spec->num_mixers++] = spec->kctls.list;
16199 16193
16200 spec->num_mux_defs = 1; 16194 spec->num_mux_defs = 1;
16201 spec->input_mux = &spec->private_imux; 16195 spec->input_mux = &spec->private_imux;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index c59065513118..3db39adad79a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -35,7 +35,6 @@
35#include "hda_patch.h" 35#include "hda_patch.h"
36#include "hda_beep.h" 36#include "hda_beep.h"
37 37
38#define NUM_CONTROL_ALLOC 32
39#define STAC_PWR_EVENT 0x20 38#define STAC_PWR_EVENT 0x20
40#define STAC_HP_EVENT 0x30 39#define STAC_HP_EVENT 0x30
41#define STAC_VREF_EVENT 0x40 40#define STAC_VREF_EVENT 0x40
@@ -218,8 +217,7 @@ struct sigmatel_spec {
218 217
219 /* dynamic controls and input_mux */ 218 /* dynamic controls and input_mux */
220 struct auto_pin_cfg autocfg; 219 struct auto_pin_cfg autocfg;
221 unsigned int num_kctl_alloc, num_kctl_used; 220 struct snd_array kctls;
222 struct snd_kcontrol_new *kctl_alloc;
223 struct hda_input_mux private_dimux; 221 struct hda_input_mux private_dimux;
224 struct hda_input_mux private_imux; 222 struct hda_input_mux private_imux;
225 struct hda_input_mux private_smux; 223 struct hda_input_mux private_smux;
@@ -1233,6 +1231,8 @@ static const char *slave_sws[] = {
1233 NULL 1231 NULL
1234}; 1232};
1235 1233
1234static void stac92xx_free_kctls(struct hda_codec *codec);
1235
1236static int stac92xx_build_controls(struct hda_codec *codec) 1236static int stac92xx_build_controls(struct hda_codec *codec)
1237{ 1237{
1238 struct sigmatel_spec *spec = codec->spec; 1238 struct sigmatel_spec *spec = codec->spec;
@@ -1305,6 +1305,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1305 return err; 1305 return err;
1306 } 1306 }
1307 1307
1308 stac92xx_free_kctls(codec); /* no longer needed */
1308 return 0; 1309 return 0;
1309} 1310}
1310 1311
@@ -2592,28 +2593,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
2592{ 2593{
2593 struct snd_kcontrol_new *knew; 2594 struct snd_kcontrol_new *knew;
2594 2595
2595 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 2596 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2596 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 2597 knew = snd_array_new(&spec->kctls);
2597 2598 if (!knew)
2598 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ 2599 return -ENOMEM;
2599 if (! knew)
2600 return -ENOMEM;
2601 if (spec->kctl_alloc) {
2602 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
2603 kfree(spec->kctl_alloc);
2604 }
2605 spec->kctl_alloc = knew;
2606 spec->num_kctl_alloc = num;
2607 }
2608
2609 knew = &spec->kctl_alloc[spec->num_kctl_used];
2610 *knew = stac92xx_control_templates[type]; 2600 *knew = stac92xx_control_templates[type];
2611 knew->index = idx; 2601 knew->index = idx;
2612 knew->name = kstrdup(name, GFP_KERNEL); 2602 knew->name = kstrdup(name, GFP_KERNEL);
2613 if (! knew->name) 2603 if (! knew->name)
2614 return -ENOMEM; 2604 return -ENOMEM;
2615 knew->private_value = val; 2605 knew->private_value = val;
2616 spec->num_kctl_used++;
2617 return 0; 2606 return 0;
2618} 2607}
2619 2608
@@ -3434,8 +3423,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
3434 if (dig_in && spec->autocfg.dig_in_pin) 3423 if (dig_in && spec->autocfg.dig_in_pin)
3435 spec->dig_in_nid = dig_in; 3424 spec->dig_in_nid = dig_in;
3436 3425
3437 if (spec->kctl_alloc) 3426 if (spec->kctls.list)
3438 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3427 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3439 3428
3440 spec->input_mux = &spec->private_imux; 3429 spec->input_mux = &spec->private_imux;
3441 spec->dinput_mux = &spec->private_dimux; 3430 spec->dinput_mux = &spec->private_dimux;
@@ -3536,8 +3525,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
3536 if (spec->autocfg.dig_in_pin) 3525 if (spec->autocfg.dig_in_pin)
3537 spec->dig_in_nid = 0x04; 3526 spec->dig_in_nid = 0x04;
3538 3527
3539 if (spec->kctl_alloc) 3528 if (spec->kctls.list)
3540 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3529 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3541 3530
3542 spec->input_mux = &spec->private_imux; 3531 spec->input_mux = &spec->private_imux;
3543 spec->dinput_mux = &spec->private_dimux; 3532 spec->dinput_mux = &spec->private_dimux;
@@ -3698,20 +3687,26 @@ static int stac92xx_init(struct hda_codec *codec)
3698 return 0; 3687 return 0;
3699} 3688}
3700 3689
3690static void stac92xx_free_kctls(struct hda_codec *codec)
3691{
3692 struct sigmatel_spec *spec = codec->spec;
3693
3694 if (spec->kctls.list) {
3695 struct snd_kcontrol_new *kctl = spec->kctls.list;
3696 int i;
3697 for (i = 0; i < spec->kctls.used; i++)
3698 kfree(kctl[i].name);
3699 }
3700 snd_array_free(&spec->kctls);
3701}
3702
3701static void stac92xx_free(struct hda_codec *codec) 3703static void stac92xx_free(struct hda_codec *codec)
3702{ 3704{
3703 struct sigmatel_spec *spec = codec->spec; 3705 struct sigmatel_spec *spec = codec->spec;
3704 int i;
3705 3706
3706 if (! spec) 3707 if (! spec)
3707 return; 3708 return;
3708 3709
3709 if (spec->kctl_alloc) {
3710 for (i = 0; i < spec->num_kctl_used; i++)
3711 kfree(spec->kctl_alloc[i].name);
3712 kfree(spec->kctl_alloc);
3713 }
3714
3715 if (spec->bios_pin_configs) 3710 if (spec->bios_pin_configs)
3716 kfree(spec->bios_pin_configs); 3711 kfree(spec->bios_pin_configs);
3717 3712
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
283static 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 */
303static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, 297static 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)
941static void via_free(struct hda_codec *codec) 936static 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