aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-05-07 11:17:32 -0400
committerTakashi Iwai <tiwai@suse.de>2012-05-08 12:01:33 -0400
commit23d30f28275ddd7fdb87f265e9a440baf4a4cf09 (patch)
tree7a17854761b905a78a0c24978e701a6ae9d0d768 /sound/pci
parent5536c6d69376273d5210ce05b7d5d462f0dff9d6 (diff)
ALSA: hda - Move up the fixup helper functions to the library module
Move the fixup helper functions in patch_realtek.c to hda_auto_parser.c so that they can be used in other codec drivers like patch_conexant.c. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_auto_parser.c163
-rw-r--r--sound/pci/hda/hda_auto_parser.h80
-rw-r--r--sound/pci/hda/patch_conexant.c62
-rw-r--r--sound/pci/hda/patch_realtek.c244
5 files changed, 309 insertions, 242 deletions
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index ace157cc3d15..bd4149f1aaf4 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,6 +1,6 @@
1snd-hda-intel-objs := hda_intel.o 1snd-hda-intel-objs := hda_intel.o
2 2
3snd-hda-codec-y := hda_codec.o hda_jack.o 3snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o
4snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o 4snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
5snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o 5snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
6snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o 6snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
new file mode 100644
index 000000000000..7cc3a1688240
--- /dev/null
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -0,0 +1,163 @@
1/*
2 * BIOS auto-parser helper functions for HD-audio
3 *
4 * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
5 *
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/slab.h>
13#include <linux/export.h>
14#include <sound/core.h>
15#include "hda_codec.h"
16#include "hda_auto_parser.h"
17
18#define SFX "hda_codec: "
19
20int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
21 const struct hda_verb *list)
22{
23 const struct hda_verb **v;
24 snd_array_init(&spec->verbs, sizeof(struct hda_verb *), 8);
25 v = snd_array_new(&spec->verbs);
26 if (!v)
27 return -ENOMEM;
28 *v = list;
29 return 0;
30}
31EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs);
32
33void snd_hda_gen_apply_verbs(struct hda_codec *codec)
34{
35 struct hda_gen_spec *spec = codec->spec;
36 int i;
37 for (i = 0; i < spec->verbs.used; i++) {
38 struct hda_verb **v = snd_array_elem(&spec->verbs, i);
39 snd_hda_sequence_write(codec, *v);
40 }
41}
42EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs);
43
44void snd_hda_apply_pincfgs(struct hda_codec *codec,
45 const struct hda_pintbl *cfg)
46{
47 for (; cfg->nid; cfg++)
48 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
49}
50EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);
51
52void snd_hda_apply_fixup(struct hda_codec *codec, int action)
53{
54 struct hda_gen_spec *spec = codec->spec;
55 int id = spec->fixup_id;
56#ifdef CONFIG_SND_DEBUG_VERBOSE
57 const char *modelname = spec->fixup_name;
58#endif
59 int depth = 0;
60
61 if (!spec->fixup_list)
62 return;
63
64 while (id >= 0) {
65 const struct hda_fixup *fix = spec->fixup_list + id;
66
67 switch (fix->type) {
68 case HDA_FIXUP_PINS:
69 if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
70 break;
71 snd_printdd(KERN_INFO SFX
72 "%s: Apply pincfg for %s\n",
73 codec->chip_name, modelname);
74 snd_hda_apply_pincfgs(codec, fix->v.pins);
75 break;
76 case HDA_FIXUP_VERBS:
77 if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
78 break;
79 snd_printdd(KERN_INFO SFX
80 "%s: Apply fix-verbs for %s\n",
81 codec->chip_name, modelname);
82 snd_hda_gen_add_verbs(codec->spec, fix->v.verbs);
83 break;
84 case HDA_FIXUP_FUNC:
85 if (!fix->v.func)
86 break;
87 snd_printdd(KERN_INFO SFX
88 "%s: Apply fix-func for %s\n",
89 codec->chip_name, modelname);
90 fix->v.func(codec, fix, action);
91 break;
92 default:
93 snd_printk(KERN_ERR SFX
94 "%s: Invalid fixup type %d\n",
95 codec->chip_name, fix->type);
96 break;
97 }
98 if (!fix->chained)
99 break;
100 if (++depth > 10)
101 break;
102 id = fix->chain_id;
103 }
104}
105EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);
106
107void snd_hda_pick_fixup(struct hda_codec *codec,
108 const struct hda_model_fixup *models,
109 const struct snd_pci_quirk *quirk,
110 const struct hda_fixup *fixlist)
111{
112 struct hda_gen_spec *spec = codec->spec;
113 const struct snd_pci_quirk *q;
114 int id = -1;
115 const char *name = NULL;
116
117 /* when model=nofixup is given, don't pick up any fixups */
118 if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
119 spec->fixup_list = NULL;
120 spec->fixup_id = -1;
121 return;
122 }
123
124 if (codec->modelname && models) {
125 while (models->name) {
126 if (!strcmp(codec->modelname, models->name)) {
127 id = models->id;
128 name = models->name;
129 break;
130 }
131 models++;
132 }
133 }
134 if (id < 0) {
135 q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
136 if (q) {
137 id = q->value;
138#ifdef CONFIG_SND_DEBUG_VERBOSE
139 name = q->name;
140#endif
141 }
142 }
143 if (id < 0) {
144 for (q = quirk; q->subvendor; q++) {
145 unsigned int vendorid =
146 q->subdevice | (q->subvendor << 16);
147 if (vendorid == codec->subsystem_id) {
148 id = q->value;
149#ifdef CONFIG_SND_DEBUG_VERBOSE
150 name = q->name;
151#endif
152 break;
153 }
154 }
155 }
156
157 spec->fixup_id = id;
158 if (id >= 0) {
159 spec->fixup_list = fixlist;
160 spec->fixup_name = name;
161 }
162}
163EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h
new file mode 100644
index 000000000000..9fe4f5d245ad
--- /dev/null
+++ b/sound/pci/hda/hda_auto_parser.h
@@ -0,0 +1,80 @@
1/*
2 * BIOS auto-parser helper functions for HD-audio
3 *
4 * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
5 *
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __SOUND_HDA_AUTO_PARSER_H
13#define __SOUND_HDA_AUTO_PARSER_H
14
15struct hda_gen_spec {
16 /* fix-up list */
17 int fixup_id;
18 const struct hda_fixup *fixup_list;
19 const char *fixup_name;
20
21 /* additional init verbs */
22 struct snd_array verbs;
23};
24
25
26/*
27 * Fix-up pin default configurations and add default verbs
28 */
29
30struct hda_pintbl {
31 hda_nid_t nid;
32 u32 val;
33};
34
35struct hda_model_fixup {
36 const int id;
37 const char *name;
38};
39
40struct hda_fixup {
41 int type;
42 bool chained;
43 int chain_id;
44 union {
45 const struct hda_pintbl *pins;
46 const struct hda_verb *verbs;
47 void (*func)(struct hda_codec *codec,
48 const struct hda_fixup *fix,
49 int action);
50 } v;
51};
52
53/* fixup types */
54enum {
55 HDA_FIXUP_INVALID,
56 HDA_FIXUP_PINS,
57 HDA_FIXUP_VERBS,
58 HDA_FIXUP_FUNC,
59};
60
61/* fixup action definitions */
62enum {
63 HDA_FIXUP_ACT_PRE_PROBE,
64 HDA_FIXUP_ACT_PROBE,
65 HDA_FIXUP_ACT_INIT,
66 HDA_FIXUP_ACT_BUILD,
67};
68
69int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
70 const struct hda_verb *list);
71void snd_hda_gen_apply_verbs(struct hda_codec *codec);
72void snd_hda_apply_pincfgs(struct hda_codec *codec,
73 const struct hda_pintbl *cfg);
74void snd_hda_apply_fixup(struct hda_codec *codec, int action);
75void snd_hda_pick_fixup(struct hda_codec *codec,
76 const struct hda_model_fixup *models,
77 const struct snd_pci_quirk *quirk,
78 const struct hda_fixup *fixlist);
79
80#endif /* __SOUND_HDA_AUTO_PARSER_H */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index aabdb9e9a484..2cfcec049ea9 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -30,6 +30,7 @@
30 30
31#include "hda_codec.h" 31#include "hda_codec.h"
32#include "hda_local.h" 32#include "hda_local.h"
33#include "hda_auto_parser.h"
33#include "hda_beep.h" 34#include "hda_beep.h"
34#include "hda_jack.h" 35#include "hda_jack.h"
35 36
@@ -66,6 +67,7 @@ struct imux_info {
66}; 67};
67 68
68struct conexant_spec { 69struct conexant_spec {
70 struct hda_gen_spec gen;
69 71
70 const struct snd_kcontrol_new *mixers[5]; 72 const struct snd_kcontrol_new *mixers[5];
71 int num_mixers; 73 int num_mixers;
@@ -4407,47 +4409,21 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
4407/* 4409/*
4408 * pin fix-up 4410 * pin fix-up
4409 */ 4411 */
4410struct cxt_pincfg {
4411 hda_nid_t nid;
4412 u32 val;
4413};
4414
4415static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg)
4416{
4417 for (; cfg->nid; cfg++)
4418 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
4419
4420}
4421
4422enum { 4412enum {
4423 CXT_PINCFG_LENOVO_X200, 4413 CXT_PINCFG_LENOVO_X200,
4424 CXT_PINCFG_LENOVO_TP410, 4414 CXT_PINCFG_LENOVO_TP410,
4425 CXT_FIXUP_STEREO_DMIC, 4415 CXT_FIXUP_STEREO_DMIC,
4426}; 4416};
4427 4417
4428static void apply_fixup(struct hda_codec *codec, 4418static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
4429 const struct snd_pci_quirk *quirk, 4419 const struct hda_fixup *fix, int action)
4430 const struct cxt_pincfg **table)
4431{ 4420{
4432 struct conexant_spec *spec = codec->spec; 4421 struct conexant_spec *spec = codec->spec;
4433 4422 spec->fixup_stereo_dmic = 1;
4434 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
4435 if (!quirk)
4436 return;
4437 if (table[quirk->value]) {
4438 snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n",
4439 quirk->name);
4440 apply_pincfg(codec, table[quirk->value]);
4441 }
4442 if (quirk->value == CXT_FIXUP_STEREO_DMIC) {
4443 snd_printdd(KERN_INFO "hda_codec: applying internal mic workaround for %s\n",
4444 quirk->name);
4445 spec->fixup_stereo_dmic = 1;
4446 }
4447} 4423}
4448 4424
4449/* ThinkPad X200 & co with cxt5051 */ 4425/* ThinkPad X200 & co with cxt5051 */
4450static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { 4426static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
4451 { 0x16, 0x042140ff }, /* HP (seq# overridden) */ 4427 { 0x16, 0x042140ff }, /* HP (seq# overridden) */
4452 { 0x17, 0x21a11000 }, /* dock-mic */ 4428 { 0x17, 0x21a11000 }, /* dock-mic */
4453 { 0x19, 0x2121103f }, /* dock-HP */ 4429 { 0x19, 0x2121103f }, /* dock-HP */
@@ -4456,17 +4432,26 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
4456}; 4432};
4457 4433
4458/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */ 4434/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
4459static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = { 4435static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
4460 { 0x19, 0x042110ff }, /* HP (seq# overridden) */ 4436 { 0x19, 0x042110ff }, /* HP (seq# overridden) */
4461 { 0x1a, 0x21a190f0 }, /* dock-mic */ 4437 { 0x1a, 0x21a190f0 }, /* dock-mic */
4462 { 0x1c, 0x212140ff }, /* dock-HP */ 4438 { 0x1c, 0x212140ff }, /* dock-HP */
4463 {} 4439 {}
4464}; 4440};
4465 4441
4466static const struct cxt_pincfg *cxt_pincfg_tbl[] = { 4442static const struct hda_fixup cxt_fixups[] = {
4467 [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, 4443 [CXT_PINCFG_LENOVO_X200] = {
4468 [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, 4444 .type = HDA_FIXUP_PINS,
4469 [CXT_FIXUP_STEREO_DMIC] = NULL, 4445 .v.pins = cxt_pincfg_lenovo_x200,
4446 },
4447 [CXT_PINCFG_LENOVO_TP410] = {
4448 .type = HDA_FIXUP_PINS,
4449 .v.pins = cxt_pincfg_lenovo_tp410,
4450 },
4451 [CXT_FIXUP_STEREO_DMIC] = {
4452 .type = HDA_FIXUP_FUNC,
4453 .v.func = cxt_fixup_stereo_dmic,
4454 },
4470}; 4455};
4471 4456
4472static const struct snd_pci_quirk cxt5051_fixups[] = { 4457static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4520,13 +4505,16 @@ static int patch_conexant_auto(struct hda_codec *codec)
4520 case 0x14f15051: 4505 case 0x14f15051:
4521 add_cx5051_fake_mutes(codec); 4506 add_cx5051_fake_mutes(codec);
4522 codec->pin_amp_workaround = 1; 4507 codec->pin_amp_workaround = 1;
4523 apply_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); 4508 snd_hda_pick_fixup(codec, NULL, cxt5051_fixups, cxt_fixups);
4524 break; 4509 break;
4525 default: 4510 default:
4526 codec->pin_amp_workaround = 1; 4511 codec->pin_amp_workaround = 1;
4527 apply_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); 4512 snd_hda_pick_fixup(codec, NULL, cxt5066_fixups, cxt_fixups);
4513 break;
4528 } 4514 }
4529 4515
4516 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
4517
4530 /* Show mute-led control only on HP laptops 4518 /* Show mute-led control only on HP laptops
4531 * This is a sort of white-list: on HP laptops, EAPD corresponds 4519 * This is a sort of white-list: on HP laptops, EAPD corresponds
4532 * only to the mute-LED without actualy amp function. Meanwhile, 4520 * only to the mute-LED without actualy amp function. Meanwhile,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ae9732ce8670..152f458afd2b 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -32,6 +32,7 @@
32#include <sound/jack.h> 32#include <sound/jack.h>
33#include "hda_codec.h" 33#include "hda_codec.h"
34#include "hda_local.h" 34#include "hda_local.h"
35#include "hda_auto_parser.h"
35#include "hda_beep.h" 36#include "hda_beep.h"
36#include "hda_jack.h" 37#include "hda_jack.h"
37 38
@@ -66,8 +67,6 @@ struct alc_customize_define {
66 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */ 67 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
67}; 68};
68 69
69struct alc_fixup;
70
71struct alc_multi_io { 70struct alc_multi_io {
72 hda_nid_t pin; /* multi-io widget pin NID */ 71 hda_nid_t pin; /* multi-io widget pin NID */
73 hda_nid_t dac; /* DAC to be connected */ 72 hda_nid_t dac; /* DAC to be connected */
@@ -82,19 +81,33 @@ enum {
82 81
83#define MAX_VOL_NIDS 0x40 82#define MAX_VOL_NIDS 0x40
84 83
84/* make compatible with old code */
85#define alc_apply_pincfgs snd_hda_apply_pincfgs
86#define alc_apply_fixup snd_hda_apply_fixup
87#define alc_pick_fixup snd_hda_pick_fixup
88#define alc_fixup hda_fixup
89#define alc_pincfg hda_pintbl
90#define alc_model_fixup hda_model_fixup
91
92#define ALC_FIXUP_PINS HDA_FIXUP_PINS
93#define ALC_FIXUP_VERBS HDA_FIXUP_VERBS
94#define ALC_FIXUP_FUNC HDA_FIXUP_FUNC
95
96#define ALC_FIXUP_ACT_PRE_PROBE HDA_FIXUP_ACT_PRE_PROBE
97#define ALC_FIXUP_ACT_PROBE HDA_FIXUP_ACT_PROBE
98#define ALC_FIXUP_ACT_INIT HDA_FIXUP_ACT_INIT
99#define ALC_FIXUP_ACT_BUILD HDA_FIXUP_ACT_BUILD
100
101
85struct alc_spec { 102struct alc_spec {
103 struct hda_gen_spec gen;
104
86 /* codec parameterization */ 105 /* codec parameterization */
87 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ 106 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
88 unsigned int num_mixers; 107 unsigned int num_mixers;
89 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */ 108 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
90 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ 109 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
91 110
92 const struct hda_verb *init_verbs[10]; /* initialization verbs
93 * don't forget NULL
94 * termination!
95 */
96 unsigned int num_init_verbs;
97
98 char stream_name_analog[32]; /* analog PCM stream */ 111 char stream_name_analog[32]; /* analog PCM stream */
99 const struct hda_pcm_stream *stream_analog_playback; 112 const struct hda_pcm_stream *stream_analog_playback;
100 const struct hda_pcm_stream *stream_analog_capture; 113 const struct hda_pcm_stream *stream_analog_capture;
@@ -210,11 +223,6 @@ struct alc_spec {
210 unsigned int pll_coef_idx, pll_coef_bit; 223 unsigned int pll_coef_idx, pll_coef_bit;
211 unsigned int coef0; 224 unsigned int coef0;
212 225
213 /* fix-up list */
214 int fixup_id;
215 const struct alc_fixup *fixup_list;
216 const char *fixup_name;
217
218 /* multi-io */ 226 /* multi-io */
219 int multi_ios; 227 int multi_ios;
220 struct alc_multi_io multi_io[4]; 228 struct alc_multi_io multi_io[4];
@@ -396,13 +404,6 @@ static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
396 spec->mixers[spec->num_mixers++] = mix; 404 spec->mixers[spec->num_mixers++] = mix;
397} 405}
398 406
399static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
400{
401 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
402 return;
403 spec->init_verbs[spec->num_init_verbs++] = verb;
404}
405
406/* 407/*
407 * GPIO setup tables, used in initialization 408 * GPIO setup tables, used in initialization
408 */ 409 */
@@ -1185,6 +1186,16 @@ static void alc_auto_check_switches(struct hda_codec *codec)
1185 */ 1186 */
1186#define ALC_FIXUP_SKU_IGNORE (2) 1187#define ALC_FIXUP_SKU_IGNORE (2)
1187 1188
1189static void alc_fixup_sku_ignore(struct hda_codec *codec,
1190 const struct hda_fixup *fix, int action)
1191{
1192 struct alc_spec *spec = codec->spec;
1193 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
1194 spec->cdefine.fixup = 1;
1195 spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
1196 }
1197}
1198
1188static int alc_auto_parse_customize_define(struct hda_codec *codec) 1199static int alc_auto_parse_customize_define(struct hda_codec *codec)
1189{ 1200{
1190 unsigned int ass, tmp, i; 1201 unsigned int ass, tmp, i;
@@ -1388,178 +1399,6 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
1388} 1399}
1389 1400
1390/* 1401/*
1391 * Fix-up pin default configurations and add default verbs
1392 */
1393
1394struct alc_pincfg {
1395 hda_nid_t nid;
1396 u32 val;
1397};
1398
1399struct alc_model_fixup {
1400 const int id;
1401 const char *name;
1402};
1403
1404struct alc_fixup {
1405 int type;
1406 bool chained;
1407 int chain_id;
1408 union {
1409 unsigned int sku;
1410 const struct alc_pincfg *pins;
1411 const struct hda_verb *verbs;
1412 void (*func)(struct hda_codec *codec,
1413 const struct alc_fixup *fix,
1414 int action);
1415 } v;
1416};
1417
1418enum {
1419 ALC_FIXUP_INVALID,
1420 ALC_FIXUP_SKU,
1421 ALC_FIXUP_PINS,
1422 ALC_FIXUP_VERBS,
1423 ALC_FIXUP_FUNC,
1424};
1425
1426enum {
1427 ALC_FIXUP_ACT_PRE_PROBE,
1428 ALC_FIXUP_ACT_PROBE,
1429 ALC_FIXUP_ACT_INIT,
1430 ALC_FIXUP_ACT_BUILD,
1431};
1432
1433static void alc_apply_pincfgs(struct hda_codec *codec,
1434 const struct alc_pincfg *cfg)
1435{
1436 for (; cfg->nid; cfg++)
1437 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
1438}
1439
1440static void alc_apply_fixup(struct hda_codec *codec, int action)
1441{
1442 struct alc_spec *spec = codec->spec;
1443 int id = spec->fixup_id;
1444#ifdef CONFIG_SND_DEBUG_VERBOSE
1445 const char *modelname = spec->fixup_name;
1446#endif
1447 int depth = 0;
1448
1449 if (!spec->fixup_list)
1450 return;
1451
1452 while (id >= 0) {
1453 const struct alc_fixup *fix = spec->fixup_list + id;
1454 const struct alc_pincfg *cfg;
1455
1456 switch (fix->type) {
1457 case ALC_FIXUP_SKU:
1458 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1459 break;
1460 snd_printdd(KERN_INFO "hda_codec: %s: "
1461 "Apply sku override for %s\n",
1462 codec->chip_name, modelname);
1463 spec->cdefine.sku_cfg = fix->v.sku;
1464 spec->cdefine.fixup = 1;
1465 break;
1466 case ALC_FIXUP_PINS:
1467 cfg = fix->v.pins;
1468 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1469 break;
1470 snd_printdd(KERN_INFO "hda_codec: %s: "
1471 "Apply pincfg for %s\n",
1472 codec->chip_name, modelname);
1473 alc_apply_pincfgs(codec, cfg);
1474 break;
1475 case ALC_FIXUP_VERBS:
1476 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1477 break;
1478 snd_printdd(KERN_INFO "hda_codec: %s: "
1479 "Apply fix-verbs for %s\n",
1480 codec->chip_name, modelname);
1481 add_verb(codec->spec, fix->v.verbs);
1482 break;
1483 case ALC_FIXUP_FUNC:
1484 if (!fix->v.func)
1485 break;
1486 snd_printdd(KERN_INFO "hda_codec: %s: "
1487 "Apply fix-func for %s\n",
1488 codec->chip_name, modelname);
1489 fix->v.func(codec, fix, action);
1490 break;
1491 default:
1492 snd_printk(KERN_ERR "hda_codec: %s: "
1493 "Invalid fixup type %d\n",
1494 codec->chip_name, fix->type);
1495 break;
1496 }
1497 if (!fix->chained)
1498 break;
1499 if (++depth > 10)
1500 break;
1501 id = fix->chain_id;
1502 }
1503}
1504
1505static void alc_pick_fixup(struct hda_codec *codec,
1506 const struct alc_model_fixup *models,
1507 const struct snd_pci_quirk *quirk,
1508 const struct alc_fixup *fixlist)
1509{
1510 struct alc_spec *spec = codec->spec;
1511 const struct snd_pci_quirk *q;
1512 int id = -1;
1513 const char *name = NULL;
1514
1515 /* when model=nofixup is given, don't pick up any fixups */
1516 if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
1517 spec->fixup_list = NULL;
1518 spec->fixup_id = -1;
1519 return;
1520 }
1521
1522 if (codec->modelname && models) {
1523 while (models->name) {
1524 if (!strcmp(codec->modelname, models->name)) {
1525 id = models->id;
1526 name = models->name;
1527 break;
1528 }
1529 models++;
1530 }
1531 }
1532 if (id < 0) {
1533 q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1534 if (q) {
1535 id = q->value;
1536#ifdef CONFIG_SND_DEBUG_VERBOSE
1537 name = q->name;
1538#endif
1539 }
1540 }
1541 if (id < 0) {
1542 for (q = quirk; q->subvendor; q++) {
1543 unsigned int vendorid =
1544 q->subdevice | (q->subvendor << 16);
1545 if (vendorid == codec->subsystem_id) {
1546 id = q->value;
1547#ifdef CONFIG_SND_DEBUG_VERBOSE
1548 name = q->name;
1549#endif
1550 break;
1551 }
1552 }
1553 }
1554
1555 spec->fixup_id = id;
1556 if (id >= 0) {
1557 spec->fixup_list = fixlist;
1558 spec->fixup_name = name;
1559 }
1560}
1561
1562/*
1563 * COEF access helper functions 1402 * COEF access helper functions
1564 */ 1403 */
1565static int alc_read_coef_idx(struct hda_codec *codec, 1404static int alc_read_coef_idx(struct hda_codec *codec,
@@ -2050,7 +1889,6 @@ static void alc_auto_init_std(struct hda_codec *codec);
2050static int alc_init(struct hda_codec *codec) 1889static int alc_init(struct hda_codec *codec)
2051{ 1890{
2052 struct alc_spec *spec = codec->spec; 1891 struct alc_spec *spec = codec->spec;
2053 unsigned int i;
2054 1892
2055 if (spec->init_hook) 1893 if (spec->init_hook)
2056 spec->init_hook(codec); 1894 spec->init_hook(codec);
@@ -2058,8 +1896,6 @@ static int alc_init(struct hda_codec *codec)
2058 alc_fix_pll(codec); 1896 alc_fix_pll(codec);
2059 alc_auto_init_amp(codec, spec->init_amp); 1897 alc_auto_init_amp(codec, spec->init_amp);
2060 1898
2061 for (i = 0; i < spec->num_init_verbs; i++)
2062 snd_hda_sequence_write(codec, spec->init_verbs[i]);
2063 alc_init_special_input_src(codec); 1899 alc_init_special_input_src(codec);
2064 alc_auto_init_std(codec); 1900 alc_auto_init_std(codec);
2065 1901
@@ -4885,7 +4721,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
4885 spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ 4721 spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
4886 snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); 4722 snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
4887 spec->unsol_event = alc_sku_unsol_event; 4723 spec->unsol_event = alc_sku_unsol_event;
4888 add_verb(codec->spec, alc_gpio1_init_verbs); 4724 snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs);
4889 } 4725 }
4890} 4726}
4891 4727
@@ -5216,8 +5052,8 @@ static const struct alc_fixup alc882_fixups[] = {
5216 } 5052 }
5217 }, 5053 },
5218 [ALC882_FIXUP_ACER_ASPIRE_7736] = { 5054 [ALC882_FIXUP_ACER_ASPIRE_7736] = {
5219 .type = ALC_FIXUP_SKU, 5055 .type = ALC_FIXUP_FUNC,
5220 .v.sku = ALC_FIXUP_SKU_IGNORE, 5056 .v.func = alc_fixup_sku_ignore,
5221 }, 5057 },
5222 [ALC882_FIXUP_ASUS_W90V] = { 5058 [ALC882_FIXUP_ASUS_W90V] = {
5223 .type = ALC_FIXUP_PINS, 5059 .type = ALC_FIXUP_PINS,
@@ -5693,7 +5529,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
5693 if (err > 0) { 5529 if (err > 0) {
5694 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) { 5530 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
5695 add_mixer(spec, alc268_beep_mixer); 5531 add_mixer(spec, alc268_beep_mixer);
5696 add_verb(spec, alc268_beep_init_verbs); 5532 snd_hda_gen_add_verbs(&spec->gen, alc268_beep_init_verbs);
5697 } 5533 }
5698 } 5534 }
5699 return err; 5535 return err;
@@ -5995,8 +5831,8 @@ static const struct alc_fixup alc269_fixups[] = {
5995 } 5831 }
5996 }, 5832 },
5997 [ALC269_FIXUP_SKU_IGNORE] = { 5833 [ALC269_FIXUP_SKU_IGNORE] = {
5998 .type = ALC_FIXUP_SKU, 5834 .type = ALC_FIXUP_FUNC,
5999 .v.sku = ALC_FIXUP_SKU_IGNORE, 5835 .v.func = alc_fixup_sku_ignore,
6000 }, 5836 },
6001 [ALC269_FIXUP_ASUS_G73JW] = { 5837 [ALC269_FIXUP_ASUS_G73JW] = {
6002 .type = ALC_FIXUP_PINS, 5838 .type = ALC_FIXUP_PINS,
@@ -6491,7 +6327,7 @@ static int patch_alc861vd(struct hda_codec *codec)
6491 6327
6492 if (codec->vendor_id == 0x10ec0660) { 6328 if (codec->vendor_id == 0x10ec0660) {
6493 /* always turn on EAPD */ 6329 /* always turn on EAPD */
6494 add_verb(spec, alc660vd_eapd_verbs); 6330 snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs);
6495 } 6331 }
6496 6332
6497 if (!spec->no_analog) { 6333 if (!spec->no_analog) {
@@ -6604,8 +6440,8 @@ static const struct alc_fixup alc662_fixups[] = {
6604 } 6440 }
6605 }, 6441 },
6606 [ALC662_FIXUP_SKU_IGNORE] = { 6442 [ALC662_FIXUP_SKU_IGNORE] = {
6607 .type = ALC_FIXUP_SKU, 6443 .type = ALC_FIXUP_FUNC,
6608 .v.sku = ALC_FIXUP_SKU_IGNORE, 6444 .v.func = alc_fixup_sku_ignore,
6609 }, 6445 },
6610 [ALC662_FIXUP_HP_RP5800] = { 6446 [ALC662_FIXUP_HP_RP5800] = {
6611 .type = ALC_FIXUP_PINS, 6447 .type = ALC_FIXUP_PINS,