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: stable/11/sys/dev/sound/pci/hda/hdaa_patches.c 351814 2019-09-04 14:05:04Z jkim $"); 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 } 390351814Sjkim } else if (id == HDA_CODEC_ALC285 && 391351814Sjkim subid == LENOVO_X120KH_SUBVENDOR) { 392351814Sjkim switch (nid) { 393351814Sjkim case 33: 394351814Sjkim patch = "as=1 seq=15"; 395351814Sjkim break; 396351814Sjkim } 397253036Smav } else if (id == HDA_CODEC_ALC269 && 398253036Smav subid == ASUS_UX31A_SUBVENDOR) { 399253036Smav switch (nid) { 400253036Smav case 33: 401253036Smav patch = "as=1 seq=15"; 402253036Smav break; 403253036Smav } 404264831Smarius } else if (id == HDA_CODEC_ALC892 && 405264831Smarius subid == INTEL_DH87RL_SUBVENDOR) { 406264831Smarius switch (nid) { 407264831Smarius case 27: 408264831Smarius patch = "as=1 seq=15"; 409264831Smarius break; 410264831Smarius } 411281544Srpaulo } else if (id == HDA_CODEC_ALC292 && 412281544Srpaulo subid == LENOVO_X120BS_SUBVENDOR) { 413281544Srpaulo switch (nid) { 414281544Srpaulo case 21: 415281544Srpaulo patch = "as=1 seq=15"; 416281544Srpaulo break; 417281544Srpaulo } 418230130Smav } 419230130Smav 420230130Smav if (patch != NULL) 421230130Smav config = hdaa_widget_pin_patch(config, patch); 422230130Smav HDA_BOOTVERBOSE( 423230130Smav if (config != orig) 424230130Smav device_printf(w->devinfo->dev, 425230130Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 426230130Smav nid, orig, config); 427230130Smav ); 428230130Smav w->wclass.pin.config = config; 429230130Smav} 430230130Smav 431230130Smavstatic void 432230130Smavhdaa_widget_patch(struct hdaa_widget *w) 433230130Smav{ 434230130Smav struct hdaa_devinfo *devinfo = w->devinfo; 435230130Smav uint32_t orig; 436230130Smav nid_t beeper = -1; 437230130Smav 438230130Smav orig = w->param.widget_cap; 439230130Smav /* On some codecs beeper is an input pin, but it is not recordable 440230130Smav alone. Also most of BIOSes does not declare beeper pin. 441230130Smav Change beeper pin node type to beeper to help parser. */ 442230130Smav switch (hdaa_codec_id(devinfo)) { 443230130Smav case HDA_CODEC_AD1882: 444230130Smav case HDA_CODEC_AD1883: 445230130Smav case HDA_CODEC_AD1984: 446230130Smav case HDA_CODEC_AD1984A: 447230130Smav case HDA_CODEC_AD1984B: 448230130Smav case HDA_CODEC_AD1987: 449230130Smav case HDA_CODEC_AD1988: 450230130Smav case HDA_CODEC_AD1988B: 451230130Smav case HDA_CODEC_AD1989B: 452230130Smav beeper = 26; 453230130Smav break; 454230130Smav case HDA_CODEC_ALC260: 455230130Smav beeper = 23; 456230130Smav break; 457230130Smav } 458230130Smav if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 459230130Smav hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 460230130Smav beeper = 29; 461230130Smav if (w->nid == beeper) { 462230130Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 463230130Smav w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 464230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 465230130Smav w->waspin = 1; 466230130Smav } 467244145Smav /* 468244145Smav * Clear "digital" flag from digital mic input, as its signal then goes 469244145Smav * to "analog" mixer and this separation just limits functionaity. 470244145Smav */ 471244145Smav if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 472244145Smav w->nid == 23) 473244145Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 474230130Smav HDA_BOOTVERBOSE( 475230130Smav if (w->param.widget_cap != orig) { 476230130Smav device_printf(w->devinfo->dev, 477230130Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 478230130Smav w->nid, orig, w->param.widget_cap); 479230130Smav } 480230130Smav ); 481230130Smav 482230130Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 483230130Smav hdac_pin_patch(w); 484230130Smav} 485230130Smav 486230130Smavvoid 487230130Smavhdaa_patch(struct hdaa_devinfo *devinfo) 488230130Smav{ 489230130Smav struct hdaa_widget *w; 490248786Smav uint32_t id, subid, subsystemid; 491230130Smav int i; 492230130Smav 493230130Smav id = hdaa_codec_id(devinfo); 494242352Smav subid = hdaa_card_id(devinfo); 495248786Smav subsystemid = hda_get_subsystem_id(devinfo->dev); 496230130Smav 497230130Smav /* 498230130Smav * Quirks 499230130Smav */ 500261508Shselasky for (i = 0; i < nitems(hdac_quirks); i++) { 501230130Smav if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 502248786Smav HDA_DEV_MATCH(hdac_quirks[i].id, id) && 503248786Smav HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid))) 504230130Smav continue; 505238011Smav devinfo->quirks |= hdac_quirks[i].set; 506238011Smav devinfo->quirks &= ~(hdac_quirks[i].unset); 507238011Smav devinfo->gpio = hdac_quirks[i].gpio; 508230130Smav } 509230130Smav 510230130Smav /* Apply per-widget patch. */ 511230130Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 512230130Smav w = hdaa_widget_get(devinfo, i); 513230130Smav if (w == NULL) 514230130Smav continue; 515230130Smav hdaa_widget_patch(w); 516230130Smav } 517230130Smav 518230130Smav switch (id) { 519230130Smav case HDA_CODEC_AD1983: 520230130Smav /* 521230130Smav * This CODEC has several possible usages, but none 522230130Smav * fit the parser best. Help parser to choose better. 523230130Smav */ 524230130Smav /* Disable direct unmixed playback to get pcm volume. */ 525230130Smav w = hdaa_widget_get(devinfo, 5); 526230130Smav if (w != NULL) 527230130Smav w->connsenable[0] = 0; 528230130Smav w = hdaa_widget_get(devinfo, 6); 529230130Smav if (w != NULL) 530230130Smav w->connsenable[0] = 0; 531230130Smav w = hdaa_widget_get(devinfo, 11); 532230130Smav if (w != NULL) 533230130Smav w->connsenable[0] = 0; 534230130Smav /* Disable mic and line selectors. */ 535230130Smav w = hdaa_widget_get(devinfo, 12); 536230130Smav if (w != NULL) 537230130Smav w->connsenable[1] = 0; 538230130Smav w = hdaa_widget_get(devinfo, 13); 539230130Smav if (w != NULL) 540230130Smav w->connsenable[1] = 0; 541230130Smav /* Disable recording from mono playback mix. */ 542230130Smav w = hdaa_widget_get(devinfo, 20); 543230130Smav if (w != NULL) 544230130Smav w->connsenable[3] = 0; 545230130Smav break; 546230130Smav case HDA_CODEC_AD1986A: 547230130Smav /* 548230130Smav * This CODEC has overcomplicated input mixing. 549230130Smav * Make some cleaning there. 550230130Smav */ 551230130Smav /* Disable input mono mixer. Not needed and not supported. */ 552230130Smav w = hdaa_widget_get(devinfo, 43); 553230130Smav if (w != NULL) 554230130Smav w->enable = 0; 555230130Smav /* Disable any with any input mixing mesh. Use separately. */ 556230130Smav w = hdaa_widget_get(devinfo, 39); 557230130Smav if (w != NULL) 558230130Smav w->enable = 0; 559230130Smav w = hdaa_widget_get(devinfo, 40); 560230130Smav if (w != NULL) 561230130Smav w->enable = 0; 562230130Smav w = hdaa_widget_get(devinfo, 41); 563230130Smav if (w != NULL) 564230130Smav w->enable = 0; 565230130Smav w = hdaa_widget_get(devinfo, 42); 566230130Smav if (w != NULL) 567230130Smav w->enable = 0; 568230130Smav /* Disable duplicate mixer node connector. */ 569230130Smav w = hdaa_widget_get(devinfo, 15); 570230130Smav if (w != NULL) 571230130Smav w->connsenable[3] = 0; 572230130Smav /* There is only one mic preamplifier, use it effectively. */ 573230130Smav w = hdaa_widget_get(devinfo, 31); 574230130Smav if (w != NULL) { 575230130Smav if ((w->wclass.pin.config & 576230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 577230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 578230130Smav w = hdaa_widget_get(devinfo, 16); 579230130Smav if (w != NULL) 580230130Smav w->connsenable[2] = 0; 581230130Smav } else { 582230130Smav w = hdaa_widget_get(devinfo, 15); 583230130Smav if (w != NULL) 584230130Smav w->connsenable[0] = 0; 585230130Smav } 586230130Smav } 587230130Smav w = hdaa_widget_get(devinfo, 32); 588230130Smav if (w != NULL) { 589230130Smav if ((w->wclass.pin.config & 590230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 591230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 592230130Smav w = hdaa_widget_get(devinfo, 16); 593230130Smav if (w != NULL) 594230130Smav w->connsenable[0] = 0; 595230130Smav } else { 596230130Smav w = hdaa_widget_get(devinfo, 15); 597230130Smav if (w != NULL) 598230130Smav w->connsenable[1] = 0; 599230130Smav } 600230130Smav } 601230130Smav 602230130Smav if (subid == ASUS_A8X_SUBVENDOR) { 603230130Smav /* 604230130Smav * This is just plain ridiculous.. There 605230130Smav * are several A8 series that share the same 606230130Smav * pci id but works differently (EAPD). 607230130Smav */ 608230130Smav w = hdaa_widget_get(devinfo, 26); 609230130Smav if (w != NULL && w->type == 610230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 611230130Smav (w->wclass.pin.config & 612230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 613230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 614230130Smav devinfo->quirks &= 615230130Smav ~HDAA_QUIRK_EAPDINV; 616230130Smav } 617230130Smav break; 618230130Smav case HDA_CODEC_AD1981HD: 619230130Smav /* 620230130Smav * This CODEC has very unusual design with several 621230130Smav * points inappropriate for the present parser. 622230130Smav */ 623230130Smav /* Disable recording from mono playback mix. */ 624230130Smav w = hdaa_widget_get(devinfo, 21); 625230130Smav if (w != NULL) 626230130Smav w->connsenable[3] = 0; 627230130Smav /* Disable rear to front mic mixer, use separately. */ 628230130Smav w = hdaa_widget_get(devinfo, 31); 629230130Smav if (w != NULL) 630230130Smav w->enable = 0; 631230130Smav /* Disable direct playback, use mixer. */ 632230130Smav w = hdaa_widget_get(devinfo, 5); 633230130Smav if (w != NULL) 634230130Smav w->connsenable[0] = 0; 635230130Smav w = hdaa_widget_get(devinfo, 6); 636230130Smav if (w != NULL) 637230130Smav w->connsenable[0] = 0; 638230130Smav w = hdaa_widget_get(devinfo, 9); 639230130Smav if (w != NULL) 640230130Smav w->connsenable[0] = 0; 641230130Smav w = hdaa_widget_get(devinfo, 24); 642230130Smav if (w != NULL) 643230130Smav w->connsenable[0] = 0; 644230130Smav break; 645242417Smav case HDA_CODEC_ALC269: 646242417Smav /* 647242417Smav * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 648242417Smav * that mutes speaker if unused mixer at NID 15 is muted. 649242417Smav * Probably CODEC incorrectly reports internal connections. 650242417Smav * Hide that muter from the driver. There are several CODECs 651242417Smav * sharing this ID and I have not enough information about 652242417Smav * them to implement more universal solution. 653242417Smav */ 654242417Smav if (subid == 0x84371043) { 655242417Smav w = hdaa_widget_get(devinfo, 15); 656242417Smav if (w != NULL) 657242417Smav w->param.inamp_cap = 0; 658242417Smav } 659242417Smav break; 660230130Smav case HDA_CODEC_CX20582: 661230130Smav case HDA_CODEC_CX20583: 662230130Smav case HDA_CODEC_CX20584: 663230130Smav case HDA_CODEC_CX20585: 664230130Smav case HDA_CODEC_CX20590: 665230130Smav /* 666230130Smav * These codecs have extra connectivity on record side 667230130Smav * too reach for the present parser. 668230130Smav */ 669230130Smav w = hdaa_widget_get(devinfo, 20); 670230130Smav if (w != NULL) 671230130Smav w->connsenable[1] = 0; 672230130Smav w = hdaa_widget_get(devinfo, 21); 673230130Smav if (w != NULL) 674230130Smav w->connsenable[1] = 0; 675230130Smav w = hdaa_widget_get(devinfo, 22); 676230130Smav if (w != NULL) 677230130Smav w->connsenable[0] = 0; 678230130Smav break; 679230130Smav case HDA_CODEC_VT1708S_0: 680230130Smav case HDA_CODEC_VT1708S_1: 681230130Smav case HDA_CODEC_VT1708S_2: 682230130Smav case HDA_CODEC_VT1708S_3: 683230130Smav case HDA_CODEC_VT1708S_4: 684230130Smav case HDA_CODEC_VT1708S_5: 685230130Smav case HDA_CODEC_VT1708S_6: 686230130Smav case HDA_CODEC_VT1708S_7: 687230130Smav /* 688230130Smav * These codecs have hidden mic boost controls. 689230130Smav */ 690230130Smav w = hdaa_widget_get(devinfo, 26); 691230130Smav if (w != NULL) 692230130Smav w->param.inamp_cap = 693230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 694230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 695230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 696230130Smav w = hdaa_widget_get(devinfo, 30); 697230130Smav if (w != NULL) 698230130Smav w->param.inamp_cap = 699230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 700230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 701230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 702230130Smav break; 703230130Smav } 704230130Smav} 705230130Smav 706285723Smavstatic uint32_t 707285723Smavhdaa_read_coef(device_t dev, nid_t nid, uint16_t idx) 708285723Smav{ 709285723Smav 710285723Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx)); 711285723Smav return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid))); 712285723Smav} 713285723Smav 714285723Smavstatic uint32_t 715285723Smavhdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val) 716285723Smav{ 717285723Smav 718285723Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx)); 719285723Smav return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val))); 720285723Smav} 721285723Smav 722230130Smavvoid 723230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo) 724230130Smav{ 725230130Smav device_t dev = devinfo->dev; 726230130Smav uint32_t id, subid, val; 727230130Smav 728230130Smav id = hdaa_codec_id(devinfo); 729242352Smav subid = hdaa_card_id(devinfo); 730230130Smav 731230130Smav switch (id) { 732230130Smav case HDA_CODEC_VT1708S_0: 733230130Smav case HDA_CODEC_VT1708S_1: 734230130Smav case HDA_CODEC_VT1708S_2: 735230130Smav case HDA_CODEC_VT1708S_3: 736230130Smav case HDA_CODEC_VT1708S_4: 737230130Smav case HDA_CODEC_VT1708S_5: 738230130Smav case HDA_CODEC_VT1708S_6: 739230130Smav case HDA_CODEC_VT1708S_7: 740230130Smav /* Enable Mic Boost Volume controls. */ 741230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 742230130Smav 0xf98, 0x01)); 743241375Smav /* Fall though */ 744241375Smav case HDA_CODEC_VT1818S: 745230130Smav /* Don't bypass mixer. */ 746230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 747230130Smav 0xf88, 0xc0)); 748230130Smav break; 749312366Syongari case HDA_CODEC_ALC1150: 750312366Syongari if (subid == 0xd9781462) { 751312366Syongari /* Too low volume on MSI H170 GAMING M3. */ 752312366Syongari hdaa_write_coef(dev, 0x20, 0x07, 0x7cb); 753312366Syongari } 754312366Syongari break; 755230130Smav } 756230130Smav if (subid == APPLE_INTEL_MAC) 757230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 758230130Smav 0x7e7, 0)); 759230130Smav if (id == HDA_CODEC_ALC269) { 760230532Smav if (subid == 0x16e31043 || subid == 0x831a1043 || 761230532Smav subid == 0x834a1043 || subid == 0x83981043 || 762230532Smav subid == 0x83ce1043) { 763230130Smav /* 764230130Smav * The ditital mics on some Asus laptops produce 765230130Smav * differential signals instead of expected stereo. 766230130Smav * That results in silence if downmix it to mono. 767230130Smav * To workaround, make codec to handle signal as mono. 768230130Smav */ 769285723Smav val = hdaa_read_coef(dev, 0x20, 0x07); 770285723Smav hdaa_write_coef(dev, 0x20, 0x07, val|0x80); 771230130Smav } 772285723Smav if (subid == 0x15171043) { 773285723Smav /* Increase output amp on ASUS UX31A by +5dB. */ 774285723Smav hdaa_write_coef(dev, 0x20, 0x12, 0x2800); 775285723Smav } 776230130Smav } 777230130Smav} 778