diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_auto_parser.c | 163 | ||||
-rw-r--r-- | sound/pci/hda/hda_auto_parser.h | 80 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 62 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 244 |
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 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | 2 | ||
3 | snd-hda-codec-y := hda_codec.o hda_jack.o | 3 | snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o |
4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
6 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 6 | snd-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 | |||
20 | int 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 | } | ||
31 | EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs); | ||
32 | |||
33 | void 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 | } | ||
42 | EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs); | ||
43 | |||
44 | void 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 | } | ||
50 | EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs); | ||
51 | |||
52 | void 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 | } | ||
105 | EXPORT_SYMBOL_HDA(snd_hda_apply_fixup); | ||
106 | |||
107 | void 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 | } | ||
163 | EXPORT_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 | |||
15 | struct 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 | |||
30 | struct hda_pintbl { | ||
31 | hda_nid_t nid; | ||
32 | u32 val; | ||
33 | }; | ||
34 | |||
35 | struct hda_model_fixup { | ||
36 | const int id; | ||
37 | const char *name; | ||
38 | }; | ||
39 | |||
40 | struct 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 */ | ||
54 | enum { | ||
55 | HDA_FIXUP_INVALID, | ||
56 | HDA_FIXUP_PINS, | ||
57 | HDA_FIXUP_VERBS, | ||
58 | HDA_FIXUP_FUNC, | ||
59 | }; | ||
60 | |||
61 | /* fixup action definitions */ | ||
62 | enum { | ||
63 | HDA_FIXUP_ACT_PRE_PROBE, | ||
64 | HDA_FIXUP_ACT_PROBE, | ||
65 | HDA_FIXUP_ACT_INIT, | ||
66 | HDA_FIXUP_ACT_BUILD, | ||
67 | }; | ||
68 | |||
69 | int snd_hda_gen_add_verbs(struct hda_gen_spec *spec, | ||
70 | const struct hda_verb *list); | ||
71 | void snd_hda_gen_apply_verbs(struct hda_codec *codec); | ||
72 | void snd_hda_apply_pincfgs(struct hda_codec *codec, | ||
73 | const struct hda_pintbl *cfg); | ||
74 | void snd_hda_apply_fixup(struct hda_codec *codec, int action); | ||
75 | void 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 | ||
68 | struct conexant_spec { | 69 | struct 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 | */ |
4410 | struct cxt_pincfg { | ||
4411 | hda_nid_t nid; | ||
4412 | u32 val; | ||
4413 | }; | ||
4414 | |||
4415 | static 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 | |||
4422 | enum { | 4412 | enum { |
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 | ||
4428 | static void apply_fixup(struct hda_codec *codec, | 4418 | static 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 */ |
4450 | static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { | 4426 | static 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 */ |
4459 | static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = { | 4435 | static 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 | ||
4466 | static const struct cxt_pincfg *cxt_pincfg_tbl[] = { | 4442 | static 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 | ||
4472 | static const struct snd_pci_quirk cxt5051_fixups[] = { | 4457 | static 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 | ||
69 | struct alc_fixup; | ||
70 | |||
71 | struct alc_multi_io { | 70 | struct 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 | |||
85 | struct alc_spec { | 102 | struct 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 | ||
399 | static 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 | ||
1189 | static 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 | |||
1188 | static int alc_auto_parse_customize_define(struct hda_codec *codec) | 1199 | static 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 | |||
1394 | struct alc_pincfg { | ||
1395 | hda_nid_t nid; | ||
1396 | u32 val; | ||
1397 | }; | ||
1398 | |||
1399 | struct alc_model_fixup { | ||
1400 | const int id; | ||
1401 | const char *name; | ||
1402 | }; | ||
1403 | |||
1404 | struct 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 | |||
1418 | enum { | ||
1419 | ALC_FIXUP_INVALID, | ||
1420 | ALC_FIXUP_SKU, | ||
1421 | ALC_FIXUP_PINS, | ||
1422 | ALC_FIXUP_VERBS, | ||
1423 | ALC_FIXUP_FUNC, | ||
1424 | }; | ||
1425 | |||
1426 | enum { | ||
1427 | ALC_FIXUP_ACT_PRE_PROBE, | ||
1428 | ALC_FIXUP_ACT_PROBE, | ||
1429 | ALC_FIXUP_ACT_INIT, | ||
1430 | ALC_FIXUP_ACT_BUILD, | ||
1431 | }; | ||
1432 | |||
1433 | static 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 | |||
1440 | static 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 | |||
1505 | static 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 | */ |
1565 | static int alc_read_coef_idx(struct hda_codec *codec, | 1404 | static int alc_read_coef_idx(struct hda_codec *codec, |
@@ -2050,7 +1889,6 @@ static void alc_auto_init_std(struct hda_codec *codec); | |||
2050 | static int alc_init(struct hda_codec *codec) | 1889 | static 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, |