[ALSA] sound: hda: missing includes of hda_patch.h
[linux-2.6-block.git] / sound / pci / hda / patch_via.c
CommitLineData
c577b8a1
JC
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for VIA VT1708 codec
5 *
6 * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
7 * Takashi Iwai <tiwai@suse.de>
8 *
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25/* */
26/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
27/* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */
28/* 2006-08-02 Lydia Wang Add support to VT1709 codec */
29/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
f7278fd0
JC
30/* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
31/* 2007-09-17 Lydia Wang Add VT1708B codec support */
c577b8a1
JC
32/* */
33/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
34
35
c577b8a1
JC
36#include <linux/init.h>
37#include <linux/delay.h>
38#include <linux/slab.h>
c577b8a1
JC
39#include <sound/core.h>
40#include "hda_codec.h"
41#include "hda_local.h"
3c9a3203 42#include "hda_patch.h"
c577b8a1
JC
43
44/* amp values */
45#define AMP_VAL_IDX_SHIFT 19
46#define AMP_VAL_IDX_MASK (0x0f<<19)
47
48#define NUM_CONTROL_ALLOC 32
49#define NUM_VERB_ALLOC 32
50
51/* Pin Widget NID */
52#define VT1708_HP_NID 0x13
53#define VT1708_DIGOUT_NID 0x14
54#define VT1708_DIGIN_NID 0x16
f7278fd0 55#define VT1708_DIGIN_PIN 0x26
c577b8a1
JC
56
57#define VT1709_HP_DAC_NID 0x28
58#define VT1709_DIGOUT_NID 0x13
59#define VT1709_DIGIN_NID 0x17
f7278fd0
JC
60#define VT1709_DIGIN_PIN 0x25
61
62#define VT1708B_HP_NID 0x25
63#define VT1708B_DIGOUT_NID 0x12
64#define VT1708B_DIGIN_NID 0x15
65#define VT1708B_DIGIN_PIN 0x21
c577b8a1
JC
66
67#define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
68#define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
69#define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
f7278fd0
JC
70#define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
71#define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
c577b8a1
JC
72
73
74enum {
75 VIA_CTL_WIDGET_VOL,
76 VIA_CTL_WIDGET_MUTE,
77};
78
79enum {
80 AUTO_SEQ_FRONT,
81 AUTO_SEQ_SURROUND,
82 AUTO_SEQ_CENLFE,
83 AUTO_SEQ_SIDE
84};
85
86static struct snd_kcontrol_new vt1708_control_templates[] = {
87 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
88 HDA_CODEC_MUTE(NULL, 0, 0, 0),
89};
90
91
92struct via_spec {
93 /* codec parameterization */
94 struct snd_kcontrol_new *mixers[3];
95 unsigned int num_mixers;
96
97 struct hda_verb *init_verbs;
98
99 char *stream_name_analog;
100 struct hda_pcm_stream *stream_analog_playback;
101 struct hda_pcm_stream *stream_analog_capture;
102
103 char *stream_name_digital;
104 struct hda_pcm_stream *stream_digital_playback;
105 struct hda_pcm_stream *stream_digital_capture;
106
107 /* playback */
108 struct hda_multi_out multiout;
109
110 /* capture */
111 unsigned int num_adc_nids;
112 hda_nid_t *adc_nids;
113 hda_nid_t dig_in_nid;
114
115 /* capture source */
116 const struct hda_input_mux *input_mux;
117 unsigned int cur_mux[3];
118
119 /* PCM information */
120 struct hda_pcm pcm_rec[2];
121
122 /* dynamic controls, init_verbs and input_mux */
123 struct auto_pin_cfg autocfg;
124 unsigned int num_kctl_alloc, num_kctl_used;
125 struct snd_kcontrol_new *kctl_alloc;
126 struct hda_input_mux private_imux;
41923e44 127 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
cb53c626
TI
128
129#ifdef CONFIG_SND_HDA_POWER_SAVE
130 struct hda_loopback_check loopback;
131#endif
c577b8a1
JC
132};
133
134static hda_nid_t vt1708_adc_nids[2] = {
135 /* ADC1-2 */
136 0x15, 0x27
137};
138
139static hda_nid_t vt1709_adc_nids[3] = {
140 /* ADC1-2 */
141 0x14, 0x15, 0x16
142};
143
f7278fd0
JC
144static hda_nid_t vt1708B_adc_nids[2] = {
145 /* ADC1-2 */
146 0x13, 0x14
147};
148
c577b8a1
JC
149/* add dynamic controls */
150static int via_add_control(struct via_spec *spec, int type, const char *name,
151 unsigned long val)
152{
153 struct snd_kcontrol_new *knew;
154
155 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
156 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
157
158 /* array + terminator */
159 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
160 if (!knew)
161 return -ENOMEM;
162 if (spec->kctl_alloc) {
163 memcpy(knew, spec->kctl_alloc,
164 sizeof(*knew) * spec->num_kctl_alloc);
165 kfree(spec->kctl_alloc);
166 }
167 spec->kctl_alloc = knew;
168 spec->num_kctl_alloc = num;
169 }
170
171 knew = &spec->kctl_alloc[spec->num_kctl_used];
172 *knew = vt1708_control_templates[type];
173 knew->name = kstrdup(name, GFP_KERNEL);
174
175 if (!knew->name)
176 return -ENOMEM;
177 knew->private_value = val;
178 spec->num_kctl_used++;
179 return 0;
180}
181
182/* create input playback/capture controls for the given pin */
183static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
184 const char *ctlname, int idx, int mix_nid)
185{
186 char name[32];
187 int err;
188
189 sprintf(name, "%s Playback Volume", ctlname);
190 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
191 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
192 if (err < 0)
193 return err;
194 sprintf(name, "%s Playback Switch", ctlname);
195 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
196 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
197 if (err < 0)
198 return err;
199 return 0;
200}
201
202static void via_auto_set_output_and_unmute(struct hda_codec *codec,
203 hda_nid_t nid, int pin_type,
204 int dac_idx)
205{
206 /* set as output */
207 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
208 pin_type);
209 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
210 AMP_OUT_UNMUTE);
211}
212
213
214static void via_auto_init_multi_out(struct hda_codec *codec)
215{
216 struct via_spec *spec = codec->spec;
217 int i;
218
219 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
220 hda_nid_t nid = spec->autocfg.line_out_pins[i];
221 if (nid)
222 via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
223 }
224}
225
226static void via_auto_init_hp_out(struct hda_codec *codec)
227{
228 struct via_spec *spec = codec->spec;
229 hda_nid_t pin;
230
231 pin = spec->autocfg.hp_pins[0];
232 if (pin) /* connect to front */
233 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
234}
235
236static void via_auto_init_analog_input(struct hda_codec *codec)
237{
238 struct via_spec *spec = codec->spec;
239 int i;
240
241 for (i = 0; i < AUTO_PIN_LAST; i++) {
242 hda_nid_t nid = spec->autocfg.input_pins[i];
243
244 snd_hda_codec_write(codec, nid, 0,
245 AC_VERB_SET_PIN_WIDGET_CONTROL,
246 (i <= AUTO_PIN_FRONT_MIC ?
247 PIN_VREF50 : PIN_IN));
248
249 }
250}
251/*
252 * input MUX handling
253 */
254static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_info *uinfo)
256{
257 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258 struct via_spec *spec = codec->spec;
259 return snd_hda_input_mux_info(spec->input_mux, uinfo);
260}
261
262static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
263 struct snd_ctl_elem_value *ucontrol)
264{
265 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
266 struct via_spec *spec = codec->spec;
267 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
268
269 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
270 return 0;
271}
272
273static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
275{
276 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
277 struct via_spec *spec = codec->spec;
278 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
279 unsigned int vendor_id = codec->vendor_id;
280
281 /* AIW0 lydia 060801 add for correct sw0 input select */
282 if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
283 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
284 0x18, &spec->cur_mux[adc_idx]);
285 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
f7278fd0 286 IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0)
c577b8a1
JC
287 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
288 0x19, &spec->cur_mux[adc_idx]);
f7278fd0
JC
289 else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
290 IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0)
291 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
292 0x17, &spec->cur_mux[adc_idx]);
c577b8a1
JC
293 else
294 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
295 spec->adc_nids[adc_idx],
296 &spec->cur_mux[adc_idx]);
297}
298
299/* capture mixer elements */
300static struct snd_kcontrol_new vt1708_capture_mixer[] = {
301 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
302 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
303 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
304 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
305 {
306 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
307 /* The multiple "Capture Source" controls confuse alsamixer
308 * So call somewhat different..
c577b8a1
JC
309 */
310 /* .name = "Capture Source", */
311 .name = "Input Source",
312 .count = 1,
313 .info = via_mux_enum_info,
314 .get = via_mux_enum_get,
315 .put = via_mux_enum_put,
316 },
317 { } /* end */
318};
319/*
320 * generic initialization of ADC, input mixers and output mixers
321 */
322static struct hda_verb vt1708_volume_init_verbs[] = {
323 /*
324 * Unmute ADC0-1 and set the default input to mic-in
325 */
326 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
327 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
328
329
f7278fd0 330 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
c577b8a1
JC
331 * mixer widget
332 */
333 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
f7278fd0
JC
334 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
335 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
336 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
337 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
338 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
c577b8a1
JC
339
340 /*
341 * Set up output mixers (0x19 - 0x1b)
342 */
343 /* set vol=0 to output mixers */
344 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
345 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
346 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
347
348 /* Setup default input to PW4 */
349 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
c577b8a1
JC
350 /* PW9 Output enable */
351 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
f7278fd0 352 { }
c577b8a1
JC
353};
354
355static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
356 struct hda_codec *codec,
357 struct snd_pcm_substream *substream)
358{
359 struct via_spec *spec = codec->spec;
9a08160b
TI
360 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
361 hinfo);
c577b8a1
JC
362}
363
364static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
365 struct hda_codec *codec,
366 unsigned int stream_tag,
367 unsigned int format,
368 struct snd_pcm_substream *substream)
369{
370 struct via_spec *spec = codec->spec;
371 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
372 stream_tag, format, substream);
373}
374
375static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
376 struct hda_codec *codec,
377 struct snd_pcm_substream *substream)
378{
379 struct via_spec *spec = codec->spec;
380 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
381}
382
383/*
384 * Digital out
385 */
386static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
387 struct hda_codec *codec,
388 struct snd_pcm_substream *substream)
389{
390 struct via_spec *spec = codec->spec;
391 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
392}
393
394static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
395 struct hda_codec *codec,
396 struct snd_pcm_substream *substream)
397{
398 struct via_spec *spec = codec->spec;
399 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
400}
401
6b97eb45
TI
402static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
403 struct hda_codec *codec,
404 unsigned int stream_tag,
405 unsigned int format,
406 struct snd_pcm_substream *substream)
407{
408 struct via_spec *spec = codec->spec;
409 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
410 stream_tag, format, substream);
411}
412
c577b8a1
JC
413/*
414 * Analog capture
415 */
416static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
417 struct hda_codec *codec,
418 unsigned int stream_tag,
419 unsigned int format,
420 struct snd_pcm_substream *substream)
421{
422 struct via_spec *spec = codec->spec;
423
424 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
425 stream_tag, 0, format);
426 return 0;
427}
428
429static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
430 struct hda_codec *codec,
431 struct snd_pcm_substream *substream)
432{
433 struct via_spec *spec = codec->spec;
434 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
435 0, 0, 0);
436 return 0;
437}
438
439static struct hda_pcm_stream vt1708_pcm_analog_playback = {
440 .substreams = 1,
441 .channels_min = 2,
442 .channels_max = 8,
443 .nid = 0x10, /* NID to query formats and rates */
444 .ops = {
445 .open = via_playback_pcm_open,
446 .prepare = via_playback_pcm_prepare,
447 .cleanup = via_playback_pcm_cleanup
448 },
449};
450
451static struct hda_pcm_stream vt1708_pcm_analog_capture = {
452 .substreams = 2,
453 .channels_min = 2,
454 .channels_max = 2,
455 .nid = 0x15, /* NID to query formats and rates */
456 .ops = {
457 .prepare = via_capture_pcm_prepare,
458 .cleanup = via_capture_pcm_cleanup
459 },
460};
461
462static struct hda_pcm_stream vt1708_pcm_digital_playback = {
463 .substreams = 1,
464 .channels_min = 2,
465 .channels_max = 2,
466 /* NID is set in via_build_pcms */
467 .ops = {
468 .open = via_dig_playback_pcm_open,
6b97eb45
TI
469 .close = via_dig_playback_pcm_close,
470 .prepare = via_dig_playback_pcm_prepare
c577b8a1
JC
471 },
472};
473
474static struct hda_pcm_stream vt1708_pcm_digital_capture = {
475 .substreams = 1,
476 .channels_min = 2,
477 .channels_max = 2,
478};
479
480static int via_build_controls(struct hda_codec *codec)
481{
482 struct via_spec *spec = codec->spec;
483 int err;
484 int i;
485
486 for (i = 0; i < spec->num_mixers; i++) {
487 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
488 if (err < 0)
489 return err;
490 }
491
492 if (spec->multiout.dig_out_nid) {
493 err = snd_hda_create_spdif_out_ctls(codec,
494 spec->multiout.dig_out_nid);
495 if (err < 0)
496 return err;
9a08160b
TI
497 err = snd_hda_create_spdif_share_sw(codec,
498 &spec->multiout);
499 if (err < 0)
500 return err;
501 spec->multiout.share_spdif = 1;
c577b8a1
JC
502 }
503 if (spec->dig_in_nid) {
504 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
505 if (err < 0)
506 return err;
507 }
508 return 0;
509}
510
511static int via_build_pcms(struct hda_codec *codec)
512{
513 struct via_spec *spec = codec->spec;
514 struct hda_pcm *info = spec->pcm_rec;
515
516 codec->num_pcms = 1;
517 codec->pcm_info = info;
518
519 info->name = spec->stream_name_analog;
520 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
521 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
522 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
523 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
524
525 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
526 spec->multiout.max_channels;
527
528 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
529 codec->num_pcms++;
530 info++;
531 info->name = spec->stream_name_digital;
7ba72ba1 532 info->pcm_type = HDA_PCM_TYPE_SPDIF;
c577b8a1
JC
533 if (spec->multiout.dig_out_nid) {
534 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
535 *(spec->stream_digital_playback);
536 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
537 spec->multiout.dig_out_nid;
538 }
539 if (spec->dig_in_nid) {
540 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
541 *(spec->stream_digital_capture);
542 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
543 spec->dig_in_nid;
544 }
545 }
546
547 return 0;
548}
549
550static void via_free(struct hda_codec *codec)
551{
552 struct via_spec *spec = codec->spec;
553 unsigned int i;
554
555 if (!spec)
556 return;
557
558 if (spec->kctl_alloc) {
559 for (i = 0; i < spec->num_kctl_used; i++)
560 kfree(spec->kctl_alloc[i].name);
561 kfree(spec->kctl_alloc);
562 }
563
564 kfree(codec->spec);
565}
566
567static int via_init(struct hda_codec *codec)
568{
569 struct via_spec *spec = codec->spec;
570 snd_hda_sequence_write(codec, spec->init_verbs);
f7278fd0
JC
571 /* Lydia Add for EAPD enable */
572 if (!spec->dig_in_nid) { /* No Digital In connection */
573 if (IS_VT1708_VENDORID(codec->vendor_id)) {
574 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
575 AC_VERB_SET_PIN_WIDGET_CONTROL,
12b74c80 576 PIN_OUT);
f7278fd0
JC
577 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
578 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
579 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
580 IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
581 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
582 AC_VERB_SET_PIN_WIDGET_CONTROL,
12b74c80 583 PIN_OUT);
f7278fd0
JC
584 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
585 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
586 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
587 IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
588 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
589 AC_VERB_SET_PIN_WIDGET_CONTROL,
12b74c80 590 PIN_OUT);
f7278fd0
JC
591 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
592 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
593 }
12b74c80
TI
594 } else /* enable SPDIF-input pin */
595 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
596 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
f7278fd0 597
c577b8a1
JC
598 return 0;
599}
600
cb53c626
TI
601#ifdef CONFIG_SND_HDA_POWER_SAVE
602static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
603{
604 struct via_spec *spec = codec->spec;
605 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
606}
607#endif
608
c577b8a1
JC
609/*
610 */
611static struct hda_codec_ops via_patch_ops = {
612 .build_controls = via_build_controls,
613 .build_pcms = via_build_pcms,
614 .init = via_init,
615 .free = via_free,
cb53c626
TI
616#ifdef CONFIG_SND_HDA_POWER_SAVE
617 .check_power_status = via_check_power_status,
618#endif
c577b8a1
JC
619};
620
621/* fill in the dac_nids table from the parsed pin configuration */
622static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
623 const struct auto_pin_cfg *cfg)
624{
625 int i;
626 hda_nid_t nid;
627
628 spec->multiout.num_dacs = cfg->line_outs;
629
630 spec->multiout.dac_nids = spec->private_dac_nids;
631
632 for(i = 0; i < 4; i++) {
633 nid = cfg->line_out_pins[i];
634 if (nid) {
635 /* config dac list */
636 switch (i) {
637 case AUTO_SEQ_FRONT:
638 spec->multiout.dac_nids[i] = 0x10;
639 break;
640 case AUTO_SEQ_CENLFE:
641 spec->multiout.dac_nids[i] = 0x12;
642 break;
643 case AUTO_SEQ_SURROUND:
644 spec->multiout.dac_nids[i] = 0x13;
645 break;
646 case AUTO_SEQ_SIDE:
647 spec->multiout.dac_nids[i] = 0x11;
648 break;
649 }
650 }
651 }
652
653 return 0;
654}
655
656/* add playback controls from the parsed DAC table */
657static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
658 const struct auto_pin_cfg *cfg)
659{
660 char name[32];
661 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
662 hda_nid_t nid, nid_vol = 0;
663 int i, err;
664
665 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
666 nid = cfg->line_out_pins[i];
667
668 if (!nid)
669 continue;
670
671 if (i != AUTO_SEQ_FRONT)
672 nid_vol = 0x1b - i + 1;
673
674 if (i == AUTO_SEQ_CENLFE) {
675 /* Center/LFE */
676 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
f7278fd0
JC
677 "Center Playback Volume",
678 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
679 HDA_OUTPUT));
c577b8a1
JC
680 if (err < 0)
681 return err;
682 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
683 "LFE Playback Volume",
f7278fd0
JC
684 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
685 HDA_OUTPUT));
c577b8a1
JC
686 if (err < 0)
687 return err;
688 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
689 "Center Playback Switch",
f7278fd0
JC
690 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
691 HDA_OUTPUT));
c577b8a1
JC
692 if (err < 0)
693 return err;
694 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
695 "LFE Playback Switch",
f7278fd0
JC
696 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
697 HDA_OUTPUT));
c577b8a1
JC
698 if (err < 0)
699 return err;
700 } else if (i == AUTO_SEQ_FRONT){
701 /* add control to mixer index 0 */
702 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
703 "Master Front Playback Volume",
f7278fd0
JC
704 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
705 HDA_INPUT));
c577b8a1
JC
706 if (err < 0)
707 return err;
708 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
709 "Master Front Playback Switch",
f7278fd0
JC
710 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
711 HDA_INPUT));
c577b8a1
JC
712 if (err < 0)
713 return err;
714
715 /* add control to PW3 */
716 sprintf(name, "%s Playback Volume", chname[i]);
717 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
718 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
719 HDA_OUTPUT));
c577b8a1
JC
720 if (err < 0)
721 return err;
722 sprintf(name, "%s Playback Switch", chname[i]);
723 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
724 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
725 HDA_OUTPUT));
c577b8a1
JC
726 if (err < 0)
727 return err;
728 } else {
729 sprintf(name, "%s Playback Volume", chname[i]);
730 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
731 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
732 HDA_OUTPUT));
c577b8a1
JC
733 if (err < 0)
734 return err;
735 sprintf(name, "%s Playback Switch", chname[i]);
736 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
737 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
738 HDA_OUTPUT));
c577b8a1
JC
739 if (err < 0)
740 return err;
741 }
742 }
743
744 return 0;
745}
746
747static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
748{
749 int err;
750
751 if (!pin)
752 return 0;
753
754 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
755
756 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
757 "Headphone Playback Volume",
758 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
759 if (err < 0)
760 return err;
761 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
762 "Headphone Playback Switch",
763 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
764 if (err < 0)
765 return err;
766
767 return 0;
768}
769
770/* create playback/capture controls for input pins */
771static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
772 const struct auto_pin_cfg *cfg)
773{
774 static char *labels[] = {
775 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
776 };
777 struct hda_input_mux *imux = &spec->private_imux;
778 int i, err, idx = 0;
779
780 /* for internal loopback recording select */
781 imux->items[imux->num_items].label = "Stereo Mixer";
782 imux->items[imux->num_items].index = idx;
783 imux->num_items++;
784
785 for (i = 0; i < AUTO_PIN_LAST; i++) {
786 if (!cfg->input_pins[i])
787 continue;
788
789 switch (cfg->input_pins[i]) {
790 case 0x1d: /* Mic */
791 idx = 2;
792 break;
793
794 case 0x1e: /* Line In */
795 idx = 3;
796 break;
797
798 case 0x21: /* Front Mic */
799 idx = 4;
800 break;
801
802 case 0x24: /* CD */
803 idx = 1;
804 break;
805 }
806 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
807 idx, 0x17);
808 if (err < 0)
809 return err;
810 imux->items[imux->num_items].label = labels[i];
811 imux->items[imux->num_items].index = idx;
812 imux->num_items++;
813 }
814 return 0;
815}
816
cb53c626
TI
817#ifdef CONFIG_SND_HDA_POWER_SAVE
818static struct hda_amp_list vt1708_loopbacks[] = {
819 { 0x17, HDA_INPUT, 1 },
820 { 0x17, HDA_INPUT, 2 },
821 { 0x17, HDA_INPUT, 3 },
822 { 0x17, HDA_INPUT, 4 },
823 { } /* end */
824};
825#endif
826
c577b8a1
JC
827static int vt1708_parse_auto_config(struct hda_codec *codec)
828{
829 struct via_spec *spec = codec->spec;
830 int err;
831
832 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
833 if (err < 0)
834 return err;
835 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
836 if (err < 0)
837 return err;
838 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
839 return 0; /* can't find valid BIOS pin config */
840
841 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
842 if (err < 0)
843 return err;
844 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
845 if (err < 0)
846 return err;
847 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
848 if (err < 0)
849 return err;
850
851 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
852
853 if (spec->autocfg.dig_out_pin)
854 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
855 if (spec->autocfg.dig_in_pin)
856 spec->dig_in_nid = VT1708_DIGIN_NID;
857
858 if (spec->kctl_alloc)
859 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
860
861 spec->init_verbs = vt1708_volume_init_verbs;
862
863 spec->input_mux = &spec->private_imux;
864
865 return 1;
866}
867
868/* init callback for auto-configuration model -- overriding the default init */
869static int via_auto_init(struct hda_codec *codec)
870{
871 via_init(codec);
872 via_auto_init_multi_out(codec);
873 via_auto_init_hp_out(codec);
874 via_auto_init_analog_input(codec);
875 return 0;
876}
877
878static int patch_vt1708(struct hda_codec *codec)
879{
880 struct via_spec *spec;
881 int err;
882
883 /* create a codec specific record */
884 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
885 if (spec == NULL)
886 return -ENOMEM;
887
888 codec->spec = spec;
889
890 /* automatic parse from the BIOS config */
891 err = vt1708_parse_auto_config(codec);
892 if (err < 0) {
893 via_free(codec);
894 return err;
895 } else if (!err) {
896 printk(KERN_INFO "hda_codec: Cannot set up configuration "
897 "from BIOS. Using genenic mode...\n");
898 }
899
900
901 spec->stream_name_analog = "VT1708 Analog";
902 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
903 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
904
905 spec->stream_name_digital = "VT1708 Digital";
906 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
907 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
908
909
910 if (!spec->adc_nids && spec->input_mux) {
911 spec->adc_nids = vt1708_adc_nids;
912 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
913 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
914 spec->num_mixers++;
915 }
916
917 codec->patch_ops = via_patch_ops;
918
919 codec->patch_ops.init = via_auto_init;
cb53c626
TI
920#ifdef CONFIG_SND_HDA_POWER_SAVE
921 spec->loopback.amplist = vt1708_loopbacks;
922#endif
c577b8a1
JC
923
924 return 0;
925}
926
927/* capture mixer elements */
928static struct snd_kcontrol_new vt1709_capture_mixer[] = {
929 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
930 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
931 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
932 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
933 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
934 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
935 {
936 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
937 /* The multiple "Capture Source" controls confuse alsamixer
938 * So call somewhat different..
c577b8a1
JC
939 */
940 /* .name = "Capture Source", */
941 .name = "Input Source",
942 .count = 1,
943 .info = via_mux_enum_info,
944 .get = via_mux_enum_get,
945 .put = via_mux_enum_put,
946 },
947 { } /* end */
948};
949
950/*
951 * generic initialization of ADC, input mixers and output mixers
952 */
953static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
954 /*
955 * Unmute ADC0-2 and set the default input to mic-in
956 */
957 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
958 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
959 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
960
961
f7278fd0 962 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
c577b8a1
JC
963 * mixer widget
964 */
965 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
f7278fd0
JC
966 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
967 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
968 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
969 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
970 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
c577b8a1
JC
971
972 /*
973 * Set up output selector (0x1a, 0x1b, 0x29)
974 */
975 /* set vol=0 to output mixers */
976 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
977 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
978 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
979
980 /*
981 * Unmute PW3 and PW4
982 */
983 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
984 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
985
986 /* Set input of PW4 as AOW4 */
987 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
c577b8a1
JC
988 /* PW9 Output enable */
989 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
990 { }
991};
992
993static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
994 .substreams = 1,
995 .channels_min = 2,
996 .channels_max = 10,
997 .nid = 0x10, /* NID to query formats and rates */
998 .ops = {
999 .open = via_playback_pcm_open,
1000 .prepare = via_playback_pcm_prepare,
1001 .cleanup = via_playback_pcm_cleanup
1002 },
1003};
1004
1005static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1006 .substreams = 1,
1007 .channels_min = 2,
1008 .channels_max = 6,
1009 .nid = 0x10, /* NID to query formats and rates */
1010 .ops = {
1011 .open = via_playback_pcm_open,
1012 .prepare = via_playback_pcm_prepare,
1013 .cleanup = via_playback_pcm_cleanup
1014 },
1015};
1016
1017static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1018 .substreams = 2,
1019 .channels_min = 2,
1020 .channels_max = 2,
1021 .nid = 0x14, /* NID to query formats and rates */
1022 .ops = {
1023 .prepare = via_capture_pcm_prepare,
1024 .cleanup = via_capture_pcm_cleanup
1025 },
1026};
1027
1028static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1029 .substreams = 1,
1030 .channels_min = 2,
1031 .channels_max = 2,
1032 /* NID is set in via_build_pcms */
1033 .ops = {
1034 .open = via_dig_playback_pcm_open,
1035 .close = via_dig_playback_pcm_close
1036 },
1037};
1038
1039static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1040 .substreams = 1,
1041 .channels_min = 2,
1042 .channels_max = 2,
1043};
1044
1045static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1046 const struct auto_pin_cfg *cfg)
1047{
1048 int i;
1049 hda_nid_t nid;
1050
1051 if (cfg->line_outs == 4) /* 10 channels */
1052 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1053 else if (cfg->line_outs == 3) /* 6 channels */
1054 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1055
1056 spec->multiout.dac_nids = spec->private_dac_nids;
1057
1058 if (cfg->line_outs == 4) { /* 10 channels */
1059 for (i = 0; i < cfg->line_outs; i++) {
1060 nid = cfg->line_out_pins[i];
1061 if (nid) {
1062 /* config dac list */
1063 switch (i) {
1064 case AUTO_SEQ_FRONT:
1065 /* AOW0 */
1066 spec->multiout.dac_nids[i] = 0x10;
1067 break;
1068 case AUTO_SEQ_CENLFE:
1069 /* AOW2 */
1070 spec->multiout.dac_nids[i] = 0x12;
1071 break;
1072 case AUTO_SEQ_SURROUND:
1073 /* AOW3 */
1074 spec->multiout.dac_nids[i] = 0x27;
1075 break;
1076 case AUTO_SEQ_SIDE:
1077 /* AOW1 */
1078 spec->multiout.dac_nids[i] = 0x11;
1079 break;
1080 default:
1081 break;
1082 }
1083 }
1084 }
1085 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1086
1087 } else if (cfg->line_outs == 3) { /* 6 channels */
1088 for(i = 0; i < cfg->line_outs; i++) {
1089 nid = cfg->line_out_pins[i];
1090 if (nid) {
1091 /* config dac list */
1092 switch(i) {
1093 case AUTO_SEQ_FRONT:
1094 /* AOW0 */
1095 spec->multiout.dac_nids[i] = 0x10;
1096 break;
1097 case AUTO_SEQ_CENLFE:
1098 /* AOW2 */
1099 spec->multiout.dac_nids[i] = 0x12;
1100 break;
1101 case AUTO_SEQ_SURROUND:
1102 /* AOW1 */
1103 spec->multiout.dac_nids[i] = 0x11;
1104 break;
1105 default:
1106 break;
1107 }
1108 }
1109 }
1110 }
1111
1112 return 0;
1113}
1114
1115/* add playback controls from the parsed DAC table */
1116static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1117 const struct auto_pin_cfg *cfg)
1118{
1119 char name[32];
1120 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1121 hda_nid_t nid = 0;
1122 int i, err;
1123
1124 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1125 nid = cfg->line_out_pins[i];
1126
1127 if (!nid)
1128 continue;
1129
1130 if (i == AUTO_SEQ_CENLFE) {
1131 /* Center/LFE */
1132 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1133 "Center Playback Volume",
f7278fd0
JC
1134 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1135 HDA_OUTPUT));
c577b8a1
JC
1136 if (err < 0)
1137 return err;
1138 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1139 "LFE Playback Volume",
f7278fd0
JC
1140 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1141 HDA_OUTPUT));
c577b8a1
JC
1142 if (err < 0)
1143 return err;
1144 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1145 "Center Playback Switch",
f7278fd0
JC
1146 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1147 HDA_OUTPUT));
c577b8a1
JC
1148 if (err < 0)
1149 return err;
1150 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1151 "LFE Playback Switch",
f7278fd0
JC
1152 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1153 HDA_OUTPUT));
c577b8a1
JC
1154 if (err < 0)
1155 return err;
1156 } else if (i == AUTO_SEQ_FRONT){
1157 /* add control to mixer index 0 */
1158 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1159 "Master Front Playback Volume",
f7278fd0
JC
1160 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1161 HDA_INPUT));
c577b8a1
JC
1162 if (err < 0)
1163 return err;
1164 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1165 "Master Front Playback Switch",
f7278fd0
JC
1166 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1167 HDA_INPUT));
c577b8a1
JC
1168 if (err < 0)
1169 return err;
1170
1171 /* add control to PW3 */
1172 sprintf(name, "%s Playback Volume", chname[i]);
1173 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
1174 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1175 HDA_OUTPUT));
c577b8a1
JC
1176 if (err < 0)
1177 return err;
1178 sprintf(name, "%s Playback Switch", chname[i]);
1179 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
1180 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1181 HDA_OUTPUT));
c577b8a1
JC
1182 if (err < 0)
1183 return err;
1184 } else if (i == AUTO_SEQ_SURROUND) {
1185 sprintf(name, "%s Playback Volume", chname[i]);
1186 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
1187 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1188 HDA_OUTPUT));
c577b8a1
JC
1189 if (err < 0)
1190 return err;
1191 sprintf(name, "%s Playback Switch", chname[i]);
1192 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
1193 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1194 HDA_OUTPUT));
c577b8a1
JC
1195 if (err < 0)
1196 return err;
1197 } else if (i == AUTO_SEQ_SIDE) {
1198 sprintf(name, "%s Playback Volume", chname[i]);
1199 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
1200 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1201 HDA_OUTPUT));
c577b8a1
JC
1202 if (err < 0)
1203 return err;
1204 sprintf(name, "%s Playback Switch", chname[i]);
1205 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
1206 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1207 HDA_OUTPUT));
c577b8a1
JC
1208 if (err < 0)
1209 return err;
1210 }
1211 }
1212
1213 return 0;
1214}
1215
1216static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1217{
1218 int err;
1219
1220 if (!pin)
1221 return 0;
1222
1223 if (spec->multiout.num_dacs == 5) /* 10 channels */
1224 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1225 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1226 spec->multiout.hp_nid = 0;
1227
1228 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1229 "Headphone Playback Volume",
1230 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1231 if (err < 0)
1232 return err;
1233 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1234 "Headphone Playback Switch",
1235 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1236 if (err < 0)
1237 return err;
1238
1239 return 0;
1240}
1241
1242/* create playback/capture controls for input pins */
1243static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1244 const struct auto_pin_cfg *cfg)
1245{
1246 static char *labels[] = {
1247 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1248 };
1249 struct hda_input_mux *imux = &spec->private_imux;
1250 int i, err, idx = 0;
1251
1252 /* for internal loopback recording select */
1253 imux->items[imux->num_items].label = "Stereo Mixer";
1254 imux->items[imux->num_items].index = idx;
1255 imux->num_items++;
1256
1257 for (i = 0; i < AUTO_PIN_LAST; i++) {
1258 if (!cfg->input_pins[i])
1259 continue;
1260
1261 switch (cfg->input_pins[i]) {
1262 case 0x1d: /* Mic */
1263 idx = 2;
1264 break;
1265
1266 case 0x1e: /* Line In */
1267 idx = 3;
1268 break;
1269
1270 case 0x21: /* Front Mic */
1271 idx = 4;
1272 break;
1273
1274 case 0x23: /* CD */
1275 idx = 1;
1276 break;
1277 }
1278 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1279 idx, 0x18);
1280 if (err < 0)
1281 return err;
1282 imux->items[imux->num_items].label = labels[i];
1283 imux->items[imux->num_items].index = idx;
1284 imux->num_items++;
1285 }
1286 return 0;
1287}
1288
1289static int vt1709_parse_auto_config(struct hda_codec *codec)
1290{
1291 struct via_spec *spec = codec->spec;
1292 int err;
1293
1294 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1295 if (err < 0)
1296 return err;
1297 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1298 if (err < 0)
1299 return err;
1300 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1301 return 0; /* can't find valid BIOS pin config */
1302
1303 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1304 if (err < 0)
1305 return err;
1306 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1307 if (err < 0)
1308 return err;
1309 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1310 if (err < 0)
1311 return err;
1312
1313 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1314
1315 if (spec->autocfg.dig_out_pin)
1316 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1317 if (spec->autocfg.dig_in_pin)
1318 spec->dig_in_nid = VT1709_DIGIN_NID;
1319
1320 if (spec->kctl_alloc)
1321 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1322
1323 spec->input_mux = &spec->private_imux;
1324
1325 return 1;
1326}
1327
cb53c626
TI
1328#ifdef CONFIG_SND_HDA_POWER_SAVE
1329static struct hda_amp_list vt1709_loopbacks[] = {
1330 { 0x18, HDA_INPUT, 1 },
1331 { 0x18, HDA_INPUT, 2 },
1332 { 0x18, HDA_INPUT, 3 },
1333 { 0x18, HDA_INPUT, 4 },
1334 { } /* end */
1335};
1336#endif
1337
c577b8a1
JC
1338static int patch_vt1709_10ch(struct hda_codec *codec)
1339{
1340 struct via_spec *spec;
1341 int err;
1342
1343 /* create a codec specific record */
1344 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1345 if (spec == NULL)
1346 return -ENOMEM;
1347
1348 codec->spec = spec;
1349
1350 err = vt1709_parse_auto_config(codec);
1351 if (err < 0) {
1352 via_free(codec);
1353 return err;
1354 } else if (!err) {
1355 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1356 "Using genenic mode...\n");
1357 }
1358
1359 spec->init_verbs = vt1709_10ch_volume_init_verbs;
1360
1361 spec->stream_name_analog = "VT1709 Analog";
1362 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1363 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1364
1365 spec->stream_name_digital = "VT1709 Digital";
1366 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1367 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1368
1369
1370 if (!spec->adc_nids && spec->input_mux) {
1371 spec->adc_nids = vt1709_adc_nids;
1372 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1373 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1374 spec->num_mixers++;
1375 }
1376
1377 codec->patch_ops = via_patch_ops;
1378
1379 codec->patch_ops.init = via_auto_init;
cb53c626
TI
1380#ifdef CONFIG_SND_HDA_POWER_SAVE
1381 spec->loopback.amplist = vt1709_loopbacks;
1382#endif
c577b8a1
JC
1383
1384 return 0;
1385}
1386/*
1387 * generic initialization of ADC, input mixers and output mixers
1388 */
1389static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1390 /*
1391 * Unmute ADC0-2 and set the default input to mic-in
1392 */
1393 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1394 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1395 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1396
1397
1398 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1399 * mixer widget
1400 */
1401 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1402 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1403 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1404 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1405 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1406 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1407
1408 /*
1409 * Set up output selector (0x1a, 0x1b, 0x29)
1410 */
1411 /* set vol=0 to output mixers */
1412 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1413 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1414 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1415
1416 /*
1417 * Unmute PW3 and PW4
1418 */
1419 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1420 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1421
1422 /* Set input of PW4 as MW0 */
1423 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
c577b8a1
JC
1424 /* PW9 Output enable */
1425 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1426 { }
1427};
1428
1429static int patch_vt1709_6ch(struct hda_codec *codec)
1430{
1431 struct via_spec *spec;
1432 int err;
1433
1434 /* create a codec specific record */
1435 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1436 if (spec == NULL)
1437 return -ENOMEM;
1438
1439 codec->spec = spec;
1440
1441 err = vt1709_parse_auto_config(codec);
1442 if (err < 0) {
1443 via_free(codec);
1444 return err;
1445 } else if (!err) {
1446 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1447 "Using genenic mode...\n");
1448 }
1449
1450 spec->init_verbs = vt1709_6ch_volume_init_verbs;
1451
1452 spec->stream_name_analog = "VT1709 Analog";
1453 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1454 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1455
1456 spec->stream_name_digital = "VT1709 Digital";
1457 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1458 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1459
1460
1461 if (!spec->adc_nids && spec->input_mux) {
1462 spec->adc_nids = vt1709_adc_nids;
1463 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1464 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1465 spec->num_mixers++;
1466 }
1467
1468 codec->patch_ops = via_patch_ops;
1469
1470 codec->patch_ops.init = via_auto_init;
cb53c626
TI
1471#ifdef CONFIG_SND_HDA_POWER_SAVE
1472 spec->loopback.amplist = vt1709_loopbacks;
1473#endif
f7278fd0
JC
1474 return 0;
1475}
1476
1477/* capture mixer elements */
1478static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1479 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1480 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1481 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1482 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1483 {
1484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485 /* The multiple "Capture Source" controls confuse alsamixer
1486 * So call somewhat different..
f7278fd0
JC
1487 */
1488 /* .name = "Capture Source", */
1489 .name = "Input Source",
1490 .count = 1,
1491 .info = via_mux_enum_info,
1492 .get = via_mux_enum_get,
1493 .put = via_mux_enum_put,
1494 },
1495 { } /* end */
1496};
1497/*
1498 * generic initialization of ADC, input mixers and output mixers
1499 */
1500static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1501 /*
1502 * Unmute ADC0-1 and set the default input to mic-in
1503 */
1504 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1505 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1506
1507
1508 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1509 * mixer widget
1510 */
1511 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1512 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1513 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1514 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1515 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1516 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1517
1518 /*
1519 * Set up output mixers
1520 */
1521 /* set vol=0 to output mixers */
1522 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1523 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1524 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1525
1526 /* Setup default input to PW4 */
1527 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1528 /* PW9 Output enable */
1529 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1530 /* PW10 Input enable */
1531 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1532 { }
1533};
1534
1535static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1536 /*
1537 * Unmute ADC0-1 and set the default input to mic-in
1538 */
1539 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1540 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1541
1542
1543 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1544 * mixer widget
1545 */
1546 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1547 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1548 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1549 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1550 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1551 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1552
1553 /*
1554 * Set up output mixers
1555 */
1556 /* set vol=0 to output mixers */
1557 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1558 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1559 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1560
1561 /* Setup default input of PW4 to MW0 */
1562 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1563 /* PW9 Output enable */
1564 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1565 /* PW10 Input enable */
1566 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1567 { }
1568};
1569
1570static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1571 .substreams = 1,
1572 .channels_min = 2,
1573 .channels_max = 8,
1574 .nid = 0x10, /* NID to query formats and rates */
1575 .ops = {
1576 .open = via_playback_pcm_open,
1577 .prepare = via_playback_pcm_prepare,
1578 .cleanup = via_playback_pcm_cleanup
1579 },
1580};
1581
1582static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1583 .substreams = 1,
1584 .channels_min = 2,
1585 .channels_max = 4,
1586 .nid = 0x10, /* NID to query formats and rates */
1587 .ops = {
1588 .open = via_playback_pcm_open,
1589 .prepare = via_playback_pcm_prepare,
1590 .cleanup = via_playback_pcm_cleanup
1591 },
1592};
1593
1594static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1595 .substreams = 2,
1596 .channels_min = 2,
1597 .channels_max = 2,
1598 .nid = 0x13, /* NID to query formats and rates */
1599 .ops = {
1600 .prepare = via_capture_pcm_prepare,
1601 .cleanup = via_capture_pcm_cleanup
1602 },
1603};
1604
1605static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1606 .substreams = 1,
1607 .channels_min = 2,
1608 .channels_max = 2,
1609 /* NID is set in via_build_pcms */
1610 .ops = {
1611 .open = via_dig_playback_pcm_open,
1612 .close = via_dig_playback_pcm_close,
1613 .prepare = via_dig_playback_pcm_prepare
1614 },
1615};
1616
1617static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1618 .substreams = 1,
1619 .channels_min = 2,
1620 .channels_max = 2,
1621};
1622
1623/* fill in the dac_nids table from the parsed pin configuration */
1624static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1625 const struct auto_pin_cfg *cfg)
1626{
1627 int i;
1628 hda_nid_t nid;
1629
1630 spec->multiout.num_dacs = cfg->line_outs;
1631
1632 spec->multiout.dac_nids = spec->private_dac_nids;
1633
1634 for (i = 0; i < 4; i++) {
1635 nid = cfg->line_out_pins[i];
1636 if (nid) {
1637 /* config dac list */
1638 switch (i) {
1639 case AUTO_SEQ_FRONT:
1640 spec->multiout.dac_nids[i] = 0x10;
1641 break;
1642 case AUTO_SEQ_CENLFE:
1643 spec->multiout.dac_nids[i] = 0x24;
1644 break;
1645 case AUTO_SEQ_SURROUND:
1646 spec->multiout.dac_nids[i] = 0x25;
1647 break;
1648 case AUTO_SEQ_SIDE:
1649 spec->multiout.dac_nids[i] = 0x11;
1650 break;
1651 }
1652 }
1653 }
1654
1655 return 0;
1656}
1657
1658/* add playback controls from the parsed DAC table */
1659static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1660 const struct auto_pin_cfg *cfg)
1661{
1662 char name[32];
1663 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1664 hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1665 hda_nid_t nid, nid_vol = 0;
1666 int i, err;
1667
1668 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1669 nid = cfg->line_out_pins[i];
1670
1671 if (!nid)
1672 continue;
1673
1674 nid_vol = nid_vols[i];
1675
1676 if (i == AUTO_SEQ_CENLFE) {
1677 /* Center/LFE */
1678 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1679 "Center Playback Volume",
1680 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1681 HDA_OUTPUT));
1682 if (err < 0)
1683 return err;
1684 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1685 "LFE Playback Volume",
1686 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1687 HDA_OUTPUT));
1688 if (err < 0)
1689 return err;
1690 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1691 "Center Playback Switch",
1692 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1693 HDA_OUTPUT));
1694 if (err < 0)
1695 return err;
1696 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1697 "LFE Playback Switch",
1698 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1699 HDA_OUTPUT));
1700 if (err < 0)
1701 return err;
1702 } else if (i == AUTO_SEQ_FRONT) {
1703 /* add control to mixer index 0 */
1704 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1705 "Master Front Playback Volume",
1706 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1707 HDA_INPUT));
1708 if (err < 0)
1709 return err;
1710 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1711 "Master Front Playback Switch",
1712 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1713 HDA_INPUT));
1714 if (err < 0)
1715 return err;
1716
1717 /* add control to PW3 */
1718 sprintf(name, "%s Playback Volume", chname[i]);
1719 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1720 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1721 HDA_OUTPUT));
1722 if (err < 0)
1723 return err;
1724 sprintf(name, "%s Playback Switch", chname[i]);
1725 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1726 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1727 HDA_OUTPUT));
1728 if (err < 0)
1729 return err;
1730 } else {
1731 sprintf(name, "%s Playback Volume", chname[i]);
1732 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1733 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1734 HDA_OUTPUT));
1735 if (err < 0)
1736 return err;
1737 sprintf(name, "%s Playback Switch", chname[i]);
1738 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1739 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1740 HDA_OUTPUT));
1741 if (err < 0)
1742 return err;
1743 }
1744 }
1745
1746 return 0;
1747}
1748
1749static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1750{
1751 int err;
1752
1753 if (!pin)
1754 return 0;
1755
1756 spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1757
1758 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1759 "Headphone Playback Volume",
1760 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1761 if (err < 0)
1762 return err;
1763 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1764 "Headphone Playback Switch",
1765 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1766 if (err < 0)
1767 return err;
1768
1769 return 0;
1770}
1771
1772/* create playback/capture controls for input pins */
1773static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1774 const struct auto_pin_cfg *cfg)
1775{
1776 static char *labels[] = {
1777 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1778 };
1779 struct hda_input_mux *imux = &spec->private_imux;
1780 int i, err, idx = 0;
1781
1782 /* for internal loopback recording select */
1783 imux->items[imux->num_items].label = "Stereo Mixer";
1784 imux->items[imux->num_items].index = idx;
1785 imux->num_items++;
1786
1787 for (i = 0; i < AUTO_PIN_LAST; i++) {
1788 if (!cfg->input_pins[i])
1789 continue;
1790
1791 switch (cfg->input_pins[i]) {
1792 case 0x1a: /* Mic */
1793 idx = 2;
1794 break;
1795
1796 case 0x1b: /* Line In */
1797 idx = 3;
1798 break;
1799
1800 case 0x1e: /* Front Mic */
1801 idx = 4;
1802 break;
1803
1804 case 0x1f: /* CD */
1805 idx = 1;
1806 break;
1807 }
1808 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1809 idx, 0x16);
1810 if (err < 0)
1811 return err;
1812 imux->items[imux->num_items].label = labels[i];
1813 imux->items[imux->num_items].index = idx;
1814 imux->num_items++;
1815 }
1816 return 0;
1817}
1818
1819static int vt1708B_parse_auto_config(struct hda_codec *codec)
1820{
1821 struct via_spec *spec = codec->spec;
1822 int err;
1823
1824 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1825 if (err < 0)
1826 return err;
1827 err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1828 if (err < 0)
1829 return err;
1830 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1831 return 0; /* can't find valid BIOS pin config */
1832
1833 err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1834 if (err < 0)
1835 return err;
1836 err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1837 if (err < 0)
1838 return err;
1839 err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1840 if (err < 0)
1841 return err;
1842
1843 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1844
1845 if (spec->autocfg.dig_out_pin)
1846 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1847 if (spec->autocfg.dig_in_pin)
1848 spec->dig_in_nid = VT1708B_DIGIN_NID;
1849
1850 if (spec->kctl_alloc)
1851 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1852
1853 spec->input_mux = &spec->private_imux;
1854
1855 return 1;
1856}
1857
1858#ifdef CONFIG_SND_HDA_POWER_SAVE
1859static struct hda_amp_list vt1708B_loopbacks[] = {
1860 { 0x16, HDA_INPUT, 1 },
1861 { 0x16, HDA_INPUT, 2 },
1862 { 0x16, HDA_INPUT, 3 },
1863 { 0x16, HDA_INPUT, 4 },
1864 { } /* end */
1865};
1866#endif
1867
1868static int patch_vt1708B_8ch(struct hda_codec *codec)
1869{
1870 struct via_spec *spec;
1871 int err;
1872
1873 /* create a codec specific record */
1874 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1875 if (spec == NULL)
1876 return -ENOMEM;
1877
1878 codec->spec = spec;
1879
1880 /* automatic parse from the BIOS config */
1881 err = vt1708B_parse_auto_config(codec);
1882 if (err < 0) {
1883 via_free(codec);
1884 return err;
1885 } else if (!err) {
1886 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1887 "from BIOS. Using genenic mode...\n");
1888 }
1889
1890 spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1891
1892 spec->stream_name_analog = "VT1708B Analog";
1893 spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1894 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1895
1896 spec->stream_name_digital = "VT1708B Digital";
1897 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1898 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1899
1900 if (!spec->adc_nids && spec->input_mux) {
1901 spec->adc_nids = vt1708B_adc_nids;
1902 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1903 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1904 spec->num_mixers++;
1905 }
1906
1907 codec->patch_ops = via_patch_ops;
1908
1909 codec->patch_ops.init = via_auto_init;
1910#ifdef CONFIG_SND_HDA_POWER_SAVE
1911 spec->loopback.amplist = vt1708B_loopbacks;
1912#endif
1913
1914 return 0;
1915}
1916
1917static int patch_vt1708B_4ch(struct hda_codec *codec)
1918{
1919 struct via_spec *spec;
1920 int err;
1921
1922 /* create a codec specific record */
1923 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1924 if (spec == NULL)
1925 return -ENOMEM;
1926
1927 codec->spec = spec;
1928
1929 /* automatic parse from the BIOS config */
1930 err = vt1708B_parse_auto_config(codec);
1931 if (err < 0) {
1932 via_free(codec);
1933 return err;
1934 } else if (!err) {
1935 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1936 "from BIOS. Using genenic mode...\n");
1937 }
1938
1939 spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1940
1941 spec->stream_name_analog = "VT1708B Analog";
1942 spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1943 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1944
1945 spec->stream_name_digital = "VT1708B Digital";
1946 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1947 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1948
1949 if (!spec->adc_nids && spec->input_mux) {
1950 spec->adc_nids = vt1708B_adc_nids;
1951 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1952 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1953 spec->num_mixers++;
1954 }
1955
1956 codec->patch_ops = via_patch_ops;
1957
1958 codec->patch_ops.init = via_auto_init;
1959#ifdef CONFIG_SND_HDA_POWER_SAVE
1960 spec->loopback.amplist = vt1708B_loopbacks;
1961#endif
c577b8a1
JC
1962
1963 return 0;
1964}
1965
1966/*
1967 * patch entries
1968 */
1969struct hda_codec_preset snd_hda_preset_via[] = {
1970 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1971 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1972 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1973 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
f7278fd0
JC
1974 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1975 .patch = patch_vt1709_10ch},
1976 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1977 .patch = patch_vt1709_10ch},
1978 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1979 .patch = patch_vt1709_10ch},
1980 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
1981 .patch = patch_vt1709_10ch},
1982 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
1983 .patch = patch_vt1709_6ch},
1984 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
1985 .patch = patch_vt1709_6ch},
1986 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
1987 .patch = patch_vt1709_6ch},
1988 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
1989 .patch = patch_vt1709_6ch},
1990 { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
1991 .patch = patch_vt1708B_8ch},
1992 { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
1993 .patch = patch_vt1708B_8ch},
1994 { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
1995 .patch = patch_vt1708B_8ch},
1996 { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
1997 .patch = patch_vt1708B_8ch},
1998 { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
1999 .patch = patch_vt1708B_4ch},
2000 { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
2001 .patch = patch_vt1708B_4ch},
2002 { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
2003 .patch = patch_vt1708B_4ch},
2004 { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
2005 .patch = patch_vt1708B_4ch},
c577b8a1
JC
2006 {} /* terminator */
2007};