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