xref: /dragonfly/sys/dev/sound/pci/hda/hdaa_patches.c (revision 8fa945931144abe9f415a9bab98495195f5cd528)
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
hdac_pin_patch(struct hdaa_widget * w)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
hdaa_widget_patch(struct hdaa_widget * w)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
hdaa_patch(struct hdaa_devinfo * devinfo)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
hdaa_patch_direct(struct hdaa_devinfo * devinfo)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
hda_read_coef_idx(device_t dev,nid_t nid,unsigned int coef_idx)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
hda_write_coef_idx(device_t dev,nid_t nid,unsigned int coef_idx,unsigned coef_val)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 }
811