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