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