hdaa_patches.c revision 241375
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 241375 2012-10-09 17:06:31Z 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); 142230130Smav subid = hdaa_subvendor_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 */ 274230130Smav if (id == HDA_CODEC_AD1986A && 275230130Smav (subid == ASUS_M2NPVMX_SUBVENDOR || 276230130Smav subid == ASUS_A8NVMCSM_SUBVENDOR || 277230130Smav subid == ASUS_P5PL2_SUBVENDOR)) { 278230130Smav switch (nid) { 279230130Smav case 26: /* Headphones with redirection */ 280230130Smav patch = "as=1 seq=15"; 281230130Smav break; 282230130Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 283230130Smav patch = "device=Line-in as=8 seq=1"; 284230130Smav break; 285230130Smav case 29: /* Can't use this as input, as the only available mic 286230130Smav * preamplifier is busy by front panel mic (nid 31). 287230130Smav * If you want to use this rear connector as mic input, 288230130Smav * you have to disable the front panel one. */ 289230130Smav patch = "as=0"; 290230130Smav break; 291230130Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 292230130Smav patch = "as=8 seq=3"; 293230130Smav break; 294230130Smav case 32: 295230130Smav patch = "as=8 seq=4"; 296230130Smav break; 297230130Smav case 34: 298230130Smav patch = "as=8 seq=5"; 299230130Smav break; 300230130Smav case 36: 301230130Smav patch = "as=8 seq=6"; 302230130Smav break; 303230130Smav } 304230130Smav } else if (id == HDA_CODEC_ALC260 && 305230130Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) { 306230130Smav switch (nid) { 307230130Smav case 16: 308230130Smav patch = "seq=15 device=Headphones"; 309230130Smav break; 310230130Smav } 311230130Smav } else if (id == HDA_CODEC_ALC268) { 312230130Smav if (subid == ACER_T5320_SUBVENDOR) { 313230130Smav switch (nid) { 314230130Smav case 20: /* Headphones Jack */ 315230130Smav patch = "as=1 seq=15"; 316230130Smav break; 317230130Smav } 318230130Smav } 319230130Smav } else if (id == HDA_CODEC_CX20561 && 320230130Smav subid == LENOVO_B450_SUBVENDOR) { 321230130Smav switch (nid) { 322230130Smav case 22: 323230130Smav patch = "as=1 seq=15"; 324230130Smav break; 325230130Smav } 326230130Smav } 327230130Smav 328230130Smav if (patch != NULL) 329230130Smav config = hdaa_widget_pin_patch(config, patch); 330230130Smav HDA_BOOTVERBOSE( 331230130Smav if (config != orig) 332230130Smav device_printf(w->devinfo->dev, 333230130Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 334230130Smav nid, orig, config); 335230130Smav ); 336230130Smav w->wclass.pin.config = config; 337230130Smav} 338230130Smav 339230130Smavstatic void 340230130Smavhdaa_widget_patch(struct hdaa_widget *w) 341230130Smav{ 342230130Smav struct hdaa_devinfo *devinfo = w->devinfo; 343230130Smav uint32_t orig; 344230130Smav nid_t beeper = -1; 345230130Smav 346230130Smav orig = w->param.widget_cap; 347230130Smav /* On some codecs beeper is an input pin, but it is not recordable 348230130Smav alone. Also most of BIOSes does not declare beeper pin. 349230130Smav Change beeper pin node type to beeper to help parser. */ 350230130Smav switch (hdaa_codec_id(devinfo)) { 351230130Smav case HDA_CODEC_AD1882: 352230130Smav case HDA_CODEC_AD1883: 353230130Smav case HDA_CODEC_AD1984: 354230130Smav case HDA_CODEC_AD1984A: 355230130Smav case HDA_CODEC_AD1984B: 356230130Smav case HDA_CODEC_AD1987: 357230130Smav case HDA_CODEC_AD1988: 358230130Smav case HDA_CODEC_AD1988B: 359230130Smav case HDA_CODEC_AD1989B: 360230130Smav beeper = 26; 361230130Smav break; 362230130Smav case HDA_CODEC_ALC260: 363230130Smav beeper = 23; 364230130Smav break; 365230130Smav } 366230130Smav if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 367230130Smav hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 368230130Smav beeper = 29; 369230130Smav if (w->nid == beeper) { 370230130Smav w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 371230130Smav w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 372230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 373230130Smav w->waspin = 1; 374230130Smav } 375230130Smav HDA_BOOTVERBOSE( 376230130Smav if (w->param.widget_cap != orig) { 377230130Smav device_printf(w->devinfo->dev, 378230130Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 379230130Smav w->nid, orig, w->param.widget_cap); 380230130Smav } 381230130Smav ); 382230130Smav 383230130Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 384230130Smav hdac_pin_patch(w); 385230130Smav} 386230130Smav 387230130Smavvoid 388230130Smavhdaa_patch(struct hdaa_devinfo *devinfo) 389230130Smav{ 390230130Smav struct hdaa_widget *w; 391230130Smav uint32_t id, subid; 392230130Smav int i; 393230130Smav 394230130Smav id = hdaa_codec_id(devinfo); 395230130Smav subid = hdaa_subvendor_id(devinfo); 396230130Smav 397230130Smav /* 398230130Smav * Quirks 399230130Smav */ 400230130Smav for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 401230130Smav if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 402230130Smav HDA_DEV_MATCH(hdac_quirks[i].id, id))) 403230130Smav continue; 404238011Smav devinfo->quirks |= hdac_quirks[i].set; 405238011Smav devinfo->quirks &= ~(hdac_quirks[i].unset); 406238011Smav devinfo->gpio = hdac_quirks[i].gpio; 407230130Smav } 408230130Smav 409230130Smav /* Apply per-widget patch. */ 410230130Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 411230130Smav w = hdaa_widget_get(devinfo, i); 412230130Smav if (w == NULL) 413230130Smav continue; 414230130Smav hdaa_widget_patch(w); 415230130Smav } 416230130Smav 417230130Smav switch (id) { 418230130Smav case HDA_CODEC_AD1983: 419230130Smav /* 420230130Smav * This CODEC has several possible usages, but none 421230130Smav * fit the parser best. Help parser to choose better. 422230130Smav */ 423230130Smav /* Disable direct unmixed playback to get pcm volume. */ 424230130Smav w = hdaa_widget_get(devinfo, 5); 425230130Smav if (w != NULL) 426230130Smav w->connsenable[0] = 0; 427230130Smav w = hdaa_widget_get(devinfo, 6); 428230130Smav if (w != NULL) 429230130Smav w->connsenable[0] = 0; 430230130Smav w = hdaa_widget_get(devinfo, 11); 431230130Smav if (w != NULL) 432230130Smav w->connsenable[0] = 0; 433230130Smav /* Disable mic and line selectors. */ 434230130Smav w = hdaa_widget_get(devinfo, 12); 435230130Smav if (w != NULL) 436230130Smav w->connsenable[1] = 0; 437230130Smav w = hdaa_widget_get(devinfo, 13); 438230130Smav if (w != NULL) 439230130Smav w->connsenable[1] = 0; 440230130Smav /* Disable recording from mono playback mix. */ 441230130Smav w = hdaa_widget_get(devinfo, 20); 442230130Smav if (w != NULL) 443230130Smav w->connsenable[3] = 0; 444230130Smav break; 445230130Smav case HDA_CODEC_AD1986A: 446230130Smav /* 447230130Smav * This CODEC has overcomplicated input mixing. 448230130Smav * Make some cleaning there. 449230130Smav */ 450230130Smav /* Disable input mono mixer. Not needed and not supported. */ 451230130Smav w = hdaa_widget_get(devinfo, 43); 452230130Smav if (w != NULL) 453230130Smav w->enable = 0; 454230130Smav /* Disable any with any input mixing mesh. Use separately. */ 455230130Smav w = hdaa_widget_get(devinfo, 39); 456230130Smav if (w != NULL) 457230130Smav w->enable = 0; 458230130Smav w = hdaa_widget_get(devinfo, 40); 459230130Smav if (w != NULL) 460230130Smav w->enable = 0; 461230130Smav w = hdaa_widget_get(devinfo, 41); 462230130Smav if (w != NULL) 463230130Smav w->enable = 0; 464230130Smav w = hdaa_widget_get(devinfo, 42); 465230130Smav if (w != NULL) 466230130Smav w->enable = 0; 467230130Smav /* Disable duplicate mixer node connector. */ 468230130Smav w = hdaa_widget_get(devinfo, 15); 469230130Smav if (w != NULL) 470230130Smav w->connsenable[3] = 0; 471230130Smav /* There is only one mic preamplifier, use it effectively. */ 472230130Smav w = hdaa_widget_get(devinfo, 31); 473230130Smav if (w != NULL) { 474230130Smav if ((w->wclass.pin.config & 475230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 476230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 477230130Smav w = hdaa_widget_get(devinfo, 16); 478230130Smav if (w != NULL) 479230130Smav w->connsenable[2] = 0; 480230130Smav } else { 481230130Smav w = hdaa_widget_get(devinfo, 15); 482230130Smav if (w != NULL) 483230130Smav w->connsenable[0] = 0; 484230130Smav } 485230130Smav } 486230130Smav w = hdaa_widget_get(devinfo, 32); 487230130Smav if (w != NULL) { 488230130Smav if ((w->wclass.pin.config & 489230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 490230130Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 491230130Smav w = hdaa_widget_get(devinfo, 16); 492230130Smav if (w != NULL) 493230130Smav w->connsenable[0] = 0; 494230130Smav } else { 495230130Smav w = hdaa_widget_get(devinfo, 15); 496230130Smav if (w != NULL) 497230130Smav w->connsenable[1] = 0; 498230130Smav } 499230130Smav } 500230130Smav 501230130Smav if (subid == ASUS_A8X_SUBVENDOR) { 502230130Smav /* 503230130Smav * This is just plain ridiculous.. There 504230130Smav * are several A8 series that share the same 505230130Smav * pci id but works differently (EAPD). 506230130Smav */ 507230130Smav w = hdaa_widget_get(devinfo, 26); 508230130Smav if (w != NULL && w->type == 509230130Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 510230130Smav (w->wclass.pin.config & 511230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 512230130Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 513230130Smav devinfo->quirks &= 514230130Smav ~HDAA_QUIRK_EAPDINV; 515230130Smav } 516230130Smav break; 517230130Smav case HDA_CODEC_AD1981HD: 518230130Smav /* 519230130Smav * This CODEC has very unusual design with several 520230130Smav * points inappropriate for the present parser. 521230130Smav */ 522230130Smav /* Disable recording from mono playback mix. */ 523230130Smav w = hdaa_widget_get(devinfo, 21); 524230130Smav if (w != NULL) 525230130Smav w->connsenable[3] = 0; 526230130Smav /* Disable rear to front mic mixer, use separately. */ 527230130Smav w = hdaa_widget_get(devinfo, 31); 528230130Smav if (w != NULL) 529230130Smav w->enable = 0; 530230130Smav /* Disable direct playback, use mixer. */ 531230130Smav w = hdaa_widget_get(devinfo, 5); 532230130Smav if (w != NULL) 533230130Smav w->connsenable[0] = 0; 534230130Smav w = hdaa_widget_get(devinfo, 6); 535230130Smav if (w != NULL) 536230130Smav w->connsenable[0] = 0; 537230130Smav w = hdaa_widget_get(devinfo, 9); 538230130Smav if (w != NULL) 539230130Smav w->connsenable[0] = 0; 540230130Smav w = hdaa_widget_get(devinfo, 24); 541230130Smav if (w != NULL) 542230130Smav w->connsenable[0] = 0; 543230130Smav break; 544230130Smav case HDA_CODEC_CX20582: 545230130Smav case HDA_CODEC_CX20583: 546230130Smav case HDA_CODEC_CX20584: 547230130Smav case HDA_CODEC_CX20585: 548230130Smav case HDA_CODEC_CX20590: 549230130Smav /* 550230130Smav * These codecs have extra connectivity on record side 551230130Smav * too reach for the present parser. 552230130Smav */ 553230130Smav w = hdaa_widget_get(devinfo, 20); 554230130Smav if (w != NULL) 555230130Smav w->connsenable[1] = 0; 556230130Smav w = hdaa_widget_get(devinfo, 21); 557230130Smav if (w != NULL) 558230130Smav w->connsenable[1] = 0; 559230130Smav w = hdaa_widget_get(devinfo, 22); 560230130Smav if (w != NULL) 561230130Smav w->connsenable[0] = 0; 562230130Smav break; 563230130Smav case HDA_CODEC_VT1708S_0: 564230130Smav case HDA_CODEC_VT1708S_1: 565230130Smav case HDA_CODEC_VT1708S_2: 566230130Smav case HDA_CODEC_VT1708S_3: 567230130Smav case HDA_CODEC_VT1708S_4: 568230130Smav case HDA_CODEC_VT1708S_5: 569230130Smav case HDA_CODEC_VT1708S_6: 570230130Smav case HDA_CODEC_VT1708S_7: 571230130Smav /* 572230130Smav * These codecs have hidden mic boost controls. 573230130Smav */ 574230130Smav w = hdaa_widget_get(devinfo, 26); 575230130Smav if (w != NULL) 576230130Smav w->param.inamp_cap = 577230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 578230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 579230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 580230130Smav w = hdaa_widget_get(devinfo, 30); 581230130Smav if (w != NULL) 582230130Smav w->param.inamp_cap = 583230130Smav (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 584230130Smav (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 585230130Smav (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 586230130Smav break; 587230130Smav } 588230130Smav} 589230130Smav 590230130Smavvoid 591230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo) 592230130Smav{ 593230130Smav device_t dev = devinfo->dev; 594230130Smav uint32_t id, subid, val; 595230130Smav 596230130Smav id = hdaa_codec_id(devinfo); 597230130Smav subid = hdaa_subvendor_id(devinfo); 598230130Smav 599230130Smav switch (id) { 600230130Smav case HDA_CODEC_VT1708S_0: 601230130Smav case HDA_CODEC_VT1708S_1: 602230130Smav case HDA_CODEC_VT1708S_2: 603230130Smav case HDA_CODEC_VT1708S_3: 604230130Smav case HDA_CODEC_VT1708S_4: 605230130Smav case HDA_CODEC_VT1708S_5: 606230130Smav case HDA_CODEC_VT1708S_6: 607230130Smav case HDA_CODEC_VT1708S_7: 608230130Smav /* Enable Mic Boost Volume controls. */ 609230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 610230130Smav 0xf98, 0x01)); 611241375Smav /* Fall though */ 612241375Smav case HDA_CODEC_VT1818S: 613230130Smav /* Don't bypass mixer. */ 614230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 615230130Smav 0xf88, 0xc0)); 616230130Smav break; 617230130Smav } 618230130Smav if (subid == APPLE_INTEL_MAC) 619230130Smav hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 620230130Smav 0x7e7, 0)); 621230130Smav if (id == HDA_CODEC_ALC269) { 622230532Smav if (subid == 0x16e31043 || subid == 0x831a1043 || 623230532Smav subid == 0x834a1043 || subid == 0x83981043 || 624230532Smav subid == 0x83ce1043) { 625230130Smav /* 626230130Smav * The ditital mics on some Asus laptops produce 627230130Smav * differential signals instead of expected stereo. 628230130Smav * That results in silence if downmix it to mono. 629230130Smav * To workaround, make codec to handle signal as mono. 630230130Smav */ 631230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 632230130Smav val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 633230130Smav hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 634230130Smav hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 635230130Smav } 636230130Smav } 637230130Smav} 638