Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/hda/patch_analog.c
10817 views
1
/*
2
* HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
3
* AD1986A, AD1988
4
*
5
* Copyright (c) 2005-2007 Takashi Iwai <[email protected]>
6
*
7
* This driver is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This driver is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
22
#include <linux/init.h>
23
#include <linux/delay.h>
24
#include <linux/slab.h>
25
#include <linux/pci.h>
26
27
#include <sound/core.h>
28
#include "hda_codec.h"
29
#include "hda_local.h"
30
#include "hda_beep.h"
31
32
struct ad198x_spec {
33
const struct snd_kcontrol_new *mixers[6];
34
int num_mixers;
35
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
36
const struct hda_verb *init_verbs[6]; /* initialization verbs
37
* don't forget NULL termination!
38
*/
39
unsigned int num_init_verbs;
40
41
/* playback */
42
struct hda_multi_out multiout; /* playback set-up
43
* max_channels, dacs must be set
44
* dig_out_nid and hp_nid are optional
45
*/
46
unsigned int cur_eapd;
47
unsigned int need_dac_fix;
48
49
const hda_nid_t *alt_dac_nid;
50
const struct hda_pcm_stream *stream_analog_alt_playback;
51
52
/* capture */
53
unsigned int num_adc_nids;
54
const hda_nid_t *adc_nids;
55
hda_nid_t dig_in_nid; /* digital-in NID; optional */
56
57
/* capture source */
58
const struct hda_input_mux *input_mux;
59
const hda_nid_t *capsrc_nids;
60
unsigned int cur_mux[3];
61
62
/* channel model */
63
const struct hda_channel_mode *channel_mode;
64
int num_channel_mode;
65
66
/* PCM information */
67
struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
68
69
unsigned int spdif_route;
70
71
/* dynamic controls, init_verbs and input_mux */
72
struct auto_pin_cfg autocfg;
73
struct snd_array kctls;
74
struct hda_input_mux private_imux;
75
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
76
77
unsigned int jack_present: 1;
78
unsigned int inv_jack_detect: 1;/* inverted jack-detection */
79
unsigned int inv_eapd: 1; /* inverted EAPD implementation */
80
unsigned int analog_beep: 1; /* analog beep input present */
81
82
#ifdef CONFIG_SND_HDA_POWER_SAVE
83
struct hda_loopback_check loopback;
84
#endif
85
/* for virtual master */
86
hda_nid_t vmaster_nid;
87
const char * const *slave_vols;
88
const char * const *slave_sws;
89
};
90
91
/*
92
* input MUX handling (common part)
93
*/
94
static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
95
{
96
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
97
struct ad198x_spec *spec = codec->spec;
98
99
return snd_hda_input_mux_info(spec->input_mux, uinfo);
100
}
101
102
static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
103
{
104
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
105
struct ad198x_spec *spec = codec->spec;
106
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
107
108
ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
109
return 0;
110
}
111
112
static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
113
{
114
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
115
struct ad198x_spec *spec = codec->spec;
116
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
117
118
return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
119
spec->capsrc_nids[adc_idx],
120
&spec->cur_mux[adc_idx]);
121
}
122
123
/*
124
* initialization (common callbacks)
125
*/
126
static int ad198x_init(struct hda_codec *codec)
127
{
128
struct ad198x_spec *spec = codec->spec;
129
int i;
130
131
for (i = 0; i < spec->num_init_verbs; i++)
132
snd_hda_sequence_write(codec, spec->init_verbs[i]);
133
return 0;
134
}
135
136
static const char * const ad_slave_vols[] = {
137
"Front Playback Volume",
138
"Surround Playback Volume",
139
"Center Playback Volume",
140
"LFE Playback Volume",
141
"Side Playback Volume",
142
"Headphone Playback Volume",
143
"Mono Playback Volume",
144
"Speaker Playback Volume",
145
"IEC958 Playback Volume",
146
NULL
147
};
148
149
static const char * const ad_slave_sws[] = {
150
"Front Playback Switch",
151
"Surround Playback Switch",
152
"Center Playback Switch",
153
"LFE Playback Switch",
154
"Side Playback Switch",
155
"Headphone Playback Switch",
156
"Mono Playback Switch",
157
"Speaker Playback Switch",
158
"IEC958 Playback Switch",
159
NULL
160
};
161
162
static const char * const ad1988_6stack_fp_slave_vols[] = {
163
"Front Playback Volume",
164
"Surround Playback Volume",
165
"Center Playback Volume",
166
"LFE Playback Volume",
167
"Side Playback Volume",
168
"IEC958 Playback Volume",
169
NULL
170
};
171
172
static const char * const ad1988_6stack_fp_slave_sws[] = {
173
"Front Playback Switch",
174
"Surround Playback Switch",
175
"Center Playback Switch",
176
"LFE Playback Switch",
177
"Side Playback Switch",
178
"IEC958 Playback Switch",
179
NULL
180
};
181
static void ad198x_free_kctls(struct hda_codec *codec);
182
183
#ifdef CONFIG_SND_HDA_INPUT_BEEP
184
/* additional beep mixers; the actual parameters are overwritten at build */
185
static const struct snd_kcontrol_new ad_beep_mixer[] = {
186
HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
187
HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
188
{ } /* end */
189
};
190
191
static const struct snd_kcontrol_new ad_beep2_mixer[] = {
192
HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
193
HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
194
{ } /* end */
195
};
196
197
#define set_beep_amp(spec, nid, idx, dir) \
198
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
199
#else
200
#define set_beep_amp(spec, nid, idx, dir) /* NOP */
201
#endif
202
203
static int ad198x_build_controls(struct hda_codec *codec)
204
{
205
struct ad198x_spec *spec = codec->spec;
206
struct snd_kcontrol *kctl;
207
unsigned int i;
208
int err;
209
210
for (i = 0; i < spec->num_mixers; i++) {
211
err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
212
if (err < 0)
213
return err;
214
}
215
if (spec->multiout.dig_out_nid) {
216
err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
217
if (err < 0)
218
return err;
219
err = snd_hda_create_spdif_share_sw(codec,
220
&spec->multiout);
221
if (err < 0)
222
return err;
223
spec->multiout.share_spdif = 1;
224
}
225
if (spec->dig_in_nid) {
226
err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
227
if (err < 0)
228
return err;
229
}
230
231
/* create beep controls if needed */
232
#ifdef CONFIG_SND_HDA_INPUT_BEEP
233
if (spec->beep_amp) {
234
const struct snd_kcontrol_new *knew;
235
knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
236
for ( ; knew->name; knew++) {
237
struct snd_kcontrol *kctl;
238
kctl = snd_ctl_new1(knew, codec);
239
if (!kctl)
240
return -ENOMEM;
241
kctl->private_value = spec->beep_amp;
242
err = snd_hda_ctl_add(codec, 0, kctl);
243
if (err < 0)
244
return err;
245
}
246
}
247
#endif
248
249
/* if we have no master control, let's create it */
250
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
251
unsigned int vmaster_tlv[4];
252
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
253
HDA_OUTPUT, vmaster_tlv);
254
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
255
vmaster_tlv,
256
(spec->slave_vols ?
257
spec->slave_vols : ad_slave_vols));
258
if (err < 0)
259
return err;
260
}
261
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
262
err = snd_hda_add_vmaster(codec, "Master Playback Switch",
263
NULL,
264
(spec->slave_sws ?
265
spec->slave_sws : ad_slave_sws));
266
if (err < 0)
267
return err;
268
}
269
270
ad198x_free_kctls(codec); /* no longer needed */
271
272
/* assign Capture Source enums to NID */
273
kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
274
if (!kctl)
275
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
276
for (i = 0; kctl && i < kctl->count; i++) {
277
err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
278
if (err < 0)
279
return err;
280
}
281
282
/* assign IEC958 enums to NID */
283
kctl = snd_hda_find_mixer_ctl(codec,
284
SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
285
if (kctl) {
286
err = snd_hda_add_nid(codec, kctl, 0,
287
spec->multiout.dig_out_nid);
288
if (err < 0)
289
return err;
290
}
291
292
return 0;
293
}
294
295
#ifdef CONFIG_SND_HDA_POWER_SAVE
296
static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
297
{
298
struct ad198x_spec *spec = codec->spec;
299
return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
300
}
301
#endif
302
303
/*
304
* Analog playback callbacks
305
*/
306
static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
307
struct hda_codec *codec,
308
struct snd_pcm_substream *substream)
309
{
310
struct ad198x_spec *spec = codec->spec;
311
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
312
hinfo);
313
}
314
315
static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
316
struct hda_codec *codec,
317
unsigned int stream_tag,
318
unsigned int format,
319
struct snd_pcm_substream *substream)
320
{
321
struct ad198x_spec *spec = codec->spec;
322
return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
323
format, substream);
324
}
325
326
static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
327
struct hda_codec *codec,
328
struct snd_pcm_substream *substream)
329
{
330
struct ad198x_spec *spec = codec->spec;
331
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
332
}
333
334
static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
335
.substreams = 1,
336
.channels_min = 2,
337
.channels_max = 2,
338
/* NID is set in ad198x_build_pcms */
339
};
340
341
/*
342
* Digital out
343
*/
344
static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
345
struct hda_codec *codec,
346
struct snd_pcm_substream *substream)
347
{
348
struct ad198x_spec *spec = codec->spec;
349
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
350
}
351
352
static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
353
struct hda_codec *codec,
354
struct snd_pcm_substream *substream)
355
{
356
struct ad198x_spec *spec = codec->spec;
357
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
358
}
359
360
static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
361
struct hda_codec *codec,
362
unsigned int stream_tag,
363
unsigned int format,
364
struct snd_pcm_substream *substream)
365
{
366
struct ad198x_spec *spec = codec->spec;
367
return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
368
format, substream);
369
}
370
371
static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
372
struct hda_codec *codec,
373
struct snd_pcm_substream *substream)
374
{
375
struct ad198x_spec *spec = codec->spec;
376
return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
377
}
378
379
/*
380
* Analog capture
381
*/
382
static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
383
struct hda_codec *codec,
384
unsigned int stream_tag,
385
unsigned int format,
386
struct snd_pcm_substream *substream)
387
{
388
struct ad198x_spec *spec = codec->spec;
389
snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
390
stream_tag, 0, format);
391
return 0;
392
}
393
394
static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
395
struct hda_codec *codec,
396
struct snd_pcm_substream *substream)
397
{
398
struct ad198x_spec *spec = codec->spec;
399
snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
400
return 0;
401
}
402
403
404
/*
405
*/
406
static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
407
.substreams = 1,
408
.channels_min = 2,
409
.channels_max = 6, /* changed later */
410
.nid = 0, /* fill later */
411
.ops = {
412
.open = ad198x_playback_pcm_open,
413
.prepare = ad198x_playback_pcm_prepare,
414
.cleanup = ad198x_playback_pcm_cleanup
415
},
416
};
417
418
static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
419
.substreams = 1,
420
.channels_min = 2,
421
.channels_max = 2,
422
.nid = 0, /* fill later */
423
.ops = {
424
.prepare = ad198x_capture_pcm_prepare,
425
.cleanup = ad198x_capture_pcm_cleanup
426
},
427
};
428
429
static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
430
.substreams = 1,
431
.channels_min = 2,
432
.channels_max = 2,
433
.nid = 0, /* fill later */
434
.ops = {
435
.open = ad198x_dig_playback_pcm_open,
436
.close = ad198x_dig_playback_pcm_close,
437
.prepare = ad198x_dig_playback_pcm_prepare,
438
.cleanup = ad198x_dig_playback_pcm_cleanup
439
},
440
};
441
442
static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
443
.substreams = 1,
444
.channels_min = 2,
445
.channels_max = 2,
446
/* NID is set in alc_build_pcms */
447
};
448
449
static int ad198x_build_pcms(struct hda_codec *codec)
450
{
451
struct ad198x_spec *spec = codec->spec;
452
struct hda_pcm *info = spec->pcm_rec;
453
454
codec->num_pcms = 1;
455
codec->pcm_info = info;
456
457
info->name = "AD198x Analog";
458
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
459
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
460
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
461
info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
462
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
463
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
464
465
if (spec->multiout.dig_out_nid) {
466
info++;
467
codec->num_pcms++;
468
info->name = "AD198x Digital";
469
info->pcm_type = HDA_PCM_TYPE_SPDIF;
470
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
471
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
472
if (spec->dig_in_nid) {
473
info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
474
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
475
}
476
}
477
478
if (spec->alt_dac_nid && spec->stream_analog_alt_playback) {
479
codec->num_pcms++;
480
info = spec->pcm_rec + 2;
481
info->name = "AD198x Headphone";
482
info->pcm_type = HDA_PCM_TYPE_AUDIO;
483
info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
484
*spec->stream_analog_alt_playback;
485
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
486
spec->alt_dac_nid[0];
487
}
488
489
return 0;
490
}
491
492
static void ad198x_free_kctls(struct hda_codec *codec)
493
{
494
struct ad198x_spec *spec = codec->spec;
495
496
if (spec->kctls.list) {
497
struct snd_kcontrol_new *kctl = spec->kctls.list;
498
int i;
499
for (i = 0; i < spec->kctls.used; i++)
500
kfree(kctl[i].name);
501
}
502
snd_array_free(&spec->kctls);
503
}
504
505
static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
506
hda_nid_t hp)
507
{
508
struct ad198x_spec *spec = codec->spec;
509
if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
510
snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
511
!spec->inv_eapd ? 0x00 : 0x02);
512
if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
513
snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
514
!spec->inv_eapd ? 0x00 : 0x02);
515
}
516
517
static void ad198x_power_eapd(struct hda_codec *codec)
518
{
519
/* We currently only handle front, HP */
520
switch (codec->vendor_id) {
521
case 0x11d41882:
522
case 0x11d4882a:
523
case 0x11d41884:
524
case 0x11d41984:
525
case 0x11d41883:
526
case 0x11d4184a:
527
case 0x11d4194a:
528
case 0x11d4194b:
529
case 0x11d41988:
530
case 0x11d4198b:
531
case 0x11d4989a:
532
case 0x11d4989b:
533
ad198x_power_eapd_write(codec, 0x12, 0x11);
534
break;
535
case 0x11d41981:
536
case 0x11d41983:
537
ad198x_power_eapd_write(codec, 0x05, 0x06);
538
break;
539
case 0x11d41986:
540
ad198x_power_eapd_write(codec, 0x1b, 0x1a);
541
break;
542
}
543
}
544
545
static void ad198x_shutup(struct hda_codec *codec)
546
{
547
snd_hda_shutup_pins(codec);
548
ad198x_power_eapd(codec);
549
}
550
551
static void ad198x_free(struct hda_codec *codec)
552
{
553
struct ad198x_spec *spec = codec->spec;
554
555
if (!spec)
556
return;
557
558
ad198x_shutup(codec);
559
ad198x_free_kctls(codec);
560
kfree(spec);
561
snd_hda_detach_beep_device(codec);
562
}
563
564
#ifdef SND_HDA_NEEDS_RESUME
565
static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
566
{
567
ad198x_shutup(codec);
568
return 0;
569
}
570
#endif
571
572
static const struct hda_codec_ops ad198x_patch_ops = {
573
.build_controls = ad198x_build_controls,
574
.build_pcms = ad198x_build_pcms,
575
.init = ad198x_init,
576
.free = ad198x_free,
577
#ifdef CONFIG_SND_HDA_POWER_SAVE
578
.check_power_status = ad198x_check_power_status,
579
#endif
580
#ifdef SND_HDA_NEEDS_RESUME
581
.suspend = ad198x_suspend,
582
#endif
583
.reboot_notify = ad198x_shutup,
584
};
585
586
587
/*
588
* EAPD control
589
* the private value = nid
590
*/
591
#define ad198x_eapd_info snd_ctl_boolean_mono_info
592
593
static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
594
struct snd_ctl_elem_value *ucontrol)
595
{
596
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
597
struct ad198x_spec *spec = codec->spec;
598
if (spec->inv_eapd)
599
ucontrol->value.integer.value[0] = ! spec->cur_eapd;
600
else
601
ucontrol->value.integer.value[0] = spec->cur_eapd;
602
return 0;
603
}
604
605
static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
606
struct snd_ctl_elem_value *ucontrol)
607
{
608
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
609
struct ad198x_spec *spec = codec->spec;
610
hda_nid_t nid = kcontrol->private_value & 0xff;
611
unsigned int eapd;
612
eapd = !!ucontrol->value.integer.value[0];
613
if (spec->inv_eapd)
614
eapd = !eapd;
615
if (eapd == spec->cur_eapd)
616
return 0;
617
spec->cur_eapd = eapd;
618
snd_hda_codec_write_cache(codec, nid,
619
0, AC_VERB_SET_EAPD_BTLENABLE,
620
eapd ? 0x02 : 0x00);
621
return 1;
622
}
623
624
static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
625
struct snd_ctl_elem_info *uinfo);
626
static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
627
struct snd_ctl_elem_value *ucontrol);
628
static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
629
struct snd_ctl_elem_value *ucontrol);
630
631
632
/*
633
* AD1986A specific
634
*/
635
636
#define AD1986A_SPDIF_OUT 0x02
637
#define AD1986A_FRONT_DAC 0x03
638
#define AD1986A_SURR_DAC 0x04
639
#define AD1986A_CLFE_DAC 0x05
640
#define AD1986A_ADC 0x06
641
642
static const hda_nid_t ad1986a_dac_nids[3] = {
643
AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
644
};
645
static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
646
static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
647
648
static const struct hda_input_mux ad1986a_capture_source = {
649
.num_items = 7,
650
.items = {
651
{ "Mic", 0x0 },
652
{ "CD", 0x1 },
653
{ "Aux", 0x3 },
654
{ "Line", 0x4 },
655
{ "Mix", 0x5 },
656
{ "Mono", 0x6 },
657
{ "Phone", 0x7 },
658
},
659
};
660
661
662
static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
663
.ops = &snd_hda_bind_vol,
664
.values = {
665
HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
666
HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
667
HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
668
0
669
},
670
};
671
672
static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
673
.ops = &snd_hda_bind_sw,
674
.values = {
675
HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
676
HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
677
HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
678
0
679
},
680
};
681
682
/*
683
* mixers
684
*/
685
static const struct snd_kcontrol_new ad1986a_mixers[] = {
686
/*
687
* bind volumes/mutes of 3 DACs as a single PCM control for simplicity
688
*/
689
HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
690
HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
691
HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
692
HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
693
HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
694
HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
695
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
696
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
697
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
698
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
699
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
700
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
701
HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
702
HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
703
HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
704
HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
705
HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
706
HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
707
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
708
HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
709
HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
710
HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
711
HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
712
HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
713
HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
714
{
715
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
716
.name = "Capture Source",
717
.info = ad198x_mux_enum_info,
718
.get = ad198x_mux_enum_get,
719
.put = ad198x_mux_enum_put,
720
},
721
HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
722
{ } /* end */
723
};
724
725
/* additional mixers for 3stack mode */
726
static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
727
{
728
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
729
.name = "Channel Mode",
730
.info = ad198x_ch_mode_info,
731
.get = ad198x_ch_mode_get,
732
.put = ad198x_ch_mode_put,
733
},
734
{ } /* end */
735
};
736
737
/* laptop model - 2ch only */
738
static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
739
740
/* master controls both pins 0x1a and 0x1b */
741
static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
742
.ops = &snd_hda_bind_vol,
743
.values = {
744
HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
745
HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
746
0,
747
},
748
};
749
750
static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
751
.ops = &snd_hda_bind_sw,
752
.values = {
753
HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
754
HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
755
0,
756
},
757
};
758
759
static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
760
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
761
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
762
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
763
HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
764
HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
765
HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
766
HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
767
HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
768
HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
769
HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
770
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
771
HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
772
HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
773
/*
774
HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
775
HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
776
HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
777
HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
778
{
779
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
780
.name = "Capture Source",
781
.info = ad198x_mux_enum_info,
782
.get = ad198x_mux_enum_get,
783
.put = ad198x_mux_enum_put,
784
},
785
{ } /* end */
786
};
787
788
/* laptop-eapd model - 2ch only */
789
790
static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
791
.num_items = 3,
792
.items = {
793
{ "Mic", 0x0 },
794
{ "Internal Mic", 0x4 },
795
{ "Mix", 0x5 },
796
},
797
};
798
799
static const struct hda_input_mux ad1986a_automic_capture_source = {
800
.num_items = 2,
801
.items = {
802
{ "Mic", 0x0 },
803
{ "Mix", 0x5 },
804
},
805
};
806
807
static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
808
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
809
HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
810
{ } /* end */
811
};
812
813
static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
814
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
815
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
816
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
817
HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
818
HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
819
HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
820
HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
821
{
822
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
823
.name = "Capture Source",
824
.info = ad198x_mux_enum_info,
825
.get = ad198x_mux_enum_get,
826
.put = ad198x_mux_enum_put,
827
},
828
{
829
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
830
.name = "External Amplifier",
831
.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
832
.info = ad198x_eapd_info,
833
.get = ad198x_eapd_get,
834
.put = ad198x_eapd_put,
835
.private_value = 0x1b, /* port-D */
836
},
837
{ } /* end */
838
};
839
840
static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
841
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
842
HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
843
{ } /* end */
844
};
845
846
/* re-connect the mic boost input according to the jack sensing */
847
static void ad1986a_automic(struct hda_codec *codec)
848
{
849
unsigned int present;
850
present = snd_hda_jack_detect(codec, 0x1f);
851
/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
852
snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
853
present ? 0 : 2);
854
}
855
856
#define AD1986A_MIC_EVENT 0x36
857
858
static void ad1986a_automic_unsol_event(struct hda_codec *codec,
859
unsigned int res)
860
{
861
if ((res >> 26) != AD1986A_MIC_EVENT)
862
return;
863
ad1986a_automic(codec);
864
}
865
866
static int ad1986a_automic_init(struct hda_codec *codec)
867
{
868
ad198x_init(codec);
869
ad1986a_automic(codec);
870
return 0;
871
}
872
873
/* laptop-automute - 2ch only */
874
875
static void ad1986a_update_hp(struct hda_codec *codec)
876
{
877
struct ad198x_spec *spec = codec->spec;
878
unsigned int mute;
879
880
if (spec->jack_present)
881
mute = HDA_AMP_MUTE; /* mute internal speaker */
882
else
883
/* unmute internal speaker if necessary */
884
mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
885
snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
886
HDA_AMP_MUTE, mute);
887
}
888
889
static void ad1986a_hp_automute(struct hda_codec *codec)
890
{
891
struct ad198x_spec *spec = codec->spec;
892
893
spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
894
if (spec->inv_jack_detect)
895
spec->jack_present = !spec->jack_present;
896
ad1986a_update_hp(codec);
897
}
898
899
#define AD1986A_HP_EVENT 0x37
900
901
static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
902
{
903
if ((res >> 26) != AD1986A_HP_EVENT)
904
return;
905
ad1986a_hp_automute(codec);
906
}
907
908
static int ad1986a_hp_init(struct hda_codec *codec)
909
{
910
ad198x_init(codec);
911
ad1986a_hp_automute(codec);
912
return 0;
913
}
914
915
/* bind hp and internal speaker mute (with plug check) */
916
static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
917
struct snd_ctl_elem_value *ucontrol)
918
{
919
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
920
long *valp = ucontrol->value.integer.value;
921
int change;
922
923
change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
924
HDA_AMP_MUTE,
925
valp[0] ? 0 : HDA_AMP_MUTE);
926
change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
927
HDA_AMP_MUTE,
928
valp[1] ? 0 : HDA_AMP_MUTE);
929
if (change)
930
ad1986a_update_hp(codec);
931
return change;
932
}
933
934
static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
935
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
936
{
937
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
938
.name = "Master Playback Switch",
939
.subdevice = HDA_SUBDEV_AMP_FLAG,
940
.info = snd_hda_mixer_amp_switch_info,
941
.get = snd_hda_mixer_amp_switch_get,
942
.put = ad1986a_hp_master_sw_put,
943
.private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
944
},
945
{ } /* end */
946
};
947
948
949
/*
950
* initialization verbs
951
*/
952
static const struct hda_verb ad1986a_init_verbs[] = {
953
/* Front, Surround, CLFE DAC; mute as default */
954
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
955
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
956
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
957
/* Downmix - off */
958
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
959
/* HP, Line-Out, Surround, CLFE selectors */
960
{0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
961
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
962
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
963
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
964
/* Mono selector */
965
{0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
966
/* Mic selector: Mic 1/2 pin */
967
{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
968
/* Line-in selector: Line-in */
969
{0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
970
/* Mic 1/2 swap */
971
{0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
972
/* Record selector: mic */
973
{0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
974
/* Mic, Phone, CD, Aux, Line-In amp; mute as default */
975
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
976
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
977
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
978
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
979
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
980
/* PC beep */
981
{0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
982
/* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
983
{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
984
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
985
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
986
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
987
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
988
/* HP Pin */
989
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
990
/* Front, Surround, CLFE Pins */
991
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
992
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
993
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
994
/* Mono Pin */
995
{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
996
/* Mic Pin */
997
{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
998
/* Line, Aux, CD, Beep-In Pin */
999
{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1000
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1001
{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1002
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1003
{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1004
{ } /* end */
1005
};
1006
1007
static const struct hda_verb ad1986a_ch2_init[] = {
1008
/* Surround out -> Line In */
1009
{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1010
/* Line-in selectors */
1011
{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
1012
/* CLFE -> Mic in */
1013
{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1014
/* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1015
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1016
{ } /* end */
1017
};
1018
1019
static const struct hda_verb ad1986a_ch4_init[] = {
1020
/* Surround out -> Surround */
1021
{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1022
{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1023
/* CLFE -> Mic in */
1024
{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1025
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1026
{ } /* end */
1027
};
1028
1029
static const struct hda_verb ad1986a_ch6_init[] = {
1030
/* Surround out -> Surround out */
1031
{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1032
{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1033
/* CLFE -> CLFE */
1034
{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1035
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1036
{ } /* end */
1037
};
1038
1039
static const struct hda_channel_mode ad1986a_modes[3] = {
1040
{ 2, ad1986a_ch2_init },
1041
{ 4, ad1986a_ch4_init },
1042
{ 6, ad1986a_ch6_init },
1043
};
1044
1045
/* eapd initialization */
1046
static const struct hda_verb ad1986a_eapd_init_verbs[] = {
1047
{0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1048
{}
1049
};
1050
1051
static const struct hda_verb ad1986a_automic_verbs[] = {
1052
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1053
{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1054
/*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1055
{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1056
{0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1057
{}
1058
};
1059
1060
/* Ultra initialization */
1061
static const struct hda_verb ad1986a_ultra_init[] = {
1062
/* eapd initialization */
1063
{ 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1064
/* CLFE -> Mic in */
1065
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1066
{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1067
{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1068
{ } /* end */
1069
};
1070
1071
/* pin sensing on HP jack */
1072
static const struct hda_verb ad1986a_hp_init_verbs[] = {
1073
{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1074
{}
1075
};
1076
1077
static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1078
unsigned int res)
1079
{
1080
switch (res >> 26) {
1081
case AD1986A_HP_EVENT:
1082
ad1986a_hp_automute(codec);
1083
break;
1084
case AD1986A_MIC_EVENT:
1085
ad1986a_automic(codec);
1086
break;
1087
}
1088
}
1089
1090
static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1091
{
1092
ad198x_init(codec);
1093
ad1986a_hp_automute(codec);
1094
ad1986a_automic(codec);
1095
return 0;
1096
}
1097
1098
1099
/* models */
1100
enum {
1101
AD1986A_6STACK,
1102
AD1986A_3STACK,
1103
AD1986A_LAPTOP,
1104
AD1986A_LAPTOP_EAPD,
1105
AD1986A_LAPTOP_AUTOMUTE,
1106
AD1986A_ULTRA,
1107
AD1986A_SAMSUNG,
1108
AD1986A_SAMSUNG_P50,
1109
AD1986A_MODELS
1110
};
1111
1112
static const char * const ad1986a_models[AD1986A_MODELS] = {
1113
[AD1986A_6STACK] = "6stack",
1114
[AD1986A_3STACK] = "3stack",
1115
[AD1986A_LAPTOP] = "laptop",
1116
[AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1117
[AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1118
[AD1986A_ULTRA] = "ultra",
1119
[AD1986A_SAMSUNG] = "samsung",
1120
[AD1986A_SAMSUNG_P50] = "samsung-p50",
1121
};
1122
1123
static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1124
SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1125
SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1126
SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1127
SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1128
SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1129
SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1130
SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1131
SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1132
SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1133
SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1134
SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1135
SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1136
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1137
SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1138
SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1139
SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1140
SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1141
SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1142
SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1143
SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1144
SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1145
SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1146
SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1147
SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1148
SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1149
SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1150
SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1151
{}
1152
};
1153
1154
#ifdef CONFIG_SND_HDA_POWER_SAVE
1155
static const struct hda_amp_list ad1986a_loopbacks[] = {
1156
{ 0x13, HDA_OUTPUT, 0 }, /* Mic */
1157
{ 0x14, HDA_OUTPUT, 0 }, /* Phone */
1158
{ 0x15, HDA_OUTPUT, 0 }, /* CD */
1159
{ 0x16, HDA_OUTPUT, 0 }, /* Aux */
1160
{ 0x17, HDA_OUTPUT, 0 }, /* Line */
1161
{ } /* end */
1162
};
1163
#endif
1164
1165
static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1166
{
1167
unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1168
return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1169
}
1170
1171
static int patch_ad1986a(struct hda_codec *codec)
1172
{
1173
struct ad198x_spec *spec;
1174
int err, board_config;
1175
1176
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1177
if (spec == NULL)
1178
return -ENOMEM;
1179
1180
codec->spec = spec;
1181
1182
err = snd_hda_attach_beep_device(codec, 0x19);
1183
if (err < 0) {
1184
ad198x_free(codec);
1185
return err;
1186
}
1187
set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1188
1189
spec->multiout.max_channels = 6;
1190
spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1191
spec->multiout.dac_nids = ad1986a_dac_nids;
1192
spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1193
spec->num_adc_nids = 1;
1194
spec->adc_nids = ad1986a_adc_nids;
1195
spec->capsrc_nids = ad1986a_capsrc_nids;
1196
spec->input_mux = &ad1986a_capture_source;
1197
spec->num_mixers = 1;
1198
spec->mixers[0] = ad1986a_mixers;
1199
spec->num_init_verbs = 1;
1200
spec->init_verbs[0] = ad1986a_init_verbs;
1201
#ifdef CONFIG_SND_HDA_POWER_SAVE
1202
spec->loopback.amplist = ad1986a_loopbacks;
1203
#endif
1204
spec->vmaster_nid = 0x1b;
1205
spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1206
1207
codec->patch_ops = ad198x_patch_ops;
1208
1209
/* override some parameters */
1210
board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1211
ad1986a_models,
1212
ad1986a_cfg_tbl);
1213
switch (board_config) {
1214
case AD1986A_3STACK:
1215
spec->num_mixers = 2;
1216
spec->mixers[1] = ad1986a_3st_mixers;
1217
spec->num_init_verbs = 2;
1218
spec->init_verbs[1] = ad1986a_ch2_init;
1219
spec->channel_mode = ad1986a_modes;
1220
spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1221
spec->need_dac_fix = 1;
1222
spec->multiout.max_channels = 2;
1223
spec->multiout.num_dacs = 1;
1224
break;
1225
case AD1986A_LAPTOP:
1226
spec->mixers[0] = ad1986a_laptop_mixers;
1227
spec->multiout.max_channels = 2;
1228
spec->multiout.num_dacs = 1;
1229
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1230
break;
1231
case AD1986A_LAPTOP_EAPD:
1232
spec->num_mixers = 3;
1233
spec->mixers[0] = ad1986a_laptop_master_mixers;
1234
spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1235
spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1236
spec->num_init_verbs = 2;
1237
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1238
spec->multiout.max_channels = 2;
1239
spec->multiout.num_dacs = 1;
1240
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1241
if (!is_jack_available(codec, 0x25))
1242
spec->multiout.dig_out_nid = 0;
1243
spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1244
break;
1245
case AD1986A_SAMSUNG:
1246
spec->num_mixers = 2;
1247
spec->mixers[0] = ad1986a_laptop_master_mixers;
1248
spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1249
spec->num_init_verbs = 3;
1250
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1251
spec->init_verbs[2] = ad1986a_automic_verbs;
1252
spec->multiout.max_channels = 2;
1253
spec->multiout.num_dacs = 1;
1254
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1255
if (!is_jack_available(codec, 0x25))
1256
spec->multiout.dig_out_nid = 0;
1257
spec->input_mux = &ad1986a_automic_capture_source;
1258
codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1259
codec->patch_ops.init = ad1986a_automic_init;
1260
break;
1261
case AD1986A_SAMSUNG_P50:
1262
spec->num_mixers = 2;
1263
spec->mixers[0] = ad1986a_automute_master_mixers;
1264
spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1265
spec->num_init_verbs = 4;
1266
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1267
spec->init_verbs[2] = ad1986a_automic_verbs;
1268
spec->init_verbs[3] = ad1986a_hp_init_verbs;
1269
spec->multiout.max_channels = 2;
1270
spec->multiout.num_dacs = 1;
1271
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1272
if (!is_jack_available(codec, 0x25))
1273
spec->multiout.dig_out_nid = 0;
1274
spec->input_mux = &ad1986a_automic_capture_source;
1275
codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1276
codec->patch_ops.init = ad1986a_samsung_p50_init;
1277
break;
1278
case AD1986A_LAPTOP_AUTOMUTE:
1279
spec->num_mixers = 3;
1280
spec->mixers[0] = ad1986a_automute_master_mixers;
1281
spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1282
spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1283
spec->num_init_verbs = 3;
1284
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1285
spec->init_verbs[2] = ad1986a_hp_init_verbs;
1286
spec->multiout.max_channels = 2;
1287
spec->multiout.num_dacs = 1;
1288
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1289
if (!is_jack_available(codec, 0x25))
1290
spec->multiout.dig_out_nid = 0;
1291
spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1292
codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1293
codec->patch_ops.init = ad1986a_hp_init;
1294
/* Lenovo N100 seems to report the reversed bit
1295
* for HP jack-sensing
1296
*/
1297
spec->inv_jack_detect = 1;
1298
break;
1299
case AD1986A_ULTRA:
1300
spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1301
spec->num_init_verbs = 2;
1302
spec->init_verbs[1] = ad1986a_ultra_init;
1303
spec->multiout.max_channels = 2;
1304
spec->multiout.num_dacs = 1;
1305
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1306
spec->multiout.dig_out_nid = 0;
1307
break;
1308
}
1309
1310
/* AD1986A has a hardware problem that it can't share a stream
1311
* with multiple output pins. The copy of front to surrounds
1312
* causes noisy or silent outputs at a certain timing, e.g.
1313
* changing the volume.
1314
* So, let's disable the shared stream.
1315
*/
1316
spec->multiout.no_share_stream = 1;
1317
1318
codec->no_trigger_sense = 1;
1319
codec->no_sticky_stream = 1;
1320
1321
return 0;
1322
}
1323
1324
/*
1325
* AD1983 specific
1326
*/
1327
1328
#define AD1983_SPDIF_OUT 0x02
1329
#define AD1983_DAC 0x03
1330
#define AD1983_ADC 0x04
1331
1332
static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1333
static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1334
static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1335
1336
static const struct hda_input_mux ad1983_capture_source = {
1337
.num_items = 4,
1338
.items = {
1339
{ "Mic", 0x0 },
1340
{ "Line", 0x1 },
1341
{ "Mix", 0x2 },
1342
{ "Mix Mono", 0x3 },
1343
},
1344
};
1345
1346
/*
1347
* SPDIF playback route
1348
*/
1349
static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1350
{
1351
static const char * const texts[] = { "PCM", "ADC" };
1352
1353
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1354
uinfo->count = 1;
1355
uinfo->value.enumerated.items = 2;
1356
if (uinfo->value.enumerated.item > 1)
1357
uinfo->value.enumerated.item = 1;
1358
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1359
return 0;
1360
}
1361
1362
static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1363
{
1364
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1365
struct ad198x_spec *spec = codec->spec;
1366
1367
ucontrol->value.enumerated.item[0] = spec->spdif_route;
1368
return 0;
1369
}
1370
1371
static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1372
{
1373
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1374
struct ad198x_spec *spec = codec->spec;
1375
1376
if (ucontrol->value.enumerated.item[0] > 1)
1377
return -EINVAL;
1378
if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1379
spec->spdif_route = ucontrol->value.enumerated.item[0];
1380
snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1381
AC_VERB_SET_CONNECT_SEL,
1382
spec->spdif_route);
1383
return 1;
1384
}
1385
return 0;
1386
}
1387
1388
static const struct snd_kcontrol_new ad1983_mixers[] = {
1389
HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1390
HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1391
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1392
HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1393
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1394
HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1395
HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1396
HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1397
HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1398
HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1399
HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1400
HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1401
HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT),
1402
HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1403
HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1404
{
1405
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1406
.name = "Capture Source",
1407
.info = ad198x_mux_enum_info,
1408
.get = ad198x_mux_enum_get,
1409
.put = ad198x_mux_enum_put,
1410
},
1411
{
1412
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1413
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1414
.info = ad1983_spdif_route_info,
1415
.get = ad1983_spdif_route_get,
1416
.put = ad1983_spdif_route_put,
1417
},
1418
{ } /* end */
1419
};
1420
1421
static const struct hda_verb ad1983_init_verbs[] = {
1422
/* Front, HP, Mono; mute as default */
1423
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1424
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1425
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1426
/* Beep, PCM, Mic, Line-In: mute */
1427
{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1428
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1429
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1430
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1431
/* Front, HP selectors; from Mix */
1432
{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1433
{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1434
/* Mono selector; from Mix */
1435
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1436
/* Mic selector; Mic */
1437
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1438
/* Line-in selector: Line-in */
1439
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1440
/* Mic boost: 0dB */
1441
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1442
/* Record selector: mic */
1443
{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1444
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1445
/* SPDIF route: PCM */
1446
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1447
/* Front Pin */
1448
{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1449
/* HP Pin */
1450
{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1451
/* Mono Pin */
1452
{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1453
/* Mic Pin */
1454
{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1455
/* Line Pin */
1456
{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1457
{ } /* end */
1458
};
1459
1460
#ifdef CONFIG_SND_HDA_POWER_SAVE
1461
static const struct hda_amp_list ad1983_loopbacks[] = {
1462
{ 0x12, HDA_OUTPUT, 0 }, /* Mic */
1463
{ 0x13, HDA_OUTPUT, 0 }, /* Line */
1464
{ } /* end */
1465
};
1466
#endif
1467
1468
static int patch_ad1983(struct hda_codec *codec)
1469
{
1470
struct ad198x_spec *spec;
1471
int err;
1472
1473
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1474
if (spec == NULL)
1475
return -ENOMEM;
1476
1477
codec->spec = spec;
1478
1479
err = snd_hda_attach_beep_device(codec, 0x10);
1480
if (err < 0) {
1481
ad198x_free(codec);
1482
return err;
1483
}
1484
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1485
1486
spec->multiout.max_channels = 2;
1487
spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1488
spec->multiout.dac_nids = ad1983_dac_nids;
1489
spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1490
spec->num_adc_nids = 1;
1491
spec->adc_nids = ad1983_adc_nids;
1492
spec->capsrc_nids = ad1983_capsrc_nids;
1493
spec->input_mux = &ad1983_capture_source;
1494
spec->num_mixers = 1;
1495
spec->mixers[0] = ad1983_mixers;
1496
spec->num_init_verbs = 1;
1497
spec->init_verbs[0] = ad1983_init_verbs;
1498
spec->spdif_route = 0;
1499
#ifdef CONFIG_SND_HDA_POWER_SAVE
1500
spec->loopback.amplist = ad1983_loopbacks;
1501
#endif
1502
spec->vmaster_nid = 0x05;
1503
1504
codec->patch_ops = ad198x_patch_ops;
1505
1506
codec->no_trigger_sense = 1;
1507
codec->no_sticky_stream = 1;
1508
1509
return 0;
1510
}
1511
1512
1513
/*
1514
* AD1981 HD specific
1515
*/
1516
1517
#define AD1981_SPDIF_OUT 0x02
1518
#define AD1981_DAC 0x03
1519
#define AD1981_ADC 0x04
1520
1521
static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1522
static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1523
static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1524
1525
/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1526
static const struct hda_input_mux ad1981_capture_source = {
1527
.num_items = 7,
1528
.items = {
1529
{ "Front Mic", 0x0 },
1530
{ "Line", 0x1 },
1531
{ "Mix", 0x2 },
1532
{ "Mix Mono", 0x3 },
1533
{ "CD", 0x4 },
1534
{ "Mic", 0x6 },
1535
{ "Aux", 0x7 },
1536
},
1537
};
1538
1539
static const struct snd_kcontrol_new ad1981_mixers[] = {
1540
HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1541
HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1542
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1543
HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1544
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1545
HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1546
HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1547
HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1548
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1549
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1550
HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1551
HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1552
HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1553
HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1554
HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1555
HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1556
HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1557
HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1558
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1559
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1560
HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1561
HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1562
{
1563
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1564
.name = "Capture Source",
1565
.info = ad198x_mux_enum_info,
1566
.get = ad198x_mux_enum_get,
1567
.put = ad198x_mux_enum_put,
1568
},
1569
/* identical with AD1983 */
1570
{
1571
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1572
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1573
.info = ad1983_spdif_route_info,
1574
.get = ad1983_spdif_route_get,
1575
.put = ad1983_spdif_route_put,
1576
},
1577
{ } /* end */
1578
};
1579
1580
static const struct hda_verb ad1981_init_verbs[] = {
1581
/* Front, HP, Mono; mute as default */
1582
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1583
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1584
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1585
/* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1586
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1587
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1588
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1589
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1590
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1591
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1592
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1593
/* Front, HP selectors; from Mix */
1594
{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1595
{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1596
/* Mono selector; from Mix */
1597
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1598
/* Mic Mixer; select Front Mic */
1599
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1600
{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1601
/* Mic boost: 0dB */
1602
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1603
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1604
/* Record selector: Front mic */
1605
{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1606
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1607
/* SPDIF route: PCM */
1608
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1609
/* Front Pin */
1610
{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1611
/* HP Pin */
1612
{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1613
/* Mono Pin */
1614
{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1615
/* Front & Rear Mic Pins */
1616
{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1617
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1618
/* Line Pin */
1619
{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1620
/* Digital Beep */
1621
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1622
/* Line-Out as Input: disabled */
1623
{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1624
{ } /* end */
1625
};
1626
1627
#ifdef CONFIG_SND_HDA_POWER_SAVE
1628
static const struct hda_amp_list ad1981_loopbacks[] = {
1629
{ 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1630
{ 0x13, HDA_OUTPUT, 0 }, /* Line */
1631
{ 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1632
{ 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1633
{ 0x1d, HDA_OUTPUT, 0 }, /* CD */
1634
{ } /* end */
1635
};
1636
#endif
1637
1638
/*
1639
* Patch for HP nx6320
1640
*
1641
* nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1642
* speaker output enabled _and_ mute-LED off.
1643
*/
1644
1645
#define AD1981_HP_EVENT 0x37
1646
#define AD1981_MIC_EVENT 0x38
1647
1648
static const struct hda_verb ad1981_hp_init_verbs[] = {
1649
{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1650
/* pin sensing on HP and Mic jacks */
1651
{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1652
{0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1653
{}
1654
};
1655
1656
/* turn on/off EAPD (+ mute HP) as a master switch */
1657
static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1658
struct snd_ctl_elem_value *ucontrol)
1659
{
1660
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1661
struct ad198x_spec *spec = codec->spec;
1662
1663
if (! ad198x_eapd_put(kcontrol, ucontrol))
1664
return 0;
1665
/* change speaker pin appropriately */
1666
snd_hda_codec_write(codec, 0x05, 0,
1667
AC_VERB_SET_PIN_WIDGET_CONTROL,
1668
spec->cur_eapd ? PIN_OUT : 0);
1669
/* toggle HP mute appropriately */
1670
snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1671
HDA_AMP_MUTE,
1672
spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1673
return 1;
1674
}
1675
1676
/* bind volumes of both NID 0x05 and 0x06 */
1677
static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1678
.ops = &snd_hda_bind_vol,
1679
.values = {
1680
HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1681
HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1682
0
1683
},
1684
};
1685
1686
/* mute internal speaker if HP is plugged */
1687
static void ad1981_hp_automute(struct hda_codec *codec)
1688
{
1689
unsigned int present;
1690
1691
present = snd_hda_jack_detect(codec, 0x06);
1692
snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1693
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1694
}
1695
1696
/* toggle input of built-in and mic jack appropriately */
1697
static void ad1981_hp_automic(struct hda_codec *codec)
1698
{
1699
static const struct hda_verb mic_jack_on[] = {
1700
{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1701
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1702
{}
1703
};
1704
static const struct hda_verb mic_jack_off[] = {
1705
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1706
{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1707
{}
1708
};
1709
unsigned int present;
1710
1711
present = snd_hda_jack_detect(codec, 0x08);
1712
if (present)
1713
snd_hda_sequence_write(codec, mic_jack_on);
1714
else
1715
snd_hda_sequence_write(codec, mic_jack_off);
1716
}
1717
1718
/* unsolicited event for HP jack sensing */
1719
static void ad1981_hp_unsol_event(struct hda_codec *codec,
1720
unsigned int res)
1721
{
1722
res >>= 26;
1723
switch (res) {
1724
case AD1981_HP_EVENT:
1725
ad1981_hp_automute(codec);
1726
break;
1727
case AD1981_MIC_EVENT:
1728
ad1981_hp_automic(codec);
1729
break;
1730
}
1731
}
1732
1733
static const struct hda_input_mux ad1981_hp_capture_source = {
1734
.num_items = 3,
1735
.items = {
1736
{ "Mic", 0x0 },
1737
{ "Docking-Station", 0x1 },
1738
{ "Mix", 0x2 },
1739
},
1740
};
1741
1742
static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
1743
HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1744
{
1745
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1746
.subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1747
.name = "Master Playback Switch",
1748
.info = ad198x_eapd_info,
1749
.get = ad198x_eapd_get,
1750
.put = ad1981_hp_master_sw_put,
1751
.private_value = 0x05,
1752
},
1753
HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1754
HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1755
#if 0
1756
/* FIXME: analog mic/line loopback doesn't work with my tests...
1757
* (although recording is OK)
1758
*/
1759
HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1760
HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1761
HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1762
HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1763
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1764
HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1765
/* FIXME: does this laptop have analog CD connection? */
1766
HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1767
HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1768
#endif
1769
HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1770
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1771
HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1772
HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1773
{
1774
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1775
.name = "Capture Source",
1776
.info = ad198x_mux_enum_info,
1777
.get = ad198x_mux_enum_get,
1778
.put = ad198x_mux_enum_put,
1779
},
1780
{ } /* end */
1781
};
1782
1783
/* initialize jack-sensing, too */
1784
static int ad1981_hp_init(struct hda_codec *codec)
1785
{
1786
ad198x_init(codec);
1787
ad1981_hp_automute(codec);
1788
ad1981_hp_automic(codec);
1789
return 0;
1790
}
1791
1792
/* configuration for Toshiba Laptops */
1793
static const struct hda_verb ad1981_toshiba_init_verbs[] = {
1794
{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1795
/* pin sensing on HP and Mic jacks */
1796
{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1797
{0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1798
{}
1799
};
1800
1801
static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1802
HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1803
HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1804
{ }
1805
};
1806
1807
/* configuration for Lenovo Thinkpad T60 */
1808
static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1809
HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1810
HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1811
HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1812
HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1813
HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1814
HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1815
HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1816
HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1817
HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1818
HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1819
HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1820
{
1821
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1822
.name = "Capture Source",
1823
.info = ad198x_mux_enum_info,
1824
.get = ad198x_mux_enum_get,
1825
.put = ad198x_mux_enum_put,
1826
},
1827
/* identical with AD1983 */
1828
{
1829
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1830
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1831
.info = ad1983_spdif_route_info,
1832
.get = ad1983_spdif_route_get,
1833
.put = ad1983_spdif_route_put,
1834
},
1835
{ } /* end */
1836
};
1837
1838
static const struct hda_input_mux ad1981_thinkpad_capture_source = {
1839
.num_items = 3,
1840
.items = {
1841
{ "Mic", 0x0 },
1842
{ "Mix", 0x2 },
1843
{ "CD", 0x4 },
1844
},
1845
};
1846
1847
/* models */
1848
enum {
1849
AD1981_BASIC,
1850
AD1981_HP,
1851
AD1981_THINKPAD,
1852
AD1981_TOSHIBA,
1853
AD1981_MODELS
1854
};
1855
1856
static const char * const ad1981_models[AD1981_MODELS] = {
1857
[AD1981_HP] = "hp",
1858
[AD1981_THINKPAD] = "thinkpad",
1859
[AD1981_BASIC] = "basic",
1860
[AD1981_TOSHIBA] = "toshiba"
1861
};
1862
1863
static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
1864
SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1865
SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1866
/* All HP models */
1867
SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1868
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1869
/* Lenovo Thinkpad T60/X60/Z6xx */
1870
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1871
/* HP nx6320 (reversed SSID, H/W bug) */
1872
SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1873
{}
1874
};
1875
1876
static int patch_ad1981(struct hda_codec *codec)
1877
{
1878
struct ad198x_spec *spec;
1879
int err, board_config;
1880
1881
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1882
if (spec == NULL)
1883
return -ENOMEM;
1884
1885
codec->spec = spec;
1886
1887
err = snd_hda_attach_beep_device(codec, 0x10);
1888
if (err < 0) {
1889
ad198x_free(codec);
1890
return err;
1891
}
1892
set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1893
1894
spec->multiout.max_channels = 2;
1895
spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1896
spec->multiout.dac_nids = ad1981_dac_nids;
1897
spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1898
spec->num_adc_nids = 1;
1899
spec->adc_nids = ad1981_adc_nids;
1900
spec->capsrc_nids = ad1981_capsrc_nids;
1901
spec->input_mux = &ad1981_capture_source;
1902
spec->num_mixers = 1;
1903
spec->mixers[0] = ad1981_mixers;
1904
spec->num_init_verbs = 1;
1905
spec->init_verbs[0] = ad1981_init_verbs;
1906
spec->spdif_route = 0;
1907
#ifdef CONFIG_SND_HDA_POWER_SAVE
1908
spec->loopback.amplist = ad1981_loopbacks;
1909
#endif
1910
spec->vmaster_nid = 0x05;
1911
1912
codec->patch_ops = ad198x_patch_ops;
1913
1914
/* override some parameters */
1915
board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1916
ad1981_models,
1917
ad1981_cfg_tbl);
1918
switch (board_config) {
1919
case AD1981_HP:
1920
spec->mixers[0] = ad1981_hp_mixers;
1921
spec->num_init_verbs = 2;
1922
spec->init_verbs[1] = ad1981_hp_init_verbs;
1923
spec->multiout.dig_out_nid = 0;
1924
spec->input_mux = &ad1981_hp_capture_source;
1925
1926
codec->patch_ops.init = ad1981_hp_init;
1927
codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1928
/* set the upper-limit for mixer amp to 0dB for avoiding the
1929
* possible damage by overloading
1930
*/
1931
snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1932
(0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1933
(0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1934
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1935
(1 << AC_AMPCAP_MUTE_SHIFT));
1936
break;
1937
case AD1981_THINKPAD:
1938
spec->mixers[0] = ad1981_thinkpad_mixers;
1939
spec->input_mux = &ad1981_thinkpad_capture_source;
1940
/* set the upper-limit for mixer amp to 0dB for avoiding the
1941
* possible damage by overloading
1942
*/
1943
snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1944
(0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1945
(0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1946
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1947
(1 << AC_AMPCAP_MUTE_SHIFT));
1948
break;
1949
case AD1981_TOSHIBA:
1950
spec->mixers[0] = ad1981_hp_mixers;
1951
spec->mixers[1] = ad1981_toshiba_mixers;
1952
spec->num_init_verbs = 2;
1953
spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1954
spec->multiout.dig_out_nid = 0;
1955
spec->input_mux = &ad1981_hp_capture_source;
1956
codec->patch_ops.init = ad1981_hp_init;
1957
codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1958
break;
1959
}
1960
1961
codec->no_trigger_sense = 1;
1962
codec->no_sticky_stream = 1;
1963
1964
return 0;
1965
}
1966
1967
1968
/*
1969
* AD1988
1970
*
1971
* Output pins and routes
1972
*
1973
* Pin Mix Sel DAC (*)
1974
* port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1975
* port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1976
* port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1977
* port-D 0x12 (mute/hp) <- 0x29 <- 04
1978
* port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1979
* port-F 0x16 (mute) <- 0x2a <- 06
1980
* port-G 0x24 (mute) <- 0x27 <- 05
1981
* port-H 0x25 (mute) <- 0x28 <- 0a
1982
* mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1983
*
1984
* DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1985
* (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1986
*
1987
* Input pins and routes
1988
*
1989
* pin boost mix input # / adc input #
1990
* port-A 0x11 -> 0x38 -> mix 2, ADC 0
1991
* port-B 0x14 -> 0x39 -> mix 0, ADC 1
1992
* port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1993
* port-D 0x12 -> 0x3d -> mix 3, ADC 8
1994
* port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1995
* port-F 0x16 -> 0x3b -> mix 5, ADC 3
1996
* port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1997
* port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1998
*
1999
*
2000
* DAC assignment
2001
* 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2002
* 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2003
*
2004
* Inputs of Analog Mix (0x20)
2005
* 0:Port-B (front mic)
2006
* 1:Port-C/G/H (line-in)
2007
* 2:Port-A
2008
* 3:Port-D (line-in/2)
2009
* 4:Port-E/G/H (mic-in)
2010
* 5:Port-F (mic2-in)
2011
* 6:CD
2012
* 7:Beep
2013
*
2014
* ADC selection
2015
* 0:Port-A
2016
* 1:Port-B (front mic-in)
2017
* 2:Port-C (line-in)
2018
* 3:Port-F (mic2-in)
2019
* 4:Port-E (mic-in)
2020
* 5:CD
2021
* 6:Port-G
2022
* 7:Port-H
2023
* 8:Port-D (line-in/2)
2024
* 9:Mix
2025
*
2026
* Proposed pin assignments by the datasheet
2027
*
2028
* 6-stack
2029
* Port-A front headphone
2030
* B front mic-in
2031
* C rear line-in
2032
* D rear front-out
2033
* E rear mic-in
2034
* F rear surround
2035
* G rear CLFE
2036
* H rear side
2037
*
2038
* 3-stack
2039
* Port-A front headphone
2040
* B front mic
2041
* C rear line-in/surround
2042
* D rear front-out
2043
* E rear mic-in/CLFE
2044
*
2045
* laptop
2046
* Port-A headphone
2047
* B mic-in
2048
* C docking station
2049
* D internal speaker (with EAPD)
2050
* E/F quad mic array
2051
*/
2052
2053
2054
/* models */
2055
enum {
2056
AD1988_6STACK,
2057
AD1988_6STACK_DIG,
2058
AD1988_6STACK_DIG_FP,
2059
AD1988_3STACK,
2060
AD1988_3STACK_DIG,
2061
AD1988_LAPTOP,
2062
AD1988_LAPTOP_DIG,
2063
AD1988_AUTO,
2064
AD1988_MODEL_LAST,
2065
};
2066
2067
/* reivision id to check workarounds */
2068
#define AD1988A_REV2 0x100200
2069
2070
#define is_rev2(codec) \
2071
((codec)->vendor_id == 0x11d41988 && \
2072
(codec)->revision_id == AD1988A_REV2)
2073
2074
/*
2075
* mixers
2076
*/
2077
2078
static const hda_nid_t ad1988_6stack_dac_nids[4] = {
2079
0x04, 0x06, 0x05, 0x0a
2080
};
2081
2082
static const hda_nid_t ad1988_3stack_dac_nids[3] = {
2083
0x04, 0x05, 0x0a
2084
};
2085
2086
/* for AD1988A revision-2, DAC2-4 are swapped */
2087
static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2088
0x04, 0x05, 0x0a, 0x06
2089
};
2090
2091
static const hda_nid_t ad1988_alt_dac_nid[1] = {
2092
0x03
2093
};
2094
2095
static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2096
0x04, 0x0a, 0x06
2097
};
2098
2099
static const hda_nid_t ad1988_adc_nids[3] = {
2100
0x08, 0x09, 0x0f
2101
};
2102
2103
static const hda_nid_t ad1988_capsrc_nids[3] = {
2104
0x0c, 0x0d, 0x0e
2105
};
2106
2107
#define AD1988_SPDIF_OUT 0x02
2108
#define AD1988_SPDIF_OUT_HDMI 0x0b
2109
#define AD1988_SPDIF_IN 0x07
2110
2111
static const hda_nid_t ad1989b_slave_dig_outs[] = {
2112
AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2113
};
2114
2115
static const struct hda_input_mux ad1988_6stack_capture_source = {
2116
.num_items = 5,
2117
.items = {
2118
{ "Front Mic", 0x1 }, /* port-B */
2119
{ "Line", 0x2 }, /* port-C */
2120
{ "Mic", 0x4 }, /* port-E */
2121
{ "CD", 0x5 },
2122
{ "Mix", 0x9 },
2123
},
2124
};
2125
2126
static const struct hda_input_mux ad1988_laptop_capture_source = {
2127
.num_items = 3,
2128
.items = {
2129
{ "Mic/Line", 0x1 }, /* port-B */
2130
{ "CD", 0x5 },
2131
{ "Mix", 0x9 },
2132
},
2133
};
2134
2135
/*
2136
*/
2137
static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2138
struct snd_ctl_elem_info *uinfo)
2139
{
2140
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2141
struct ad198x_spec *spec = codec->spec;
2142
return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2143
spec->num_channel_mode);
2144
}
2145
2146
static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2147
struct snd_ctl_elem_value *ucontrol)
2148
{
2149
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2150
struct ad198x_spec *spec = codec->spec;
2151
return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2152
spec->num_channel_mode, spec->multiout.max_channels);
2153
}
2154
2155
static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2156
struct snd_ctl_elem_value *ucontrol)
2157
{
2158
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2159
struct ad198x_spec *spec = codec->spec;
2160
int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2161
spec->num_channel_mode,
2162
&spec->multiout.max_channels);
2163
if (err >= 0 && spec->need_dac_fix)
2164
spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2165
return err;
2166
}
2167
2168
/* 6-stack mode */
2169
static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2170
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2171
HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2172
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2173
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2174
HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2175
{ } /* end */
2176
};
2177
2178
static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2179
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2180
HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2181
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2182
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2183
HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2184
{ } /* end */
2185
};
2186
2187
static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2188
HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2189
HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2190
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2191
HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2192
HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2193
HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2194
HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2195
2196
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2197
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2198
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2199
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2200
HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2201
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2202
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2203
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2204
2205
HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2206
HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2207
2208
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2209
HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2210
2211
{ } /* end */
2212
};
2213
2214
static const struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
2215
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2216
2217
{ } /* end */
2218
};
2219
2220
/* 3-stack mode */
2221
static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2222
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2223
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2224
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2225
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2226
{ } /* end */
2227
};
2228
2229
static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2230
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2231
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2232
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2233
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2234
{ } /* end */
2235
};
2236
2237
static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2238
HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2239
HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2240
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2241
HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2242
HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2243
HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2244
2245
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2246
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2247
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2248
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2249
HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2250
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2251
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2252
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2253
2254
HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2255
HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2256
2257
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2258
HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2259
{
2260
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2261
.name = "Channel Mode",
2262
.info = ad198x_ch_mode_info,
2263
.get = ad198x_ch_mode_get,
2264
.put = ad198x_ch_mode_put,
2265
},
2266
2267
{ } /* end */
2268
};
2269
2270
/* laptop mode */
2271
static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2272
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2273
HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2274
HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2275
2276
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2277
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2278
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2279
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2280
HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2281
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2282
2283
HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2284
HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2285
2286
HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2287
2288
{
2289
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2290
.name = "External Amplifier",
2291
.subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2292
.info = ad198x_eapd_info,
2293
.get = ad198x_eapd_get,
2294
.put = ad198x_eapd_put,
2295
.private_value = 0x12, /* port-D */
2296
},
2297
2298
{ } /* end */
2299
};
2300
2301
/* capture */
2302
static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
2303
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2304
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2305
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2306
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2307
HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2308
HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2309
{
2310
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2311
/* The multiple "Capture Source" controls confuse alsamixer
2312
* So call somewhat different..
2313
*/
2314
/* .name = "Capture Source", */
2315
.name = "Input Source",
2316
.count = 3,
2317
.info = ad198x_mux_enum_info,
2318
.get = ad198x_mux_enum_get,
2319
.put = ad198x_mux_enum_put,
2320
},
2321
{ } /* end */
2322
};
2323
2324
static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2325
struct snd_ctl_elem_info *uinfo)
2326
{
2327
static const char * const texts[] = {
2328
"PCM", "ADC1", "ADC2", "ADC3"
2329
};
2330
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2331
uinfo->count = 1;
2332
uinfo->value.enumerated.items = 4;
2333
if (uinfo->value.enumerated.item >= 4)
2334
uinfo->value.enumerated.item = 3;
2335
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2336
return 0;
2337
}
2338
2339
static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2340
struct snd_ctl_elem_value *ucontrol)
2341
{
2342
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2343
unsigned int sel;
2344
2345
sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2346
AC_AMP_GET_INPUT);
2347
if (!(sel & 0x80))
2348
ucontrol->value.enumerated.item[0] = 0;
2349
else {
2350
sel = snd_hda_codec_read(codec, 0x0b, 0,
2351
AC_VERB_GET_CONNECT_SEL, 0);
2352
if (sel < 3)
2353
sel++;
2354
else
2355
sel = 0;
2356
ucontrol->value.enumerated.item[0] = sel;
2357
}
2358
return 0;
2359
}
2360
2361
static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2362
struct snd_ctl_elem_value *ucontrol)
2363
{
2364
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2365
unsigned int val, sel;
2366
int change;
2367
2368
val = ucontrol->value.enumerated.item[0];
2369
if (val > 3)
2370
return -EINVAL;
2371
if (!val) {
2372
sel = snd_hda_codec_read(codec, 0x1d, 0,
2373
AC_VERB_GET_AMP_GAIN_MUTE,
2374
AC_AMP_GET_INPUT);
2375
change = sel & 0x80;
2376
if (change) {
2377
snd_hda_codec_write_cache(codec, 0x1d, 0,
2378
AC_VERB_SET_AMP_GAIN_MUTE,
2379
AMP_IN_UNMUTE(0));
2380
snd_hda_codec_write_cache(codec, 0x1d, 0,
2381
AC_VERB_SET_AMP_GAIN_MUTE,
2382
AMP_IN_MUTE(1));
2383
}
2384
} else {
2385
sel = snd_hda_codec_read(codec, 0x1d, 0,
2386
AC_VERB_GET_AMP_GAIN_MUTE,
2387
AC_AMP_GET_INPUT | 0x01);
2388
change = sel & 0x80;
2389
if (change) {
2390
snd_hda_codec_write_cache(codec, 0x1d, 0,
2391
AC_VERB_SET_AMP_GAIN_MUTE,
2392
AMP_IN_MUTE(0));
2393
snd_hda_codec_write_cache(codec, 0x1d, 0,
2394
AC_VERB_SET_AMP_GAIN_MUTE,
2395
AMP_IN_UNMUTE(1));
2396
}
2397
sel = snd_hda_codec_read(codec, 0x0b, 0,
2398
AC_VERB_GET_CONNECT_SEL, 0) + 1;
2399
change |= sel != val;
2400
if (change)
2401
snd_hda_codec_write_cache(codec, 0x0b, 0,
2402
AC_VERB_SET_CONNECT_SEL,
2403
val - 1);
2404
}
2405
return change;
2406
}
2407
2408
static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2409
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2410
{
2411
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2412
.name = "IEC958 Playback Source",
2413
.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2414
.info = ad1988_spdif_playback_source_info,
2415
.get = ad1988_spdif_playback_source_get,
2416
.put = ad1988_spdif_playback_source_put,
2417
},
2418
{ } /* end */
2419
};
2420
2421
static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2422
HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2423
{ } /* end */
2424
};
2425
2426
static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2427
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2428
HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2429
{ } /* end */
2430
};
2431
2432
/*
2433
* initialization verbs
2434
*/
2435
2436
/*
2437
* for 6-stack (+dig)
2438
*/
2439
static const struct hda_verb ad1988_6stack_init_verbs[] = {
2440
/* Front, Surround, CLFE, side DAC; unmute as default */
2441
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2442
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2443
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2444
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2445
/* Port-A front headphon path */
2446
{0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2447
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2448
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2449
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2450
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2451
/* Port-D line-out path */
2452
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2453
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2454
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2455
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2456
/* Port-F surround path */
2457
{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2458
{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2459
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2460
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2461
/* Port-G CLFE path */
2462
{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2463
{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2464
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2465
{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2466
/* Port-H side path */
2467
{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2468
{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2469
{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2470
{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2471
/* Mono out path */
2472
{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2473
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2474
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2475
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2476
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2477
/* Port-B front mic-in path */
2478
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2479
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2480
{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2481
/* Port-C line-in path */
2482
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2483
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2484
{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2485
{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2486
/* Port-E mic-in path */
2487
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2488
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2489
{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2490
{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2491
/* Analog CD Input */
2492
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2493
/* Analog Mix output amp */
2494
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2495
2496
{ }
2497
};
2498
2499
static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
2500
/* Headphone; unmute as default */
2501
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2502
/* Port-A front headphon path */
2503
{0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2504
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2505
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2506
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2507
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2508
2509
{ }
2510
};
2511
2512
static const struct hda_verb ad1988_capture_init_verbs[] = {
2513
/* mute analog mix */
2514
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2515
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2516
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2517
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2518
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2519
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2520
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2521
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2522
/* select ADCs - front-mic */
2523
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2524
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2525
{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2526
2527
{ }
2528
};
2529
2530
static const struct hda_verb ad1988_spdif_init_verbs[] = {
2531
/* SPDIF out sel */
2532
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2533
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2534
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2535
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2536
/* SPDIF out pin */
2537
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2538
2539
{ }
2540
};
2541
2542
static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
2543
/* unmute SPDIF input pin */
2544
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2545
{ }
2546
};
2547
2548
/* AD1989 has no ADC -> SPDIF route */
2549
static const struct hda_verb ad1989_spdif_init_verbs[] = {
2550
/* SPDIF-1 out pin */
2551
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2552
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2553
/* SPDIF-2/HDMI out pin */
2554
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2555
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2556
{ }
2557
};
2558
2559
/*
2560
* verbs for 3stack (+dig)
2561
*/
2562
static const struct hda_verb ad1988_3stack_ch2_init[] = {
2563
/* set port-C to line-in */
2564
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2565
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2566
/* set port-E to mic-in */
2567
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2568
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2569
{ } /* end */
2570
};
2571
2572
static const struct hda_verb ad1988_3stack_ch6_init[] = {
2573
/* set port-C to surround out */
2574
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2575
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2576
/* set port-E to CLFE out */
2577
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2578
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2579
{ } /* end */
2580
};
2581
2582
static const struct hda_channel_mode ad1988_3stack_modes[2] = {
2583
{ 2, ad1988_3stack_ch2_init },
2584
{ 6, ad1988_3stack_ch6_init },
2585
};
2586
2587
static const struct hda_verb ad1988_3stack_init_verbs[] = {
2588
/* Front, Surround, CLFE, side DAC; unmute as default */
2589
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2590
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2591
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2592
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2593
/* Port-A front headphon path */
2594
{0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2595
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2596
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2597
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2598
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2599
/* Port-D line-out path */
2600
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2601
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2602
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2603
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2604
/* Mono out path */
2605
{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2606
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2607
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2608
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2609
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2610
/* Port-B front mic-in path */
2611
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2612
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2613
{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2614
/* Port-C line-in/surround path - 6ch mode as default */
2615
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2616
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2617
{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2618
{0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2619
{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2620
/* Port-E mic-in/CLFE path - 6ch mode as default */
2621
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2622
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2623
{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2624
{0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2625
{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2626
/* mute analog mix */
2627
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2628
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2629
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2630
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2631
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2632
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2633
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2634
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2635
/* select ADCs - front-mic */
2636
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2637
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2638
{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2639
/* Analog Mix output amp */
2640
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2641
{ }
2642
};
2643
2644
/*
2645
* verbs for laptop mode (+dig)
2646
*/
2647
static const struct hda_verb ad1988_laptop_hp_on[] = {
2648
/* unmute port-A and mute port-D */
2649
{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2650
{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2651
{ } /* end */
2652
};
2653
static const struct hda_verb ad1988_laptop_hp_off[] = {
2654
/* mute port-A and unmute port-D */
2655
{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2656
{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2657
{ } /* end */
2658
};
2659
2660
#define AD1988_HP_EVENT 0x01
2661
2662
static const struct hda_verb ad1988_laptop_init_verbs[] = {
2663
/* Front, Surround, CLFE, side DAC; unmute as default */
2664
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2665
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2666
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2667
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2668
/* Port-A front headphon path */
2669
{0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2670
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2671
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2672
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2673
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2674
/* unsolicited event for pin-sense */
2675
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2676
/* Port-D line-out path + EAPD */
2677
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2678
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2679
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2680
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2681
{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2682
/* Mono out path */
2683
{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2684
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2685
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2686
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2687
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2688
/* Port-B mic-in path */
2689
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2690
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2691
{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2692
/* Port-C docking station - try to output */
2693
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2694
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2695
{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2696
{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2697
/* mute analog mix */
2698
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2699
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2700
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2701
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2702
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2703
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2704
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2705
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2706
/* select ADCs - mic */
2707
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2708
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2709
{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2710
/* Analog Mix output amp */
2711
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2712
{ }
2713
};
2714
2715
static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2716
{
2717
if ((res >> 26) != AD1988_HP_EVENT)
2718
return;
2719
if (snd_hda_jack_detect(codec, 0x11))
2720
snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2721
else
2722
snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2723
}
2724
2725
#ifdef CONFIG_SND_HDA_POWER_SAVE
2726
static const struct hda_amp_list ad1988_loopbacks[] = {
2727
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
2728
{ 0x20, HDA_INPUT, 1 }, /* Line */
2729
{ 0x20, HDA_INPUT, 4 }, /* Mic */
2730
{ 0x20, HDA_INPUT, 6 }, /* CD */
2731
{ } /* end */
2732
};
2733
#endif
2734
2735
/*
2736
* Automatic parse of I/O pins from the BIOS configuration
2737
*/
2738
2739
enum {
2740
AD_CTL_WIDGET_VOL,
2741
AD_CTL_WIDGET_MUTE,
2742
AD_CTL_BIND_MUTE,
2743
};
2744
static const struct snd_kcontrol_new ad1988_control_templates[] = {
2745
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2746
HDA_CODEC_MUTE(NULL, 0, 0, 0),
2747
HDA_BIND_MUTE(NULL, 0, 0, 0),
2748
};
2749
2750
/* add dynamic controls */
2751
static int add_control(struct ad198x_spec *spec, int type, const char *name,
2752
unsigned long val)
2753
{
2754
struct snd_kcontrol_new *knew;
2755
2756
snd_array_init(&spec->kctls, sizeof(*knew), 32);
2757
knew = snd_array_new(&spec->kctls);
2758
if (!knew)
2759
return -ENOMEM;
2760
*knew = ad1988_control_templates[type];
2761
knew->name = kstrdup(name, GFP_KERNEL);
2762
if (! knew->name)
2763
return -ENOMEM;
2764
if (get_amp_nid_(val))
2765
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2766
knew->private_value = val;
2767
return 0;
2768
}
2769
2770
#define AD1988_PIN_CD_NID 0x18
2771
#define AD1988_PIN_BEEP_NID 0x10
2772
2773
static const hda_nid_t ad1988_mixer_nids[8] = {
2774
/* A B C D E F G H */
2775
0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2776
};
2777
2778
static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2779
{
2780
static const hda_nid_t idx_to_dac[8] = {
2781
/* A B C D E F G H */
2782
0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2783
};
2784
static const hda_nid_t idx_to_dac_rev2[8] = {
2785
/* A B C D E F G H */
2786
0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2787
};
2788
if (is_rev2(codec))
2789
return idx_to_dac_rev2[idx];
2790
else
2791
return idx_to_dac[idx];
2792
}
2793
2794
static const hda_nid_t ad1988_boost_nids[8] = {
2795
0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2796
};
2797
2798
static int ad1988_pin_idx(hda_nid_t nid)
2799
{
2800
static const hda_nid_t ad1988_io_pins[8] = {
2801
0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2802
};
2803
int i;
2804
for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2805
if (ad1988_io_pins[i] == nid)
2806
return i;
2807
return 0; /* should be -1 */
2808
}
2809
2810
static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2811
{
2812
static const int loopback_idx[8] = {
2813
2, 0, 1, 3, 4, 5, 1, 4
2814
};
2815
switch (nid) {
2816
case AD1988_PIN_CD_NID:
2817
return 6;
2818
default:
2819
return loopback_idx[ad1988_pin_idx(nid)];
2820
}
2821
}
2822
2823
static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2824
{
2825
static const int adc_idx[8] = {
2826
0, 1, 2, 8, 4, 3, 6, 7
2827
};
2828
switch (nid) {
2829
case AD1988_PIN_CD_NID:
2830
return 5;
2831
default:
2832
return adc_idx[ad1988_pin_idx(nid)];
2833
}
2834
}
2835
2836
/* fill in the dac_nids table from the parsed pin configuration */
2837
static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2838
const struct auto_pin_cfg *cfg)
2839
{
2840
struct ad198x_spec *spec = codec->spec;
2841
int i, idx;
2842
2843
spec->multiout.dac_nids = spec->private_dac_nids;
2844
2845
/* check the pins hardwired to audio widget */
2846
for (i = 0; i < cfg->line_outs; i++) {
2847
idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2848
spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2849
}
2850
spec->multiout.num_dacs = cfg->line_outs;
2851
return 0;
2852
}
2853
2854
/* add playback controls from the parsed DAC table */
2855
static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2856
const struct auto_pin_cfg *cfg)
2857
{
2858
char name[32];
2859
static const char * const chname[4] = {
2860
"Front", "Surround", NULL /*CLFE*/, "Side"
2861
};
2862
hda_nid_t nid;
2863
int i, err;
2864
2865
for (i = 0; i < cfg->line_outs; i++) {
2866
hda_nid_t dac = spec->multiout.dac_nids[i];
2867
if (! dac)
2868
continue;
2869
nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2870
if (i == 2) {
2871
/* Center/LFE */
2872
err = add_control(spec, AD_CTL_WIDGET_VOL,
2873
"Center Playback Volume",
2874
HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2875
if (err < 0)
2876
return err;
2877
err = add_control(spec, AD_CTL_WIDGET_VOL,
2878
"LFE Playback Volume",
2879
HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2880
if (err < 0)
2881
return err;
2882
err = add_control(spec, AD_CTL_BIND_MUTE,
2883
"Center Playback Switch",
2884
HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2885
if (err < 0)
2886
return err;
2887
err = add_control(spec, AD_CTL_BIND_MUTE,
2888
"LFE Playback Switch",
2889
HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2890
if (err < 0)
2891
return err;
2892
} else {
2893
sprintf(name, "%s Playback Volume", chname[i]);
2894
err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2895
HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2896
if (err < 0)
2897
return err;
2898
sprintf(name, "%s Playback Switch", chname[i]);
2899
err = add_control(spec, AD_CTL_BIND_MUTE, name,
2900
HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2901
if (err < 0)
2902
return err;
2903
}
2904
}
2905
return 0;
2906
}
2907
2908
/* add playback controls for speaker and HP outputs */
2909
static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2910
const char *pfx)
2911
{
2912
struct ad198x_spec *spec = codec->spec;
2913
hda_nid_t nid;
2914
int i, idx, err;
2915
char name[32];
2916
2917
if (! pin)
2918
return 0;
2919
2920
idx = ad1988_pin_idx(pin);
2921
nid = ad1988_idx_to_dac(codec, idx);
2922
/* check whether the corresponding DAC was already taken */
2923
for (i = 0; i < spec->autocfg.line_outs; i++) {
2924
hda_nid_t pin = spec->autocfg.line_out_pins[i];
2925
hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2926
if (dac == nid)
2927
break;
2928
}
2929
if (i >= spec->autocfg.line_outs) {
2930
/* specify the DAC as the extra output */
2931
if (!spec->multiout.hp_nid)
2932
spec->multiout.hp_nid = nid;
2933
else
2934
spec->multiout.extra_out_nid[0] = nid;
2935
/* control HP volume/switch on the output mixer amp */
2936
sprintf(name, "%s Playback Volume", pfx);
2937
err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2938
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2939
if (err < 0)
2940
return err;
2941
}
2942
nid = ad1988_mixer_nids[idx];
2943
sprintf(name, "%s Playback Switch", pfx);
2944
if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2945
HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2946
return err;
2947
return 0;
2948
}
2949
2950
/* create input playback/capture controls for the given pin */
2951
static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2952
const char *ctlname, int ctlidx, int boost)
2953
{
2954
char name[32];
2955
int err, idx;
2956
2957
sprintf(name, "%s Playback Volume", ctlname);
2958
idx = ad1988_pin_to_loopback_idx(pin);
2959
if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2960
HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2961
return err;
2962
sprintf(name, "%s Playback Switch", ctlname);
2963
if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2964
HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2965
return err;
2966
if (boost) {
2967
hda_nid_t bnid;
2968
idx = ad1988_pin_idx(pin);
2969
bnid = ad1988_boost_nids[idx];
2970
if (bnid) {
2971
sprintf(name, "%s Boost Volume", ctlname);
2972
return add_control(spec, AD_CTL_WIDGET_VOL, name,
2973
HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2974
2975
}
2976
}
2977
return 0;
2978
}
2979
2980
/* create playback/capture controls for input pins */
2981
static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
2982
const struct auto_pin_cfg *cfg)
2983
{
2984
struct ad198x_spec *spec = codec->spec;
2985
struct hda_input_mux *imux = &spec->private_imux;
2986
int i, err, type, type_idx;
2987
2988
for (i = 0; i < cfg->num_inputs; i++) {
2989
const char *label;
2990
type = cfg->inputs[i].type;
2991
label = hda_get_autocfg_input_label(codec, cfg, i);
2992
snd_hda_add_imux_item(imux, label,
2993
ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
2994
&type_idx);
2995
err = new_analog_input(spec, cfg->inputs[i].pin,
2996
label, type_idx,
2997
type == AUTO_PIN_MIC);
2998
if (err < 0)
2999
return err;
3000
}
3001
snd_hda_add_imux_item(imux, "Mix", 9, NULL);
3002
3003
if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
3004
"Analog Mix Playback Volume",
3005
HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3006
return err;
3007
if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
3008
"Analog Mix Playback Switch",
3009
HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3010
return err;
3011
3012
return 0;
3013
}
3014
3015
static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
3016
hda_nid_t nid, int pin_type,
3017
int dac_idx)
3018
{
3019
/* set as output */
3020
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3021
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3022
switch (nid) {
3023
case 0x11: /* port-A - DAC 04 */
3024
snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3025
break;
3026
case 0x14: /* port-B - DAC 06 */
3027
snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
3028
break;
3029
case 0x15: /* port-C - DAC 05 */
3030
snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
3031
break;
3032
case 0x17: /* port-E - DAC 0a */
3033
snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3034
break;
3035
case 0x13: /* mono - DAC 04 */
3036
snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3037
break;
3038
}
3039
}
3040
3041
static void ad1988_auto_init_multi_out(struct hda_codec *codec)
3042
{
3043
struct ad198x_spec *spec = codec->spec;
3044
int i;
3045
3046
for (i = 0; i < spec->autocfg.line_outs; i++) {
3047
hda_nid_t nid = spec->autocfg.line_out_pins[i];
3048
ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3049
}
3050
}
3051
3052
static void ad1988_auto_init_extra_out(struct hda_codec *codec)
3053
{
3054
struct ad198x_spec *spec = codec->spec;
3055
hda_nid_t pin;
3056
3057
pin = spec->autocfg.speaker_pins[0];
3058
if (pin) /* connect to front */
3059
ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
3060
pin = spec->autocfg.hp_pins[0];
3061
if (pin) /* connect to front */
3062
ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3063
}
3064
3065
static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3066
{
3067
struct ad198x_spec *spec = codec->spec;
3068
const struct auto_pin_cfg *cfg = &spec->autocfg;
3069
int i, idx;
3070
3071
for (i = 0; i < cfg->num_inputs; i++) {
3072
hda_nid_t nid = cfg->inputs[i].pin;
3073
int type = cfg->inputs[i].type;
3074
switch (nid) {
3075
case 0x15: /* port-C */
3076
snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3077
break;
3078
case 0x17: /* port-E */
3079
snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3080
break;
3081
}
3082
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3083
type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
3084
if (nid != AD1988_PIN_CD_NID)
3085
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3086
AMP_OUT_MUTE);
3087
idx = ad1988_pin_idx(nid);
3088
if (ad1988_boost_nids[idx])
3089
snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3090
AC_VERB_SET_AMP_GAIN_MUTE,
3091
AMP_OUT_ZERO);
3092
}
3093
}
3094
3095
/* parse the BIOS configuration and set up the alc_spec */
3096
/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3097
static int ad1988_parse_auto_config(struct hda_codec *codec)
3098
{
3099
struct ad198x_spec *spec = codec->spec;
3100
int err;
3101
3102
if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3103
return err;
3104
if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3105
return err;
3106
if (! spec->autocfg.line_outs)
3107
return 0; /* can't find valid BIOS pin config */
3108
if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3109
(err = ad1988_auto_create_extra_out(codec,
3110
spec->autocfg.speaker_pins[0],
3111
"Speaker")) < 0 ||
3112
(err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3113
"Headphone")) < 0 ||
3114
(err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
3115
return err;
3116
3117
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3118
3119
if (spec->autocfg.dig_outs)
3120
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3121
if (spec->autocfg.dig_in_pin)
3122
spec->dig_in_nid = AD1988_SPDIF_IN;
3123
3124
if (spec->kctls.list)
3125
spec->mixers[spec->num_mixers++] = spec->kctls.list;
3126
3127
spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3128
3129
spec->input_mux = &spec->private_imux;
3130
3131
return 1;
3132
}
3133
3134
/* init callback for auto-configuration model -- overriding the default init */
3135
static int ad1988_auto_init(struct hda_codec *codec)
3136
{
3137
ad198x_init(codec);
3138
ad1988_auto_init_multi_out(codec);
3139
ad1988_auto_init_extra_out(codec);
3140
ad1988_auto_init_analog_input(codec);
3141
return 0;
3142
}
3143
3144
/*
3145
*/
3146
3147
static const char * const ad1988_models[AD1988_MODEL_LAST] = {
3148
[AD1988_6STACK] = "6stack",
3149
[AD1988_6STACK_DIG] = "6stack-dig",
3150
[AD1988_6STACK_DIG_FP] = "6stack-dig-fp",
3151
[AD1988_3STACK] = "3stack",
3152
[AD1988_3STACK_DIG] = "3stack-dig",
3153
[AD1988_LAPTOP] = "laptop",
3154
[AD1988_LAPTOP_DIG] = "laptop-dig",
3155
[AD1988_AUTO] = "auto",
3156
};
3157
3158
static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
3159
SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3160
SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3161
SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3162
SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
3163
SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3164
{}
3165
};
3166
3167
static int patch_ad1988(struct hda_codec *codec)
3168
{
3169
struct ad198x_spec *spec;
3170
int err, board_config;
3171
3172
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3173
if (spec == NULL)
3174
return -ENOMEM;
3175
3176
codec->spec = spec;
3177
3178
if (is_rev2(codec))
3179
snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3180
3181
board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3182
ad1988_models, ad1988_cfg_tbl);
3183
if (board_config < 0) {
3184
printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3185
codec->chip_name);
3186
board_config = AD1988_AUTO;
3187
}
3188
3189
if (board_config == AD1988_AUTO) {
3190
/* automatic parse from the BIOS config */
3191
err = ad1988_parse_auto_config(codec);
3192
if (err < 0) {
3193
ad198x_free(codec);
3194
return err;
3195
} else if (! err) {
3196
printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3197
board_config = AD1988_6STACK;
3198
}
3199
}
3200
3201
err = snd_hda_attach_beep_device(codec, 0x10);
3202
if (err < 0) {
3203
ad198x_free(codec);
3204
return err;
3205
}
3206
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3207
3208
switch (board_config) {
3209
case AD1988_6STACK:
3210
case AD1988_6STACK_DIG:
3211
case AD1988_6STACK_DIG_FP:
3212
spec->multiout.max_channels = 8;
3213
spec->multiout.num_dacs = 4;
3214
if (is_rev2(codec))
3215
spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3216
else
3217
spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3218
spec->input_mux = &ad1988_6stack_capture_source;
3219
spec->num_mixers = 2;
3220
if (is_rev2(codec))
3221
spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3222
else
3223
spec->mixers[0] = ad1988_6stack_mixers1;
3224
spec->mixers[1] = ad1988_6stack_mixers2;
3225
spec->num_init_verbs = 1;
3226
spec->init_verbs[0] = ad1988_6stack_init_verbs;
3227
if (board_config == AD1988_6STACK_DIG_FP) {
3228
spec->num_mixers++;
3229
spec->mixers[2] = ad1988_6stack_fp_mixers;
3230
spec->num_init_verbs++;
3231
spec->init_verbs[1] = ad1988_6stack_fp_init_verbs;
3232
spec->slave_vols = ad1988_6stack_fp_slave_vols;
3233
spec->slave_sws = ad1988_6stack_fp_slave_sws;
3234
spec->alt_dac_nid = ad1988_alt_dac_nid;
3235
spec->stream_analog_alt_playback =
3236
&ad198x_pcm_analog_alt_playback;
3237
}
3238
if ((board_config == AD1988_6STACK_DIG) ||
3239
(board_config == AD1988_6STACK_DIG_FP)) {
3240
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3241
spec->dig_in_nid = AD1988_SPDIF_IN;
3242
}
3243
break;
3244
case AD1988_3STACK:
3245
case AD1988_3STACK_DIG:
3246
spec->multiout.max_channels = 6;
3247
spec->multiout.num_dacs = 3;
3248
if (is_rev2(codec))
3249
spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3250
else
3251
spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3252
spec->input_mux = &ad1988_6stack_capture_source;
3253
spec->channel_mode = ad1988_3stack_modes;
3254
spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3255
spec->num_mixers = 2;
3256
if (is_rev2(codec))
3257
spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3258
else
3259
spec->mixers[0] = ad1988_3stack_mixers1;
3260
spec->mixers[1] = ad1988_3stack_mixers2;
3261
spec->num_init_verbs = 1;
3262
spec->init_verbs[0] = ad1988_3stack_init_verbs;
3263
if (board_config == AD1988_3STACK_DIG)
3264
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3265
break;
3266
case AD1988_LAPTOP:
3267
case AD1988_LAPTOP_DIG:
3268
spec->multiout.max_channels = 2;
3269
spec->multiout.num_dacs = 1;
3270
spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3271
spec->input_mux = &ad1988_laptop_capture_source;
3272
spec->num_mixers = 1;
3273
spec->mixers[0] = ad1988_laptop_mixers;
3274
spec->inv_eapd = 1; /* inverted EAPD */
3275
spec->num_init_verbs = 1;
3276
spec->init_verbs[0] = ad1988_laptop_init_verbs;
3277
if (board_config == AD1988_LAPTOP_DIG)
3278
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3279
break;
3280
}
3281
3282
spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3283
spec->adc_nids = ad1988_adc_nids;
3284
spec->capsrc_nids = ad1988_capsrc_nids;
3285
spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3286
spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3287
if (spec->multiout.dig_out_nid) {
3288
if (codec->vendor_id >= 0x11d4989a) {
3289
spec->mixers[spec->num_mixers++] =
3290
ad1989_spdif_out_mixers;
3291
spec->init_verbs[spec->num_init_verbs++] =
3292
ad1989_spdif_init_verbs;
3293
codec->slave_dig_outs = ad1989b_slave_dig_outs;
3294
} else {
3295
spec->mixers[spec->num_mixers++] =
3296
ad1988_spdif_out_mixers;
3297
spec->init_verbs[spec->num_init_verbs++] =
3298
ad1988_spdif_init_verbs;
3299
}
3300
}
3301
if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3302
spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3303
spec->init_verbs[spec->num_init_verbs++] =
3304
ad1988_spdif_in_init_verbs;
3305
}
3306
3307
codec->patch_ops = ad198x_patch_ops;
3308
switch (board_config) {
3309
case AD1988_AUTO:
3310
codec->patch_ops.init = ad1988_auto_init;
3311
break;
3312
case AD1988_LAPTOP:
3313
case AD1988_LAPTOP_DIG:
3314
codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3315
break;
3316
}
3317
#ifdef CONFIG_SND_HDA_POWER_SAVE
3318
spec->loopback.amplist = ad1988_loopbacks;
3319
#endif
3320
spec->vmaster_nid = 0x04;
3321
3322
codec->no_trigger_sense = 1;
3323
codec->no_sticky_stream = 1;
3324
3325
return 0;
3326
}
3327
3328
3329
/*
3330
* AD1884 / AD1984
3331
*
3332
* port-B - front line/mic-in
3333
* port-E - aux in/out
3334
* port-F - aux in/out
3335
* port-C - rear line/mic-in
3336
* port-D - rear line/hp-out
3337
* port-A - front line/hp-out
3338
*
3339
* AD1984 = AD1884 + two digital mic-ins
3340
*
3341
* FIXME:
3342
* For simplicity, we share the single DAC for both HP and line-outs
3343
* right now. The inidividual playbacks could be easily implemented,
3344
* but no build-up framework is given, so far.
3345
*/
3346
3347
static const hda_nid_t ad1884_dac_nids[1] = {
3348
0x04,
3349
};
3350
3351
static const hda_nid_t ad1884_adc_nids[2] = {
3352
0x08, 0x09,
3353
};
3354
3355
static const hda_nid_t ad1884_capsrc_nids[2] = {
3356
0x0c, 0x0d,
3357
};
3358
3359
#define AD1884_SPDIF_OUT 0x02
3360
3361
static const struct hda_input_mux ad1884_capture_source = {
3362
.num_items = 4,
3363
.items = {
3364
{ "Front Mic", 0x0 },
3365
{ "Mic", 0x1 },
3366
{ "CD", 0x2 },
3367
{ "Mix", 0x3 },
3368
},
3369
};
3370
3371
static const struct snd_kcontrol_new ad1884_base_mixers[] = {
3372
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3373
/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3374
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3375
HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3376
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3377
HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3378
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3379
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3380
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3381
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3382
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3383
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3384
HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3385
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3386
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3387
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3388
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3389
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3390
{
3391
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3392
/* The multiple "Capture Source" controls confuse alsamixer
3393
* So call somewhat different..
3394
*/
3395
/* .name = "Capture Source", */
3396
.name = "Input Source",
3397
.count = 2,
3398
.info = ad198x_mux_enum_info,
3399
.get = ad198x_mux_enum_get,
3400
.put = ad198x_mux_enum_put,
3401
},
3402
/* SPDIF controls */
3403
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3404
{
3405
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3406
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3407
/* identical with ad1983 */
3408
.info = ad1983_spdif_route_info,
3409
.get = ad1983_spdif_route_get,
3410
.put = ad1983_spdif_route_put,
3411
},
3412
{ } /* end */
3413
};
3414
3415
static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3416
HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3417
HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3418
HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3419
HDA_INPUT),
3420
HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3421
HDA_INPUT),
3422
{ } /* end */
3423
};
3424
3425
/*
3426
* initialization verbs
3427
*/
3428
static const struct hda_verb ad1884_init_verbs[] = {
3429
/* DACs; mute as default */
3430
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3431
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3432
/* Port-A (HP) mixer */
3433
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3434
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3435
/* Port-A pin */
3436
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3437
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3438
/* HP selector - select DAC2 */
3439
{0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3440
/* Port-D (Line-out) mixer */
3441
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3442
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3443
/* Port-D pin */
3444
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3445
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3446
/* Mono-out mixer */
3447
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3448
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3449
/* Mono-out pin */
3450
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3451
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3452
/* Mono selector */
3453
{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3454
/* Port-B (front mic) pin */
3455
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3456
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3457
/* Port-C (rear mic) pin */
3458
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3459
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3460
/* Analog mixer; mute as default */
3461
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3462
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3463
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3464
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3465
/* Analog Mix output amp */
3466
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3467
/* SPDIF output selector */
3468
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3469
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3470
{ } /* end */
3471
};
3472
3473
#ifdef CONFIG_SND_HDA_POWER_SAVE
3474
static const struct hda_amp_list ad1884_loopbacks[] = {
3475
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
3476
{ 0x20, HDA_INPUT, 1 }, /* Mic */
3477
{ 0x20, HDA_INPUT, 2 }, /* CD */
3478
{ 0x20, HDA_INPUT, 4 }, /* Docking */
3479
{ } /* end */
3480
};
3481
#endif
3482
3483
static const char * const ad1884_slave_vols[] = {
3484
"PCM Playback Volume",
3485
"Mic Playback Volume",
3486
"Mono Playback Volume",
3487
"Front Mic Playback Volume",
3488
"Mic Playback Volume",
3489
"CD Playback Volume",
3490
"Internal Mic Playback Volume",
3491
"Docking Mic Playback Volume",
3492
/* "Beep Playback Volume", */
3493
"IEC958 Playback Volume",
3494
NULL
3495
};
3496
3497
static int patch_ad1884(struct hda_codec *codec)
3498
{
3499
struct ad198x_spec *spec;
3500
int err;
3501
3502
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3503
if (spec == NULL)
3504
return -ENOMEM;
3505
3506
codec->spec = spec;
3507
3508
err = snd_hda_attach_beep_device(codec, 0x10);
3509
if (err < 0) {
3510
ad198x_free(codec);
3511
return err;
3512
}
3513
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3514
3515
spec->multiout.max_channels = 2;
3516
spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3517
spec->multiout.dac_nids = ad1884_dac_nids;
3518
spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3519
spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3520
spec->adc_nids = ad1884_adc_nids;
3521
spec->capsrc_nids = ad1884_capsrc_nids;
3522
spec->input_mux = &ad1884_capture_source;
3523
spec->num_mixers = 1;
3524
spec->mixers[0] = ad1884_base_mixers;
3525
spec->num_init_verbs = 1;
3526
spec->init_verbs[0] = ad1884_init_verbs;
3527
spec->spdif_route = 0;
3528
#ifdef CONFIG_SND_HDA_POWER_SAVE
3529
spec->loopback.amplist = ad1884_loopbacks;
3530
#endif
3531
spec->vmaster_nid = 0x04;
3532
/* we need to cover all playback volumes */
3533
spec->slave_vols = ad1884_slave_vols;
3534
3535
codec->patch_ops = ad198x_patch_ops;
3536
3537
codec->no_trigger_sense = 1;
3538
codec->no_sticky_stream = 1;
3539
3540
return 0;
3541
}
3542
3543
/*
3544
* Lenovo Thinkpad T61/X61
3545
*/
3546
static const struct hda_input_mux ad1984_thinkpad_capture_source = {
3547
.num_items = 4,
3548
.items = {
3549
{ "Mic", 0x0 },
3550
{ "Internal Mic", 0x1 },
3551
{ "Mix", 0x3 },
3552
{ "Docking-Station", 0x4 },
3553
},
3554
};
3555
3556
3557
/*
3558
* Dell Precision T3400
3559
*/
3560
static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
3561
.num_items = 3,
3562
.items = {
3563
{ "Front Mic", 0x0 },
3564
{ "Line-In", 0x1 },
3565
{ "Mix", 0x3 },
3566
},
3567
};
3568
3569
3570
static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3571
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3572
/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3573
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3574
HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3575
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3576
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3577
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3578
HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3579
HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3580
HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3581
HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3582
HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3583
HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3584
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3585
HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3586
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3587
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3588
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3589
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3590
{
3591
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3592
/* The multiple "Capture Source" controls confuse alsamixer
3593
* So call somewhat different..
3594
*/
3595
/* .name = "Capture Source", */
3596
.name = "Input Source",
3597
.count = 2,
3598
.info = ad198x_mux_enum_info,
3599
.get = ad198x_mux_enum_get,
3600
.put = ad198x_mux_enum_put,
3601
},
3602
/* SPDIF controls */
3603
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3604
{
3605
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3606
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3607
/* identical with ad1983 */
3608
.info = ad1983_spdif_route_info,
3609
.get = ad1983_spdif_route_get,
3610
.put = ad1983_spdif_route_put,
3611
},
3612
{ } /* end */
3613
};
3614
3615
/* additional verbs */
3616
static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
3617
/* Port-E (docking station mic) pin */
3618
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3619
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3620
/* docking mic boost */
3621
{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3622
/* Analog PC Beeper - allow firmware/ACPI beeps */
3623
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3624
/* Analog mixer - docking mic; mute as default */
3625
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3626
/* enable EAPD bit */
3627
{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3628
{ } /* end */
3629
};
3630
3631
/*
3632
* Dell Precision T3400
3633
*/
3634
static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3635
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3636
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3637
HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3638
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3639
HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3640
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3641
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3642
HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3643
HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3644
HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
3645
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3646
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3647
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3648
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3649
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3650
{
3651
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3652
/* The multiple "Capture Source" controls confuse alsamixer
3653
* So call somewhat different..
3654
*/
3655
/* .name = "Capture Source", */
3656
.name = "Input Source",
3657
.count = 2,
3658
.info = ad198x_mux_enum_info,
3659
.get = ad198x_mux_enum_get,
3660
.put = ad198x_mux_enum_put,
3661
},
3662
{ } /* end */
3663
};
3664
3665
/* Digial MIC ADC NID 0x05 + 0x06 */
3666
static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3667
struct hda_codec *codec,
3668
unsigned int stream_tag,
3669
unsigned int format,
3670
struct snd_pcm_substream *substream)
3671
{
3672
snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3673
stream_tag, 0, format);
3674
return 0;
3675
}
3676
3677
static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3678
struct hda_codec *codec,
3679
struct snd_pcm_substream *substream)
3680
{
3681
snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3682
return 0;
3683
}
3684
3685
static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3686
.substreams = 2,
3687
.channels_min = 2,
3688
.channels_max = 2,
3689
.nid = 0x05,
3690
.ops = {
3691
.prepare = ad1984_pcm_dmic_prepare,
3692
.cleanup = ad1984_pcm_dmic_cleanup
3693
},
3694
};
3695
3696
static int ad1984_build_pcms(struct hda_codec *codec)
3697
{
3698
struct ad198x_spec *spec = codec->spec;
3699
struct hda_pcm *info;
3700
int err;
3701
3702
err = ad198x_build_pcms(codec);
3703
if (err < 0)
3704
return err;
3705
3706
info = spec->pcm_rec + codec->num_pcms;
3707
codec->num_pcms++;
3708
info->name = "AD1984 Digital Mic";
3709
info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3710
return 0;
3711
}
3712
3713
/* models */
3714
enum {
3715
AD1984_BASIC,
3716
AD1984_THINKPAD,
3717
AD1984_DELL_DESKTOP,
3718
AD1984_MODELS
3719
};
3720
3721
static const char * const ad1984_models[AD1984_MODELS] = {
3722
[AD1984_BASIC] = "basic",
3723
[AD1984_THINKPAD] = "thinkpad",
3724
[AD1984_DELL_DESKTOP] = "dell_desktop",
3725
};
3726
3727
static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
3728
/* Lenovo Thinkpad T61/X61 */
3729
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3730
SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3731
SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
3732
{}
3733
};
3734
3735
static int patch_ad1984(struct hda_codec *codec)
3736
{
3737
struct ad198x_spec *spec;
3738
int board_config, err;
3739
3740
err = patch_ad1884(codec);
3741
if (err < 0)
3742
return err;
3743
spec = codec->spec;
3744
board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3745
ad1984_models, ad1984_cfg_tbl);
3746
switch (board_config) {
3747
case AD1984_BASIC:
3748
/* additional digital mics */
3749
spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3750
codec->patch_ops.build_pcms = ad1984_build_pcms;
3751
break;
3752
case AD1984_THINKPAD:
3753
if (codec->subsystem_id == 0x17aa20fb) {
3754
/* Thinpad X300 does not have the ability to do SPDIF,
3755
or attach to docking station to use SPDIF */
3756
spec->multiout.dig_out_nid = 0;
3757
} else
3758
spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3759
spec->input_mux = &ad1984_thinkpad_capture_source;
3760
spec->mixers[0] = ad1984_thinkpad_mixers;
3761
spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3762
spec->analog_beep = 1;
3763
break;
3764
case AD1984_DELL_DESKTOP:
3765
spec->multiout.dig_out_nid = 0;
3766
spec->input_mux = &ad1984_dell_desktop_capture_source;
3767
spec->mixers[0] = ad1984_dell_desktop_mixers;
3768
break;
3769
}
3770
return 0;
3771
}
3772
3773
3774
/*
3775
* AD1883 / AD1884A / AD1984A / AD1984B
3776
*
3777
* port-B (0x14) - front mic-in
3778
* port-E (0x1c) - rear mic-in
3779
* port-F (0x16) - CD / ext out
3780
* port-C (0x15) - rear line-in
3781
* port-D (0x12) - rear line-out
3782
* port-A (0x11) - front hp-out
3783
*
3784
* AD1984A = AD1884A + digital-mic
3785
* AD1883 = equivalent with AD1984A
3786
* AD1984B = AD1984A + extra SPDIF-out
3787
*
3788
* FIXME:
3789
* We share the single DAC for both HP and line-outs (see AD1884/1984).
3790
*/
3791
3792
static const hda_nid_t ad1884a_dac_nids[1] = {
3793
0x03,
3794
};
3795
3796
#define ad1884a_adc_nids ad1884_adc_nids
3797
#define ad1884a_capsrc_nids ad1884_capsrc_nids
3798
3799
#define AD1884A_SPDIF_OUT 0x02
3800
3801
static const struct hda_input_mux ad1884a_capture_source = {
3802
.num_items = 5,
3803
.items = {
3804
{ "Front Mic", 0x0 },
3805
{ "Mic", 0x4 },
3806
{ "Line", 0x1 },
3807
{ "CD", 0x2 },
3808
{ "Mix", 0x3 },
3809
},
3810
};
3811
3812
static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
3813
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3814
HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3815
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3816
HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3817
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3818
HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3819
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3820
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3821
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3822
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3823
HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3824
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3825
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3826
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3827
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3828
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3829
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3830
HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
3831
HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3832
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3833
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3834
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3835
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3836
{
3837
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3838
/* The multiple "Capture Source" controls confuse alsamixer
3839
* So call somewhat different..
3840
*/
3841
/* .name = "Capture Source", */
3842
.name = "Input Source",
3843
.count = 2,
3844
.info = ad198x_mux_enum_info,
3845
.get = ad198x_mux_enum_get,
3846
.put = ad198x_mux_enum_put,
3847
},
3848
/* SPDIF controls */
3849
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3850
{
3851
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3852
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3853
/* identical with ad1983 */
3854
.info = ad1983_spdif_route_info,
3855
.get = ad1983_spdif_route_get,
3856
.put = ad1983_spdif_route_put,
3857
},
3858
{ } /* end */
3859
};
3860
3861
/*
3862
* initialization verbs
3863
*/
3864
static const struct hda_verb ad1884a_init_verbs[] = {
3865
/* DACs; unmute as default */
3866
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3867
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3868
/* Port-A (HP) mixer - route only from analog mixer */
3869
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3870
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3871
/* Port-A pin */
3872
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3873
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3874
/* Port-D (Line-out) mixer - route only from analog mixer */
3875
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3876
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3877
/* Port-D pin */
3878
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3879
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3880
/* Mono-out mixer - route only from analog mixer */
3881
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3882
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3883
/* Mono-out pin */
3884
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3885
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3886
/* Port-B (front mic) pin */
3887
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3888
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3889
/* Port-C (rear line-in) pin */
3890
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3891
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3892
/* Port-E (rear mic) pin */
3893
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3894
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3895
{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3896
/* Port-F (CD) pin */
3897
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3898
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3899
/* Analog mixer; mute as default */
3900
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3901
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3902
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3903
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3904
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3905
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3906
/* Analog Mix output amp */
3907
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3908
/* capture sources */
3909
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3910
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3911
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3912
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3913
/* SPDIF output amp */
3914
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3915
{ } /* end */
3916
};
3917
3918
#ifdef CONFIG_SND_HDA_POWER_SAVE
3919
static const struct hda_amp_list ad1884a_loopbacks[] = {
3920
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
3921
{ 0x20, HDA_INPUT, 1 }, /* Mic */
3922
{ 0x20, HDA_INPUT, 2 }, /* CD */
3923
{ 0x20, HDA_INPUT, 4 }, /* Docking */
3924
{ } /* end */
3925
};
3926
#endif
3927
3928
/*
3929
* Laptop model
3930
*
3931
* Port A: Headphone jack
3932
* Port B: MIC jack
3933
* Port C: Internal MIC
3934
* Port D: Dock Line Out (if enabled)
3935
* Port E: Dock Line In (if enabled)
3936
* Port F: Internal speakers
3937
*/
3938
3939
static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3940
struct snd_ctl_elem_value *ucontrol)
3941
{
3942
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3943
int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3944
int mute = (!ucontrol->value.integer.value[0] &&
3945
!ucontrol->value.integer.value[1]);
3946
/* toggle GPIO1 according to the mute state */
3947
snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3948
mute ? 0x02 : 0x0);
3949
return ret;
3950
}
3951
3952
static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3953
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3954
{
3955
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3956
.name = "Master Playback Switch",
3957
.subdevice = HDA_SUBDEV_AMP_FLAG,
3958
.info = snd_hda_mixer_amp_switch_info,
3959
.get = snd_hda_mixer_amp_switch_get,
3960
.put = ad1884a_mobile_master_sw_put,
3961
.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3962
},
3963
HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3964
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3965
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3966
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3967
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3968
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3969
HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3970
HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3971
HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3972
HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3973
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3974
HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3975
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3976
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3977
{ } /* end */
3978
};
3979
3980
static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3981
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3982
/*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3983
{
3984
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3985
.name = "Master Playback Switch",
3986
.subdevice = HDA_SUBDEV_AMP_FLAG,
3987
.info = snd_hda_mixer_amp_switch_info,
3988
.get = snd_hda_mixer_amp_switch_get,
3989
.put = ad1884a_mobile_master_sw_put,
3990
.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3991
},
3992
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3993
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3994
HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3995
HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3996
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3997
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3998
{ } /* end */
3999
};
4000
4001
/* mute internal speaker if HP is plugged */
4002
static void ad1884a_hp_automute(struct hda_codec *codec)
4003
{
4004
unsigned int present;
4005
4006
present = snd_hda_jack_detect(codec, 0x11);
4007
snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4008
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4009
snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4010
present ? 0x00 : 0x02);
4011
}
4012
4013
/* switch to external mic if plugged */
4014
static void ad1884a_hp_automic(struct hda_codec *codec)
4015
{
4016
unsigned int present;
4017
4018
present = snd_hda_jack_detect(codec, 0x14);
4019
snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
4020
present ? 0 : 1);
4021
}
4022
4023
#define AD1884A_HP_EVENT 0x37
4024
#define AD1884A_MIC_EVENT 0x36
4025
4026
/* unsolicited event for HP jack sensing */
4027
static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4028
{
4029
switch (res >> 26) {
4030
case AD1884A_HP_EVENT:
4031
ad1884a_hp_automute(codec);
4032
break;
4033
case AD1884A_MIC_EVENT:
4034
ad1884a_hp_automic(codec);
4035
break;
4036
}
4037
}
4038
4039
/* initialize jack-sensing, too */
4040
static int ad1884a_hp_init(struct hda_codec *codec)
4041
{
4042
ad198x_init(codec);
4043
ad1884a_hp_automute(codec);
4044
ad1884a_hp_automic(codec);
4045
return 0;
4046
}
4047
4048
/* mute internal speaker if HP or docking HP is plugged */
4049
static void ad1884a_laptop_automute(struct hda_codec *codec)
4050
{
4051
unsigned int present;
4052
4053
present = snd_hda_jack_detect(codec, 0x11);
4054
if (!present)
4055
present = snd_hda_jack_detect(codec, 0x12);
4056
snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4057
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4058
snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4059
present ? 0x00 : 0x02);
4060
}
4061
4062
/* switch to external mic if plugged */
4063
static void ad1884a_laptop_automic(struct hda_codec *codec)
4064
{
4065
unsigned int idx;
4066
4067
if (snd_hda_jack_detect(codec, 0x14))
4068
idx = 0;
4069
else if (snd_hda_jack_detect(codec, 0x1c))
4070
idx = 4;
4071
else
4072
idx = 1;
4073
snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
4074
}
4075
4076
/* unsolicited event for HP jack sensing */
4077
static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
4078
unsigned int res)
4079
{
4080
switch (res >> 26) {
4081
case AD1884A_HP_EVENT:
4082
ad1884a_laptop_automute(codec);
4083
break;
4084
case AD1884A_MIC_EVENT:
4085
ad1884a_laptop_automic(codec);
4086
break;
4087
}
4088
}
4089
4090
/* initialize jack-sensing, too */
4091
static int ad1884a_laptop_init(struct hda_codec *codec)
4092
{
4093
ad198x_init(codec);
4094
ad1884a_laptop_automute(codec);
4095
ad1884a_laptop_automic(codec);
4096
return 0;
4097
}
4098
4099
/* additional verbs for laptop model */
4100
static const struct hda_verb ad1884a_laptop_verbs[] = {
4101
/* Port-A (HP) pin - always unmuted */
4102
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4103
/* Port-F (int speaker) mixer - route only from analog mixer */
4104
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4105
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4106
/* Port-F (int speaker) pin */
4107
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4108
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4109
/* required for compaq 6530s/6531s speaker output */
4110
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4111
/* Port-C pin - internal mic-in */
4112
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4113
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4114
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4115
/* Port-D (docking line-out) pin - default unmuted */
4116
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4117
/* analog mix */
4118
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4119
/* unsolicited event for pin-sense */
4120
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4121
{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4122
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4123
{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4124
/* allow to touch GPIO1 (for mute control) */
4125
{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4126
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4127
{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4128
{ } /* end */
4129
};
4130
4131
static const struct hda_verb ad1884a_mobile_verbs[] = {
4132
/* DACs; unmute as default */
4133
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4134
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4135
/* Port-A (HP) mixer - route only from analog mixer */
4136
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4137
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4138
/* Port-A pin */
4139
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4140
/* Port-A (HP) pin - always unmuted */
4141
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4142
/* Port-B (mic jack) pin */
4143
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4144
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4145
/* Port-C (int mic) pin */
4146
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4147
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4148
/* Port-F (int speaker) mixer - route only from analog mixer */
4149
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4150
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4151
/* Port-F pin */
4152
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4153
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4154
/* Analog mixer; mute as default */
4155
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4156
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4157
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4158
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4159
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4160
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4161
/* Analog Mix output amp */
4162
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4163
/* capture sources */
4164
/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4165
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4166
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4167
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4168
/* unsolicited event for pin-sense */
4169
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4170
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4171
/* allow to touch GPIO1 (for mute control) */
4172
{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4173
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4174
{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4175
{ } /* end */
4176
};
4177
4178
/*
4179
* Thinkpad X300
4180
* 0x11 - HP
4181
* 0x12 - speaker
4182
* 0x14 - mic-in
4183
* 0x17 - built-in mic
4184
*/
4185
4186
static const struct hda_verb ad1984a_thinkpad_verbs[] = {
4187
/* HP unmute */
4188
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4189
/* analog mix */
4190
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4191
/* turn on EAPD */
4192
{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4193
/* unsolicited event for pin-sense */
4194
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4195
/* internal mic - dmic */
4196
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4197
/* set magic COEFs for dmic */
4198
{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4199
{0x01, AC_VERB_SET_PROC_COEF, 0x08},
4200
{ } /* end */
4201
};
4202
4203
static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4204
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4205
HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4206
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4207
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4208
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4209
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4210
HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4211
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4212
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4213
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4214
{
4215
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4216
.name = "Capture Source",
4217
.info = ad198x_mux_enum_info,
4218
.get = ad198x_mux_enum_get,
4219
.put = ad198x_mux_enum_put,
4220
},
4221
{ } /* end */
4222
};
4223
4224
static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
4225
.num_items = 3,
4226
.items = {
4227
{ "Mic", 0x0 },
4228
{ "Internal Mic", 0x5 },
4229
{ "Mix", 0x3 },
4230
},
4231
};
4232
4233
/* mute internal speaker if HP is plugged */
4234
static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4235
{
4236
unsigned int present;
4237
4238
present = snd_hda_jack_detect(codec, 0x11);
4239
snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4240
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4241
}
4242
4243
/* unsolicited event for HP jack sensing */
4244
static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4245
unsigned int res)
4246
{
4247
if ((res >> 26) != AD1884A_HP_EVENT)
4248
return;
4249
ad1984a_thinkpad_automute(codec);
4250
}
4251
4252
/* initialize jack-sensing, too */
4253
static int ad1984a_thinkpad_init(struct hda_codec *codec)
4254
{
4255
ad198x_init(codec);
4256
ad1984a_thinkpad_automute(codec);
4257
return 0;
4258
}
4259
4260
/*
4261
* Precision R5500
4262
* 0x12 - HP/line-out
4263
* 0x13 - speaker (mono)
4264
* 0x15 - mic-in
4265
*/
4266
4267
static const struct hda_verb ad1984a_precision_verbs[] = {
4268
/* Unmute main output path */
4269
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4270
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
4271
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4272
/* Analog mixer; mute as default */
4273
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4274
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4275
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4276
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4277
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4278
/* Select mic as input */
4279
{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
4280
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
4281
/* Configure as mic */
4282
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4283
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4284
/* HP unmute */
4285
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4286
/* turn on EAPD */
4287
{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4288
/* unsolicited event for pin-sense */
4289
{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4290
{ } /* end */
4291
};
4292
4293
static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
4294
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4295
HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4296
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4297
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4298
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4299
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4300
HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4301
HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4302
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
4303
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4304
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4305
{ } /* end */
4306
};
4307
4308
4309
/* mute internal speaker if HP is plugged */
4310
static void ad1984a_precision_automute(struct hda_codec *codec)
4311
{
4312
unsigned int present;
4313
4314
present = snd_hda_jack_detect(codec, 0x12);
4315
snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
4316
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4317
}
4318
4319
4320
/* unsolicited event for HP jack sensing */
4321
static void ad1984a_precision_unsol_event(struct hda_codec *codec,
4322
unsigned int res)
4323
{
4324
if ((res >> 26) != AD1884A_HP_EVENT)
4325
return;
4326
ad1984a_precision_automute(codec);
4327
}
4328
4329
/* initialize jack-sensing, too */
4330
static int ad1984a_precision_init(struct hda_codec *codec)
4331
{
4332
ad198x_init(codec);
4333
ad1984a_precision_automute(codec);
4334
return 0;
4335
}
4336
4337
4338
/*
4339
* HP Touchsmart
4340
* port-A (0x11) - front hp-out
4341
* port-B (0x14) - unused
4342
* port-C (0x15) - unused
4343
* port-D (0x12) - rear line out
4344
* port-E (0x1c) - front mic-in
4345
* port-F (0x16) - Internal speakers
4346
* digital-mic (0x17) - Internal mic
4347
*/
4348
4349
static const struct hda_verb ad1984a_touchsmart_verbs[] = {
4350
/* DACs; unmute as default */
4351
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4352
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4353
/* Port-A (HP) mixer - route only from analog mixer */
4354
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4355
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4356
/* Port-A pin */
4357
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4358
/* Port-A (HP) pin - always unmuted */
4359
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4360
/* Port-E (int speaker) mixer - route only from analog mixer */
4361
{0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4362
/* Port-E pin */
4363
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4364
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4365
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4366
/* Port-F (int speaker) mixer - route only from analog mixer */
4367
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4368
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4369
/* Port-F pin */
4370
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4371
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4372
/* Analog mixer; mute as default */
4373
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4374
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4375
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4376
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4377
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4378
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4379
/* Analog Mix output amp */
4380
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4381
/* capture sources */
4382
/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4383
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4384
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4385
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4386
/* unsolicited event for pin-sense */
4387
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4388
{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4389
/* allow to touch GPIO1 (for mute control) */
4390
{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4391
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4392
{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4393
/* internal mic - dmic */
4394
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4395
/* set magic COEFs for dmic */
4396
{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4397
{0x01, AC_VERB_SET_PROC_COEF, 0x08},
4398
{ } /* end */
4399
};
4400
4401
static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4402
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4403
/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4404
{
4405
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4406
.subdevice = HDA_SUBDEV_AMP_FLAG,
4407
.name = "Master Playback Switch",
4408
.info = snd_hda_mixer_amp_switch_info,
4409
.get = snd_hda_mixer_amp_switch_get,
4410
.put = ad1884a_mobile_master_sw_put,
4411
.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4412
},
4413
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4414
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4415
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4416
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4417
HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4418
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4419
{ } /* end */
4420
};
4421
4422
/* switch to external mic if plugged */
4423
static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4424
{
4425
if (snd_hda_jack_detect(codec, 0x1c))
4426
snd_hda_codec_write(codec, 0x0c, 0,
4427
AC_VERB_SET_CONNECT_SEL, 0x4);
4428
else
4429
snd_hda_codec_write(codec, 0x0c, 0,
4430
AC_VERB_SET_CONNECT_SEL, 0x5);
4431
}
4432
4433
4434
/* unsolicited event for HP jack sensing */
4435
static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4436
unsigned int res)
4437
{
4438
switch (res >> 26) {
4439
case AD1884A_HP_EVENT:
4440
ad1884a_hp_automute(codec);
4441
break;
4442
case AD1884A_MIC_EVENT:
4443
ad1984a_touchsmart_automic(codec);
4444
break;
4445
}
4446
}
4447
4448
/* initialize jack-sensing, too */
4449
static int ad1984a_touchsmart_init(struct hda_codec *codec)
4450
{
4451
ad198x_init(codec);
4452
ad1884a_hp_automute(codec);
4453
ad1984a_touchsmart_automic(codec);
4454
return 0;
4455
}
4456
4457
4458
/*
4459
*/
4460
4461
enum {
4462
AD1884A_DESKTOP,
4463
AD1884A_LAPTOP,
4464
AD1884A_MOBILE,
4465
AD1884A_THINKPAD,
4466
AD1984A_TOUCHSMART,
4467
AD1984A_PRECISION,
4468
AD1884A_MODELS
4469
};
4470
4471
static const char * const ad1884a_models[AD1884A_MODELS] = {
4472
[AD1884A_DESKTOP] = "desktop",
4473
[AD1884A_LAPTOP] = "laptop",
4474
[AD1884A_MOBILE] = "mobile",
4475
[AD1884A_THINKPAD] = "thinkpad",
4476
[AD1984A_TOUCHSMART] = "touchsmart",
4477
[AD1984A_PRECISION] = "precision",
4478
};
4479
4480
static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4481
SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
4482
SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4483
SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4484
SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4485
SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4486
SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4487
SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4488
SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4489
SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4490
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4491
SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4492
{}
4493
};
4494
4495
static int patch_ad1884a(struct hda_codec *codec)
4496
{
4497
struct ad198x_spec *spec;
4498
int err, board_config;
4499
4500
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4501
if (spec == NULL)
4502
return -ENOMEM;
4503
4504
codec->spec = spec;
4505
4506
err = snd_hda_attach_beep_device(codec, 0x10);
4507
if (err < 0) {
4508
ad198x_free(codec);
4509
return err;
4510
}
4511
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4512
4513
spec->multiout.max_channels = 2;
4514
spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4515
spec->multiout.dac_nids = ad1884a_dac_nids;
4516
spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4517
spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4518
spec->adc_nids = ad1884a_adc_nids;
4519
spec->capsrc_nids = ad1884a_capsrc_nids;
4520
spec->input_mux = &ad1884a_capture_source;
4521
spec->num_mixers = 1;
4522
spec->mixers[0] = ad1884a_base_mixers;
4523
spec->num_init_verbs = 1;
4524
spec->init_verbs[0] = ad1884a_init_verbs;
4525
spec->spdif_route = 0;
4526
#ifdef CONFIG_SND_HDA_POWER_SAVE
4527
spec->loopback.amplist = ad1884a_loopbacks;
4528
#endif
4529
codec->patch_ops = ad198x_patch_ops;
4530
4531
/* override some parameters */
4532
board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4533
ad1884a_models,
4534
ad1884a_cfg_tbl);
4535
switch (board_config) {
4536
case AD1884A_LAPTOP:
4537
spec->mixers[0] = ad1884a_laptop_mixers;
4538
spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4539
spec->multiout.dig_out_nid = 0;
4540
codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4541
codec->patch_ops.init = ad1884a_laptop_init;
4542
/* set the upper-limit for mixer amp to 0dB for avoiding the
4543
* possible damage by overloading
4544
*/
4545
snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4546
(0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4547
(0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4548
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4549
(1 << AC_AMPCAP_MUTE_SHIFT));
4550
break;
4551
case AD1884A_MOBILE:
4552
spec->mixers[0] = ad1884a_mobile_mixers;
4553
spec->init_verbs[0] = ad1884a_mobile_verbs;
4554
spec->multiout.dig_out_nid = 0;
4555
codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4556
codec->patch_ops.init = ad1884a_hp_init;
4557
/* set the upper-limit for mixer amp to 0dB for avoiding the
4558
* possible damage by overloading
4559
*/
4560
snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4561
(0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4562
(0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4563
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4564
(1 << AC_AMPCAP_MUTE_SHIFT));
4565
break;
4566
case AD1884A_THINKPAD:
4567
spec->mixers[0] = ad1984a_thinkpad_mixers;
4568
spec->init_verbs[spec->num_init_verbs++] =
4569
ad1984a_thinkpad_verbs;
4570
spec->multiout.dig_out_nid = 0;
4571
spec->input_mux = &ad1984a_thinkpad_capture_source;
4572
codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4573
codec->patch_ops.init = ad1984a_thinkpad_init;
4574
break;
4575
case AD1984A_PRECISION:
4576
spec->mixers[0] = ad1984a_precision_mixers;
4577
spec->init_verbs[spec->num_init_verbs++] =
4578
ad1984a_precision_verbs;
4579
spec->multiout.dig_out_nid = 0;
4580
codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
4581
codec->patch_ops.init = ad1984a_precision_init;
4582
break;
4583
case AD1984A_TOUCHSMART:
4584
spec->mixers[0] = ad1984a_touchsmart_mixers;
4585
spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4586
spec->multiout.dig_out_nid = 0;
4587
codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4588
codec->patch_ops.init = ad1984a_touchsmart_init;
4589
/* set the upper-limit for mixer amp to 0dB for avoiding the
4590
* possible damage by overloading
4591
*/
4592
snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4593
(0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4594
(0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4595
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4596
(1 << AC_AMPCAP_MUTE_SHIFT));
4597
break;
4598
}
4599
4600
codec->no_trigger_sense = 1;
4601
codec->no_sticky_stream = 1;
4602
4603
return 0;
4604
}
4605
4606
4607
/*
4608
* AD1882 / AD1882A
4609
*
4610
* port-A - front hp-out
4611
* port-B - front mic-in
4612
* port-C - rear line-in, shared surr-out (3stack)
4613
* port-D - rear line-out
4614
* port-E - rear mic-in, shared clfe-out (3stack)
4615
* port-F - rear surr-out (6stack)
4616
* port-G - rear clfe-out (6stack)
4617
*/
4618
4619
static const hda_nid_t ad1882_dac_nids[3] = {
4620
0x04, 0x03, 0x05
4621
};
4622
4623
static const hda_nid_t ad1882_adc_nids[2] = {
4624
0x08, 0x09,
4625
};
4626
4627
static const hda_nid_t ad1882_capsrc_nids[2] = {
4628
0x0c, 0x0d,
4629
};
4630
4631
#define AD1882_SPDIF_OUT 0x02
4632
4633
/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4634
static const struct hda_input_mux ad1882_capture_source = {
4635
.num_items = 5,
4636
.items = {
4637
{ "Front Mic", 0x1 },
4638
{ "Mic", 0x4 },
4639
{ "Line", 0x2 },
4640
{ "CD", 0x3 },
4641
{ "Mix", 0x7 },
4642
},
4643
};
4644
4645
/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4646
static const struct hda_input_mux ad1882a_capture_source = {
4647
.num_items = 5,
4648
.items = {
4649
{ "Front Mic", 0x1 },
4650
{ "Mic", 0x4},
4651
{ "Line", 0x2 },
4652
{ "Digital Mic", 0x06 },
4653
{ "Mix", 0x7 },
4654
},
4655
};
4656
4657
static const struct snd_kcontrol_new ad1882_base_mixers[] = {
4658
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4659
HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4660
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4661
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4662
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4663
HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4664
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4665
HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4666
4667
HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
4668
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
4669
HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT),
4670
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4671
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4672
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4673
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4674
{
4675
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4676
/* The multiple "Capture Source" controls confuse alsamixer
4677
* So call somewhat different..
4678
*/
4679
/* .name = "Capture Source", */
4680
.name = "Input Source",
4681
.count = 2,
4682
.info = ad198x_mux_enum_info,
4683
.get = ad198x_mux_enum_get,
4684
.put = ad198x_mux_enum_put,
4685
},
4686
/* SPDIF controls */
4687
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4688
{
4689
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4690
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4691
/* identical with ad1983 */
4692
.info = ad1983_spdif_route_info,
4693
.get = ad1983_spdif_route_get,
4694
.put = ad1983_spdif_route_put,
4695
},
4696
{ } /* end */
4697
};
4698
4699
static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4700
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4701
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4702
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4703
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4704
HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4705
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4706
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4707
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4708
{ } /* end */
4709
};
4710
4711
static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4712
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4713
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4714
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4715
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4716
HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4717
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4718
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4719
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4720
HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT),
4721
{ } /* end */
4722
};
4723
4724
static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4725
HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4726
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4727
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4728
{
4729
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4730
.name = "Channel Mode",
4731
.info = ad198x_ch_mode_info,
4732
.get = ad198x_ch_mode_get,
4733
.put = ad198x_ch_mode_put,
4734
},
4735
{ } /* end */
4736
};
4737
4738
static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4739
HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4740
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4741
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4742
{ } /* end */
4743
};
4744
4745
static const struct hda_verb ad1882_ch2_init[] = {
4746
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4747
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4748
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4749
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4750
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4751
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4752
{ } /* end */
4753
};
4754
4755
static const struct hda_verb ad1882_ch4_init[] = {
4756
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4757
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4758
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4759
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4760
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4761
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4762
{ } /* end */
4763
};
4764
4765
static const struct hda_verb ad1882_ch6_init[] = {
4766
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4767
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4768
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4769
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4770
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4771
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4772
{ } /* end */
4773
};
4774
4775
static const struct hda_channel_mode ad1882_modes[3] = {
4776
{ 2, ad1882_ch2_init },
4777
{ 4, ad1882_ch4_init },
4778
{ 6, ad1882_ch6_init },
4779
};
4780
4781
/*
4782
* initialization verbs
4783
*/
4784
static const struct hda_verb ad1882_init_verbs[] = {
4785
/* DACs; mute as default */
4786
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4787
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4788
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4789
/* Port-A (HP) mixer */
4790
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4791
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4792
/* Port-A pin */
4793
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4794
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4795
/* HP selector - select DAC2 */
4796
{0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4797
/* Port-D (Line-out) mixer */
4798
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4799
{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4800
/* Port-D pin */
4801
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4802
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4803
/* Mono-out mixer */
4804
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4805
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4806
/* Mono-out pin */
4807
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4808
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4809
/* Port-B (front mic) pin */
4810
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4811
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4812
{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4813
/* Port-C (line-in) pin */
4814
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4815
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4816
{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4817
/* Port-C mixer - mute as input */
4818
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4819
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4820
/* Port-E (mic-in) pin */
4821
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4822
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4823
{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4824
/* Port-E mixer - mute as input */
4825
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4826
{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4827
/* Port-F (surround) */
4828
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4829
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4830
/* Port-G (CLFE) */
4831
{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4832
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4833
/* Analog mixer; mute as default */
4834
/* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4835
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4836
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4837
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4838
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4839
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4840
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4841
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4842
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4843
/* Analog Mix output amp */
4844
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4845
/* SPDIF output selector */
4846
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4847
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4848
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4849
{ } /* end */
4850
};
4851
4852
#ifdef CONFIG_SND_HDA_POWER_SAVE
4853
static const struct hda_amp_list ad1882_loopbacks[] = {
4854
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
4855
{ 0x20, HDA_INPUT, 1 }, /* Mic */
4856
{ 0x20, HDA_INPUT, 4 }, /* Line */
4857
{ 0x20, HDA_INPUT, 6 }, /* CD */
4858
{ } /* end */
4859
};
4860
#endif
4861
4862
/* models */
4863
enum {
4864
AD1882_3STACK,
4865
AD1882_6STACK,
4866
AD1882_MODELS
4867
};
4868
4869
static const char * const ad1882_models[AD1986A_MODELS] = {
4870
[AD1882_3STACK] = "3stack",
4871
[AD1882_6STACK] = "6stack",
4872
};
4873
4874
4875
static int patch_ad1882(struct hda_codec *codec)
4876
{
4877
struct ad198x_spec *spec;
4878
int err, board_config;
4879
4880
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4881
if (spec == NULL)
4882
return -ENOMEM;
4883
4884
codec->spec = spec;
4885
4886
err = snd_hda_attach_beep_device(codec, 0x10);
4887
if (err < 0) {
4888
ad198x_free(codec);
4889
return err;
4890
}
4891
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4892
4893
spec->multiout.max_channels = 6;
4894
spec->multiout.num_dacs = 3;
4895
spec->multiout.dac_nids = ad1882_dac_nids;
4896
spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4897
spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4898
spec->adc_nids = ad1882_adc_nids;
4899
spec->capsrc_nids = ad1882_capsrc_nids;
4900
if (codec->vendor_id == 0x11d41882)
4901
spec->input_mux = &ad1882_capture_source;
4902
else
4903
spec->input_mux = &ad1882a_capture_source;
4904
spec->num_mixers = 2;
4905
spec->mixers[0] = ad1882_base_mixers;
4906
if (codec->vendor_id == 0x11d41882)
4907
spec->mixers[1] = ad1882_loopback_mixers;
4908
else
4909
spec->mixers[1] = ad1882a_loopback_mixers;
4910
spec->num_init_verbs = 1;
4911
spec->init_verbs[0] = ad1882_init_verbs;
4912
spec->spdif_route = 0;
4913
#ifdef CONFIG_SND_HDA_POWER_SAVE
4914
spec->loopback.amplist = ad1882_loopbacks;
4915
#endif
4916
spec->vmaster_nid = 0x04;
4917
4918
codec->patch_ops = ad198x_patch_ops;
4919
4920
/* override some parameters */
4921
board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4922
ad1882_models, NULL);
4923
switch (board_config) {
4924
default:
4925
case AD1882_3STACK:
4926
spec->num_mixers = 3;
4927
spec->mixers[2] = ad1882_3stack_mixers;
4928
spec->channel_mode = ad1882_modes;
4929
spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4930
spec->need_dac_fix = 1;
4931
spec->multiout.max_channels = 2;
4932
spec->multiout.num_dacs = 1;
4933
break;
4934
case AD1882_6STACK:
4935
spec->num_mixers = 3;
4936
spec->mixers[2] = ad1882_6stack_mixers;
4937
break;
4938
}
4939
4940
codec->no_trigger_sense = 1;
4941
codec->no_sticky_stream = 1;
4942
4943
return 0;
4944
}
4945
4946
4947
/*
4948
* patch entries
4949
*/
4950
static const struct hda_codec_preset snd_hda_preset_analog[] = {
4951
{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4952
{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4953
{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4954
{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4955
{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4956
{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4957
{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4958
{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4959
{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4960
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4961
{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4962
{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4963
{ .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4964
{ .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4965
{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4966
{} /* terminator */
4967
};
4968
4969
MODULE_ALIAS("snd-hda-codec-id:11d4*");
4970
4971
MODULE_LICENSE("GPL");
4972
MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4973
4974
static struct hda_codec_preset_list analog_list = {
4975
.preset = snd_hda_preset_analog,
4976
.owner = THIS_MODULE,
4977
};
4978
4979
static int __init patch_analog_init(void)
4980
{
4981
return snd_hda_add_codec_preset(&analog_list);
4982
}
4983
4984
static void __exit patch_analog_exit(void)
4985
{
4986
snd_hda_delete_codec_preset(&analog_list);
4987
}
4988
4989
module_init(patch_analog_init)
4990
module_exit(patch_analog_exit)
4991
4992