[ALSA] ali5451 - Code clean up, irq handler fix
[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 */
30/* */
31/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32
33
34#include <sound/driver.h>
35#include <linux/init.h>
36#include <linux/delay.h>
37#include <linux/slab.h>
c577b8a1
JC
38#include <sound/core.h>
39#include "hda_codec.h"
40#include "hda_local.h"
41
42
43/* amp values */
44#define AMP_VAL_IDX_SHIFT 19
45#define AMP_VAL_IDX_MASK (0x0f<<19)
46
47#define NUM_CONTROL_ALLOC 32
48#define NUM_VERB_ALLOC 32
49
50/* Pin Widget NID */
51#define VT1708_HP_NID 0x13
52#define VT1708_DIGOUT_NID 0x14
53#define VT1708_DIGIN_NID 0x16
54
55#define VT1709_HP_DAC_NID 0x28
56#define VT1709_DIGOUT_NID 0x13
57#define VT1709_DIGIN_NID 0x17
58
59#define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
60#define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
61#define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
62
63
64enum {
65 VIA_CTL_WIDGET_VOL,
66 VIA_CTL_WIDGET_MUTE,
67};
68
69enum {
70 AUTO_SEQ_FRONT,
71 AUTO_SEQ_SURROUND,
72 AUTO_SEQ_CENLFE,
73 AUTO_SEQ_SIDE
74};
75
76static struct snd_kcontrol_new vt1708_control_templates[] = {
77 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
78 HDA_CODEC_MUTE(NULL, 0, 0, 0),
79};
80
81
82struct via_spec {
83 /* codec parameterization */
84 struct snd_kcontrol_new *mixers[3];
85 unsigned int num_mixers;
86
87 struct hda_verb *init_verbs;
88
89 char *stream_name_analog;
90 struct hda_pcm_stream *stream_analog_playback;
91 struct hda_pcm_stream *stream_analog_capture;
92
93 char *stream_name_digital;
94 struct hda_pcm_stream *stream_digital_playback;
95 struct hda_pcm_stream *stream_digital_capture;
96
97 /* playback */
98 struct hda_multi_out multiout;
99
100 /* capture */
101 unsigned int num_adc_nids;
102 hda_nid_t *adc_nids;
103 hda_nid_t dig_in_nid;
104
105 /* capture source */
106 const struct hda_input_mux *input_mux;
107 unsigned int cur_mux[3];
108
109 /* PCM information */
110 struct hda_pcm pcm_rec[2];
111
112 /* dynamic controls, init_verbs and input_mux */
113 struct auto_pin_cfg autocfg;
114 unsigned int num_kctl_alloc, num_kctl_used;
115 struct snd_kcontrol_new *kctl_alloc;
116 struct hda_input_mux private_imux;
117 hda_nid_t private_dac_nids[4];
118};
119
120static hda_nid_t vt1708_adc_nids[2] = {
121 /* ADC1-2 */
122 0x15, 0x27
123};
124
125static hda_nid_t vt1709_adc_nids[3] = {
126 /* ADC1-2 */
127 0x14, 0x15, 0x16
128};
129
130/* add dynamic controls */
131static int via_add_control(struct via_spec *spec, int type, const char *name,
132 unsigned long val)
133{
134 struct snd_kcontrol_new *knew;
135
136 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
137 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
138
139 /* array + terminator */
140 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
141 if (!knew)
142 return -ENOMEM;
143 if (spec->kctl_alloc) {
144 memcpy(knew, spec->kctl_alloc,
145 sizeof(*knew) * spec->num_kctl_alloc);
146 kfree(spec->kctl_alloc);
147 }
148 spec->kctl_alloc = knew;
149 spec->num_kctl_alloc = num;
150 }
151
152 knew = &spec->kctl_alloc[spec->num_kctl_used];
153 *knew = vt1708_control_templates[type];
154 knew->name = kstrdup(name, GFP_KERNEL);
155
156 if (!knew->name)
157 return -ENOMEM;
158 knew->private_value = val;
159 spec->num_kctl_used++;
160 return 0;
161}
162
163/* create input playback/capture controls for the given pin */
164static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
165 const char *ctlname, int idx, int mix_nid)
166{
167 char name[32];
168 int err;
169
170 sprintf(name, "%s Playback Volume", ctlname);
171 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
172 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
173 if (err < 0)
174 return err;
175 sprintf(name, "%s Playback Switch", ctlname);
176 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
177 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
178 if (err < 0)
179 return err;
180 return 0;
181}
182
183static void via_auto_set_output_and_unmute(struct hda_codec *codec,
184 hda_nid_t nid, int pin_type,
185 int dac_idx)
186{
187 /* set as output */
188 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
189 pin_type);
190 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
191 AMP_OUT_UNMUTE);
192}
193
194
195static void via_auto_init_multi_out(struct hda_codec *codec)
196{
197 struct via_spec *spec = codec->spec;
198 int i;
199
200 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
201 hda_nid_t nid = spec->autocfg.line_out_pins[i];
202 if (nid)
203 via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
204 }
205}
206
207static void via_auto_init_hp_out(struct hda_codec *codec)
208{
209 struct via_spec *spec = codec->spec;
210 hda_nid_t pin;
211
212 pin = spec->autocfg.hp_pins[0];
213 if (pin) /* connect to front */
214 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
215}
216
217static void via_auto_init_analog_input(struct hda_codec *codec)
218{
219 struct via_spec *spec = codec->spec;
220 int i;
221
222 for (i = 0; i < AUTO_PIN_LAST; i++) {
223 hda_nid_t nid = spec->autocfg.input_pins[i];
224
225 snd_hda_codec_write(codec, nid, 0,
226 AC_VERB_SET_PIN_WIDGET_CONTROL,
227 (i <= AUTO_PIN_FRONT_MIC ?
228 PIN_VREF50 : PIN_IN));
229
230 }
231}
232/*
233 * input MUX handling
234 */
235static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
236 struct snd_ctl_elem_info *uinfo)
237{
238 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
239 struct via_spec *spec = codec->spec;
240 return snd_hda_input_mux_info(spec->input_mux, uinfo);
241}
242
243static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
244 struct snd_ctl_elem_value *ucontrol)
245{
246 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
247 struct via_spec *spec = codec->spec;
248 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
249
250 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
251 return 0;
252}
253
254static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_value *ucontrol)
256{
257 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258 struct via_spec *spec = codec->spec;
259 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
260 unsigned int vendor_id = codec->vendor_id;
261
262 /* AIW0 lydia 060801 add for correct sw0 input select */
263 if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
264 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
265 0x18, &spec->cur_mux[adc_idx]);
266 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
267 IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) )
268 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
269 0x19, &spec->cur_mux[adc_idx]);
270 else
271 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
272 spec->adc_nids[adc_idx],
273 &spec->cur_mux[adc_idx]);
274}
275
276/* capture mixer elements */
277static struct snd_kcontrol_new vt1708_capture_mixer[] = {
278 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
279 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
280 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
281 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
282 {
283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
284 /* The multiple "Capture Source" controls confuse alsamixer
285 * So call somewhat different..
286 * FIXME: the controls appear in the "playback" view!
287 */
288 /* .name = "Capture Source", */
289 .name = "Input Source",
290 .count = 1,
291 .info = via_mux_enum_info,
292 .get = via_mux_enum_get,
293 .put = via_mux_enum_put,
294 },
295 { } /* end */
296};
297/*
298 * generic initialization of ADC, input mixers and output mixers
299 */
300static struct hda_verb vt1708_volume_init_verbs[] = {
301 /*
302 * Unmute ADC0-1 and set the default input to mic-in
303 */
304 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
305 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
306
307
308 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
309 * mixer widget
310 */
311 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
312 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
313 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
315 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
317
318 /*
319 * Set up output mixers (0x19 - 0x1b)
320 */
321 /* set vol=0 to output mixers */
322 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
323 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
324 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
325
326 /* Setup default input to PW4 */
327 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
328 /* Set mic as default input of sw0 */
329 {0x18, AC_VERB_SET_CONNECT_SEL, 0x2},
330 /* PW9 Output enable */
331 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
332};
333
334static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
335 struct hda_codec *codec,
336 struct snd_pcm_substream *substream)
337{
338 struct via_spec *spec = codec->spec;
339 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
340}
341
342static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
343 struct hda_codec *codec,
344 unsigned int stream_tag,
345 unsigned int format,
346 struct snd_pcm_substream *substream)
347{
348 struct via_spec *spec = codec->spec;
349 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
350 stream_tag, format, substream);
351}
352
353static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
354 struct hda_codec *codec,
355 struct snd_pcm_substream *substream)
356{
357 struct via_spec *spec = codec->spec;
358 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
359}
360
361/*
362 * Digital out
363 */
364static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
365 struct hda_codec *codec,
366 struct snd_pcm_substream *substream)
367{
368 struct via_spec *spec = codec->spec;
369 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
370}
371
372static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
373 struct hda_codec *codec,
374 struct snd_pcm_substream *substream)
375{
376 struct via_spec *spec = codec->spec;
377 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
378}
379
380/*
381 * Analog capture
382 */
383static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
384 struct hda_codec *codec,
385 unsigned int stream_tag,
386 unsigned int format,
387 struct snd_pcm_substream *substream)
388{
389 struct via_spec *spec = codec->spec;
390
391 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
392 stream_tag, 0, format);
393 return 0;
394}
395
396static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
397 struct hda_codec *codec,
398 struct snd_pcm_substream *substream)
399{
400 struct via_spec *spec = codec->spec;
401 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
402 0, 0, 0);
403 return 0;
404}
405
406static struct hda_pcm_stream vt1708_pcm_analog_playback = {
407 .substreams = 1,
408 .channels_min = 2,
409 .channels_max = 8,
410 .nid = 0x10, /* NID to query formats and rates */
411 .ops = {
412 .open = via_playback_pcm_open,
413 .prepare = via_playback_pcm_prepare,
414 .cleanup = via_playback_pcm_cleanup
415 },
416};
417
418static struct hda_pcm_stream vt1708_pcm_analog_capture = {
419 .substreams = 2,
420 .channels_min = 2,
421 .channels_max = 2,
422 .nid = 0x15, /* NID to query formats and rates */
423 .ops = {
424 .prepare = via_capture_pcm_prepare,
425 .cleanup = via_capture_pcm_cleanup
426 },
427};
428
429static struct hda_pcm_stream vt1708_pcm_digital_playback = {
430 .substreams = 1,
431 .channels_min = 2,
432 .channels_max = 2,
433 /* NID is set in via_build_pcms */
434 .ops = {
435 .open = via_dig_playback_pcm_open,
436 .close = via_dig_playback_pcm_close
437 },
438};
439
440static struct hda_pcm_stream vt1708_pcm_digital_capture = {
441 .substreams = 1,
442 .channels_min = 2,
443 .channels_max = 2,
444};
445
446static int via_build_controls(struct hda_codec *codec)
447{
448 struct via_spec *spec = codec->spec;
449 int err;
450 int i;
451
452 for (i = 0; i < spec->num_mixers; i++) {
453 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
454 if (err < 0)
455 return err;
456 }
457
458 if (spec->multiout.dig_out_nid) {
459 err = snd_hda_create_spdif_out_ctls(codec,
460 spec->multiout.dig_out_nid);
461 if (err < 0)
462 return err;
463 }
464 if (spec->dig_in_nid) {
465 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
466 if (err < 0)
467 return err;
468 }
469 return 0;
470}
471
472static int via_build_pcms(struct hda_codec *codec)
473{
474 struct via_spec *spec = codec->spec;
475 struct hda_pcm *info = spec->pcm_rec;
476
477 codec->num_pcms = 1;
478 codec->pcm_info = info;
479
480 info->name = spec->stream_name_analog;
481 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
482 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
483 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
484 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
485
486 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
487 spec->multiout.max_channels;
488
489 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
490 codec->num_pcms++;
491 info++;
492 info->name = spec->stream_name_digital;
493 if (spec->multiout.dig_out_nid) {
494 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
495 *(spec->stream_digital_playback);
496 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
497 spec->multiout.dig_out_nid;
498 }
499 if (spec->dig_in_nid) {
500 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
501 *(spec->stream_digital_capture);
502 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
503 spec->dig_in_nid;
504 }
505 }
506
507 return 0;
508}
509
510static void via_free(struct hda_codec *codec)
511{
512 struct via_spec *spec = codec->spec;
513 unsigned int i;
514
515 if (!spec)
516 return;
517
518 if (spec->kctl_alloc) {
519 for (i = 0; i < spec->num_kctl_used; i++)
520 kfree(spec->kctl_alloc[i].name);
521 kfree(spec->kctl_alloc);
522 }
523
524 kfree(codec->spec);
525}
526
527static int via_init(struct hda_codec *codec)
528{
529 struct via_spec *spec = codec->spec;
530 snd_hda_sequence_write(codec, spec->init_verbs);
531 return 0;
532}
533
534#ifdef CONFIG_PM
535/*
536 * resume
537 */
538static int via_resume(struct hda_codec *codec)
539{
540 struct via_spec *spec = codec->spec;
541 int i;
542
543 via_init(codec);
544 for (i = 0; i < spec->num_mixers; i++)
545 snd_hda_resume_ctls(codec, spec->mixers[i]);
546 if (spec->multiout.dig_out_nid)
547 snd_hda_resume_spdif_out(codec);
548 if (spec->dig_in_nid)
549 snd_hda_resume_spdif_in(codec);
550
551 return 0;
552}
553#endif
554
555/*
556 */
557static struct hda_codec_ops via_patch_ops = {
558 .build_controls = via_build_controls,
559 .build_pcms = via_build_pcms,
560 .init = via_init,
561 .free = via_free,
562#ifdef CONFIG_PM
563 .resume = via_resume,
564#endif
565};
566
567/* fill in the dac_nids table from the parsed pin configuration */
568static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
569 const struct auto_pin_cfg *cfg)
570{
571 int i;
572 hda_nid_t nid;
573
574 spec->multiout.num_dacs = cfg->line_outs;
575
576 spec->multiout.dac_nids = spec->private_dac_nids;
577
578 for(i = 0; i < 4; i++) {
579 nid = cfg->line_out_pins[i];
580 if (nid) {
581 /* config dac list */
582 switch (i) {
583 case AUTO_SEQ_FRONT:
584 spec->multiout.dac_nids[i] = 0x10;
585 break;
586 case AUTO_SEQ_CENLFE:
587 spec->multiout.dac_nids[i] = 0x12;
588 break;
589 case AUTO_SEQ_SURROUND:
590 spec->multiout.dac_nids[i] = 0x13;
591 break;
592 case AUTO_SEQ_SIDE:
593 spec->multiout.dac_nids[i] = 0x11;
594 break;
595 }
596 }
597 }
598
599 return 0;
600}
601
602/* add playback controls from the parsed DAC table */
603static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
604 const struct auto_pin_cfg *cfg)
605{
606 char name[32];
607 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
608 hda_nid_t nid, nid_vol = 0;
609 int i, err;
610
611 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
612 nid = cfg->line_out_pins[i];
613
614 if (!nid)
615 continue;
616
617 if (i != AUTO_SEQ_FRONT)
618 nid_vol = 0x1b - i + 1;
619
620 if (i == AUTO_SEQ_CENLFE) {
621 /* Center/LFE */
622 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
623 "Center Playback Volume",
624 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
625 if (err < 0)
626 return err;
627 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
628 "LFE Playback Volume",
629 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
630 if (err < 0)
631 return err;
632 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
633 "Center Playback Switch",
634 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
635 if (err < 0)
636 return err;
637 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
638 "LFE Playback Switch",
639 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
640 if (err < 0)
641 return err;
642 } else if (i == AUTO_SEQ_FRONT){
643 /* add control to mixer index 0 */
644 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
645 "Master Front Playback Volume",
646 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
647 if (err < 0)
648 return err;
649 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
650 "Master Front Playback Switch",
651 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
652 if (err < 0)
653 return err;
654
655 /* add control to PW3 */
656 sprintf(name, "%s Playback Volume", chname[i]);
657 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
658 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
659 if (err < 0)
660 return err;
661 sprintf(name, "%s Playback Switch", chname[i]);
662 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
663 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
664 if (err < 0)
665 return err;
666 } else {
667 sprintf(name, "%s Playback Volume", chname[i]);
668 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
669 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
670 if (err < 0)
671 return err;
672 sprintf(name, "%s Playback Switch", chname[i]);
673 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
674 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
675 if (err < 0)
676 return err;
677 }
678 }
679
680 return 0;
681}
682
683static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
684{
685 int err;
686
687 if (!pin)
688 return 0;
689
690 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
691
692 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
693 "Headphone Playback Volume",
694 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
695 if (err < 0)
696 return err;
697 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
698 "Headphone Playback Switch",
699 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
700 if (err < 0)
701 return err;
702
703 return 0;
704}
705
706/* create playback/capture controls for input pins */
707static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
708 const struct auto_pin_cfg *cfg)
709{
710 static char *labels[] = {
711 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
712 };
713 struct hda_input_mux *imux = &spec->private_imux;
714 int i, err, idx = 0;
715
716 /* for internal loopback recording select */
717 imux->items[imux->num_items].label = "Stereo Mixer";
718 imux->items[imux->num_items].index = idx;
719 imux->num_items++;
720
721 for (i = 0; i < AUTO_PIN_LAST; i++) {
722 if (!cfg->input_pins[i])
723 continue;
724
725 switch (cfg->input_pins[i]) {
726 case 0x1d: /* Mic */
727 idx = 2;
728 break;
729
730 case 0x1e: /* Line In */
731 idx = 3;
732 break;
733
734 case 0x21: /* Front Mic */
735 idx = 4;
736 break;
737
738 case 0x24: /* CD */
739 idx = 1;
740 break;
741 }
742 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
743 idx, 0x17);
744 if (err < 0)
745 return err;
746 imux->items[imux->num_items].label = labels[i];
747 imux->items[imux->num_items].index = idx;
748 imux->num_items++;
749 }
750 return 0;
751}
752
753static int vt1708_parse_auto_config(struct hda_codec *codec)
754{
755 struct via_spec *spec = codec->spec;
756 int err;
757
758 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
759 if (err < 0)
760 return err;
761 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
762 if (err < 0)
763 return err;
764 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
765 return 0; /* can't find valid BIOS pin config */
766
767 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
768 if (err < 0)
769 return err;
770 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
771 if (err < 0)
772 return err;
773 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
774 if (err < 0)
775 return err;
776
777 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
778
779 if (spec->autocfg.dig_out_pin)
780 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
781 if (spec->autocfg.dig_in_pin)
782 spec->dig_in_nid = VT1708_DIGIN_NID;
783
784 if (spec->kctl_alloc)
785 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
786
787 spec->init_verbs = vt1708_volume_init_verbs;
788
789 spec->input_mux = &spec->private_imux;
790
791 return 1;
792}
793
794/* init callback for auto-configuration model -- overriding the default init */
795static int via_auto_init(struct hda_codec *codec)
796{
797 via_init(codec);
798 via_auto_init_multi_out(codec);
799 via_auto_init_hp_out(codec);
800 via_auto_init_analog_input(codec);
801 return 0;
802}
803
804static int patch_vt1708(struct hda_codec *codec)
805{
806 struct via_spec *spec;
807 int err;
808
809 /* create a codec specific record */
810 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
811 if (spec == NULL)
812 return -ENOMEM;
813
814 codec->spec = spec;
815
816 /* automatic parse from the BIOS config */
817 err = vt1708_parse_auto_config(codec);
818 if (err < 0) {
819 via_free(codec);
820 return err;
821 } else if (!err) {
822 printk(KERN_INFO "hda_codec: Cannot set up configuration "
823 "from BIOS. Using genenic mode...\n");
824 }
825
826
827 spec->stream_name_analog = "VT1708 Analog";
828 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
829 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
830
831 spec->stream_name_digital = "VT1708 Digital";
832 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
833 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
834
835
836 if (!spec->adc_nids && spec->input_mux) {
837 spec->adc_nids = vt1708_adc_nids;
838 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
839 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
840 spec->num_mixers++;
841 }
842
843 codec->patch_ops = via_patch_ops;
844
845 codec->patch_ops.init = via_auto_init;
846
847 return 0;
848}
849
850/* capture mixer elements */
851static struct snd_kcontrol_new vt1709_capture_mixer[] = {
852 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
853 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
854 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
855 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
856 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
857 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
858 {
859 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
860 /* The multiple "Capture Source" controls confuse alsamixer
861 * So call somewhat different..
862 * FIXME: the controls appear in the "playback" view!
863 */
864 /* .name = "Capture Source", */
865 .name = "Input Source",
866 .count = 1,
867 .info = via_mux_enum_info,
868 .get = via_mux_enum_get,
869 .put = via_mux_enum_put,
870 },
871 { } /* end */
872};
873
874/*
875 * generic initialization of ADC, input mixers and output mixers
876 */
877static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
878 /*
879 * Unmute ADC0-2 and set the default input to mic-in
880 */
881 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
882 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
883 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
884
885
886 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
887 * mixer widget
888 */
889 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
890 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
891 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
892 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
893 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
894 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
895
896 /*
897 * Set up output selector (0x1a, 0x1b, 0x29)
898 */
899 /* set vol=0 to output mixers */
900 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
901 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
902 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
903
904 /*
905 * Unmute PW3 and PW4
906 */
907 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
908 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
909
910 /* Set input of PW4 as AOW4 */
911 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
912 /* Set mic as default input of sw0 */
913 {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
914 /* PW9 Output enable */
915 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
916 { }
917};
918
919static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
920 .substreams = 1,
921 .channels_min = 2,
922 .channels_max = 10,
923 .nid = 0x10, /* NID to query formats and rates */
924 .ops = {
925 .open = via_playback_pcm_open,
926 .prepare = via_playback_pcm_prepare,
927 .cleanup = via_playback_pcm_cleanup
928 },
929};
930
931static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
932 .substreams = 1,
933 .channels_min = 2,
934 .channels_max = 6,
935 .nid = 0x10, /* NID to query formats and rates */
936 .ops = {
937 .open = via_playback_pcm_open,
938 .prepare = via_playback_pcm_prepare,
939 .cleanup = via_playback_pcm_cleanup
940 },
941};
942
943static struct hda_pcm_stream vt1709_pcm_analog_capture = {
944 .substreams = 2,
945 .channels_min = 2,
946 .channels_max = 2,
947 .nid = 0x14, /* NID to query formats and rates */
948 .ops = {
949 .prepare = via_capture_pcm_prepare,
950 .cleanup = via_capture_pcm_cleanup
951 },
952};
953
954static struct hda_pcm_stream vt1709_pcm_digital_playback = {
955 .substreams = 1,
956 .channels_min = 2,
957 .channels_max = 2,
958 /* NID is set in via_build_pcms */
959 .ops = {
960 .open = via_dig_playback_pcm_open,
961 .close = via_dig_playback_pcm_close
962 },
963};
964
965static struct hda_pcm_stream vt1709_pcm_digital_capture = {
966 .substreams = 1,
967 .channels_min = 2,
968 .channels_max = 2,
969};
970
971static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
972 const struct auto_pin_cfg *cfg)
973{
974 int i;
975 hda_nid_t nid;
976
977 if (cfg->line_outs == 4) /* 10 channels */
978 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
979 else if (cfg->line_outs == 3) /* 6 channels */
980 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
981
982 spec->multiout.dac_nids = spec->private_dac_nids;
983
984 if (cfg->line_outs == 4) { /* 10 channels */
985 for (i = 0; i < cfg->line_outs; i++) {
986 nid = cfg->line_out_pins[i];
987 if (nid) {
988 /* config dac list */
989 switch (i) {
990 case AUTO_SEQ_FRONT:
991 /* AOW0 */
992 spec->multiout.dac_nids[i] = 0x10;
993 break;
994 case AUTO_SEQ_CENLFE:
995 /* AOW2 */
996 spec->multiout.dac_nids[i] = 0x12;
997 break;
998 case AUTO_SEQ_SURROUND:
999 /* AOW3 */
1000 spec->multiout.dac_nids[i] = 0x27;
1001 break;
1002 case AUTO_SEQ_SIDE:
1003 /* AOW1 */
1004 spec->multiout.dac_nids[i] = 0x11;
1005 break;
1006 default:
1007 break;
1008 }
1009 }
1010 }
1011 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1012
1013 } else if (cfg->line_outs == 3) { /* 6 channels */
1014 for(i = 0; i < cfg->line_outs; i++) {
1015 nid = cfg->line_out_pins[i];
1016 if (nid) {
1017 /* config dac list */
1018 switch(i) {
1019 case AUTO_SEQ_FRONT:
1020 /* AOW0 */
1021 spec->multiout.dac_nids[i] = 0x10;
1022 break;
1023 case AUTO_SEQ_CENLFE:
1024 /* AOW2 */
1025 spec->multiout.dac_nids[i] = 0x12;
1026 break;
1027 case AUTO_SEQ_SURROUND:
1028 /* AOW1 */
1029 spec->multiout.dac_nids[i] = 0x11;
1030 break;
1031 default:
1032 break;
1033 }
1034 }
1035 }
1036 }
1037
1038 return 0;
1039}
1040
1041/* add playback controls from the parsed DAC table */
1042static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1043 const struct auto_pin_cfg *cfg)
1044{
1045 char name[32];
1046 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1047 hda_nid_t nid = 0;
1048 int i, err;
1049
1050 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1051 nid = cfg->line_out_pins[i];
1052
1053 if (!nid)
1054 continue;
1055
1056 if (i == AUTO_SEQ_CENLFE) {
1057 /* Center/LFE */
1058 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1059 "Center Playback Volume",
1060 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1061 if (err < 0)
1062 return err;
1063 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1064 "LFE Playback Volume",
1065 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1066 if (err < 0)
1067 return err;
1068 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1069 "Center Playback Switch",
1070 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1071 if (err < 0)
1072 return err;
1073 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1074 "LFE Playback Switch",
1075 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1076 if (err < 0)
1077 return err;
1078 } else if (i == AUTO_SEQ_FRONT){
1079 /* add control to mixer index 0 */
1080 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1081 "Master Front Playback Volume",
1082 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1083 if (err < 0)
1084 return err;
1085 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1086 "Master Front Playback Switch",
1087 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1088 if (err < 0)
1089 return err;
1090
1091 /* add control to PW3 */
1092 sprintf(name, "%s Playback Volume", chname[i]);
1093 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1094 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1095 if (err < 0)
1096 return err;
1097 sprintf(name, "%s Playback Switch", chname[i]);
1098 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1099 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1100 if (err < 0)
1101 return err;
1102 } else if (i == AUTO_SEQ_SURROUND) {
1103 sprintf(name, "%s Playback Volume", chname[i]);
1104 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1105 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1106 if (err < 0)
1107 return err;
1108 sprintf(name, "%s Playback Switch", chname[i]);
1109 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1110 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1111 if (err < 0)
1112 return err;
1113 } else if (i == AUTO_SEQ_SIDE) {
1114 sprintf(name, "%s Playback Volume", chname[i]);
1115 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1116 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1117 if (err < 0)
1118 return err;
1119 sprintf(name, "%s Playback Switch", chname[i]);
1120 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1121 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1122 if (err < 0)
1123 return err;
1124 }
1125 }
1126
1127 return 0;
1128}
1129
1130static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1131{
1132 int err;
1133
1134 if (!pin)
1135 return 0;
1136
1137 if (spec->multiout.num_dacs == 5) /* 10 channels */
1138 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1139 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1140 spec->multiout.hp_nid = 0;
1141
1142 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1143 "Headphone Playback Volume",
1144 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1145 if (err < 0)
1146 return err;
1147 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1148 "Headphone Playback Switch",
1149 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1150 if (err < 0)
1151 return err;
1152
1153 return 0;
1154}
1155
1156/* create playback/capture controls for input pins */
1157static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1158 const struct auto_pin_cfg *cfg)
1159{
1160 static char *labels[] = {
1161 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1162 };
1163 struct hda_input_mux *imux = &spec->private_imux;
1164 int i, err, idx = 0;
1165
1166 /* for internal loopback recording select */
1167 imux->items[imux->num_items].label = "Stereo Mixer";
1168 imux->items[imux->num_items].index = idx;
1169 imux->num_items++;
1170
1171 for (i = 0; i < AUTO_PIN_LAST; i++) {
1172 if (!cfg->input_pins[i])
1173 continue;
1174
1175 switch (cfg->input_pins[i]) {
1176 case 0x1d: /* Mic */
1177 idx = 2;
1178 break;
1179
1180 case 0x1e: /* Line In */
1181 idx = 3;
1182 break;
1183
1184 case 0x21: /* Front Mic */
1185 idx = 4;
1186 break;
1187
1188 case 0x23: /* CD */
1189 idx = 1;
1190 break;
1191 }
1192 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1193 idx, 0x18);
1194 if (err < 0)
1195 return err;
1196 imux->items[imux->num_items].label = labels[i];
1197 imux->items[imux->num_items].index = idx;
1198 imux->num_items++;
1199 }
1200 return 0;
1201}
1202
1203static int vt1709_parse_auto_config(struct hda_codec *codec)
1204{
1205 struct via_spec *spec = codec->spec;
1206 int err;
1207
1208 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1209 if (err < 0)
1210 return err;
1211 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1212 if (err < 0)
1213 return err;
1214 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1215 return 0; /* can't find valid BIOS pin config */
1216
1217 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1218 if (err < 0)
1219 return err;
1220 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1221 if (err < 0)
1222 return err;
1223 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1224 if (err < 0)
1225 return err;
1226
1227 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1228
1229 if (spec->autocfg.dig_out_pin)
1230 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1231 if (spec->autocfg.dig_in_pin)
1232 spec->dig_in_nid = VT1709_DIGIN_NID;
1233
1234 if (spec->kctl_alloc)
1235 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1236
1237 spec->input_mux = &spec->private_imux;
1238
1239 return 1;
1240}
1241
1242static int patch_vt1709_10ch(struct hda_codec *codec)
1243{
1244 struct via_spec *spec;
1245 int err;
1246
1247 /* create a codec specific record */
1248 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1249 if (spec == NULL)
1250 return -ENOMEM;
1251
1252 codec->spec = spec;
1253
1254 err = vt1709_parse_auto_config(codec);
1255 if (err < 0) {
1256 via_free(codec);
1257 return err;
1258 } else if (!err) {
1259 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1260 "Using genenic mode...\n");
1261 }
1262
1263 spec->init_verbs = vt1709_10ch_volume_init_verbs;
1264
1265 spec->stream_name_analog = "VT1709 Analog";
1266 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1267 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1268
1269 spec->stream_name_digital = "VT1709 Digital";
1270 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1271 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1272
1273
1274 if (!spec->adc_nids && spec->input_mux) {
1275 spec->adc_nids = vt1709_adc_nids;
1276 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1277 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1278 spec->num_mixers++;
1279 }
1280
1281 codec->patch_ops = via_patch_ops;
1282
1283 codec->patch_ops.init = via_auto_init;
1284
1285 return 0;
1286}
1287/*
1288 * generic initialization of ADC, input mixers and output mixers
1289 */
1290static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1291 /*
1292 * Unmute ADC0-2 and set the default input to mic-in
1293 */
1294 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1295 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1296 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1297
1298
1299 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1300 * mixer widget
1301 */
1302 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1303 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1304 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1305 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1306 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1307 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1308
1309 /*
1310 * Set up output selector (0x1a, 0x1b, 0x29)
1311 */
1312 /* set vol=0 to output mixers */
1313 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1314 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1315 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1316
1317 /*
1318 * Unmute PW3 and PW4
1319 */
1320 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1321 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1322
1323 /* Set input of PW4 as MW0 */
1324 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1325 /* Set mic as default input of sw0 */
1326 {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
1327 /* PW9 Output enable */
1328 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1329 { }
1330};
1331
1332static int patch_vt1709_6ch(struct hda_codec *codec)
1333{
1334 struct via_spec *spec;
1335 int err;
1336
1337 /* create a codec specific record */
1338 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1339 if (spec == NULL)
1340 return -ENOMEM;
1341
1342 codec->spec = spec;
1343
1344 err = vt1709_parse_auto_config(codec);
1345 if (err < 0) {
1346 via_free(codec);
1347 return err;
1348 } else if (!err) {
1349 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1350 "Using genenic mode...\n");
1351 }
1352
1353 spec->init_verbs = vt1709_6ch_volume_init_verbs;
1354
1355 spec->stream_name_analog = "VT1709 Analog";
1356 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1357 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1358
1359 spec->stream_name_digital = "VT1709 Digital";
1360 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1361 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1362
1363
1364 if (!spec->adc_nids && spec->input_mux) {
1365 spec->adc_nids = vt1709_adc_nids;
1366 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1367 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1368 spec->num_mixers++;
1369 }
1370
1371 codec->patch_ops = via_patch_ops;
1372
1373 codec->patch_ops.init = via_auto_init;
1374
1375 return 0;
1376}
1377
1378/*
1379 * patch entries
1380 */
1381struct hda_codec_preset snd_hda_preset_via[] = {
1382 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1383 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1384 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1385 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1386 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1387 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1388 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1389 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1390 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1391 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1392 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1393 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1394 {} /* terminator */
1395};
This page took 0.131097 seconds and 5 git commands to generate.