]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/alsa-hda-via-update
Revert "Disable build of xen kernel."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / alsa-hda-via-update
1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: ALSA: hda - VIA codecs updates
3 Patch-mainline: 2.6.28-rc1
4 References:
5
6 A pile of updates for VIA HD-audio codecs.
7
8 Signed-off-by: Takashi Iwai <tiwai@suse.de>
9
10 ---
11 diff -ruN a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
12 --- a/sound/pci/hda/patch_via.c
13 +++ b/sound/pci/hda/patch_via.c
14 @@ -1,10 +1,10 @@
15 /*
16 * Universal Interface for Intel High Definition Audio Codec
17 *
18 - * HD audio interface patch for VIA VT1708 codec
19 + * HD audio interface patch for VIA VT1702/VT1708/VT1709 codec
20 *
21 - * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
22 - * Takashi Iwai <tiwai@suse.de>
23 + * Copyright (c) 2006-2008 Lydia Wang <lydiawang@viatech.com>
24 + * Takashi Iwai <tiwai@suse.de>
25 *
26 * This driver is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 @@ -29,6 +29,13 @@
29 /* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
30 /* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
31 /* 2007-09-17 Lydia Wang Add VT1708B codec support */
32 +/* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */
33 +/* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */
34 +/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
35 +/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
36 +/* 2008-04-09 Lydia Wang Add Independent HP feature */
37 +/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
38 +/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */
39 /* */
40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41
42 @@ -37,6 +44,7 @@
43 #include <linux/delay.h>
44 #include <linux/slab.h>
45 #include <sound/core.h>
46 +#include <sound/asoundef.h>
47 #include "hda_codec.h"
48 #include "hda_local.h"
49 #include "hda_patch.h"
50 @@ -53,6 +61,8 @@
51 #define VT1708_DIGOUT_NID 0x14
52 #define VT1708_DIGIN_NID 0x16
53 #define VT1708_DIGIN_PIN 0x26
54 +#define VT1708_HP_PIN_NID 0x20
55 +#define VT1708_CD_PIN_NID 0x24
56
57 #define VT1709_HP_DAC_NID 0x28
58 #define VT1709_DIGOUT_NID 0x13
59 @@ -64,12 +74,64 @@
60 #define VT1708B_DIGIN_NID 0x15
61 #define VT1708B_DIGIN_PIN 0x21
62
63 +#define VT1708S_HP_NID 0x25
64 +#define VT1708S_DIGOUT_NID 0x12
65 +
66 +#define VT1702_HP_NID 0x17
67 +#define VT1702_DIGOUT_NID 0x11
68 +
69 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
70 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
71 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
72 #define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
73 #define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
74 +#define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397)
75 +#define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398)
76 +
77 +enum VIA_HDA_CODEC {
78 + UNKNOWN = -1,
79 + VT1708,
80 + VT1709_10CH,
81 + VT1709_6CH,
82 + VT1708B_8CH,
83 + VT1708B_4CH,
84 + VT1708S,
85 + VT1702,
86 + CODEC_TYPES,
87 +};
88 +
89 +static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id)
90 +{
91 + u16 ven_id = vendor_id >> 16;
92 + u16 dev_id = vendor_id & 0xffff;
93 + enum VIA_HDA_CODEC codec_type;
94 +
95 + /* get codec type */
96 + if (ven_id != 0x1106)
97 + codec_type = UNKNOWN;
98 + else if (dev_id >= 0x1708 && dev_id <= 0x170b)
99 + codec_type = VT1708;
100 + else if (dev_id >= 0xe710 && dev_id <= 0xe713)
101 + codec_type = VT1709_10CH;
102 + else if (dev_id >= 0xe714 && dev_id <= 0xe717)
103 + codec_type = VT1709_6CH;
104 + else if (dev_id >= 0xe720 && dev_id <= 0xe723)
105 + codec_type = VT1708B_8CH;
106 + else if (dev_id >= 0xe724 && dev_id <= 0xe727)
107 + codec_type = VT1708B_4CH;
108 + else if ((dev_id & 0xfff) == 0x397
109 + && (dev_id >> 12) < 8)
110 + codec_type = VT1708S;
111 + else if ((dev_id & 0xfff) == 0x398
112 + && (dev_id >> 12) < 8)
113 + codec_type = VT1702;
114 + else
115 + codec_type = UNKNOWN;
116 + return codec_type;
117 +};
118
119 +#define VIA_HP_EVENT 0x01
120 +#define VIA_GPIO_EVENT 0x02
121
122 enum {
123 VIA_CTL_WIDGET_VOL,
124 @@ -77,12 +139,54 @@
125 };
126
127 enum {
128 - AUTO_SEQ_FRONT,
129 + AUTO_SEQ_FRONT = 0,
130 AUTO_SEQ_SURROUND,
131 AUTO_SEQ_CENLFE,
132 AUTO_SEQ_SIDE
133 };
134
135 +#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
136 +
137 +/* Some VT1708S based boards gets the micboost setting wrong, so we have
138 + * to apply some brute-force and re-write the TLV's by software. */
139 +static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag,
140 + unsigned int size, unsigned int __user *_tlv)
141 +{
142 + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
143 + hda_nid_t nid = get_amp_nid(kcontrol);
144 +
145 + if (get_codec_type(codec->vendor_id) == VT1708S
146 + && (nid == 0x1a || nid == 0x1e)) {
147 + if (size < 4 * sizeof(unsigned int))
148 + return -ENOMEM;
149 + if (put_user(1, _tlv)) /* SNDRV_CTL_TLVT_DB_SCALE */
150 + return -EFAULT;
151 + if (put_user(2 * sizeof(unsigned int), _tlv + 1))
152 + return -EFAULT;
153 + if (put_user(0, _tlv + 2)) /* offset = 0 */
154 + return -EFAULT;
155 + if (put_user(1000, _tlv + 3)) /* step size = 10 dB */
156 + return -EFAULT;
157 + }
158 + return 0;
159 +}
160 +
161 +static int mic_boost_volume_info(struct snd_kcontrol *kcontrol,
162 + struct snd_ctl_elem_info *uinfo)
163 +{
164 + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
165 + hda_nid_t nid = get_amp_nid(kcontrol);
166 +
167 + if (get_codec_type(codec->vendor_id) == VT1708S
168 + && (nid == 0x1a || nid == 0x1e)) {
169 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
170 + uinfo->count = 2;
171 + uinfo->value.integer.min = 0;
172 + uinfo->value.integer.max = 3;
173 + }
174 + return 0;
175 +}
176 +
177 static struct snd_kcontrol_new vt1708_control_templates[] = {
178 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
179 HDA_CODEC_MUTE(NULL, 0, 0, 0),
180 @@ -94,7 +198,8 @@
181 struct snd_kcontrol_new *mixers[3];
182 unsigned int num_mixers;
183
184 - struct hda_verb *init_verbs;
185 + struct hda_verb *init_verbs[5];
186 + unsigned int num_iverbs;
187
188 char *stream_name_analog;
189 struct hda_pcm_stream *stream_analog_playback;
190 @@ -106,6 +211,7 @@
191
192 /* playback */
193 struct hda_multi_out multiout;
194 + hda_nid_t extra_dig_out_nid;
195
196 /* capture */
197 unsigned int num_adc_nids;
198 @@ -117,15 +223,19 @@
199 unsigned int cur_mux[3];
200
201 /* PCM information */
202 - struct hda_pcm pcm_rec[2];
203 + struct hda_pcm pcm_rec[3];
204
205 /* dynamic controls, init_verbs and input_mux */
206 struct auto_pin_cfg autocfg;
207 unsigned int num_kctl_alloc, num_kctl_used;
208 struct snd_kcontrol_new *kctl_alloc;
209 - struct hda_input_mux private_imux;
210 + struct hda_input_mux private_imux[2];
211 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
212
213 + /* HP mode source */
214 + const struct hda_input_mux *hp_mux;
215 + unsigned int hp_independent_mode;
216 +
217 #ifdef CONFIG_SND_HDA_POWER_SAVE
218 struct hda_loopback_check loopback;
219 #endif
220 @@ -146,6 +256,16 @@
221 0x13, 0x14
222 };
223
224 +static hda_nid_t vt1708S_adc_nids[2] = {
225 + /* ADC1-2 */
226 + 0x13, 0x14
227 +};
228 +
229 +static hda_nid_t vt1702_adc_nids[3] = {
230 + /* ADC1-2 */
231 + 0x12, 0x20, 0x1F
232 +};
233 +
234 /* add dynamic controls */
235 static int via_add_control(struct via_spec *spec, int type, const char *name,
236 unsigned long val)
237 @@ -283,19 +403,108 @@
238 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
239 0x18, &spec->cur_mux[adc_idx]);
240 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
241 - IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0)
242 + IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0))
243 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
244 0x19, &spec->cur_mux[adc_idx]);
245 else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
246 - IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0)
247 + IS_VT1708B_4CH_VENDORID(vendor_id)) && (adc_idx == 0))
248 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
249 0x17, &spec->cur_mux[adc_idx]);
250 + else if (IS_VT1702_VENDORID(vendor_id) && (adc_idx == 0))
251 + return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
252 + 0x13, &spec->cur_mux[adc_idx]);
253 else
254 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
255 spec->adc_nids[adc_idx],
256 &spec->cur_mux[adc_idx]);
257 }
258
259 +static int via_independent_hp_info(struct snd_kcontrol *kcontrol,
260 + struct snd_ctl_elem_info *uinfo)
261 +{
262 + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
263 + struct via_spec *spec = codec->spec;
264 + return snd_hda_input_mux_info(spec->hp_mux, uinfo);
265 +}
266 +
267 +static int via_independent_hp_get(struct snd_kcontrol *kcontrol,
268 + struct snd_ctl_elem_value *ucontrol)
269 +{
270 + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
271 + struct via_spec *spec = codec->spec;
272 + hda_nid_t nid = spec->autocfg.hp_pins[0];
273 + unsigned int pinsel = snd_hda_codec_read(codec, nid, 0,
274 + AC_VERB_GET_CONNECT_SEL,
275 + 0x00);
276 +
277 + ucontrol->value.enumerated.item[0] = pinsel;
278 +
279 + return 0;
280 +}
281 +
282 +static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
283 + struct snd_ctl_elem_value *ucontrol)
284 +{
285 + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
286 + struct via_spec *spec = codec->spec;
287 + hda_nid_t nid = spec->autocfg.hp_pins[0];
288 + unsigned int pinsel = ucontrol->value.enumerated.item[0];
289 + unsigned int con_nid = snd_hda_codec_read(codec, nid, 0,
290 + AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
291 +
292 + if (con_nid == spec->multiout.hp_nid) {
293 + if (pinsel == 0) {
294 + if (!spec->hp_independent_mode) {
295 + if (spec->multiout.num_dacs > 1)
296 + spec->multiout.num_dacs -= 1;
297 + spec->hp_independent_mode = 1;
298 + }
299 + } else if (pinsel == 1) {
300 + if (spec->hp_independent_mode) {
301 + if (spec->multiout.num_dacs > 1)
302 + spec->multiout.num_dacs += 1;
303 + spec->hp_independent_mode = 0;
304 + }
305 + }
306 + } else {
307 + if (pinsel == 0) {
308 + if (spec->hp_independent_mode) {
309 + if (spec->multiout.num_dacs > 1)
310 + spec->multiout.num_dacs += 1;
311 + spec->hp_independent_mode = 0;
312 + }
313 + } else if (pinsel == 1) {
314 + if (!spec->hp_independent_mode) {
315 + if (spec->multiout.num_dacs > 1)
316 + spec->multiout.num_dacs -= 1;
317 + spec->hp_independent_mode = 1;
318 + }
319 + }
320 + }
321 + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
322 + pinsel);
323 +
324 + if (spec->multiout.hp_nid &&
325 + spec->multiout.hp_nid != spec->multiout.dac_nids[HDA_FRONT])
326 + snd_hda_codec_setup_stream(codec,
327 + spec->multiout.hp_nid,
328 + 0, 0, 0);
329 +
330 + return 0;
331 +}
332 +
333 +static struct snd_kcontrol_new via_hp_mixer[] = {
334 + {
335 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
336 + .name = "Independent HP",
337 + .count = 1,
338 + .info = via_independent_hp_info,
339 + .get = via_independent_hp_get,
340 + .put = via_independent_hp_put,
341 + },
342 + { } /* end */
343 +};
344 +
345 /* capture mixer elements */
346 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
347 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
348 @@ -380,6 +589,138 @@
349 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
350 }
351
352 +
353 +static void playback_multi_pcm_prep_0(struct hda_codec *codec,
354 + unsigned int stream_tag,
355 + unsigned int format,
356 + struct snd_pcm_substream *substream)
357 +{
358 + struct via_spec *spec = codec->spec;
359 + struct hda_multi_out *mout = &spec->multiout;
360 + hda_nid_t *nids = mout->dac_nids;
361 + int chs = substream->runtime->channels;
362 + int i;
363 +
364 + mutex_lock(&codec->spdif_mutex);
365 + if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
366 + if (chs == 2 &&
367 + snd_hda_is_supported_format(codec, mout->dig_out_nid,
368 + format) &&
369 + !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
370 + mout->dig_out_used = HDA_DIG_ANALOG_DUP;
371 + /* turn off SPDIF once; otherwise the IEC958 bits won't
372 + * be updated */
373 + if (codec->spdif_ctls & AC_DIG1_ENABLE)
374 + snd_hda_codec_write(codec, mout->dig_out_nid, 0,
375 + AC_VERB_SET_DIGI_CONVERT_1,
376 + codec->spdif_ctls &
377 + ~AC_DIG1_ENABLE & 0xff);
378 + snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
379 + stream_tag, 0, format);
380 + /* turn on again (if needed) */
381 + if (codec->spdif_ctls & AC_DIG1_ENABLE)
382 + snd_hda_codec_write(codec, mout->dig_out_nid, 0,
383 + AC_VERB_SET_DIGI_CONVERT_1,
384 + codec->spdif_ctls & 0xff);
385 + } else {
386 + mout->dig_out_used = 0;
387 + snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
388 + 0, 0, 0);
389 + }
390 + }
391 + mutex_unlock(&codec->spdif_mutex);
392 +
393 + /* front */
394 + snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
395 + 0, format);
396 +
397 + if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
398 + !spec->hp_independent_mode)
399 + /* headphone out will just decode front left/right (stereo) */
400 + snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
401 + 0, format);
402 +
403 + /* extra outputs copied from front */
404 + for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
405 + if (mout->extra_out_nid[i])
406 + snd_hda_codec_setup_stream(codec,
407 + mout->extra_out_nid[i],
408 + stream_tag, 0, format);
409 +
410 + /* surrounds */
411 + for (i = 1; i < mout->num_dacs; i++) {
412 + if (chs >= (i + 1) * 2) /* independent out */
413 + snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
414 + i * 2, format);
415 + else /* copy front */
416 + snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
417 + 0, format);
418 + }
419 +}
420 +
421 +static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
422 + struct hda_codec *codec,
423 + unsigned int stream_tag,
424 + unsigned int format,
425 + struct snd_pcm_substream *substream)
426 +{
427 + struct via_spec *spec = codec->spec;
428 + struct hda_multi_out *mout = &spec->multiout;
429 + hda_nid_t *nids = mout->dac_nids;
430 +
431 + if (substream->number == 0)
432 + playback_multi_pcm_prep_0(codec, stream_tag, format,
433 + substream);
434 + else {
435 + if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
436 + spec->hp_independent_mode)
437 + snd_hda_codec_setup_stream(codec, mout->hp_nid,
438 + stream_tag, 0, format);
439 + }
440 +
441 + return 0;
442 +}
443 +
444 +static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
445 + struct hda_codec *codec,
446 + struct snd_pcm_substream *substream)
447 +{
448 + struct via_spec *spec = codec->spec;
449 + struct hda_multi_out *mout = &spec->multiout;
450 + hda_nid_t *nids = mout->dac_nids;
451 + int i;
452 +
453 + if (substream->number == 0) {
454 + for (i = 0; i < mout->num_dacs; i++)
455 + snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
456 +
457 + if (mout->hp_nid && !spec->hp_independent_mode)
458 + snd_hda_codec_setup_stream(codec, mout->hp_nid,
459 + 0, 0, 0);
460 +
461 + for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
462 + if (mout->extra_out_nid[i])
463 + snd_hda_codec_setup_stream(codec,
464 + mout->extra_out_nid[i],
465 + 0, 0, 0);
466 + mutex_lock(&codec->spdif_mutex);
467 + if (mout->dig_out_nid &&
468 + mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
469 + snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
470 + 0, 0, 0);
471 + mout->dig_out_used = 0;
472 + }
473 + mutex_unlock(&codec->spdif_mutex);
474 + } else {
475 + if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
476 + spec->hp_independent_mode)
477 + snd_hda_codec_setup_stream(codec, mout->hp_nid,
478 + 0, 0, 0);
479 + }
480 +
481 + return 0;
482 +}
483 +
484 /*
485 * Digital out
486 */
487 @@ -399,6 +740,21 @@
488 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
489 }
490
491 +/* setup SPDIF output stream */
492 +static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid,
493 + unsigned int stream_tag, unsigned int format)
494 +{
495 + /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
496 + if (codec->spdif_ctls & AC_DIG1_ENABLE)
497 + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
498 + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
499 + snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
500 + /* turn on again (if needed) */
501 + if (codec->spdif_ctls & AC_DIG1_ENABLE)
502 + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
503 + codec->spdif_ctls & 0xff);
504 +}
505 +
506 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
507 struct hda_codec *codec,
508 unsigned int stream_tag,
509 @@ -406,8 +762,20 @@
510 struct snd_pcm_substream *substream)
511 {
512 struct via_spec *spec = codec->spec;
513 - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
514 - stream_tag, format, substream);
515 + hda_nid_t nid;
516 +
517 + /* 1st or 2nd S/PDIF */
518 + if (substream->number == 0)
519 + nid = spec->multiout.dig_out_nid;
520 + else if (substream->number == 1)
521 + nid = spec->extra_dig_out_nid;
522 + else
523 + return -1;
524 +
525 + mutex_lock(&codec->spdif_mutex);
526 + setup_dig_playback_stream(codec, nid, stream_tag, format);
527 + mutex_unlock(&codec->spdif_mutex);
528 + return 0;
529 }
530
531 /*
532 @@ -436,14 +804,14 @@
533 }
534
535 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
536 - .substreams = 1,
537 + .substreams = 2,
538 .channels_min = 2,
539 .channels_max = 8,
540 .nid = 0x10, /* NID to query formats and rates */
541 .ops = {
542 .open = via_playback_pcm_open,
543 - .prepare = via_playback_pcm_prepare,
544 - .cleanup = via_playback_pcm_cleanup
545 + .prepare = via_playback_multi_pcm_prepare,
546 + .cleanup = via_playback_multi_pcm_cleanup
547 },
548 };
549
550 @@ -515,6 +883,13 @@
551 if (err < 0)
552 return err;
553 spec->multiout.share_spdif = 1;
554 +
555 + if (spec->extra_dig_out_nid) {
556 + err = snd_hda_create_spdif_out_ctls(codec,
557 + spec->extra_dig_out_nid);
558 + if (err < 0)
559 + return err;
560 + }
561 }
562 if (spec->dig_in_nid) {
563 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
564 @@ -580,10 +955,89 @@
565 kfree(codec->spec);
566 }
567
568 +/* mute internal speaker if HP is plugged */
569 +static void via_hp_automute(struct hda_codec *codec)
570 +{
571 + unsigned int present;
572 + struct via_spec *spec = codec->spec;
573 +
574 + present = snd_hda_codec_read(codec, spec->autocfg.hp_pins[0], 0,
575 + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
576 + snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
577 + HDA_OUTPUT, 0, HDA_AMP_MUTE,
578 + present ? HDA_AMP_MUTE : 0);
579 +}
580 +
581 +static void via_gpio_control(struct hda_codec *codec)
582 +{
583 + unsigned int gpio_data;
584 + unsigned int vol_counter;
585 + unsigned int vol;
586 + unsigned int master_vol;
587 +
588 + struct via_spec *spec = codec->spec;
589 +
590 + gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
591 + AC_VERB_GET_GPIO_DATA, 0) & 0x03;
592 +
593 + vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
594 + 0xF84, 0) & 0x3F0000) >> 16;
595 +
596 + vol = vol_counter & 0x1F;
597 + master_vol = snd_hda_codec_read(codec, 0x1A, 0,
598 + AC_VERB_GET_AMP_GAIN_MUTE,
599 + AC_AMP_GET_INPUT);
600 +
601 + if (gpio_data == 0x02) {
602 + /* unmute line out */
603 + snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
604 + HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
605 +
606 + if (vol_counter & 0x20) {
607 + /* decrease volume */
608 + if (vol > master_vol)
609 + vol = master_vol;
610 + snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
611 + 0, HDA_AMP_VOLMASK,
612 + master_vol-vol);
613 + } else {
614 + /* increase volume */
615 + snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
616 + HDA_AMP_VOLMASK,
617 + ((master_vol+vol) > 0x2A) ? 0x2A :
618 + (master_vol+vol));
619 + }
620 + } else if (!(gpio_data & 0x02)) {
621 + /* mute line out */
622 + snd_hda_codec_amp_stereo(codec,
623 + spec->autocfg.line_out_pins[0],
624 + HDA_OUTPUT, 0, HDA_AMP_MUTE,
625 + HDA_AMP_MUTE);
626 + }
627 +}
628 +
629 +/* unsolicited event for jack sensing */
630 +static void via_unsol_event(struct hda_codec *codec,
631 + unsigned int res)
632 +{
633 + res >>= 26;
634 + if (res == VIA_HP_EVENT)
635 + via_hp_automute(codec);
636 + else if (res == VIA_GPIO_EVENT)
637 + via_gpio_control(codec);
638 +}
639 +
640 +static hda_nid_t slave_dig_outs[] = {
641 + 0,
642 +};
643 +
644 static int via_init(struct hda_codec *codec)
645 {
646 struct via_spec *spec = codec->spec;
647 - snd_hda_sequence_write(codec, spec->init_verbs);
648 + int i;
649 + for (i = 0; i < spec->num_iverbs; i++)
650 + snd_hda_sequence_write(codec, spec->init_verbs[i]);
651 +
652 /* Lydia Add for EAPD enable */
653 if (!spec->dig_in_nid) { /* No Digital In connection */
654 if (IS_VT1708_VENDORID(codec->vendor_id)) {
655 @@ -611,6 +1065,9 @@
656 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
657 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
658
659 + /* no slave outs */
660 + codec->slave_dig_outs = slave_dig_outs;
661 +
662 return 0;
663 }
664
665 @@ -657,10 +1114,10 @@
666 spec->multiout.dac_nids[i] = 0x12;
667 break;
668 case AUTO_SEQ_SURROUND:
669 - spec->multiout.dac_nids[i] = 0x13;
670 + spec->multiout.dac_nids[i] = 0x11;
671 break;
672 case AUTO_SEQ_SIDE:
673 - spec->multiout.dac_nids[i] = 0x11;
674 + spec->multiout.dac_nids[i] = 0x13;
675 break;
676 }
677 }
678 @@ -685,7 +1142,7 @@
679 continue;
680
681 if (i != AUTO_SEQ_FRONT)
682 - nid_vol = 0x1b - i + 1;
683 + nid_vol = 0x18 + i;
684
685 if (i == AUTO_SEQ_CENLFE) {
686 /* Center/LFE */
687 @@ -760,6 +1217,24 @@
688 return 0;
689 }
690
691 +static void create_hp_imux(struct via_spec *spec)
692 +{
693 + int i;
694 + struct hda_input_mux *imux = &spec->private_imux[1];
695 + static const char *texts[] = { "OFF", "ON", NULL};
696 +
697 + /* for hp mode select */
698 + i = 0;
699 + while (texts[i] != NULL) {
700 + imux->items[imux->num_items].label = texts[i];
701 + imux->items[imux->num_items].index = i;
702 + imux->num_items++;
703 + i++;
704 + }
705 +
706 + spec->hp_mux = &spec->private_imux[1];
707 +}
708 +
709 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
710 {
711 int err;
712 @@ -780,6 +1255,8 @@
713 if (err < 0)
714 return err;
715
716 + create_hp_imux(spec);
717 +
718 return 0;
719 }
720
721 @@ -790,7 +1267,7 @@
722 static char *labels[] = {
723 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
724 };
725 - struct hda_input_mux *imux = &spec->private_imux;
726 + struct hda_input_mux *imux = &spec->private_imux[0];
727 int i, err, idx = 0;
728
729 /* for internal loopback recording select */
730 @@ -840,11 +1317,36 @@
731 };
732 #endif
733
734 +static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
735 +{
736 + unsigned int def_conf;
737 + unsigned char seqassoc;
738 +
739 + def_conf = snd_hda_codec_read(codec, nid, 0,
740 + AC_VERB_GET_CONFIG_DEFAULT, 0);
741 + seqassoc = (unsigned char) get_defcfg_association(def_conf);
742 + seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
743 + if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) {
744 + if (seqassoc == 0xff) {
745 + def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
746 + snd_hda_codec_write(codec, nid, 0,
747 + AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
748 + def_conf >> 24);
749 + }
750 + }
751 +
752 + return;
753 +}
754 +
755 static int vt1708_parse_auto_config(struct hda_codec *codec)
756 {
757 struct via_spec *spec = codec->spec;
758 int err;
759
760 + /* Add HP and CD pin config connect bit re-config action */
761 + vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
762 + vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
763 +
764 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
765 if (err < 0)
766 return err;
767 @@ -874,9 +1376,12 @@
768 if (spec->kctl_alloc)
769 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
770
771 - spec->init_verbs = vt1708_volume_init_verbs;
772 + spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
773 +
774 + spec->input_mux = &spec->private_imux[0];
775
776 - spec->input_mux = &spec->private_imux;
777 + if (spec->hp_mux)
778 + spec->mixers[spec->num_mixers++] = via_hp_mixer;
779
780 return 1;
781 }
782 @@ -897,7 +1402,7 @@
783 int err;
784
785 /* create a codec specific record */
786 - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
787 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
788 if (spec == NULL)
789 return -ENOMEM;
790
791 @@ -966,6 +1471,11 @@
792 { } /* end */
793 };
794
795 +static struct hda_verb vt1709_uniwill_init_verbs[] = {
796 + {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
797 + { }
798 +};
799 +
800 /*
801 * generic initialization of ADC, input mixers and output mixers
802 */
803 @@ -1090,11 +1600,11 @@
804 break;
805 case AUTO_SEQ_SURROUND:
806 /* AOW3 */
807 - spec->multiout.dac_nids[i] = 0x27;
808 + spec->multiout.dac_nids[i] = 0x11;
809 break;
810 case AUTO_SEQ_SIDE:
811 /* AOW1 */
812 - spec->multiout.dac_nids[i] = 0x11;
813 + spec->multiout.dac_nids[i] = 0x27;
814 break;
815 default:
816 break;
817 @@ -1203,26 +1713,26 @@
818 } else if (i == AUTO_SEQ_SURROUND) {
819 sprintf(name, "%s Playback Volume", chname[i]);
820 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
821 - HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
822 + HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
823 HDA_OUTPUT));
824 if (err < 0)
825 return err;
826 sprintf(name, "%s Playback Switch", chname[i]);
827 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
828 - HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
829 + HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
830 HDA_OUTPUT));
831 if (err < 0)
832 return err;
833 } else if (i == AUTO_SEQ_SIDE) {
834 sprintf(name, "%s Playback Volume", chname[i]);
835 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
836 - HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
837 + HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
838 HDA_OUTPUT));
839 if (err < 0)
840 return err;
841 sprintf(name, "%s Playback Switch", chname[i]);
842 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
843 - HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
844 + HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
845 HDA_OUTPUT));
846 if (err < 0)
847 return err;
848 @@ -1265,7 +1775,7 @@
849 static char *labels[] = {
850 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
851 };
852 - struct hda_input_mux *imux = &spec->private_imux;
853 + struct hda_input_mux *imux = &spec->private_imux[0];
854 int i, err, idx = 0;
855
856 /* for internal loopback recording select */
857 @@ -1339,7 +1849,10 @@
858 if (spec->kctl_alloc)
859 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
860
861 - spec->input_mux = &spec->private_imux;
862 + spec->input_mux = &spec->private_imux[0];
863 +
864 + if (spec->hp_mux)
865 + spec->mixers[spec->num_mixers++] = via_hp_mixer;
866
867 return 1;
868 }
869 @@ -1360,7 +1873,7 @@
870 int err;
871
872 /* create a codec specific record */
873 - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
874 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
875 if (spec == NULL)
876 return -ENOMEM;
877
878 @@ -1375,7 +1888,8 @@
879 "Using genenic mode...\n");
880 }
881
882 - spec->init_verbs = vt1709_10ch_volume_init_verbs;
883 + spec->init_verbs[spec->num_iverbs++] = vt1709_10ch_volume_init_verbs;
884 + spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
885
886 spec->stream_name_analog = "VT1709 Analog";
887 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
888 @@ -1396,6 +1910,7 @@
889 codec->patch_ops = via_patch_ops;
890
891 codec->patch_ops.init = via_auto_init;
892 + codec->patch_ops.unsol_event = via_unsol_event;
893 #ifdef CONFIG_SND_HDA_POWER_SAVE
894 spec->loopback.amplist = vt1709_loopbacks;
895 #endif
896 @@ -1451,7 +1966,7 @@
897 int err;
898
899 /* create a codec specific record */
900 - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
901 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
902 if (spec == NULL)
903 return -ENOMEM;
904
905 @@ -1466,7 +1981,8 @@
906 "Using genenic mode...\n");
907 }
908
909 - spec->init_verbs = vt1709_6ch_volume_init_verbs;
910 + spec->init_verbs[spec->num_iverbs++] = vt1709_6ch_volume_init_verbs;
911 + spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
912
913 spec->stream_name_analog = "VT1709 Analog";
914 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
915 @@ -1487,6 +2003,7 @@
916 codec->patch_ops = via_patch_ops;
917
918 codec->patch_ops.init = via_auto_init;
919 + codec->patch_ops.unsol_event = via_unsol_event;
920 #ifdef CONFIG_SND_HDA_POWER_SAVE
921 spec->loopback.amplist = vt1709_loopbacks;
922 #endif
923 @@ -1586,27 +2103,32 @@
924 { }
925 };
926
927 +static struct hda_verb vt1708B_uniwill_init_verbs[] = {
928 + {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
929 + { }
930 +};
931 +
932 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
933 - .substreams = 1,
934 + .substreams = 2,
935 .channels_min = 2,
936 .channels_max = 8,
937 .nid = 0x10, /* NID to query formats and rates */
938 .ops = {
939 .open = via_playback_pcm_open,
940 - .prepare = via_playback_pcm_prepare,
941 - .cleanup = via_playback_pcm_cleanup
942 + .prepare = via_playback_multi_pcm_prepare,
943 + .cleanup = via_playback_multi_pcm_cleanup
944 },
945 };
946
947 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
948 - .substreams = 1,
949 + .substreams = 2,
950 .channels_min = 2,
951 .channels_max = 4,
952 .nid = 0x10, /* NID to query formats and rates */
953 .ops = {
954 .open = via_playback_pcm_open,
955 - .prepare = via_playback_pcm_prepare,
956 - .cleanup = via_playback_pcm_cleanup
957 + .prepare = via_playback_multi_pcm_prepare,
958 + .cleanup = via_playback_multi_pcm_cleanup
959 },
960 };
961
962 @@ -1662,10 +2184,10 @@
963 spec->multiout.dac_nids[i] = 0x24;
964 break;
965 case AUTO_SEQ_SURROUND:
966 - spec->multiout.dac_nids[i] = 0x25;
967 + spec->multiout.dac_nids[i] = 0x11;
968 break;
969 case AUTO_SEQ_SIDE:
970 - spec->multiout.dac_nids[i] = 0x11;
971 + spec->multiout.dac_nids[i] = 0x25;
972 break;
973 }
974 }
975 @@ -1680,7 +2202,7 @@
976 {
977 char name[32];
978 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
979 - hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
980 + hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27};
981 hda_nid_t nid, nid_vol = 0;
982 int i, err;
983
984 @@ -1785,6 +2307,8 @@
985 if (err < 0)
986 return err;
987
988 + create_hp_imux(spec);
989 +
990 return 0;
991 }
992
993 @@ -1795,7 +2319,7 @@
994 static char *labels[] = {
995 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
996 };
997 - struct hda_input_mux *imux = &spec->private_imux;
998 + struct hda_input_mux *imux = &spec->private_imux[0];
999 int i, err, idx = 0;
1000
1001 /* for internal loopback recording select */
1002 @@ -1869,7 +2393,10 @@
1003 if (spec->kctl_alloc)
1004 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1005
1006 - spec->input_mux = &spec->private_imux;
1007 + spec->input_mux = &spec->private_imux[0];
1008 +
1009 + if (spec->hp_mux)
1010 + spec->mixers[spec->num_mixers++] = via_hp_mixer;
1011
1012 return 1;
1013 }
1014 @@ -1890,7 +2417,7 @@
1015 int err;
1016
1017 /* create a codec specific record */
1018 - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1019 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1020 if (spec == NULL)
1021 return -ENOMEM;
1022
1023 @@ -1906,7 +2433,8 @@
1024 "from BIOS. Using genenic mode...\n");
1025 }
1026
1027 - spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1028 + spec->init_verbs[spec->num_iverbs++] = vt1708B_8ch_volume_init_verbs;
1029 + spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
1030
1031 spec->stream_name_analog = "VT1708B Analog";
1032 spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1033 @@ -1926,6 +2454,7 @@
1034 codec->patch_ops = via_patch_ops;
1035
1036 codec->patch_ops.init = via_auto_init;
1037 + codec->patch_ops.unsol_event = via_unsol_event;
1038 #ifdef CONFIG_SND_HDA_POWER_SAVE
1039 spec->loopback.amplist = vt1708B_loopbacks;
1040 #endif
1041 @@ -1939,7 +2468,7 @@
1042 int err;
1043
1044 /* create a codec specific record */
1045 - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1046 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1047 if (spec == NULL)
1048 return -ENOMEM;
1049
1050 @@ -1955,7 +2484,8 @@
1051 "from BIOS. Using genenic mode...\n");
1052 }
1053
1054 - spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1055 + spec->init_verbs[spec->num_iverbs++] = vt1708B_4ch_volume_init_verbs;
1056 + spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
1057
1058 spec->stream_name_analog = "VT1708B Analog";
1059 spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1060 @@ -1975,6 +2505,7 @@
1061 codec->patch_ops = via_patch_ops;
1062
1063 codec->patch_ops.init = via_auto_init;
1064 + codec->patch_ops.unsol_event = via_unsol_event;
1065 #ifdef CONFIG_SND_HDA_POWER_SAVE
1066 spec->loopback.amplist = vt1708B_loopbacks;
1067 #endif
1068 @@ -1982,6 +2513,752 @@
1069 return 0;
1070 }
1071
1072 +/* Patch for VT1708S */
1073 +
1074 +/* VT1708S software backdoor based override for buggy hardware micboost
1075 + * setting */
1076 +#define MIC_BOOST_VOLUME(xname, nid) { \
1077 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1078 + .name = xname, \
1079 + .index = 0, \
1080 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1081 + SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1082 + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
1083 + .info = mic_boost_volume_info, \
1084 + .get = snd_hda_mixer_amp_volume_get, \
1085 + .put = snd_hda_mixer_amp_volume_put, \
1086 + .tlv = { .c = mic_boost_tlv }, \
1087 + .private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT) }
1088 +
1089 +/* capture mixer elements */
1090 +static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
1091 + HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1092 + HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1093 + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1094 + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1095 + MIC_BOOST_VOLUME("Mic Boost Capture Volume", 0x1A),
1096 + MIC_BOOST_VOLUME("Front Mic Boost Capture Volume", 0x1E),
1097 + {
1098 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1099 + /* The multiple "Capture Source" controls confuse alsamixer
1100 + * So call somewhat different..
1101 + */
1102 + /* .name = "Capture Source", */
1103 + .name = "Input Source",
1104 + .count = 1,
1105 + .info = via_mux_enum_info,
1106 + .get = via_mux_enum_get,
1107 + .put = via_mux_enum_put,
1108 + },
1109 + { } /* end */
1110 +};
1111 +
1112 +static struct hda_verb vt1708S_volume_init_verbs[] = {
1113 + /* Unmute ADC0-1 and set the default input to mic-in */
1114 + {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1115 + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1116 +
1117 + /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the
1118 + * analog-loopback mixer widget */
1119 + /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1120 + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1121 + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1122 + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1123 + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1124 + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1125 +
1126 + /* Setup default input of PW4 to MW0 */
1127 + {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1128 + /* PW9, PW10 Output enable */
1129 + {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1130 + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1131 + /* Enable Mic Boost Volume backdoor */
1132 + {0x1, 0xf98, 0x1},
1133 + { }
1134 +};
1135 +
1136 +static struct hda_verb vt1708S_uniwill_init_verbs[] = {
1137 + {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
1138 + { }
1139 +};
1140 +
1141 +static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
1142 + .substreams = 2,
1143 + .channels_min = 2,
1144 + .channels_max = 8,
1145 + .nid = 0x10, /* NID to query formats and rates */
1146 + .ops = {
1147 + .open = via_playback_pcm_open,
1148 + .prepare = via_playback_pcm_prepare,
1149 + .cleanup = via_playback_pcm_cleanup
1150 + },
1151 +};
1152 +
1153 +static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
1154 + .substreams = 2,
1155 + .channels_min = 2,
1156 + .channels_max = 2,
1157 + .nid = 0x13, /* NID to query formats and rates */
1158 + .ops = {
1159 + .prepare = via_capture_pcm_prepare,
1160 + .cleanup = via_capture_pcm_cleanup
1161 + },
1162 +};
1163 +
1164 +static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
1165 + .substreams = 2,
1166 + .channels_min = 2,
1167 + .channels_max = 2,
1168 + /* NID is set in via_build_pcms */
1169 + .ops = {
1170 + .open = via_dig_playback_pcm_open,
1171 + .close = via_dig_playback_pcm_close,
1172 + .prepare = via_dig_playback_pcm_prepare
1173 + },
1174 +};
1175 +
1176 +/* fill in the dac_nids table from the parsed pin configuration */
1177 +static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
1178 + const struct auto_pin_cfg *cfg)
1179 +{
1180 + int i;
1181 + hda_nid_t nid;
1182 +
1183 + spec->multiout.num_dacs = cfg->line_outs;
1184 +
1185 + spec->multiout.dac_nids = spec->private_dac_nids;
1186 +
1187 + for (i = 0; i < 4; i++) {
1188 + nid = cfg->line_out_pins[i];
1189 + if (nid) {
1190 + /* config dac list */
1191 + switch (i) {
1192 + case AUTO_SEQ_FRONT:
1193 + spec->multiout.dac_nids[i] = 0x10;
1194 + break;
1195 + case AUTO_SEQ_CENLFE:
1196 + spec->multiout.dac_nids[i] = 0x24;
1197 + break;
1198 + case AUTO_SEQ_SURROUND:
1199 + spec->multiout.dac_nids[i] = 0x11;
1200 + break;
1201 + case AUTO_SEQ_SIDE:
1202 + spec->multiout.dac_nids[i] = 0x25;
1203 + break;
1204 + }
1205 + }
1206 + }
1207 +
1208 + return 0;
1209 +}
1210 +
1211 +/* add playback controls from the parsed DAC table */
1212 +static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
1213 + const struct auto_pin_cfg *cfg)
1214 +{
1215 + char name[32];
1216 + static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1217 + hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
1218 + hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
1219 + hda_nid_t nid, nid_vol, nid_mute;
1220 + int i, err;
1221 +
1222 + for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1223 + nid = cfg->line_out_pins[i];
1224 +
1225 + if (!nid)
1226 + continue;
1227 +
1228 + nid_vol = nid_vols[i];
1229 + nid_mute = nid_mutes[i];
1230 +
1231 + if (i == AUTO_SEQ_CENLFE) {
1232 + /* Center/LFE */
1233 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1234 + "Center Playback Volume",
1235 + HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1236 + HDA_OUTPUT));
1237 + if (err < 0)
1238 + return err;
1239 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1240 + "LFE Playback Volume",
1241 + HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1242 + HDA_OUTPUT));
1243 + if (err < 0)
1244 + return err;
1245 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1246 + "Center Playback Switch",
1247 + HDA_COMPOSE_AMP_VAL(nid_mute,
1248 + 1, 0,
1249 + HDA_OUTPUT));
1250 + if (err < 0)
1251 + return err;
1252 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1253 + "LFE Playback Switch",
1254 + HDA_COMPOSE_AMP_VAL(nid_mute,
1255 + 2, 0,
1256 + HDA_OUTPUT));
1257 + if (err < 0)
1258 + return err;
1259 + } else if (i == AUTO_SEQ_FRONT) {
1260 + /* add control to mixer index 0 */
1261 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1262 + "Master Front Playback Volume",
1263 + HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
1264 + HDA_INPUT));
1265 + if (err < 0)
1266 + return err;
1267 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1268 + "Master Front Playback Switch",
1269 + HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
1270 + HDA_INPUT));
1271 + if (err < 0)
1272 + return err;
1273 +
1274 + /* Front */
1275 + sprintf(name, "%s Playback Volume", chname[i]);
1276 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1277 + HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1278 + HDA_OUTPUT));
1279 + if (err < 0)
1280 + return err;
1281 + sprintf(name, "%s Playback Switch", chname[i]);
1282 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1283 + HDA_COMPOSE_AMP_VAL(nid_mute,
1284 + 3, 0,
1285 + HDA_OUTPUT));
1286 + if (err < 0)
1287 + return err;
1288 + } else {
1289 + sprintf(name, "%s Playback Volume", chname[i]);
1290 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1291 + HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1292 + HDA_OUTPUT));
1293 + if (err < 0)
1294 + return err;
1295 + sprintf(name, "%s Playback Switch", chname[i]);
1296 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1297 + HDA_COMPOSE_AMP_VAL(nid_mute,
1298 + 3, 0,
1299 + HDA_OUTPUT));
1300 + if (err < 0)
1301 + return err;
1302 + }
1303 + }
1304 +
1305 + return 0;
1306 +}
1307 +
1308 +static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1309 +{
1310 + int err;
1311 +
1312 + if (!pin)
1313 + return 0;
1314 +
1315 + spec->multiout.hp_nid = VT1708S_HP_NID; /* AOW3 */
1316 +
1317 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1318 + "Headphone Playback Volume",
1319 + HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
1320 + if (err < 0)
1321 + return err;
1322 +
1323 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1324 + "Headphone Playback Switch",
1325 + HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1326 + if (err < 0)
1327 + return err;
1328 +
1329 + create_hp_imux(spec);
1330 +
1331 + return 0;
1332 +}
1333 +
1334 +/* create playback/capture controls for input pins */
1335 +static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
1336 + const struct auto_pin_cfg *cfg)
1337 +{
1338 + static char *labels[] = {
1339 + "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1340 + };
1341 + struct hda_input_mux *imux = &spec->private_imux[0];
1342 + int i, err, idx = 0;
1343 +
1344 + /* for internal loopback recording select */
1345 + imux->items[imux->num_items].label = "Stereo Mixer";
1346 + imux->items[imux->num_items].index = 5;
1347 + imux->num_items++;
1348 +
1349 + for (i = 0; i < AUTO_PIN_LAST; i++) {
1350 + if (!cfg->input_pins[i])
1351 + continue;
1352 +
1353 + switch (cfg->input_pins[i]) {
1354 + case 0x1a: /* Mic */
1355 + idx = 2;
1356 + break;
1357 +
1358 + case 0x1b: /* Line In */
1359 + idx = 3;
1360 + break;
1361 +
1362 + case 0x1e: /* Front Mic */
1363 + idx = 4;
1364 + break;
1365 +
1366 + case 0x1f: /* CD */
1367 + idx = 1;
1368 + break;
1369 + }
1370 + err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1371 + idx, 0x16);
1372 + if (err < 0)
1373 + return err;
1374 + imux->items[imux->num_items].label = labels[i];
1375 + imux->items[imux->num_items].index = idx-1;
1376 + imux->num_items++;
1377 + }
1378 + return 0;
1379 +}
1380 +
1381 +static int vt1708S_parse_auto_config(struct hda_codec *codec)
1382 +{
1383 + struct via_spec *spec = codec->spec;
1384 + int err;
1385 + static hda_nid_t vt1708s_ignore[] = {0x21, 0};
1386 +
1387 + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
1388 + vt1708s_ignore);
1389 + if (err < 0)
1390 + return err;
1391 + err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg);
1392 + if (err < 0)
1393 + return err;
1394 + if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1395 + return 0; /* can't find valid BIOS pin config */
1396 +
1397 + err = vt1708S_auto_create_multi_out_ctls(spec, &spec->autocfg);
1398 + if (err < 0)
1399 + return err;
1400 + err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1401 + if (err < 0)
1402 + return err;
1403 + err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg);
1404 + if (err < 0)
1405 + return err;
1406 +
1407 + spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1408 +
1409 + if (spec->autocfg.dig_out_pin)
1410 + spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
1411 +
1412 + spec->extra_dig_out_nid = 0x15;
1413 +
1414 + if (spec->kctl_alloc)
1415 + spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1416 +
1417 + spec->input_mux = &spec->private_imux[0];
1418 +
1419 + if (spec->hp_mux)
1420 + spec->mixers[spec->num_mixers++] = via_hp_mixer;
1421 +
1422 + return 1;
1423 +}
1424 +
1425 +#ifdef CONFIG_SND_HDA_POWER_SAVE
1426 +static struct hda_amp_list vt1708S_loopbacks[] = {
1427 + { 0x16, HDA_INPUT, 1 },
1428 + { 0x16, HDA_INPUT, 2 },
1429 + { 0x16, HDA_INPUT, 3 },
1430 + { 0x16, HDA_INPUT, 4 },
1431 + { } /* end */
1432 +};
1433 +#endif
1434 +
1435 +static int patch_vt1708S(struct hda_codec *codec)
1436 +{
1437 + struct via_spec *spec;
1438 + int err;
1439 +
1440 + /* create a codec specific record */
1441 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1442 + if (spec == NULL)
1443 + return -ENOMEM;
1444 +
1445 + codec->spec = spec;
1446 +
1447 + /* automatic parse from the BIOS config */
1448 + err = vt1708S_parse_auto_config(codec);
1449 + if (err < 0) {
1450 + via_free(codec);
1451 + return err;
1452 + } else if (!err) {
1453 + printk(KERN_INFO "hda_codec: Cannot set up configuration "
1454 + "from BIOS. Using genenic mode...\n");
1455 + }
1456 +
1457 + spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
1458 + spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs;
1459 +
1460 + spec->stream_name_analog = "VT1708S Analog";
1461 + spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
1462 + spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
1463 +
1464 + spec->stream_name_digital = "VT1708S Digital";
1465 + spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
1466 +
1467 + if (!spec->adc_nids && spec->input_mux) {
1468 + spec->adc_nids = vt1708S_adc_nids;
1469 + spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids);
1470 + spec->mixers[spec->num_mixers] = vt1708S_capture_mixer;
1471 + spec->num_mixers++;
1472 + }
1473 +
1474 + codec->patch_ops = via_patch_ops;
1475 +
1476 + codec->patch_ops.init = via_auto_init;
1477 + codec->patch_ops.unsol_event = via_unsol_event;
1478 +#ifdef CONFIG_SND_HDA_POWER_SAVE
1479 + spec->loopback.amplist = vt1708S_loopbacks;
1480 +#endif
1481 +
1482 + return 0;
1483 +}
1484 +
1485 +/* Patch for VT1702 */
1486 +
1487 +/* capture mixer elements */
1488 +static struct snd_kcontrol_new vt1702_capture_mixer[] = {
1489 + HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT),
1490 + HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT),
1491 + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT),
1492 + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x20, 0x0, HDA_INPUT),
1493 + HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x1F, 0x0, HDA_INPUT),
1494 + HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x1F, 0x0, HDA_INPUT),
1495 + HDA_CODEC_VOLUME("Digital Mic Boost Capture Volume", 0x1E, 0x0,
1496 + HDA_INPUT),
1497 + {
1498 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1499 + /* The multiple "Capture Source" controls confuse alsamixer
1500 + * So call somewhat different..
1501 + */
1502 + /* .name = "Capture Source", */
1503 + .name = "Input Source",
1504 + .count = 1,
1505 + .info = via_mux_enum_info,
1506 + .get = via_mux_enum_get,
1507 + .put = via_mux_enum_put,
1508 + },
1509 + { } /* end */
1510 +};
1511 +
1512 +static struct hda_verb vt1702_volume_init_verbs[] = {
1513 + /*
1514 + * Unmute ADC0-1 and set the default input to mic-in
1515 + */
1516 + {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1517 + {0x1F, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1518 + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1519 +
1520 +
1521 + /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1522 + * mixer widget
1523 + */
1524 + /* Amp Indices: Mic1 = 1, Line = 1, Mic2 = 3 */
1525 + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1526 + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1527 + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1528 + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1529 + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1530 +
1531 + /* Setup default input of PW4 to MW0 */
1532 + {0x17, AC_VERB_SET_CONNECT_SEL, 0x1},
1533 + /* PW6 PW7 Output enable */
1534 + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1535 + {0x1C, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1536 + { }
1537 +};
1538 +
1539 +static struct hda_verb vt1702_uniwill_init_verbs[] = {
1540 + {0x01, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_GPIO_EVENT},
1541 + {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
1542 + { }
1543 +};
1544 +
1545 +static struct hda_pcm_stream vt1702_pcm_analog_playback = {
1546 + .substreams = 2,
1547 + .channels_min = 2,
1548 + .channels_max = 2,
1549 + .nid = 0x10, /* NID to query formats and rates */
1550 + .ops = {
1551 + .open = via_playback_pcm_open,
1552 + .prepare = via_playback_multi_pcm_prepare,
1553 + .cleanup = via_playback_multi_pcm_cleanup
1554 + },
1555 +};
1556 +
1557 +static struct hda_pcm_stream vt1702_pcm_analog_capture = {
1558 + .substreams = 3,
1559 + .channels_min = 2,
1560 + .channels_max = 2,
1561 + .nid = 0x12, /* NID to query formats and rates */
1562 + .ops = {
1563 + .prepare = via_capture_pcm_prepare,
1564 + .cleanup = via_capture_pcm_cleanup
1565 + },
1566 +};
1567 +
1568 +static struct hda_pcm_stream vt1702_pcm_digital_playback = {
1569 + .substreams = 2,
1570 + .channels_min = 2,
1571 + .channels_max = 2,
1572 + /* NID is set in via_build_pcms */
1573 + .ops = {
1574 + .open = via_dig_playback_pcm_open,
1575 + .close = via_dig_playback_pcm_close,
1576 + .prepare = via_dig_playback_pcm_prepare
1577 + },
1578 +};
1579 +
1580 +/* fill in the dac_nids table from the parsed pin configuration */
1581 +static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
1582 + const struct auto_pin_cfg *cfg)
1583 +{
1584 + spec->multiout.num_dacs = 1;
1585 + spec->multiout.dac_nids = spec->private_dac_nids;
1586 +
1587 + if (cfg->line_out_pins[0]) {
1588 + /* config dac list */
1589 + spec->multiout.dac_nids[0] = 0x10;
1590 + }
1591 +
1592 + return 0;
1593 +}
1594 +
1595 +/* add playback controls from the parsed DAC table */
1596 +static int vt1702_auto_create_line_out_ctls(struct via_spec *spec,
1597 + const struct auto_pin_cfg *cfg)
1598 +{
1599 + int err;
1600 +
1601 + if (!cfg->line_out_pins[0])
1602 + return -1;
1603 +
1604 + /* add control to mixer index 0 */
1605 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1606 + "Master Front Playback Volume",
1607 + HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
1608 + if (err < 0)
1609 + return err;
1610 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1611 + "Master Front Playback Switch",
1612 + HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
1613 + if (err < 0)
1614 + return err;
1615 +
1616 + /* Front */
1617 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1618 + "Front Playback Volume",
1619 + HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT));
1620 + if (err < 0)
1621 + return err;
1622 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1623 + "Front Playback Switch",
1624 + HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT));
1625 + if (err < 0)
1626 + return err;
1627 +
1628 + return 0;
1629 +}
1630 +
1631 +static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1632 +{
1633 + int err;
1634 +
1635 + if (!pin)
1636 + return 0;
1637 +
1638 + spec->multiout.hp_nid = 0x1D;
1639 +
1640 + err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1641 + "Headphone Playback Volume",
1642 + HDA_COMPOSE_AMP_VAL(0x1D, 3, 0, HDA_OUTPUT));
1643 + if (err < 0)
1644 + return err;
1645 +
1646 + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1647 + "Headphone Playback Switch",
1648 + HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1649 + if (err < 0)
1650 + return err;
1651 +
1652 + create_hp_imux(spec);
1653 +
1654 + return 0;
1655 +}
1656 +
1657 +/* create playback/capture controls for input pins */
1658 +static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec,
1659 + const struct auto_pin_cfg *cfg)
1660 +{
1661 + static char *labels[] = {
1662 + "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1663 + };
1664 + struct hda_input_mux *imux = &spec->private_imux[0];
1665 + int i, err, idx = 0;
1666 +
1667 + /* for internal loopback recording select */
1668 + imux->items[imux->num_items].label = "Stereo Mixer";
1669 + imux->items[imux->num_items].index = 3;
1670 + imux->num_items++;
1671 +
1672 + for (i = 0; i < AUTO_PIN_LAST; i++) {
1673 + if (!cfg->input_pins[i])
1674 + continue;
1675 +
1676 + switch (cfg->input_pins[i]) {
1677 + case 0x14: /* Mic */
1678 + idx = 1;
1679 + break;
1680 +
1681 + case 0x15: /* Line In */
1682 + idx = 2;
1683 + break;
1684 +
1685 + case 0x18: /* Front Mic */
1686 + idx = 3;
1687 + break;
1688 + }
1689 + err = via_new_analog_input(spec, cfg->input_pins[i],
1690 + labels[i], idx, 0x1A);
1691 + if (err < 0)
1692 + return err;
1693 + imux->items[imux->num_items].label = labels[i];
1694 + imux->items[imux->num_items].index = idx-1;
1695 + imux->num_items++;
1696 + }
1697 + return 0;
1698 +}
1699 +
1700 +static int vt1702_parse_auto_config(struct hda_codec *codec)
1701 +{
1702 + struct via_spec *spec = codec->spec;
1703 + int err;
1704 + static hda_nid_t vt1702_ignore[] = {0x1C, 0};
1705 +
1706 + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
1707 + vt1702_ignore);
1708 + if (err < 0)
1709 + return err;
1710 + err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg);
1711 + if (err < 0)
1712 + return err;
1713 + if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1714 + return 0; /* can't find valid BIOS pin config */
1715 +
1716 + err = vt1702_auto_create_line_out_ctls(spec, &spec->autocfg);
1717 + if (err < 0)
1718 + return err;
1719 + err = vt1702_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1720 + if (err < 0)
1721 + return err;
1722 + err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg);
1723 + if (err < 0)
1724 + return err;
1725 +
1726 + spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1727 +
1728 + if (spec->autocfg.dig_out_pin)
1729 + spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
1730 +
1731 + spec->extra_dig_out_nid = 0x1B;
1732 +
1733 + if (spec->kctl_alloc)
1734 + spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1735 +
1736 + spec->input_mux = &spec->private_imux[0];
1737 +
1738 + if (spec->hp_mux)
1739 + spec->mixers[spec->num_mixers++] = via_hp_mixer;
1740 +
1741 + return 1;
1742 +}
1743 +
1744 +#ifdef CONFIG_SND_HDA_POWER_SAVE
1745 +static struct hda_amp_list vt1702_loopbacks[] = {
1746 + { 0x1A, HDA_INPUT, 1 },
1747 + { 0x1A, HDA_INPUT, 2 },
1748 + { 0x1A, HDA_INPUT, 3 },
1749 + { 0x1A, HDA_INPUT, 4 },
1750 + { } /* end */
1751 +};
1752 +#endif
1753 +
1754 +static int patch_vt1702(struct hda_codec *codec)
1755 +{
1756 + struct via_spec *spec;
1757 + int err;
1758 + unsigned int response;
1759 + unsigned char control;
1760 +
1761 + /* create a codec specific record */
1762 + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1763 + if (spec == NULL)
1764 + return -ENOMEM;
1765 +
1766 + codec->spec = spec;
1767 +
1768 + /* automatic parse from the BIOS config */
1769 + err = vt1702_parse_auto_config(codec);
1770 + if (err < 0) {
1771 + via_free(codec);
1772 + return err;
1773 + } else if (!err) {
1774 + printk(KERN_INFO "hda_codec: Cannot set up configuration "
1775 + "from BIOS. Using genenic mode...\n");
1776 + }
1777 +
1778 + spec->init_verbs[spec->num_iverbs++] = vt1702_volume_init_verbs;
1779 + spec->init_verbs[spec->num_iverbs++] = vt1702_uniwill_init_verbs;
1780 +
1781 + spec->stream_name_analog = "VT1702 Analog";
1782 + spec->stream_analog_playback = &vt1702_pcm_analog_playback;
1783 + spec->stream_analog_capture = &vt1702_pcm_analog_capture;
1784 +
1785 + spec->stream_name_digital = "VT1702 Digital";
1786 + spec->stream_digital_playback = &vt1702_pcm_digital_playback;
1787 +
1788 + if (!spec->adc_nids && spec->input_mux) {
1789 + spec->adc_nids = vt1702_adc_nids;
1790 + spec->num_adc_nids = ARRAY_SIZE(vt1702_adc_nids);
1791 + spec->mixers[spec->num_mixers] = vt1702_capture_mixer;
1792 + spec->num_mixers++;
1793 + }
1794 +
1795 + codec->patch_ops = via_patch_ops;
1796 +
1797 + codec->patch_ops.init = via_auto_init;
1798 + codec->patch_ops.unsol_event = via_unsol_event;
1799 +#ifdef CONFIG_SND_HDA_POWER_SAVE
1800 + spec->loopback.amplist = vt1702_loopbacks;
1801 +#endif
1802 +
1803 + /* Open backdoor */
1804 + response = snd_hda_codec_read(codec, codec->afg, 0, 0xF8C, 0);
1805 + control = (unsigned char)(response & 0xff);
1806 + control |= 0x3;
1807 + snd_hda_codec_write(codec, codec->afg, 0, 0xF88, control);
1808 +
1809 + /* Enable GPIO 0&1 for volume&mute control */
1810 + /* Enable GPIO 2 for DMIC-DATA */
1811 + response = snd_hda_codec_read(codec, codec->afg, 0, 0xF84, 0);
1812 + control = (unsigned char)((response >> 16) & 0x3f);
1813 + snd_hda_codec_write(codec, codec->afg, 0, 0xF82, control);
1814 +
1815 + return 0;
1816 +}
1817 +
1818 /*
1819 * patch entries
1820 */
1821 @@ -2022,5 +3299,37 @@
1822 .patch = patch_vt1708B_4ch},
1823 { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
1824 .patch = patch_vt1708B_4ch},
1825 + { .id = 0x11060397, .name = "VIA VT1708S",
1826 + .patch = patch_vt1708S},
1827 + { .id = 0x11061397, .name = "VIA VT1708S",
1828 + .patch = patch_vt1708S},
1829 + { .id = 0x11062397, .name = "VIA VT1708S",
1830 + .patch = patch_vt1708S},
1831 + { .id = 0x11063397, .name = "VIA VT1708S",
1832 + .patch = patch_vt1708S},
1833 + { .id = 0x11064397, .name = "VIA VT1708S",
1834 + .patch = patch_vt1708S},
1835 + { .id = 0x11065397, .name = "VIA VT1708S",
1836 + .patch = patch_vt1708S},
1837 + { .id = 0x11066397, .name = "VIA VT1708S",
1838 + .patch = patch_vt1708S},
1839 + { .id = 0x11067397, .name = "VIA VT1708S",
1840 + .patch = patch_vt1708S},
1841 + { .id = 0x11060398, .name = "VIA VT1702",
1842 + .patch = patch_vt1702},
1843 + { .id = 0x11061398, .name = "VIA VT1702",
1844 + .patch = patch_vt1702},
1845 + { .id = 0x11062398, .name = "VIA VT1702",
1846 + .patch = patch_vt1702},
1847 + { .id = 0x11063398, .name = "VIA VT1702",
1848 + .patch = patch_vt1702},
1849 + { .id = 0x11064398, .name = "VIA VT1702",
1850 + .patch = patch_vt1702},
1851 + { .id = 0x11065398, .name = "VIA VT1702",
1852 + .patch = patch_vt1702},
1853 + { .id = 0x11066398, .name = "VIA VT1702",
1854 + .patch = patch_vt1702},
1855 + { .id = 0x11067398, .name = "VIA VT1702",
1856 + .patch = patch_vt1702},
1857 {} /* terminator */
1858 };