diff options
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r-- | sound/pci/hda/patch_via.c | 71 |
1 files changed, 30 insertions, 41 deletions
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 | ||