hdaa_patches.c revision 248148
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/9/sys/dev/sound/pci/hda/hdaa_patches.c 248148 2013-03-11 07:53:51Z 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); 142243060Smav 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 */ 274244712Smav if (id == HDA_CODEC_AD1984A && 275244712Smav subid == LENOVO_X300_SUBVENDOR) { 276244712Smav switch (nid) { 277244712Smav case 17: /* Headphones with redirection */ 278244712Smav patch = "as=1 seq=15"; 279244712Smav break; 280244712Smav case 20: /* Two mics together */ 281244712Smav patch = "as=2 seq=15"; 282244712Smav break; 283244712Smav } 284244712Smav } 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 } 336248148Smav } else if (id == HDA_CODEC_CX20590 && 337248148Smav subid == LENOVO_X220_SUBVENDOR) { 338248148Smav switch (nid) { 339248148Smav case 25: 340248148Smav patch = "as=1 seq=15"; 341248148Smav break; 342248148Smav } 343230130Smav } 344230130Smav 345230130Smav if (patch != NULL) 346230130Smav config = hdaa_widget_pin_patch(config, patch); 347230130Smav HDA_BOOTVERBOSE( 348230130Smav if (config != orig) 349230130Smav device_printf(w->devinfo->dev, 350230130Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 351230130Smav nid, orig, config); 352230130Smav ); 353230130Smav w->wclass.pin.config = config; 354230130Smav} 355230130Smav 356230130Smavstatic void 357230130Smavhdaa_widget_patch(struct hdaa_widget *w) 358230130Smav{ 359230130Smav struct hdaa_devinfo *devinfo = w->devinfo; 360230130Smav uint32_t orig; 361230130Smav nid_t beeper = -1; 362230130Smav 363230130Smav orig = w->param.widget_cap; 364230130Smav /* On some codecs beeper is an input pin, but it is not recordable 365230130Smav alone. Also most of BIOSes does not declare beeper pin. 366230130Smav Change beeper pin node type to beeper to help parser. */ 367230130Smav switch (hdaa_codec_id(devinfo)) { 368230130Smav case HDA_CODEC_AD1882: 369230130Smav case HDA_CODEC_AD1883: 370230130Smav case HDA_CODEC_AD1984: 371230130Smav case HDA_CODEC_AD1984A: 372230130Smav case HDA_CODEC_AD1984B: 373230130Smav case HDA_CODEC_AD1987: 374230130Smav case HDA_CODEC_AD1988: 375230130Smav case HDA_CODEC_AD1988B: 376230130Smav case HDA_CODEC_AD1989B: 377230130Smav beeper = 26; 378230130Smav break; 379230130Smav case HDA_CODEC_ALC260: 380230130Smav beeper = 23; 381230130Smav break; 382230130Smav } 383230130Smav if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 384230130Smav hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 385230130Smav beeper = 29; 386230130Smav if (w->nid == beeper) { 387230130Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 388230130Smav w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 389230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 390230130Smav w->waspin = 1; 391230130Smav } 392244712Smav /* 393244712Smav * Clear "digital" flag from digital mic input, as its signal then goes 394244712Smav * to "analog" mixer and this separation just limits functionaity. 395244712Smav */ 396244712Smav if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 397244712Smav w->nid == 23) 398244712Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 399230130Smav HDA_BOOTVERBOSE( 400230130Smav if (w->param.widget_cap != orig) { 401230130Smav device_printf(w->devinfo->dev, 402230130Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 403230130Smav w->nid, orig, w->param.widget_cap); 404230130Smav } 405230130Smav ); 406230130Smav 407230130Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 408230130Smav hdac_pin_patch(w); 409230130Smav} 410230130Smav 411230130Smavvoid 412230130Smavhdaa_patch(struct hdaa_devinfo *devinfo) 413230130Smav{ 414230130Smav struct hdaa_widget *w; 415230130Smav uint32_t id, subid; 416230130Smav int i; 417230130Smav 418230130Smav id = hdaa_codec_id(devinfo); 419243060Smav subid = hdaa_card_id(devinfo); 420230130Smav 421230130Smav /* 422230130Smav * Quirks 423230130Smav */ 424230130Smav for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 425230130Smav if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 426230130Smav HDA_DEV_MATCH(hdac_quirks[i].id, id))) 427230130Smav continue; 428238131Smav devinfo->quirks |= hdac_quirks[i].set; 429238131Smav devinfo->quirks &= ~(hdac_quirks[i].unset); 430238131Smav devinfo->gpio = hdac_quirks[i].gpio; 431230130Smav } 432230130Smav 433230130Smav /* Apply per-widget patch. */ 434230130Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 435230130Smav w = hdaa_widget_get(devinfo, i); 436230130Smav if (w == NULL) 437230130Smav continue; 438230130Smav hdaa_widget_patch(w); 439230130Smav } 440230130Smav 441230130Smav switch (id) { 442230130Smav case HDA_CODEC_AD1983: 443230130Smav /* 444230130Smav * This CODEC has several possible usages, but none 445230130Smav * fit the parser best. Help parser to choose better. 446230130Smav */ 447230130Smav /* Disable direct unmixed playback to get pcm volume. */ 448230130Smav w = hdaa_widget_get(devinfo, 5); 449230130Smav if (w != NULL) 450230130Smav w->connsenable[0] = 0; 451230130Smav w = hdaa_widget_get(devinfo, 6); 452230130Smav if (w != NULL) 453230130Smav w->connsenable[0] = 0; 454230130Smav w = hdaa_widget_get(devinfo, 11); 455230130Smav if (w != NULL) 456230130Smav w->connsenable[0] = 0; 457230130Smav /* Disable mic and line selectors. */ 458230130Smav w = hdaa_widget_get(devinfo, 12); 459230130Smav if (w != NULL) 460230130Smav w->connsenable[1] = 0; 461230130Smav w = hdaa_widget_get(devinfo, 13); 462230130Smav if (w != NULL) 463230130Smav w->connsenable[1] = 0; 464230130Smav /* Disable recording from mono playback mix. */ 465230130Smav w = hdaa_widget_get(devinfo, 20); 466230130Smav if (w != NULL) 467230130Smav w->connsenable[3] = 0; 468230130Smav break; 469230130Smav case HDA_CODEC_AD1986A: 470230130Smav /* 471230130Smav * This CODEC has overcomplicated input mixing. 472230130Smav * Make some cleaning there. 473230130Smav */ 474230130Smav /* Disable input mono mixer. Not needed and not supported. */ 475230130Smav w = hdaa_widget_get(devinfo, 43); 476230130Smav if (w != NULL) 477230130Smav w->enable = 0; 478230130Smav /* Disable any with any input mixing mesh. Use separately. */ 479230130Smav w = hdaa_widget_get(devinfo, 39); 480230130Smav if (w != NULL) 481230130Smav w->enable = 0; 482230130Smav w = hdaa_widget_get(devinfo, 40); 483230130Smav if (w != NULL) 484230130Smav w->enable = 0; 485230130Smav w = hdaa_widget_get(devinfo, 41); 486230130Smav if (w != NULL) 487230130Smav w->enable = 0; 488230130Smav w = hdaa_widget_get(devinfo, 42); 489230130Smav if (w != NULL) 490230130Smav w->enable = 0; 491230130Smav /* Disable duplicate mixer node connector. */ 492230130Smav w = hdaa_widget_get(devinfo, 15); 493230130Smav if (w != NULL) 494230130Smav w->connsenable[3] = 0; 495230130Smav /* There is only one mic preamplifier, use it effectively. */ 496230130Smav w = hdaa_widget_get(devinfo, 31); 497230130Smav if (w != NULL) { 498230130Smav if ((w->wclass.pin.config & 499230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 500230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 501230130Smav w = hdaa_widget_get(devinfo, 16); 502230130Smav if (w != NULL) 503230130Smav w->connsenable[2] = 0; 504230130Smav } else { 505230130Smav w = hdaa_widget_get(devinfo, 15); 506230130Smav if (w != NULL) 507230130Smav w->connsenable[0] = 0; 508230130Smav } 509230130Smav } 510230130Smav w = hdaa_widget_get(devinfo, 32); 511230130Smav if (w != NULL) { 512230130Smav if ((w->wclass.pin.config & 513230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 514230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 515230130Smav w = hdaa_widget_get(devinfo, 16); 516230130Smav if (w != NULL) 517230130Smav w->connsenable[0] = 0; 518230130Smav } else { 519230130Smav w = hdaa_widget_get(devinfo, 15); 520230130Smav if (w != NULL) 521230130Smav w->connsenable[1] = 0; 522230130Smav } 523230130Smav } 524230130Smav 525230130Smav if (subid == ASUS_A8X_SUBVENDOR) { 526230130Smav /* 527230130Smav * This is just plain ridiculous.. There 528230130Smav * are several A8 series that share the same 529230130Smav * pci id but works differently (EAPD). 530230130Smav */ 531230130Smav w = hdaa_widget_get(devinfo, 26); 532230130Smav if (w != NULL && w->type == 533230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 534230130Smav (w->wclass.pin.config & 535230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 536230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 537230130Smav devinfo->quirks &= 538230130Smav ~HDAA_QUIRK_EAPDINV; 539230130Smav } 540230130Smav break; 541230130Smav case HDA_CODEC_AD1981HD: 542230130Smav /* 543230130Smav * This CODEC has very unusual design with several 544230130Smav * points inappropriate for the present parser. 545230130Smav */ 546230130Smav /* Disable recording from mono playback mix. */ 547230130Smav w = hdaa_widget_get(devinfo, 21); 548230130Smav if (w != NULL) 549230130Smav w->connsenable[3] = 0; 550230130Smav /* Disable rear to front mic mixer, use separately. */ 551230130Smav w = hdaa_widget_get(devinfo, 31); 552230130Smav if (w != NULL) 553230130Smav w->enable = 0; 554230130Smav /* Disable direct playback, use mixer. */ 555230130Smav w = hdaa_widget_get(devinfo, 5); 556230130Smav if (w != NULL) 557230130Smav w->connsenable[0] = 0; 558230130Smav w = hdaa_widget_get(devinfo, 6); 559230130Smav if (w != NULL) 560230130Smav w->connsenable[0] = 0; 561230130Smav w = hdaa_widget_get(devinfo, 9); 562230130Smav if (w != NULL) 563230130Smav w->connsenable[0] = 0; 564230130Smav w = hdaa_widget_get(devinfo, 24); 565230130Smav if (w != NULL) 566230130Smav w->connsenable[0] = 0; 567230130Smav break; 568243064Smav case HDA_CODEC_ALC269: 569243064Smav /* 570243064Smav * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 571243064Smav * that mutes speaker if unused mixer at NID 15 is muted. 572243064Smav * Probably CODEC incorrectly reports internal connections. 573243064Smav * Hide that muter from the driver. There are several CODECs 574243064Smav * sharing this ID and I have not enough information about 575243064Smav * them to implement more universal solution. 576243064Smav */ 577243064Smav if (subid == 0x84371043) { 578243064Smav w = hdaa_widget_get(devinfo, 15); 579243064Smav if (w != NULL) 580243064Smav w->param.inamp_cap = 0; 581243064Smav } 582243064Smav break; 583230130Smav case HDA_CODEC_CX20582: 584230130Smav case HDA_CODEC_CX20583: 585230130Smav case HDA_CODEC_CX20584: 586230130Smav case HDA_CODEC_CX20585: 587230130Smav case HDA_CODEC_CX20590: 588230130Smav /* 589230130Smav * These codecs have extra connectivity on record side 590230130Smav * too reach for the present parser. 591230130Smav */ 592230130Smav w = hdaa_widget_get(devinfo, 20); 593230130Smav if (w != NULL) 594230130Smav w->connsenable[1] = 0; 595230130Smav w = hdaa_widget_get(devinfo, 21); 596230130Smav if (w != NULL) 597230130Smav w->connsenable[1] = 0; 598230130Smav w = hdaa_widget_get(devinfo, 22); 599230130Smav if (w != NULL) 600230130Smav w->connsenable[0] = 0; 601230130Smav break; 602230130Smav case HDA_CODEC_VT1708S_0: 603230130Smav case HDA_CODEC_VT1708S_1: 604230130Smav case HDA_CODEC_VT1708S_2: 605230130Smav case HDA_CODEC_VT1708S_3: 606230130Smav case HDA_CODEC_VT1708S_4: 607230130Smav case HDA_CODEC_VT1708S_5: 608230130Smav case HDA_CODEC_VT1708S_6: 609230130Smav case HDA_CODEC_VT1708S_7: 610230130Smav /* 611230130Smav * These codecs have hidden mic boost controls. 612230130Smav */ 613230130Smav w = hdaa_widget_get(devinfo, 26); 614230130Smav if (w != NULL) 615230130Smav w->param.inamp_cap = 616230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 617230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 618230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 619230130Smav w = hdaa_widget_get(devinfo, 30); 620230130Smav if (w != NULL) 621230130Smav w->param.inamp_cap = 622230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 623230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 624230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 625230130Smav break; 626230130Smav } 627230130Smav} 628230130Smav 629230130Smavvoid 630230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo) 631230130Smav{ 632230130Smav device_t dev = devinfo->dev; 633230130Smav uint32_t id, subid, val; 634230130Smav 635230130Smav id = hdaa_codec_id(devinfo); 636243060Smav subid = hdaa_card_id(devinfo); 637230130Smav 638230130Smav switch (id) { 639230130Smav case HDA_CODEC_VT1708S_0: 640230130Smav case HDA_CODEC_VT1708S_1: 641230130Smav case HDA_CODEC_VT1708S_2: 642230130Smav case HDA_CODEC_VT1708S_3: 643230130Smav case HDA_CODEC_VT1708S_4: 644230130Smav case HDA_CODEC_VT1708S_5: 645230130Smav case HDA_CODEC_VT1708S_6: 646230130Smav case HDA_CODEC_VT1708S_7: 647230130Smav /* Enable Mic Boost Volume controls. */ 648230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 649230130Smav 0xf98, 0x01)); 650241742Smav /* Fall though */ 651241742Smav case HDA_CODEC_VT1818S: 652230130Smav /* Don't bypass mixer. */ 653230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 654230130Smav 0xf88, 0xc0)); 655230130Smav break; 656230130Smav } 657230130Smav if (subid == APPLE_INTEL_MAC) 658230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 659230130Smav 0x7e7, 0)); 660230130Smav if (id == HDA_CODEC_ALC269) { 661232798Smav if (subid == 0x16e31043 || subid == 0x831a1043 || 662232798Smav subid == 0x834a1043 || subid == 0x83981043 || 663232798Smav subid == 0x83ce1043) { 664230130Smav /* 665230130Smav * The ditital mics on some Asus laptops produce 666230130Smav * differential signals instead of expected stereo. 667230130Smav * That results in silence if downmix it to mono. 668230130Smav * To workaround, make codec to handle signal as mono. 669230130Smav */ 670230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 671230130Smav val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 672230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 673230130Smav hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 674230130Smav } 675230130Smav } 676230130Smav} 677