]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sound/pci/hda/hdaa_patches.c
Update DTS files from Linux 4.12
[FreeBSD/FreeBSD.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_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
111             0, 0,
112             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
113         { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
114             0, 0,
115             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
116         { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
117             0, 0,
118             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
119         { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
120             0, 0,
121             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
122         { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
123             0, 0,
124             HDAA_GPIO_SET(0) },
125         { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
126             0, 0,
127             HDAA_GPIO_SET(2) },
128         { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
129             0, 0,
130             HDAA_GPIO_SET(0) },
131         { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
132             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
133             0 },
134         { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
135             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
136             0 },
137         { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
138             0, HDAA_QUIRK_FORCESTEREO,
139             0 },
140         /* Mac Pro 1,1 requires ovref for proper volume level. */
141         { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
142             0, HDAA_QUIRK_OVREF,
143             0 }
144 };
145
146 static void
147 hdac_pin_patch(struct hdaa_widget *w)
148 {
149         const char *patch = NULL;
150         uint32_t config, orig, id, subid;
151         nid_t nid = w->nid;
152
153         config = orig = w->wclass.pin.config;
154         id = hdaa_codec_id(w->devinfo);
155         subid = hdaa_card_id(w->devinfo);
156
157         /* XXX: Old patches require complete review.
158          * Now they may create more problem then solve due to
159          * incorrect associations.
160          */
161         if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
162                 switch (nid) {
163                 case 26:
164                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
165                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
166                         break;
167                 case 27:
168                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
169                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
170                         break;
171                 default:
172                         break;
173                 }
174         } else if (id == HDA_CODEC_ALC880 &&
175             (subid == CLEVO_D900T_SUBVENDOR ||
176             subid == ASUS_M5200_SUBVENDOR)) {
177                 /*
178                  * Super broken BIOS
179                  */
180                 switch (nid) {
181                 case 24:        /* MIC1 */
182                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
183                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
184                         break;
185                 case 25:        /* XXX MIC2 */
186                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
187                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
188                         break;
189                 case 26:        /* LINE1 */
190                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
191                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
192                         break;
193                 case 27:        /* XXX LINE2 */
194                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
195                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
196                         break;
197                 case 28:        /* CD */
198                         config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
199                         config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
200                         break;
201                 }
202         } else if (id == HDA_CODEC_ALC883 &&
203             (subid == MSI_MS034A_SUBVENDOR ||
204             HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
205                 switch (nid) {
206                 case 25:
207                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
208                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
209                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
210                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
211                         break;
212                 case 28:
213                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
214                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
215                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
216                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
217                         break;
218                 }
219         } else if (id == HDA_CODEC_CX20549 && subid ==
220             HP_V3000_SUBVENDOR) {
221                 switch (nid) {
222                 case 18:
223                         config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
224                         config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
225                         break;
226                 case 20:
227                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
228                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
229                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
230                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
231                         break;
232                 case 21:
233                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
234                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
235                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
236                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
237                         break;
238                 }
239         } else if (id == HDA_CODEC_CX20551 && subid ==
240             HP_DV5000_SUBVENDOR) {
241                 switch (nid) {
242                 case 20:
243                 case 21:
244                         config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
245                         config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
246                         break;
247                 }
248         } else if (id == HDA_CODEC_ALC861 && subid ==
249             ASUS_W6F_SUBVENDOR) {
250                 switch (nid) {
251                 case 11:
252                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
253                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
254                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
255                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
256                         break;
257                 case 12:
258                 case 14:
259                 case 16:
260                 case 31:
261                 case 32:
262                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
263                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
264                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
265                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
266                         break;
267                 case 15:
268                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
269                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
270                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
271                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
272                         break;
273                 }
274         } else if (id == HDA_CODEC_ALC861 && subid ==
275             UNIWILL_9075_SUBVENDOR) {
276                 switch (nid) {
277                 case 15:
278                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
279                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
280                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
281                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
282                         break;
283                 }
284         }
285
286         /* New patches */
287         if (id == HDA_CODEC_AD1984A &&
288             subid == LENOVO_X300_SUBVENDOR) {
289                 switch (nid) {
290                 case 17: /* Headphones with redirection */
291                         patch = "as=1 seq=15";
292                         break;
293                 case 20: /* Two mics together */
294                         patch = "as=2 seq=15";
295                         break;
296                 }
297         } else if (id == HDA_CODEC_AD1986A &&
298             (subid == ASUS_M2NPVMX_SUBVENDOR ||
299             subid == ASUS_A8NVMCSM_SUBVENDOR ||
300             subid == ASUS_P5PL2_SUBVENDOR)) {
301                 switch (nid) {
302                 case 26: /* Headphones with redirection */
303                         patch = "as=1 seq=15";
304                         break;
305                 case 28: /* 5.1 out => 2.0 out + 1 input */
306                         patch = "device=Line-in as=8 seq=1";
307                         break;
308                 case 29: /* Can't use this as input, as the only available mic
309                           * preamplifier is busy by front panel mic (nid 31).
310                           * If you want to use this rear connector as mic input,
311                           * you have to disable the front panel one. */
312                         patch = "as=0";
313                         break;
314                 case 31: /* Lot of inputs configured with as=15 and unusable */
315                         patch = "as=8 seq=3";
316                         break;
317                 case 32:
318                         patch = "as=8 seq=4";
319                         break;
320                 case 34:
321                         patch = "as=8 seq=5";
322                         break;
323                 case 36:
324                         patch = "as=8 seq=6";
325                         break;
326                 }
327         } else if (id == HDA_CODEC_ALC260 &&
328             HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
329                 switch (nid) {
330                 case 16:
331                         patch = "seq=15 device=Headphones";
332                         break;
333                 }
334         } else if (id == HDA_CODEC_ALC268) {
335             if (subid == ACER_T5320_SUBVENDOR) {
336                 switch (nid) {
337                 case 20: /* Headphones Jack */
338                         patch = "as=1 seq=15";
339                         break;
340                 }
341             }
342         } else if (id == HDA_CODEC_CX20561 &&
343             subid == LENOVO_B450_SUBVENDOR) {
344                 switch (nid) {
345                 case 22:
346                         patch = "as=1 seq=15";
347                         break;
348                 }
349         } else if (id == HDA_CODEC_CX20561 &&
350             subid == LENOVO_T400_SUBVENDOR) {
351                 switch (nid) {
352                 case 22:
353                         patch = "as=1 seq=15";
354                         break;
355                 case 26:
356                         patch = "as=1 seq=0";
357                         break;
358                 }
359         } else if (id == HDA_CODEC_CX20590 &&
360             (subid == LENOVO_X1_SUBVENDOR ||
361             subid == LENOVO_X220_SUBVENDOR ||
362             subid == LENOVO_T420_SUBVENDOR ||
363             subid == LENOVO_T520_SUBVENDOR ||
364             subid == LENOVO_G580_SUBVENDOR)) {
365                 switch (nid) {
366                 case 25:
367                         patch = "as=1 seq=15";
368                         break;
369                 /*
370                  * Group onboard mic and headphone mic
371                  * together.  Fixes onboard mic.
372                  */
373                 case 27:
374                         patch = "as=2 seq=15";
375                         break;
376                 case 35:
377                         patch = "as=2";
378                         break;
379                 }
380         } else if (id == HDA_CODEC_ALC269 &&
381             (subid == LENOVO_X1CRBN_SUBVENDOR ||
382             subid == LENOVO_T430_SUBVENDOR ||
383             subid == LENOVO_T430S_SUBVENDOR ||
384             subid == LENOVO_T530_SUBVENDOR)) {
385                 switch (nid) {
386                 case 21:
387                         patch = "as=1 seq=15";
388                         break;
389                 }
390         } else if (id == HDA_CODEC_ALC269 &&
391             subid == ASUS_UX31A_SUBVENDOR) {
392                 switch (nid) {
393                 case 33:
394                         patch = "as=1 seq=15";
395                         break;
396                 }
397         } else if (id == HDA_CODEC_ALC892 &&
398             subid == INTEL_DH87RL_SUBVENDOR) {
399                 switch (nid) {
400                 case 27:
401                         patch = "as=1 seq=15";
402                         break;
403                 }
404         } else if (id == HDA_CODEC_ALC292 &&
405             subid == LENOVO_X120BS_SUBVENDOR) {
406                 switch (nid) {
407                 case 21:
408                         patch = "as=1 seq=15";
409                         break;
410                 }
411         }
412
413         if (patch != NULL)
414                 config = hdaa_widget_pin_patch(config, patch);
415         HDA_BOOTVERBOSE(
416                 if (config != orig)
417                         device_printf(w->devinfo->dev,
418                             "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
419                             nid, orig, config);
420         );
421         w->wclass.pin.config = config;
422 }
423
424 static void
425 hdaa_widget_patch(struct hdaa_widget *w)
426 {
427         struct hdaa_devinfo *devinfo = w->devinfo;
428         uint32_t orig;
429         nid_t beeper = -1;
430
431         orig = w->param.widget_cap;
432         /* On some codecs beeper is an input pin, but it is not recordable
433            alone. Also most of BIOSes does not declare beeper pin.
434            Change beeper pin node type to beeper to help parser. */
435         switch (hdaa_codec_id(devinfo)) {
436         case HDA_CODEC_AD1882:
437         case HDA_CODEC_AD1883:
438         case HDA_CODEC_AD1984:
439         case HDA_CODEC_AD1984A:
440         case HDA_CODEC_AD1984B:
441         case HDA_CODEC_AD1987:
442         case HDA_CODEC_AD1988:
443         case HDA_CODEC_AD1988B:
444         case HDA_CODEC_AD1989B:
445                 beeper = 26;
446                 break;
447         case HDA_CODEC_ALC260:
448                 beeper = 23;
449                 break;
450         }
451         if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
452             hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
453                 beeper = 29;
454         if (w->nid == beeper) {
455                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
456                 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
457                     HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
458                 w->waspin = 1;
459         }
460         /*
461          * Clear "digital" flag from digital mic input, as its signal then goes
462          * to "analog" mixer and this separation just limits functionaity.
463          */
464         if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
465             w->nid == 23)
466                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
467         HDA_BOOTVERBOSE(
468                 if (w->param.widget_cap != orig) {
469                         device_printf(w->devinfo->dev,
470                             "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
471                             w->nid, orig, w->param.widget_cap);
472                 }
473         );
474
475         if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
476                 hdac_pin_patch(w);
477 }
478
479 void
480 hdaa_patch(struct hdaa_devinfo *devinfo)
481 {
482         struct hdaa_widget *w;
483         uint32_t id, subid, subsystemid;
484         int i;
485
486         id = hdaa_codec_id(devinfo);
487         subid = hdaa_card_id(devinfo);
488         subsystemid = hda_get_subsystem_id(devinfo->dev);
489
490         /*
491          * Quirks
492          */
493         for (i = 0; i < nitems(hdac_quirks); i++) {
494                 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
495                     HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
496                     HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
497                         continue;
498                 devinfo->quirks |= hdac_quirks[i].set;
499                 devinfo->quirks &= ~(hdac_quirks[i].unset);
500                 devinfo->gpio = hdac_quirks[i].gpio;
501         }
502
503         /* Apply per-widget patch. */
504         for (i = devinfo->startnode; i < devinfo->endnode; i++) {
505                 w = hdaa_widget_get(devinfo, i);
506                 if (w == NULL)
507                         continue;
508                 hdaa_widget_patch(w);
509         }
510
511         switch (id) {
512         case HDA_CODEC_AD1983:
513                 /*
514                  * This CODEC has several possible usages, but none
515                  * fit the parser best. Help parser to choose better.
516                  */
517                 /* Disable direct unmixed playback to get pcm volume. */
518                 w = hdaa_widget_get(devinfo, 5);
519                 if (w != NULL)
520                         w->connsenable[0] = 0;
521                 w = hdaa_widget_get(devinfo, 6);
522                 if (w != NULL)
523                         w->connsenable[0] = 0;
524                 w = hdaa_widget_get(devinfo, 11);
525                 if (w != NULL)
526                         w->connsenable[0] = 0;
527                 /* Disable mic and line selectors. */
528                 w = hdaa_widget_get(devinfo, 12);
529                 if (w != NULL)
530                         w->connsenable[1] = 0;
531                 w = hdaa_widget_get(devinfo, 13);
532                 if (w != NULL)
533                         w->connsenable[1] = 0;
534                 /* Disable recording from mono playback mix. */
535                 w = hdaa_widget_get(devinfo, 20);
536                 if (w != NULL)
537                         w->connsenable[3] = 0;
538                 break;
539         case HDA_CODEC_AD1986A:
540                 /*
541                  * This CODEC has overcomplicated input mixing.
542                  * Make some cleaning there.
543                  */
544                 /* Disable input mono mixer. Not needed and not supported. */
545                 w = hdaa_widget_get(devinfo, 43);
546                 if (w != NULL)
547                         w->enable = 0;
548                 /* Disable any with any input mixing mesh. Use separately. */
549                 w = hdaa_widget_get(devinfo, 39);
550                 if (w != NULL)
551                         w->enable = 0;
552                 w = hdaa_widget_get(devinfo, 40);
553                 if (w != NULL)
554                         w->enable = 0;
555                 w = hdaa_widget_get(devinfo, 41);
556                 if (w != NULL)
557                         w->enable = 0;
558                 w = hdaa_widget_get(devinfo, 42);
559                 if (w != NULL)
560                         w->enable = 0;
561                 /* Disable duplicate mixer node connector. */
562                 w = hdaa_widget_get(devinfo, 15);
563                 if (w != NULL)
564                         w->connsenable[3] = 0;
565                 /* There is only one mic preamplifier, use it effectively. */
566                 w = hdaa_widget_get(devinfo, 31);
567                 if (w != NULL) {
568                         if ((w->wclass.pin.config &
569                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
570                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
571                                 w = hdaa_widget_get(devinfo, 16);
572                                 if (w != NULL)
573                                     w->connsenable[2] = 0;
574                         } else {
575                                 w = hdaa_widget_get(devinfo, 15);
576                                 if (w != NULL)
577                                     w->connsenable[0] = 0;
578                         }
579                 }
580                 w = hdaa_widget_get(devinfo, 32);
581                 if (w != NULL) {
582                         if ((w->wclass.pin.config &
583                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
584                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
585                                 w = hdaa_widget_get(devinfo, 16);
586                                 if (w != NULL)
587                                     w->connsenable[0] = 0;
588                         } else {
589                                 w = hdaa_widget_get(devinfo, 15);
590                                 if (w != NULL)
591                                     w->connsenable[1] = 0;
592                         }
593                 }
594
595                 if (subid == ASUS_A8X_SUBVENDOR) {
596                         /*
597                          * This is just plain ridiculous.. There
598                          * are several A8 series that share the same
599                          * pci id but works differently (EAPD).
600                          */
601                         w = hdaa_widget_get(devinfo, 26);
602                         if (w != NULL && w->type ==
603                             HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
604                             (w->wclass.pin.config &
605                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
606                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
607                                 devinfo->quirks &=
608                                     ~HDAA_QUIRK_EAPDINV;
609                 }
610                 break;
611         case HDA_CODEC_AD1981HD:
612                 /*
613                  * This CODEC has very unusual design with several
614                  * points inappropriate for the present parser.
615                  */
616                 /* Disable recording from mono playback mix. */
617                 w = hdaa_widget_get(devinfo, 21);
618                 if (w != NULL)
619                         w->connsenable[3] = 0;
620                 /* Disable rear to front mic mixer, use separately. */
621                 w = hdaa_widget_get(devinfo, 31);
622                 if (w != NULL)
623                         w->enable = 0;
624                 /* Disable direct playback, use mixer. */
625                 w = hdaa_widget_get(devinfo, 5);
626                 if (w != NULL)
627                         w->connsenable[0] = 0;
628                 w = hdaa_widget_get(devinfo, 6);
629                 if (w != NULL)
630                         w->connsenable[0] = 0;
631                 w = hdaa_widget_get(devinfo, 9);
632                 if (w != NULL)
633                         w->connsenable[0] = 0;
634                 w = hdaa_widget_get(devinfo, 24);
635                 if (w != NULL)
636                         w->connsenable[0] = 0;
637                 break;
638         case HDA_CODEC_ALC269:
639                 /*
640                  * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
641                  * that mutes speaker if unused mixer at NID 15 is muted.
642                  * Probably CODEC incorrectly reports internal connections.
643                  * Hide that muter from the driver.  There are several CODECs
644                  * sharing this ID and I have not enough information about
645                  * them to implement more universal solution.
646                  */
647                 if (subid == 0x84371043) {
648                         w = hdaa_widget_get(devinfo, 15);
649                         if (w != NULL)
650                                 w->param.inamp_cap = 0;
651                 }
652                 break;
653         case HDA_CODEC_CX20582:
654         case HDA_CODEC_CX20583:
655         case HDA_CODEC_CX20584:
656         case HDA_CODEC_CX20585:
657         case HDA_CODEC_CX20590:
658                 /*
659                  * These codecs have extra connectivity on record side
660                  * too reach for the present parser.
661                  */
662                 w = hdaa_widget_get(devinfo, 20);
663                 if (w != NULL)
664                         w->connsenable[1] = 0;
665                 w = hdaa_widget_get(devinfo, 21);
666                 if (w != NULL)
667                         w->connsenable[1] = 0;
668                 w = hdaa_widget_get(devinfo, 22);
669                 if (w != NULL)
670                         w->connsenable[0] = 0;
671                 break;
672         case HDA_CODEC_VT1708S_0:
673         case HDA_CODEC_VT1708S_1:
674         case HDA_CODEC_VT1708S_2:
675         case HDA_CODEC_VT1708S_3:
676         case HDA_CODEC_VT1708S_4:
677         case HDA_CODEC_VT1708S_5:
678         case HDA_CODEC_VT1708S_6:
679         case HDA_CODEC_VT1708S_7:
680                 /*
681                  * These codecs have hidden mic boost controls.
682                  */
683                 w = hdaa_widget_get(devinfo, 26);
684                 if (w != NULL)
685                         w->param.inamp_cap =
686                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
687                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
688                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
689                 w = hdaa_widget_get(devinfo, 30);
690                 if (w != NULL)
691                         w->param.inamp_cap =
692                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
693                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
694                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
695                 break;
696         }
697 }
698
699 static uint32_t
700 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
701 {
702
703         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
704         return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
705 }
706
707 static uint32_t
708 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
709 {
710
711         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
712         return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
713 }
714
715 void
716 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
717 {
718         device_t dev = devinfo->dev;
719         uint32_t id, subid, val;
720
721         id = hdaa_codec_id(devinfo);
722         subid = hdaa_card_id(devinfo);
723
724         switch (id) {
725         case HDA_CODEC_VT1708S_0:
726         case HDA_CODEC_VT1708S_1:
727         case HDA_CODEC_VT1708S_2:
728         case HDA_CODEC_VT1708S_3:
729         case HDA_CODEC_VT1708S_4:
730         case HDA_CODEC_VT1708S_5:
731         case HDA_CODEC_VT1708S_6:
732         case HDA_CODEC_VT1708S_7:
733                 /* Enable Mic Boost Volume controls. */
734                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
735                     0xf98, 0x01));
736                 /* Fall though */
737         case HDA_CODEC_VT1818S:
738                 /* Don't bypass mixer. */
739                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
740                     0xf88, 0xc0));
741                 break;
742         case HDA_CODEC_ALC1150:
743                 if (subid == 0xd9781462) {
744                         /* Too low volume on MSI H170 GAMING M3. */
745                         hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
746                 }
747                 break;
748         }
749         if (subid == APPLE_INTEL_MAC)
750                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
751                     0x7e7, 0));
752         if (id == HDA_CODEC_ALC269) {
753                 if (subid == 0x16e31043 || subid == 0x831a1043 ||
754                     subid == 0x834a1043 || subid == 0x83981043 ||
755                     subid == 0x83ce1043) {
756                         /*
757                          * The ditital mics on some Asus laptops produce
758                          * differential signals instead of expected stereo.
759                          * That results in silence if downmix it to mono.
760                          * To workaround, make codec to handle signal as mono.
761                          */
762                         val = hdaa_read_coef(dev, 0x20, 0x07);
763                         hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
764                 }
765                 if (subid == 0x15171043) {
766                         /* Increase output amp on ASUS UX31A by +5dB. */
767                         hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
768                 }
769         }
770 }