aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c55
1 files changed, 25 insertions, 30 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index c5906551311..3db39adad79 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