[ALSA] hda-codec - Add channel-mode helper
[linux-2.6.git] / sound / pci / hda / patch_analog.c
1 /*
2  * HD audio interface patch for AD1981HD, AD1983, AD1986A
3  *
4  * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
5  *
6  *  This driver is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This driver is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  */
20
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
26 #include <sound/core.h>
27 #include "hda_codec.h"
28 #include "hda_local.h"
29
30 struct ad198x_spec {
31         snd_kcontrol_new_t *mixers[5];
32         int num_mixers;
33
34         const struct hda_verb *init_verbs[3];   /* initialization verbs
35                                                  * don't forget NULL termination!
36                                                  */
37         unsigned int num_init_verbs;
38
39         /* playback */
40         struct hda_multi_out multiout;  /* playback set-up
41                                          * max_channels, dacs must be set
42                                          * dig_out_nid and hp_nid are optional
43                                          */
44
45         /* capture */
46         unsigned int num_adc_nids;
47         hda_nid_t *adc_nids;
48         hda_nid_t dig_in_nid;           /* digital-in NID; optional */
49
50         /* capture source */
51         const struct hda_input_mux *input_mux;
52         unsigned int cur_mux[3];
53
54         /* channel model */
55         const struct hda_channel_mode *channel_mode;
56         int num_channel_mode;
57
58         /* PCM information */
59         struct hda_pcm pcm_rec[2];      /* used in alc_build_pcms() */
60
61         struct semaphore amp_mutex;     /* PCM volume/mute control mutex */
62         unsigned int spdif_route;
63 };
64
65 /*
66  * input MUX handling (common part)
67  */
68 static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
69 {
70         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
71         struct ad198x_spec *spec = codec->spec;
72
73         return snd_hda_input_mux_info(spec->input_mux, uinfo);
74 }
75
76 static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
77 {
78         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
79         struct ad198x_spec *spec = codec->spec;
80         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
81
82         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
83         return 0;
84 }
85
86 static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
87 {
88         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
89         struct ad198x_spec *spec = codec->spec;
90         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
91
92         return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
93                                      spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
94 }
95
96 /*
97  * initialization (common callbacks)
98  */
99 static int ad198x_init(struct hda_codec *codec)
100 {
101         struct ad198x_spec *spec = codec->spec;
102         int i;
103
104         for (i = 0; i < spec->num_init_verbs; i++)
105                 snd_hda_sequence_write(codec, spec->init_verbs[i]);
106         return 0;
107 }
108
109 static int ad198x_build_controls(struct hda_codec *codec)
110 {
111         struct ad198x_spec *spec = codec->spec;
112         unsigned int i;
113         int err;
114
115         for (i = 0; i < spec->num_mixers; i++) {
116                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
117                 if (err < 0)
118                         return err;
119         }
120         if (spec->multiout.dig_out_nid) {
121                 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
122                 if (err < 0)
123                         return err;
124         } 
125         if (spec->dig_in_nid) {
126                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
127                 if (err < 0)
128                         return err;
129         }
130         return 0;
131 }
132
133 /*
134  * Analog playback callbacks
135  */
136 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
137                                     struct hda_codec *codec,
138                                     snd_pcm_substream_t *substream)
139 {
140         struct ad198x_spec *spec = codec->spec;
141         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
142 }
143
144 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
145                                        struct hda_codec *codec,
146                                        unsigned int stream_tag,
147                                        unsigned int format,
148                                        snd_pcm_substream_t *substream)
149 {
150         struct ad198x_spec *spec = codec->spec;
151         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
152                                                 format, substream);
153 }
154
155 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
156                                        struct hda_codec *codec,
157                                        snd_pcm_substream_t *substream)
158 {
159         struct ad198x_spec *spec = codec->spec;
160         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
161 }
162
163 /*
164  * Digital out
165  */
166 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
167                                         struct hda_codec *codec,
168                                         snd_pcm_substream_t *substream)
169 {
170         struct ad198x_spec *spec = codec->spec;
171         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
172 }
173
174 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
175                                          struct hda_codec *codec,
176                                          snd_pcm_substream_t *substream)
177 {
178         struct ad198x_spec *spec = codec->spec;
179         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
180 }
181
182 /*
183  * Analog capture
184  */
185 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
186                                       struct hda_codec *codec,
187                                       unsigned int stream_tag,
188                                       unsigned int format,
189                                       snd_pcm_substream_t *substream)
190 {
191         struct ad198x_spec *spec = codec->spec;
192         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
193                                    stream_tag, 0, format);
194         return 0;
195 }
196
197 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
198                                       struct hda_codec *codec,
199                                       snd_pcm_substream_t *substream)
200 {
201         struct ad198x_spec *spec = codec->spec;
202         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
203                                    0, 0, 0);
204         return 0;
205 }
206
207
208 /*
209  */
210 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
211         .substreams = 1,
212         .channels_min = 2,
213         .channels_max = 6, /* changed later */
214         .nid = 0, /* fill later */
215         .ops = {
216                 .open = ad198x_playback_pcm_open,
217                 .prepare = ad198x_playback_pcm_prepare,
218                 .cleanup = ad198x_playback_pcm_cleanup
219         },
220 };
221
222 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
223         .substreams = 1,
224         .channels_min = 2,
225         .channels_max = 2,
226         .nid = 0, /* fill later */
227         .ops = {
228                 .prepare = ad198x_capture_pcm_prepare,
229                 .cleanup = ad198x_capture_pcm_cleanup
230         },
231 };
232
233 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
234         .substreams = 1,
235         .channels_min = 2,
236         .channels_max = 2,
237         .nid = 0, /* fill later */
238         .ops = {
239                 .open = ad198x_dig_playback_pcm_open,
240                 .close = ad198x_dig_playback_pcm_close
241         },
242 };
243
244 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
245         .substreams = 1,
246         .channels_min = 2,
247         .channels_max = 2,
248         /* NID is set in alc_build_pcms */
249 };
250
251 static int ad198x_build_pcms(struct hda_codec *codec)
252 {
253         struct ad198x_spec *spec = codec->spec;
254         struct hda_pcm *info = spec->pcm_rec;
255
256         codec->num_pcms = 1;
257         codec->pcm_info = info;
258
259         info->name = "AD198x Analog";
260         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
261         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
262         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
263         info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
264         info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
265         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
266
267         if (spec->multiout.dig_out_nid) {
268                 info++;
269                 codec->num_pcms++;
270                 info->name = "AD198x Digital";
271                 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
272                 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
273                 if (spec->dig_in_nid) {
274                         info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
275                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
276                 }
277         }
278
279         return 0;
280 }
281
282 static void ad198x_free(struct hda_codec *codec)
283 {
284         kfree(codec->spec);
285 }
286
287 #ifdef CONFIG_PM
288 static int ad198x_resume(struct hda_codec *codec)
289 {
290         struct ad198x_spec *spec = codec->spec;
291         int i;
292
293         ad198x_init(codec);
294         for (i = 0; i < spec->num_mixers; i++)
295                 snd_hda_resume_ctls(codec, spec->mixers[i]);
296         if (spec->multiout.dig_out_nid)
297                 snd_hda_resume_spdif_out(codec);
298         if (spec->dig_in_nid)
299                 snd_hda_resume_spdif_in(codec);
300         return 0;
301 }
302 #endif
303
304 static struct hda_codec_ops ad198x_patch_ops = {
305         .build_controls = ad198x_build_controls,
306         .build_pcms = ad198x_build_pcms,
307         .init = ad198x_init,
308         .free = ad198x_free,
309 #ifdef CONFIG_PM
310         .resume = ad198x_resume,
311 #endif
312 };
313
314
315 /*
316  * AD1986A specific
317  */
318
319 #define AD1986A_SPDIF_OUT       0x02
320 #define AD1986A_FRONT_DAC       0x03
321 #define AD1986A_SURR_DAC        0x04
322 #define AD1986A_CLFE_DAC        0x05
323 #define AD1986A_ADC             0x06
324
325 static hda_nid_t ad1986a_dac_nids[3] = {
326         AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
327 };
328 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
329
330 static struct hda_input_mux ad1986a_capture_source = {
331         .num_items = 7,
332         .items = {
333                 { "Mic", 0x0 },
334                 { "CD", 0x1 },
335                 { "Aux", 0x3 },
336                 { "Line", 0x4 },
337                 { "Mix", 0x5 },
338                 { "Mono", 0x6 },
339                 { "Phone", 0x7 },
340         },
341 };
342
343 /*
344  * PCM control
345  *
346  * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
347  */
348
349 #define ad1986a_pcm_amp_vol_info        snd_hda_mixer_amp_volume_info
350
351 static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
352 {
353         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
354         struct ad198x_spec *ad = codec->spec;
355
356         down(&ad->amp_mutex);
357         snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
358         up(&ad->amp_mutex);
359         return 0;
360 }
361
362 static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
363 {
364         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
365         struct ad198x_spec *ad = codec->spec;
366         int i, change = 0;
367
368         down(&ad->amp_mutex);
369         for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
370                 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
371                 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
372         }
373         kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
374         up(&ad->amp_mutex);
375         return change;
376 }
377
378 #define ad1986a_pcm_amp_sw_info         snd_hda_mixer_amp_switch_info
379
380 static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
381 {
382         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
383         struct ad198x_spec *ad = codec->spec;
384
385         down(&ad->amp_mutex);
386         snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
387         up(&ad->amp_mutex);
388         return 0;
389 }
390
391 static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
392 {
393         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
394         struct ad198x_spec *ad = codec->spec;
395         int i, change = 0;
396
397         down(&ad->amp_mutex);
398         for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
399                 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
400                 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
401         }
402         kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
403         up(&ad->amp_mutex);
404         return change;
405 }
406
407 /*
408  * mixers
409  */
410 static snd_kcontrol_new_t ad1986a_mixers[] = {
411         {
412                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
413                 .name = "PCM Playback Volume",
414                 .info = ad1986a_pcm_amp_vol_info,
415                 .get = ad1986a_pcm_amp_vol_get,
416                 .put = ad1986a_pcm_amp_vol_put,
417                 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
418         },
419         {
420                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
421                 .name = "PCM Playback Switch",
422                 .info = ad1986a_pcm_amp_sw_info,
423                 .get = ad1986a_pcm_amp_sw_get,
424                 .put = ad1986a_pcm_amp_sw_put,
425                 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
426         },
427         HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
428         HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
429         HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
430         HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
431         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
432         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
433         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
434         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
435         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
436         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
437         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
438         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
439         HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
440         HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
441         HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
442         HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
443         HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
444         HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
445         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
446         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
447         HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
448         HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
449         HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
450         HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
451         {
452                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
453                 .name = "Capture Source",
454                 .info = ad198x_mux_enum_info,
455                 .get = ad198x_mux_enum_get,
456                 .put = ad198x_mux_enum_put,
457         },
458         HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
459         { } /* end */
460 };
461
462 /*
463  * initialization verbs
464  */
465 static struct hda_verb ad1986a_init_verbs[] = {
466         /* Front, Surround, CLFE DAC; mute as default */
467         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
468         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
469         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
470         /* Downmix - off */
471         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
472         /* HP, Line-Out, Surround, CLFE selectors */
473         {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
474         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
475         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
476         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
477         /* Mono selector */
478         {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
479         /* Mic selector: Mic 1/2 pin */
480         {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
481         /* Line-in selector: Line-in */
482         {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
483         /* Mic 1/2 swap */
484         {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
485         /* Record selector: mic */
486         {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
487         /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
488         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
489         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
490         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
491         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
492         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
493         /* PC beep */
494         {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
495         /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
496         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
497         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
498         {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
499         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
500         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
501         /* HP Pin */
502         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
503         /* Front, Surround, CLFE Pins */
504         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
505         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
506         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
507         /* Mono Pin */
508         {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
509         /* Mic Pin */
510         {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
511         /* Line, Aux, CD, Beep-In Pin */
512         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
513         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
514         {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
515         {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
516         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
517         { } /* end */
518 };
519
520
521 static int patch_ad1986a(struct hda_codec *codec)
522 {
523         struct ad198x_spec *spec;
524
525         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
526         if (spec == NULL)
527                 return -ENOMEM;
528
529         init_MUTEX(&spec->amp_mutex);
530         codec->spec = spec;
531
532         spec->multiout.max_channels = 6;
533         spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
534         spec->multiout.dac_nids = ad1986a_dac_nids;
535         spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
536         spec->num_adc_nids = 1;
537         spec->adc_nids = ad1986a_adc_nids;
538         spec->input_mux = &ad1986a_capture_source;
539         spec->num_mixers = 1;
540         spec->mixers[0] = ad1986a_mixers;
541         spec->num_init_verbs = 1;
542         spec->init_verbs[0] = ad1986a_init_verbs;
543
544         codec->patch_ops = ad198x_patch_ops;
545
546         return 0;
547 }
548
549 /*
550  * AD1983 specific
551  */
552
553 #define AD1983_SPDIF_OUT        0x02
554 #define AD1983_DAC              0x03
555 #define AD1983_ADC              0x04
556
557 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
558 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
559
560 static struct hda_input_mux ad1983_capture_source = {
561         .num_items = 4,
562         .items = {
563                 { "Mic", 0x0 },
564                 { "Line", 0x1 },
565                 { "Mix", 0x2 },
566                 { "Mix Mono", 0x3 },
567         },
568 };
569
570 /*
571  * SPDIF playback route
572  */
573 static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
574 {
575         static char *texts[] = { "PCM", "ADC" };
576
577         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
578         uinfo->count = 1;
579         uinfo->value.enumerated.items = 2;
580         if (uinfo->value.enumerated.item > 1)
581                 uinfo->value.enumerated.item = 1;
582         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
583         return 0;
584 }
585
586 static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
587 {
588         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
589         struct ad198x_spec *spec = codec->spec;
590
591         ucontrol->value.enumerated.item[0] = spec->spdif_route;
592         return 0;
593 }
594
595 static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
596 {
597         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
598         struct ad198x_spec *spec = codec->spec;
599
600         if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
601                 spec->spdif_route = ucontrol->value.enumerated.item[0];
602                 snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
603                                     AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
604                 return 1;
605         }
606         return 0;
607 }
608
609 static snd_kcontrol_new_t ad1983_mixers[] = {
610         HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
611         HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
612         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
613         HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
614         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
615         HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
616         HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
617         HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
618         HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
619         HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
620         HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
621         HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
622         HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
623         HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
624         HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
625         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
626         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
627         {
628                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
629                 .name = "Capture Source",
630                 .info = ad198x_mux_enum_info,
631                 .get = ad198x_mux_enum_get,
632                 .put = ad198x_mux_enum_put,
633         },
634         {
635                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
636                 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
637                 .info = ad1983_spdif_route_info,
638                 .get = ad1983_spdif_route_get,
639                 .put = ad1983_spdif_route_put,
640         },
641         { } /* end */
642 };
643
644 static struct hda_verb ad1983_init_verbs[] = {
645         /* Front, HP, Mono; mute as default */
646         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
647         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
648         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
649         /* Beep, PCM, Mic, Line-In: mute */
650         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
651         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
652         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
653         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
654         /* Front, HP selectors; from Mix */
655         {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
656         {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
657         /* Mono selector; from Mix */
658         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
659         /* Mic selector; Mic */
660         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
661         /* Line-in selector: Line-in */
662         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
663         /* Mic boost: 0dB */
664         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
665         /* Record selector: mic */
666         {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
667         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
668         /* SPDIF route: PCM */
669         {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
670         /* Front Pin */
671         {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
672         /* HP Pin */
673         {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
674         /* Mono Pin */
675         {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
676         /* Mic Pin */
677         {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
678         /* Line Pin */
679         {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
680         { } /* end */
681 };
682
683
684 static int patch_ad1983(struct hda_codec *codec)
685 {
686         struct ad198x_spec *spec;
687
688         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
689         if (spec == NULL)
690                 return -ENOMEM;
691
692         init_MUTEX(&spec->amp_mutex);
693         codec->spec = spec;
694
695         spec->multiout.max_channels = 2;
696         spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
697         spec->multiout.dac_nids = ad1983_dac_nids;
698         spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
699         spec->num_adc_nids = 1;
700         spec->adc_nids = ad1983_adc_nids;
701         spec->input_mux = &ad1983_capture_source;
702         spec->num_mixers = 1;
703         spec->mixers[0] = ad1983_mixers;
704         spec->num_init_verbs = 1;
705         spec->init_verbs[0] = ad1983_init_verbs;
706         spec->spdif_route = 0;
707
708         codec->patch_ops = ad198x_patch_ops;
709
710         return 0;
711 }
712
713
714 /*
715  * AD1981 HD specific
716  */
717
718 #define AD1981_SPDIF_OUT        0x02
719 #define AD1981_DAC              0x03
720 #define AD1981_ADC              0x04
721
722 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
723 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
724
725 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
726 static struct hda_input_mux ad1981_capture_source = {
727         .num_items = 7,
728         .items = {
729                 { "Front Mic", 0x0 },
730                 { "Line", 0x1 },
731                 { "Mix", 0x2 },
732                 { "Mix Mono", 0x3 },
733                 { "CD", 0x4 },
734                 { "Mic", 0x6 },
735                 { "Aux", 0x7 },
736         },
737 };
738
739 static snd_kcontrol_new_t ad1981_mixers[] = {
740         HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
741         HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
742         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
743         HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
744         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
745         HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
746         HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
747         HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
748         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
749         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
750         HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
751         HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
752         HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
753         HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
754         HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
755         HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
756         HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
757         HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
758         HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
759         HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
760         HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
761         HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
762         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
763         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
764         {
765                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
766                 .name = "Capture Source",
767                 .info = ad198x_mux_enum_info,
768                 .get = ad198x_mux_enum_get,
769                 .put = ad198x_mux_enum_put,
770         },
771         /* identical with AD1983 */
772         {
773                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
774                 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
775                 .info = ad1983_spdif_route_info,
776                 .get = ad1983_spdif_route_get,
777                 .put = ad1983_spdif_route_put,
778         },
779         { } /* end */
780 };
781
782 static struct hda_verb ad1981_init_verbs[] = {
783         /* Front, HP, Mono; mute as default */
784         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
785         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
786         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
787         /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
788         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
789         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
790         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
791         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
792         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
793         {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
794         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
795         /* Front, HP selectors; from Mix */
796         {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
797         {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
798         /* Mono selector; from Mix */
799         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
800         /* Mic Mixer; select Front Mic */
801         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
802         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
803         /* Mic boost: 0dB */
804         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
805         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
806         /* Record selector: Front mic */
807         {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
808         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
809         /* SPDIF route: PCM */
810         {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
811         /* Front Pin */
812         {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
813         /* HP Pin */
814         {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
815         /* Mono Pin */
816         {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
817         /* Front & Rear Mic Pins */
818         {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
819         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
820         /* Line Pin */
821         {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
822         /* Digital Beep */
823         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
824         /* Line-Out as Input: disabled */
825         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
826         { } /* end */
827 };
828
829 static int patch_ad1981(struct hda_codec *codec)
830 {
831         struct ad198x_spec *spec;
832
833         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
834         if (spec == NULL)
835                 return -ENOMEM;
836
837         init_MUTEX(&spec->amp_mutex);
838         codec->spec = spec;
839
840         spec->multiout.max_channels = 2;
841         spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
842         spec->multiout.dac_nids = ad1981_dac_nids;
843         spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
844         spec->num_adc_nids = 1;
845         spec->adc_nids = ad1981_adc_nids;
846         spec->input_mux = &ad1981_capture_source;
847         spec->num_mixers = 1;
848         spec->mixers[0] = ad1981_mixers;
849         spec->num_init_verbs = 1;
850         spec->init_verbs[0] = ad1981_init_verbs;
851         spec->spdif_route = 0;
852
853         codec->patch_ops = ad198x_patch_ops;
854
855         return 0;
856 }
857
858
859 /*
860  * patch entries
861  */
862 struct hda_codec_preset snd_hda_preset_analog[] = {
863         { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
864         { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
865         { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
866         {} /* terminator */
867 };