kernel - Add AC256 (sound) quirk
[dragonfly.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 #include <dev/sound/pci/hda/hdaa_patches.h>
45
46 SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa_patches.c 269158 2014-07-27 20:14:22Z adrian $");
47
48 static const struct {
49         uint32_t model;
50         uint32_t id;
51         uint32_t subsystemid;
52         uint32_t set, unset;
53         uint32_t gpio;
54 } hdac_quirks[] = {
55         /*
56          * XXX Force stereo quirk. Monoural recording / playback
57          *     on few codecs (especially ALC880) seems broken or
58          *     perhaps unsupported.
59          */
60         { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
61             HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
62             0 },
63         { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
64             0, 0,
65             HDAA_GPIO_SET(0) },
66         { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
67             0, 0,
68             HDAA_GPIO_SET(0) },
69         { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
70             0, 0,
71             HDAA_GPIO_SET(0) },
72         { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
73             0, 0,
74             HDAA_GPIO_SET(0) },
75         { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
76             0, 0,
77             HDAA_GPIO_SET(0) },
78         { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
79             0, 0,
80             HDAA_GPIO_SET(0) },
81         { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
82             HDAA_QUIRK_EAPDINV, 0,
83             0 },
84         { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
85             HDAA_QUIRK_EAPDINV, 0,
86             0 },
87         { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
88             HDAA_QUIRK_OVREF, 0,
89             0 },
90         { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
91             HDAA_QUIRK_OVREF, 0,
92             0 },
93         /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
94             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
95             0 },*/
96         { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
97             0, 0,
98             HDAA_GPIO_SET(1) },
99         { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
100             HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
101             0 },
102         { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
103             HDAA_QUIRK_EAPDINV, 0,
104             0 },
105         { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
106             HDAA_QUIRK_OVREF50, 0,
107             HDAA_GPIO_SET(0) },
108         { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
109             0, 0,
110             HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
111         { APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
112             0, 0,
113             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
114         { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
115             0, 0,
116             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
117         { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
118             0, 0,
119             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
120         { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
121             0, 0,
122             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
123         { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
124             0, 0,
125             HDAA_GPIO_SET(0) },
126         { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
127             0, 0,
128             HDAA_GPIO_SET(2) },
129         { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
130             0, 0,
131             HDAA_GPIO_SET(0) },
132         { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
133             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
134             0 },
135         { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
136             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
137             0 },
138         { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
139             0, HDAA_QUIRK_FORCESTEREO,
140             0 },
141         /* Mac Pro 1,1 requires ovref for proper volume level. */
142         { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
143             0, HDAA_QUIRK_OVREF,
144             0 }
145 };
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_ALC283 && (subid == ACER_C720_SUBVENDOR ||
289                                        subid == ACER_C720_SUBVENDOR2)) {
290                 switch (nid) {
291                 case 20:
292                         patch = "as=2 seq=0";
293                         break;
294                 case 25:
295                         patch = "as=1 seq=0";
296                         break;
297                 case 27:
298                         /*
299                         patch = "device=Headphones conn=Fixed as=2 seq=15";
300                         w->enable = 1;
301                         */
302                         break;
303                 case 33:
304                         break;
305                 }
306         } else
307         if (id == HDA_CODEC_AD1984A &&
308             subid == LENOVO_X300_SUBVENDOR) {
309                 switch (nid) {
310                 case 17: /* Headphones with redirection */
311                         patch = "as=1 seq=15";
312                         break;
313                 case 20: /* Two mics together */
314                         patch = "as=2 seq=15";
315                         break;
316                 }
317         } else if (id == HDA_CODEC_AD1986A &&
318             (subid == ASUS_M2NPVMX_SUBVENDOR ||
319             subid == ASUS_A8NVMCSM_SUBVENDOR ||
320             subid == ASUS_P5PL2_SUBVENDOR)) {
321                 switch (nid) {
322                 case 26: /* Headphones with redirection */
323                         patch = "as=1 seq=15";
324                         break;
325                 case 28: /* 5.1 out => 2.0 out + 1 input */
326                         patch = "device=Line-in as=8 seq=1";
327                         break;
328                 case 29: /* Can't use this as input, as the only available mic
329                           * preamplifier is busy by front panel mic (nid 31).
330                           * If you want to use this rear connector as mic input,
331                           * you have to disable the front panel one. */
332                         patch = "as=0";
333                         break;
334                 case 31: /* Lot of inputs configured with as=15 and unusable */
335                         patch = "as=8 seq=3";
336                         break;
337                 case 32:
338                         patch = "as=8 seq=4";
339                         break;
340                 case 34:
341                         patch = "as=8 seq=5";
342                         break;
343                 case 36:
344                         patch = "as=8 seq=6";
345                         break;
346                 }
347         } else if (id == HDA_CODEC_ALC260 &&
348             HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
349                 switch (nid) {
350                 case 16:
351                         patch = "seq=15 device=Headphones";
352                         break;
353                 }
354         } else if (id == HDA_CODEC_ALC268) {
355             if (subid == ACER_T5320_SUBVENDOR) {
356                 switch (nid) {
357                 case 20: /* Headphones Jack */
358                         patch = "as=1 seq=15";
359                         break;
360                 }
361             }
362         } else if (id == HDA_CODEC_CX20561 &&
363             subid == LENOVO_B450_SUBVENDOR) {
364                 switch (nid) {
365                 case 22:
366                         patch = "as=1 seq=15";
367                         break;
368                 }
369         } else if (id == HDA_CODEC_CX20561 &&
370             subid == LENOVO_T400_SUBVENDOR) {
371                 switch (nid) {
372                 case 22:
373                         patch = "as=1 seq=15";
374                         break;
375                 case 26:
376                         patch = "as=1 seq=0";
377                         break;
378                 }
379         } else if (id == HDA_CODEC_CX20590 &&
380             (subid == LENOVO_X1_SUBVENDOR ||
381             subid == LENOVO_X220_SUBVENDOR ||
382             subid == LENOVO_T420_SUBVENDOR ||
383             subid == LENOVO_T520_SUBVENDOR ||
384             subid == LENOVO_G580_SUBVENDOR)) {
385                 switch (nid) {
386                 case 25:
387                         patch = "as=1 seq=15";
388                         break;
389                 /*
390                  * Group onboard mic and headphone mic
391                  * together.  Fixes onboard mic.
392                  */
393                 case 27:
394                         patch = "as=2 seq=15";
395                         break;
396                 case 35:
397                         patch = "as=2";
398                         break;
399                 }
400         } else if (id == HDA_CODEC_ALC269 &&
401             (subid == LENOVO_X1CRBN_SUBVENDOR ||
402             subid == LENOVO_T430_SUBVENDOR ||
403             subid == LENOVO_T430S_SUBVENDOR ||
404             subid == LENOVO_T530_SUBVENDOR)) {
405                 switch (nid) {
406                 case 21:
407                         patch = "as=1 seq=15";
408                         break;
409                 }
410         } else if (id == HDA_CODEC_ALC269 &&
411             subid == ASUS_UX31A_SUBVENDOR) {
412                 switch (nid) {
413                 case 33:
414                         patch = "as=1 seq=15";
415                         break;
416                 }
417         } else if (id == HDA_CODEC_ALC892 &&
418             subid == INTEL_DH87RL_SUBVENDOR) {
419                 switch (nid) {
420                 case 27:
421                         patch = "as=1 seq=15";
422                         break;
423                 }
424         }
425
426         if (patch != NULL)
427                 config = hdaa_widget_pin_patch(config, patch);
428         HDA_BOOTVERBOSE(
429                 if (config != orig)
430                         device_printf(w->devinfo->dev,
431                             "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
432                             nid, orig, config);
433         );
434         w->wclass.pin.config = config;
435 }
436
437 static void
438 hdaa_widget_patch(struct hdaa_widget *w)
439 {
440         struct hdaa_devinfo *devinfo = w->devinfo;
441         uint32_t orig;
442         nid_t beeper = -1;
443         uint32_t id, subid;
444
445         id = hdaa_codec_id(devinfo);
446         subid = hdaa_card_id(devinfo);
447
448         orig = w->param.widget_cap;
449         /* On some codecs beeper is an input pin, but it is not recordable
450            alone. Also most of BIOSes does not declare beeper pin.
451            Change beeper pin node type to beeper to help parser. */
452         switch (hdaa_codec_id(devinfo)) {
453         case HDA_CODEC_AD1882:
454         case HDA_CODEC_AD1883:
455         case HDA_CODEC_AD1984:
456         case HDA_CODEC_AD1984A:
457         case HDA_CODEC_AD1984B:
458         case HDA_CODEC_AD1987:
459         case HDA_CODEC_AD1988:
460         case HDA_CODEC_AD1988B:
461         case HDA_CODEC_AD1989B:
462                 beeper = 26;
463                 break;
464         case HDA_CODEC_ALC260:
465                 beeper = 23;
466                 break;
467         }
468         if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
469             hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
470                 beeper = 29;
471         if (w->nid == beeper) {
472                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
473                 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
474                     HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
475                 w->waspin = 1;
476         }
477         /*
478          * Clear "digital" flag from digital mic input, as its signal then goes
479          * to "analog" mixer and this separation just limits functionaity.
480          */
481         if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
482             w->nid == 23)
483                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
484         HDA_BOOTVERBOSE(
485                 if (w->param.widget_cap != orig) {
486                         device_printf(w->devinfo->dev,
487                             "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
488                             w->nid, orig, w->param.widget_cap);
489                 }
490         );
491
492 #if 1
493         /*
494          * Redirect the headphone plug sense (NID 33 -> redir to 12).
495          *
496          * Disable the remixer (NID 11).  There was a comment in the linux
497          * driver that disabling the remixer removes low level whitenoise.
498          * this makes sense since the mixer's unconnected inputs might have
499          * noise on them that leaks through.
500          */
501         if (id == HDA_CODEC_ALC283 && (subid == ACER_C720_SUBVENDOR ||
502                                        subid == ACER_C720_SUBVENDOR2)) {
503                 if (w->nid == 33)
504                         w->senseredir = 12;
505                 if (w->nid == 11)
506                         w->enable = 0;
507         }
508 #endif
509
510         if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
511                 hdac_pin_patch(w);
512 }
513
514 void
515 hdaa_patch(struct hdaa_devinfo *devinfo)
516 {
517         struct hdaa_widget *w;
518         uint32_t id, subid, subsystemid;
519         uint32_t val;
520         int i;
521
522         id = hdaa_codec_id(devinfo);
523         subid = hdaa_card_id(devinfo);
524         subsystemid = hda_get_subsystem_id(devinfo->dev);
525
526         /*
527          * Quirks
528          */
529         for (i = 0; i < nitems(hdac_quirks); i++) {
530                 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
531                     HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
532                     HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
533                         continue;
534                 devinfo->quirks |= hdac_quirks[i].set;
535                 devinfo->quirks &= ~(hdac_quirks[i].unset);
536                 devinfo->gpio = hdac_quirks[i].gpio;
537         }
538
539         /* Apply per-widget patch. */
540         for (i = devinfo->startnode; i < devinfo->endnode; i++) {
541                 w = hdaa_widget_get(devinfo, i);
542                 if (w == NULL)
543                         continue;
544                 hdaa_widget_patch(w);
545         }
546
547         switch (id) {
548         case HDA_CODEC_AD1983:
549                 /*
550                  * This CODEC has several possible usages, but none
551                  * fit the parser best. Help parser to choose better.
552                  */
553                 /* Disable direct unmixed playback to get pcm volume. */
554                 w = hdaa_widget_get(devinfo, 5);
555                 if (w != NULL)
556                         w->connsenable[0] = 0;
557                 w = hdaa_widget_get(devinfo, 6);
558                 if (w != NULL)
559                         w->connsenable[0] = 0;
560                 w = hdaa_widget_get(devinfo, 11);
561                 if (w != NULL)
562                         w->connsenable[0] = 0;
563                 /* Disable mic and line selectors. */
564                 w = hdaa_widget_get(devinfo, 12);
565                 if (w != NULL)
566                         w->connsenable[1] = 0;
567                 w = hdaa_widget_get(devinfo, 13);
568                 if (w != NULL)
569                         w->connsenable[1] = 0;
570                 /* Disable recording from mono playback mix. */
571                 w = hdaa_widget_get(devinfo, 20);
572                 if (w != NULL)
573                         w->connsenable[3] = 0;
574                 break;
575         case HDA_CODEC_AD1986A:
576                 /*
577                  * This CODEC has overcomplicated input mixing.
578                  * Make some cleaning there.
579                  */
580                 /* Disable input mono mixer. Not needed and not supported. */
581                 w = hdaa_widget_get(devinfo, 43);
582                 if (w != NULL)
583                         w->enable = 0;
584                 /* Disable any with any input mixing mesh. Use separately. */
585                 w = hdaa_widget_get(devinfo, 39);
586                 if (w != NULL)
587                         w->enable = 0;
588                 w = hdaa_widget_get(devinfo, 40);
589                 if (w != NULL)
590                         w->enable = 0;
591                 w = hdaa_widget_get(devinfo, 41);
592                 if (w != NULL)
593                         w->enable = 0;
594                 w = hdaa_widget_get(devinfo, 42);
595                 if (w != NULL)
596                         w->enable = 0;
597                 /* Disable duplicate mixer node connector. */
598                 w = hdaa_widget_get(devinfo, 15);
599                 if (w != NULL)
600                         w->connsenable[3] = 0;
601                 /* There is only one mic preamplifier, use it effectively. */
602                 w = hdaa_widget_get(devinfo, 31);
603                 if (w != NULL) {
604                         if ((w->wclass.pin.config &
605                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
606                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
607                                 w = hdaa_widget_get(devinfo, 16);
608                                 if (w != NULL)
609                                     w->connsenable[2] = 0;
610                         } else {
611                                 w = hdaa_widget_get(devinfo, 15);
612                                 if (w != NULL)
613                                     w->connsenable[0] = 0;
614                         }
615                 }
616                 w = hdaa_widget_get(devinfo, 32);
617                 if (w != NULL) {
618                         if ((w->wclass.pin.config &
619                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
620                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
621                                 w = hdaa_widget_get(devinfo, 16);
622                                 if (w != NULL)
623                                     w->connsenable[0] = 0;
624                         } else {
625                                 w = hdaa_widget_get(devinfo, 15);
626                                 if (w != NULL)
627                                     w->connsenable[1] = 0;
628                         }
629                 }
630
631                 if (subid == ASUS_A8X_SUBVENDOR) {
632                         /*
633                          * This is just plain ridiculous.. There
634                          * are several A8 series that share the same
635                          * pci id but works differently (EAPD).
636                          */
637                         w = hdaa_widget_get(devinfo, 26);
638                         if (w != NULL && w->type ==
639                             HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
640                             (w->wclass.pin.config &
641                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
642                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
643                                 devinfo->quirks &=
644                                     ~HDAA_QUIRK_EAPDINV;
645                 }
646                 break;
647         case HDA_CODEC_AD1981HD:
648                 /*
649                  * This CODEC has very unusual design with several
650                  * points inappropriate for the present parser.
651                  */
652                 /* Disable recording from mono playback mix. */
653                 w = hdaa_widget_get(devinfo, 21);
654                 if (w != NULL)
655                         w->connsenable[3] = 0;
656                 /* Disable rear to front mic mixer, use separately. */
657                 w = hdaa_widget_get(devinfo, 31);
658                 if (w != NULL)
659                         w->enable = 0;
660                 /* Disable direct playback, use mixer. */
661                 w = hdaa_widget_get(devinfo, 5);
662                 if (w != NULL)
663                         w->connsenable[0] = 0;
664                 w = hdaa_widget_get(devinfo, 6);
665                 if (w != NULL)
666                         w->connsenable[0] = 0;
667                 w = hdaa_widget_get(devinfo, 9);
668                 if (w != NULL)
669                         w->connsenable[0] = 0;
670                 w = hdaa_widget_get(devinfo, 24);
671                 if (w != NULL)
672                         w->connsenable[0] = 0;
673                 break;
674         case HDA_CODEC_ALC256:
675                 val = hda_read_coef_idx(devinfo->dev, 0x20, 0x46);
676                 hda_write_coef_idx(devinfo->dev, 0x20, 0x46, val|0x3000);
677                 break;
678         case HDA_CODEC_ALC269:
679                 /*
680                  * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
681                  * that mutes speaker if unused mixer at NID 15 is muted.
682                  * Probably CODEC incorrectly reports internal connections.
683                  * Hide that muter from the driver.  There are several CODECs
684                  * sharing this ID and I have not enough information about
685                  * them to implement more universal solution.
686                  */
687                 if (subid == 0x84371043) {
688                         w = hdaa_widget_get(devinfo, 15);
689                         if (w != NULL)
690                                 w->param.inamp_cap = 0;
691                 }
692                 break;
693         case HDA_CODEC_CX20582:
694         case HDA_CODEC_CX20583:
695         case HDA_CODEC_CX20584:
696         case HDA_CODEC_CX20585:
697         case HDA_CODEC_CX20590:
698                 /*
699                  * These codecs have extra connectivity on record side
700                  * too reach for the present parser.
701                  */
702                 w = hdaa_widget_get(devinfo, 20);
703                 if (w != NULL)
704                         w->connsenable[1] = 0;
705                 w = hdaa_widget_get(devinfo, 21);
706                 if (w != NULL)
707                         w->connsenable[1] = 0;
708                 w = hdaa_widget_get(devinfo, 22);
709                 if (w != NULL)
710                         w->connsenable[0] = 0;
711                 break;
712         case HDA_CODEC_VT1708S_0:
713         case HDA_CODEC_VT1708S_1:
714         case HDA_CODEC_VT1708S_2:
715         case HDA_CODEC_VT1708S_3:
716         case HDA_CODEC_VT1708S_4:
717         case HDA_CODEC_VT1708S_5:
718         case HDA_CODEC_VT1708S_6:
719         case HDA_CODEC_VT1708S_7:
720                 /*
721                  * These codecs have hidden mic boost controls.
722                  */
723                 w = hdaa_widget_get(devinfo, 26);
724                 if (w != NULL)
725                         w->param.inamp_cap =
726                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
727                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
728                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
729                 w = hdaa_widget_get(devinfo, 30);
730                 if (w != NULL)
731                         w->param.inamp_cap =
732                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
733                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
734                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
735                 break;
736         }
737 }
738
739 void
740 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
741 {
742         device_t dev = devinfo->dev;
743         uint32_t id, subid, val;
744
745         id = hdaa_codec_id(devinfo);
746         subid = hdaa_card_id(devinfo);
747
748         switch (id) {
749         case HDA_CODEC_VT1708S_0:
750         case HDA_CODEC_VT1708S_1:
751         case HDA_CODEC_VT1708S_2:
752         case HDA_CODEC_VT1708S_3:
753         case HDA_CODEC_VT1708S_4:
754         case HDA_CODEC_VT1708S_5:
755         case HDA_CODEC_VT1708S_6:
756         case HDA_CODEC_VT1708S_7:
757                 /* Enable Mic Boost Volume controls. */
758                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
759                     0xf98, 0x01));
760                 /* Fall though */
761         case HDA_CODEC_VT1818S:
762                 /* Don't bypass mixer. */
763                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
764                     0xf88, 0xc0));
765                 break;
766         }
767         if (subid == APPLE_INTEL_MAC)
768                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
769                     0x7e7, 0));
770         if (id == HDA_CODEC_ALC269) {
771                 if (subid == 0x16e31043 || subid == 0x831a1043 ||
772                     subid == 0x834a1043 || subid == 0x83981043 ||
773                     subid == 0x83ce1043) {
774                         /*
775                          * The ditital mics on some Asus laptops produce
776                          * differential signals instead of expected stereo.
777                          * That results in silence if downmix it to mono.
778                          * To workaround, make codec to handle signal as mono.
779                          */
780                         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
781                         val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
782                         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
783                         hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
784                 }
785         }
786         if (id == HDA_CODEC_ALC283) {
787                 if (subid == ACER_C720_SUBVENDOR ||
788                     subid == ACER_C720_SUBVENDOR2)
789                         hdaa_patch_direct_acer_c720(devinfo);
790         }
791 }
792
793 /* XXX move me to a better place */
794 uint32_t
795 hda_read_coef_idx(device_t dev, nid_t nid, unsigned int coef_idx)
796 {
797         uint32_t val;
798
799         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, coef_idx));
800         val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid));
801         return val;
802 }
803
804 void
805 hda_write_coef_idx(device_t dev, nid_t nid, unsigned int coef_idx,
806                    unsigned coef_val)
807 {
808         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, coef_idx));
809         hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, coef_val));
810 }