]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.drivers/alsa-hda-via-update
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / alsa-hda-via-update
CommitLineData
00e5a55c
BS
1From: Takashi Iwai <tiwai@suse.de>
2Subject: ALSA: hda - VIA codecs updates
3Patch-mainline: 2.6.28-rc1
4References:
5
6A pile of updates for VIA HD-audio codecs.
7
8Signed-off-by: Takashi Iwai <tiwai@suse.de>
9
10---
11diff -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 };