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