]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/sound/pci/hda/hdaa_patches.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / sound / pci / hda / hdaa_patches.c
1 /*-
2  * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
3  * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
4  * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
31  */
32
33 #ifdef HAVE_KERNEL_OPTION_HEADERS
34 #include "opt_snd.h"
35 #endif
36
37 #include <dev/sound/pcm/sound.h>
38
39 #include <sys/ctype.h>
40
41 #include <dev/sound/pci/hda/hdac.h>
42 #include <dev/sound/pci/hda/hdaa.h>
43 #include <dev/sound/pci/hda/hda_reg.h>
44
45 SND_DECLARE_FILE("$FreeBSD$");
46
47 static const struct {
48         uint32_t model;
49         uint32_t id;
50         uint32_t subsystemid;
51         uint32_t set, unset;
52         uint32_t gpio;
53 } hdac_quirks[] = {
54         /*
55          * XXX Force stereo quirk. Monoural recording / playback
56          *     on few codecs (especially ALC880) seems broken or
57          *     perhaps unsupported.
58          */
59         { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
60             HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
61             0 },
62         { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
63             0, 0,
64             HDAA_GPIO_SET(0) },
65         { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
66             0, 0,
67             HDAA_GPIO_SET(0) },
68         { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
69             0, 0,
70             HDAA_GPIO_SET(0) },
71         { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
72             0, 0,
73             HDAA_GPIO_SET(0) },
74         { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
75             0, 0,
76             HDAA_GPIO_SET(0) },
77         { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
78             0, 0,
79             HDAA_GPIO_SET(0) },
80         { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
81             HDAA_QUIRK_EAPDINV, 0,
82             0 },
83         { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
84             HDAA_QUIRK_EAPDINV, 0,
85             0 },
86         { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
87             HDAA_QUIRK_OVREF, 0,
88             0 },
89         { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
90             HDAA_QUIRK_OVREF, 0,
91             0 },
92         /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
93             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
94             0 },*/
95         { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
96             0, 0,
97             HDAA_GPIO_SET(1) },
98         { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
99             HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
100             0 },
101         { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
102             HDAA_QUIRK_EAPDINV, 0,
103             0 },
104         { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
105             HDAA_QUIRK_OVREF50, 0,
106             HDAA_GPIO_SET(0) },
107         { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
108             0, 0,
109             HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
110         { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
111             0, 0,
112             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
113         { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
114             0, 0,
115             HDAA_GPIO_SET(0) },
116         { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
117             0, 0,
118             HDAA_GPIO_SET(2) },
119         { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
120             0, 0,
121             HDAA_GPIO_SET(0) },
122         { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
123             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
124             0 },
125         { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
126             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
127             0 },
128         { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
129             0, HDAA_QUIRK_FORCESTEREO,
130             0 },
131         /* Mac Pro 1,1 requires ovref for proper volume level. */
132         { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
133             0, HDAA_QUIRK_OVREF,
134             0 }
135 };
136 #define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0]))
137
138 static void
139 hdac_pin_patch(struct hdaa_widget *w)
140 {
141         const char *patch = NULL;
142         uint32_t config, orig, id, subid;
143         nid_t nid = w->nid;
144
145         config = orig = w->wclass.pin.config;
146         id = hdaa_codec_id(w->devinfo);
147         subid = hdaa_card_id(w->devinfo);
148
149         /* XXX: Old patches require complete review.
150          * Now they may create more problem then solve due to
151          * incorrect associations.
152          */
153         if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
154                 switch (nid) {
155                 case 26:
156                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
157                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
158                         break;
159                 case 27:
160                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
161                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
162                         break;
163                 default:
164                         break;
165                 }
166         } else if (id == HDA_CODEC_ALC880 &&
167             (subid == CLEVO_D900T_SUBVENDOR ||
168             subid == ASUS_M5200_SUBVENDOR)) {
169                 /*
170                  * Super broken BIOS
171                  */
172                 switch (nid) {
173                 case 24:        /* MIC1 */
174                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
175                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
176                         break;
177                 case 25:        /* XXX MIC2 */
178                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
179                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
180                         break;
181                 case 26:        /* LINE1 */
182                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
183                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
184                         break;
185                 case 27:        /* XXX LINE2 */
186                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
187                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
188                         break;
189                 case 28:        /* CD */
190                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
191                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
192                         break;
193                 }
194         } else if (id == HDA_CODEC_ALC883 &&
195             (subid == MSI_MS034A_SUBVENDOR ||
196             HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
197                 switch (nid) {
198                 case 25:
199                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
200                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
201                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
202                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
203                         break;
204                 case 28:
205                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
206                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
207                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
208                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
209                         break;
210                 }
211         } else if (id == HDA_CODEC_CX20549 && subid ==
212             HP_V3000_SUBVENDOR) {
213                 switch (nid) {
214                 case 18:
215                         config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
216                         config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
217                         break;
218                 case 20:
219                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
220                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
221                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
222                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
223                         break;
224                 case 21:
225                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
226                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
227                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
228                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
229                         break;
230                 }
231         } else if (id == HDA_CODEC_CX20551 && subid ==
232             HP_DV5000_SUBVENDOR) {
233                 switch (nid) {
234                 case 20:
235                 case 21:
236                         config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
237                         config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
238                         break;
239                 }
240         } else if (id == HDA_CODEC_ALC861 && subid ==
241             ASUS_W6F_SUBVENDOR) {
242                 switch (nid) {
243                 case 11:
244                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
245                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
246                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
247                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
248                         break;
249                 case 12:
250                 case 14:
251                 case 16:
252                 case 31:
253                 case 32:
254                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
255                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
256                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
257                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
258                         break;
259                 case 15:
260                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
261                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
262                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
263                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
264                         break;
265                 }
266         } else if (id == HDA_CODEC_ALC861 && subid ==
267             UNIWILL_9075_SUBVENDOR) {
268                 switch (nid) {
269                 case 15:
270                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
271                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
272                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
273                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
274                         break;
275                 }
276         }
277
278         /* New patches */
279         if (id == HDA_CODEC_AD1984A &&
280             subid == LENOVO_X300_SUBVENDOR) {
281                 switch (nid) {
282                 case 17: /* Headphones with redirection */
283                         patch = "as=1 seq=15";
284                         break;
285                 case 20: /* Two mics together */
286                         patch = "as=2 seq=15";
287                         break;
288                 }
289         } else if (id == HDA_CODEC_AD1986A &&
290             (subid == ASUS_M2NPVMX_SUBVENDOR ||
291             subid == ASUS_A8NVMCSM_SUBVENDOR ||
292             subid == ASUS_P5PL2_SUBVENDOR)) {
293                 switch (nid) {
294                 case 26: /* Headphones with redirection */
295                         patch = "as=1 seq=15";
296                         break;
297                 case 28: /* 5.1 out => 2.0 out + 1 input */
298                         patch = "device=Line-in as=8 seq=1";
299                         break;
300                 case 29: /* Can't use this as input, as the only available mic
301                           * preamplifier is busy by front panel mic (nid 31).
302                           * If you want to use this rear connector as mic input,
303                           * you have to disable the front panel one. */
304                         patch = "as=0";
305                         break;
306                 case 31: /* Lot of inputs configured with as=15 and unusable */
307                         patch = "as=8 seq=3";
308                         break;
309                 case 32:
310                         patch = "as=8 seq=4";
311                         break;
312                 case 34:
313                         patch = "as=8 seq=5";
314                         break;
315                 case 36:
316                         patch = "as=8 seq=6";
317                         break;
318                 }
319         } else if (id == HDA_CODEC_ALC260 &&
320             HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
321                 switch (nid) {
322                 case 16:
323                         patch = "seq=15 device=Headphones";
324                         break;
325                 }
326         } else if (id == HDA_CODEC_ALC268) {
327             if (subid == ACER_T5320_SUBVENDOR) {
328                 switch (nid) {
329                 case 20: /* Headphones Jack */
330                         patch = "as=1 seq=15";
331                         break;
332                 }
333             }
334         } else if (id == HDA_CODEC_CX20561 &&
335             subid == LENOVO_B450_SUBVENDOR) {
336                 switch (nid) {
337                 case 22:
338                         patch = "as=1 seq=15";
339                         break;
340                 }
341         } else if (id == HDA_CODEC_CX20590 &&
342             (subid == LENOVO_X1_SUBVENDOR ||
343             subid == LENOVO_X220_SUBVENDOR ||
344             subid == LENOVO_T420_SUBVENDOR ||
345             subid == LENOVO_T520_SUBVENDOR)) {
346                 switch (nid) {
347                 case 25:
348                         patch = "as=1 seq=15";
349                         break;
350                 /* 
351                  * Group onboard mic and headphone mic
352                  * together.  Fixes onboard mic.
353                  */
354                 case 27:
355                         patch = "as=2 seq=15";
356                         break;
357                 case 35:
358                         patch = "as=2";
359                         break;
360                 }
361         } else if (id == HDA_CODEC_ALC269 &&
362             (subid == LENOVO_X1CRBN_SUBVENDOR ||
363             subid == LENOVO_T430_SUBVENDOR ||
364             subid == LENOVO_T430S_SUBVENDOR ||
365             subid == LENOVO_T530_SUBVENDOR)) {
366                 switch (nid) {
367                 case 21:
368                         patch = "as=1 seq=15";
369                         break;
370                 }
371         } else if (id == HDA_CODEC_ALC269 &&
372             subid == ASUS_UX31A_SUBVENDOR) {
373                 switch (nid) {
374                 case 33:
375                         patch = "as=1 seq=15";
376                         break;
377                 }
378         }
379
380         if (patch != NULL)
381                 config = hdaa_widget_pin_patch(config, patch);
382         HDA_BOOTVERBOSE(
383                 if (config != orig)
384                         device_printf(w->devinfo->dev,
385                             "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
386                             nid, orig, config);
387         );
388         w->wclass.pin.config = config;
389 }
390
391 static void
392 hdaa_widget_patch(struct hdaa_widget *w)
393 {
394         struct hdaa_devinfo *devinfo = w->devinfo;
395         uint32_t orig;
396         nid_t beeper = -1;
397
398         orig = w->param.widget_cap;
399         /* On some codecs beeper is an input pin, but it is not recordable
400            alone. Also most of BIOSes does not declare beeper pin.
401            Change beeper pin node type to beeper to help parser. */
402         switch (hdaa_codec_id(devinfo)) {
403         case HDA_CODEC_AD1882:
404         case HDA_CODEC_AD1883:
405         case HDA_CODEC_AD1984:
406         case HDA_CODEC_AD1984A:
407         case HDA_CODEC_AD1984B:
408         case HDA_CODEC_AD1987:
409         case HDA_CODEC_AD1988:
410         case HDA_CODEC_AD1988B:
411         case HDA_CODEC_AD1989B:
412                 beeper = 26;
413                 break;
414         case HDA_CODEC_ALC260:
415                 beeper = 23;
416                 break;
417         }
418         if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
419             hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
420                 beeper = 29;
421         if (w->nid == beeper) {
422                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
423                 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
424                     HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
425                 w->waspin = 1;
426         }
427         /*
428          * Clear "digital" flag from digital mic input, as its signal then goes
429          * to "analog" mixer and this separation just limits functionaity.
430          */
431         if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
432             w->nid == 23)
433                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
434         HDA_BOOTVERBOSE(
435                 if (w->param.widget_cap != orig) {
436                         device_printf(w->devinfo->dev,
437                             "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
438                             w->nid, orig, w->param.widget_cap);
439                 }
440         );
441
442         if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
443                 hdac_pin_patch(w);
444 }
445
446 void
447 hdaa_patch(struct hdaa_devinfo *devinfo)
448 {
449         struct hdaa_widget *w;
450         uint32_t id, subid, subsystemid;
451         int i;
452
453         id = hdaa_codec_id(devinfo);
454         subid = hdaa_card_id(devinfo);
455         subsystemid = hda_get_subsystem_id(devinfo->dev);
456
457         /*
458          * Quirks
459          */
460         for (i = 0; i < HDAC_QUIRKS_LEN; i++) {
461                 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
462                     HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
463                     HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
464                         continue;
465                 devinfo->quirks |= hdac_quirks[i].set;
466                 devinfo->quirks &= ~(hdac_quirks[i].unset);
467                 devinfo->gpio = hdac_quirks[i].gpio;
468         }
469
470         /* Apply per-widget patch. */
471         for (i = devinfo->startnode; i < devinfo->endnode; i++) {
472                 w = hdaa_widget_get(devinfo, i);
473                 if (w == NULL)
474                         continue;
475                 hdaa_widget_patch(w);
476         }
477
478         switch (id) {
479         case HDA_CODEC_AD1983:
480                 /*
481                  * This CODEC has several possible usages, but none
482                  * fit the parser best. Help parser to choose better.
483                  */
484                 /* Disable direct unmixed playback to get pcm volume. */
485                 w = hdaa_widget_get(devinfo, 5);
486                 if (w != NULL)
487                         w->connsenable[0] = 0;
488                 w = hdaa_widget_get(devinfo, 6);
489                 if (w != NULL)
490                         w->connsenable[0] = 0;
491                 w = hdaa_widget_get(devinfo, 11);
492                 if (w != NULL)
493                         w->connsenable[0] = 0;
494                 /* Disable mic and line selectors. */
495                 w = hdaa_widget_get(devinfo, 12);
496                 if (w != NULL)
497                         w->connsenable[1] = 0;
498                 w = hdaa_widget_get(devinfo, 13);
499                 if (w != NULL)
500                         w->connsenable[1] = 0;
501                 /* Disable recording from mono playback mix. */
502                 w = hdaa_widget_get(devinfo, 20);
503                 if (w != NULL)
504                         w->connsenable[3] = 0;
505                 break;
506         case HDA_CODEC_AD1986A:
507                 /*
508                  * This CODEC has overcomplicated input mixing.
509                  * Make some cleaning there.
510                  */
511                 /* Disable input mono mixer. Not needed and not supported. */
512                 w = hdaa_widget_get(devinfo, 43);
513                 if (w != NULL)
514                         w->enable = 0;
515                 /* Disable any with any input mixing mesh. Use separately. */
516                 w = hdaa_widget_get(devinfo, 39);
517                 if (w != NULL)
518                         w->enable = 0;
519                 w = hdaa_widget_get(devinfo, 40);
520                 if (w != NULL)
521                         w->enable = 0;
522                 w = hdaa_widget_get(devinfo, 41);
523                 if (w != NULL)
524                         w->enable = 0;
525                 w = hdaa_widget_get(devinfo, 42);
526                 if (w != NULL)
527                         w->enable = 0;
528                 /* Disable duplicate mixer node connector. */
529                 w = hdaa_widget_get(devinfo, 15);
530                 if (w != NULL)
531                         w->connsenable[3] = 0;
532                 /* There is only one mic preamplifier, use it effectively. */
533                 w = hdaa_widget_get(devinfo, 31);
534                 if (w != NULL) {
535                         if ((w->wclass.pin.config &
536                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
537                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
538                                 w = hdaa_widget_get(devinfo, 16);
539                                 if (w != NULL)
540                                     w->connsenable[2] = 0;
541                         } else {
542                                 w = hdaa_widget_get(devinfo, 15);
543                                 if (w != NULL)
544                                     w->connsenable[0] = 0;
545                         }
546                 }
547                 w = hdaa_widget_get(devinfo, 32);
548                 if (w != NULL) {
549                         if ((w->wclass.pin.config &
550                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
551                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
552                                 w = hdaa_widget_get(devinfo, 16);
553                                 if (w != NULL)
554                                     w->connsenable[0] = 0;
555                         } else {
556                                 w = hdaa_widget_get(devinfo, 15);
557                                 if (w != NULL)
558                                     w->connsenable[1] = 0;
559                         }
560                 }
561
562                 if (subid == ASUS_A8X_SUBVENDOR) {
563                         /*
564                          * This is just plain ridiculous.. There
565                          * are several A8 series that share the same
566                          * pci id but works differently (EAPD).
567                          */
568                         w = hdaa_widget_get(devinfo, 26);
569                         if (w != NULL && w->type ==
570                             HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
571                             (w->wclass.pin.config &
572                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
573                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
574                                 devinfo->quirks &=
575                                     ~HDAA_QUIRK_EAPDINV;
576                 }
577                 break;
578         case HDA_CODEC_AD1981HD:
579                 /*
580                  * This CODEC has very unusual design with several
581                  * points inappropriate for the present parser.
582                  */
583                 /* Disable recording from mono playback mix. */
584                 w = hdaa_widget_get(devinfo, 21);
585                 if (w != NULL)
586                         w->connsenable[3] = 0;
587                 /* Disable rear to front mic mixer, use separately. */
588                 w = hdaa_widget_get(devinfo, 31);
589                 if (w != NULL)
590                         w->enable = 0;
591                 /* Disable direct playback, use mixer. */
592                 w = hdaa_widget_get(devinfo, 5);
593                 if (w != NULL)
594                         w->connsenable[0] = 0;
595                 w = hdaa_widget_get(devinfo, 6);
596                 if (w != NULL)
597                         w->connsenable[0] = 0;
598                 w = hdaa_widget_get(devinfo, 9);
599                 if (w != NULL)
600                         w->connsenable[0] = 0;
601                 w = hdaa_widget_get(devinfo, 24);
602                 if (w != NULL)
603                         w->connsenable[0] = 0;
604                 break;
605         case HDA_CODEC_ALC269:
606                 /*
607                  * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
608                  * that mutes speaker if unused mixer at NID 15 is muted.
609                  * Probably CODEC incorrectly reports internal connections.
610                  * Hide that muter from the driver.  There are several CODECs
611                  * sharing this ID and I have not enough information about
612                  * them to implement more universal solution.
613                  */
614                 if (subid == 0x84371043) {
615                         w = hdaa_widget_get(devinfo, 15);
616                         if (w != NULL)
617                                 w->param.inamp_cap = 0;
618                 }
619                 break;
620         case HDA_CODEC_CX20582:
621         case HDA_CODEC_CX20583:
622         case HDA_CODEC_CX20584:
623         case HDA_CODEC_CX20585:
624         case HDA_CODEC_CX20590:
625                 /*
626                  * These codecs have extra connectivity on record side
627                  * too reach for the present parser.
628                  */
629                 w = hdaa_widget_get(devinfo, 20);
630                 if (w != NULL)
631                         w->connsenable[1] = 0;
632                 w = hdaa_widget_get(devinfo, 21);
633                 if (w != NULL)
634                         w->connsenable[1] = 0;
635                 w = hdaa_widget_get(devinfo, 22);
636                 if (w != NULL)
637                         w->connsenable[0] = 0;
638                 break;
639         case HDA_CODEC_VT1708S_0:
640         case HDA_CODEC_VT1708S_1:
641         case HDA_CODEC_VT1708S_2:
642         case HDA_CODEC_VT1708S_3:
643         case HDA_CODEC_VT1708S_4:
644         case HDA_CODEC_VT1708S_5:
645         case HDA_CODEC_VT1708S_6:
646         case HDA_CODEC_VT1708S_7:
647                 /*
648                  * These codecs have hidden mic boost controls.
649                  */
650                 w = hdaa_widget_get(devinfo, 26);
651                 if (w != NULL)
652                         w->param.inamp_cap =
653                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
654                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
655                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
656                 w = hdaa_widget_get(devinfo, 30);
657                 if (w != NULL)
658                         w->param.inamp_cap =
659                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
660                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
661                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
662                 break;
663         }
664 }
665
666 void
667 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
668 {
669         device_t dev = devinfo->dev;
670         uint32_t id, subid, val;
671
672         id = hdaa_codec_id(devinfo);
673         subid = hdaa_card_id(devinfo);
674
675         switch (id) {
676         case HDA_CODEC_VT1708S_0:
677         case HDA_CODEC_VT1708S_1:
678         case HDA_CODEC_VT1708S_2:
679         case HDA_CODEC_VT1708S_3:
680         case HDA_CODEC_VT1708S_4:
681         case HDA_CODEC_VT1708S_5:
682         case HDA_CODEC_VT1708S_6:
683         case HDA_CODEC_VT1708S_7:
684                 /* Enable Mic Boost Volume controls. */
685                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
686                     0xf98, 0x01));
687                 /* Fall though */
688         case HDA_CODEC_VT1818S:
689                 /* Don't bypass mixer. */
690                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
691                     0xf88, 0xc0));
692                 break;
693         }
694         if (subid == APPLE_INTEL_MAC)
695                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
696                     0x7e7, 0));
697         if (id == HDA_CODEC_ALC269) {
698                 if (subid == 0x16e31043 || subid == 0x831a1043 ||
699                     subid == 0x834a1043 || subid == 0x83981043 ||
700                     subid == 0x83ce1043) {
701                         /*
702                          * The ditital mics on some Asus laptops produce
703                          * differential signals instead of expected stereo.
704                          * That results in silence if downmix it to mono.
705                          * To workaround, make codec to handle signal as mono.
706                          */
707                         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
708                         val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
709                         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
710                         hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
711                 }
712         }
713 }