]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - sound/pci/hda/alc262_quirks.c
ALSA: hda/realtek - Convert ALC262 lenovo-3000 quirks to fixup-list
[mirror_ubuntu-bionic-kernel.git] / sound / pci / hda / alc262_quirks.c
1 /*
2 * ALC262 quirk models
3 * included by patch_realtek.c
4 */
5
6 /* ALC262 models */
7 enum {
8 ALC262_AUTO,
9 ALC262_BASIC,
10 ALC262_HIPPO,
11 ALC262_HIPPO_1,
12 ALC262_FUJITSU,
13 ALC262_BENQ_ED8,
14 ALC262_BENQ_T31,
15 ALC262_ULTRA,
16 ALC262_MODEL_LAST /* last tag */
17 };
18
19 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
20 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
21
22 #define alc262_dac_nids alc260_dac_nids
23 #define alc262_adc_nids alc882_adc_nids
24 #define alc262_adc_nids_alt alc882_adc_nids_alt
25 #define alc262_capsrc_nids alc882_capsrc_nids
26 #define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
27
28 #define alc262_modes alc260_modes
29 #define alc262_capture_source alc882_capture_source
30
31 static const hda_nid_t alc262_dmic_adc_nids[1] = {
32 /* ADC0 */
33 0x09
34 };
35
36 static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
37
38 static const struct snd_kcontrol_new alc262_base_mixer[] = {
39 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
40 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
41 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
42 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
43 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
44 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
45 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
46 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
47 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
48 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
49 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
50 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
51 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
52 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
53 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
54 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
55 { } /* end */
56 };
57
58 /* bind hp and internal speaker mute (with plug check) as master switch */
59
60 static int alc262_hippo_master_sw_get(struct snd_kcontrol *kcontrol,
61 struct snd_ctl_elem_value *ucontrol)
62 {
63 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
64 struct alc_spec *spec = codec->spec;
65 *ucontrol->value.integer.value = !spec->master_mute;
66 return 0;
67 }
68
69 static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
70 struct snd_ctl_elem_value *ucontrol)
71 {
72 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
73 struct alc_spec *spec = codec->spec;
74 int val = !*ucontrol->value.integer.value;
75
76 if (val == spec->master_mute)
77 return 0;
78 spec->master_mute = val;
79 update_outputs(codec);
80 return 1;
81 }
82
83 #define ALC262_HIPPO_MASTER_SWITCH \
84 { \
85 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
86 .name = "Master Playback Switch", \
87 .info = snd_ctl_boolean_mono_info, \
88 .get = alc262_hippo_master_sw_get, \
89 .put = alc262_hippo_master_sw_put, \
90 }, \
91 { \
92 .iface = NID_MAPPING, \
93 .name = "Master Playback Switch", \
94 .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
95 (SUBDEV_SPEAKER(0) << 16), \
96 }
97
98 #define alc262_hp_master_sw_get alc262_hippo_master_sw_get
99 #define alc262_hp_master_sw_put alc262_hippo_master_sw_put
100
101 static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
102 ALC262_HIPPO_MASTER_SWITCH,
103 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
104 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
105 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
106 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
107 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
108 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
109 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
110 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
111 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
112 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
113 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
114 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
115 { } /* end */
116 };
117
118 static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
119 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
120 ALC262_HIPPO_MASTER_SWITCH,
121 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
122 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
123 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
124 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
125 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
126 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
127 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
128 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
129 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
130 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
131 { } /* end */
132 };
133
134 /* mute/unmute internal speaker according to the hp jack and mute state */
135 static void alc262_hippo_setup(struct hda_codec *codec)
136 {
137 struct alc_spec *spec = codec->spec;
138
139 spec->autocfg.hp_pins[0] = 0x15;
140 spec->autocfg.speaker_pins[0] = 0x14;
141 alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
142 }
143
144 static void alc262_hippo1_setup(struct hda_codec *codec)
145 {
146 struct alc_spec *spec = codec->spec;
147
148 spec->autocfg.hp_pins[0] = 0x1b;
149 spec->autocfg.speaker_pins[0] = 0x14;
150 alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
151 }
152
153
154 static const struct snd_kcontrol_new alc262_sony_mixer[] = {
155 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
156 ALC262_HIPPO_MASTER_SWITCH,
157 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
158 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
159 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
160 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
161 { } /* end */
162 };
163
164 static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
165 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
166 ALC262_HIPPO_MASTER_SWITCH,
167 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
168 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
169 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
170 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
171 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
172 { } /* end */
173 };
174
175 #define alc262_capture_mixer alc882_capture_mixer
176 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
177
178 /*
179 * generic initialization of ADC, input mixers and output mixers
180 */
181 static const struct hda_verb alc262_init_verbs[] = {
182 /*
183 * Unmute ADC0-2 and set the default input to mic-in
184 */
185 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
186 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
187 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
188 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
189 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
190 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
191
192 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
193 * mixer widget
194 * Note: PASD motherboards uses the Line In 2 as the input for
195 * front panel mic (mic 2)
196 */
197 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
198 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
199 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
200 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
201 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
202 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
203
204 /*
205 * Set up output mixers (0x0c - 0x0e)
206 */
207 /* set vol=0 to output mixers */
208 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
209 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
210 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
211 /* set up input amps for analog loopback */
212 /* Amp Indices: DAC = 0, mixer = 1 */
213 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
214 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
215 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
216 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
217 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
218 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
219
220 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
221 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
222 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
223 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
224 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
225 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
226
227 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
228 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
229 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
230 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
231 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
232
233 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
234 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
235
236 /* FIXME: use matrix-type input source selection */
237 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
238 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
239 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
240 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
241 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
242 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
243 /* Input mixer2 */
244 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
245 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
246 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
247 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
248 /* Input mixer3 */
249 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
250 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
251 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
252 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
253
254 { }
255 };
256
257 static const struct hda_verb alc262_eapd_verbs[] = {
258 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
259 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
260 { }
261 };
262
263 static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
264 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
265 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
266 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
267
268 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
269 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
270 {}
271 };
272
273 static const struct hda_verb alc262_sony_unsol_verbs[] = {
274 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
275 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
276 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
277
278 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
279 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
280 {}
281 };
282
283 /*
284 * fujitsu model
285 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
286 * 0x1b = port replicator headphone out
287 */
288
289 static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
290 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
291 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
292 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
293 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
294 {}
295 };
296
297 static const struct hda_input_mux alc262_fujitsu_capture_source = {
298 .num_items = 3,
299 .items = {
300 { "Mic", 0x0 },
301 { "Internal Mic", 0x1 },
302 { "CD", 0x4 },
303 },
304 };
305
306 static void alc262_fujitsu_setup(struct hda_codec *codec)
307 {
308 struct alc_spec *spec = codec->spec;
309
310 spec->autocfg.hp_pins[0] = 0x14;
311 spec->autocfg.hp_pins[1] = 0x1b;
312 spec->autocfg.speaker_pins[0] = 0x15;
313 alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
314 }
315
316 /* bind volumes of both NID 0x0c and 0x0d */
317 static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
318 .ops = &snd_hda_bind_vol,
319 .values = {
320 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
321 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
322 0
323 },
324 };
325
326 static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
327 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
328 {
329 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
330 .name = "Master Playback Switch",
331 .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
332 .info = snd_ctl_boolean_mono_info,
333 .get = alc262_hp_master_sw_get,
334 .put = alc262_hp_master_sw_put,
335 },
336 {
337 .iface = NID_MAPPING,
338 .name = "Master Playback Switch",
339 .private_value = 0x1b,
340 },
341 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
342 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
343 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
344 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
345 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
346 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
347 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
348 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
349 { } /* end */
350 };
351
352 /* additional init verbs for Benq laptops */
353 static const struct hda_verb alc262_EAPD_verbs[] = {
354 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
355 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
356 {}
357 };
358
359 static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
360 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
361 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
362
363 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
364 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
365 {}
366 };
367
368 /* Samsung Q1 Ultra Vista model setup */
369 static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
370 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
371 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
372 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
373 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
374 HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
375 HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
376 { } /* end */
377 };
378
379 static const struct hda_verb alc262_ultra_verbs[] = {
380 /* output mixer */
381 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
382 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
383 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
384 /* speaker */
385 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
386 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
387 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
388 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
389 /* HP */
390 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
391 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
392 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
393 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
394 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
395 /* internal mic */
396 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
397 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
398 /* ADC, choose mic */
399 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
400 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
401 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
402 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
403 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
404 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
405 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
406 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
407 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
408 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
409 {}
410 };
411
412 /* mute/unmute internal speaker according to the hp jack and mute state */
413 static void alc262_ultra_automute(struct hda_codec *codec)
414 {
415 struct alc_spec *spec = codec->spec;
416 unsigned int mute;
417
418 mute = 0;
419 /* auto-mute only when HP is used as HP */
420 if (!spec->cur_mux[0]) {
421 spec->hp_jack_present = snd_hda_jack_detect(codec, 0x15);
422 if (spec->hp_jack_present)
423 mute = HDA_AMP_MUTE;
424 }
425 /* mute/unmute internal speaker */
426 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
427 HDA_AMP_MUTE, mute);
428 /* mute/unmute HP */
429 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
430 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
431 }
432
433 /* unsolicited event for HP jack sensing */
434 static void alc262_ultra_unsol_event(struct hda_codec *codec,
435 unsigned int res)
436 {
437 if ((res >> 26) != ALC_HP_EVENT)
438 return;
439 alc262_ultra_automute(codec);
440 }
441
442 static const struct hda_input_mux alc262_ultra_capture_source = {
443 .num_items = 2,
444 .items = {
445 { "Mic", 0x1 },
446 { "Headphone", 0x7 },
447 },
448 };
449
450 static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_value *ucontrol)
452 {
453 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
454 struct alc_spec *spec = codec->spec;
455 int ret;
456
457 ret = alc_mux_enum_put(kcontrol, ucontrol);
458 if (!ret)
459 return 0;
460 /* reprogram the HP pin as mic or HP according to the input source */
461 snd_hda_codec_write_cache(codec, 0x15, 0,
462 AC_VERB_SET_PIN_WIDGET_CONTROL,
463 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
464 alc262_ultra_automute(codec); /* mute/unmute HP */
465 return ret;
466 }
467
468 static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
469 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
470 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
471 {
472 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
473 .name = "Capture Source",
474 .info = alc_mux_enum_info,
475 .get = alc_mux_enum_get,
476 .put = alc262_ultra_mux_enum_put,
477 },
478 {
479 .iface = NID_MAPPING,
480 .name = "Capture Source",
481 .private_value = 0x15,
482 },
483 { } /* end */
484 };
485
486 /*
487 * configuration and preset
488 */
489 static const char * const alc262_models[ALC262_MODEL_LAST] = {
490 [ALC262_BASIC] = "basic",
491 [ALC262_HIPPO] = "hippo",
492 [ALC262_HIPPO_1] = "hippo_1",
493 [ALC262_FUJITSU] = "fujitsu",
494 [ALC262_BENQ_ED8] = "benq",
495 [ALC262_BENQ_T31] = "benq-t31",
496 [ALC262_ULTRA] = "ultra",
497 [ALC262_AUTO] = "auto",
498 };
499
500 static const struct snd_pci_quirk alc262_cfg_tbl[] = {
501 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
502 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
503 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
504 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
505 ALC262_ULTRA),
506 SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
507 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
508 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
509 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
510 {}
511 };
512
513 static const struct alc_config_preset alc262_presets[] = {
514 [ALC262_BASIC] = {
515 .mixers = { alc262_base_mixer },
516 .init_verbs = { alc262_init_verbs },
517 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
518 .dac_nids = alc262_dac_nids,
519 .hp_nid = 0x03,
520 .num_channel_mode = ARRAY_SIZE(alc262_modes),
521 .channel_mode = alc262_modes,
522 .input_mux = &alc262_capture_source,
523 },
524 [ALC262_HIPPO] = {
525 .mixers = { alc262_hippo_mixer },
526 .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
527 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
528 .dac_nids = alc262_dac_nids,
529 .hp_nid = 0x03,
530 .dig_out_nid = ALC262_DIGOUT_NID,
531 .num_channel_mode = ARRAY_SIZE(alc262_modes),
532 .channel_mode = alc262_modes,
533 .input_mux = &alc262_capture_source,
534 .unsol_event = alc_sku_unsol_event,
535 .setup = alc262_hippo_setup,
536 .init_hook = alc_inithook,
537 },
538 [ALC262_HIPPO_1] = {
539 .mixers = { alc262_hippo1_mixer },
540 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
541 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
542 .dac_nids = alc262_dac_nids,
543 .hp_nid = 0x02,
544 .dig_out_nid = ALC262_DIGOUT_NID,
545 .num_channel_mode = ARRAY_SIZE(alc262_modes),
546 .channel_mode = alc262_modes,
547 .input_mux = &alc262_capture_source,
548 .unsol_event = alc_sku_unsol_event,
549 .setup = alc262_hippo1_setup,
550 .init_hook = alc_inithook,
551 },
552 [ALC262_FUJITSU] = {
553 .mixers = { alc262_fujitsu_mixer },
554 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
555 alc262_fujitsu_unsol_verbs },
556 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
557 .dac_nids = alc262_dac_nids,
558 .hp_nid = 0x03,
559 .dig_out_nid = ALC262_DIGOUT_NID,
560 .num_channel_mode = ARRAY_SIZE(alc262_modes),
561 .channel_mode = alc262_modes,
562 .input_mux = &alc262_fujitsu_capture_source,
563 .unsol_event = alc_sku_unsol_event,
564 .setup = alc262_fujitsu_setup,
565 .init_hook = alc_inithook,
566 },
567 [ALC262_BENQ_ED8] = {
568 .mixers = { alc262_base_mixer },
569 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
570 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
571 .dac_nids = alc262_dac_nids,
572 .hp_nid = 0x03,
573 .num_channel_mode = ARRAY_SIZE(alc262_modes),
574 .channel_mode = alc262_modes,
575 .input_mux = &alc262_capture_source,
576 },
577 [ALC262_BENQ_T31] = {
578 .mixers = { alc262_benq_t31_mixer },
579 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
580 alc_hp15_unsol_verbs },
581 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
582 .dac_nids = alc262_dac_nids,
583 .hp_nid = 0x03,
584 .num_channel_mode = ARRAY_SIZE(alc262_modes),
585 .channel_mode = alc262_modes,
586 .input_mux = &alc262_capture_source,
587 .unsol_event = alc_sku_unsol_event,
588 .setup = alc262_hippo_setup,
589 .init_hook = alc_inithook,
590 },
591 [ALC262_ULTRA] = {
592 .mixers = { alc262_ultra_mixer },
593 .cap_mixer = alc262_ultra_capture_mixer,
594 .init_verbs = { alc262_ultra_verbs },
595 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
596 .dac_nids = alc262_dac_nids,
597 .num_channel_mode = ARRAY_SIZE(alc262_modes),
598 .channel_mode = alc262_modes,
599 .input_mux = &alc262_ultra_capture_source,
600 .adc_nids = alc262_adc_nids, /* ADC0 */
601 .capsrc_nids = alc262_capsrc_nids,
602 .num_adc_nids = 1, /* single ADC */
603 .unsol_event = alc262_ultra_unsol_event,
604 .init_hook = alc262_ultra_automute,
605 },
606 };
607