hdaa_patches.c revision 252148
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 252148 2013-06-24 09:20:14Z glebius $"); 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 && 337252148Sglebius (subid == LENOVO_X1_SUBVENDOR || 338252148Sglebius subid == LENOVO_X220_SUBVENDOR || 339252148Sglebius subid == LENOVO_T420_SUBVENDOR || 340252148Sglebius subid == LENOVO_T520_SUBVENDOR)) { 341248148Smav switch (nid) { 342248148Smav case 25: 343248148Smav patch = "as=1 seq=15"; 344248148Smav break; 345252148Sglebius /* 346252148Sglebius * Group onboard mic and headphone mic 347252148Sglebius * together. Fixes onboard mic. 348252148Sglebius */ 349252148Sglebius case 27: 350252148Sglebius patch = "as=2 seq=15"; 351252148Sglebius break; 352252148Sglebius case 35: 353252148Sglebius patch = "as=2"; 354252148Sglebius break; 355248148Smav } 356252148Sglebius } else if (id == HDA_CODEC_ALC269 && 357252148Sglebius (subid == LENOVO_X1CRBN_SUBVENDOR || 358252148Sglebius subid == LENOVO_T430_SUBVENDOR || 359252148Sglebius subid == LENOVO_T430S_SUBVENDOR || 360252148Sglebius subid == LENOVO_T530_SUBVENDOR)) { 361252148Sglebius switch (nid) { 362252148Sglebius case 21: 363252148Sglebius patch = "as=1 seq=15"; 364252148Sglebius break; 365252148Sglebius } 366230130Smav } 367230130Smav 368230130Smav if (patch != NULL) 369230130Smav config = hdaa_widget_pin_patch(config, patch); 370230130Smav HDA_BOOTVERBOSE( 371230130Smav if (config != orig) 372230130Smav device_printf(w->devinfo->dev, 373230130Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 374230130Smav nid, orig, config); 375230130Smav ); 376230130Smav w->wclass.pin.config = config; 377230130Smav} 378230130Smav 379230130Smavstatic void 380230130Smavhdaa_widget_patch(struct hdaa_widget *w) 381230130Smav{ 382230130Smav struct hdaa_devinfo *devinfo = w->devinfo; 383230130Smav uint32_t orig; 384230130Smav nid_t beeper = -1; 385230130Smav 386230130Smav orig = w->param.widget_cap; 387230130Smav /* On some codecs beeper is an input pin, but it is not recordable 388230130Smav alone. Also most of BIOSes does not declare beeper pin. 389230130Smav Change beeper pin node type to beeper to help parser. */ 390230130Smav switch (hdaa_codec_id(devinfo)) { 391230130Smav case HDA_CODEC_AD1882: 392230130Smav case HDA_CODEC_AD1883: 393230130Smav case HDA_CODEC_AD1984: 394230130Smav case HDA_CODEC_AD1984A: 395230130Smav case HDA_CODEC_AD1984B: 396230130Smav case HDA_CODEC_AD1987: 397230130Smav case HDA_CODEC_AD1988: 398230130Smav case HDA_CODEC_AD1988B: 399230130Smav case HDA_CODEC_AD1989B: 400230130Smav beeper = 26; 401230130Smav break; 402230130Smav case HDA_CODEC_ALC260: 403230130Smav beeper = 23; 404230130Smav break; 405230130Smav } 406230130Smav if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 407230130Smav hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 408230130Smav beeper = 29; 409230130Smav if (w->nid == beeper) { 410230130Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 411230130Smav w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 412230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 413230130Smav w->waspin = 1; 414230130Smav } 415244712Smav /* 416244712Smav * Clear "digital" flag from digital mic input, as its signal then goes 417244712Smav * to "analog" mixer and this separation just limits functionaity. 418244712Smav */ 419244712Smav if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 420244712Smav w->nid == 23) 421244712Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 422230130Smav HDA_BOOTVERBOSE( 423230130Smav if (w->param.widget_cap != orig) { 424230130Smav device_printf(w->devinfo->dev, 425230130Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 426230130Smav w->nid, orig, w->param.widget_cap); 427230130Smav } 428230130Smav ); 429230130Smav 430230130Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 431230130Smav hdac_pin_patch(w); 432230130Smav} 433230130Smav 434230130Smavvoid 435230130Smavhdaa_patch(struct hdaa_devinfo *devinfo) 436230130Smav{ 437230130Smav struct hdaa_widget *w; 438230130Smav uint32_t id, subid; 439230130Smav int i; 440230130Smav 441230130Smav id = hdaa_codec_id(devinfo); 442243060Smav subid = hdaa_card_id(devinfo); 443230130Smav 444230130Smav /* 445230130Smav * Quirks 446230130Smav */ 447230130Smav for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 448230130Smav if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 449230130Smav HDA_DEV_MATCH(hdac_quirks[i].id, id))) 450230130Smav continue; 451238131Smav devinfo->quirks |= hdac_quirks[i].set; 452238131Smav devinfo->quirks &= ~(hdac_quirks[i].unset); 453238131Smav devinfo->gpio = hdac_quirks[i].gpio; 454230130Smav } 455230130Smav 456230130Smav /* Apply per-widget patch. */ 457230130Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 458230130Smav w = hdaa_widget_get(devinfo, i); 459230130Smav if (w == NULL) 460230130Smav continue; 461230130Smav hdaa_widget_patch(w); 462230130Smav } 463230130Smav 464230130Smav switch (id) { 465230130Smav case HDA_CODEC_AD1983: 466230130Smav /* 467230130Smav * This CODEC has several possible usages, but none 468230130Smav * fit the parser best. Help parser to choose better. 469230130Smav */ 470230130Smav /* Disable direct unmixed playback to get pcm volume. */ 471230130Smav w = hdaa_widget_get(devinfo, 5); 472230130Smav if (w != NULL) 473230130Smav w->connsenable[0] = 0; 474230130Smav w = hdaa_widget_get(devinfo, 6); 475230130Smav if (w != NULL) 476230130Smav w->connsenable[0] = 0; 477230130Smav w = hdaa_widget_get(devinfo, 11); 478230130Smav if (w != NULL) 479230130Smav w->connsenable[0] = 0; 480230130Smav /* Disable mic and line selectors. */ 481230130Smav w = hdaa_widget_get(devinfo, 12); 482230130Smav if (w != NULL) 483230130Smav w->connsenable[1] = 0; 484230130Smav w = hdaa_widget_get(devinfo, 13); 485230130Smav if (w != NULL) 486230130Smav w->connsenable[1] = 0; 487230130Smav /* Disable recording from mono playback mix. */ 488230130Smav w = hdaa_widget_get(devinfo, 20); 489230130Smav if (w != NULL) 490230130Smav w->connsenable[3] = 0; 491230130Smav break; 492230130Smav case HDA_CODEC_AD1986A: 493230130Smav /* 494230130Smav * This CODEC has overcomplicated input mixing. 495230130Smav * Make some cleaning there. 496230130Smav */ 497230130Smav /* Disable input mono mixer. Not needed and not supported. */ 498230130Smav w = hdaa_widget_get(devinfo, 43); 499230130Smav if (w != NULL) 500230130Smav w->enable = 0; 501230130Smav /* Disable any with any input mixing mesh. Use separately. */ 502230130Smav w = hdaa_widget_get(devinfo, 39); 503230130Smav if (w != NULL) 504230130Smav w->enable = 0; 505230130Smav w = hdaa_widget_get(devinfo, 40); 506230130Smav if (w != NULL) 507230130Smav w->enable = 0; 508230130Smav w = hdaa_widget_get(devinfo, 41); 509230130Smav if (w != NULL) 510230130Smav w->enable = 0; 511230130Smav w = hdaa_widget_get(devinfo, 42); 512230130Smav if (w != NULL) 513230130Smav w->enable = 0; 514230130Smav /* Disable duplicate mixer node connector. */ 515230130Smav w = hdaa_widget_get(devinfo, 15); 516230130Smav if (w != NULL) 517230130Smav w->connsenable[3] = 0; 518230130Smav /* There is only one mic preamplifier, use it effectively. */ 519230130Smav w = hdaa_widget_get(devinfo, 31); 520230130Smav if (w != NULL) { 521230130Smav if ((w->wclass.pin.config & 522230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 523230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 524230130Smav w = hdaa_widget_get(devinfo, 16); 525230130Smav if (w != NULL) 526230130Smav w->connsenable[2] = 0; 527230130Smav } else { 528230130Smav w = hdaa_widget_get(devinfo, 15); 529230130Smav if (w != NULL) 530230130Smav w->connsenable[0] = 0; 531230130Smav } 532230130Smav } 533230130Smav w = hdaa_widget_get(devinfo, 32); 534230130Smav if (w != NULL) { 535230130Smav if ((w->wclass.pin.config & 536230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 537230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 538230130Smav w = hdaa_widget_get(devinfo, 16); 539230130Smav if (w != NULL) 540230130Smav w->connsenable[0] = 0; 541230130Smav } else { 542230130Smav w = hdaa_widget_get(devinfo, 15); 543230130Smav if (w != NULL) 544230130Smav w->connsenable[1] = 0; 545230130Smav } 546230130Smav } 547230130Smav 548230130Smav if (subid == ASUS_A8X_SUBVENDOR) { 549230130Smav /* 550230130Smav * This is just plain ridiculous.. There 551230130Smav * are several A8 series that share the same 552230130Smav * pci id but works differently (EAPD). 553230130Smav */ 554230130Smav w = hdaa_widget_get(devinfo, 26); 555230130Smav if (w != NULL && w->type == 556230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 557230130Smav (w->wclass.pin.config & 558230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 559230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 560230130Smav devinfo->quirks &= 561230130Smav ~HDAA_QUIRK_EAPDINV; 562230130Smav } 563230130Smav break; 564230130Smav case HDA_CODEC_AD1981HD: 565230130Smav /* 566230130Smav * This CODEC has very unusual design with several 567230130Smav * points inappropriate for the present parser. 568230130Smav */ 569230130Smav /* Disable recording from mono playback mix. */ 570230130Smav w = hdaa_widget_get(devinfo, 21); 571230130Smav if (w != NULL) 572230130Smav w->connsenable[3] = 0; 573230130Smav /* Disable rear to front mic mixer, use separately. */ 574230130Smav w = hdaa_widget_get(devinfo, 31); 575230130Smav if (w != NULL) 576230130Smav w->enable = 0; 577230130Smav /* Disable direct playback, use mixer. */ 578230130Smav w = hdaa_widget_get(devinfo, 5); 579230130Smav if (w != NULL) 580230130Smav w->connsenable[0] = 0; 581230130Smav w = hdaa_widget_get(devinfo, 6); 582230130Smav if (w != NULL) 583230130Smav w->connsenable[0] = 0; 584230130Smav w = hdaa_widget_get(devinfo, 9); 585230130Smav if (w != NULL) 586230130Smav w->connsenable[0] = 0; 587230130Smav w = hdaa_widget_get(devinfo, 24); 588230130Smav if (w != NULL) 589230130Smav w->connsenable[0] = 0; 590230130Smav break; 591243064Smav case HDA_CODEC_ALC269: 592243064Smav /* 593243064Smav * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 594243064Smav * that mutes speaker if unused mixer at NID 15 is muted. 595243064Smav * Probably CODEC incorrectly reports internal connections. 596243064Smav * Hide that muter from the driver. There are several CODECs 597243064Smav * sharing this ID and I have not enough information about 598243064Smav * them to implement more universal solution. 599243064Smav */ 600243064Smav if (subid == 0x84371043) { 601243064Smav w = hdaa_widget_get(devinfo, 15); 602243064Smav if (w != NULL) 603243064Smav w->param.inamp_cap = 0; 604243064Smav } 605243064Smav break; 606230130Smav case HDA_CODEC_CX20582: 607230130Smav case HDA_CODEC_CX20583: 608230130Smav case HDA_CODEC_CX20584: 609230130Smav case HDA_CODEC_CX20585: 610230130Smav case HDA_CODEC_CX20590: 611230130Smav /* 612230130Smav * These codecs have extra connectivity on record side 613230130Smav * too reach for the present parser. 614230130Smav */ 615230130Smav w = hdaa_widget_get(devinfo, 20); 616230130Smav if (w != NULL) 617230130Smav w->connsenable[1] = 0; 618230130Smav w = hdaa_widget_get(devinfo, 21); 619230130Smav if (w != NULL) 620230130Smav w->connsenable[1] = 0; 621230130Smav w = hdaa_widget_get(devinfo, 22); 622230130Smav if (w != NULL) 623230130Smav w->connsenable[0] = 0; 624230130Smav break; 625230130Smav case HDA_CODEC_VT1708S_0: 626230130Smav case HDA_CODEC_VT1708S_1: 627230130Smav case HDA_CODEC_VT1708S_2: 628230130Smav case HDA_CODEC_VT1708S_3: 629230130Smav case HDA_CODEC_VT1708S_4: 630230130Smav case HDA_CODEC_VT1708S_5: 631230130Smav case HDA_CODEC_VT1708S_6: 632230130Smav case HDA_CODEC_VT1708S_7: 633230130Smav /* 634230130Smav * These codecs have hidden mic boost controls. 635230130Smav */ 636230130Smav w = hdaa_widget_get(devinfo, 26); 637230130Smav if (w != NULL) 638230130Smav w->param.inamp_cap = 639230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 640230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 641230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 642230130Smav w = hdaa_widget_get(devinfo, 30); 643230130Smav if (w != NULL) 644230130Smav w->param.inamp_cap = 645230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 646230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 647230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 648230130Smav break; 649230130Smav } 650230130Smav} 651230130Smav 652230130Smavvoid 653230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo) 654230130Smav{ 655230130Smav device_t dev = devinfo->dev; 656230130Smav uint32_t id, subid, val; 657230130Smav 658230130Smav id = hdaa_codec_id(devinfo); 659243060Smav subid = hdaa_card_id(devinfo); 660230130Smav 661230130Smav switch (id) { 662230130Smav case HDA_CODEC_VT1708S_0: 663230130Smav case HDA_CODEC_VT1708S_1: 664230130Smav case HDA_CODEC_VT1708S_2: 665230130Smav case HDA_CODEC_VT1708S_3: 666230130Smav case HDA_CODEC_VT1708S_4: 667230130Smav case HDA_CODEC_VT1708S_5: 668230130Smav case HDA_CODEC_VT1708S_6: 669230130Smav case HDA_CODEC_VT1708S_7: 670230130Smav /* Enable Mic Boost Volume controls. */ 671230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 672230130Smav 0xf98, 0x01)); 673241742Smav /* Fall though */ 674241742Smav case HDA_CODEC_VT1818S: 675230130Smav /* Don't bypass mixer. */ 676230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 677230130Smav 0xf88, 0xc0)); 678230130Smav break; 679230130Smav } 680230130Smav if (subid == APPLE_INTEL_MAC) 681230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 682230130Smav 0x7e7, 0)); 683230130Smav if (id == HDA_CODEC_ALC269) { 684232798Smav if (subid == 0x16e31043 || subid == 0x831a1043 || 685232798Smav subid == 0x834a1043 || subid == 0x83981043 || 686232798Smav subid == 0x83ce1043) { 687230130Smav /* 688230130Smav * The ditital mics on some Asus laptops produce 689230130Smav * differential signals instead of expected stereo. 690230130Smav * That results in silence if downmix it to mono. 691230130Smav * To workaround, make codec to handle signal as mono. 692230130Smav */ 693230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 694230130Smav val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 695230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 696230130Smav hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 697230130Smav } 698230130Smav } 699230130Smav} 700