[ALSA] hda - Add model for ASUS P5K-E/WIFI-AP
[deliverable/linux.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;
888afa15 434 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
c577b8a1
JC
435 return 0;
436}
437
438static struct hda_pcm_stream vt1708_pcm_analog_playback = {
439 .substreams = 1,
440 .channels_min = 2,
441 .channels_max = 8,
442 .nid = 0x10, /* NID to query formats and rates */
443 .ops = {
444 .open = via_playback_pcm_open,
445 .prepare = via_playback_pcm_prepare,
446 .cleanup = via_playback_pcm_cleanup
447 },
448};
449
450static struct hda_pcm_stream vt1708_pcm_analog_capture = {
451 .substreams = 2,
452 .channels_min = 2,
453 .channels_max = 2,
454 .nid = 0x15, /* NID to query formats and rates */
455 .ops = {
456 .prepare = via_capture_pcm_prepare,
457 .cleanup = via_capture_pcm_cleanup
458 },
459};
460
461static struct hda_pcm_stream vt1708_pcm_digital_playback = {
462 .substreams = 1,
463 .channels_min = 2,
464 .channels_max = 2,
465 /* NID is set in via_build_pcms */
466 .ops = {
467 .open = via_dig_playback_pcm_open,
6b97eb45
TI
468 .close = via_dig_playback_pcm_close,
469 .prepare = via_dig_playback_pcm_prepare
c577b8a1
JC
470 },
471};
472
473static struct hda_pcm_stream vt1708_pcm_digital_capture = {
474 .substreams = 1,
475 .channels_min = 2,
476 .channels_max = 2,
477};
478
479static int via_build_controls(struct hda_codec *codec)
480{
481 struct via_spec *spec = codec->spec;
482 int err;
483 int i;
484
485 for (i = 0; i < spec->num_mixers; i++) {
486 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
487 if (err < 0)
488 return err;
489 }
490
491 if (spec->multiout.dig_out_nid) {
492 err = snd_hda_create_spdif_out_ctls(codec,
493 spec->multiout.dig_out_nid);
494 if (err < 0)
495 return err;
9a08160b
TI
496 err = snd_hda_create_spdif_share_sw(codec,
497 &spec->multiout);
498 if (err < 0)
499 return err;
500 spec->multiout.share_spdif = 1;
c577b8a1
JC
501 }
502 if (spec->dig_in_nid) {
503 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
504 if (err < 0)
505 return err;
506 }
507 return 0;
508}
509
510static int via_build_pcms(struct hda_codec *codec)
511{
512 struct via_spec *spec = codec->spec;
513 struct hda_pcm *info = spec->pcm_rec;
514
515 codec->num_pcms = 1;
516 codec->pcm_info = info;
517
518 info->name = spec->stream_name_analog;
519 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
520 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
521 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
522 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
523
524 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
525 spec->multiout.max_channels;
526
527 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
528 codec->num_pcms++;
529 info++;
530 info->name = spec->stream_name_digital;
7ba72ba1 531 info->pcm_type = HDA_PCM_TYPE_SPDIF;
c577b8a1
JC
532 if (spec->multiout.dig_out_nid) {
533 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
534 *(spec->stream_digital_playback);
535 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
536 spec->multiout.dig_out_nid;
537 }
538 if (spec->dig_in_nid) {
539 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
540 *(spec->stream_digital_capture);
541 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
542 spec->dig_in_nid;
543 }
544 }
545
546 return 0;
547}
548
549static void via_free(struct hda_codec *codec)
550{
551 struct via_spec *spec = codec->spec;
552 unsigned int i;
553
554 if (!spec)
555 return;
556
557 if (spec->kctl_alloc) {
558 for (i = 0; i < spec->num_kctl_used; i++)
559 kfree(spec->kctl_alloc[i].name);
560 kfree(spec->kctl_alloc);
561 }
562
563 kfree(codec->spec);
564}
565
566static int via_init(struct hda_codec *codec)
567{
568 struct via_spec *spec = codec->spec;
569 snd_hda_sequence_write(codec, spec->init_verbs);
f7278fd0
JC
570 /* Lydia Add for EAPD enable */
571 if (!spec->dig_in_nid) { /* No Digital In connection */
572 if (IS_VT1708_VENDORID(codec->vendor_id)) {
573 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
574 AC_VERB_SET_PIN_WIDGET_CONTROL,
12b74c80 575 PIN_OUT);
f7278fd0
JC
576 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
577 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
578 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
579 IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
580 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
581 AC_VERB_SET_PIN_WIDGET_CONTROL,
12b74c80 582 PIN_OUT);
f7278fd0
JC
583 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
584 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
585 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
586 IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
587 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
588 AC_VERB_SET_PIN_WIDGET_CONTROL,
12b74c80 589 PIN_OUT);
f7278fd0
JC
590 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
591 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
592 }
12b74c80
TI
593 } else /* enable SPDIF-input pin */
594 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
595 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
f7278fd0 596
c577b8a1
JC
597 return 0;
598}
599
cb53c626
TI
600#ifdef CONFIG_SND_HDA_POWER_SAVE
601static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
602{
603 struct via_spec *spec = codec->spec;
604 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
605}
606#endif
607
c577b8a1
JC
608/*
609 */
610static struct hda_codec_ops via_patch_ops = {
611 .build_controls = via_build_controls,
612 .build_pcms = via_build_pcms,
613 .init = via_init,
614 .free = via_free,
cb53c626
TI
615#ifdef CONFIG_SND_HDA_POWER_SAVE
616 .check_power_status = via_check_power_status,
617#endif
c577b8a1
JC
618};
619
620/* fill in the dac_nids table from the parsed pin configuration */
621static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
622 const struct auto_pin_cfg *cfg)
623{
624 int i;
625 hda_nid_t nid;
626
627 spec->multiout.num_dacs = cfg->line_outs;
628
629 spec->multiout.dac_nids = spec->private_dac_nids;
630
631 for(i = 0; i < 4; i++) {
632 nid = cfg->line_out_pins[i];
633 if (nid) {
634 /* config dac list */
635 switch (i) {
636 case AUTO_SEQ_FRONT:
637 spec->multiout.dac_nids[i] = 0x10;
638 break;
639 case AUTO_SEQ_CENLFE:
640 spec->multiout.dac_nids[i] = 0x12;
641 break;
642 case AUTO_SEQ_SURROUND:
643 spec->multiout.dac_nids[i] = 0x13;
644 break;
645 case AUTO_SEQ_SIDE:
646 spec->multiout.dac_nids[i] = 0x11;
647 break;
648 }
649 }
650 }
651
652 return 0;
653}
654
655/* add playback controls from the parsed DAC table */
656static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
657 const struct auto_pin_cfg *cfg)
658{
659 char name[32];
660 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
661 hda_nid_t nid, nid_vol = 0;
662 int i, err;
663
664 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
665 nid = cfg->line_out_pins[i];
666
667 if (!nid)
668 continue;
669
670 if (i != AUTO_SEQ_FRONT)
671 nid_vol = 0x1b - i + 1;
672
673 if (i == AUTO_SEQ_CENLFE) {
674 /* Center/LFE */
675 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
f7278fd0
JC
676 "Center Playback Volume",
677 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
678 HDA_OUTPUT));
c577b8a1
JC
679 if (err < 0)
680 return err;
681 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
682 "LFE Playback Volume",
f7278fd0
JC
683 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
684 HDA_OUTPUT));
c577b8a1
JC
685 if (err < 0)
686 return err;
687 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
688 "Center Playback Switch",
f7278fd0
JC
689 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
690 HDA_OUTPUT));
c577b8a1
JC
691 if (err < 0)
692 return err;
693 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
694 "LFE Playback Switch",
f7278fd0
JC
695 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
696 HDA_OUTPUT));
c577b8a1
JC
697 if (err < 0)
698 return err;
699 } else if (i == AUTO_SEQ_FRONT){
700 /* add control to mixer index 0 */
701 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
702 "Master Front Playback Volume",
f7278fd0
JC
703 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
704 HDA_INPUT));
c577b8a1
JC
705 if (err < 0)
706 return err;
707 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
708 "Master Front Playback Switch",
f7278fd0
JC
709 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
710 HDA_INPUT));
c577b8a1
JC
711 if (err < 0)
712 return err;
713
714 /* add control to PW3 */
715 sprintf(name, "%s Playback Volume", chname[i]);
716 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
717 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
718 HDA_OUTPUT));
c577b8a1
JC
719 if (err < 0)
720 return err;
721 sprintf(name, "%s Playback Switch", chname[i]);
722 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
723 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
724 HDA_OUTPUT));
c577b8a1
JC
725 if (err < 0)
726 return err;
727 } else {
728 sprintf(name, "%s Playback Volume", chname[i]);
729 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
730 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
731 HDA_OUTPUT));
c577b8a1
JC
732 if (err < 0)
733 return err;
734 sprintf(name, "%s Playback Switch", chname[i]);
735 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
736 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
737 HDA_OUTPUT));
c577b8a1
JC
738 if (err < 0)
739 return err;
740 }
741 }
742
743 return 0;
744}
745
746static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
747{
748 int err;
749
750 if (!pin)
751 return 0;
752
753 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
754
755 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
756 "Headphone Playback Volume",
757 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
758 if (err < 0)
759 return err;
760 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
761 "Headphone Playback Switch",
762 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
763 if (err < 0)
764 return err;
765
766 return 0;
767}
768
769/* create playback/capture controls for input pins */
770static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
771 const struct auto_pin_cfg *cfg)
772{
773 static char *labels[] = {
774 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
775 };
776 struct hda_input_mux *imux = &spec->private_imux;
777 int i, err, idx = 0;
778
779 /* for internal loopback recording select */
780 imux->items[imux->num_items].label = "Stereo Mixer";
781 imux->items[imux->num_items].index = idx;
782 imux->num_items++;
783
784 for (i = 0; i < AUTO_PIN_LAST; i++) {
785 if (!cfg->input_pins[i])
786 continue;
787
788 switch (cfg->input_pins[i]) {
789 case 0x1d: /* Mic */
790 idx = 2;
791 break;
792
793 case 0x1e: /* Line In */
794 idx = 3;
795 break;
796
797 case 0x21: /* Front Mic */
798 idx = 4;
799 break;
800
801 case 0x24: /* CD */
802 idx = 1;
803 break;
804 }
805 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
806 idx, 0x17);
807 if (err < 0)
808 return err;
809 imux->items[imux->num_items].label = labels[i];
810 imux->items[imux->num_items].index = idx;
811 imux->num_items++;
812 }
813 return 0;
814}
815
cb53c626
TI
816#ifdef CONFIG_SND_HDA_POWER_SAVE
817static struct hda_amp_list vt1708_loopbacks[] = {
818 { 0x17, HDA_INPUT, 1 },
819 { 0x17, HDA_INPUT, 2 },
820 { 0x17, HDA_INPUT, 3 },
821 { 0x17, HDA_INPUT, 4 },
822 { } /* end */
823};
824#endif
825
c577b8a1
JC
826static int vt1708_parse_auto_config(struct hda_codec *codec)
827{
828 struct via_spec *spec = codec->spec;
829 int err;
830
831 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
832 if (err < 0)
833 return err;
834 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
835 if (err < 0)
836 return err;
837 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
838 return 0; /* can't find valid BIOS pin config */
839
840 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
841 if (err < 0)
842 return err;
843 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
844 if (err < 0)
845 return err;
846 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
847 if (err < 0)
848 return err;
849
850 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
851
852 if (spec->autocfg.dig_out_pin)
853 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
854 if (spec->autocfg.dig_in_pin)
855 spec->dig_in_nid = VT1708_DIGIN_NID;
856
857 if (spec->kctl_alloc)
858 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
859
860 spec->init_verbs = vt1708_volume_init_verbs;
861
862 spec->input_mux = &spec->private_imux;
863
864 return 1;
865}
866
867/* init callback for auto-configuration model -- overriding the default init */
868static int via_auto_init(struct hda_codec *codec)
869{
870 via_init(codec);
871 via_auto_init_multi_out(codec);
872 via_auto_init_hp_out(codec);
873 via_auto_init_analog_input(codec);
874 return 0;
875}
876
877static int patch_vt1708(struct hda_codec *codec)
878{
879 struct via_spec *spec;
880 int err;
881
882 /* create a codec specific record */
883 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
884 if (spec == NULL)
885 return -ENOMEM;
886
887 codec->spec = spec;
888
889 /* automatic parse from the BIOS config */
890 err = vt1708_parse_auto_config(codec);
891 if (err < 0) {
892 via_free(codec);
893 return err;
894 } else if (!err) {
895 printk(KERN_INFO "hda_codec: Cannot set up configuration "
896 "from BIOS. Using genenic mode...\n");
897 }
898
899
900 spec->stream_name_analog = "VT1708 Analog";
901 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
902 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
903
904 spec->stream_name_digital = "VT1708 Digital";
905 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
906 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
907
908
909 if (!spec->adc_nids && spec->input_mux) {
910 spec->adc_nids = vt1708_adc_nids;
911 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
912 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
913 spec->num_mixers++;
914 }
915
916 codec->patch_ops = via_patch_ops;
917
918 codec->patch_ops.init = via_auto_init;
cb53c626
TI
919#ifdef CONFIG_SND_HDA_POWER_SAVE
920 spec->loopback.amplist = vt1708_loopbacks;
921#endif
c577b8a1
JC
922
923 return 0;
924}
925
926/* capture mixer elements */
927static struct snd_kcontrol_new vt1709_capture_mixer[] = {
928 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
929 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
930 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
931 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
932 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
933 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
934 {
935 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
936 /* The multiple "Capture Source" controls confuse alsamixer
937 * So call somewhat different..
c577b8a1
JC
938 */
939 /* .name = "Capture Source", */
940 .name = "Input Source",
941 .count = 1,
942 .info = via_mux_enum_info,
943 .get = via_mux_enum_get,
944 .put = via_mux_enum_put,
945 },
946 { } /* end */
947};
948
949/*
950 * generic initialization of ADC, input mixers and output mixers
951 */
952static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
953 /*
954 * Unmute ADC0-2 and set the default input to mic-in
955 */
956 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
957 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
958 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
959
960
f7278fd0 961 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
c577b8a1
JC
962 * mixer widget
963 */
964 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
f7278fd0
JC
965 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
966 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
967 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
968 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
969 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
c577b8a1
JC
970
971 /*
972 * Set up output selector (0x1a, 0x1b, 0x29)
973 */
974 /* set vol=0 to output mixers */
975 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
976 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
977 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
978
979 /*
980 * Unmute PW3 and PW4
981 */
982 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
983 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
984
985 /* Set input of PW4 as AOW4 */
986 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
c577b8a1
JC
987 /* PW9 Output enable */
988 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
989 { }
990};
991
992static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
993 .substreams = 1,
994 .channels_min = 2,
995 .channels_max = 10,
996 .nid = 0x10, /* NID to query formats and rates */
997 .ops = {
998 .open = via_playback_pcm_open,
999 .prepare = via_playback_pcm_prepare,
1000 .cleanup = via_playback_pcm_cleanup
1001 },
1002};
1003
1004static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1005 .substreams = 1,
1006 .channels_min = 2,
1007 .channels_max = 6,
1008 .nid = 0x10, /* NID to query formats and rates */
1009 .ops = {
1010 .open = via_playback_pcm_open,
1011 .prepare = via_playback_pcm_prepare,
1012 .cleanup = via_playback_pcm_cleanup
1013 },
1014};
1015
1016static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1017 .substreams = 2,
1018 .channels_min = 2,
1019 .channels_max = 2,
1020 .nid = 0x14, /* NID to query formats and rates */
1021 .ops = {
1022 .prepare = via_capture_pcm_prepare,
1023 .cleanup = via_capture_pcm_cleanup
1024 },
1025};
1026
1027static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1028 .substreams = 1,
1029 .channels_min = 2,
1030 .channels_max = 2,
1031 /* NID is set in via_build_pcms */
1032 .ops = {
1033 .open = via_dig_playback_pcm_open,
1034 .close = via_dig_playback_pcm_close
1035 },
1036};
1037
1038static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1039 .substreams = 1,
1040 .channels_min = 2,
1041 .channels_max = 2,
1042};
1043
1044static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1045 const struct auto_pin_cfg *cfg)
1046{
1047 int i;
1048 hda_nid_t nid;
1049
1050 if (cfg->line_outs == 4) /* 10 channels */
1051 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1052 else if (cfg->line_outs == 3) /* 6 channels */
1053 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1054
1055 spec->multiout.dac_nids = spec->private_dac_nids;
1056
1057 if (cfg->line_outs == 4) { /* 10 channels */
1058 for (i = 0; i < cfg->line_outs; i++) {
1059 nid = cfg->line_out_pins[i];
1060 if (nid) {
1061 /* config dac list */
1062 switch (i) {
1063 case AUTO_SEQ_FRONT:
1064 /* AOW0 */
1065 spec->multiout.dac_nids[i] = 0x10;
1066 break;
1067 case AUTO_SEQ_CENLFE:
1068 /* AOW2 */
1069 spec->multiout.dac_nids[i] = 0x12;
1070 break;
1071 case AUTO_SEQ_SURROUND:
1072 /* AOW3 */
1073 spec->multiout.dac_nids[i] = 0x27;
1074 break;
1075 case AUTO_SEQ_SIDE:
1076 /* AOW1 */
1077 spec->multiout.dac_nids[i] = 0x11;
1078 break;
1079 default:
1080 break;
1081 }
1082 }
1083 }
1084 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1085
1086 } else if (cfg->line_outs == 3) { /* 6 channels */
1087 for(i = 0; i < cfg->line_outs; i++) {
1088 nid = cfg->line_out_pins[i];
1089 if (nid) {
1090 /* config dac list */
1091 switch(i) {
1092 case AUTO_SEQ_FRONT:
1093 /* AOW0 */
1094 spec->multiout.dac_nids[i] = 0x10;
1095 break;
1096 case AUTO_SEQ_CENLFE:
1097 /* AOW2 */
1098 spec->multiout.dac_nids[i] = 0x12;
1099 break;
1100 case AUTO_SEQ_SURROUND:
1101 /* AOW1 */
1102 spec->multiout.dac_nids[i] = 0x11;
1103 break;
1104 default:
1105 break;
1106 }
1107 }
1108 }
1109 }
1110
1111 return 0;
1112}
1113
1114/* add playback controls from the parsed DAC table */
1115static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1116 const struct auto_pin_cfg *cfg)
1117{
1118 char name[32];
1119 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1120 hda_nid_t nid = 0;
1121 int i, err;
1122
1123 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1124 nid = cfg->line_out_pins[i];
1125
1126 if (!nid)
1127 continue;
1128
1129 if (i == AUTO_SEQ_CENLFE) {
1130 /* Center/LFE */
1131 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1132 "Center Playback Volume",
f7278fd0
JC
1133 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1134 HDA_OUTPUT));
c577b8a1
JC
1135 if (err < 0)
1136 return err;
1137 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1138 "LFE Playback Volume",
f7278fd0
JC
1139 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1140 HDA_OUTPUT));
c577b8a1
JC
1141 if (err < 0)
1142 return err;
1143 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1144 "Center Playback Switch",
f7278fd0
JC
1145 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1146 HDA_OUTPUT));
c577b8a1
JC
1147 if (err < 0)
1148 return err;
1149 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1150 "LFE Playback Switch",
f7278fd0
JC
1151 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1152 HDA_OUTPUT));
c577b8a1
JC
1153 if (err < 0)
1154 return err;
1155 } else if (i == AUTO_SEQ_FRONT){
1156 /* add control to mixer index 0 */
1157 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1158 "Master Front Playback Volume",
f7278fd0
JC
1159 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1160 HDA_INPUT));
c577b8a1
JC
1161 if (err < 0)
1162 return err;
1163 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1164 "Master Front Playback Switch",
f7278fd0
JC
1165 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1166 HDA_INPUT));
c577b8a1
JC
1167 if (err < 0)
1168 return err;
1169
1170 /* add control to PW3 */
1171 sprintf(name, "%s Playback Volume", chname[i]);
1172 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
1173 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1174 HDA_OUTPUT));
c577b8a1
JC
1175 if (err < 0)
1176 return err;
1177 sprintf(name, "%s Playback Switch", chname[i]);
1178 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
1179 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1180 HDA_OUTPUT));
c577b8a1
JC
1181 if (err < 0)
1182 return err;
1183 } else if (i == AUTO_SEQ_SURROUND) {
1184 sprintf(name, "%s Playback Volume", chname[i]);
1185 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
1186 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1187 HDA_OUTPUT));
c577b8a1
JC
1188 if (err < 0)
1189 return err;
1190 sprintf(name, "%s Playback Switch", chname[i]);
1191 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
1192 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1193 HDA_OUTPUT));
c577b8a1
JC
1194 if (err < 0)
1195 return err;
1196 } else if (i == AUTO_SEQ_SIDE) {
1197 sprintf(name, "%s Playback Volume", chname[i]);
1198 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
f7278fd0
JC
1199 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1200 HDA_OUTPUT));
c577b8a1
JC
1201 if (err < 0)
1202 return err;
1203 sprintf(name, "%s Playback Switch", chname[i]);
1204 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
f7278fd0
JC
1205 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1206 HDA_OUTPUT));
c577b8a1
JC
1207 if (err < 0)
1208 return err;
1209 }
1210 }
1211
1212 return 0;
1213}
1214
1215static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1216{
1217 int err;
1218
1219 if (!pin)
1220 return 0;
1221
1222 if (spec->multiout.num_dacs == 5) /* 10 channels */
1223 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1224 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1225 spec->multiout.hp_nid = 0;
1226
1227 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1228 "Headphone Playback Volume",
1229 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1230 if (err < 0)
1231 return err;
1232 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1233 "Headphone Playback Switch",
1234 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1235 if (err < 0)
1236 return err;
1237
1238 return 0;
1239}
1240
1241/* create playback/capture controls for input pins */
1242static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1243 const struct auto_pin_cfg *cfg)
1244{
1245 static char *labels[] = {
1246 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1247 };
1248 struct hda_input_mux *imux = &spec->private_imux;
1249 int i, err, idx = 0;
1250
1251 /* for internal loopback recording select */
1252 imux->items[imux->num_items].label = "Stereo Mixer";
1253 imux->items[imux->num_items].index = idx;
1254 imux->num_items++;
1255
1256 for (i = 0; i < AUTO_PIN_LAST; i++) {
1257 if (!cfg->input_pins[i])
1258 continue;
1259
1260 switch (cfg->input_pins[i]) {
1261 case 0x1d: /* Mic */
1262 idx = 2;
1263 break;
1264
1265 case 0x1e: /* Line In */
1266 idx = 3;
1267 break;
1268
1269 case 0x21: /* Front Mic */
1270 idx = 4;
1271 break;
1272
1273 case 0x23: /* CD */
1274 idx = 1;
1275 break;
1276 }
1277 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1278 idx, 0x18);
1279 if (err < 0)
1280 return err;
1281 imux->items[imux->num_items].label = labels[i];
1282 imux->items[imux->num_items].index = idx;
1283 imux->num_items++;
1284 }
1285 return 0;
1286}
1287
1288static int vt1709_parse_auto_config(struct hda_codec *codec)
1289{
1290 struct via_spec *spec = codec->spec;
1291 int err;
1292
1293 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1294 if (err < 0)
1295 return err;
1296 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1297 if (err < 0)
1298 return err;
1299 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1300 return 0; /* can't find valid BIOS pin config */
1301
1302 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1303 if (err < 0)
1304 return err;
1305 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1306 if (err < 0)
1307 return err;
1308 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1309 if (err < 0)
1310 return err;
1311
1312 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1313
1314 if (spec->autocfg.dig_out_pin)
1315 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1316 if (spec->autocfg.dig_in_pin)
1317 spec->dig_in_nid = VT1709_DIGIN_NID;
1318
1319 if (spec->kctl_alloc)
1320 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1321
1322 spec->input_mux = &spec->private_imux;
1323
1324 return 1;
1325}
1326
cb53c626
TI
1327#ifdef CONFIG_SND_HDA_POWER_SAVE
1328static struct hda_amp_list vt1709_loopbacks[] = {
1329 { 0x18, HDA_INPUT, 1 },
1330 { 0x18, HDA_INPUT, 2 },
1331 { 0x18, HDA_INPUT, 3 },
1332 { 0x18, HDA_INPUT, 4 },
1333 { } /* end */
1334};
1335#endif
1336
c577b8a1
JC
1337static int patch_vt1709_10ch(struct hda_codec *codec)
1338{
1339 struct via_spec *spec;
1340 int err;
1341
1342 /* create a codec specific record */
1343 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1344 if (spec == NULL)
1345 return -ENOMEM;
1346
1347 codec->spec = spec;
1348
1349 err = vt1709_parse_auto_config(codec);
1350 if (err < 0) {
1351 via_free(codec);
1352 return err;
1353 } else if (!err) {
1354 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1355 "Using genenic mode...\n");
1356 }
1357
1358 spec->init_verbs = vt1709_10ch_volume_init_verbs;
1359
1360 spec->stream_name_analog = "VT1709 Analog";
1361 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1362 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1363
1364 spec->stream_name_digital = "VT1709 Digital";
1365 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1366 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1367
1368
1369 if (!spec->adc_nids && spec->input_mux) {
1370 spec->adc_nids = vt1709_adc_nids;
1371 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1372 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1373 spec->num_mixers++;
1374 }
1375
1376 codec->patch_ops = via_patch_ops;
1377
1378 codec->patch_ops.init = via_auto_init;
cb53c626
TI
1379#ifdef CONFIG_SND_HDA_POWER_SAVE
1380 spec->loopback.amplist = vt1709_loopbacks;
1381#endif
c577b8a1
JC
1382
1383 return 0;
1384}
1385/*
1386 * generic initialization of ADC, input mixers and output mixers
1387 */
1388static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1389 /*
1390 * Unmute ADC0-2 and set the default input to mic-in
1391 */
1392 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1393 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1394 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1395
1396
1397 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1398 * mixer widget
1399 */
1400 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1401 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1402 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1403 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1404 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1405 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1406
1407 /*
1408 * Set up output selector (0x1a, 0x1b, 0x29)
1409 */
1410 /* set vol=0 to output mixers */
1411 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1412 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1413 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1414
1415 /*
1416 * Unmute PW3 and PW4
1417 */
1418 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1419 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1420
1421 /* Set input of PW4 as MW0 */
1422 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
c577b8a1
JC
1423 /* PW9 Output enable */
1424 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1425 { }
1426};
1427
1428static int patch_vt1709_6ch(struct hda_codec *codec)
1429{
1430 struct via_spec *spec;
1431 int err;
1432
1433 /* create a codec specific record */
1434 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1435 if (spec == NULL)
1436 return -ENOMEM;
1437
1438 codec->spec = spec;
1439
1440 err = vt1709_parse_auto_config(codec);
1441 if (err < 0) {
1442 via_free(codec);
1443 return err;
1444 } else if (!err) {
1445 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1446 "Using genenic mode...\n");
1447 }
1448
1449 spec->init_verbs = vt1709_6ch_volume_init_verbs;
1450
1451 spec->stream_name_analog = "VT1709 Analog";
1452 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1453 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1454
1455 spec->stream_name_digital = "VT1709 Digital";
1456 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1457 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1458
1459
1460 if (!spec->adc_nids && spec->input_mux) {
1461 spec->adc_nids = vt1709_adc_nids;
1462 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1463 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1464 spec->num_mixers++;
1465 }
1466
1467 codec->patch_ops = via_patch_ops;
1468
1469 codec->patch_ops.init = via_auto_init;
cb53c626
TI
1470#ifdef CONFIG_SND_HDA_POWER_SAVE
1471 spec->loopback.amplist = vt1709_loopbacks;
1472#endif
f7278fd0
JC
1473 return 0;
1474}
1475
1476/* capture mixer elements */
1477static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1478 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1479 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1480 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1481 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1482 {
1483 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1484 /* The multiple "Capture Source" controls confuse alsamixer
1485 * So call somewhat different..
f7278fd0
JC
1486 */
1487 /* .name = "Capture Source", */
1488 .name = "Input Source",
1489 .count = 1,
1490 .info = via_mux_enum_info,
1491 .get = via_mux_enum_get,
1492 .put = via_mux_enum_put,
1493 },
1494 { } /* end */
1495};
1496/*
1497 * generic initialization of ADC, input mixers and output mixers
1498 */
1499static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1500 /*
1501 * Unmute ADC0-1 and set the default input to mic-in
1502 */
1503 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1504 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1505
1506
1507 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1508 * mixer widget
1509 */
1510 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1511 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1512 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1513 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1514 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1515 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1516
1517 /*
1518 * Set up output mixers
1519 */
1520 /* set vol=0 to output mixers */
1521 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1522 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1523 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1524
1525 /* Setup default input to PW4 */
1526 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1527 /* PW9 Output enable */
1528 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1529 /* PW10 Input enable */
1530 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1531 { }
1532};
1533
1534static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1535 /*
1536 * Unmute ADC0-1 and set the default input to mic-in
1537 */
1538 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1539 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1540
1541
1542 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1543 * mixer widget
1544 */
1545 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1546 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1547 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1548 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1549 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1550 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1551
1552 /*
1553 * Set up output mixers
1554 */
1555 /* set vol=0 to output mixers */
1556 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1557 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1558 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1559
1560 /* Setup default input of PW4 to MW0 */
1561 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1562 /* PW9 Output enable */
1563 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1564 /* PW10 Input enable */
1565 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1566 { }
1567};
1568
1569static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1570 .substreams = 1,
1571 .channels_min = 2,
1572 .channels_max = 8,
1573 .nid = 0x10, /* NID to query formats and rates */
1574 .ops = {
1575 .open = via_playback_pcm_open,
1576 .prepare = via_playback_pcm_prepare,
1577 .cleanup = via_playback_pcm_cleanup
1578 },
1579};
1580
1581static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1582 .substreams = 1,
1583 .channels_min = 2,
1584 .channels_max = 4,
1585 .nid = 0x10, /* NID to query formats and rates */
1586 .ops = {
1587 .open = via_playback_pcm_open,
1588 .prepare = via_playback_pcm_prepare,
1589 .cleanup = via_playback_pcm_cleanup
1590 },
1591};
1592
1593static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1594 .substreams = 2,
1595 .channels_min = 2,
1596 .channels_max = 2,
1597 .nid = 0x13, /* NID to query formats and rates */
1598 .ops = {
1599 .prepare = via_capture_pcm_prepare,
1600 .cleanup = via_capture_pcm_cleanup
1601 },
1602};
1603
1604static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1605 .substreams = 1,
1606 .channels_min = 2,
1607 .channels_max = 2,
1608 /* NID is set in via_build_pcms */
1609 .ops = {
1610 .open = via_dig_playback_pcm_open,
1611 .close = via_dig_playback_pcm_close,
1612 .prepare = via_dig_playback_pcm_prepare
1613 },
1614};
1615
1616static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1617 .substreams = 1,
1618 .channels_min = 2,
1619 .channels_max = 2,
1620};
1621
1622/* fill in the dac_nids table from the parsed pin configuration */
1623static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1624 const struct auto_pin_cfg *cfg)
1625{
1626 int i;
1627 hda_nid_t nid;
1628
1629 spec->multiout.num_dacs = cfg->line_outs;
1630
1631 spec->multiout.dac_nids = spec->private_dac_nids;
1632
1633 for (i = 0; i < 4; i++) {
1634 nid = cfg->line_out_pins[i];
1635 if (nid) {
1636 /* config dac list */
1637 switch (i) {
1638 case AUTO_SEQ_FRONT:
1639 spec->multiout.dac_nids[i] = 0x10;
1640 break;
1641 case AUTO_SEQ_CENLFE:
1642 spec->multiout.dac_nids[i] = 0x24;
1643 break;
1644 case AUTO_SEQ_SURROUND:
1645 spec->multiout.dac_nids[i] = 0x25;
1646 break;
1647 case AUTO_SEQ_SIDE:
1648 spec->multiout.dac_nids[i] = 0x11;
1649 break;
1650 }
1651 }
1652 }
1653
1654 return 0;
1655}
1656
1657/* add playback controls from the parsed DAC table */
1658static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1659 const struct auto_pin_cfg *cfg)
1660{
1661 char name[32];
1662 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1663 hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1664 hda_nid_t nid, nid_vol = 0;
1665 int i, err;
1666
1667 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1668 nid = cfg->line_out_pins[i];
1669
1670 if (!nid)
1671 continue;
1672
1673 nid_vol = nid_vols[i];
1674
1675 if (i == AUTO_SEQ_CENLFE) {
1676 /* Center/LFE */
1677 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1678 "Center Playback Volume",
1679 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1680 HDA_OUTPUT));
1681 if (err < 0)
1682 return err;
1683 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1684 "LFE Playback Volume",
1685 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1686 HDA_OUTPUT));
1687 if (err < 0)
1688 return err;
1689 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1690 "Center Playback Switch",
1691 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1692 HDA_OUTPUT));
1693 if (err < 0)
1694 return err;
1695 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1696 "LFE Playback Switch",
1697 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1698 HDA_OUTPUT));
1699 if (err < 0)
1700 return err;
1701 } else if (i == AUTO_SEQ_FRONT) {
1702 /* add control to mixer index 0 */
1703 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1704 "Master Front Playback Volume",
1705 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1706 HDA_INPUT));
1707 if (err < 0)
1708 return err;
1709 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1710 "Master Front Playback Switch",
1711 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1712 HDA_INPUT));
1713 if (err < 0)
1714 return err;
1715
1716 /* add control to PW3 */
1717 sprintf(name, "%s Playback Volume", chname[i]);
1718 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1719 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1720 HDA_OUTPUT));
1721 if (err < 0)
1722 return err;
1723 sprintf(name, "%s Playback Switch", chname[i]);
1724 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1725 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1726 HDA_OUTPUT));
1727 if (err < 0)
1728 return err;
1729 } else {
1730 sprintf(name, "%s Playback Volume", chname[i]);
1731 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1732 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1733 HDA_OUTPUT));
1734 if (err < 0)
1735 return err;
1736 sprintf(name, "%s Playback Switch", chname[i]);
1737 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1738 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1739 HDA_OUTPUT));
1740 if (err < 0)
1741 return err;
1742 }
1743 }
1744
1745 return 0;
1746}
1747
1748static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1749{
1750 int err;
1751
1752 if (!pin)
1753 return 0;
1754
1755 spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1756
1757 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1758 "Headphone Playback Volume",
1759 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1760 if (err < 0)
1761 return err;
1762 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1763 "Headphone Playback Switch",
1764 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1765 if (err < 0)
1766 return err;
1767
1768 return 0;
1769}
1770
1771/* create playback/capture controls for input pins */
1772static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1773 const struct auto_pin_cfg *cfg)
1774{
1775 static char *labels[] = {
1776 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1777 };
1778 struct hda_input_mux *imux = &spec->private_imux;
1779 int i, err, idx = 0;
1780
1781 /* for internal loopback recording select */
1782 imux->items[imux->num_items].label = "Stereo Mixer";
1783 imux->items[imux->num_items].index = idx;
1784 imux->num_items++;
1785
1786 for (i = 0; i < AUTO_PIN_LAST; i++) {
1787 if (!cfg->input_pins[i])
1788 continue;
1789
1790 switch (cfg->input_pins[i]) {
1791 case 0x1a: /* Mic */
1792 idx = 2;
1793 break;
1794
1795 case 0x1b: /* Line In */
1796 idx = 3;
1797 break;
1798
1799 case 0x1e: /* Front Mic */
1800 idx = 4;
1801 break;
1802
1803 case 0x1f: /* CD */
1804 idx = 1;
1805 break;
1806 }
1807 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1808 idx, 0x16);
1809 if (err < 0)
1810 return err;
1811 imux->items[imux->num_items].label = labels[i];
1812 imux->items[imux->num_items].index = idx;
1813 imux->num_items++;
1814 }
1815 return 0;
1816}
1817
1818static int vt1708B_parse_auto_config(struct hda_codec *codec)
1819{
1820 struct via_spec *spec = codec->spec;
1821 int err;
1822
1823 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1824 if (err < 0)
1825 return err;
1826 err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1827 if (err < 0)
1828 return err;
1829 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1830 return 0; /* can't find valid BIOS pin config */
1831
1832 err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1833 if (err < 0)
1834 return err;
1835 err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1836 if (err < 0)
1837 return err;
1838 err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1839 if (err < 0)
1840 return err;
1841
1842 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1843
1844 if (spec->autocfg.dig_out_pin)
1845 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1846 if (spec->autocfg.dig_in_pin)
1847 spec->dig_in_nid = VT1708B_DIGIN_NID;
1848
1849 if (spec->kctl_alloc)
1850 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1851
1852 spec->input_mux = &spec->private_imux;
1853
1854 return 1;
1855}
1856
1857#ifdef CONFIG_SND_HDA_POWER_SAVE
1858static struct hda_amp_list vt1708B_loopbacks[] = {
1859 { 0x16, HDA_INPUT, 1 },
1860 { 0x16, HDA_INPUT, 2 },
1861 { 0x16, HDA_INPUT, 3 },
1862 { 0x16, HDA_INPUT, 4 },
1863 { } /* end */
1864};
1865#endif
1866
1867static int patch_vt1708B_8ch(struct hda_codec *codec)
1868{
1869 struct via_spec *spec;
1870 int err;
1871
1872 /* create a codec specific record */
1873 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1874 if (spec == NULL)
1875 return -ENOMEM;
1876
1877 codec->spec = spec;
1878
1879 /* automatic parse from the BIOS config */
1880 err = vt1708B_parse_auto_config(codec);
1881 if (err < 0) {
1882 via_free(codec);
1883 return err;
1884 } else if (!err) {
1885 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1886 "from BIOS. Using genenic mode...\n");
1887 }
1888
1889 spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1890
1891 spec->stream_name_analog = "VT1708B Analog";
1892 spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1893 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1894
1895 spec->stream_name_digital = "VT1708B Digital";
1896 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1897 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1898
1899 if (!spec->adc_nids && spec->input_mux) {
1900 spec->adc_nids = vt1708B_adc_nids;
1901 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1902 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1903 spec->num_mixers++;
1904 }
1905
1906 codec->patch_ops = via_patch_ops;
1907
1908 codec->patch_ops.init = via_auto_init;
1909#ifdef CONFIG_SND_HDA_POWER_SAVE
1910 spec->loopback.amplist = vt1708B_loopbacks;
1911#endif
1912
1913 return 0;
1914}
1915
1916static int patch_vt1708B_4ch(struct hda_codec *codec)
1917{
1918 struct via_spec *spec;
1919 int err;
1920
1921 /* create a codec specific record */
1922 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1923 if (spec == NULL)
1924 return -ENOMEM;
1925
1926 codec->spec = spec;
1927
1928 /* automatic parse from the BIOS config */
1929 err = vt1708B_parse_auto_config(codec);
1930 if (err < 0) {
1931 via_free(codec);
1932 return err;
1933 } else if (!err) {
1934 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1935 "from BIOS. Using genenic mode...\n");
1936 }
1937
1938 spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1939
1940 spec->stream_name_analog = "VT1708B Analog";
1941 spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1942 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1943
1944 spec->stream_name_digital = "VT1708B Digital";
1945 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1946 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1947
1948 if (!spec->adc_nids && spec->input_mux) {
1949 spec->adc_nids = vt1708B_adc_nids;
1950 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1951 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1952 spec->num_mixers++;
1953 }
1954
1955 codec->patch_ops = via_patch_ops;
1956
1957 codec->patch_ops.init = via_auto_init;
1958#ifdef CONFIG_SND_HDA_POWER_SAVE
1959 spec->loopback.amplist = vt1708B_loopbacks;
1960#endif
c577b8a1
JC
1961
1962 return 0;
1963}
1964
1965/*
1966 * patch entries
1967 */
1968struct hda_codec_preset snd_hda_preset_via[] = {
1969 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1970 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1971 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1972 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
f7278fd0
JC
1973 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1974 .patch = patch_vt1709_10ch},
1975 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1976 .patch = patch_vt1709_10ch},
1977 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1978 .patch = patch_vt1709_10ch},
1979 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
1980 .patch = patch_vt1709_10ch},
1981 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
1982 .patch = patch_vt1709_6ch},
1983 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
1984 .patch = patch_vt1709_6ch},
1985 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
1986 .patch = patch_vt1709_6ch},
1987 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
1988 .patch = patch_vt1709_6ch},
1989 { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
1990 .patch = patch_vt1708B_8ch},
1991 { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
1992 .patch = patch_vt1708B_8ch},
1993 { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
1994 .patch = patch_vt1708B_8ch},
1995 { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
1996 .patch = patch_vt1708B_8ch},
1997 { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
1998 .patch = patch_vt1708B_4ch},
1999 { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
2000 .patch = patch_vt1708B_4ch},
2001 { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
2002 .patch = patch_vt1708B_4ch},
2003 { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
2004 .patch = patch_vt1708B_4ch},
c577b8a1
JC
2005 {} /* terminator */
2006};
This page took 0.326206 seconds and 5 git commands to generate.