summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,
{
memset(cache, 0, sizeof(*cache));
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)
{
- kfree(cache->buffer);
+ snd_array_free(&cache->buf);
}
/* 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,
{
u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
u16 cur = cache->hash[idx];
+ struct hda_cache_head *info_head = cache->buf.list;
struct hda_cache_head *info;
while (cur != 0xffff) {
- info = (struct hda_cache_head *)(cache->buffer +
- cur * cache->record_size);
+ info = &info_head[cur];
if (info->key == key)
return info;
cur = info->next;
}
/* add a new hash entry */
- if (cache->num_entries >= cache->size) {
- /* 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 = snd_array_new(&cache->buf);
info->key = key;
info->val = 0;
info->next = cache->hash[idx];
@@ -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 */
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;
- 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;
hda_nid_t nid;
unsigned int idx, dir, ch;
@@ -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 */
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;
- 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;
if (!key)
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 {
struct hda_cache_rec {
u16 hash[64]; /* hash table for index */
- unsigned int num_entries; /* number of assigned entries */
- unsigned int size; /* allocated size */
- unsigned int record_size; /* record size (including header) */
- void *buffer; /* hash table entries */
+ struct snd_array buf; /* record entries */
};
/* 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 {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -154,6 +153,8 @@ static const char *ad_slave_sws[] = {
NULL
};
+static void ad198x_free_kctls(struct hda_codec *codec);
+
static int ad198x_build_controls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -202,6 +203,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
return err;
}
+ ad198x_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -375,16 +377,27 @@ static int ad198x_build_pcms(struct hda_codec *codec)
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;
- 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);
+ 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 ad198x_free(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+
+ if (!spec)
+ return;
+
+ ad198x_free_kctls(codec);
kfree(codec->spec);
}
@@ -2452,9 +2465,6 @@ static struct hda_amp_list ad1988_loopbacks[] = {
* Automatic parse of I/O pins from the BIOS configuration
*/
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
enum {
AD_CTL_WIDGET_VOL,
AD_CTL_WIDGET_MUTE,
@@ -2472,27 +2482,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
- 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];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = ad1988_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
@@ -2846,8 +2844,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = AD1988_SPDIF_IN;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
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 {
/* dynamic controls, init_verbs and input_mux */
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;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -344,15 +342,6 @@ static int conexant_init(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);
}
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 {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -1590,6 +1589,9 @@ static const char *alc_slave_sws[] = {
/*
* build control elements
*/
+
+static void alc_free_kctls(struct hda_codec *codec);
+
static int alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -1636,6 +1638,7 @@ static int alc_build_controls(struct hda_codec *codec)
return err;
}
+ alc_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -2726,19 +2729,27 @@ static int alc_build_pcms(struct hda_codec *codec)
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)
{
struct alc_spec *spec = codec->spec;
- unsigned int i;
if (!spec)
return;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
+ alc_free_kctls(codec);
kfree(spec);
codec->spec = NULL; /* to be sure */
}
@@ -3423,9 +3434,6 @@ static struct alc_config_preset alc880_presets[] = {
* Automatic parse of I/O pins from the BIOS configuration
*/
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
enum {
ALC_CTL_WIDGET_VOL,
ALC_CTL_WIDGET_MUTE,
@@ -3443,29 +3451,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- /* array + terminator */
- 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];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = alc880_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
@@ -3789,8 +3783,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC880_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
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)
err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
- if (!spec->kctl_alloc)
+ if (!spec->kctls.list)
return 0; /* can't find valid BIOS pin config */
err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
if (err < 0)
@@ -5187,8 +5181,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
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)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC262_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
spec->num_mux_defs = 1;
@@ -11387,8 +11381,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
if (spec->autocfg.speaker_pins[0] != 0x1d)
spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
@@ -12159,8 +12153,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
/* create a beep mixer control if the pin 0x1d isn't assigned */
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)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
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)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++]
= alc861vd_volume_init_verbs;
@@ -16194,8 +16188,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->num_mux_defs = 1;
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 @@
#include "hda_patch.h"
#include "hda_beep.h"
-#define NUM_CONTROL_ALLOC 32
#define STAC_PWR_EVENT 0x20
#define STAC_HP_EVENT 0x30
#define STAC_VREF_EVENT 0x40
@@ -218,8 +217,7 @@ struct sigmatel_spec {
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_dimux;
struct hda_input_mux private_imux;
struct hda_input_mux private_smux;
@@ -1233,6 +1231,8 @@ static const char *slave_sws[] = {
NULL
};
+static void stac92xx_free_kctls(struct hda_codec *codec);
+
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
@@ -1305,6 +1305,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err;
}
+ stac92xx_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -2592,28 +2593,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
- 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];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = stac92xx_control_templates[type];
knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
@@ -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)
spec->dig_in_nid = dig_in;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3536,8 +3525,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = 0x04;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3698,20 +3687,26 @@ static int stac92xx_init(struct hda_codec *codec)
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)
{
struct sigmatel_spec *spec = codec->spec;
- int i;
if (! spec)
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)
kfree(spec->bios_pin_configs);
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 @@
#define AMP_VAL_IDX_SHIFT 19
#define AMP_VAL_IDX_MASK (0x0f<<19)
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
/* Pin Widget NID */
#define VT1708_HP_NID 0x13
#define VT1708_DIGOUT_NID 0x14
@@ -227,8 +224,7 @@ struct via_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_imux[2];
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,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- /* array + terminator */
- 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];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = vt1708_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
-
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
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 */
static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
const char *ctlname, int idx, int mix_nid)
@@ -896,6 +890,7 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
+ via_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -941,17 +936,11 @@ static int via_build_pcms(struct hda_codec *codec)
static void via_free(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
- unsigned int i;
if (!spec)
return;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
-
+ via_free_kctls(codec);
kfree(codec->spec);
}
@@ -1373,8 +1362,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
@@ -1846,8 +1835,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1709_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -2390,8 +2379,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708B_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -2855,8 +2844,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x15;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -3174,8 +3163,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x1B;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
OpenPOWER on IntegriCloud