Commit 603c4019 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Use generic array helpers

Use generic array helpers to simplify array handling in snd-hda-intel.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b2e18597
...@@ -756,12 +756,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache, ...@@ -756,12 +756,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache,
{ {
memset(cache, 0, sizeof(*cache)); memset(cache, 0, sizeof(*cache));
memset(cache->hash, 0xff, sizeof(cache->hash)); memset(cache->hash, 0xff, sizeof(cache->hash));
cache->record_size = record_size; snd_array_init(&cache->buf, record_size, 64);
} }
static void free_hda_cache(struct hda_cache_rec *cache) static void free_hda_cache(struct hda_cache_rec *cache)
{ {
kfree(cache->buffer); snd_array_free(&cache->buf);
} }
/* query the hash. allocate an entry if not found. */ /* 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,38 +770,18 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
{ {
u16 idx = key % (u16)ARRAY_SIZE(cache->hash); u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
u16 cur = cache->hash[idx]; u16 cur = cache->hash[idx];
struct hda_cache_head *info_head = cache->buf.list;
struct hda_cache_head *info; struct hda_cache_head *info;
while (cur != 0xffff) { while (cur != 0xffff) {
info = (struct hda_cache_head *)(cache->buffer + info = &info_head[cur];
cur * cache->record_size);
if (info->key == key) if (info->key == key)
return info; return info;
cur = info->next; cur = info->next;
} }
/* add a new hash entry */ /* add a new hash entry */
if (cache->num_entries >= cache->size) { info = snd_array_new(&cache->buf);
/* reallocate the array */
unsigned int new_size = cache->size + 64;
void *new_buffer;
new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL);
if (!new_buffer) {
snd_printk(KERN_ERR "hda_codec: "
"can't malloc amp_info\n");
return NULL;
}
if (cache->buffer) {
memcpy(new_buffer, cache->buffer,
cache->size * cache->record_size);
kfree(cache->buffer);
}
cache->size = new_size;
cache->buffer = new_buffer;
}
cur = cache->num_entries++;
info = (struct hda_cache_head *)(cache->buffer +
cur * cache->record_size);
info->key = key; info->key = key;
info->val = 0; info->val = 0;
info->next = cache->hash[idx]; info->next = cache->hash[idx];
...@@ -942,10 +922,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, ...@@ -942,10 +922,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
/* resume the all amp commands from the cache */ /* resume the all amp commands from the cache */
void snd_hda_codec_resume_amp(struct hda_codec *codec) void snd_hda_codec_resume_amp(struct hda_codec *codec)
{ {
struct hda_amp_info *buffer = codec->amp_cache.buffer; struct hda_amp_info *buffer = codec->amp_cache.buf.list;
int i; int i;
for (i = 0; i < codec->amp_cache.size; i++, buffer++) { for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
u32 key = buffer->head.key; u32 key = buffer->head.key;
hda_nid_t nid; hda_nid_t nid;
unsigned int idx, dir, ch; unsigned int idx, dir, ch;
...@@ -1779,10 +1759,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, ...@@ -1779,10 +1759,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
/* resume the all commands from the cache */ /* resume the all commands from the cache */
void snd_hda_codec_resume_cache(struct hda_codec *codec) void snd_hda_codec_resume_cache(struct hda_codec *codec)
{ {
struct hda_cache_head *buffer = codec->cmd_cache.buffer; struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
int i; int i;
for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
u32 key = buffer->key; u32 key = buffer->key;
if (!key) if (!key)
continue; continue;
......
...@@ -657,10 +657,7 @@ struct hda_amp_info { ...@@ -657,10 +657,7 @@ struct hda_amp_info {
struct hda_cache_rec { struct hda_cache_rec {
u16 hash[64]; /* hash table for index */ u16 hash[64]; /* hash table for index */
unsigned int num_entries; /* number of assigned entries */ struct snd_array buf; /* record entries */
unsigned int size; /* allocated size */
unsigned int record_size; /* record size (including header) */
void *buffer; /* hash table entries */
}; };
/* PCM callbacks */ /* PCM callbacks */
......
...@@ -67,8 +67,7 @@ struct ad198x_spec { ...@@ -67,8 +67,7 @@ struct ad198x_spec {
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used; struct snd_array kctls;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
...@@ -154,6 +153,8 @@ static const char *ad_slave_sws[] = { ...@@ -154,6 +153,8 @@ static const char *ad_slave_sws[] = {
NULL NULL
}; };
static void ad198x_free_kctls(struct hda_codec *codec);
static int ad198x_build_controls(struct hda_codec *codec) static int ad198x_build_controls(struct hda_codec *codec)
{ {
struct ad198x_spec *spec = codec->spec; struct ad198x_spec *spec = codec->spec;
...@@ -202,6 +203,7 @@ static int ad198x_build_controls(struct hda_codec *codec) ...@@ -202,6 +203,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
return err; return err;
} }
ad198x_free_kctls(codec); /* no longer needed */
return 0; return 0;
} }
...@@ -375,16 +377,27 @@ static int ad198x_build_pcms(struct hda_codec *codec) ...@@ -375,16 +377,27 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return 0; return 0;
} }
static void ad198x_free(struct hda_codec *codec) static void ad198x_free_kctls(struct hda_codec *codec)
{ {
struct ad198x_spec *spec = codec->spec; struct ad198x_spec *spec = codec->spec;
unsigned int i;
if (spec->kctl_alloc) { if (spec->kctls.list) {
for (i = 0; i < spec->num_kctl_used; i++) struct snd_kcontrol_new *kctl = spec->kctls.list;
kfree(spec->kctl_alloc[i].name); int i;
kfree(spec->kctl_alloc); for (i = 0; i < spec->kctls.used; i++)
kfree(kctl[i].name);
} }
snd_array_free(&spec->kctls);
}
static void ad198x_free(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
if (!spec)
return;
ad198x_free_kctls(codec);
kfree(codec->spec); kfree(codec->spec);
} }
...@@ -2452,9 +2465,6 @@ static struct hda_amp_list ad1988_loopbacks[] = { ...@@ -2452,9 +2465,6 @@ static struct hda_amp_list ad1988_loopbacks[] = {
* Automatic parse of I/O pins from the BIOS configuration * Automatic parse of I/O pins from the BIOS configuration
*/ */
#define NUM_CONTROL_ALLOC 32
#define NUM_VERB_ALLOC 32
enum { enum {
AD_CTL_WIDGET_VOL, AD_CTL_WIDGET_VOL,
AD_CTL_WIDGET_MUTE, AD_CTL_WIDGET_MUTE,
...@@ -2472,27 +2482,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, ...@@ -2472,27 +2482,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
if (spec->num_kctl_used >= spec->num_kctl_alloc) { snd_array_init(&spec->kctls, sizeof(*knew), 32);
int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; knew = snd_array_new(&spec->kctls);
if (!knew)
knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ return -ENOMEM;
if (! knew)
return -ENOMEM;
if (spec->kctl_alloc) {
memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
kfree(spec->kctl_alloc);
}
spec->kctl_alloc = knew;
spec->num_kctl_alloc = num;
}
knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = ad1988_control_templates[type]; *knew = ad1988_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL); knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name) if (! knew->name)
return -ENOMEM; return -ENOMEM;
knew->private_value = val; knew->private_value = val;
spec->num_kctl_used++;
return 0; return 0;
} }
...@@ -2846,8 +2844,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) ...@@ -2846,8 +2844,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = AD1988_SPDIF_IN; spec->dig_in_nid = AD1988_SPDIF_IN;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
......
...@@ -86,8 +86,6 @@ struct conexant_spec { ...@@ -86,8 +86,6 @@ struct conexant_spec {
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
...@@ -344,15 +342,6 @@ static int conexant_init(struct hda_codec *codec) ...@@ -344,15 +342,6 @@ static int conexant_init(struct hda_codec *codec)
static void conexant_free(struct hda_codec *codec) static void conexant_free(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec;
unsigned int i;
if (spec->kctl_alloc) {
for (i = 0; i < spec->num_kctl_used; i++)
kfree(spec->kctl_alloc[i].name);
kfree(spec->kctl_alloc);
}
kfree(codec->spec); kfree(codec->spec);
} }
......
...@@ -284,8 +284,7 @@ struct alc_spec { ...@@ -284,8 +284,7 @@ struct alc_spec {
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used; struct snd_array kctls;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
...@@ -1590,6 +1589,9 @@ static const char *alc_slave_sws[] = { ...@@ -1590,6 +1589,9 @@ static const char *alc_slave_sws[] = {
/* /*
* build control elements * build control elements
*/ */
static void alc_free_kctls(struct hda_codec *codec);
static int alc_build_controls(struct hda_codec *codec) static int alc_build_controls(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
...@@ -1636,6 +1638,7 @@ static int alc_build_controls(struct hda_codec *codec) ...@@ -1636,6 +1638,7 @@ static int alc_build_controls(struct hda_codec *codec)
return err; return err;
} }
alc_free_kctls(codec); /* no longer needed */
return 0; return 0;
} }
...@@ -2726,19 +2729,27 @@ static int alc_build_pcms(struct hda_codec *codec) ...@@ -2726,19 +2729,27 @@ static int alc_build_pcms(struct hda_codec *codec)
return 0; return 0;
} }
static void alc_free_kctls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
if (spec->kctls.list) {
struct snd_kcontrol_new *kctl = spec->kctls.list;
int i;
for (i = 0; i < spec->kctls.used; i++)
kfree(kctl[i].name);
}
snd_array_free(&spec->kctls);
}
static void alc_free(struct hda_codec *codec) static void alc_free(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
unsigned int i;
if (!spec) if (!spec)
return; return;
if (spec->kctl_alloc) { alc_free_kctls(codec);
for (i = 0; i < spec->num_kctl_used; i++)
kfree(spec->kctl_alloc[i].name);
kfree(spec->kctl_alloc);
}
kfree(spec); kfree(spec);
codec->spec = NULL; /* to be sure */ codec->spec = NULL; /* to be sure */
} }
...@@ -3423,9 +3434,6 @@ static struct alc_config_preset alc880_presets[] = { ...@@ -3423,9 +3434,6 @@ static struct alc_config_preset alc880_presets[] = {
* Automatic parse of I/O pins from the BIOS configuration * Automatic parse of I/O pins from the BIOS configuration
*/ */
#define NUM_CONTROL_ALLOC 32
#define NUM_VERB_ALLOC 32
enum { enum {
ALC_CTL_WIDGET_VOL, ALC_CTL_WIDGET_VOL,
ALC_CTL_WIDGET_MUTE, ALC_CTL_WIDGET_MUTE,
...@@ -3443,29 +3451,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name, ...@@ -3443,29 +3451,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
if (spec->num_kctl_used >= spec->num_kctl_alloc) { snd_array_init(&spec->kctls, sizeof(*knew), 32);
int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; knew = snd_array_new(&spec->kctls);
if (!knew)
/* array + terminator */ return -ENOMEM;
knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
if (!knew)
return -ENOMEM;
if (spec->kctl_alloc) {
memcpy(knew, spec->kctl_alloc,
sizeof(*knew) * spec->num_kctl_alloc);
kfree(spec->kctl_alloc);
}
spec->kctl_alloc = knew;
spec->num_kctl_alloc = num;
}
knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = alc880_control_templates[type]; *knew = alc880_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL); knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name) if (!knew->name)
return -ENOMEM; return -ENOMEM;
knew->private_value = val; knew->private_value = val;
spec->num_kctl_used++;
return 0; return 0;
} }
...@@ -3789,8 +3783,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) ...@@ -3789,8 +3783,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC880_DIGIN_NID; spec->dig_in_nid = ALC880_DIGIN_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
...@@ -5177,7 +5171,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) ...@@ -5177,7 +5171,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0) if (err < 0)
return err; return err;
if (!spec->kctl_alloc) if (!spec->kctls.list)
return 0; /* can't find valid BIOS pin config */ return 0; /* can't find valid BIOS pin config */
err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
if (err < 0) if (err < 0)
...@@ -5187,8 +5181,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) ...@@ -5187,8 +5181,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
...@@ -10256,8 +10250,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec) ...@@ -10256,8 +10250,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC262_DIGIN_NID; spec->dig_in_nid = ALC262_DIGIN_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
...@@ -11387,8 +11381,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec) ...@@ -11387,8 +11381,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
if (spec->autocfg.speaker_pins[0] != 0x1d) if (spec->autocfg.speaker_pins[0] != 0x1d)
spec->mixers[spec->num_mixers++] = alc268_beep_mixer; spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
...@@ -12159,8 +12153,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) ...@@ -12159,8 +12153,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
/* create a beep mixer control if the pin 0x1d isn't assigned */ /* create a beep mixer control if the pin 0x1d isn't assigned */
for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) 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,8 +13251,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
...@@ -14368,8 +14362,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) ...@@ -14368,8 +14362,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] spec->init_verbs[spec->num_init_verbs++]
= alc861vd_volume_init_verbs; = alc861vd_volume_init_verbs;
...@@ -16194,8 +16188,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) ...@@ -16194,8 +16188,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux; spec->input_mux = &spec->private_imux;
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include "hda_patch.h" #include "hda_patch.h"
#include "hda_beep.h" #include "hda_beep.h"
#define NUM_CONTROL_ALLOC 32
#define STAC_PWR_EVENT 0x20 #define STAC_PWR_EVENT 0x20
#define STAC_HP_EVENT 0x30 #define STAC_HP_EVENT 0x30
#define STAC_VREF_EVENT 0x40 #define STAC_VREF_EVENT 0x40
...@@ -218,8 +217,7 @@ struct sigmatel_spec { ...@@ -218,8 +217,7 @@ struct sigmatel_spec {
/* dynamic controls and input_mux */ /* dynamic controls and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used; struct snd_array kctls;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_dimux; struct hda_input_mux private_dimux;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
struct hda_input_mux private_smux; struct hda_input_mux private_smux;
...@@ -1233,6 +1231,8 @@ static const char *slave_sws[] = { ...@@ -1233,6 +1231,8 @@ static const char *slave_sws[] = {
NULL NULL
}; };
static void stac92xx_free_kctls(struct hda_codec *codec);
static int stac92xx_build_controls(struct hda_codec *codec) static int stac92xx_build_controls(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
...@@ -1305,6 +1305,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) ...@@ -1305,6 +1305,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err; return err;
} }
stac92xx_free_kctls(codec); /* no longer needed */
return 0; return 0;
} }
...@@ -2592,28 +2593,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, ...@@ -2592,28 +2593,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
if (spec->num_kctl_used >= spec->num_kctl_alloc) { snd_array_init(&spec->kctls, sizeof(*knew), 32);
int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; knew = snd_array_new(&spec->kctls);
if (!knew)
knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ return -ENOMEM;
if (! knew)
return -ENOMEM;
if (spec->kctl_alloc) {
memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
kfree(spec->kctl_alloc);
}
spec->kctl_alloc = knew;
spec->num_kctl_alloc = num;
}
knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = stac92xx_control_templates[type]; *knew = stac92xx_control_templates[type];
knew->index = idx; knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL); knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name) if (! knew->name)
return -ENOMEM; return -ENOMEM;
knew->private_value = val; knew->private_value = val;
spec->num_kctl_used++;
return 0; return 0;
} }
...@@ -3434,8 +3423,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out ...@@ -3434,8 +3423,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
if (dig_in && spec->autocfg.dig_in_pin) if (dig_in && spec->autocfg.dig_in_pin)
spec->dig_in_nid = dig_in; spec->dig_in_nid = dig_in;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux; spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux; spec->dinput_mux = &spec->private_dimux;
...@@ -3536,8 +3525,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) ...@@ -3536,8 +3525,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = 0x04; spec->dig_in_nid = 0x04;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux; spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux; spec->dinput_mux = &spec->private_dimux;
...@@ -3698,20 +3687,26 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3698,20 +3687,26 @@ static int stac92xx_init(struct hda_codec *codec)
return 0; return 0;
} }
static void stac92xx_free_kctls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
if (spec->kctls.list) {
struct snd_kcontrol_new *kctl = spec->kctls.list;
int i;
for (i = 0; i < spec->kctls.used; i++)
kfree(kctl[i].name);
}
snd_array_free(&spec->kctls);
}
static void stac92xx_free(struct hda_codec *codec) static void stac92xx_free(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
int i;
if (! spec) if (! spec)
return; return;
if (spec->kctl_alloc) {
for (i = 0; i < spec->num_kctl_used; i++)
kfree(spec->kctl_alloc[i].name);
kfree(spec->kctl_alloc);
}
if (spec->bios_pin_configs) if (spec->bios_pin_configs)
kfree(spec->bios_pin_configs); kfree(spec->bios_pin_configs);
......
...@@ -53,9 +53,6 @@ ...@@ -53,9 +53,6 @@
#define AMP_VAL_IDX_SHIFT 19 #define AMP_VAL_IDX_SHIFT 19
#define AMP_VAL_IDX_MASK (0x0f<<19) #define AMP_VAL_IDX_MASK (0x0f<<19)
#define NUM_CONTROL_ALLOC 32
#define NUM_VERB_ALLOC 32
/* Pin Widget NID */ /* Pin Widget NID */
#define VT1708_HP_NID 0x13 #define VT1708_HP_NID 0x13
#define VT1708_DIGOUT_NID 0x14 #define VT1708_DIGOUT_NID 0x14
...@@ -227,8 +224,7 @@ struct via_spec { ...@@ -227,8 +224,7 @@ struct via_spec {
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used; struct snd_array kctls;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux[2]; struct hda_input_mux private_imux[2];
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
...@@ -272,33 +268,31 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, ...@@ -272,33 +268,31 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
if (spec->num_kctl_used >= spec->num_kctl_alloc) { snd_array_init(&spec->kctls, sizeof(*knew), 32);
int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; knew = snd_array_new(&spec->kctls);
if (!knew)
/* array + terminator */ return -ENOMEM;
knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
if (!knew)
return -ENOMEM;
if (spec->kctl_alloc) {
memcpy(knew, spec->kctl_alloc,
sizeof(*knew) * spec->num_kctl_alloc);
kfree(spec->kctl_alloc);
}
spec->kctl_alloc = knew;
spec->num_kctl_alloc = num;
}
knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = vt1708_control_templates[type]; *knew = vt1708_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL); knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name) if (!knew->name)
return -ENOMEM; return -ENOMEM;
knew->private_value = val; knew->private_value = val;
spec->num_kctl_used++;
return 0; return 0;
} }
static void via_free_kctls(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
if (spec->kctls.list) {
struct snd_kcontrol_new *kctl = spec->kctls.list;
int i;
for (i = 0; i < spec->kctls.used; i++)
kfree(kctl[i].name);
}
snd_array_free(&spec->kctls);
}
/* create input playback/capture controls for the given pin */ /* create input playback/capture controls for the given pin */
static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
const char *ctlname, int idx, int mix_nid) const char *ctlname, int idx, int mix_nid)
...@@ -896,6 +890,7 @@ static int via_build_controls(struct hda_codec *codec) ...@@ -896,6 +890,7 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
} }
via_free_kctls(codec); /* no longer needed */
return 0; return 0;
} }
...@@ -941,17 +936,11 @@ static int via_build_pcms(struct hda_codec *codec) ...@@ -941,17 +936,11 @@ static int via_build_pcms(struct hda_codec *codec)
static void via_free(struct hda_codec *codec) static void via_free(struct hda_codec *codec)
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
unsigned int i;
if (!spec) if (!spec)
return; return;
if (spec->kctl_alloc) { via_free_kctls(codec);
for (i = 0; i < spec->num_kctl_used; i++)
kfree(spec->kctl_alloc[i].name);
kfree(spec->kctl_alloc);
}
kfree(codec->spec); kfree(codec->spec);
} }
...@@ -1373,8 +1362,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) ...@@ -1373,8 +1362,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708_DIGIN_NID; spec->dig_in_nid = VT1708_DIGIN_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
...@@ -1846,8 +1835,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) ...@@ -1846,8 +1835,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1709_DIGIN_NID; spec->dig_in_nid = VT1709_DIGIN_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
...@@ -2390,8 +2379,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) ...@@ -2390,8 +2379,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708B_DIGIN_NID; spec->dig_in_nid = VT1708B_DIGIN_NID;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
...@@ -2855,8 +2844,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) ...@@ -2855,8 +2844,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x15; spec->extra_dig_out_nid = 0x15;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
...@@ -3174,8 +3163,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) ...@@ -3174,8 +3163,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x1B; spec->extra_dig_out_nid = 0x1B;
if (spec->kctl_alloc) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment