hdaa_patches.c revision 244145
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: head/sys/dev/sound/pci/hda/hdaa_patches.c 244145 2012-12-12 11:44:20Z mav $"); 46230130Smav 47230130Smavstatic const struct { 48230130Smav uint32_t model; 49230130Smav uint32_t id; 50230130Smav uint32_t set, unset; 51230130Smav uint32_t gpio; 52230130Smav} hdac_quirks[] = { 53230130Smav /* 54230130Smav * XXX Force stereo quirk. Monoural recording / playback 55230130Smav * on few codecs (especially ALC880) seems broken or 56230130Smav * perhaps unsupported. 57230130Smav */ 58230130Smav { HDA_MATCH_ALL, HDA_MATCH_ALL, 59230130Smav HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0, 60230130Smav 0 }, 61230130Smav { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 62230130Smav 0, 0, 63230130Smav HDAA_GPIO_SET(0) }, 64230130Smav { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 65230130Smav 0, 0, 66230130Smav HDAA_GPIO_SET(0) }, 67230130Smav { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 68230130Smav 0, 0, 69230130Smav HDAA_GPIO_SET(0) }, 70230130Smav { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 71230130Smav 0, 0, 72230130Smav HDAA_GPIO_SET(0) }, 73230130Smav { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 74230130Smav 0, 0, 75230130Smav HDAA_GPIO_SET(0) }, 76230130Smav { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 77230130Smav 0, 0, 78230130Smav HDAA_GPIO_SET(0) }, 79230130Smav { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 80230130Smav HDAA_QUIRK_EAPDINV, 0, 81230130Smav 0 }, 82230130Smav { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 83230130Smav HDAA_QUIRK_EAPDINV, 0, 84230130Smav 0 }, 85230130Smav { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 86230130Smav HDAA_QUIRK_OVREF, 0, 87230130Smav 0 }, 88230130Smav { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 89230130Smav HDAA_QUIRK_OVREF, 0, 90230130Smav 0 }, 91230130Smav /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 92230130Smav HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 93230130Smav 0 },*/ 94230130Smav { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 95230130Smav 0, 0, 96230130Smav HDAA_GPIO_SET(1) }, 97230130Smav { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 98230130Smav HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0, 99230130Smav 0 }, 100230130Smav { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 101230130Smav HDAA_QUIRK_EAPDINV, 0, 102230130Smav 0 }, 103230130Smav { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 104230130Smav HDAA_QUIRK_OVREF50, 0, 105230130Smav HDAA_GPIO_SET(0) }, 106230130Smav { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 107230130Smav 0, 0, 108230130Smav HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) }, 109230130Smav { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, 110230130Smav 0, 0, 111230130Smav HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) }, 112230130Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 113230130Smav 0, 0, 114230130Smav HDAA_GPIO_SET(0) }, 115230130Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 116230130Smav 0, 0, 117230130Smav HDAA_GPIO_SET(2) }, 118230130Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 119230130Smav 0, 0, 120230130Smav HDAA_GPIO_SET(0) }, 121230130Smav { HDA_MATCH_ALL, HDA_CODEC_AD1988, 122230130Smav HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 123230130Smav 0 }, 124230130Smav { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 125230130Smav HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 126230130Smav 0 }, 127230130Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 128230130Smav 0, HDAA_QUIRK_FORCESTEREO, 129230130Smav 0 } 130230130Smav}; 131230130Smav#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 132230130Smav 133230130Smavstatic void 134230130Smavhdac_pin_patch(struct hdaa_widget *w) 135230130Smav{ 136230130Smav const char *patch = NULL; 137230130Smav uint32_t config, orig, id, subid; 138230130Smav nid_t nid = w->nid; 139230130Smav 140230130Smav config = orig = w->wclass.pin.config; 141230130Smav id = hdaa_codec_id(w->devinfo); 142242352Smav subid = hdaa_card_id(w->devinfo); 143230130Smav 144230130Smav /* XXX: Old patches require complete review. 145230130Smav * Now they may create more problem then solve due to 146230130Smav * incorrect associations. 147230130Smav */ 148230130Smav if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) { 149230130Smav switch (nid) { 150230130Smav case 26: 151230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 152230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 153230130Smav break; 154230130Smav case 27: 155230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 156230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 157230130Smav break; 158230130Smav default: 159230130Smav break; 160230130Smav } 161230130Smav } else if (id == HDA_CODEC_ALC880 && 162230130Smav (subid == CLEVO_D900T_SUBVENDOR || 163230130Smav subid == ASUS_M5200_SUBVENDOR)) { 164230130Smav /* 165230130Smav * Super broken BIOS 166230130Smav */ 167230130Smav switch (nid) { 168230130Smav case 24: /* MIC1 */ 169230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 170230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 171230130Smav break; 172230130Smav case 25: /* XXX MIC2 */ 173230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 174230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 175230130Smav break; 176230130Smav case 26: /* LINE1 */ 177230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 178230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 179230130Smav break; 180230130Smav case 27: /* XXX LINE2 */ 181230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 182230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 183230130Smav break; 184230130Smav case 28: /* CD */ 185230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 186230130Smav config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 187230130Smav break; 188230130Smav } 189230130Smav } else if (id == HDA_CODEC_ALC883 && 190230130Smav (subid == MSI_MS034A_SUBVENDOR || 191230130Smav HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) { 192230130Smav switch (nid) { 193230130Smav case 25: 194230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 195230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 196230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 197230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 198230130Smav break; 199230130Smav case 28: 200230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 201230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 202230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 203230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 204230130Smav break; 205230130Smav } 206230130Smav } else if (id == HDA_CODEC_CX20549 && subid == 207230130Smav HP_V3000_SUBVENDOR) { 208230130Smav switch (nid) { 209230130Smav case 18: 210230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 211230130Smav config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 212230130Smav break; 213230130Smav case 20: 214230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 215230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 216230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 217230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 218230130Smav break; 219230130Smav case 21: 220230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 221230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 222230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 223230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 224230130Smav break; 225230130Smav } 226230130Smav } else if (id == HDA_CODEC_CX20551 && subid == 227230130Smav HP_DV5000_SUBVENDOR) { 228230130Smav switch (nid) { 229230130Smav case 20: 230230130Smav case 21: 231230130Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 232230130Smav config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 233230130Smav break; 234230130Smav } 235230130Smav } else if (id == HDA_CODEC_ALC861 && subid == 236230130Smav ASUS_W6F_SUBVENDOR) { 237230130Smav switch (nid) { 238230130Smav case 11: 239230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 240230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 241230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 242230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 243230130Smav break; 244230130Smav case 12: 245230130Smav case 14: 246230130Smav case 16: 247230130Smav case 31: 248230130Smav case 32: 249230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 250230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 251230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 252230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 253230130Smav break; 254230130Smav case 15: 255230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 256230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 257230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 258230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 259230130Smav break; 260230130Smav } 261230130Smav } else if (id == HDA_CODEC_ALC861 && subid == 262230130Smav UNIWILL_9075_SUBVENDOR) { 263230130Smav switch (nid) { 264230130Smav case 15: 265230130Smav config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 266230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 267230130Smav config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 268230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 269230130Smav break; 270230130Smav } 271230130Smav } 272230130Smav 273230130Smav /* New patches */ 274244145Smav if (id == HDA_CODEC_AD1984A && 275244145Smav subid == LENOVO_X300_SUBVENDOR) { 276244145Smav switch (nid) { 277244145Smav case 17: /* Headphones with redirection */ 278244145Smav patch = "as=1 seq=15"; 279244145Smav break; 280244145Smav case 20: /* Two mics together */ 281244145Smav patch = "as=2 seq=15"; 282244145Smav break; 283244145Smav } 284244145Smav } else if (id == HDA_CODEC_AD1986A && 285230130Smav (subid == ASUS_M2NPVMX_SUBVENDOR || 286230130Smav subid == ASUS_A8NVMCSM_SUBVENDOR || 287230130Smav subid == ASUS_P5PL2_SUBVENDOR)) { 288230130Smav switch (nid) { 289230130Smav case 26: /* Headphones with redirection */ 290230130Smav patch = "as=1 seq=15"; 291230130Smav break; 292230130Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 293230130Smav patch = "device=Line-in as=8 seq=1"; 294230130Smav break; 295230130Smav case 29: /* Can't use this as input, as the only available mic 296230130Smav * preamplifier is busy by front panel mic (nid 31). 297230130Smav * If you want to use this rear connector as mic input, 298230130Smav * you have to disable the front panel one. */ 299230130Smav patch = "as=0"; 300230130Smav break; 301230130Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 302230130Smav patch = "as=8 seq=3"; 303230130Smav break; 304230130Smav case 32: 305230130Smav patch = "as=8 seq=4"; 306230130Smav break; 307230130Smav case 34: 308230130Smav patch = "as=8 seq=5"; 309230130Smav break; 310230130Smav case 36: 311230130Smav patch = "as=8 seq=6"; 312230130Smav break; 313230130Smav } 314230130Smav } else if (id == HDA_CODEC_ALC260 && 315230130Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) { 316230130Smav switch (nid) { 317230130Smav case 16: 318230130Smav patch = "seq=15 device=Headphones"; 319230130Smav break; 320230130Smav } 321230130Smav } else if (id == HDA_CODEC_ALC268) { 322230130Smav if (subid == ACER_T5320_SUBVENDOR) { 323230130Smav switch (nid) { 324230130Smav case 20: /* Headphones Jack */ 325230130Smav patch = "as=1 seq=15"; 326230130Smav break; 327230130Smav } 328230130Smav } 329230130Smav } else if (id == HDA_CODEC_CX20561 && 330230130Smav subid == LENOVO_B450_SUBVENDOR) { 331230130Smav switch (nid) { 332230130Smav case 22: 333230130Smav patch = "as=1 seq=15"; 334230130Smav break; 335230130Smav } 336230130Smav } 337230130Smav 338230130Smav if (patch != NULL) 339230130Smav config = hdaa_widget_pin_patch(config, patch); 340230130Smav HDA_BOOTVERBOSE( 341230130Smav if (config != orig) 342230130Smav device_printf(w->devinfo->dev, 343230130Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 344230130Smav nid, orig, config); 345230130Smav ); 346230130Smav w->wclass.pin.config = config; 347230130Smav} 348230130Smav 349230130Smavstatic void 350230130Smavhdaa_widget_patch(struct hdaa_widget *w) 351230130Smav{ 352230130Smav struct hdaa_devinfo *devinfo = w->devinfo; 353230130Smav uint32_t orig; 354230130Smav nid_t beeper = -1; 355230130Smav 356230130Smav orig = w->param.widget_cap; 357230130Smav /* On some codecs beeper is an input pin, but it is not recordable 358230130Smav alone. Also most of BIOSes does not declare beeper pin. 359230130Smav Change beeper pin node type to beeper to help parser. */ 360230130Smav switch (hdaa_codec_id(devinfo)) { 361230130Smav case HDA_CODEC_AD1882: 362230130Smav case HDA_CODEC_AD1883: 363230130Smav case HDA_CODEC_AD1984: 364230130Smav case HDA_CODEC_AD1984A: 365230130Smav case HDA_CODEC_AD1984B: 366230130Smav case HDA_CODEC_AD1987: 367230130Smav case HDA_CODEC_AD1988: 368230130Smav case HDA_CODEC_AD1988B: 369230130Smav case HDA_CODEC_AD1989B: 370230130Smav beeper = 26; 371230130Smav break; 372230130Smav case HDA_CODEC_ALC260: 373230130Smav beeper = 23; 374230130Smav break; 375230130Smav } 376230130Smav if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 377230130Smav hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 378230130Smav beeper = 29; 379230130Smav if (w->nid == beeper) { 380230130Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 381230130Smav w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 382230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 383230130Smav w->waspin = 1; 384230130Smav } 385244145Smav /* 386244145Smav * Clear "digital" flag from digital mic input, as its signal then goes 387244145Smav * to "analog" mixer and this separation just limits functionaity. 388244145Smav */ 389244145Smav if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 390244145Smav w->nid == 23) 391244145Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 392230130Smav HDA_BOOTVERBOSE( 393230130Smav if (w->param.widget_cap != orig) { 394230130Smav device_printf(w->devinfo->dev, 395230130Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 396230130Smav w->nid, orig, w->param.widget_cap); 397230130Smav } 398230130Smav ); 399230130Smav 400230130Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 401230130Smav hdac_pin_patch(w); 402230130Smav} 403230130Smav 404230130Smavvoid 405230130Smavhdaa_patch(struct hdaa_devinfo *devinfo) 406230130Smav{ 407230130Smav struct hdaa_widget *w; 408230130Smav uint32_t id, subid; 409230130Smav int i; 410230130Smav 411230130Smav id = hdaa_codec_id(devinfo); 412242352Smav subid = hdaa_card_id(devinfo); 413230130Smav 414230130Smav /* 415230130Smav * Quirks 416230130Smav */ 417230130Smav for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 418230130Smav if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 419230130Smav HDA_DEV_MATCH(hdac_quirks[i].id, id))) 420230130Smav continue; 421238011Smav devinfo->quirks |= hdac_quirks[i].set; 422238011Smav devinfo->quirks &= ~(hdac_quirks[i].unset); 423238011Smav devinfo->gpio = hdac_quirks[i].gpio; 424230130Smav } 425230130Smav 426230130Smav /* Apply per-widget patch. */ 427230130Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 428230130Smav w = hdaa_widget_get(devinfo, i); 429230130Smav if (w == NULL) 430230130Smav continue; 431230130Smav hdaa_widget_patch(w); 432230130Smav } 433230130Smav 434230130Smav switch (id) { 435230130Smav case HDA_CODEC_AD1983: 436230130Smav /* 437230130Smav * This CODEC has several possible usages, but none 438230130Smav * fit the parser best. Help parser to choose better. 439230130Smav */ 440230130Smav /* Disable direct unmixed playback to get pcm volume. */ 441230130Smav w = hdaa_widget_get(devinfo, 5); 442230130Smav if (w != NULL) 443230130Smav w->connsenable[0] = 0; 444230130Smav w = hdaa_widget_get(devinfo, 6); 445230130Smav if (w != NULL) 446230130Smav w->connsenable[0] = 0; 447230130Smav w = hdaa_widget_get(devinfo, 11); 448230130Smav if (w != NULL) 449230130Smav w->connsenable[0] = 0; 450230130Smav /* Disable mic and line selectors. */ 451230130Smav w = hdaa_widget_get(devinfo, 12); 452230130Smav if (w != NULL) 453230130Smav w->connsenable[1] = 0; 454230130Smav w = hdaa_widget_get(devinfo, 13); 455230130Smav if (w != NULL) 456230130Smav w->connsenable[1] = 0; 457230130Smav /* Disable recording from mono playback mix. */ 458230130Smav w = hdaa_widget_get(devinfo, 20); 459230130Smav if (w != NULL) 460230130Smav w->connsenable[3] = 0; 461230130Smav break; 462230130Smav case HDA_CODEC_AD1986A: 463230130Smav /* 464230130Smav * This CODEC has overcomplicated input mixing. 465230130Smav * Make some cleaning there. 466230130Smav */ 467230130Smav /* Disable input mono mixer. Not needed and not supported. */ 468230130Smav w = hdaa_widget_get(devinfo, 43); 469230130Smav if (w != NULL) 470230130Smav w->enable = 0; 471230130Smav /* Disable any with any input mixing mesh. Use separately. */ 472230130Smav w = hdaa_widget_get(devinfo, 39); 473230130Smav if (w != NULL) 474230130Smav w->enable = 0; 475230130Smav w = hdaa_widget_get(devinfo, 40); 476230130Smav if (w != NULL) 477230130Smav w->enable = 0; 478230130Smav w = hdaa_widget_get(devinfo, 41); 479230130Smav if (w != NULL) 480230130Smav w->enable = 0; 481230130Smav w = hdaa_widget_get(devinfo, 42); 482230130Smav if (w != NULL) 483230130Smav w->enable = 0; 484230130Smav /* Disable duplicate mixer node connector. */ 485230130Smav w = hdaa_widget_get(devinfo, 15); 486230130Smav if (w != NULL) 487230130Smav w->connsenable[3] = 0; 488230130Smav /* There is only one mic preamplifier, use it effectively. */ 489230130Smav w = hdaa_widget_get(devinfo, 31); 490230130Smav if (w != NULL) { 491230130Smav if ((w->wclass.pin.config & 492230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 493230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 494230130Smav w = hdaa_widget_get(devinfo, 16); 495230130Smav if (w != NULL) 496230130Smav w->connsenable[2] = 0; 497230130Smav } else { 498230130Smav w = hdaa_widget_get(devinfo, 15); 499230130Smav if (w != NULL) 500230130Smav w->connsenable[0] = 0; 501230130Smav } 502230130Smav } 503230130Smav w = hdaa_widget_get(devinfo, 32); 504230130Smav if (w != NULL) { 505230130Smav if ((w->wclass.pin.config & 506230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 507230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 508230130Smav w = hdaa_widget_get(devinfo, 16); 509230130Smav if (w != NULL) 510230130Smav w->connsenable[0] = 0; 511230130Smav } else { 512230130Smav w = hdaa_widget_get(devinfo, 15); 513230130Smav if (w != NULL) 514230130Smav w->connsenable[1] = 0; 515230130Smav } 516230130Smav } 517230130Smav 518230130Smav if (subid == ASUS_A8X_SUBVENDOR) { 519230130Smav /* 520230130Smav * This is just plain ridiculous.. There 521230130Smav * are several A8 series that share the same 522230130Smav * pci id but works differently (EAPD). 523230130Smav */ 524230130Smav w = hdaa_widget_get(devinfo, 26); 525230130Smav if (w != NULL && w->type == 526230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 527230130Smav (w->wclass.pin.config & 528230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 529230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 530230130Smav devinfo->quirks &= 531230130Smav ~HDAA_QUIRK_EAPDINV; 532230130Smav } 533230130Smav break; 534230130Smav case HDA_CODEC_AD1981HD: 535230130Smav /* 536230130Smav * This CODEC has very unusual design with several 537230130Smav * points inappropriate for the present parser. 538230130Smav */ 539230130Smav /* Disable recording from mono playback mix. */ 540230130Smav w = hdaa_widget_get(devinfo, 21); 541230130Smav if (w != NULL) 542230130Smav w->connsenable[3] = 0; 543230130Smav /* Disable rear to front mic mixer, use separately. */ 544230130Smav w = hdaa_widget_get(devinfo, 31); 545230130Smav if (w != NULL) 546230130Smav w->enable = 0; 547230130Smav /* Disable direct playback, use mixer. */ 548230130Smav w = hdaa_widget_get(devinfo, 5); 549230130Smav if (w != NULL) 550230130Smav w->connsenable[0] = 0; 551230130Smav w = hdaa_widget_get(devinfo, 6); 552230130Smav if (w != NULL) 553230130Smav w->connsenable[0] = 0; 554230130Smav w = hdaa_widget_get(devinfo, 9); 555230130Smav if (w != NULL) 556230130Smav w->connsenable[0] = 0; 557230130Smav w = hdaa_widget_get(devinfo, 24); 558230130Smav if (w != NULL) 559230130Smav w->connsenable[0] = 0; 560230130Smav break; 561242417Smav case HDA_CODEC_ALC269: 562242417Smav /* 563242417Smav * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 564242417Smav * that mutes speaker if unused mixer at NID 15 is muted. 565242417Smav * Probably CODEC incorrectly reports internal connections. 566242417Smav * Hide that muter from the driver. There are several CODECs 567242417Smav * sharing this ID and I have not enough information about 568242417Smav * them to implement more universal solution. 569242417Smav */ 570242417Smav if (subid == 0x84371043) { 571242417Smav w = hdaa_widget_get(devinfo, 15); 572242417Smav if (w != NULL) 573242417Smav w->param.inamp_cap = 0; 574242417Smav } 575242417Smav break; 576230130Smav case HDA_CODEC_CX20582: 577230130Smav case HDA_CODEC_CX20583: 578230130Smav case HDA_CODEC_CX20584: 579230130Smav case HDA_CODEC_CX20585: 580230130Smav case HDA_CODEC_CX20590: 581230130Smav /* 582230130Smav * These codecs have extra connectivity on record side 583230130Smav * too reach for the present parser. 584230130Smav */ 585230130Smav w = hdaa_widget_get(devinfo, 20); 586230130Smav if (w != NULL) 587230130Smav w->connsenable[1] = 0; 588230130Smav w = hdaa_widget_get(devinfo, 21); 589230130Smav if (w != NULL) 590230130Smav w->connsenable[1] = 0; 591230130Smav w = hdaa_widget_get(devinfo, 22); 592230130Smav if (w != NULL) 593230130Smav w->connsenable[0] = 0; 594230130Smav break; 595230130Smav case HDA_CODEC_VT1708S_0: 596230130Smav case HDA_CODEC_VT1708S_1: 597230130Smav case HDA_CODEC_VT1708S_2: 598230130Smav case HDA_CODEC_VT1708S_3: 599230130Smav case HDA_CODEC_VT1708S_4: 600230130Smav case HDA_CODEC_VT1708S_5: 601230130Smav case HDA_CODEC_VT1708S_6: 602230130Smav case HDA_CODEC_VT1708S_7: 603230130Smav /* 604230130Smav * These codecs have hidden mic boost controls. 605230130Smav */ 606230130Smav w = hdaa_widget_get(devinfo, 26); 607230130Smav if (w != NULL) 608230130Smav w->param.inamp_cap = 609230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 610230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 611230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 612230130Smav w = hdaa_widget_get(devinfo, 30); 613230130Smav if (w != NULL) 614230130Smav w->param.inamp_cap = 615230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 616230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 617230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 618230130Smav break; 619230130Smav } 620230130Smav} 621230130Smav 622230130Smavvoid 623230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo) 624230130Smav{ 625230130Smav device_t dev = devinfo->dev; 626230130Smav uint32_t id, subid, val; 627230130Smav 628230130Smav id = hdaa_codec_id(devinfo); 629242352Smav subid = hdaa_card_id(devinfo); 630230130Smav 631230130Smav switch (id) { 632230130Smav case HDA_CODEC_VT1708S_0: 633230130Smav case HDA_CODEC_VT1708S_1: 634230130Smav case HDA_CODEC_VT1708S_2: 635230130Smav case HDA_CODEC_VT1708S_3: 636230130Smav case HDA_CODEC_VT1708S_4: 637230130Smav case HDA_CODEC_VT1708S_5: 638230130Smav case HDA_CODEC_VT1708S_6: 639230130Smav case HDA_CODEC_VT1708S_7: 640230130Smav /* Enable Mic Boost Volume controls. */ 641230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 642230130Smav 0xf98, 0x01)); 643241375Smav /* Fall though */ 644241375Smav case HDA_CODEC_VT1818S: 645230130Smav /* Don't bypass mixer. */ 646230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 647230130Smav 0xf88, 0xc0)); 648230130Smav break; 649230130Smav } 650230130Smav if (subid == APPLE_INTEL_MAC) 651230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 652230130Smav 0x7e7, 0)); 653230130Smav if (id == HDA_CODEC_ALC269) { 654230532Smav if (subid == 0x16e31043 || subid == 0x831a1043 || 655230532Smav subid == 0x834a1043 || subid == 0x83981043 || 656230532Smav subid == 0x83ce1043) { 657230130Smav /* 658230130Smav * The ditital mics on some Asus laptops produce 659230130Smav * differential signals instead of expected stereo. 660230130Smav * That results in silence if downmix it to mono. 661230130Smav * To workaround, make codec to handle signal as mono. 662230130Smav */ 663230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 664230130Smav val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 665230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 666230130Smav hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 667230130Smav } 668230130Smav } 669230130Smav} 670