1230130Smav/*- 2230130Smav * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3230130Smav * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4230130Smav * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org> 5230130Smav * All rights reserved. 6230130Smav * 7230130Smav * Redistribution and use in source and binary forms, with or without 8230130Smav * modification, are permitted provided that the following conditions 9230130Smav * are met: 10230130Smav * 1. Redistributions of source code must retain the above copyright 11230130Smav * notice, this list of conditions and the following disclaimer. 12230130Smav * 2. Redistributions in binary form must reproduce the above copyright 13230130Smav * notice, this list of conditions and the following disclaimer in the 14230130Smav * documentation and/or other materials provided with the distribution. 15230130Smav * 16230130Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17230130Smav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18230130Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19230130Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20230130Smav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21230130Smav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22230130Smav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23230130Smav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24230130Smav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25230130Smav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26230130Smav * SUCH DAMAGE. 27230130Smav */ 28230130Smav 29230130Smav/* 30230130Smav * Intel High Definition Audio (Audio function quirks) driver for FreeBSD. 31230130Smav */ 32230130Smav 33230130Smav#ifdef HAVE_KERNEL_OPTION_HEADERS 34230130Smav#include "opt_snd.h" 35230130Smav#endif 36230130Smav 37230130Smav#include <dev/sound/pcm/sound.h> 38230130Smav 39230130Smav#include <sys/ctype.h> 40230130Smav 41230130Smav#include <dev/sound/pci/hda/hdac.h> 42230130Smav#include <dev/sound/pci/hda/hdaa.h> 43230130Smav#include <dev/sound/pci/hda/hda_reg.h> 44230130Smav 45230130SmavSND_DECLARE_FILE("$FreeBSD: releng/11.0/sys/dev/sound/pci/hda/hdaa_patches.c 285723 2015-07-20 17:48:00Z mav $"); 46230130Smav 47230130Smavstatic const struct { 48230130Smav uint32_t model; 49230130Smav uint32_t id; 50248786Smav uint32_t subsystemid; 51230130Smav uint32_t set, unset; 52230130Smav uint32_t gpio; 53230130Smav} hdac_quirks[] = { 54230130Smav /* 55230130Smav * XXX Force stereo quirk. Monoural recording / playback 56230130Smav * on few codecs (especially ALC880) seems broken or 57230130Smav * perhaps unsupported. 58230130Smav */ 59248786Smav { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL, 60230130Smav HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0, 61230130Smav 0 }, 62248786Smav { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL, 63230130Smav 0, 0, 64230130Smav HDAA_GPIO_SET(0) }, 65248786Smav { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL, 66230130Smav 0, 0, 67230130Smav HDAA_GPIO_SET(0) }, 68248786Smav { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL, 69230130Smav 0, 0, 70230130Smav HDAA_GPIO_SET(0) }, 71248786Smav { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL, 72230130Smav 0, 0, 73230130Smav HDAA_GPIO_SET(0) }, 74248786Smav { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL, 75230130Smav 0, 0, 76230130Smav HDAA_GPIO_SET(0) }, 77248786Smav { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL, 78230130Smav 0, 0, 79230130Smav HDAA_GPIO_SET(0) }, 80248786Smav { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL, 81230130Smav HDAA_QUIRK_EAPDINV, 0, 82230130Smav 0 }, 83248786Smav { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL, 84230130Smav HDAA_QUIRK_EAPDINV, 0, 85230130Smav 0 }, 86248786Smav { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL, 87230130Smav HDAA_QUIRK_OVREF, 0, 88230130Smav 0 }, 89248786Smav { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL, 90230130Smav HDAA_QUIRK_OVREF, 0, 91230130Smav 0 }, 92248786Smav /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL, 93230130Smav HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 94230130Smav 0 },*/ 95248786Smav { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL, 96230130Smav 0, 0, 97230130Smav HDAA_GPIO_SET(1) }, 98248786Smav { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL, 99230130Smav HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0, 100230130Smav 0 }, 101248786Smav { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL, 102230130Smav HDAA_QUIRK_EAPDINV, 0, 103230130Smav 0 }, 104248786Smav { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL, 105230130Smav HDAA_QUIRK_OVREF50, 0, 106230130Smav HDAA_GPIO_SET(0) }, 107248786Smav { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL, 108230130Smav 0, 0, 109230130Smav HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) }, 110261507Shselasky { APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL, 111261507Shselasky 0, 0, 112261507Shselasky HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) }, 113248786Smav { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL, 114230130Smav 0, 0, 115230130Smav HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) }, 116261507Shselasky { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL, 117261507Shselasky 0, 0, 118261507Shselasky HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) }, 119261507Shselasky { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL, 120261507Shselasky 0, 0, 121261507Shselasky HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) }, 122248786Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL, 123230130Smav 0, 0, 124230130Smav HDAA_GPIO_SET(0) }, 125248786Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL, 126230130Smav 0, 0, 127230130Smav HDAA_GPIO_SET(2) }, 128248786Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL, 129230130Smav 0, 0, 130230130Smav HDAA_GPIO_SET(0) }, 131248786Smav { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL, 132230130Smav HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 133230130Smav 0 }, 134248786Smav { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL, 135230130Smav HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 136230130Smav 0 }, 137248786Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL, 138230130Smav 0, HDAA_QUIRK_FORCESTEREO, 139248786Smav 0 }, 140248786Smav /* Mac Pro 1,1 requires ovref for proper volume level. */ 141248786Smav { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00, 142248786Smav 0, HDAA_QUIRK_OVREF, 143230130Smav 0 } 144230130Smav}; 145230130Smav 146230130Smavstatic void 147230130Smavhdac_pin_patch(struct hdaa_widget *w) 148230130Smav{ 149230130Smav const char *patch = NULL; 150230130Smav uint32_t config, orig, id, subid; 151230130Smav nid_t nid = w->nid; 152230130Smav 153230130Smav config = orig = w->wclass.pin.config; 154230130Smav id = hdaa_codec_id(w->devinfo); 155242352Smav subid = hdaa_card_id(w->devinfo); 156230130Smav 157230130Smav /* XXX: Old patches require complete review. 158230130Smav * Now they may create more problem then solve due to 159230130Smav * incorrect associations. 160230130Smav */ 161230130Smav if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) { 162230130Smav switch (nid) { 163230130Smav case 26: 164230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 165230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 166230130Smav break; 167230130Smav case 27: 168230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 169230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 170230130Smav break; 171230130Smav default: 172230130Smav break; 173230130Smav } 174230130Smav } else if (id == HDA_CODEC_ALC880 && 175230130Smav (subid == CLEVO_D900T_SUBVENDOR || 176230130Smav subid == ASUS_M5200_SUBVENDOR)) { 177230130Smav /* 178230130Smav * Super broken BIOS 179230130Smav */ 180230130Smav switch (nid) { 181230130Smav case 24: /* MIC1 */ 182230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 183230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 184230130Smav break; 185230130Smav case 25: /* XXX MIC2 */ 186230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 187230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 188230130Smav break; 189230130Smav case 26: /* LINE1 */ 190230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 191230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 192230130Smav break; 193230130Smav case 27: /* XXX LINE2 */ 194230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 195230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 196230130Smav break; 197230130Smav case 28: /* CD */ 198230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 199230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 200230130Smav break; 201230130Smav } 202230130Smav } else if (id == HDA_CODEC_ALC883 && 203230130Smav (subid == MSI_MS034A_SUBVENDOR || 204230130Smav HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) { 205230130Smav switch (nid) { 206230130Smav case 25: 207230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 208230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 209230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 210230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 211230130Smav break; 212230130Smav case 28: 213230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 214230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 215230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 216230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 217230130Smav break; 218230130Smav } 219230130Smav } else if (id == HDA_CODEC_CX20549 && subid == 220230130Smav HP_V3000_SUBVENDOR) { 221230130Smav switch (nid) { 222230130Smav case 18: 223230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 224230130Smav config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 225230130Smav break; 226230130Smav case 20: 227230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 228230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 229230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 230230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 231230130Smav break; 232230130Smav case 21: 233230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 234230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 235230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 236230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 237230130Smav break; 238230130Smav } 239230130Smav } else if (id == HDA_CODEC_CX20551 && subid == 240230130Smav HP_DV5000_SUBVENDOR) { 241230130Smav switch (nid) { 242230130Smav case 20: 243230130Smav case 21: 244230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 245230130Smav config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 246230130Smav break; 247230130Smav } 248230130Smav } else if (id == HDA_CODEC_ALC861 && subid == 249230130Smav ASUS_W6F_SUBVENDOR) { 250230130Smav switch (nid) { 251230130Smav case 11: 252230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 253230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 254230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 255230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 256230130Smav break; 257230130Smav case 12: 258230130Smav case 14: 259230130Smav case 16: 260230130Smav case 31: 261230130Smav case 32: 262230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 263230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 264230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 265230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 266230130Smav break; 267230130Smav case 15: 268230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 269230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 270230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 271230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 272230130Smav break; 273230130Smav } 274230130Smav } else if (id == HDA_CODEC_ALC861 && subid == 275230130Smav UNIWILL_9075_SUBVENDOR) { 276230130Smav switch (nid) { 277230130Smav case 15: 278230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 279230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 280230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 281230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 282230130Smav break; 283230130Smav } 284230130Smav } 285230130Smav 286230130Smav /* New patches */ 287244145Smav if (id == HDA_CODEC_AD1984A && 288244145Smav subid == LENOVO_X300_SUBVENDOR) { 289244145Smav switch (nid) { 290244145Smav case 17: /* Headphones with redirection */ 291244145Smav patch = "as=1 seq=15"; 292244145Smav break; 293244145Smav case 20: /* Two mics together */ 294244145Smav patch = "as=2 seq=15"; 295244145Smav break; 296244145Smav } 297244145Smav } else if (id == HDA_CODEC_AD1986A && 298230130Smav (subid == ASUS_M2NPVMX_SUBVENDOR || 299230130Smav subid == ASUS_A8NVMCSM_SUBVENDOR || 300230130Smav subid == ASUS_P5PL2_SUBVENDOR)) { 301230130Smav switch (nid) { 302230130Smav case 26: /* Headphones with redirection */ 303230130Smav patch = "as=1 seq=15"; 304230130Smav break; 305230130Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 306230130Smav patch = "device=Line-in as=8 seq=1"; 307230130Smav break; 308230130Smav case 29: /* Can't use this as input, as the only available mic 309230130Smav * preamplifier is busy by front panel mic (nid 31). 310230130Smav * If you want to use this rear connector as mic input, 311230130Smav * you have to disable the front panel one. */ 312230130Smav patch = "as=0"; 313230130Smav break; 314230130Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 315230130Smav patch = "as=8 seq=3"; 316230130Smav break; 317230130Smav case 32: 318230130Smav patch = "as=8 seq=4"; 319230130Smav break; 320230130Smav case 34: 321230130Smav patch = "as=8 seq=5"; 322230130Smav break; 323230130Smav case 36: 324230130Smav patch = "as=8 seq=6"; 325230130Smav break; 326230130Smav } 327230130Smav } else if (id == HDA_CODEC_ALC260 && 328230130Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) { 329230130Smav switch (nid) { 330230130Smav case 16: 331230130Smav patch = "seq=15 device=Headphones"; 332230130Smav break; 333230130Smav } 334230130Smav } else if (id == HDA_CODEC_ALC268) { 335230130Smav if (subid == ACER_T5320_SUBVENDOR) { 336230130Smav switch (nid) { 337230130Smav case 20: /* Headphones Jack */ 338230130Smav patch = "as=1 seq=15"; 339230130Smav break; 340230130Smav } 341230130Smav } 342230130Smav } else if (id == HDA_CODEC_CX20561 && 343230130Smav subid == LENOVO_B450_SUBVENDOR) { 344230130Smav switch (nid) { 345230130Smav case 22: 346230130Smav patch = "as=1 seq=15"; 347230130Smav break; 348230130Smav } 349269152Sadrian } else if (id == HDA_CODEC_CX20561 && 350269152Sadrian subid == LENOVO_T400_SUBVENDOR) { 351269152Sadrian switch (nid) { 352269152Sadrian case 22: 353269152Sadrian patch = "as=1 seq=15"; 354269152Sadrian break; 355269152Sadrian case 26: 356269152Sadrian patch = "as=1 seq=0"; 357269152Sadrian break; 358269152Sadrian } 359247815Smav } else if (id == HDA_CODEC_CX20590 && 360247911Sglebius (subid == LENOVO_X1_SUBVENDOR || 361247911Sglebius subid == LENOVO_X220_SUBVENDOR || 362247911Sglebius subid == LENOVO_T420_SUBVENDOR || 363268584Smarkj subid == LENOVO_T520_SUBVENDOR || 364268584Smarkj subid == LENOVO_G580_SUBVENDOR)) { 365247815Smav switch (nid) { 366247815Smav case 25: 367247815Smav patch = "as=1 seq=15"; 368247815Smav break; 369264831Smarius /* 370250797Ssbruno * Group onboard mic and headphone mic 371250797Ssbruno * together. Fixes onboard mic. 372250797Ssbruno */ 373250797Ssbruno case 27: 374250797Ssbruno patch = "as=2 seq=15"; 375250797Ssbruno break; 376250797Ssbruno case 35: 377250797Ssbruno patch = "as=2"; 378250797Ssbruno break; 379247815Smav } 380247911Sglebius } else if (id == HDA_CODEC_ALC269 && 381248187Sglebius (subid == LENOVO_X1CRBN_SUBVENDOR || 382248187Sglebius subid == LENOVO_T430_SUBVENDOR || 383248254Sdelphij subid == LENOVO_T430S_SUBVENDOR || 384248254Sdelphij subid == LENOVO_T530_SUBVENDOR)) { 385247911Sglebius switch (nid) { 386247911Sglebius case 21: 387247911Sglebius patch = "as=1 seq=15"; 388247911Sglebius break; 389247911Sglebius } 390253036Smav } else if (id == HDA_CODEC_ALC269 && 391253036Smav subid == ASUS_UX31A_SUBVENDOR) { 392253036Smav switch (nid) { 393253036Smav case 33: 394253036Smav patch = "as=1 seq=15"; 395253036Smav break; 396253036Smav } 397264831Smarius } else if (id == HDA_CODEC_ALC892 && 398264831Smarius subid == INTEL_DH87RL_SUBVENDOR) { 399264831Smarius switch (nid) { 400264831Smarius case 27: 401264831Smarius patch = "as=1 seq=15"; 402264831Smarius break; 403264831Smarius } 404281544Srpaulo } else if (id == HDA_CODEC_ALC292 && 405281544Srpaulo subid == LENOVO_X120BS_SUBVENDOR) { 406281544Srpaulo switch (nid) { 407281544Srpaulo case 21: 408281544Srpaulo patch = "as=1 seq=15"; 409281544Srpaulo break; 410281544Srpaulo } 411230130Smav } 412230130Smav 413230130Smav if (patch != NULL) 414230130Smav config = hdaa_widget_pin_patch(config, patch); 415230130Smav HDA_BOOTVERBOSE( 416230130Smav if (config != orig) 417230130Smav device_printf(w->devinfo->dev, 418230130Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 419230130Smav nid, orig, config); 420230130Smav ); 421230130Smav w->wclass.pin.config = config; 422230130Smav} 423230130Smav 424230130Smavstatic void 425230130Smavhdaa_widget_patch(struct hdaa_widget *w) 426230130Smav{ 427230130Smav struct hdaa_devinfo *devinfo = w->devinfo; 428230130Smav uint32_t orig; 429230130Smav nid_t beeper = -1; 430230130Smav 431230130Smav orig = w->param.widget_cap; 432230130Smav /* On some codecs beeper is an input pin, but it is not recordable 433230130Smav alone. Also most of BIOSes does not declare beeper pin. 434230130Smav Change beeper pin node type to beeper to help parser. */ 435230130Smav switch (hdaa_codec_id(devinfo)) { 436230130Smav case HDA_CODEC_AD1882: 437230130Smav case HDA_CODEC_AD1883: 438230130Smav case HDA_CODEC_AD1984: 439230130Smav case HDA_CODEC_AD1984A: 440230130Smav case HDA_CODEC_AD1984B: 441230130Smav case HDA_CODEC_AD1987: 442230130Smav case HDA_CODEC_AD1988: 443230130Smav case HDA_CODEC_AD1988B: 444230130Smav case HDA_CODEC_AD1989B: 445230130Smav beeper = 26; 446230130Smav break; 447230130Smav case HDA_CODEC_ALC260: 448230130Smav beeper = 23; 449230130Smav break; 450230130Smav } 451230130Smav if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 452230130Smav hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 453230130Smav beeper = 29; 454230130Smav if (w->nid == beeper) { 455230130Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 456230130Smav w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 457230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 458230130Smav w->waspin = 1; 459230130Smav } 460244145Smav /* 461244145Smav * Clear "digital" flag from digital mic input, as its signal then goes 462244145Smav * to "analog" mixer and this separation just limits functionaity. 463244145Smav */ 464244145Smav if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 465244145Smav w->nid == 23) 466244145Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 467230130Smav HDA_BOOTVERBOSE( 468230130Smav if (w->param.widget_cap != orig) { 469230130Smav device_printf(w->devinfo->dev, 470230130Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 471230130Smav w->nid, orig, w->param.widget_cap); 472230130Smav } 473230130Smav ); 474230130Smav 475230130Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 476230130Smav hdac_pin_patch(w); 477230130Smav} 478230130Smav 479230130Smavvoid 480230130Smavhdaa_patch(struct hdaa_devinfo *devinfo) 481230130Smav{ 482230130Smav struct hdaa_widget *w; 483248786Smav uint32_t id, subid, subsystemid; 484230130Smav int i; 485230130Smav 486230130Smav id = hdaa_codec_id(devinfo); 487242352Smav subid = hdaa_card_id(devinfo); 488248786Smav subsystemid = hda_get_subsystem_id(devinfo->dev); 489230130Smav 490230130Smav /* 491230130Smav * Quirks 492230130Smav */ 493261508Shselasky for (i = 0; i < nitems(hdac_quirks); i++) { 494230130Smav if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 495248786Smav HDA_DEV_MATCH(hdac_quirks[i].id, id) && 496248786Smav HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid))) 497230130Smav continue; 498238011Smav devinfo->quirks |= hdac_quirks[i].set; 499238011Smav devinfo->quirks &= ~(hdac_quirks[i].unset); 500238011Smav devinfo->gpio = hdac_quirks[i].gpio; 501230130Smav } 502230130Smav 503230130Smav /* Apply per-widget patch. */ 504230130Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 505230130Smav w = hdaa_widget_get(devinfo, i); 506230130Smav if (w == NULL) 507230130Smav continue; 508230130Smav hdaa_widget_patch(w); 509230130Smav } 510230130Smav 511230130Smav switch (id) { 512230130Smav case HDA_CODEC_AD1983: 513230130Smav /* 514230130Smav * This CODEC has several possible usages, but none 515230130Smav * fit the parser best. Help parser to choose better. 516230130Smav */ 517230130Smav /* Disable direct unmixed playback to get pcm volume. */ 518230130Smav w = hdaa_widget_get(devinfo, 5); 519230130Smav if (w != NULL) 520230130Smav w->connsenable[0] = 0; 521230130Smav w = hdaa_widget_get(devinfo, 6); 522230130Smav if (w != NULL) 523230130Smav w->connsenable[0] = 0; 524230130Smav w = hdaa_widget_get(devinfo, 11); 525230130Smav if (w != NULL) 526230130Smav w->connsenable[0] = 0; 527230130Smav /* Disable mic and line selectors. */ 528230130Smav w = hdaa_widget_get(devinfo, 12); 529230130Smav if (w != NULL) 530230130Smav w->connsenable[1] = 0; 531230130Smav w = hdaa_widget_get(devinfo, 13); 532230130Smav if (w != NULL) 533230130Smav w->connsenable[1] = 0; 534230130Smav /* Disable recording from mono playback mix. */ 535230130Smav w = hdaa_widget_get(devinfo, 20); 536230130Smav if (w != NULL) 537230130Smav w->connsenable[3] = 0; 538230130Smav break; 539230130Smav case HDA_CODEC_AD1986A: 540230130Smav /* 541230130Smav * This CODEC has overcomplicated input mixing. 542230130Smav * Make some cleaning there. 543230130Smav */ 544230130Smav /* Disable input mono mixer. Not needed and not supported. */ 545230130Smav w = hdaa_widget_get(devinfo, 43); 546230130Smav if (w != NULL) 547230130Smav w->enable = 0; 548230130Smav /* Disable any with any input mixing mesh. Use separately. */ 549230130Smav w = hdaa_widget_get(devinfo, 39); 550230130Smav if (w != NULL) 551230130Smav w->enable = 0; 552230130Smav w = hdaa_widget_get(devinfo, 40); 553230130Smav if (w != NULL) 554230130Smav w->enable = 0; 555230130Smav w = hdaa_widget_get(devinfo, 41); 556230130Smav if (w != NULL) 557230130Smav w->enable = 0; 558230130Smav w = hdaa_widget_get(devinfo, 42); 559230130Smav if (w != NULL) 560230130Smav w->enable = 0; 561230130Smav /* Disable duplicate mixer node connector. */ 562230130Smav w = hdaa_widget_get(devinfo, 15); 563230130Smav if (w != NULL) 564230130Smav w->connsenable[3] = 0; 565230130Smav /* There is only one mic preamplifier, use it effectively. */ 566230130Smav w = hdaa_widget_get(devinfo, 31); 567230130Smav if (w != NULL) { 568230130Smav if ((w->wclass.pin.config & 569230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 570230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 571230130Smav w = hdaa_widget_get(devinfo, 16); 572230130Smav if (w != NULL) 573230130Smav w->connsenable[2] = 0; 574230130Smav } else { 575230130Smav w = hdaa_widget_get(devinfo, 15); 576230130Smav if (w != NULL) 577230130Smav w->connsenable[0] = 0; 578230130Smav } 579230130Smav } 580230130Smav w = hdaa_widget_get(devinfo, 32); 581230130Smav if (w != NULL) { 582230130Smav if ((w->wclass.pin.config & 583230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 584230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 585230130Smav w = hdaa_widget_get(devinfo, 16); 586230130Smav if (w != NULL) 587230130Smav w->connsenable[0] = 0; 588230130Smav } else { 589230130Smav w = hdaa_widget_get(devinfo, 15); 590230130Smav if (w != NULL) 591230130Smav w->connsenable[1] = 0; 592230130Smav } 593230130Smav } 594230130Smav 595230130Smav if (subid == ASUS_A8X_SUBVENDOR) { 596230130Smav /* 597230130Smav * This is just plain ridiculous.. There 598230130Smav * are several A8 series that share the same 599230130Smav * pci id but works differently (EAPD). 600230130Smav */ 601230130Smav w = hdaa_widget_get(devinfo, 26); 602230130Smav if (w != NULL && w->type == 603230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 604230130Smav (w->wclass.pin.config & 605230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 606230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 607230130Smav devinfo->quirks &= 608230130Smav ~HDAA_QUIRK_EAPDINV; 609230130Smav } 610230130Smav break; 611230130Smav case HDA_CODEC_AD1981HD: 612230130Smav /* 613230130Smav * This CODEC has very unusual design with several 614230130Smav * points inappropriate for the present parser. 615230130Smav */ 616230130Smav /* Disable recording from mono playback mix. */ 617230130Smav w = hdaa_widget_get(devinfo, 21); 618230130Smav if (w != NULL) 619230130Smav w->connsenable[3] = 0; 620230130Smav /* Disable rear to front mic mixer, use separately. */ 621230130Smav w = hdaa_widget_get(devinfo, 31); 622230130Smav if (w != NULL) 623230130Smav w->enable = 0; 624230130Smav /* Disable direct playback, use mixer. */ 625230130Smav w = hdaa_widget_get(devinfo, 5); 626230130Smav if (w != NULL) 627230130Smav w->connsenable[0] = 0; 628230130Smav w = hdaa_widget_get(devinfo, 6); 629230130Smav if (w != NULL) 630230130Smav w->connsenable[0] = 0; 631230130Smav w = hdaa_widget_get(devinfo, 9); 632230130Smav if (w != NULL) 633230130Smav w->connsenable[0] = 0; 634230130Smav w = hdaa_widget_get(devinfo, 24); 635230130Smav if (w != NULL) 636230130Smav w->connsenable[0] = 0; 637230130Smav break; 638242417Smav case HDA_CODEC_ALC269: 639242417Smav /* 640242417Smav * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 641242417Smav * that mutes speaker if unused mixer at NID 15 is muted. 642242417Smav * Probably CODEC incorrectly reports internal connections. 643242417Smav * Hide that muter from the driver. There are several CODECs 644242417Smav * sharing this ID and I have not enough information about 645242417Smav * them to implement more universal solution. 646242417Smav */ 647242417Smav if (subid == 0x84371043) { 648242417Smav w = hdaa_widget_get(devinfo, 15); 649242417Smav if (w != NULL) 650242417Smav w->param.inamp_cap = 0; 651242417Smav } 652242417Smav break; 653230130Smav case HDA_CODEC_CX20582: 654230130Smav case HDA_CODEC_CX20583: 655230130Smav case HDA_CODEC_CX20584: 656230130Smav case HDA_CODEC_CX20585: 657230130Smav case HDA_CODEC_CX20590: 658230130Smav /* 659230130Smav * These codecs have extra connectivity on record side 660230130Smav * too reach for the present parser. 661230130Smav */ 662230130Smav w = hdaa_widget_get(devinfo, 20); 663230130Smav if (w != NULL) 664230130Smav w->connsenable[1] = 0; 665230130Smav w = hdaa_widget_get(devinfo, 21); 666230130Smav if (w != NULL) 667230130Smav w->connsenable[1] = 0; 668230130Smav w = hdaa_widget_get(devinfo, 22); 669230130Smav if (w != NULL) 670230130Smav w->connsenable[0] = 0; 671230130Smav break; 672230130Smav case HDA_CODEC_VT1708S_0: 673230130Smav case HDA_CODEC_VT1708S_1: 674230130Smav case HDA_CODEC_VT1708S_2: 675230130Smav case HDA_CODEC_VT1708S_3: 676230130Smav case HDA_CODEC_VT1708S_4: 677230130Smav case HDA_CODEC_VT1708S_5: 678230130Smav case HDA_CODEC_VT1708S_6: 679230130Smav case HDA_CODEC_VT1708S_7: 680230130Smav /* 681230130Smav * These codecs have hidden mic boost controls. 682230130Smav */ 683230130Smav w = hdaa_widget_get(devinfo, 26); 684230130Smav if (w != NULL) 685230130Smav w->param.inamp_cap = 686230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 687230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 688230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 689230130Smav w = hdaa_widget_get(devinfo, 30); 690230130Smav if (w != NULL) 691230130Smav w->param.inamp_cap = 692230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 693230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 694230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 695230130Smav break; 696230130Smav } 697230130Smav} 698230130Smav 699285723Smavstatic uint32_t 700285723Smavhdaa_read_coef(device_t dev, nid_t nid, uint16_t idx) 701285723Smav{ 702285723Smav 703285723Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx)); 704285723Smav return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid))); 705285723Smav} 706285723Smav 707285723Smavstatic uint32_t 708285723Smavhdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val) 709285723Smav{ 710285723Smav 711285723Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx)); 712285723Smav return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val))); 713285723Smav} 714285723Smav 715230130Smavvoid 716230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo) 717230130Smav{ 718230130Smav device_t dev = devinfo->dev; 719230130Smav uint32_t id, subid, val; 720230130Smav 721230130Smav id = hdaa_codec_id(devinfo); 722242352Smav subid = hdaa_card_id(devinfo); 723230130Smav 724230130Smav switch (id) { 725230130Smav case HDA_CODEC_VT1708S_0: 726230130Smav case HDA_CODEC_VT1708S_1: 727230130Smav case HDA_CODEC_VT1708S_2: 728230130Smav case HDA_CODEC_VT1708S_3: 729230130Smav case HDA_CODEC_VT1708S_4: 730230130Smav case HDA_CODEC_VT1708S_5: 731230130Smav case HDA_CODEC_VT1708S_6: 732230130Smav case HDA_CODEC_VT1708S_7: 733230130Smav /* Enable Mic Boost Volume controls. */ 734230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 735230130Smav 0xf98, 0x01)); 736241375Smav /* Fall though */ 737241375Smav case HDA_CODEC_VT1818S: 738230130Smav /* Don't bypass mixer. */ 739230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 740230130Smav 0xf88, 0xc0)); 741230130Smav break; 742230130Smav } 743230130Smav if (subid == APPLE_INTEL_MAC) 744230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 745230130Smav 0x7e7, 0)); 746230130Smav if (id == HDA_CODEC_ALC269) { 747230532Smav if (subid == 0x16e31043 || subid == 0x831a1043 || 748230532Smav subid == 0x834a1043 || subid == 0x83981043 || 749230532Smav subid == 0x83ce1043) { 750230130Smav /* 751230130Smav * The ditital mics on some Asus laptops produce 752230130Smav * differential signals instead of expected stereo. 753230130Smav * That results in silence if downmix it to mono. 754230130Smav * To workaround, make codec to handle signal as mono. 755230130Smav */ 756285723Smav val = hdaa_read_coef(dev, 0x20, 0x07); 757285723Smav hdaa_write_coef(dev, 0x20, 0x07, val|0x80); 758230130Smav } 759285723Smav if (subid == 0x15171043) { 760285723Smav /* Increase output amp on ASUS UX31A by +5dB. */ 761285723Smav hdaa_write_coef(dev, 0x20, 0x12, 0x2800); 762285723Smav } 763230130Smav } 764230130Smav} 765