hdac.c revision 170518
1162922Sariff/*- 2162922Sariff * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3162922Sariff * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4162922Sariff * All rights reserved. 5162922Sariff * 6162922Sariff * Redistribution and use in source and binary forms, with or without 7162922Sariff * modification, are permitted provided that the following conditions 8162922Sariff * are met: 9162922Sariff * 1. Redistributions of source code must retain the above copyright 10162922Sariff * notice, this list of conditions and the following disclaimer. 11162922Sariff * 2. Redistributions in binary form must reproduce the above copyright 12162922Sariff * notice, this list of conditions and the following disclaimer in the 13162922Sariff * documentation and/or other materials provided with the distribution. 14162922Sariff * 15162922Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18162922Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25162922Sariff * SUCH DAMAGE. 26162922Sariff */ 27162922Sariff 28162922Sariff/* 29162922Sariff * Intel High Definition Audio (Controller) driver for FreeBSD. Be advised 30162922Sariff * that this driver still in its early stage, and possible of rewrite are 31162922Sariff * pretty much guaranteed. There are supposedly several distinct parent/child 32162922Sariff * busses to make this "perfect", but as for now and for the sake of 33162922Sariff * simplicity, everything is gobble up within single source. 34162922Sariff * 35162922Sariff * List of subsys: 36162922Sariff * 1) HDA Controller support 37162922Sariff * 2) HDA Codecs support, which may include 38162922Sariff * - HDA 39162922Sariff * - Modem 40162922Sariff * - HDMI 41162922Sariff * 3) Widget parser - the real magic of why this driver works on so 42162922Sariff * many hardwares with minimal vendor specific quirk. The original 43162922Sariff * parser was written using Ruby and can be found at 44162922Sariff * http://people.freebsd.org/~ariff/HDA/parser.rb . This crude 45162922Sariff * ruby parser take the verbose dmesg dump as its input. Refer to 46162922Sariff * http://www.microsoft.com/whdc/device/audio/default.mspx for various 47164614Sariff * interesting documents, especially UAA (Universal Audio Architecture). 48162922Sariff * 4) Possible vendor specific support. 49162922Sariff * (snd_hda_intel, snd_hda_ati, etc..) 50162922Sariff * 51162922Sariff * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the 52162922Sariff * Compaq V3000 with Conexant HDA. 53162922Sariff * 54162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 55162922Sariff * * * 56162922Sariff * * This driver is a collaborative effort made by: * 57162922Sariff * * * 58162922Sariff * * Stephane E. Potvin <sepotvin@videotron.ca> * 59162922Sariff * * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * 60162922Sariff * * Wesley Morgan <morganw@chemikals.org> * 61162922Sariff * * Daniel Eischen <deischen@FreeBSD.org> * 62162922Sariff * * Maxime Guillaud <bsd-ports@mguillaud.net> * 63162922Sariff * * Ariff Abdullah <ariff@FreeBSD.org> * 64162922Sariff * * * 65162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 66162922Sariff * * * 67162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 68162922Sariff */ 69162922Sariff 70163057Sariff#include <sys/ctype.h> 71163057Sariff 72162922Sariff#include <dev/sound/pcm/sound.h> 73162922Sariff#include <dev/pci/pcireg.h> 74162922Sariff#include <dev/pci/pcivar.h> 75162922Sariff 76162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 77162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 78162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 79162922Sariff#include <dev/sound/pci/hda/hdac.h> 80162922Sariff 81162922Sariff#include "mixer_if.h" 82162922Sariff 83170518Sariff#define HDA_DRV_TEST_REV "20070611_0045" 84162922Sariff#define HDA_WIDGET_PARSER_REV 1 85162922Sariff 86162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 170518 2007-06-10 23:01:40Z ariff $"); 87162922Sariff 88169277Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 89169277Sariff if (bootverbose != 0 || snd_verbose > 3) { \ 90169277Sariff stmt \ 91169277Sariff } \ 92162922Sariff} while(0) 93162922Sariff 94162965Sariff#if 1 95162922Sariff#undef HDAC_INTR_EXTRA 96162922Sariff#define HDAC_INTR_EXTRA 1 97162922Sariff#endif 98162922Sariff 99162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 100162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 101163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 102163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 103162922Sariff 104162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 105163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 106163257Sariff (fl) == 0xffffffff || \ 107163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 108163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 109163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 110163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 111162965Sariff#define HDA_MATCH_ALL 0xffffffff 112162965Sariff#define HDAC_INVALID 0xffffffff 113162965Sariff 114169277Sariff/* Default controller / jack sense poll: 250ms */ 115169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 116169277Sariff 117162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 118162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 119162922Sariff 120162922Sariff/* Controller models */ 121162922Sariff 122162922Sariff/* Intel */ 123162922Sariff#define INTEL_VENDORID 0x8086 124162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 125162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 126163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 127163136Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 128162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 129162922Sariff 130162922Sariff/* Nvidia */ 131162922Sariff#define NVIDIA_VENDORID 0x10de 132162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 133162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 134163136Sariff#define HDA_NVIDIA_MCP61A HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 135163136Sariff#define HDA_NVIDIA_MCP61B HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 136163136Sariff#define HDA_NVIDIA_MCP65A HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 137163136Sariff#define HDA_NVIDIA_MCP65B HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 138162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 139162922Sariff 140162922Sariff/* ATI */ 141162922Sariff#define ATI_VENDORID 0x1002 142162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 143163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 144162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 145162922Sariff 146163136Sariff/* VIA */ 147163136Sariff#define VIA_VENDORID 0x1106 148163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 149163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 150163136Sariff 151163136Sariff/* SiS */ 152163136Sariff#define SIS_VENDORID 0x1039 153163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 154163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 155163136Sariff 156162922Sariff/* OEM/subvendors */ 157162922Sariff 158165466Sariff/* Intel */ 159165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 160165466Sariff 161162922Sariff/* HP/Compaq */ 162162922Sariff#define HP_VENDORID 0x103c 163162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 164162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 165162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 166165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 167166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 168169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 169169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 170162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 171165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 172165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 173162922Sariff 174162922Sariff/* Dell */ 175162922Sariff#define DELL_VENDORID 0x1028 176162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 177162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 178169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 179169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 180162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 181162922Sariff 182162922Sariff/* Clevo */ 183162922Sariff#define CLEVO_VENDORID 0x1558 184162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 185162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 186162922Sariff 187162922Sariff/* Acer */ 188162922Sariff#define ACER_VENDORID 0x1025 189165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 190169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 191162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 192162922Sariff 193162965Sariff/* Asus */ 194162965Sariff#define ASUS_VENDORID 0x1043 195162965Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 196163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 197163432Sariff#define ASUS_A8JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 198165103Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 199165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 200167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 201167648Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 202169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 203169277Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 204170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 205169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 206169277Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 207170518Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 208162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 209162922Sariff 210163257Sariff/* IBM / Lenovo */ 211163257Sariff#define IBM_VENDORID 0x1014 212163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 213163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 214162965Sariff 215164614Sariff/* Lenovo */ 216164657Sariff#define LENOVO_VENDORID 0x17aa 217164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 218164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 219163257Sariff 220164657Sariff/* Samsung */ 221164657Sariff#define SAMSUNG_VENDORID 0x144d 222164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 223164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 224164614Sariff 225164750Sariff/* Medion ? */ 226164750Sariff#define MEDION_VENDORID 0x161f 227164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 228164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 229164750Sariff 230164828Sariff/* 231164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 232164828Sariff * instead of their own, which is beyond my comprehension 233164828Sariff * (see HDA_CODEC_STAC9221 below). 234164828Sariff */ 235164828Sariff#define APPLE_INTEL_MAC 0x76808384 236164828Sariff 237165281Sariff/* LG Electronics */ 238165281Sariff#define LG_VENDORID 0x1854 239165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 240165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 241165281Sariff 242165351Sariff/* Fujitsu Siemens */ 243165351Sariff#define FS_VENDORID 0x1734 244165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 245165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 246165351Sariff 247165770Sariff/* Toshiba */ 248165770Sariff#define TOSHIBA_VENDORID 0x1179 249165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 250165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 251165770Sariff 252165992Sariff/* Micro-Star International (MSI) */ 253165992Sariff#define MSI_VENDORID 0x1462 254165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 255165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 256165992Sariff 257169277Sariff/* Uniwill ? */ 258169277Sariff#define UNIWILL_VENDORID 0x1584 259169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 260169277Sariff 261169277Sariff 262162922Sariff/* Misc constants.. */ 263162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 264162922Sariff#define HDA_AMP_MUTE_NONE (0) 265162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 266162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 267162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 268162922Sariff 269162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 270162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 271162922Sariff 272162922Sariff#define HDA_DAC_PATH (1 << 0) 273162922Sariff#define HDA_ADC_PATH (1 << 1) 274162922Sariff#define HDA_ADC_RECSEL (1 << 2) 275162922Sariff 276169277Sariff#define HDA_DAC_LOCKED (1 << 3) 277169277Sariff#define HDA_ADC_LOCKED (1 << 4) 278169277Sariff 279163057Sariff#define HDA_CTL_OUT (1 << 0) 280163057Sariff#define HDA_CTL_IN (1 << 1) 281162922Sariff#define HDA_CTL_BOTH (HDA_CTL_IN | HDA_CTL_OUT) 282162922Sariff 283169277Sariff#define HDA_GPIO_MAX 8 284169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 285163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 286163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 287163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 288169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 289169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 290169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 291169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 292169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 293169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 294162922Sariff 295169277Sariff/* 9 - 25 = anything else */ 296169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 297169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 298169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 299169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 300169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 301169277Sariff 302169277Sariff/* 26 - 31 = vrefs */ 303169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 304169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 305169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 306169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 307169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 308169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 309169277Sariff 310169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 311169277Sariff HDA_QUIRK_IVREF100) 312169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 313169277Sariff HDA_QUIRK_OVREF100) 314169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 315169277Sariff 316169277Sariff#define SOUND_MASK_SKIP (1 << 30) 317169277Sariff#define SOUND_MASK_DISABLE (1 << 31) 318169277Sariff 319163057Sariffstatic const struct { 320163057Sariff char *key; 321163057Sariff uint32_t value; 322163057Sariff} hdac_quirks_tab[] = { 323163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 324163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 325163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 326169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 327169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 328169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 329169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 330169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 331165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 332163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 333163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 334163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 335163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 336169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 337169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 338169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 339169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 340169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 341169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 342169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 343169277Sariff { "ivref", HDA_QUIRK_IVREF }, 344169277Sariff { "ovref", HDA_QUIRK_OVREF }, 345165069Sariff { "vref", HDA_QUIRK_VREF }, 346163057Sariff}; 347163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 348163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 349163057Sariff 350162922Sariff#define HDA_BDL_MIN 2 351162922Sariff#define HDA_BDL_MAX 256 352162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 353162922Sariff 354169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 355167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 356167648Sariff 357162922Sariff#define HDA_BUFSZ_MIN 4096 358162922Sariff#define HDA_BUFSZ_MAX 65536 359162922Sariff#define HDA_BUFSZ_DEFAULT 16384 360162922Sariff 361162922Sariff#define HDA_PARSE_MAXDEPTH 10 362162922Sariff 363169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 364169277Sariff#define HDAC_UNSOLTAG_EVENT_TEST 0x01 365162922Sariff 366165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 367162922Sariff 368162922Sariffenum { 369162922Sariff HDA_PARSE_MIXER, 370162922Sariff HDA_PARSE_DIRECT 371162922Sariff}; 372162922Sariff 373162922Sariff/* Default */ 374162922Sariffstatic uint32_t hdac_fmt[] = { 375162922Sariff AFMT_STEREO | AFMT_S16_LE, 376162922Sariff 0 377162922Sariff}; 378162922Sariff 379162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 380162922Sariff 381162922Sariffstatic const struct { 382162922Sariff uint32_t model; 383162922Sariff char *desc; 384162922Sariff} hdac_devices[] = { 385162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 386162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 387163136Sariff { HDA_INTEL_82801H, "Intel 82801H" }, 388163136Sariff { HDA_INTEL_63XXESB, "Intel 631x/632xESB" }, 389162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 390162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 391163136Sariff { HDA_NVIDIA_MCP61A, "NVidia MCP61A" }, 392163136Sariff { HDA_NVIDIA_MCP61B, "NVidia MCP61B" }, 393163136Sariff { HDA_NVIDIA_MCP65A, "NVidia MCP65A" }, 394163136Sariff { HDA_NVIDIA_MCP65B, "NVidia MCP65B" }, 395162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 396163136Sariff { HDA_ATI_SB600, "ATI SB600" }, 397163136Sariff { HDA_VIA_VT82XX, "VIA VT8251/8237A" }, 398163136Sariff { HDA_SIS_966, "SiS 966" }, 399162922Sariff /* Unknown */ 400162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 401162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 402162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 403163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 404163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 405162922Sariff}; 406162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 407162922Sariff 408162922Sariffstatic const struct { 409169277Sariff uint16_t vendor; 410169277Sariff uint8_t reg; 411169277Sariff uint8_t mask; 412169277Sariff uint8_t enable; 413169277Sariff} hdac_pcie_snoop[] = { 414169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 415169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 416169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 417169277Sariff}; 418169277Sariff#define HDAC_PCIESNOOP_LEN \ 419169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 420169277Sariff 421169277Sariffstatic const struct { 422162922Sariff uint32_t rate; 423162922Sariff int valid; 424162922Sariff uint16_t base; 425162922Sariff uint16_t mul; 426162922Sariff uint16_t div; 427162922Sariff} hda_rate_tab[] = { 428162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 429162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 430162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 431162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 432162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 433162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 434162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 435162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 436162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 437162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 438162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 439162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 440162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 441162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 442162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 443162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 444162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 445162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 446162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 447162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 448162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 449162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 450162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 451162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 452162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 453162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 454162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 455162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 456162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 457162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 458162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 459162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 460162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 461162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 462162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 463162922Sariff}; 464162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 465162922Sariff 466162922Sariff/* All codecs you can eat... */ 467162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 468162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 469162922Sariff 470162922Sariff/* Realtek */ 471162922Sariff#define REALTEK_VENDORID 0x10ec 472162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 473169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 474170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 475162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 476169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 477162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 478163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 479163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 480169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 481165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 482162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 483162922Sariff 484169277Sariff/* Analog Devices */ 485169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 486169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 487169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 488169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 489169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 490170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 491169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 492162922Sariff 493162922Sariff/* CMedia */ 494162922Sariff#define CMEDIA_VENDORID 0x434d 495162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 496162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 497162922Sariff 498162922Sariff/* Sigmatel */ 499162922Sariff#define SIGMATEL_VENDORID 0x8384 500162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 501162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 502162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 503162922Sariff#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 504165305Sariff#define HDA_CODEC_STAC9227 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 505166796Sariff#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 506162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 507162922Sariff 508162922Sariff/* 509162922Sariff * Conexant 510162922Sariff * 511162922Sariff * Ok, the truth is, I don't have any idea at all whether 512162922Sariff * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only 513162922Sariff * place that tell me it is "Venice" is from its Windows driver INF. 514163057Sariff * 515163057Sariff * Venice - CX????? 516163057Sariff * Waikiki - CX20551-22 517162922Sariff */ 518162922Sariff#define CONEXANT_VENDORID 0x14f1 519162922Sariff#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 520163057Sariff#define HDA_CODEC_CXWAIKIKI HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 521162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 522162922Sariff 523169277Sariff/* VIA */ 524169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 525169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 526169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 527169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 528169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 529169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 530169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 531169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 532169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 533169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 534169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 535169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 536169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 537162922Sariff 538169277Sariff 539162922Sariff/* Codecs */ 540162922Sariffstatic const struct { 541162922Sariff uint32_t id; 542162922Sariff char *name; 543162922Sariff} hdac_codecs[] = { 544162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 545169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 546170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 547162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 548169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 549162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 550162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 551163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 552169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 553165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 554169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 555169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 556169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 557169277Sariff { HDA_CODEC_AD1988, "Analog Devices AD1988" }, 558170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 559162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 560162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 561162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 562162922Sariff { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 563162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 564165305Sariff { HDA_CODEC_STAC9227, "Sigmatel STAC9227" }, 565166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 566162922Sariff { HDA_CODEC_CXVENICE, "Conexant Venice" }, 567163057Sariff { HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" }, 568169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 569169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 570169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 571169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 572169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 573169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 574169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 575169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 576169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 577169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 578169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 579169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 580162922Sariff /* Unknown codec */ 581162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 582169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 583162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 584162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 585162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 586169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 587162922Sariff}; 588162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 589162922Sariff 590162922Sariffenum { 591162922Sariff HDAC_HP_SWITCH_CTL, 592169277Sariff HDAC_HP_SWITCH_CTRL, 593169277Sariff HDAC_HP_SWITCH_DEBUG 594162922Sariff}; 595162922Sariff 596162922Sariffstatic const struct { 597162965Sariff uint32_t model; 598162922Sariff uint32_t id; 599162922Sariff int type; 600165039Sariff int inverted; 601169277Sariff int polling; 602169277Sariff int execsense; 603162922Sariff nid_t hpnid; 604162922Sariff nid_t spkrnid[8]; 605162922Sariff nid_t eapdnid; 606162922Sariff} hdac_hp_switch[] = { 607162922Sariff /* Specific OEM models */ 608169277Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 609169277Sariff 0, 0, -1, 17, { 16, -1 }, 16 }, 610169277Sariff /* { HP_XW4300_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL, 611169277Sariff 0, 0, -1, 21, { 16, 17, -1 }, -1 } */ 612169277Sariff /*{ HP_3010_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_DEBUG, 613169277Sariff 0, 1, 0, 16, { 15, 18, 19, 20, 21, -1 }, -1 },*/ 614169277Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 615169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 616169277Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 617169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 618169277Sariff { HP_NX6325_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 619169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 620169277Sariff { TOSHIBA_U200_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 621169277Sariff 0, 0, -1, 6, { 5, -1 }, -1 }, 622169277Sariff { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 623169277Sariff 0, 0, -1, 13, { 14, -1 }, -1 }, 624169277Sariff { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 625169277Sariff 0, 0, -1, 13, { 14, -1 }, -1 }, 626169277Sariff { DELL_OPLX745_SUBVENDOR, HDA_CODEC_AD1983, HDAC_HP_SWITCH_CTL, 627169277Sariff 0, 0, -1, 6, { 5, 7, -1 }, -1 }, 628169277Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL, 629169277Sariff 0, 0, -1, 10, { 13, -1 }, -1 }, 630169277Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 631169277Sariff 1, 0, -1, 26, { 27, -1 }, -1 }, 632169277Sariff { LG_LW20_SUBVENDOR, HDA_CODEC_ALC880, HDAC_HP_SWITCH_CTL, 633169277Sariff 0, 0, -1, 27, { 20, -1 }, -1 }, 634169277Sariff { ACER_A5050_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 635169277Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 636169277Sariff { ACER_3681WXM_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 637169277Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 638169277Sariff { MSI_MS1034_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 639169277Sariff 0, 0, -1, 20, { 27, -1 }, -1 }, 640162922Sariff /* 641162922Sariff * All models that at least come from the same vendor with 642162922Sariff * simmilar codec. 643162922Sariff */ 644169277Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 645169277Sariff 0, 0, -1, 17, { 16, -1 }, 16 }, 646169277Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 647169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 648169277Sariff { TOSHIBA_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 649169277Sariff 0, 0, -1, 6, { 5, -1 }, -1 }, 650169277Sariff { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 651169277Sariff 0, 0, -1, 13, { 14, -1 }, -1 }, 652169277Sariff { LENOVO_ALL_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 653169277Sariff 1, 0, -1, 26, { 27, -1 }, -1 }, 654166294Sariff#if 0 655169277Sariff { ACER_ALL_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 656169277Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 657166294Sariff#endif 658162922Sariff}; 659162922Sariff#define HDAC_HP_SWITCH_LEN \ 660162922Sariff (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0])) 661162922Sariff 662162922Sariffstatic const struct { 663162965Sariff uint32_t model; 664162922Sariff uint32_t id; 665162922Sariff nid_t eapdnid; 666162922Sariff int hp_switch; 667162922Sariff} hdac_eapd_switch[] = { 668162922Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, 16, 1 }, 669162922Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 670162922Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 671162922Sariff}; 672162922Sariff#define HDAC_EAPD_SWITCH_LEN \ 673162922Sariff (sizeof(hdac_eapd_switch) / sizeof(hdac_eapd_switch[0])) 674162922Sariff 675162922Sariff/**************************************************************************** 676162922Sariff * Function prototypes 677162922Sariff ****************************************************************************/ 678162922Sariffstatic void hdac_intr_handler(void *); 679162922Sariffstatic int hdac_reset(struct hdac_softc *); 680162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 681162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 682162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 683162922Sariff struct hdac_dma *, bus_size_t); 684169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 685162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 686162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 687162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 688162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 689162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 690162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 691162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 692162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 693162922Sariffstatic void hdac_scan_codecs(struct hdac_softc *); 694162922Sariffstatic int hdac_probe_codec(struct hdac_codec *); 695162922Sariffstatic struct hdac_devinfo *hdac_probe_function(struct hdac_codec *, nid_t); 696162922Sariffstatic void hdac_add_child(struct hdac_softc *, struct hdac_devinfo *); 697162922Sariff 698162922Sariffstatic void hdac_attach2(void *); 699162922Sariff 700162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 701162922Sariff uint32_t, int); 702162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 703162922Sariff struct hdac_command_list *, int); 704162922Sariff 705162922Sariffstatic int hdac_probe(device_t); 706162922Sariffstatic int hdac_attach(device_t); 707162922Sariffstatic int hdac_detach(device_t); 708162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 709162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 710162922Sariff uint32_t, int, int); 711162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 712162922Sariff nid_t, int, int); 713162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 714162922Sariff nid_t, nid_t, int, int, int, int, int, int); 715162922Sariffstatic int hdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *); 716162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 717162922Sariff 718164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 719164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 720164614Sariff 721162922Sariff#define hdac_command(a1, a2, a3) \ 722162922Sariff hdac_command_sendone_internal(a1, a2, a3) 723162922Sariff 724162922Sariff#define hdac_codec_id(d) \ 725162922Sariff ((uint32_t)((d == NULL) ? 0x00000000 : \ 726162922Sariff ((((uint32_t)(d)->vendor_id & 0x0000ffff) << 16) | \ 727162922Sariff ((uint32_t)(d)->device_id & 0x0000ffff)))) 728162922Sariff 729162922Sariffstatic char * 730162922Sariffhdac_codec_name(struct hdac_devinfo *devinfo) 731162922Sariff{ 732162922Sariff uint32_t id; 733162922Sariff int i; 734162922Sariff 735162922Sariff id = hdac_codec_id(devinfo); 736162922Sariff 737162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 738163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 739162922Sariff return (hdac_codecs[i].name); 740162922Sariff } 741162922Sariff 742162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 743162922Sariff} 744162922Sariff 745162922Sariffstatic char * 746162922Sariffhdac_audio_ctl_ossmixer_mask2name(uint32_t devmask) 747162922Sariff{ 748162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 749162922Sariff static char *unknown = "???"; 750162922Sariff int i; 751162922Sariff 752162922Sariff for (i = SOUND_MIXER_NRDEVICES - 1; i >= 0; i--) { 753162922Sariff if (devmask & (1 << i)) 754162922Sariff return (ossname[i]); 755162922Sariff } 756162922Sariff return (unknown); 757162922Sariff} 758162922Sariff 759162922Sariffstatic void 760162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 761162922Sariff{ 762162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 763162922Sariff int i, first = 1; 764162922Sariff 765162922Sariff bzero(buf, len); 766162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 767162922Sariff if (mask & (1 << i)) { 768162922Sariff if (first == 0) 769162922Sariff strlcat(buf, ", ", len); 770162922Sariff strlcat(buf, ossname[i], len); 771162922Sariff first = 0; 772162922Sariff } 773162922Sariff } 774162922Sariff} 775162922Sariff 776162922Sariffstatic struct hdac_audio_ctl * 777162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 778162922Sariff{ 779162922Sariff if (devinfo == NULL || 780162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 781162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 782162922Sariff devinfo->function.audio.ctlcnt < 1 || 783162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 784162922Sariff return (NULL); 785162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 786162922Sariff} 787162922Sariff 788162922Sariffstatic struct hdac_audio_ctl * 789162922Sariffhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, 790162922Sariff int index, int cnt) 791162922Sariff{ 792162922Sariff struct hdac_audio_ctl *ctl, *retctl = NULL; 793162922Sariff int i, at, atindex, found = 0; 794162922Sariff 795162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 796162922Sariff return (NULL); 797162922Sariff 798162922Sariff at = cnt; 799162922Sariff if (at == 0) 800162922Sariff at = 1; 801162922Sariff else if (at < 0) 802162922Sariff at = -1; 803162922Sariff atindex = index; 804162922Sariff if (atindex < 0) 805162922Sariff atindex = -1; 806162922Sariff 807162922Sariff i = 0; 808162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 809162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 810162922Sariff continue; 811162922Sariff if (!(ctl->widget->nid == nid && (atindex == -1 || 812162922Sariff ctl->index == atindex))) 813162922Sariff continue; 814162922Sariff found++; 815162922Sariff if (found == cnt) 816162922Sariff return (ctl); 817162922Sariff retctl = ctl; 818162922Sariff } 819162922Sariff 820162922Sariff return ((at == -1) ? retctl : NULL); 821162922Sariff} 822162922Sariff 823162922Sariffstatic void 824162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 825162922Sariff{ 826162922Sariff struct hdac_softc *sc; 827162922Sariff struct hdac_widget *w; 828162922Sariff struct hdac_audio_ctl *ctl; 829169277Sariff uint32_t val, id, res; 830162922Sariff int i = 0, j, forcemute; 831162922Sariff nid_t cad; 832162922Sariff 833162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 834162922Sariff devinfo->codec->sc == NULL) 835162922Sariff return; 836162922Sariff 837162922Sariff sc = devinfo->codec->sc; 838162922Sariff cad = devinfo->codec->cad; 839162922Sariff id = hdac_codec_id(devinfo); 840162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 841163257Sariff if (HDA_DEV_MATCH(hdac_hp_switch[i].model, 842162965Sariff sc->pci_subvendor) && 843162922Sariff hdac_hp_switch[i].id == id) 844162922Sariff break; 845162922Sariff } 846162922Sariff 847162922Sariff if (i >= HDAC_HP_SWITCH_LEN) 848162922Sariff return; 849162922Sariff 850162922Sariff forcemute = 0; 851162922Sariff if (hdac_hp_switch[i].eapdnid != -1) { 852162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid); 853162965Sariff if (w != NULL && w->param.eapdbtl != HDAC_INVALID) 854162922Sariff forcemute = (w->param.eapdbtl & 855162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1; 856162922Sariff } 857162922Sariff 858169277Sariff if (hdac_hp_switch[i].execsense != -1) 859169277Sariff hdac_command(sc, 860169277Sariff HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid, 861169277Sariff hdac_hp_switch[i].execsense), cad); 862162922Sariff res = hdac_command(sc, 863162922Sariff HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad); 864163057Sariff HDA_BOOTVERBOSE( 865162922Sariff device_printf(sc->dev, 866163057Sariff "HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n", 867162922Sariff hdac_hp_switch[i].hpnid, res); 868162922Sariff ); 869169277Sariff res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 870165039Sariff res ^= hdac_hp_switch[i].inverted; 871162922Sariff 872162922Sariff switch (hdac_hp_switch[i].type) { 873162922Sariff case HDAC_HP_SWITCH_CTL: 874162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 875162922Sariff hdac_hp_switch[i].hpnid, 0, 1); 876162922Sariff if (ctl != NULL) { 877169277Sariff val = (res != 0 && forcemute == 0) ? 878162922Sariff HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL; 879169277Sariff if (val != ctl->muted) { 880169277Sariff ctl->muted = val; 881162922Sariff hdac_audio_ctl_amp_set(ctl, 882162922Sariff HDA_AMP_MUTE_DEFAULT, ctl->left, 883162922Sariff ctl->right); 884162922Sariff } 885162922Sariff } 886169277Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 887169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 888169277Sariff hdac_hp_switch[i].spkrnid[j], 0, 1); 889169277Sariff if (ctl == NULL) 890169277Sariff continue; 891169277Sariff val = (res != 0 || forcemute == 1) ? 892169277Sariff HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE; 893169277Sariff if (val == ctl->muted) 894169277Sariff continue; 895169277Sariff ctl->muted = val; 896169277Sariff hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT, 897169277Sariff ctl->left, ctl->right); 898169277Sariff } 899162922Sariff break; 900162922Sariff case HDAC_HP_SWITCH_CTRL: 901162922Sariff if (res != 0) { 902162922Sariff /* HP in */ 903162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 904163057Sariff if (w != NULL && w->type == 905163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 906162922Sariff if (forcemute == 0) 907169277Sariff val = w->wclass.pin.ctrl | 908162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 909162922Sariff else 910169277Sariff val = w->wclass.pin.ctrl & 911162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 912169277Sariff if (val != w->wclass.pin.ctrl) { 913169277Sariff w->wclass.pin.ctrl = val; 914169277Sariff hdac_command(sc, 915169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 916169277Sariff w->nid, w->wclass.pin.ctrl), cad); 917169277Sariff } 918162922Sariff } 919162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 920162922Sariff w = hdac_widget_get(devinfo, 921162922Sariff hdac_hp_switch[i].spkrnid[j]); 922169277Sariff if (w == NULL || w->type != 923169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 924169277Sariff continue; 925169277Sariff val = w->wclass.pin.ctrl & 926169277Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 927169277Sariff if (val == w->wclass.pin.ctrl) 928169277Sariff continue; 929169277Sariff w->wclass.pin.ctrl = val; 930169277Sariff hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL( 931169277Sariff cad, w->nid, w->wclass.pin.ctrl), cad); 932162922Sariff } 933162922Sariff } else { 934162922Sariff /* HP out */ 935162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 936163057Sariff if (w != NULL && w->type == 937163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 938169277Sariff val = w->wclass.pin.ctrl & 939162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 940169277Sariff if (val != w->wclass.pin.ctrl) { 941169277Sariff w->wclass.pin.ctrl = val; 942169277Sariff hdac_command(sc, 943169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 944169277Sariff w->nid, w->wclass.pin.ctrl), cad); 945169277Sariff } 946162922Sariff } 947162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 948162922Sariff w = hdac_widget_get(devinfo, 949162922Sariff hdac_hp_switch[i].spkrnid[j]); 950169277Sariff if (w == NULL || w->type != 951169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 952169277Sariff continue; 953169277Sariff if (forcemute == 0) 954169277Sariff val = w->wclass.pin.ctrl | 955169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 956169277Sariff else 957169277Sariff val = w->wclass.pin.ctrl & 958169277Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 959169277Sariff if (val == w->wclass.pin.ctrl) 960169277Sariff continue; 961169277Sariff w->wclass.pin.ctrl = val; 962169277Sariff hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL( 963169277Sariff cad, w->nid, w->wclass.pin.ctrl), cad); 964162922Sariff } 965162922Sariff } 966162922Sariff break; 967169277Sariff case HDAC_HP_SWITCH_DEBUG: 968169277Sariff if (hdac_hp_switch[i].execsense != -1) 969169277Sariff hdac_command(sc, 970169277Sariff HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid, 971169277Sariff hdac_hp_switch[i].execsense), cad); 972169277Sariff res = hdac_command(sc, 973169277Sariff HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad); 974169277Sariff device_printf(sc->dev, 975169277Sariff "[ 0] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n", 976169277Sariff hdac_hp_switch[i].hpnid, res); 977169277Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 978169277Sariff w = hdac_widget_get(devinfo, 979169277Sariff hdac_hp_switch[i].spkrnid[j]); 980169277Sariff if (w == NULL || w->type != 981169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 982169277Sariff continue; 983169277Sariff if (hdac_hp_switch[i].execsense != -1) 984169277Sariff hdac_command(sc, 985169277Sariff HDA_CMD_SET_PIN_SENSE(cad, w->nid, 986169277Sariff hdac_hp_switch[i].execsense), cad); 987169277Sariff res = hdac_command(sc, 988169277Sariff HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 989169277Sariff device_printf(sc->dev, 990169277Sariff "[%2d] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n", 991169277Sariff j + 1, w->nid, res); 992169277Sariff } 993169277Sariff break; 994162922Sariff default: 995162922Sariff break; 996162922Sariff } 997162922Sariff} 998162922Sariff 999162922Sariffstatic void 1000162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1001162922Sariff{ 1002162922Sariff struct hdac_softc *sc; 1003162922Sariff struct hdac_devinfo *devinfo = NULL; 1004162965Sariff device_t *devlist = NULL; 1005162922Sariff int devcount, i; 1006162922Sariff 1007162922Sariff if (codec == NULL || codec->sc == NULL) 1008162922Sariff return; 1009162922Sariff 1010162922Sariff sc = codec->sc; 1011162922Sariff 1012163057Sariff HDA_BOOTVERBOSE( 1013163057Sariff device_printf(sc->dev, "HDA_DEBUG: Unsol Tag: 0x%08x\n", tag); 1014162922Sariff ); 1015162922Sariff 1016162922Sariff device_get_children(sc->dev, &devlist, &devcount); 1017162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 1018162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 1019162965Sariff if (devinfo != NULL && devinfo->node_type == 1020162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 1021162965Sariff devinfo->codec != NULL && 1022162965Sariff devinfo->codec->cad == codec->cad) { 1023162965Sariff break; 1024162965Sariff } else 1025162965Sariff devinfo = NULL; 1026162922Sariff } 1027162965Sariff if (devlist != NULL) 1028162965Sariff free(devlist, M_TEMP); 1029162965Sariff 1030162922Sariff if (devinfo == NULL) 1031162922Sariff return; 1032162922Sariff 1033162922Sariff switch (tag) { 1034162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1035162922Sariff hdac_hp_switch_handler(devinfo); 1036162922Sariff break; 1037169277Sariff case HDAC_UNSOLTAG_EVENT_TEST: 1038169277Sariff device_printf(sc->dev, "Unsol Test!\n"); 1039169277Sariff break; 1040162922Sariff default: 1041162922Sariff break; 1042162922Sariff } 1043162922Sariff} 1044162922Sariff 1045164614Sariffstatic int 1046162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1047162922Sariff{ 1048162922Sariff /* XXX to be removed */ 1049162922Sariff#ifdef HDAC_INTR_EXTRA 1050162922Sariff uint32_t res; 1051162922Sariff#endif 1052162922Sariff 1053162922Sariff if (ch->blkcnt == 0) 1054164614Sariff return (0); 1055162922Sariff 1056162922Sariff /* XXX to be removed */ 1057162922Sariff#ifdef HDAC_INTR_EXTRA 1058162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1059162922Sariff#endif 1060162922Sariff 1061162922Sariff /* XXX to be removed */ 1062162922Sariff#ifdef HDAC_INTR_EXTRA 1063163057Sariff HDA_BOOTVERBOSE( 1064163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1065163057Sariff device_printf(sc->dev, 1066163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1067163057Sariff "%08x\n", 1068163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1069163057Sariff ); 1070162922Sariff#endif 1071162922Sariff 1072162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1073163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1074162922Sariff 1075162922Sariff /* XXX to be removed */ 1076162922Sariff#ifdef HDAC_INTR_EXTRA 1077162922Sariff if (res & HDAC_SDSTS_BCIS) { 1078162922Sariff#endif 1079164614Sariff return (1); 1080162922Sariff /* XXX to be removed */ 1081162922Sariff#ifdef HDAC_INTR_EXTRA 1082162922Sariff } 1083162922Sariff#endif 1084164614Sariff 1085164614Sariff return (0); 1086162922Sariff} 1087162922Sariff 1088162922Sariff/**************************************************************************** 1089162922Sariff * void hdac_intr_handler(void *) 1090162922Sariff * 1091162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1092162922Sariff ****************************************************************************/ 1093162922Sariffstatic void 1094162922Sariffhdac_intr_handler(void *context) 1095162922Sariff{ 1096162922Sariff struct hdac_softc *sc; 1097162922Sariff uint32_t intsts; 1098162922Sariff uint8_t rirbsts; 1099164614Sariff struct hdac_rirb *rirb_base; 1100164614Sariff uint32_t trigger = 0; 1101162922Sariff 1102162922Sariff sc = (struct hdac_softc *)context; 1103162922Sariff 1104162922Sariff hdac_lock(sc); 1105164614Sariff if (sc->polling != 0) { 1106164614Sariff hdac_unlock(sc); 1107164614Sariff return; 1108164614Sariff } 1109162922Sariff /* Do we have anything to do? */ 1110162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1111163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1112162922Sariff hdac_unlock(sc); 1113162922Sariff return; 1114162922Sariff } 1115162922Sariff 1116162922Sariff /* Was this a controller interrupt? */ 1117163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1118162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1119162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1120162922Sariff /* Get as many responses that we can */ 1121163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1122164614Sariff HDAC_WRITE_1(&sc->mem, 1123164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1124164614Sariff hdac_rirb_flush(sc); 1125162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1126162922Sariff } 1127162922Sariff /* XXX to be removed */ 1128162922Sariff /* Clear interrupt and exit */ 1129162922Sariff#ifdef HDAC_INTR_EXTRA 1130162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1131162922Sariff#endif 1132162922Sariff } 1133164614Sariff 1134164614Sariff hdac_unsolq_flush(sc); 1135164614Sariff 1136163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1137164614Sariff if ((intsts & (1 << sc->num_iss)) && 1138164614Sariff hdac_stream_intr(sc, &sc->play) != 0) 1139164614Sariff trigger |= 1; 1140164614Sariff if ((intsts & (1 << 0)) && 1141164614Sariff hdac_stream_intr(sc, &sc->rec) != 0) 1142164614Sariff trigger |= 2; 1143162922Sariff /* XXX to be removed */ 1144162922Sariff#ifdef HDAC_INTR_EXTRA 1145164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1146164614Sariff HDAC_INTSTS_SIS_MASK); 1147162922Sariff#endif 1148162922Sariff } 1149162922Sariff 1150164614Sariff hdac_unlock(sc); 1151162922Sariff 1152164614Sariff if (trigger & 1) 1153164614Sariff chn_intr(sc->play.c); 1154164614Sariff if (trigger & 2) 1155164614Sariff chn_intr(sc->rec.c); 1156162922Sariff} 1157162922Sariff 1158162922Sariff/**************************************************************************** 1159163057Sariff * int hdac_reset(hdac_softc *) 1160162922Sariff * 1161162922Sariff * Reset the hdac to a quiescent and known state. 1162162922Sariff ****************************************************************************/ 1163162922Sariffstatic int 1164162922Sariffhdac_reset(struct hdac_softc *sc) 1165162922Sariff{ 1166162922Sariff uint32_t gctl; 1167162922Sariff int count, i; 1168162922Sariff 1169162922Sariff /* 1170162922Sariff * Stop all Streams DMA engine 1171162922Sariff */ 1172162922Sariff for (i = 0; i < sc->num_iss; i++) 1173162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1174162922Sariff for (i = 0; i < sc->num_oss; i++) 1175162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1176162922Sariff for (i = 0; i < sc->num_bss; i++) 1177162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1178162922Sariff 1179162922Sariff /* 1180169277Sariff * Stop Control DMA engines. 1181162922Sariff */ 1182162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1183162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1184162922Sariff 1185162922Sariff /* 1186169277Sariff * Reset DMA position buffer. 1187169277Sariff */ 1188169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1189169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1190169277Sariff 1191169277Sariff /* 1192162922Sariff * Reset the controller. The reset must remain asserted for 1193162922Sariff * a minimum of 100us. 1194162922Sariff */ 1195162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1196162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1197162922Sariff count = 10000; 1198162922Sariff do { 1199162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1200162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1201162922Sariff break; 1202162922Sariff DELAY(10); 1203162922Sariff } while (--count); 1204162922Sariff if (gctl & HDAC_GCTL_CRST) { 1205162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1206162922Sariff return (ENXIO); 1207162922Sariff } 1208162922Sariff DELAY(100); 1209162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1210162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1211162922Sariff count = 10000; 1212162922Sariff do { 1213162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1214163057Sariff if (gctl & HDAC_GCTL_CRST) 1215162922Sariff break; 1216162922Sariff DELAY(10); 1217162922Sariff } while (--count); 1218162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1219162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1220162922Sariff return (ENXIO); 1221162922Sariff } 1222162922Sariff 1223162922Sariff /* 1224162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1225162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1226162922Sariff * computer. Let's use twice as much as necessary to make sure that 1227162922Sariff * it's reset properly. 1228162922Sariff */ 1229162922Sariff DELAY(1000); 1230162922Sariff 1231162922Sariff return (0); 1232162922Sariff} 1233162922Sariff 1234162922Sariff 1235162922Sariff/**************************************************************************** 1236162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1237162922Sariff * 1238162922Sariff * Retreive the general capabilities of the hdac; 1239162922Sariff * Number of Input Streams 1240162922Sariff * Number of Output Streams 1241162922Sariff * Number of bidirectional Streams 1242162922Sariff * 64bit ready 1243162922Sariff * CORB and RIRB sizes 1244162922Sariff ****************************************************************************/ 1245162922Sariffstatic int 1246162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1247162922Sariff{ 1248162922Sariff uint16_t gcap; 1249162922Sariff uint8_t corbsize, rirbsize; 1250162922Sariff 1251162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1252162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1253162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1254162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1255162922Sariff 1256163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1257162922Sariff 1258162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1259162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1260162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1261162922Sariff sc->corb_size = 256; 1262162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1263162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1264162922Sariff sc->corb_size = 16; 1265162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1266162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1267162922Sariff sc->corb_size = 2; 1268162922Sariff else { 1269162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1270162922Sariff __func__, corbsize); 1271162922Sariff return (ENXIO); 1272162922Sariff } 1273162922Sariff 1274162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1275162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1276162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1277162922Sariff sc->rirb_size = 256; 1278162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1279162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1280162922Sariff sc->rirb_size = 16; 1281162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1282162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1283162922Sariff sc->rirb_size = 2; 1284162922Sariff else { 1285162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1286162922Sariff __func__, rirbsize); 1287162922Sariff return (ENXIO); 1288162922Sariff } 1289162922Sariff 1290162922Sariff return (0); 1291162922Sariff} 1292162922Sariff 1293162922Sariff 1294162922Sariff/**************************************************************************** 1295162922Sariff * void hdac_dma_cb 1296162922Sariff * 1297162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1298162922Sariff * established. We just record the physical address of the mapping into 1299162922Sariff * the struct hdac_dma passed in. 1300162922Sariff ****************************************************************************/ 1301162922Sariffstatic void 1302162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1303162922Sariff{ 1304162922Sariff struct hdac_dma *dma; 1305162922Sariff 1306162922Sariff if (error == 0) { 1307162922Sariff dma = (struct hdac_dma *)callback_arg; 1308162922Sariff dma->dma_paddr = segs[0].ds_addr; 1309162922Sariff } 1310162922Sariff} 1311162922Sariff 1312162922Sariff 1313162922Sariff/**************************************************************************** 1314162922Sariff * int hdac_dma_alloc 1315162922Sariff * 1316162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1317162922Sariff * It must be freed by a corresponding hdac_dma_free. 1318162922Sariff ****************************************************************************/ 1319162922Sariffstatic int 1320162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1321162922Sariff{ 1322169277Sariff bus_size_t roundsz; 1323162922Sariff int result; 1324162922Sariff int lowaddr; 1325162922Sariff 1326169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1327162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1328162922Sariff BUS_SPACE_MAXADDR_32BIT; 1329162922Sariff bzero(dma, sizeof(*dma)); 1330162922Sariff 1331162922Sariff /* 1332162922Sariff * Create a DMA tag 1333162922Sariff */ 1334162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1335162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1336162922Sariff 0, /* boundary */ 1337162922Sariff lowaddr, /* lowaddr */ 1338162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1339162922Sariff NULL, /* filtfunc */ 1340162922Sariff NULL, /* fistfuncarg */ 1341169277Sariff roundsz, /* maxsize */ 1342162922Sariff 1, /* nsegments */ 1343169277Sariff roundsz, /* maxsegsz */ 1344162922Sariff 0, /* flags */ 1345162922Sariff NULL, /* lockfunc */ 1346162922Sariff NULL, /* lockfuncarg */ 1347162922Sariff &dma->dma_tag); /* dmat */ 1348162922Sariff if (result != 0) { 1349162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1350162922Sariff __func__, result); 1351167773Sariff goto hdac_dma_alloc_fail; 1352162922Sariff } 1353162922Sariff 1354162922Sariff /* 1355162922Sariff * Allocate DMA memory 1356162922Sariff */ 1357162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1358169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1359169277Sariff ((sc->nocache != 0) ? BUS_DMA_NOCACHE : 0), &dma->dma_map); 1360162922Sariff if (result != 0) { 1361162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1362162922Sariff __func__, result); 1363167773Sariff goto hdac_dma_alloc_fail; 1364162922Sariff } 1365162922Sariff 1366169277Sariff dma->dma_size = roundsz; 1367169277Sariff 1368162922Sariff /* 1369162922Sariff * Map the memory 1370162922Sariff */ 1371162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1372169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1373162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1374167773Sariff if (result == 0) 1375167773Sariff result = ENOMEM; 1376162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1377162922Sariff __func__, result); 1378167773Sariff goto hdac_dma_alloc_fail; 1379162922Sariff } 1380162922Sariff 1381169277Sariff HDA_BOOTVERBOSE( 1382169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1383169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1384169277Sariff ); 1385169277Sariff 1386162922Sariff return (0); 1387169277Sariff 1388167773Sariffhdac_dma_alloc_fail: 1389169277Sariff hdac_dma_free(sc, dma); 1390167773Sariff 1391162922Sariff return (result); 1392162922Sariff} 1393162922Sariff 1394162922Sariff 1395162922Sariff/**************************************************************************** 1396169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1397162922Sariff * 1398162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1399162922Sariff * hdac_dma_alloc function. 1400162922Sariff ****************************************************************************/ 1401162922Sariffstatic void 1402169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1403162922Sariff{ 1404167773Sariff if (dma->dma_map != NULL) { 1405169277Sariff#if 0 1406162922Sariff /* Flush caches */ 1407162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1408162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1409169277Sariff#endif 1410162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1411167773Sariff } 1412167773Sariff if (dma->dma_vaddr != NULL) { 1413162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1414167773Sariff dma->dma_vaddr = NULL; 1415167773Sariff } 1416167773Sariff dma->dma_map = NULL; 1417167773Sariff if (dma->dma_tag != NULL) { 1418162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1419167773Sariff dma->dma_tag = NULL; 1420162922Sariff } 1421167773Sariff dma->dma_size = 0; 1422162922Sariff} 1423162922Sariff 1424162922Sariff/**************************************************************************** 1425162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1426162922Sariff * 1427162922Sariff * Allocate all the bus resources necessary to speak with the physical 1428162922Sariff * controller. 1429162922Sariff ****************************************************************************/ 1430162922Sariffstatic int 1431162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1432162922Sariff{ 1433162922Sariff struct hdac_mem *mem; 1434162922Sariff 1435162922Sariff mem = &sc->mem; 1436162922Sariff mem->mem_rid = PCIR_BAR(0); 1437162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1438162922Sariff &mem->mem_rid, RF_ACTIVE); 1439162922Sariff if (mem->mem_res == NULL) { 1440162922Sariff device_printf(sc->dev, 1441162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1442162922Sariff return (ENOMEM); 1443162922Sariff } 1444162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1445162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1446162922Sariff 1447162922Sariff return (0); 1448162922Sariff} 1449162922Sariff 1450162922Sariff/**************************************************************************** 1451162922Sariff * void hdac_mem_free(struct hdac_softc *) 1452162922Sariff * 1453162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1454162922Sariff ****************************************************************************/ 1455162922Sariffstatic void 1456162922Sariffhdac_mem_free(struct hdac_softc *sc) 1457162922Sariff{ 1458162922Sariff struct hdac_mem *mem; 1459162922Sariff 1460162922Sariff mem = &sc->mem; 1461162922Sariff if (mem->mem_res != NULL) 1462162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1463162922Sariff mem->mem_res); 1464164614Sariff mem->mem_res = NULL; 1465162922Sariff} 1466162922Sariff 1467162922Sariff/**************************************************************************** 1468162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1469162922Sariff * 1470162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1471162922Sariff ****************************************************************************/ 1472162922Sariffstatic int 1473162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1474162922Sariff{ 1475162922Sariff struct hdac_irq *irq; 1476162922Sariff int result; 1477162922Sariff 1478162922Sariff irq = &sc->irq; 1479162922Sariff irq->irq_rid = 0x0; 1480162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1481162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1482162922Sariff if (irq->irq_res == NULL) { 1483162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1484162922Sariff __func__); 1485167773Sariff goto hdac_irq_alloc_fail; 1486162922Sariff } 1487162922Sariff result = snd_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE, 1488164614Sariff hdac_intr_handler, sc, &irq->irq_handle); 1489162922Sariff if (result != 0) { 1490162922Sariff device_printf(sc->dev, 1491162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1492162922Sariff __func__, result); 1493167773Sariff goto hdac_irq_alloc_fail; 1494162922Sariff } 1495162922Sariff 1496162922Sariff return (0); 1497162922Sariff 1498167773Sariffhdac_irq_alloc_fail: 1499164614Sariff hdac_irq_free(sc); 1500164614Sariff 1501162922Sariff return (ENXIO); 1502162922Sariff} 1503162922Sariff 1504162922Sariff/**************************************************************************** 1505162922Sariff * void hdac_irq_free(struct hdac_softc *) 1506162922Sariff * 1507162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1508162922Sariff ****************************************************************************/ 1509162922Sariffstatic void 1510162922Sariffhdac_irq_free(struct hdac_softc *sc) 1511162922Sariff{ 1512162922Sariff struct hdac_irq *irq; 1513162922Sariff 1514162922Sariff irq = &sc->irq; 1515164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1516162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1517162922Sariff if (irq->irq_res != NULL) 1518162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1519162922Sariff irq->irq_res); 1520164614Sariff irq->irq_handle = NULL; 1521164614Sariff irq->irq_res = NULL; 1522162922Sariff} 1523162922Sariff 1524162922Sariff/**************************************************************************** 1525162922Sariff * void hdac_corb_init(struct hdac_softc *) 1526162922Sariff * 1527162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1528162922Sariff * The CORB engine must not be running when this function is called. 1529162922Sariff ****************************************************************************/ 1530162922Sariffstatic void 1531162922Sariffhdac_corb_init(struct hdac_softc *sc) 1532162922Sariff{ 1533162922Sariff uint8_t corbsize; 1534162922Sariff uint64_t corbpaddr; 1535162922Sariff 1536162922Sariff /* Setup the CORB size. */ 1537162922Sariff switch (sc->corb_size) { 1538162922Sariff case 256: 1539162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1540162922Sariff break; 1541162922Sariff case 16: 1542162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1543162922Sariff break; 1544162922Sariff case 2: 1545162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1546162922Sariff break; 1547162922Sariff default: 1548162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1549162922Sariff } 1550162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1551162922Sariff 1552162922Sariff /* Setup the CORB Address in the hdac */ 1553162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1554162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1555162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1556162922Sariff 1557162922Sariff /* Set the WP and RP */ 1558162922Sariff sc->corb_wp = 0; 1559162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1560162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1561162922Sariff /* 1562162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1563162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1564162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1565162922Sariff * manually reset the bit to zero before continuing. 1566162922Sariff */ 1567162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1568162922Sariff 1569162922Sariff /* Enable CORB error reporting */ 1570162922Sariff#if 0 1571162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1572162922Sariff#endif 1573162922Sariff} 1574162922Sariff 1575162922Sariff/**************************************************************************** 1576162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1577162922Sariff * 1578162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1579162922Sariff * The RIRB engine must not be running when this function is called. 1580162922Sariff ****************************************************************************/ 1581162922Sariffstatic void 1582162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1583162922Sariff{ 1584162922Sariff uint8_t rirbsize; 1585162922Sariff uint64_t rirbpaddr; 1586162922Sariff 1587162922Sariff /* Setup the RIRB size. */ 1588162922Sariff switch (sc->rirb_size) { 1589162922Sariff case 256: 1590162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1591162922Sariff break; 1592162922Sariff case 16: 1593162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1594162922Sariff break; 1595162922Sariff case 2: 1596162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1597162922Sariff break; 1598162922Sariff default: 1599162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1600162922Sariff } 1601162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1602162922Sariff 1603162922Sariff /* Setup the RIRB Address in the hdac */ 1604162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1605162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1606162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1607162922Sariff 1608162922Sariff /* Setup the WP and RP */ 1609162922Sariff sc->rirb_rp = 0; 1610162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1611162922Sariff 1612164614Sariff if (sc->polling == 0) { 1613164614Sariff /* Setup the interrupt threshold */ 1614164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1615162922Sariff 1616164614Sariff /* Enable Overrun and response received reporting */ 1617162922Sariff#if 0 1618164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1619164614Sariff HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1620162922Sariff#else 1621164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1622162922Sariff#endif 1623164614Sariff } 1624162922Sariff 1625169277Sariff#if 0 1626162922Sariff /* 1627162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1628162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1629162922Sariff * should be sufficient to do this only once as the rirb is purely 1630162922Sariff * read-only from now on. 1631162922Sariff */ 1632162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1633162922Sariff BUS_DMASYNC_PREREAD); 1634169277Sariff#endif 1635162922Sariff} 1636162922Sariff 1637162922Sariff/**************************************************************************** 1638162922Sariff * void hdac_corb_start(hdac_softc *) 1639162922Sariff * 1640162922Sariff * Startup the corb DMA engine 1641162922Sariff ****************************************************************************/ 1642162922Sariffstatic void 1643162922Sariffhdac_corb_start(struct hdac_softc *sc) 1644162922Sariff{ 1645162922Sariff uint32_t corbctl; 1646162922Sariff 1647162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1648162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1649162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1650162922Sariff} 1651162922Sariff 1652162922Sariff/**************************************************************************** 1653162922Sariff * void hdac_rirb_start(hdac_softc *) 1654162922Sariff * 1655162922Sariff * Startup the rirb DMA engine 1656162922Sariff ****************************************************************************/ 1657162922Sariffstatic void 1658162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1659162922Sariff{ 1660162922Sariff uint32_t rirbctl; 1661162922Sariff 1662162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1663162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1664162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1665162922Sariff} 1666162922Sariff 1667162922Sariff 1668162922Sariff/**************************************************************************** 1669162922Sariff * void hdac_scan_codecs(struct hdac_softc *) 1670162922Sariff * 1671162922Sariff * Scan the bus for available codecs. 1672162922Sariff ****************************************************************************/ 1673162922Sariffstatic void 1674162922Sariffhdac_scan_codecs(struct hdac_softc *sc) 1675162922Sariff{ 1676162922Sariff struct hdac_codec *codec; 1677162922Sariff int i; 1678162922Sariff uint16_t statests; 1679162922Sariff 1680162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1681162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) { 1682162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1683162922Sariff /* We have found a codec. */ 1684162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1685162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1686162922Sariff if (codec == NULL) { 1687162922Sariff device_printf(sc->dev, 1688162922Sariff "Unable to allocate memory for codec\n"); 1689162922Sariff continue; 1690162922Sariff } 1691164614Sariff codec->commands = NULL; 1692164614Sariff codec->responses_received = 0; 1693162922Sariff codec->verbs_sent = 0; 1694162922Sariff codec->sc = sc; 1695162922Sariff codec->cad = i; 1696162922Sariff sc->codecs[i] = codec; 1697162922Sariff if (hdac_probe_codec(codec) != 0) 1698162922Sariff break; 1699162922Sariff } 1700162922Sariff } 1701162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1702163057Sariff /* bus_generic_attach(sc->dev); */ 1703162922Sariff} 1704162922Sariff 1705162922Sariff/**************************************************************************** 1706162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1707162922Sariff * 1708162922Sariff * Probe a the given codec_id for available function groups. 1709162922Sariff ****************************************************************************/ 1710162922Sariffstatic int 1711162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1712162922Sariff{ 1713162922Sariff struct hdac_softc *sc = codec->sc; 1714162922Sariff struct hdac_devinfo *devinfo; 1715162922Sariff uint32_t vendorid, revisionid, subnode; 1716162922Sariff int startnode; 1717162922Sariff int endnode; 1718162922Sariff int i; 1719162922Sariff nid_t cad = codec->cad; 1720162922Sariff 1721163057Sariff HDA_BOOTVERBOSE( 1722163057Sariff device_printf(sc->dev, "HDA_DEBUG: Probing codec: %d\n", cad); 1723162922Sariff ); 1724162922Sariff vendorid = hdac_command(sc, 1725162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1726162922Sariff cad); 1727162922Sariff revisionid = hdac_command(sc, 1728162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1729162922Sariff cad); 1730162922Sariff subnode = hdac_command(sc, 1731162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1732162922Sariff cad); 1733162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1734162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1735162922Sariff 1736163057Sariff HDA_BOOTVERBOSE( 1737163057Sariff device_printf(sc->dev, "HDA_DEBUG: \tstartnode=%d endnode=%d\n", 1738163057Sariff startnode, endnode); 1739162922Sariff ); 1740162922Sariff for (i = startnode; i < endnode; i++) { 1741162922Sariff devinfo = hdac_probe_function(codec, i); 1742162922Sariff if (devinfo != NULL) { 1743162922Sariff /* XXX Ignore other FG. */ 1744162922Sariff devinfo->vendor_id = 1745162922Sariff HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1746162922Sariff devinfo->device_id = 1747162922Sariff HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1748162922Sariff devinfo->revision_id = 1749162922Sariff HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1750162922Sariff devinfo->stepping_id = 1751162922Sariff HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1752163057Sariff HDA_BOOTVERBOSE( 1753162922Sariff device_printf(sc->dev, 1754163057Sariff "HDA_DEBUG: \tFound AFG nid=%d " 1755162922Sariff "[startnode=%d endnode=%d]\n", 1756163057Sariff devinfo->nid, startnode, endnode); 1757162922Sariff ); 1758162922Sariff return (1); 1759162922Sariff } 1760162922Sariff } 1761162922Sariff 1762163057Sariff HDA_BOOTVERBOSE( 1763163057Sariff device_printf(sc->dev, "HDA_DEBUG: \tAFG not found\n"); 1764162922Sariff ); 1765162922Sariff return (0); 1766162922Sariff} 1767162922Sariff 1768162922Sariffstatic struct hdac_devinfo * 1769162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1770162922Sariff{ 1771162922Sariff struct hdac_softc *sc = codec->sc; 1772162922Sariff struct hdac_devinfo *devinfo; 1773162922Sariff uint32_t fctgrptype; 1774162922Sariff nid_t cad = codec->cad; 1775162922Sariff 1776162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1777162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1778162922Sariff 1779162922Sariff /* XXX For now, ignore other FG. */ 1780162965Sariff if (fctgrptype != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 1781162922Sariff return (NULL); 1782162922Sariff 1783162922Sariff devinfo = (struct hdac_devinfo *)malloc(sizeof(*devinfo), M_HDAC, 1784162922Sariff M_NOWAIT | M_ZERO); 1785162922Sariff if (devinfo == NULL) { 1786162922Sariff device_printf(sc->dev, "%s: Unable to allocate ivar\n", 1787162922Sariff __func__); 1788162922Sariff return (NULL); 1789162922Sariff } 1790162922Sariff 1791162922Sariff devinfo->nid = nid; 1792162965Sariff devinfo->node_type = fctgrptype; 1793162922Sariff devinfo->codec = codec; 1794162922Sariff 1795162922Sariff hdac_add_child(sc, devinfo); 1796162922Sariff 1797162922Sariff return (devinfo); 1798162922Sariff} 1799162922Sariff 1800162922Sariffstatic void 1801162922Sariffhdac_add_child(struct hdac_softc *sc, struct hdac_devinfo *devinfo) 1802162922Sariff{ 1803162922Sariff devinfo->dev = device_add_child(sc->dev, NULL, -1); 1804162922Sariff device_set_ivars(devinfo->dev, (void *)devinfo); 1805162922Sariff /* XXX - Print more information when booting verbose??? */ 1806162922Sariff} 1807162922Sariff 1808162922Sariffstatic void 1809162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 1810162922Sariff{ 1811162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1812162922Sariff uint32_t res; 1813169277Sariff int i, j, max, ents, entnum; 1814162922Sariff nid_t cad = w->devinfo->codec->cad; 1815162922Sariff nid_t nid = w->nid; 1816169277Sariff nid_t cnid, addcnid, prevcnid; 1817162922Sariff 1818169277Sariff w->nconns = 0; 1819169277Sariff 1820162922Sariff res = hdac_command(sc, 1821162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 1822162922Sariff 1823169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 1824162922Sariff 1825169277Sariff if (ents < 1) 1826162922Sariff return; 1827162922Sariff 1828162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 1829162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 1830169277Sariff prevcnid = 0; 1831162922Sariff 1832169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 1833169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 1834169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 1835169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 1836169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 1837169277Sariff 1838169277Sariff for (i = 0; i < ents; i += entnum) { 1839162922Sariff res = hdac_command(sc, 1840162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 1841162922Sariff for (j = 0; j < entnum; j++) { 1842169277Sariff cnid = CONN_CNID(res, entnum, j); 1843169277Sariff if (cnid == 0) { 1844169277Sariff if (w->nconns < ents) 1845169277Sariff device_printf(sc->dev, 1846169277Sariff "%s: nid=%d WARNING: zero cnid " 1847169277Sariff "entnum=%d j=%d index=%d " 1848169277Sariff "entries=%d found=%d res=0x%08x\n", 1849169277Sariff __func__, nid, entnum, j, i, 1850169277Sariff ents, w->nconns, res); 1851169277Sariff else 1852169277Sariff goto getconns_out; 1853169277Sariff } 1854169277Sariff if (cnid < w->devinfo->startnode || 1855169277Sariff cnid >= w->devinfo->endnode) { 1856169277Sariff HDA_BOOTVERBOSE( 1857169277Sariff device_printf(sc->dev, 1858169277Sariff "%s: GHOST: nid=%d j=%d " 1859169277Sariff "entnum=%d index=%d res=0x%08x\n", 1860169277Sariff __func__, nid, j, entnum, i, res); 1861169277Sariff ); 1862169277Sariff } 1863169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 1864169277Sariff addcnid = cnid; 1865169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 1866162922Sariff device_printf(sc->dev, 1867169277Sariff "%s: WARNING: Invalid child range " 1868169277Sariff "nid=%d index=%d j=%d entnum=%d " 1869169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 1870169277Sariff __func__, nid, i, j, entnum, prevcnid, 1871169277Sariff cnid, res); 1872169277Sariff addcnid = cnid; 1873169277Sariff } else 1874169277Sariff addcnid = prevcnid + 1; 1875169277Sariff while (addcnid <= cnid) { 1876169277Sariff if (w->nconns > max) { 1877169277Sariff device_printf(sc->dev, 1878169277Sariff "%s: nid=%d: Adding %d: " 1879169277Sariff "Max connection reached! max=%d\n", 1880169277Sariff __func__, nid, addcnid, max + 1); 1881169277Sariff goto getconns_out; 1882169277Sariff } 1883169277Sariff w->conns[w->nconns++] = addcnid++; 1884162922Sariff } 1885169277Sariff prevcnid = cnid; 1886162922Sariff } 1887162922Sariff } 1888162922Sariff 1889169277Sariffgetconns_out: 1890163057Sariff HDA_BOOTVERBOSE( 1891169277Sariff device_printf(sc->dev, 1892169277Sariff "HDA_DEBUG: %s: nid=%d entries=%d found=%d\n", 1893169277Sariff __func__, nid, ents, w->nconns); 1894162922Sariff ); 1895169277Sariff return; 1896162922Sariff} 1897162922Sariff 1898162922Sariffstatic uint32_t 1899162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 1900162922Sariff{ 1901162922Sariff struct hdac_softc *sc; 1902166965Sariff uint32_t config, orig, id; 1903162922Sariff nid_t cad, nid; 1904162922Sariff 1905162922Sariff sc = w->devinfo->codec->sc; 1906162922Sariff cad = w->devinfo->codec->cad; 1907162922Sariff nid = w->nid; 1908162922Sariff id = hdac_codec_id(w->devinfo); 1909162922Sariff 1910162922Sariff config = hdac_command(sc, 1911162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 1912162922Sariff cad); 1913166965Sariff orig = config; 1914166965Sariff 1915162965Sariff /* 1916162965Sariff * XXX REWRITE!!!! Don't argue! 1917162965Sariff */ 1918165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 1919165281Sariff switch (nid) { 1920165281Sariff case 26: 1921165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1922165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1923165281Sariff break; 1924165281Sariff case 27: 1925165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1926165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 1927165281Sariff break; 1928167610Sariff default: 1929167610Sariff break; 1930165281Sariff } 1931165281Sariff } else if (id == HDA_CODEC_ALC880 && 1932162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 1933162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 1934162922Sariff /* 1935162965Sariff * Super broken BIOS 1936162922Sariff */ 1937162922Sariff switch (nid) { 1938162922Sariff case 20: 1939162922Sariff break; 1940162922Sariff case 21: 1941162922Sariff break; 1942162922Sariff case 22: 1943162922Sariff break; 1944162922Sariff case 23: 1945162922Sariff break; 1946162922Sariff case 24: /* MIC1 */ 1947162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1948162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 1949162922Sariff break; 1950162922Sariff case 25: /* XXX MIC2 */ 1951162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1952162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 1953162922Sariff break; 1954162922Sariff case 26: /* LINE1 */ 1955162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1956162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1957162922Sariff break; 1958162922Sariff case 27: /* XXX LINE2 */ 1959162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1960162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1961162922Sariff break; 1962162922Sariff case 28: /* CD */ 1963162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1964162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 1965162922Sariff break; 1966162922Sariff case 30: 1967162922Sariff break; 1968162922Sariff case 31: 1969162922Sariff break; 1970162922Sariff default: 1971162922Sariff break; 1972162922Sariff } 1973166965Sariff } else if (id == HDA_CODEC_ALC883 && 1974166965Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) { 1975166965Sariff switch (nid) { 1976166965Sariff case 25: 1977166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 1978166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 1979166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 1980166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 1981166965Sariff break; 1982169277Sariff case 28: 1983169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 1984169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 1985169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 1986169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 1987169277Sariff break; 1988166965Sariff default: 1989166965Sariff break; 1990166965Sariff } 1991166965Sariff } else if (id == HDA_CODEC_CXVENICE && sc->pci_subvendor == 1992166965Sariff HP_V3000_SUBVENDOR) { 1993166965Sariff switch (nid) { 1994166965Sariff case 18: 1995166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 1996166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 1997166965Sariff break; 1998166965Sariff case 20: 1999166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2000166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2001166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2002166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2003166965Sariff break; 2004167454Sariff case 21: 2005167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2006167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2007167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2008167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2009167454Sariff break; 2010166965Sariff default: 2011166965Sariff break; 2012166965Sariff } 2013169277Sariff } else if (id == HDA_CODEC_CXWAIKIKI && sc->pci_subvendor == 2014169277Sariff HP_DV5000_SUBVENDOR) { 2015169277Sariff switch (nid) { 2016169277Sariff case 20: 2017169277Sariff case 21: 2018169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2019169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2020169277Sariff break; 2021169277Sariff default: 2022169277Sariff break; 2023169277Sariff } 2024169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2025169277Sariff ASUS_W6F_SUBVENDOR) { 2026169277Sariff switch (nid) { 2027169277Sariff case 11: 2028169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2029169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2030169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2031169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2032169277Sariff break; 2033169277Sariff case 15: 2034169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2035169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2036169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2037169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2038169277Sariff break; 2039169277Sariff default: 2040169277Sariff break; 2041169277Sariff } 2042169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2043169277Sariff UNIWILL_9075_SUBVENDOR) { 2044169277Sariff switch (nid) { 2045169277Sariff case 15: 2046169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2047169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2048169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2049169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2050169277Sariff break; 2051169277Sariff default: 2052169277Sariff break; 2053169277Sariff } 2054169277Sariff } else if (id == HDA_CODEC_AD1986A && sc->pci_subvendor == 2055169277Sariff ASUS_M2NPVMX_SUBVENDOR) { 2056169277Sariff switch (nid) { 2057169277Sariff case 28: /* LINE */ 2058169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2059169277Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2060169277Sariff break; 2061169277Sariff case 29: /* MIC */ 2062169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2063169277Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2064169277Sariff break; 2065169277Sariff default: 2066169277Sariff break; 2067169277Sariff } 2068162922Sariff } 2069162922Sariff 2070166965Sariff HDA_BOOTVERBOSE( 2071166965Sariff if (config != orig) 2072166965Sariff device_printf(sc->dev, 2073166965Sariff "HDA_DEBUG: Pin config nid=%u 0x%08x -> 0x%08x\n", 2074166965Sariff nid, orig, config); 2075166965Sariff ); 2076166965Sariff 2077162922Sariff return (config); 2078162922Sariff} 2079162922Sariff 2080166965Sariffstatic uint32_t 2081166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2082166965Sariff{ 2083166965Sariff struct hdac_softc *sc; 2084166965Sariff uint32_t caps, orig, id; 2085166965Sariff nid_t cad, nid; 2086166965Sariff 2087166965Sariff sc = w->devinfo->codec->sc; 2088166965Sariff cad = w->devinfo->codec->cad; 2089166965Sariff nid = w->nid; 2090166965Sariff id = hdac_codec_id(w->devinfo); 2091166965Sariff 2092166965Sariff caps = hdac_command(sc, 2093166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2094166965Sariff orig = caps; 2095166965Sariff 2096166965Sariff HDA_BOOTVERBOSE( 2097166965Sariff if (caps != orig) 2098166965Sariff device_printf(sc->dev, 2099166965Sariff "HDA_DEBUG: Pin caps nid=%u 0x%08x -> 0x%08x\n", 2100166965Sariff nid, orig, caps); 2101166965Sariff ); 2102166965Sariff 2103166965Sariff return (caps); 2104166965Sariff} 2105166965Sariff 2106162922Sariffstatic void 2107162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2108162922Sariff{ 2109162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2110162922Sariff uint32_t config, pincap; 2111162922Sariff char *devstr, *connstr; 2112162922Sariff nid_t cad = w->devinfo->codec->cad; 2113162922Sariff nid_t nid = w->nid; 2114162922Sariff 2115162922Sariff config = hdac_widget_pin_getconfig(w); 2116162922Sariff w->wclass.pin.config = config; 2117162922Sariff 2118166965Sariff pincap = hdac_widget_pin_getcaps(w); 2119162922Sariff w->wclass.pin.cap = pincap; 2120162922Sariff 2121162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2122164614Sariff HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad) & 2123164614Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 2124164614Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 2125169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 2126169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 2127162922Sariff 2128162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 2129162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 2130162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 2131162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 2132162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 2133162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 2134162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2135162922Sariff w->param.eapdbtl = hdac_command(sc, 2136162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2137162922Sariff w->param.eapdbtl &= 0x7; 2138162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2139162922Sariff } else 2140162965Sariff w->param.eapdbtl = HDAC_INVALID; 2141162922Sariff 2142162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 2143162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 2144162922Sariff devstr = "line out"; 2145162922Sariff break; 2146162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 2147162922Sariff devstr = "speaker"; 2148162922Sariff break; 2149162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 2150162922Sariff devstr = "headphones out"; 2151162922Sariff break; 2152162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 2153162922Sariff devstr = "CD"; 2154162922Sariff break; 2155162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 2156162922Sariff devstr = "SPDIF out"; 2157162922Sariff break; 2158162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 2159162922Sariff devstr = "digital (other) out"; 2160162922Sariff break; 2161162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE: 2162162922Sariff devstr = "modem, line side"; 2163162922Sariff break; 2164162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET: 2165162922Sariff devstr = "modem, handset side"; 2166162922Sariff break; 2167162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 2168162922Sariff devstr = "line in"; 2169162922Sariff break; 2170162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 2171162922Sariff devstr = "AUX"; 2172162922Sariff break; 2173162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 2174162922Sariff devstr = "Mic in"; 2175162922Sariff break; 2176162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY: 2177162922Sariff devstr = "telephony"; 2178162922Sariff break; 2179162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 2180162922Sariff devstr = "SPDIF in"; 2181162922Sariff break; 2182162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 2183162922Sariff devstr = "digital (other) in"; 2184162922Sariff break; 2185162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER: 2186162922Sariff devstr = "other"; 2187162922Sariff break; 2188162922Sariff default: 2189162922Sariff devstr = "unknown"; 2190162922Sariff break; 2191162922Sariff } 2192162922Sariff 2193162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) { 2194162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK: 2195162922Sariff connstr = "jack"; 2196162922Sariff break; 2197162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE: 2198162922Sariff connstr = "none"; 2199162922Sariff break; 2200162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED: 2201162922Sariff connstr = "fixed"; 2202162922Sariff break; 2203162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH: 2204162922Sariff connstr = "jack / fixed"; 2205162922Sariff break; 2206162922Sariff default: 2207162922Sariff connstr = "unknown"; 2208162922Sariff break; 2209162922Sariff } 2210162922Sariff 2211162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2212162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2213162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2214162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 2215162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2216162922Sariff} 2217162922Sariff 2218162922Sariffstatic void 2219162922Sariffhdac_widget_parse(struct hdac_widget *w) 2220162922Sariff{ 2221162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2222162922Sariff uint32_t wcap, cap; 2223162922Sariff char *typestr; 2224162922Sariff nid_t cad = w->devinfo->codec->cad; 2225162922Sariff nid_t nid = w->nid; 2226162922Sariff 2227162922Sariff wcap = hdac_command(sc, 2228162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2229162922Sariff cad); 2230162922Sariff w->param.widget_cap = wcap; 2231162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2232162922Sariff 2233162922Sariff switch (w->type) { 2234162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2235162922Sariff typestr = "audio output"; 2236162922Sariff break; 2237162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2238162922Sariff typestr = "audio input"; 2239162922Sariff break; 2240162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2241162922Sariff typestr = "audio mixer"; 2242162922Sariff break; 2243162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2244162922Sariff typestr = "audio selector"; 2245162922Sariff break; 2246162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2247162922Sariff typestr = "pin"; 2248162922Sariff break; 2249162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2250162922Sariff typestr = "power widget"; 2251162922Sariff break; 2252162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2253162922Sariff typestr = "volume widget"; 2254162922Sariff break; 2255162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2256162922Sariff typestr = "beep widget"; 2257162922Sariff break; 2258162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2259162922Sariff typestr = "vendor widget"; 2260162922Sariff break; 2261162922Sariff default: 2262162922Sariff typestr = "unknown type"; 2263162922Sariff break; 2264162922Sariff } 2265162922Sariff 2266162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2267162922Sariff 2268162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(wcap)) { 2269162922Sariff hdac_command(sc, 2270162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), 2271162922Sariff cad); 2272162922Sariff DELAY(1000); 2273162922Sariff } 2274162922Sariff 2275162922Sariff hdac_widget_connection_parse(w); 2276162922Sariff 2277162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2278162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2279162922Sariff w->param.outamp_cap = 2280162922Sariff hdac_command(sc, 2281162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2282162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2283162922Sariff else 2284162922Sariff w->param.outamp_cap = 2285162922Sariff w->devinfo->function.audio.outamp_cap; 2286162922Sariff } else 2287162922Sariff w->param.outamp_cap = 0; 2288162922Sariff 2289162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2290162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2291162922Sariff w->param.inamp_cap = 2292162922Sariff hdac_command(sc, 2293162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2294162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2295162922Sariff else 2296162922Sariff w->param.inamp_cap = 2297162922Sariff w->devinfo->function.audio.inamp_cap; 2298162922Sariff } else 2299162922Sariff w->param.inamp_cap = 0; 2300162922Sariff 2301162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2302162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2303162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2304162922Sariff cap = hdac_command(sc, 2305162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2306162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2307162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2308162922Sariff w->devinfo->function.audio.supp_stream_formats; 2309162922Sariff cap = hdac_command(sc, 2310162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2311162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2312162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2313162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2314162922Sariff } else { 2315162922Sariff w->param.supp_stream_formats = 2316162922Sariff w->devinfo->function.audio.supp_stream_formats; 2317162922Sariff w->param.supp_pcm_size_rate = 2318162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2319162922Sariff } 2320162922Sariff } else { 2321162922Sariff w->param.supp_stream_formats = 0; 2322162922Sariff w->param.supp_pcm_size_rate = 0; 2323162922Sariff } 2324162922Sariff 2325162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2326162922Sariff hdac_widget_pin_parse(w); 2327162922Sariff} 2328162922Sariff 2329162922Sariffstatic struct hdac_widget * 2330162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2331162922Sariff{ 2332162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2333162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2334162922Sariff return (NULL); 2335162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2336162922Sariff} 2337162922Sariff 2338164614Sariffstatic __inline int 2339164614Sariffhda_poll_channel(struct hdac_chan *ch) 2340164614Sariff{ 2341164614Sariff uint32_t sz, delta; 2342164614Sariff volatile uint32_t ptr; 2343164614Sariff 2344164614Sariff if (ch->active == 0) 2345164614Sariff return (0); 2346164614Sariff 2347164614Sariff sz = ch->blksz * ch->blkcnt; 2348169277Sariff if (ch->dmapos != NULL) 2349169277Sariff ptr = *(ch->dmapos); 2350169277Sariff else 2351169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2352169277Sariff ch->off + HDAC_SDLPIB); 2353164614Sariff ch->ptr = ptr; 2354164614Sariff ptr %= sz; 2355164614Sariff ptr &= ~(ch->blksz - 1); 2356164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2357164614Sariff 2358164614Sariff if (delta < ch->blksz) 2359164614Sariff return (0); 2360164614Sariff 2361164614Sariff ch->prevptr = ptr; 2362164614Sariff 2363164614Sariff return (1); 2364164614Sariff} 2365164614Sariff 2366164614Sariff#define hda_chan_active(sc) ((sc)->play.active + (sc)->rec.active) 2367164614Sariff 2368162922Sariffstatic void 2369164614Sariffhda_poll_callback(void *arg) 2370164614Sariff{ 2371164614Sariff struct hdac_softc *sc = arg; 2372164614Sariff uint32_t trigger = 0; 2373164614Sariff 2374164614Sariff if (sc == NULL) 2375164614Sariff return; 2376164614Sariff 2377164614Sariff hdac_lock(sc); 2378164614Sariff if (sc->polling == 0 || hda_chan_active(sc) == 0) { 2379164614Sariff hdac_unlock(sc); 2380164614Sariff return; 2381164614Sariff } 2382164614Sariff 2383164614Sariff trigger |= (hda_poll_channel(&sc->play) != 0) ? 1 : 0; 2384164614Sariff trigger |= (hda_poll_channel(&sc->rec) != 0) ? 2 : 0; 2385164614Sariff 2386164614Sariff /* XXX */ 2387164614Sariff callout_reset(&sc->poll_hda, 1/*sc->poll_ticks*/, 2388164614Sariff hda_poll_callback, sc); 2389164614Sariff 2390164614Sariff hdac_unlock(sc); 2391164614Sariff 2392164614Sariff if (trigger & 1) 2393164614Sariff chn_intr(sc->play.c); 2394164614Sariff if (trigger & 2) 2395164614Sariff chn_intr(sc->rec.c); 2396164614Sariff} 2397164614Sariff 2398164614Sariffstatic int 2399164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2400164614Sariff{ 2401164614Sariff struct hdac_rirb *rirb_base, *rirb; 2402164614Sariff struct hdac_codec *codec; 2403164614Sariff struct hdac_command_list *commands; 2404164614Sariff nid_t cad; 2405164614Sariff uint32_t resp; 2406164614Sariff uint8_t rirbwp; 2407164614Sariff int ret = 0; 2408164614Sariff 2409164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2410164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2411169277Sariff#if 0 2412164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2413164614Sariff BUS_DMASYNC_POSTREAD); 2414169277Sariff#endif 2415164614Sariff 2416164614Sariff while (sc->rirb_rp != rirbwp) { 2417164614Sariff sc->rirb_rp++; 2418164614Sariff sc->rirb_rp %= sc->rirb_size; 2419164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2420164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2421164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2422164614Sariff sc->codecs[cad] == NULL) 2423164614Sariff continue; 2424164614Sariff resp = rirb->response; 2425164614Sariff codec = sc->codecs[cad]; 2426164614Sariff commands = codec->commands; 2427164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2428164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2429164614Sariff ((resp >> 26) & 0xffff); 2430164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2431164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2432164614Sariff codec->responses_received < commands->num_commands) 2433164614Sariff commands->responses[codec->responses_received++] = 2434164614Sariff resp; 2435164614Sariff ret++; 2436164614Sariff } 2437164614Sariff 2438164614Sariff return (ret); 2439164614Sariff} 2440164614Sariff 2441164614Sariffstatic int 2442164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2443164614Sariff{ 2444164614Sariff nid_t cad; 2445164614Sariff uint32_t tag; 2446164614Sariff int ret = 0; 2447164614Sariff 2448164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2449164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2450164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2451164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2452164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2453164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2454164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2455164614Sariff ret++; 2456164614Sariff } 2457164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2458164614Sariff } 2459164614Sariff 2460164614Sariff return (ret); 2461164614Sariff} 2462164614Sariff 2463164614Sariffstatic void 2464164614Sariffhdac_poll_callback(void *arg) 2465164614Sariff{ 2466164614Sariff struct hdac_softc *sc = arg; 2467164614Sariff if (sc == NULL) 2468164614Sariff return; 2469166796Sariff 2470164614Sariff hdac_lock(sc); 2471169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2472164614Sariff hdac_unlock(sc); 2473164614Sariff return; 2474164614Sariff } 2475164614Sariff hdac_rirb_flush(sc); 2476164614Sariff hdac_unsolq_flush(sc); 2477169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2478164614Sariff hdac_unlock(sc); 2479164614Sariff} 2480164614Sariff 2481164614Sariffstatic void 2482162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2483162922Sariff{ 2484162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2485162922Sariff uint32_t ctl; 2486162922Sariff 2487162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2488162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2489162922Sariff HDAC_SDCTL_RUN); 2490162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2491162922Sariff 2492164614Sariff ch->active = 0; 2493164614Sariff 2494164614Sariff if (sc->polling != 0) { 2495164614Sariff int pollticks; 2496164614Sariff 2497164614Sariff if (hda_chan_active(sc) == 0) { 2498164614Sariff callout_stop(&sc->poll_hda); 2499164614Sariff sc->poll_ticks = 1; 2500164614Sariff } else { 2501164614Sariff if (sc->play.active != 0) 2502164614Sariff ch = &sc->play; 2503164614Sariff else 2504164614Sariff ch = &sc->rec; 2505164614Sariff pollticks = ((uint64_t)hz * ch->blksz) / 2506164614Sariff ((uint64_t)sndbuf_getbps(ch->b) * 2507164614Sariff sndbuf_getspd(ch->b)); 2508164614Sariff pollticks >>= 2; 2509164614Sariff if (pollticks > hz) 2510164614Sariff pollticks = hz; 2511164614Sariff if (pollticks < 1) { 2512164614Sariff HDA_BOOTVERBOSE( 2513164614Sariff device_printf(sc->dev, 2514164614Sariff "%s: pollticks=%d < 1 !\n", 2515164614Sariff __func__, pollticks); 2516164614Sariff ); 2517164614Sariff pollticks = 1; 2518164614Sariff } 2519164614Sariff if (pollticks > sc->poll_ticks) { 2520164614Sariff HDA_BOOTVERBOSE( 2521164614Sariff device_printf(sc->dev, 2522164614Sariff "%s: pollticks %d -> %d\n", 2523164614Sariff __func__, sc->poll_ticks, 2524164614Sariff pollticks); 2525164614Sariff ); 2526164614Sariff sc->poll_ticks = pollticks; 2527164614Sariff callout_reset(&sc->poll_hda, 1, 2528164614Sariff hda_poll_callback, sc); 2529164614Sariff } 2530164614Sariff } 2531164614Sariff } else { 2532164614Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2533164614Sariff ctl &= ~(1 << (ch->off >> 5)); 2534164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2535164614Sariff } 2536162922Sariff} 2537162922Sariff 2538162922Sariffstatic void 2539162922Sariffhdac_stream_start(struct hdac_chan *ch) 2540162922Sariff{ 2541162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2542162922Sariff uint32_t ctl; 2543162922Sariff 2544164614Sariff if (sc->polling != 0) { 2545164614Sariff int pollticks; 2546162922Sariff 2547164614Sariff pollticks = ((uint64_t)hz * ch->blksz) / 2548164614Sariff ((uint64_t)sndbuf_getbps(ch->b) * sndbuf_getspd(ch->b)); 2549164614Sariff pollticks >>= 2; 2550164614Sariff if (pollticks > hz) 2551164614Sariff pollticks = hz; 2552164614Sariff if (pollticks < 1) { 2553164614Sariff HDA_BOOTVERBOSE( 2554164614Sariff device_printf(sc->dev, 2555164614Sariff "%s: pollticks=%d < 1 !\n", 2556164614Sariff __func__, pollticks); 2557164614Sariff ); 2558164614Sariff pollticks = 1; 2559164614Sariff } 2560164614Sariff if (hda_chan_active(sc) == 0 || pollticks < sc->poll_ticks) { 2561164614Sariff HDA_BOOTVERBOSE( 2562164614Sariff if (hda_chan_active(sc) == 0) { 2563164614Sariff device_printf(sc->dev, 2564164614Sariff "%s: pollticks=%d\n", 2565164614Sariff __func__, pollticks); 2566164614Sariff } else { 2567164614Sariff device_printf(sc->dev, 2568164614Sariff "%s: pollticks %d -> %d\n", 2569164614Sariff __func__, sc->poll_ticks, 2570164614Sariff pollticks); 2571164614Sariff } 2572164614Sariff ); 2573164614Sariff sc->poll_ticks = pollticks; 2574164614Sariff callout_reset(&sc->poll_hda, 1, hda_poll_callback, 2575164614Sariff sc); 2576164614Sariff } 2577164614Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2578164614Sariff ctl |= HDAC_SDCTL_RUN; 2579164614Sariff } else { 2580164614Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2581164614Sariff ctl |= 1 << (ch->off >> 5); 2582164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2583164614Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2584164614Sariff ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2585164614Sariff HDAC_SDCTL_RUN; 2586164614Sariff } 2587162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2588164614Sariff 2589164614Sariff ch->active = 1; 2590162922Sariff} 2591162922Sariff 2592162922Sariffstatic void 2593162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2594162922Sariff{ 2595162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2596162922Sariff int timeout = 1000; 2597162922Sariff int to = timeout; 2598162922Sariff uint32_t ctl; 2599162922Sariff 2600162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2601162922Sariff ctl |= HDAC_SDCTL_SRST; 2602162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2603162922Sariff do { 2604162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2605162922Sariff if (ctl & HDAC_SDCTL_SRST) 2606162922Sariff break; 2607162922Sariff DELAY(10); 2608162922Sariff } while (--to); 2609162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2610162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2611162922Sariff } 2612162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2613162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2614162922Sariff to = timeout; 2615162922Sariff do { 2616162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2617162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2618162922Sariff break; 2619162922Sariff DELAY(10); 2620162922Sariff } while (--to); 2621163057Sariff if (ctl & HDAC_SDCTL_SRST) 2622162922Sariff device_printf(sc->dev, "can't reset!\n"); 2623162922Sariff} 2624162922Sariff 2625162922Sariffstatic void 2626162922Sariffhdac_stream_setid(struct hdac_chan *ch) 2627162922Sariff{ 2628162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2629162922Sariff uint32_t ctl; 2630162922Sariff 2631162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 2632162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 2633162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 2634162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 2635162922Sariff} 2636162922Sariff 2637162922Sariffstatic void 2638162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 2639162922Sariff{ 2640162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2641164614Sariff struct hdac_bdle *bdle; 2642162922Sariff uint64_t addr; 2643164614Sariff uint32_t blksz, blkcnt; 2644162922Sariff int i; 2645162922Sariff 2646162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 2647164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 2648162922Sariff 2649164614Sariff if (sc->polling != 0) { 2650164614Sariff blksz = ch->blksz * ch->blkcnt; 2651164614Sariff blkcnt = 1; 2652164614Sariff } else { 2653164614Sariff blksz = ch->blksz; 2654164614Sariff blkcnt = ch->blkcnt; 2655164614Sariff } 2656164614Sariff 2657164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 2658162922Sariff bdle->addrl = (uint32_t)addr; 2659162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 2660164614Sariff bdle->len = blksz; 2661164614Sariff bdle->ioc = 1 ^ sc->polling; 2662164614Sariff addr += blksz; 2663162922Sariff } 2664162922Sariff 2665164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 2666164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 2667162922Sariff addr = ch->bdl_dma.dma_paddr; 2668162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 2669162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 2670169277Sariff if (ch->dmapos != NULL && 2671169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 2672169277Sariff addr = sc->pos_dma.dma_paddr; 2673169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 2674169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 2675169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 2676169277Sariff } 2677162922Sariff} 2678162922Sariff 2679162922Sariffstatic int 2680162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 2681162922Sariff{ 2682162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2683162922Sariff int rc; 2684162922Sariff 2685162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 2686162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 2687162922Sariff if (rc) { 2688162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 2689162922Sariff return (rc); 2690162922Sariff } 2691162922Sariff 2692162922Sariff return (0); 2693162922Sariff} 2694162922Sariff 2695162922Sariffstatic void 2696162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 2697162922Sariff int index, int lmute, int rmute, 2698162922Sariff int left, int right, int dir) 2699162922Sariff{ 2700162922Sariff uint16_t v = 0; 2701162922Sariff 2702162922Sariff if (sc == NULL) 2703162922Sariff return; 2704162922Sariff 2705162922Sariff if (left != right || lmute != rmute) { 2706162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 2707162922Sariff (lmute << 7) | left; 2708162922Sariff hdac_command(sc, 2709164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2710162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 2711162922Sariff (rmute << 7) | right; 2712162922Sariff } else 2713162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 2714162922Sariff (lmute << 7) | left; 2715162922Sariff 2716162922Sariff hdac_command(sc, 2717162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2718162922Sariff} 2719162922Sariff 2720162922Sariffstatic void 2721162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 2722162922Sariff int left, int right) 2723162922Sariff{ 2724162922Sariff struct hdac_softc *sc; 2725162922Sariff nid_t nid, cad; 2726162922Sariff int lmute, rmute; 2727162922Sariff 2728162922Sariff if (ctl == NULL || ctl->widget == NULL || 2729162922Sariff ctl->widget->devinfo == NULL || 2730162922Sariff ctl->widget->devinfo->codec == NULL || 2731162922Sariff ctl->widget->devinfo->codec->sc == NULL) 2732162922Sariff return; 2733162922Sariff 2734162922Sariff sc = ctl->widget->devinfo->codec->sc; 2735162922Sariff cad = ctl->widget->devinfo->codec->cad; 2736162922Sariff nid = ctl->widget->nid; 2737162922Sariff 2738162922Sariff if (mute == HDA_AMP_MUTE_DEFAULT) { 2739162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 2740162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 2741162922Sariff } else { 2742162922Sariff lmute = HDA_AMP_LEFT_MUTED(mute); 2743162922Sariff rmute = HDA_AMP_RIGHT_MUTED(mute); 2744162922Sariff } 2745162922Sariff 2746162922Sariff if (ctl->dir & HDA_CTL_OUT) 2747162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2748162922Sariff lmute, rmute, left, right, 0); 2749162922Sariff if (ctl->dir & HDA_CTL_IN) 2750162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2751162922Sariff lmute, rmute, left, right, 1); 2752162922Sariff ctl->left = left; 2753162922Sariff ctl->right = right; 2754162922Sariff} 2755162922Sariff 2756162922Sariffstatic void 2757162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 2758162922Sariff{ 2759162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 2760162922Sariff return; 2761162922Sariff hdac_command(w->devinfo->codec->sc, 2762162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 2763162922Sariff w->nid, index), w->devinfo->codec->cad); 2764162922Sariff w->selconn = index; 2765162922Sariff} 2766162922Sariff 2767162922Sariff 2768162922Sariff/**************************************************************************** 2769162922Sariff * uint32_t hdac_command_sendone_internal 2770162922Sariff * 2771162922Sariff * Wrapper function that sends only one command to a given codec 2772162922Sariff ****************************************************************************/ 2773162922Sariffstatic uint32_t 2774162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 2775162922Sariff{ 2776162922Sariff struct hdac_command_list cl; 2777162965Sariff uint32_t response = HDAC_INVALID; 2778162922Sariff 2779163057Sariff if (!hdac_lockowned(sc)) 2780162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 2781162922Sariff cl.num_commands = 1; 2782162922Sariff cl.verbs = &verb; 2783162922Sariff cl.responses = &response; 2784162922Sariff 2785162922Sariff hdac_command_send_internal(sc, &cl, cad); 2786162922Sariff 2787162922Sariff return (response); 2788162922Sariff} 2789162922Sariff 2790162922Sariff/**************************************************************************** 2791162922Sariff * hdac_command_send_internal 2792162922Sariff * 2793162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 2794162922Sariff * we can and msleep on the codec. When the interrupt get the responses 2795162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 2796162922Sariff * if any. 2797162922Sariff ****************************************************************************/ 2798162922Sariffstatic void 2799162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 2800162922Sariff struct hdac_command_list *commands, nid_t cad) 2801162922Sariff{ 2802162922Sariff struct hdac_codec *codec; 2803162922Sariff int corbrp; 2804162922Sariff uint32_t *corb; 2805162922Sariff int timeout; 2806162922Sariff int retry = 10; 2807164614Sariff struct hdac_rirb *rirb_base; 2808162922Sariff 2809164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 2810164614Sariff commands->num_commands < 1) 2811162922Sariff return; 2812162922Sariff 2813162922Sariff codec = sc->codecs[cad]; 2814162922Sariff codec->commands = commands; 2815162922Sariff codec->responses_received = 0; 2816162922Sariff codec->verbs_sent = 0; 2817162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 2818162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2819162922Sariff 2820162922Sariff do { 2821162922Sariff if (codec->verbs_sent != commands->num_commands) { 2822162922Sariff /* Queue as many verbs as possible */ 2823162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 2824169277Sariff#if 0 2825162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2826162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 2827169277Sariff#endif 2828162922Sariff while (codec->verbs_sent != commands->num_commands && 2829162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 2830162922Sariff sc->corb_wp++; 2831162922Sariff sc->corb_wp %= sc->corb_size; 2832162922Sariff corb[sc->corb_wp] = 2833162922Sariff commands->verbs[codec->verbs_sent++]; 2834162922Sariff } 2835162922Sariff 2836162922Sariff /* Send the verbs to the codecs */ 2837169277Sariff#if 0 2838162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2839162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 2840169277Sariff#endif 2841162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 2842162922Sariff } 2843162922Sariff 2844162922Sariff timeout = 1000; 2845164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 2846162922Sariff DELAY(10); 2847162922Sariff } while ((codec->verbs_sent != commands->num_commands || 2848164614Sariff codec->responses_received != commands->num_commands) && --retry); 2849162922Sariff 2850162922Sariff if (retry == 0) 2851162922Sariff device_printf(sc->dev, 2852164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 2853164614Sariff __func__, commands->num_commands, codec->verbs_sent, 2854164614Sariff codec->responses_received); 2855162922Sariff 2856164614Sariff codec->commands = NULL; 2857164614Sariff codec->responses_received = 0; 2858162922Sariff codec->verbs_sent = 0; 2859162922Sariff 2860164614Sariff hdac_unsolq_flush(sc); 2861162922Sariff} 2862162922Sariff 2863162922Sariff 2864162922Sariff/**************************************************************************** 2865162922Sariff * Device Methods 2866162922Sariff ****************************************************************************/ 2867162922Sariff 2868162922Sariff/**************************************************************************** 2869162922Sariff * int hdac_probe(device_t) 2870162922Sariff * 2871162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 2872162922Sariff * match using the subclass of the device. 2873162922Sariff ****************************************************************************/ 2874162922Sariffstatic int 2875162922Sariffhdac_probe(device_t dev) 2876162922Sariff{ 2877162922Sariff int i, result; 2878163257Sariff uint32_t model; 2879163257Sariff uint16_t class, subclass; 2880162922Sariff char desc[64]; 2881162922Sariff 2882162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 2883162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 2884162922Sariff class = pci_get_class(dev); 2885162922Sariff subclass = pci_get_subclass(dev); 2886162922Sariff 2887162922Sariff bzero(desc, sizeof(desc)); 2888162922Sariff result = ENXIO; 2889162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 2890162922Sariff if (hdac_devices[i].model == model) { 2891162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 2892162922Sariff result = BUS_PROBE_DEFAULT; 2893162922Sariff break; 2894162922Sariff } 2895163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 2896162922Sariff class == PCIC_MULTIMEDIA && 2897162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 2898162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 2899162922Sariff result = BUS_PROBE_GENERIC; 2900162922Sariff break; 2901162922Sariff } 2902162922Sariff } 2903162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 2904162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 2905162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 2906162922Sariff result = BUS_PROBE_GENERIC; 2907162922Sariff } 2908162922Sariff if (result != ENXIO) { 2909162922Sariff strlcat(desc, " High Definition Audio Controller", 2910162922Sariff sizeof(desc)); 2911162922Sariff device_set_desc_copy(dev, desc); 2912162922Sariff } 2913162922Sariff 2914162922Sariff return (result); 2915162922Sariff} 2916162922Sariff 2917162922Sariffstatic void * 2918162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 2919162922Sariff struct pcm_channel *c, int dir) 2920162922Sariff{ 2921162922Sariff struct hdac_devinfo *devinfo = data; 2922162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2923162922Sariff struct hdac_chan *ch; 2924162922Sariff 2925162922Sariff hdac_lock(sc); 2926162922Sariff if (dir == PCMDIR_PLAY) { 2927162922Sariff ch = &sc->play; 2928162922Sariff ch->off = (sc->num_iss + devinfo->function.audio.playcnt) << 5; 2929162922Sariff devinfo->function.audio.playcnt++; 2930162922Sariff } else { 2931162922Sariff ch = &sc->rec; 2932162922Sariff ch->off = devinfo->function.audio.reccnt << 5; 2933162922Sariff devinfo->function.audio.reccnt++; 2934162922Sariff } 2935162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 2936162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 2937162922Sariff ch->pcmrates[0] = 48000; 2938162922Sariff ch->pcmrates[1] = 0; 2939162922Sariff } 2940169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 2941169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 2942169277Sariff (sc->streamcnt * 8)); 2943169277Sariff else 2944169277Sariff ch->dmapos = NULL; 2945169277Sariff ch->sid = ++sc->streamcnt; 2946169277Sariff ch->dir = dir; 2947162922Sariff ch->b = b; 2948162922Sariff ch->c = c; 2949162922Sariff ch->devinfo = devinfo; 2950162922Sariff ch->blksz = sc->chan_size / sc->chan_blkcnt; 2951162922Sariff ch->blkcnt = sc->chan_blkcnt; 2952162922Sariff hdac_unlock(sc); 2953162922Sariff 2954162922Sariff if (hdac_bdl_alloc(ch) != 0) { 2955162922Sariff ch->blkcnt = 0; 2956162922Sariff return (NULL); 2957162922Sariff } 2958162922Sariff 2959169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 2960169277Sariff (sc->nocache != 0) ? BUS_DMA_NOCACHE : 0, sc->chan_size) != 0) 2961162922Sariff return (NULL); 2962162922Sariff 2963162922Sariff return (ch); 2964162922Sariff} 2965162922Sariff 2966162922Sariffstatic int 2967162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 2968162922Sariff{ 2969162922Sariff struct hdac_chan *ch = data; 2970162922Sariff int i; 2971162922Sariff 2972162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 2973162922Sariff if (format == ch->caps.fmtlist[i]) { 2974162922Sariff ch->fmt = format; 2975162922Sariff return (0); 2976162922Sariff } 2977162922Sariff } 2978162922Sariff 2979162922Sariff return (EINVAL); 2980162922Sariff} 2981162922Sariff 2982162922Sariffstatic int 2983162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 2984162922Sariff{ 2985162922Sariff struct hdac_chan *ch = data; 2986164614Sariff uint32_t spd = 0, threshold; 2987162922Sariff int i; 2988162922Sariff 2989162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 2990162922Sariff spd = ch->pcmrates[i]; 2991164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 2992164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 2993164614Sariff if (speed < threshold) 2994162922Sariff break; 2995162922Sariff } 2996162922Sariff 2997164614Sariff if (spd == 0) /* impossible */ 2998162922Sariff ch->spd = 48000; 2999162922Sariff else 3000162922Sariff ch->spd = spd; 3001162922Sariff 3002162922Sariff return (ch->spd); 3003162922Sariff} 3004162922Sariff 3005162922Sariffstatic void 3006162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3007162922Sariff{ 3008162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3009162922Sariff int i; 3010162922Sariff nid_t cad = ch->devinfo->codec->cad; 3011162922Sariff uint16_t fmt; 3012162922Sariff 3013162922Sariff fmt = 0; 3014162922Sariff if (ch->fmt & AFMT_S16_LE) 3015162922Sariff fmt |= ch->bit16 << 4; 3016162922Sariff else if (ch->fmt & AFMT_S32_LE) 3017162922Sariff fmt |= ch->bit32 << 4; 3018162922Sariff else 3019162922Sariff fmt |= 1 << 4; 3020162922Sariff 3021162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3022162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3023162922Sariff fmt |= hda_rate_tab[i].base; 3024162922Sariff fmt |= hda_rate_tab[i].mul; 3025162922Sariff fmt |= hda_rate_tab[i].div; 3026162922Sariff break; 3027162922Sariff } 3028162922Sariff } 3029162922Sariff 3030162922Sariff if (ch->fmt & AFMT_STEREO) 3031162922Sariff fmt |= 1; 3032162922Sariff 3033162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3034162922Sariff 3035162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3036163057Sariff HDA_BOOTVERBOSE( 3037162922Sariff device_printf(sc->dev, 3038163057Sariff "HDA_DEBUG: PCMDIR_%s: Stream setup nid=%d " 3039163057Sariff "fmt=0x%08x\n", 3040162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3041162922Sariff ch->io[i], fmt); 3042162922Sariff ); 3043162922Sariff hdac_command(sc, 3044162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3045162922Sariff hdac_command(sc, 3046162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3047162922Sariff ch->sid << 4), cad); 3048162922Sariff } 3049162922Sariff} 3050162922Sariff 3051162922Sariffstatic int 3052167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3053167648Sariff uint32_t blksz, uint32_t blkcnt) 3054162922Sariff{ 3055162922Sariff struct hdac_chan *ch = data; 3056164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3057162922Sariff 3058167648Sariff blksz &= HDA_BLK_ALIGN; 3059162922Sariff 3060167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3061167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3062167648Sariff if (blksz < HDA_BLK_MIN) 3063167648Sariff blksz = HDA_BLK_MIN; 3064167648Sariff if (blkcnt > HDA_BDL_MAX) 3065167648Sariff blkcnt = HDA_BDL_MAX; 3066167648Sariff if (blkcnt < HDA_BDL_MIN) 3067167648Sariff blkcnt = HDA_BDL_MIN; 3068164614Sariff 3069167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3070167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3071167648Sariff blkcnt >>= 1; 3072167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3073167648Sariff blksz >>= 1; 3074167648Sariff else 3075167648Sariff break; 3076167648Sariff } 3077167648Sariff 3078164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3079167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3080167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3081164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3082167648Sariff __func__, blksz, blkcnt); 3083164614Sariff 3084164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3085167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3086164614Sariff 3087167648Sariff return (1); 3088167648Sariff} 3089167648Sariff 3090167648Sariffstatic int 3091167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3092167648Sariff{ 3093167648Sariff struct hdac_chan *ch = data; 3094167648Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3095167648Sariff 3096167648Sariff hdac_channel_setfragments(obj, data, blksz, sc->chan_blkcnt); 3097167648Sariff 3098162922Sariff return (ch->blksz); 3099162922Sariff} 3100162922Sariff 3101162922Sariffstatic void 3102162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3103162922Sariff{ 3104162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3105162922Sariff nid_t cad = devinfo->codec->cad; 3106162922Sariff int i; 3107162922Sariff 3108162922Sariff hdac_stream_stop(ch); 3109162922Sariff 3110162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3111162922Sariff hdac_command(sc, 3112162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3113162922Sariff 0), cad); 3114162922Sariff } 3115162922Sariff} 3116162922Sariff 3117162922Sariffstatic void 3118162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3119162922Sariff{ 3120162922Sariff ch->ptr = 0; 3121162922Sariff ch->prevptr = 0; 3122162922Sariff hdac_stream_stop(ch); 3123162922Sariff hdac_stream_reset(ch); 3124162922Sariff hdac_bdl_setup(ch); 3125162922Sariff hdac_stream_setid(ch); 3126162922Sariff hdac_stream_setup(ch); 3127162922Sariff hdac_stream_start(ch); 3128162922Sariff} 3129162922Sariff 3130162922Sariffstatic int 3131162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3132162922Sariff{ 3133162922Sariff struct hdac_chan *ch = data; 3134162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3135162922Sariff 3136162922Sariff hdac_lock(sc); 3137162922Sariff switch (go) { 3138162922Sariff case PCMTRIG_START: 3139162922Sariff hdac_channel_start(sc, ch); 3140162922Sariff break; 3141162922Sariff case PCMTRIG_STOP: 3142162922Sariff case PCMTRIG_ABORT: 3143162922Sariff hdac_channel_stop(sc, ch); 3144162922Sariff break; 3145167610Sariff default: 3146167610Sariff break; 3147162922Sariff } 3148162922Sariff hdac_unlock(sc); 3149162922Sariff 3150162922Sariff return (0); 3151162922Sariff} 3152162922Sariff 3153162922Sariffstatic int 3154162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3155162922Sariff{ 3156162922Sariff struct hdac_chan *ch = data; 3157162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3158162922Sariff uint32_t ptr; 3159162922Sariff 3160162922Sariff hdac_lock(sc); 3161164614Sariff if (sc->polling != 0) 3162164614Sariff ptr = ch->ptr; 3163169277Sariff else if (ch->dmapos != NULL) 3164169277Sariff ptr = *(ch->dmapos); 3165164614Sariff else 3166164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3167162922Sariff hdac_unlock(sc); 3168162922Sariff 3169164614Sariff /* 3170164614Sariff * Round to available space and force 128 bytes aligment. 3171164614Sariff */ 3172164614Sariff ptr %= ch->blksz * ch->blkcnt; 3173167648Sariff ptr &= HDA_BLK_ALIGN; 3174162922Sariff 3175162922Sariff return (ptr); 3176162922Sariff} 3177162922Sariff 3178162922Sariffstatic struct pcmchan_caps * 3179162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3180162922Sariff{ 3181162922Sariff return (&((struct hdac_chan *)data)->caps); 3182162922Sariff} 3183162922Sariff 3184162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3185162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3186162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3187162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3188162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3189167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3190162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3191162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3192162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3193162922Sariff { 0, 0 } 3194162922Sariff}; 3195162922SariffCHANNEL_DECLARE(hdac_channel); 3196162922Sariff 3197169277Sariffstatic void 3198169277Sariffhdac_jack_poll_callback(void *arg) 3199169277Sariff{ 3200169277Sariff struct hdac_devinfo *devinfo = arg; 3201169277Sariff struct hdac_softc *sc; 3202169277Sariff 3203169277Sariff if (devinfo == NULL || devinfo->codec == NULL || 3204169277Sariff devinfo->codec->sc == NULL) 3205169277Sariff return; 3206169277Sariff sc = devinfo->codec->sc; 3207169277Sariff hdac_lock(sc); 3208169277Sariff if (sc->poll_ival == 0) { 3209169277Sariff hdac_unlock(sc); 3210169277Sariff return; 3211169277Sariff } 3212169277Sariff hdac_hp_switch_handler(devinfo); 3213169277Sariff callout_reset(&sc->poll_jack, sc->poll_ival, 3214169277Sariff hdac_jack_poll_callback, devinfo); 3215169277Sariff hdac_unlock(sc); 3216169277Sariff} 3217169277Sariff 3218162922Sariffstatic int 3219162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3220162922Sariff{ 3221162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3222162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3223162922Sariff struct hdac_widget *w, *cw; 3224162922Sariff struct hdac_audio_ctl *ctl; 3225162922Sariff uint32_t mask, recmask, id; 3226162922Sariff int i, j, softpcmvol; 3227162922Sariff nid_t cad; 3228162922Sariff 3229162922Sariff hdac_lock(sc); 3230162922Sariff 3231162922Sariff mask = 0; 3232162922Sariff recmask = 0; 3233162922Sariff 3234162922Sariff id = hdac_codec_id(devinfo); 3235162922Sariff cad = devinfo->codec->cad; 3236162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 3237163257Sariff if (!(HDA_DEV_MATCH(hdac_hp_switch[i].model, 3238169277Sariff sc->pci_subvendor) && hdac_hp_switch[i].id == id)) 3239162922Sariff continue; 3240162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 3241169277Sariff if (w == NULL || w->enable == 0 || w->type != 3242169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 3243169277Sariff continue; 3244169277Sariff if (hdac_hp_switch[i].polling != 0) 3245169277Sariff callout_reset(&sc->poll_jack, 1, 3246169277Sariff hdac_jack_poll_callback, devinfo); 3247169277Sariff else if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 3248162922Sariff hdac_command(sc, 3249169277Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 3250169277Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 3251162922Sariff HDAC_UNSOLTAG_EVENT_HP), cad); 3252169277Sariff else 3253169277Sariff continue; 3254169277Sariff hdac_hp_switch_handler(devinfo); 3255169277Sariff HDA_BOOTVERBOSE( 3256169277Sariff device_printf(sc->dev, 3257169277Sariff "HDA_DEBUG: Enabling headphone/speaker " 3258169277Sariff "audio routing switching:\n"); 3259169277Sariff device_printf(sc->dev, 3260169277Sariff "HDA_DEBUG: \tindex=%d nid=%d " 3261169277Sariff "pci_subvendor=0x%08x " 3262169277Sariff "codec=0x%08x [%s]\n", 3263169277Sariff i, w->nid, sc->pci_subvendor, id, 3264169277Sariff (hdac_hp_switch[i].polling != 0) ? "POLL" : 3265169277Sariff "UNSOL"); 3266169277Sariff ); 3267162922Sariff break; 3268162922Sariff } 3269162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 3270163257Sariff if (!(HDA_DEV_MATCH(hdac_eapd_switch[i].model, 3271162965Sariff sc->pci_subvendor) && 3272162965Sariff hdac_eapd_switch[i].id == id)) 3273162922Sariff continue; 3274162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 3275162922Sariff if (w == NULL || w->enable == 0) 3276162922Sariff break; 3277162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3278162965Sariff w->param.eapdbtl == HDAC_INVALID) 3279162922Sariff break; 3280162922Sariff mask |= SOUND_MASK_OGAIN; 3281162922Sariff break; 3282162922Sariff } 3283162922Sariff 3284162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3285162922Sariff w = hdac_widget_get(devinfo, i); 3286162922Sariff if (w == NULL || w->enable == 0) 3287162922Sariff continue; 3288162922Sariff mask |= w->ctlflags; 3289162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 3290162922Sariff continue; 3291162922Sariff for (j = 0; j < w->nconns; j++) { 3292162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3293162922Sariff if (cw == NULL || cw->enable == 0) 3294162922Sariff continue; 3295162922Sariff recmask |= cw->ctlflags; 3296162922Sariff } 3297162922Sariff } 3298162922Sariff 3299162922Sariff if (!(mask & SOUND_MASK_PCM)) { 3300162922Sariff softpcmvol = 1; 3301162922Sariff mask |= SOUND_MASK_PCM; 3302163057Sariff } else 3303163057Sariff softpcmvol = (devinfo->function.audio.quirks & 3304163057Sariff HDA_QUIRK_SOFTPCMVOL) ? 1 : 0; 3305162922Sariff 3306162922Sariff i = 0; 3307162922Sariff ctl = NULL; 3308162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3309162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 3310162922Sariff continue; 3311162922Sariff if (!(ctl->ossmask & SOUND_MASK_PCM)) 3312162922Sariff continue; 3313162922Sariff if (ctl->step > 0) 3314162922Sariff break; 3315162922Sariff } 3316162922Sariff 3317162922Sariff if (softpcmvol == 1 || ctl == NULL) { 3318170207Sariff pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL); 3319170207Sariff HDA_BOOTVERBOSE( 3320170207Sariff device_printf(sc->dev, 3321170207Sariff "HDA_DEBUG: %s Soft PCM volume\n", 3322170207Sariff (softpcmvol == 1) ? 3323170207Sariff "Forcing" : "Enabling"); 3324170207Sariff ); 3325162922Sariff i = 0; 3326162922Sariff /* 3327162922Sariff * XXX Temporary quirk for STAC9220, until the parser 3328162922Sariff * become smarter. 3329162922Sariff */ 3330162922Sariff if (id == HDA_CODEC_STAC9220) { 3331162922Sariff mask |= SOUND_MASK_VOLUME; 3332162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 3333162922Sariff NULL) { 3334162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 3335162922Sariff continue; 3336162922Sariff if (ctl->widget->nid == 11 && ctl->index == 0) { 3337162922Sariff ctl->ossmask = SOUND_MASK_VOLUME; 3338162922Sariff ctl->ossval = 100 | (100 << 8); 3339162922Sariff } else 3340162922Sariff ctl->ossmask &= ~SOUND_MASK_VOLUME; 3341162922Sariff } 3342165992Sariff } else if (id == HDA_CODEC_STAC9221) { 3343165992Sariff mask |= SOUND_MASK_VOLUME; 3344165992Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 3345165992Sariff NULL) { 3346165992Sariff if (ctl->widget == NULL) 3347165992Sariff continue; 3348169277Sariff if (ctl->widget->type == 3349169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT && 3350169277Sariff ctl->index == 0 && (ctl->widget->nid == 2 || 3351169277Sariff ctl->widget->enable != 0)) { 3352165992Sariff ctl->enable = 1; 3353165992Sariff ctl->ossmask = SOUND_MASK_VOLUME; 3354165992Sariff ctl->ossval = 100 | (100 << 8); 3355165992Sariff } else if (ctl->enable == 0) 3356165992Sariff continue; 3357165992Sariff else 3358165992Sariff ctl->ossmask &= ~SOUND_MASK_VOLUME; 3359165992Sariff } 3360162922Sariff } else { 3361162922Sariff mix_setparentchild(m, SOUND_MIXER_VOLUME, 3362162922Sariff SOUND_MASK_PCM); 3363162922Sariff if (!(mask & SOUND_MASK_VOLUME)) 3364162922Sariff mix_setrealdev(m, SOUND_MIXER_VOLUME, 3365162922Sariff SOUND_MIXER_NONE); 3366162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 3367162922Sariff NULL) { 3368162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 3369162922Sariff continue; 3370163057Sariff if (!HDA_FLAG_MATCH(ctl->ossmask, 3371163057Sariff SOUND_MASK_VOLUME | SOUND_MASK_PCM)) 3372162922Sariff continue; 3373162922Sariff if (!(ctl->mute == 1 && ctl->step == 0)) 3374162922Sariff ctl->enable = 0; 3375162922Sariff } 3376162922Sariff } 3377162922Sariff } 3378162922Sariff 3379169277Sariff recmask &= ~(SOUND_MASK_PCM | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER | 3380169277Sariff SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_IGAIN | 3381169277Sariff SOUND_MASK_OGAIN); 3382169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3383169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3384162922Sariff 3385162922Sariff mix_setrecdevs(m, recmask); 3386162922Sariff mix_setdevs(m, mask); 3387162922Sariff 3388162922Sariff hdac_unlock(sc); 3389162922Sariff 3390162922Sariff return (0); 3391162922Sariff} 3392162922Sariff 3393162922Sariffstatic int 3394162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3395162922Sariff unsigned left, unsigned right) 3396162922Sariff{ 3397162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3398162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3399162922Sariff struct hdac_widget *w; 3400162922Sariff struct hdac_audio_ctl *ctl; 3401162922Sariff uint32_t id, mute; 3402162922Sariff int lvol, rvol, mlvol, mrvol; 3403162922Sariff int i = 0; 3404162922Sariff 3405162922Sariff hdac_lock(sc); 3406162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3407163257Sariff uint32_t orig; 3408162922Sariff /*if (left != right || !(left == 0 || left == 1)) { 3409162922Sariff hdac_unlock(sc); 3410162922Sariff return (-1); 3411162922Sariff }*/ 3412162922Sariff id = hdac_codec_id(devinfo); 3413162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 3414163257Sariff if (HDA_DEV_MATCH(hdac_eapd_switch[i].model, 3415162965Sariff sc->pci_subvendor) && 3416162922Sariff hdac_eapd_switch[i].id == id) 3417162922Sariff break; 3418162922Sariff } 3419162922Sariff if (i >= HDAC_EAPD_SWITCH_LEN) { 3420162922Sariff hdac_unlock(sc); 3421162922Sariff return (-1); 3422162922Sariff } 3423162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 3424162922Sariff if (w == NULL || 3425162922Sariff w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3426162965Sariff w->param.eapdbtl == HDAC_INVALID) { 3427162922Sariff hdac_unlock(sc); 3428162922Sariff return (-1); 3429162922Sariff } 3430163257Sariff orig = w->param.eapdbtl; 3431163432Sariff if (left == 0) 3432162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3433162922Sariff else 3434162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3435163257Sariff if (orig != w->param.eapdbtl) { 3436163432Sariff uint32_t val; 3437163432Sariff 3438163257Sariff if (hdac_eapd_switch[i].hp_switch != 0) 3439163257Sariff hdac_hp_switch_handler(devinfo); 3440163432Sariff val = w->param.eapdbtl; 3441163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3442163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3443163257Sariff hdac_command(sc, 3444163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3445163432Sariff w->nid, val), devinfo->codec->cad); 3446163257Sariff } 3447162922Sariff hdac_unlock(sc); 3448162922Sariff return (left | (left << 8)); 3449162922Sariff } 3450162922Sariff if (dev == SOUND_MIXER_VOLUME) 3451162922Sariff devinfo->function.audio.mvol = left | (right << 8); 3452162922Sariff 3453162922Sariff mlvol = devinfo->function.audio.mvol & 0x7f; 3454162922Sariff mrvol = (devinfo->function.audio.mvol >> 8) & 0x7f; 3455162922Sariff lvol = 0; 3456162922Sariff rvol = 0; 3457162922Sariff 3458162922Sariff i = 0; 3459162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3460162922Sariff if (ctl->widget == NULL || ctl->enable == 0 || 3461162922Sariff !(ctl->ossmask & (1 << dev))) 3462162922Sariff continue; 3463162922Sariff switch (dev) { 3464162922Sariff case SOUND_MIXER_VOLUME: 3465162922Sariff lvol = ((ctl->ossval & 0x7f) * left) / 100; 3466162922Sariff lvol = (lvol * ctl->step) / 100; 3467162922Sariff rvol = (((ctl->ossval >> 8) & 0x7f) * right) / 100; 3468162922Sariff rvol = (rvol * ctl->step) / 100; 3469162922Sariff break; 3470162922Sariff default: 3471162922Sariff if (ctl->ossmask & SOUND_MASK_VOLUME) { 3472162922Sariff lvol = (left * mlvol) / 100; 3473162922Sariff lvol = (lvol * ctl->step) / 100; 3474162922Sariff rvol = (right * mrvol) / 100; 3475162922Sariff rvol = (rvol * ctl->step) / 100; 3476162922Sariff } else { 3477162922Sariff lvol = (left * ctl->step) / 100; 3478162922Sariff rvol = (right * ctl->step) / 100; 3479162922Sariff } 3480162922Sariff ctl->ossval = left | (right << 8); 3481162922Sariff break; 3482162922Sariff } 3483162922Sariff mute = 0; 3484162922Sariff if (ctl->step < 1) { 3485162922Sariff mute |= (left == 0) ? HDA_AMP_MUTE_LEFT : 3486162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 3487162922Sariff mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 3488162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 3489162922Sariff } else { 3490162922Sariff mute |= (lvol == 0) ? HDA_AMP_MUTE_LEFT : 3491162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 3492162922Sariff mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 3493162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 3494162922Sariff } 3495162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3496162922Sariff } 3497162922Sariff hdac_unlock(sc); 3498162922Sariff 3499162922Sariff return (left | (right << 8)); 3500162922Sariff} 3501162922Sariff 3502162922Sariffstatic int 3503162922Sariffhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3504162922Sariff{ 3505162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3506162922Sariff struct hdac_widget *w, *cw; 3507162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3508162922Sariff uint32_t ret = src, target; 3509162922Sariff int i, j; 3510162922Sariff 3511162922Sariff target = 0; 3512162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3513162922Sariff if (src & (1 << i)) { 3514162922Sariff target = 1 << i; 3515162922Sariff break; 3516162922Sariff } 3517162922Sariff } 3518162922Sariff 3519162922Sariff hdac_lock(sc); 3520162922Sariff 3521162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3522162922Sariff w = hdac_widget_get(devinfo, i); 3523162965Sariff if (w == NULL || w->enable == 0) 3524162922Sariff continue; 3525162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 3526162922Sariff continue; 3527162922Sariff for (j = 0; j < w->nconns; j++) { 3528162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3529162922Sariff if (cw == NULL || cw->enable == 0) 3530162922Sariff continue; 3531162922Sariff if ((target == SOUND_MASK_VOLUME && 3532162922Sariff cw->type != 3533162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 3534162922Sariff (target != SOUND_MASK_VOLUME && 3535162922Sariff cw->type == 3536162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)) 3537162922Sariff continue; 3538162922Sariff if (cw->ctlflags & target) { 3539169277Sariff if (!(w->pflags & HDA_ADC_LOCKED)) 3540169277Sariff hdac_widget_connection_select(w, j); 3541162922Sariff ret = target; 3542162922Sariff j += w->nconns; 3543162922Sariff } 3544162922Sariff } 3545162922Sariff } 3546162922Sariff 3547162922Sariff hdac_unlock(sc); 3548162922Sariff 3549162922Sariff return (ret); 3550162922Sariff} 3551162922Sariff 3552162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3553162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3554162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3555162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3556162922Sariff { 0, 0 } 3557162922Sariff}; 3558162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3559162922Sariff 3560162922Sariff/**************************************************************************** 3561162922Sariff * int hdac_attach(device_t) 3562162922Sariff * 3563162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3564162922Sariff * when this function is called. Setup everything that doesn't require 3565162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3566162922Sariff ****************************************************************************/ 3567162922Sariffstatic int 3568162922Sariffhdac_attach(device_t dev) 3569162922Sariff{ 3570162922Sariff struct hdac_softc *sc; 3571162922Sariff int result; 3572169277Sariff int i; 3573169277Sariff uint16_t vendor; 3574169277Sariff uint8_t v; 3575162922Sariff 3576162922Sariff sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO); 3577162922Sariff if (sc == NULL) { 3578162922Sariff device_printf(dev, "cannot allocate softc\n"); 3579162922Sariff return (ENOMEM); 3580162922Sariff } 3581163057Sariff 3582163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 3583162922Sariff sc->dev = dev; 3584163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 3585163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 3586169277Sariff vendor = pci_get_vendor(dev); 3587162922Sariff 3588165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 3589165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 3590165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 3591165281Sariff } 3592165281Sariff 3593164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 3594164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 3595169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 3596164614Sariff 3597164614Sariff sc->poll_ticks = 1; 3598169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 3599169277Sariff if (resource_int_value(device_get_name(dev), 3600169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 3601164614Sariff sc->polling = 1; 3602164614Sariff else 3603164614Sariff sc->polling = 0; 3604164614Sariff 3605162922Sariff sc->chan_size = pcm_getbuffersize(dev, 3606164614Sariff HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 3607164614Sariff 3608169277Sariff if (resource_int_value(device_get_name(dev), 3609169277Sariff device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 3610167648Sariff i &= HDA_BLK_ALIGN; 3611167648Sariff if (i < HDA_BLK_MIN) 3612167648Sariff i = HDA_BLK_MIN; 3613162922Sariff sc->chan_blkcnt = sc->chan_size / i; 3614162922Sariff i = 0; 3615162922Sariff while (sc->chan_blkcnt >> i) 3616162922Sariff i++; 3617162922Sariff sc->chan_blkcnt = 1 << (i - 1); 3618162922Sariff if (sc->chan_blkcnt < HDA_BDL_MIN) 3619162922Sariff sc->chan_blkcnt = HDA_BDL_MIN; 3620162922Sariff else if (sc->chan_blkcnt > HDA_BDL_MAX) 3621162922Sariff sc->chan_blkcnt = HDA_BDL_MAX; 3622162922Sariff } else 3623162922Sariff sc->chan_blkcnt = HDA_BDL_DEFAULT; 3624162922Sariff 3625162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 3626162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 3627162922Sariff 0, /* boundary */ 3628162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 3629162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 3630162922Sariff NULL, /* filtfunc */ 3631162922Sariff NULL, /* fistfuncarg */ 3632165281Sariff sc->chan_size, /* maxsize */ 3633162922Sariff 1, /* nsegments */ 3634165281Sariff sc->chan_size, /* maxsegsz */ 3635162922Sariff 0, /* flags */ 3636162922Sariff NULL, /* lockfunc */ 3637162922Sariff NULL, /* lockfuncarg */ 3638162922Sariff &sc->chan_dmat); /* dmat */ 3639162922Sariff if (result != 0) { 3640169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 3641162922Sariff __func__, result); 3642163057Sariff snd_mtxfree(sc->lock); 3643162922Sariff free(sc, M_DEVBUF); 3644162922Sariff return (ENXIO); 3645162922Sariff } 3646162922Sariff 3647162922Sariff 3648162922Sariff sc->hdabus = NULL; 3649162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 3650162922Sariff sc->codecs[i] = NULL; 3651162922Sariff 3652162922Sariff pci_enable_busmaster(dev); 3653162922Sariff 3654169277Sariff if (vendor == INTEL_VENDORID) { 3655169277Sariff /* TCSEL -> TC0 */ 3656169277Sariff v = pci_read_config(dev, 0x44, 1); 3657169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 3658169277Sariff HDA_BOOTVERBOSE( 3659169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 3660169277Sariff pci_read_config(dev, 0x44, 1)); 3661169277Sariff ); 3662169277Sariff } 3663169277Sariff 3664169277Sariff#if defined(__i386__) || defined(__amd64__) 3665169277Sariff sc->nocache = 1; 3666169277Sariff 3667169277Sariff if (resource_int_value(device_get_name(dev), 3668169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 3669169277Sariff#else 3670169277Sariff sc->nocache = 0; 3671169277Sariff#endif 3672169277Sariff /* 3673169277Sariff * Try to enable PCIe snoop to avoid messing around with 3674169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 3675169277Sariff * config is pretty much vendor specific, there are no 3676169277Sariff * general solutions on how to enable it, forcing us (even 3677169277Sariff * Microsoft) to enable uncacheable or write combined DMA 3678169277Sariff * by default. 3679169277Sariff * 3680169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 3681169277Sariff */ 3682169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 3683169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 3684169277Sariff continue; 3685169277Sariff sc->nocache = 0; 3686169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 3687169277Sariff break; 3688169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3689169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 3690169277Sariff hdac_pcie_snoop[i].enable) 3691169277Sariff break; 3692169277Sariff v &= hdac_pcie_snoop[i].mask; 3693169277Sariff v |= hdac_pcie_snoop[i].enable; 3694169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 3695169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3696169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 3697169277Sariff hdac_pcie_snoop[i].enable) { 3698169277Sariff HDA_BOOTVERBOSE( 3699169277Sariff device_printf(dev, 3700169277Sariff "WARNING: Failed to enable PCIe " 3701169277Sariff "snoop!\n"); 3702169277Sariff ); 3703169277Sariff#if defined(__i386__) || defined(__amd64__) 3704169277Sariff sc->nocache = 1; 3705169277Sariff#endif 3706169277Sariff } 3707169277Sariff break; 3708169277Sariff } 3709169277Sariff#if defined(__i386__) || defined(__amd64__) 3710169277Sariff } 3711169277Sariff#endif 3712169277Sariff 3713169277Sariff HDA_BOOTVERBOSE( 3714169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 3715169277Sariff (sc->nocache == 0) ? "PCIe snoop" : "Uncacheable", vendor); 3716169277Sariff ); 3717169277Sariff 3718162922Sariff /* Allocate resources */ 3719162922Sariff result = hdac_mem_alloc(sc); 3720162922Sariff if (result != 0) 3721163057Sariff goto hdac_attach_fail; 3722162922Sariff result = hdac_irq_alloc(sc); 3723162922Sariff if (result != 0) 3724163057Sariff goto hdac_attach_fail; 3725162922Sariff 3726162922Sariff /* Get Capabilities */ 3727162922Sariff result = hdac_get_capabilities(sc); 3728162922Sariff if (result != 0) 3729163057Sariff goto hdac_attach_fail; 3730162922Sariff 3731162922Sariff /* Allocate CORB and RIRB dma memory */ 3732162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 3733162922Sariff sc->corb_size * sizeof(uint32_t)); 3734162922Sariff if (result != 0) 3735163057Sariff goto hdac_attach_fail; 3736162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 3737162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 3738162922Sariff if (result != 0) 3739163057Sariff goto hdac_attach_fail; 3740162922Sariff 3741162922Sariff /* Quiesce everything */ 3742162922Sariff hdac_reset(sc); 3743162922Sariff 3744162922Sariff /* Initialize the CORB and RIRB */ 3745162922Sariff hdac_corb_init(sc); 3746162922Sariff hdac_rirb_init(sc); 3747162922Sariff 3748162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 3749162922Sariff sc->intrhook.ich_func = hdac_attach2; 3750162922Sariff sc->intrhook.ich_arg = (void *)sc; 3751162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 3752162922Sariff sc->intrhook.ich_func = NULL; 3753162922Sariff hdac_attach2((void *)sc); 3754162922Sariff } 3755162922Sariff 3756163057Sariff return (0); 3757162922Sariff 3758163057Sariffhdac_attach_fail: 3759162922Sariff hdac_irq_free(sc); 3760169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 3761169277Sariff hdac_dma_free(sc, &sc->corb_dma); 3762162922Sariff hdac_mem_free(sc); 3763162922Sariff snd_mtxfree(sc->lock); 3764163057Sariff free(sc, M_DEVBUF); 3765162922Sariff 3766163057Sariff return (ENXIO); 3767162922Sariff} 3768162922Sariff 3769162922Sariffstatic void 3770162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 3771162922Sariff{ 3772162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3773162922Sariff struct hdac_widget *w; 3774162922Sariff uint32_t res; 3775162922Sariff int i; 3776162922Sariff nid_t cad, nid; 3777162922Sariff 3778162922Sariff cad = devinfo->codec->cad; 3779162922Sariff nid = devinfo->nid; 3780162922Sariff 3781162922Sariff hdac_command(sc, 3782162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), cad); 3783162922Sariff 3784162922Sariff DELAY(100); 3785162922Sariff 3786162922Sariff res = hdac_command(sc, 3787162922Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 3788162922Sariff 3789162922Sariff devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 3790162922Sariff devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 3791162922Sariff devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 3792162922Sariff 3793169277Sariff res = hdac_command(sc, 3794169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 3795169277Sariff devinfo->function.audio.gpio = res; 3796169277Sariff 3797163057Sariff HDA_BOOTVERBOSE( 3798162922Sariff device_printf(sc->dev, " Vendor: 0x%08x\n", 3799162922Sariff devinfo->vendor_id); 3800162922Sariff device_printf(sc->dev, " Device: 0x%08x\n", 3801162922Sariff devinfo->device_id); 3802162922Sariff device_printf(sc->dev, " Revision: 0x%08x\n", 3803162922Sariff devinfo->revision_id); 3804162922Sariff device_printf(sc->dev, " Stepping: 0x%08x\n", 3805162922Sariff devinfo->stepping_id); 3806162922Sariff device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 3807162922Sariff sc->pci_subvendor); 3808162922Sariff device_printf(sc->dev, " Nodes: start=%d " 3809162922Sariff "endnode=%d total=%d\n", 3810162922Sariff devinfo->startnode, devinfo->endnode, devinfo->nodecnt); 3811169277Sariff device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 3812169277Sariff device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 3813169277Sariff device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 3814169277Sariff sc->num_iss, sc->num_oss, sc->num_bss); 3815169277Sariff device_printf(sc->dev, " GPIO: 0x%08x\n", 3816169277Sariff devinfo->function.audio.gpio); 3817169277Sariff device_printf(sc->dev, " NumGPIO=%d NumGPO=%d " 3818169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 3819169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 3820169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 3821169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 3822169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 3823169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 3824162922Sariff ); 3825162922Sariff 3826162922Sariff res = hdac_command(sc, 3827162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 3828162922Sariff cad); 3829162922Sariff devinfo->function.audio.supp_stream_formats = res; 3830162922Sariff 3831162922Sariff res = hdac_command(sc, 3832162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 3833162922Sariff cad); 3834162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 3835162922Sariff 3836162922Sariff res = hdac_command(sc, 3837162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 3838162922Sariff cad); 3839162922Sariff devinfo->function.audio.outamp_cap = res; 3840162922Sariff 3841162922Sariff res = hdac_command(sc, 3842162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 3843162922Sariff cad); 3844162922Sariff devinfo->function.audio.inamp_cap = res; 3845162922Sariff 3846169277Sariff if (devinfo->nodecnt > 0) 3847162922Sariff devinfo->widget = (struct hdac_widget *)malloc( 3848162922Sariff sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 3849162922Sariff M_NOWAIT | M_ZERO); 3850169277Sariff else 3851162922Sariff devinfo->widget = NULL; 3852162922Sariff 3853162922Sariff if (devinfo->widget == NULL) { 3854162922Sariff device_printf(sc->dev, "unable to allocate widgets!\n"); 3855162922Sariff devinfo->endnode = devinfo->startnode; 3856162922Sariff devinfo->nodecnt = 0; 3857162922Sariff return; 3858162922Sariff } 3859162922Sariff 3860162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3861162922Sariff w = hdac_widget_get(devinfo, i); 3862162922Sariff if (w == NULL) 3863162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 3864162922Sariff else { 3865162922Sariff w->devinfo = devinfo; 3866162922Sariff w->nid = i; 3867162922Sariff w->enable = 1; 3868162922Sariff w->selconn = -1; 3869162922Sariff w->pflags = 0; 3870162922Sariff w->ctlflags = 0; 3871162965Sariff w->param.eapdbtl = HDAC_INVALID; 3872162922Sariff hdac_widget_parse(w); 3873162922Sariff } 3874162922Sariff } 3875162922Sariff} 3876162922Sariff 3877162922Sariffstatic void 3878162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 3879162922Sariff{ 3880162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3881162922Sariff struct hdac_audio_ctl *ctls; 3882162922Sariff struct hdac_widget *w, *cw; 3883162922Sariff int i, j, cnt, max, ocap, icap; 3884163057Sariff int mute, offset, step, size; 3885162922Sariff 3886162922Sariff /* XXX This is redundant */ 3887162922Sariff max = 0; 3888162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3889162922Sariff w = hdac_widget_get(devinfo, i); 3890162922Sariff if (w == NULL || w->enable == 0) 3891162922Sariff continue; 3892162922Sariff if (w->param.outamp_cap != 0) 3893162922Sariff max++; 3894162922Sariff if (w->param.inamp_cap != 0) { 3895162922Sariff switch (w->type) { 3896162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3897162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3898162922Sariff for (j = 0; j < w->nconns; j++) { 3899162922Sariff cw = hdac_widget_get(devinfo, 3900162922Sariff w->conns[j]); 3901162922Sariff if (cw == NULL || cw->enable == 0) 3902162922Sariff continue; 3903162922Sariff max++; 3904162922Sariff } 3905162922Sariff break; 3906162922Sariff default: 3907162922Sariff max++; 3908162922Sariff break; 3909162922Sariff } 3910162922Sariff } 3911162922Sariff } 3912162922Sariff 3913162922Sariff devinfo->function.audio.ctlcnt = max; 3914162922Sariff 3915162922Sariff if (max < 1) 3916162922Sariff return; 3917162922Sariff 3918162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 3919162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 3920162922Sariff 3921162922Sariff if (ctls == NULL) { 3922162922Sariff /* Blekh! */ 3923162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 3924162922Sariff devinfo->function.audio.ctlcnt = 0; 3925162922Sariff return; 3926162922Sariff } 3927162922Sariff 3928162922Sariff cnt = 0; 3929162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 3930162922Sariff if (cnt >= max) { 3931162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 3932162922Sariff __func__); 3933162922Sariff break; 3934162922Sariff } 3935162922Sariff w = hdac_widget_get(devinfo, i); 3936162922Sariff if (w == NULL || w->enable == 0) 3937162922Sariff continue; 3938162922Sariff ocap = w->param.outamp_cap; 3939162922Sariff icap = w->param.inamp_cap; 3940162922Sariff if (ocap != 0) { 3941163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 3942163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 3943163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 3944163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 3945163057Sariff /*if (offset > step) { 3946163057Sariff HDA_BOOTVERBOSE( 3947163057Sariff device_printf(sc->dev, 3948163057Sariff "HDA_DEBUG: BUGGY outamp: nid=%d " 3949163057Sariff "[offset=%d > step=%d]\n", 3950163057Sariff w->nid, offset, step); 3951163057Sariff ); 3952163057Sariff offset = step; 3953163057Sariff }*/ 3954162922Sariff ctls[cnt].enable = 1; 3955162922Sariff ctls[cnt].widget = w; 3956163057Sariff ctls[cnt].mute = mute; 3957163057Sariff ctls[cnt].step = step; 3958163057Sariff ctls[cnt].size = size; 3959163057Sariff ctls[cnt].offset = offset; 3960163057Sariff ctls[cnt].left = offset; 3961163057Sariff ctls[cnt].right = offset; 3962162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 3963162922Sariff } 3964162922Sariff 3965162922Sariff if (icap != 0) { 3966163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 3967163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 3968163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 3969163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 3970163057Sariff /*if (offset > step) { 3971163057Sariff HDA_BOOTVERBOSE( 3972163057Sariff device_printf(sc->dev, 3973163057Sariff "HDA_DEBUG: BUGGY inamp: nid=%d " 3974163057Sariff "[offset=%d > step=%d]\n", 3975163057Sariff w->nid, offset, step); 3976163057Sariff ); 3977163057Sariff offset = step; 3978163057Sariff }*/ 3979162922Sariff switch (w->type) { 3980162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3981162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3982162922Sariff for (j = 0; j < w->nconns; j++) { 3983162922Sariff if (cnt >= max) { 3984162922Sariff device_printf(sc->dev, 3985162922Sariff "%s: Ctl overflow!\n", 3986162922Sariff __func__); 3987162922Sariff break; 3988162922Sariff } 3989162922Sariff cw = hdac_widget_get(devinfo, 3990162922Sariff w->conns[j]); 3991162922Sariff if (cw == NULL || cw->enable == 0) 3992162922Sariff continue; 3993162922Sariff ctls[cnt].enable = 1; 3994162922Sariff ctls[cnt].widget = w; 3995162922Sariff ctls[cnt].childwidget = cw; 3996162922Sariff ctls[cnt].index = j; 3997163057Sariff ctls[cnt].mute = mute; 3998163057Sariff ctls[cnt].step = step; 3999163057Sariff ctls[cnt].size = size; 4000163057Sariff ctls[cnt].offset = offset; 4001163057Sariff ctls[cnt].left = offset; 4002163057Sariff ctls[cnt].right = offset; 4003162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4004162922Sariff } 4005162922Sariff break; 4006162922Sariff default: 4007162922Sariff if (cnt >= max) { 4008162922Sariff device_printf(sc->dev, 4009162922Sariff "%s: Ctl overflow!\n", 4010162922Sariff __func__); 4011162922Sariff break; 4012162922Sariff } 4013162922Sariff ctls[cnt].enable = 1; 4014162922Sariff ctls[cnt].widget = w; 4015163057Sariff ctls[cnt].mute = mute; 4016163057Sariff ctls[cnt].step = step; 4017163057Sariff ctls[cnt].size = size; 4018163057Sariff ctls[cnt].offset = offset; 4019163057Sariff ctls[cnt].left = offset; 4020163057Sariff ctls[cnt].right = offset; 4021162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4022162922Sariff break; 4023162922Sariff } 4024162922Sariff } 4025162922Sariff } 4026162922Sariff 4027162922Sariff devinfo->function.audio.ctl = ctls; 4028162922Sariff} 4029162922Sariff 4030162965Sariffstatic const struct { 4031162965Sariff uint32_t model; 4032162965Sariff uint32_t id; 4033162965Sariff uint32_t set, unset; 4034162965Sariff} hdac_quirks[] = { 4035163057Sariff /* 4036163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4037163057Sariff * on few codecs (especially ALC880) seems broken or 4038163057Sariff * perhaps unsupported. 4039163057Sariff */ 4040163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4041169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4042162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4043165039Sariff HDA_QUIRK_GPIO0, 0 }, 4044162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4045165039Sariff HDA_QUIRK_GPIO0, 0 }, 4046165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4047165281Sariff HDA_QUIRK_GPIO0, 0 }, 4048167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4049167623Sariff HDA_QUIRK_GPIO0, 0 }, 4050169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4051169277Sariff HDA_QUIRK_GPIO0, 0 }, 4052163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4053163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4054163432Sariff { ASUS_A8JC_SUBVENDOR, HDA_CODEC_AD1986A, 4055163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4056169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4057169277Sariff HDA_QUIRK_OVREF, 0 }, 4058169277Sariff { ASUS_W6F_SUBVENDOR, HDA_CODEC_ALC861, 4059169277Sariff HDA_QUIRK_OVREF, 0 }, 4060169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4061169277Sariff HDA_QUIRK_OVREF, 0 }, 4062169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4063169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4064165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4065165281Sariff HDA_QUIRK_GPIO1, 0 }, 4066164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4067164614Sariff HDA_QUIRK_EAPDINV, 0 }, 4068164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4069164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4070165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4071165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4072169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4073169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4074170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4075170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4076162965Sariff { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 4077162965Sariff 0, HDA_QUIRK_FORCESTEREO }, 4078162965Sariff { HDA_MATCH_ALL, HDA_CODEC_STACXXXX, 4079162965Sariff HDA_QUIRK_SOFTPCMVOL, 0 } 4080162965Sariff}; 4081162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4082162965Sariff 4083162922Sariffstatic void 4084162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4085162922Sariff{ 4086162922Sariff struct hdac_widget *w; 4087165466Sariff struct hdac_audio_ctl *ctl; 4088162965Sariff uint32_t id, subvendor; 4089162922Sariff int i; 4090162922Sariff 4091163057Sariff id = hdac_codec_id(devinfo); 4092163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4093163057Sariff 4094162922Sariff /* 4095163057Sariff * Quirks 4096162922Sariff */ 4097163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4098163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4099163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4100163057Sariff continue; 4101163057Sariff if (hdac_quirks[i].set != 0) 4102163057Sariff devinfo->function.audio.quirks |= 4103163057Sariff hdac_quirks[i].set; 4104163057Sariff if (hdac_quirks[i].unset != 0) 4105163057Sariff devinfo->function.audio.quirks &= 4106163057Sariff ~(hdac_quirks[i].unset); 4107163057Sariff } 4108163057Sariff 4109162922Sariff switch (id) { 4110162922Sariff case HDA_CODEC_ALC260: 4111162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4112162922Sariff w = hdac_widget_get(devinfo, i); 4113162922Sariff if (w == NULL || w->enable == 0) 4114162922Sariff continue; 4115162922Sariff if (w->type != 4116162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4117162922Sariff continue; 4118162922Sariff if (w->nid != 5) 4119162922Sariff w->enable = 0; 4120162922Sariff } 4121166294Sariff if (subvendor == HP_XW4300_SUBVENDOR) { 4122166294Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 16, 0, 1); 4123166294Sariff if (ctl != NULL && ctl->widget != NULL) { 4124166294Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4125166294Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4126166294Sariff } 4127166294Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 17, 0, 1); 4128166294Sariff if (ctl != NULL && ctl->widget != NULL) { 4129166294Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4130166294Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4131166294Sariff } 4132169277Sariff } else if (subvendor == HP_3010_SUBVENDOR) { 4133169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 17, 0, 1); 4134169277Sariff if (ctl != NULL && ctl->widget != NULL) { 4135169277Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4136169277Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4137169277Sariff } 4138169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 21, 0, 1); 4139169277Sariff if (ctl != NULL && ctl->widget != NULL) { 4140169277Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4141169277Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4142169277Sariff } 4143166294Sariff } 4144162922Sariff break; 4145165103Sariff case HDA_CODEC_ALC861: 4146169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 21, 2, 1); 4147165466Sariff if (ctl != NULL) 4148165466Sariff ctl->muted = HDA_AMP_MUTE_ALL; 4149165103Sariff break; 4150162922Sariff case HDA_CODEC_ALC880: 4151162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4152162922Sariff w = hdac_widget_get(devinfo, i); 4153162922Sariff if (w == NULL || w->enable == 0) 4154162922Sariff continue; 4155162922Sariff if (w->type == 4156162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 4157162922Sariff w->nid != 9 && w->nid != 29) { 4158162922Sariff w->enable = 0; 4159162922Sariff } else if (w->type != 4160162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET && 4161162922Sariff w->nid == 29) { 4162163057Sariff w->type = 4163163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET; 4164163057Sariff w->param.widget_cap &= 4165163057Sariff ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 4166162922Sariff w->param.widget_cap |= 4167162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 4168162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 4169162922Sariff strlcpy(w->name, "beep widget", sizeof(w->name)); 4170162922Sariff } 4171162922Sariff } 4172162922Sariff break; 4173166965Sariff case HDA_CODEC_ALC883: 4174166965Sariff /* 4175166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4176166965Sariff * Clear vref cap for jack connectivity. 4177166965Sariff */ 4178166965Sariff w = hdac_widget_get(devinfo, 24); 4179166965Sariff if (w != NULL && w->enable != 0 && w->type == 4180166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4181166965Sariff (w->wclass.pin.config & 4182166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4183166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4184166965Sariff w->wclass.pin.cap &= ~( 4185166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4186166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4187166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4188166965Sariff w = hdac_widget_get(devinfo, 25); 4189166965Sariff if (w != NULL && w->enable != 0 && w->type == 4190166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4191166965Sariff (w->wclass.pin.config & 4192166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4193166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4194166965Sariff w->wclass.pin.cap &= ~( 4195166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4196166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4197166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4198166965Sariff /* 4199166965Sariff * nid: 26 = Line-in, leave it alone. 4200166965Sariff */ 4201166965Sariff break; 4202163257Sariff case HDA_CODEC_AD1981HD: 4203163257Sariff w = hdac_widget_get(devinfo, 11); 4204163257Sariff if (w != NULL && w->enable != 0 && w->nconns > 3) 4205163257Sariff w->selconn = 3; 4206163257Sariff if (subvendor == IBM_M52_SUBVENDOR) { 4207163257Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 7, 0, 1); 4208163257Sariff if (ctl != NULL) 4209163257Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4210163257Sariff } 4211163257Sariff break; 4212162922Sariff case HDA_CODEC_AD1986A: 4213162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4214162922Sariff w = hdac_widget_get(devinfo, i); 4215162922Sariff if (w == NULL || w->enable == 0) 4216162922Sariff continue; 4217162922Sariff if (w->type != 4218162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 4219162922Sariff continue; 4220162922Sariff if (w->nid != 3) 4221162922Sariff w->enable = 0; 4222162922Sariff } 4223169277Sariff if (subvendor == ASUS_M2NPVMX_SUBVENDOR) { 4224169277Sariff /* nid 28 is mic, nid 29 is line-in */ 4225169277Sariff w = hdac_widget_get(devinfo, 15); 4226169277Sariff if (w != NULL) 4227169277Sariff w->selconn = 2; 4228169277Sariff w = hdac_widget_get(devinfo, 16); 4229169277Sariff if (w != NULL) 4230169277Sariff w->selconn = 1; 4231169277Sariff } 4232162922Sariff break; 4233169277Sariff case HDA_CODEC_AD1988: 4234170518Sariff case HDA_CODEC_AD1988B: 4235169277Sariff /*w = hdac_widget_get(devinfo, 12); 4236169277Sariff if (w != NULL) { 4237169277Sariff w->selconn = 1; 4238169277Sariff w->pflags |= HDA_ADC_LOCKED; 4239169277Sariff } 4240169277Sariff w = hdac_widget_get(devinfo, 13); 4241169277Sariff if (w != NULL) { 4242169277Sariff w->selconn = 4; 4243169277Sariff w->pflags |= HDA_ADC_LOCKED; 4244169277Sariff } 4245169277Sariff w = hdac_widget_get(devinfo, 14); 4246169277Sariff if (w != NULL) { 4247169277Sariff w->selconn = 2; 4248169277Sariff w->pflags |= HDA_ADC_LOCKED; 4249169277Sariff }*/ 4250169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 57, 0, 1); 4251169277Sariff if (ctl != NULL) { 4252169277Sariff ctl->ossmask = SOUND_MASK_IGAIN; 4253169277Sariff ctl->widget->ctlflags |= SOUND_MASK_IGAIN; 4254169277Sariff } 4255169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 58, 0, 1); 4256169277Sariff if (ctl != NULL) { 4257169277Sariff ctl->ossmask = SOUND_MASK_IGAIN; 4258169277Sariff ctl->widget->ctlflags |= SOUND_MASK_IGAIN; 4259169277Sariff } 4260169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 60, 0, 1); 4261169277Sariff if (ctl != NULL) { 4262169277Sariff ctl->ossmask = SOUND_MASK_IGAIN; 4263169277Sariff ctl->widget->ctlflags |= SOUND_MASK_IGAIN; 4264169277Sariff } 4265169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 0, 1); 4266169277Sariff if (ctl != NULL) { 4267169277Sariff ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME; 4268169277Sariff ctl->widget->ctlflags |= SOUND_MASK_MIC; 4269169277Sariff } 4270169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 4, 1); 4271169277Sariff if (ctl != NULL) { 4272169277Sariff ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME; 4273169277Sariff ctl->widget->ctlflags |= SOUND_MASK_MIC; 4274169277Sariff } 4275169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 1, 1); 4276169277Sariff if (ctl != NULL) { 4277169277Sariff ctl->ossmask = SOUND_MASK_LINE | SOUND_MASK_VOLUME; 4278169277Sariff ctl->widget->ctlflags |= SOUND_MASK_LINE; 4279169277Sariff } 4280169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 7, 1); 4281169277Sariff if (ctl != NULL) { 4282169277Sariff ctl->ossmask = SOUND_MASK_SPEAKER | SOUND_MASK_VOLUME; 4283169277Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4284169277Sariff } 4285169277Sariff break; 4286162922Sariff case HDA_CODEC_STAC9221: 4287169277Sariff /* 4288169277Sariff * Dell XPS M1210 need all DACs for each output jacks 4289169277Sariff */ 4290169277Sariff if (subvendor == DELL_XPSM1210_SUBVENDOR) 4291169277Sariff break; 4292162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4293162922Sariff w = hdac_widget_get(devinfo, i); 4294162922Sariff if (w == NULL || w->enable == 0) 4295162922Sariff continue; 4296162922Sariff if (w->type != 4297162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 4298162922Sariff continue; 4299162922Sariff if (w->nid != 2) 4300162922Sariff w->enable = 0; 4301162922Sariff } 4302162922Sariff break; 4303162922Sariff case HDA_CODEC_STAC9221D: 4304162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4305162922Sariff w = hdac_widget_get(devinfo, i); 4306162922Sariff if (w == NULL || w->enable == 0) 4307162922Sariff continue; 4308162922Sariff if (w->type == 4309162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 4310162922Sariff w->nid != 6) 4311162922Sariff w->enable = 0; 4312162922Sariff 4313162922Sariff } 4314162922Sariff break; 4315169277Sariff case HDA_CODEC_STAC9227: 4316169277Sariff w = hdac_widget_get(devinfo, 8); 4317169277Sariff if (w != NULL) 4318169277Sariff w->enable = 0; 4319169277Sariff w = hdac_widget_get(devinfo, 9); 4320169277Sariff if (w != NULL) 4321169277Sariff w->enable = 0; 4322169277Sariff break; 4323169277Sariff case HDA_CODEC_CXWAIKIKI: 4324169277Sariff if (subvendor == HP_DV5000_SUBVENDOR) { 4325169277Sariff w = hdac_widget_get(devinfo, 27); 4326169277Sariff if (w != NULL) 4327169277Sariff w->enable = 0; 4328169277Sariff } 4329169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 16, 0, 1); 4330169277Sariff if (ctl != NULL) 4331169277Sariff ctl->ossmask = SOUND_MASK_SKIP; 4332169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 25, 0, 1); 4333169277Sariff if (ctl != NULL && ctl->childwidget != NULL && 4334169277Sariff ctl->childwidget->enable != 0) { 4335169277Sariff ctl->ossmask = SOUND_MASK_PCM | SOUND_MASK_VOLUME; 4336169277Sariff ctl->childwidget->ctlflags |= SOUND_MASK_PCM; 4337169277Sariff } 4338169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 25, 1, 1); 4339169277Sariff if (ctl != NULL && ctl->childwidget != NULL && 4340169277Sariff ctl->childwidget->enable != 0) { 4341169277Sariff ctl->ossmask = SOUND_MASK_LINE | SOUND_MASK_VOLUME; 4342169277Sariff ctl->childwidget->ctlflags |= SOUND_MASK_LINE; 4343169277Sariff } 4344169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 25, 2, 1); 4345169277Sariff if (ctl != NULL && ctl->childwidget != NULL && 4346169277Sariff ctl->childwidget->enable != 0) { 4347169277Sariff ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME; 4348169277Sariff ctl->childwidget->ctlflags |= SOUND_MASK_MIC; 4349169277Sariff } 4350169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 26, 0, 1); 4351169277Sariff if (ctl != NULL) { 4352169277Sariff ctl->ossmask = SOUND_MASK_SKIP; 4353169277Sariff /* XXX mixer \=rec mic broken.. why?!? */ 4354169277Sariff /* ctl->widget->ctlflags |= SOUND_MASK_MIC; */ 4355169277Sariff } 4356169277Sariff break; 4357162922Sariff default: 4358162922Sariff break; 4359162922Sariff } 4360162922Sariff} 4361162922Sariff 4362162922Sariffstatic int 4363162922Sariffhdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *devinfo) 4364162922Sariff{ 4365162922Sariff int *dev = &devinfo->function.audio.ossidx; 4366162922Sariff 4367162922Sariff while (*dev < SOUND_MIXER_NRDEVICES) { 4368162922Sariff switch (*dev) { 4369162922Sariff case SOUND_MIXER_VOLUME: 4370162922Sariff case SOUND_MIXER_BASS: 4371162922Sariff case SOUND_MIXER_TREBLE: 4372162922Sariff case SOUND_MIXER_PCM: 4373162922Sariff case SOUND_MIXER_SPEAKER: 4374162922Sariff case SOUND_MIXER_LINE: 4375162922Sariff case SOUND_MIXER_MIC: 4376162922Sariff case SOUND_MIXER_CD: 4377162922Sariff case SOUND_MIXER_RECLEV: 4378169277Sariff case SOUND_MIXER_IGAIN: 4379162922Sariff case SOUND_MIXER_OGAIN: /* reserved for EAPD switch */ 4380162922Sariff (*dev)++; 4381162922Sariff break; 4382162922Sariff default: 4383162922Sariff return (*dev)++; 4384162922Sariff break; 4385162922Sariff } 4386162922Sariff } 4387162922Sariff 4388162922Sariff return (-1); 4389162922Sariff} 4390162922Sariff 4391162922Sariffstatic int 4392162922Sariffhdac_widget_find_dac_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4393162922Sariff{ 4394162922Sariff struct hdac_widget *w; 4395162922Sariff int i, ret = 0; 4396162922Sariff 4397162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4398162922Sariff return (0); 4399162922Sariff w = hdac_widget_get(devinfo, nid); 4400162922Sariff if (w == NULL || w->enable == 0) 4401162922Sariff return (0); 4402162922Sariff switch (w->type) { 4403162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4404162922Sariff w->pflags |= HDA_DAC_PATH; 4405162922Sariff ret = 1; 4406162922Sariff break; 4407162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4408162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4409162922Sariff for (i = 0; i < w->nconns; i++) { 4410162922Sariff if (hdac_widget_find_dac_path(devinfo, 4411162922Sariff w->conns[i], depth + 1) != 0) { 4412162922Sariff if (w->selconn == -1) 4413162922Sariff w->selconn = i; 4414162922Sariff ret = 1; 4415162922Sariff w->pflags |= HDA_DAC_PATH; 4416162922Sariff } 4417162922Sariff } 4418162922Sariff break; 4419162922Sariff default: 4420162922Sariff break; 4421162922Sariff } 4422162922Sariff return (ret); 4423162922Sariff} 4424162922Sariff 4425162922Sariffstatic int 4426162922Sariffhdac_widget_find_adc_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4427162922Sariff{ 4428162922Sariff struct hdac_widget *w; 4429162922Sariff int i, conndev, ret = 0; 4430162922Sariff 4431162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4432162922Sariff return (0); 4433162922Sariff w = hdac_widget_get(devinfo, nid); 4434162922Sariff if (w == NULL || w->enable == 0) 4435162922Sariff return (0); 4436162922Sariff switch (w->type) { 4437162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4438162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4439162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4440162922Sariff for (i = 0; i < w->nconns; i++) { 4441162922Sariff if (hdac_widget_find_adc_path(devinfo, w->conns[i], 4442162922Sariff depth + 1) != 0) { 4443162922Sariff if (w->selconn == -1) 4444162922Sariff w->selconn = i; 4445162922Sariff w->pflags |= HDA_ADC_PATH; 4446162922Sariff ret = 1; 4447162922Sariff } 4448162922Sariff } 4449162922Sariff break; 4450162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4451162922Sariff conndev = w->wclass.pin.config & 4452162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4453162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 4454162922Sariff (conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_CD || 4455162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN || 4456162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN)) { 4457162922Sariff w->pflags |= HDA_ADC_PATH; 4458162922Sariff ret = 1; 4459162922Sariff } 4460162922Sariff break; 4461162922Sariff /*case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4462162922Sariff if (w->pflags & HDA_DAC_PATH) { 4463162922Sariff w->pflags |= HDA_ADC_PATH; 4464162922Sariff ret = 1; 4465162922Sariff } 4466162922Sariff break;*/ 4467162922Sariff default: 4468162922Sariff break; 4469162922Sariff } 4470162922Sariff return (ret); 4471162922Sariff} 4472162922Sariff 4473162922Sariffstatic uint32_t 4474162922Sariffhdac_audio_ctl_outamp_build(struct hdac_devinfo *devinfo, 4475162922Sariff nid_t nid, nid_t pnid, int index, int depth) 4476162922Sariff{ 4477162922Sariff struct hdac_widget *w, *pw; 4478162922Sariff struct hdac_audio_ctl *ctl; 4479162922Sariff uint32_t fl = 0; 4480162922Sariff int i, ossdev, conndev, strategy; 4481162922Sariff 4482162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4483162922Sariff return (0); 4484162922Sariff 4485162922Sariff w = hdac_widget_get(devinfo, nid); 4486162922Sariff if (w == NULL || w->enable == 0) 4487162922Sariff return (0); 4488162922Sariff 4489162922Sariff pw = hdac_widget_get(devinfo, pnid); 4490162922Sariff strategy = devinfo->function.audio.parsing_strategy; 4491162922Sariff 4492162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER 4493162922Sariff || w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) { 4494162922Sariff for (i = 0; i < w->nconns; i++) { 4495162922Sariff fl |= hdac_audio_ctl_outamp_build(devinfo, w->conns[i], 4496162922Sariff w->nid, i, depth + 1); 4497162922Sariff } 4498162922Sariff w->ctlflags |= fl; 4499162922Sariff return (fl); 4500162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT && 4501162922Sariff (w->pflags & HDA_DAC_PATH)) { 4502162922Sariff i = 0; 4503162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4504162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4505162922Sariff continue; 4506163057Sariff /* XXX This should be compressed! */ 4507169277Sariff if (((ctl->widget->nid == w->nid) || 4508162922Sariff (ctl->widget->nid == pnid && ctl->index == index && 4509162922Sariff (ctl->dir & HDA_CTL_IN)) || 4510162922Sariff (ctl->widget->nid == pnid && pw != NULL && 4511162922Sariff pw->type == 4512162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4513162922Sariff (pw->nconns < 2 || pw->selconn == index || 4514162922Sariff pw->selconn == -1) && 4515162922Sariff (ctl->dir & HDA_CTL_OUT)) || 4516162922Sariff (strategy == HDA_PARSE_DIRECT && 4517169277Sariff ctl->widget->nid == w->nid)) && 4518169277Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 4519163057Sariff /*if (pw != NULL && pw->selconn == -1) 4520162922Sariff pw->selconn = index; 4521162922Sariff fl |= SOUND_MASK_VOLUME; 4522162922Sariff fl |= SOUND_MASK_PCM; 4523162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4524162922Sariff ctl->ossmask |= SOUND_MASK_PCM; 4525163057Sariff ctl->ossdev = SOUND_MIXER_PCM;*/ 4526163057Sariff if (!(w->ctlflags & SOUND_MASK_PCM) || 4527163057Sariff (pw != NULL && 4528163057Sariff !(pw->ctlflags & SOUND_MASK_PCM))) { 4529163057Sariff fl |= SOUND_MASK_VOLUME; 4530163057Sariff fl |= SOUND_MASK_PCM; 4531163057Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4532163057Sariff ctl->ossmask |= SOUND_MASK_PCM; 4533163057Sariff ctl->ossdev = SOUND_MIXER_PCM; 4534163057Sariff w->ctlflags |= SOUND_MASK_VOLUME; 4535163057Sariff w->ctlflags |= SOUND_MASK_PCM; 4536163057Sariff if (pw != NULL) { 4537163057Sariff if (pw->selconn == -1) 4538163057Sariff pw->selconn = index; 4539163057Sariff pw->ctlflags |= 4540163057Sariff SOUND_MASK_VOLUME; 4541163057Sariff pw->ctlflags |= 4542163057Sariff SOUND_MASK_PCM; 4543163057Sariff } 4544163057Sariff } 4545162922Sariff } 4546162922Sariff } 4547162922Sariff w->ctlflags |= fl; 4548162922Sariff return (fl); 4549164614Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4550164614Sariff HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 4551162922Sariff (w->pflags & HDA_ADC_PATH)) { 4552162922Sariff conndev = w->wclass.pin.config & 4553162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4554162922Sariff i = 0; 4555162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4556162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4557162922Sariff continue; 4558163057Sariff /* XXX This should be compressed! */ 4559162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 4560162922Sariff (ctl->dir & HDA_CTL_IN)) || 4561162922Sariff (ctl->widget->nid == pnid && pw != NULL && 4562162922Sariff pw->type == 4563162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4564162922Sariff (pw->nconns < 2 || pw->selconn == index || 4565162922Sariff pw->selconn == -1) && 4566162922Sariff (ctl->dir & HDA_CTL_OUT)) || 4567162922Sariff (strategy == HDA_PARSE_DIRECT && 4568162922Sariff ctl->widget->nid == w->nid)) && 4569163057Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 4570162922Sariff if (pw != NULL && pw->selconn == -1) 4571162922Sariff pw->selconn = index; 4572162922Sariff ossdev = 0; 4573162922Sariff switch (conndev) { 4574162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 4575162922Sariff ossdev = SOUND_MIXER_MIC; 4576162922Sariff break; 4577162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 4578162922Sariff ossdev = SOUND_MIXER_LINE; 4579162922Sariff break; 4580162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 4581162922Sariff ossdev = SOUND_MIXER_CD; 4582162922Sariff break; 4583162922Sariff default: 4584162922Sariff ossdev = 4585162922Sariff hdac_audio_ctl_ossmixer_getnextdev( 4586162922Sariff devinfo); 4587162922Sariff if (ossdev < 0) 4588162922Sariff ossdev = 0; 4589162922Sariff break; 4590162922Sariff } 4591162922Sariff if (strategy == HDA_PARSE_MIXER) { 4592162922Sariff fl |= SOUND_MASK_VOLUME; 4593162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4594162922Sariff } 4595162922Sariff fl |= 1 << ossdev; 4596162922Sariff ctl->ossmask |= 1 << ossdev; 4597162922Sariff ctl->ossdev = ossdev; 4598162922Sariff } 4599162922Sariff } 4600162922Sariff w->ctlflags |= fl; 4601162922Sariff return (fl); 4602162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 4603162922Sariff i = 0; 4604162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4605162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4606162922Sariff continue; 4607163057Sariff /* XXX This should be compressed! */ 4608162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 4609162922Sariff (ctl->dir & HDA_CTL_IN)) || 4610162922Sariff (ctl->widget->nid == pnid && pw != NULL && 4611162922Sariff pw->type == 4612162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4613162922Sariff (pw->nconns < 2 || pw->selconn == index || 4614162922Sariff pw->selconn == -1) && 4615162922Sariff (ctl->dir & HDA_CTL_OUT)) || 4616162922Sariff (strategy == HDA_PARSE_DIRECT && 4617162922Sariff ctl->widget->nid == w->nid)) && 4618163057Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 4619162922Sariff if (pw != NULL && pw->selconn == -1) 4620162922Sariff pw->selconn = index; 4621162922Sariff fl |= SOUND_MASK_VOLUME; 4622162922Sariff fl |= SOUND_MASK_SPEAKER; 4623162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4624162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 4625162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 4626162922Sariff } 4627162922Sariff } 4628162922Sariff w->ctlflags |= fl; 4629162922Sariff return (fl); 4630162922Sariff } 4631162922Sariff return (0); 4632162922Sariff} 4633162922Sariff 4634162922Sariffstatic uint32_t 4635162922Sariffhdac_audio_ctl_inamp_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4636162922Sariff{ 4637162922Sariff struct hdac_widget *w, *cw; 4638162922Sariff struct hdac_audio_ctl *ctl; 4639162922Sariff uint32_t fl; 4640162922Sariff int i; 4641162922Sariff 4642162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4643162922Sariff return (0); 4644162922Sariff 4645162922Sariff w = hdac_widget_get(devinfo, nid); 4646162922Sariff if (w == NULL || w->enable == 0) 4647162922Sariff return (0); 4648162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 4649162922Sariff return (0); 4650162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 4651162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4652162922Sariff return (0);*/ 4653162922Sariff i = 0; 4654162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4655162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4656162922Sariff continue; 4657162922Sariff if (ctl->widget->nid == nid) { 4658162922Sariff ctl->ossmask |= SOUND_MASK_RECLEV; 4659162922Sariff w->ctlflags |= SOUND_MASK_RECLEV; 4660162922Sariff return (SOUND_MASK_RECLEV); 4661162922Sariff } 4662162922Sariff } 4663162922Sariff for (i = 0; i < w->nconns; i++) { 4664162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 4665162922Sariff if (cw == NULL || cw->enable == 0) 4666162922Sariff continue; 4667162922Sariff if (cw->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 4668162922Sariff continue; 4669162922Sariff fl = hdac_audio_ctl_inamp_build(devinfo, cw->nid, depth + 1); 4670162922Sariff if (fl != 0) { 4671162922Sariff cw->ctlflags |= fl; 4672162922Sariff w->ctlflags |= fl; 4673162922Sariff return (fl); 4674162922Sariff } 4675162922Sariff } 4676162922Sariff return (0); 4677162922Sariff} 4678162922Sariff 4679162922Sariffstatic int 4680162922Sariffhdac_audio_ctl_recsel_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4681162922Sariff{ 4682162922Sariff struct hdac_widget *w, *cw; 4683162922Sariff int i, child = 0; 4684162922Sariff 4685162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4686162922Sariff return (0); 4687162922Sariff 4688162922Sariff w = hdac_widget_get(devinfo, nid); 4689162922Sariff if (w == NULL || w->enable == 0) 4690162922Sariff return (0); 4691162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 4692162922Sariff return (0); 4693162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 4694162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4695162922Sariff return (0);*/ 4696162922Sariff /* XXX weak! */ 4697162922Sariff for (i = 0; i < w->nconns; i++) { 4698162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 4699162922Sariff if (cw == NULL) 4700162922Sariff continue; 4701162922Sariff if (++child > 1) { 4702162922Sariff w->pflags |= HDA_ADC_RECSEL; 4703162922Sariff return (1); 4704162922Sariff } 4705162922Sariff } 4706162922Sariff for (i = 0; i < w->nconns; i++) { 4707162922Sariff if (hdac_audio_ctl_recsel_build(devinfo, 4708162922Sariff w->conns[i], depth + 1) != 0) 4709162922Sariff return (1); 4710162922Sariff } 4711162922Sariff return (0); 4712162922Sariff} 4713162922Sariff 4714162922Sariffstatic int 4715162922Sariffhdac_audio_build_tree_strategy(struct hdac_devinfo *devinfo) 4716162922Sariff{ 4717162922Sariff struct hdac_widget *w, *cw; 4718162922Sariff int i, j, conndev, found_dac = 0; 4719162922Sariff int strategy; 4720162922Sariff 4721162922Sariff strategy = devinfo->function.audio.parsing_strategy; 4722162922Sariff 4723162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4724162922Sariff w = hdac_widget_get(devinfo, i); 4725162922Sariff if (w == NULL || w->enable == 0) 4726162922Sariff continue; 4727162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4728162922Sariff continue; 4729162922Sariff if (!HDA_PARAM_PIN_CAP_OUTPUT_CAP(w->wclass.pin.cap)) 4730162922Sariff continue; 4731162922Sariff conndev = w->wclass.pin.config & 4732162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4733162922Sariff if (!(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4734162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4735162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT)) 4736162922Sariff continue; 4737162922Sariff for (j = 0; j < w->nconns; j++) { 4738162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 4739162922Sariff if (cw == NULL || cw->enable == 0) 4740162922Sariff continue; 4741162922Sariff if (strategy == HDA_PARSE_MIXER && !(cw->type == 4742162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 4743162922Sariff cw->type == 4744162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4745162922Sariff continue; 4746162922Sariff if (hdac_widget_find_dac_path(devinfo, cw->nid, 0) 4747162922Sariff != 0) { 4748162922Sariff if (w->selconn == -1) 4749162922Sariff w->selconn = j; 4750162922Sariff w->pflags |= HDA_DAC_PATH; 4751162922Sariff found_dac++; 4752162922Sariff } 4753162922Sariff } 4754162922Sariff } 4755162922Sariff 4756162922Sariff return (found_dac); 4757162922Sariff} 4758162922Sariff 4759162922Sariffstatic void 4760162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 4761162922Sariff{ 4762162922Sariff struct hdac_widget *w; 4763162922Sariff struct hdac_audio_ctl *ctl; 4764162922Sariff int i, j, dacs, strategy; 4765162922Sariff 4766162922Sariff /* Construct DAC path */ 4767162922Sariff strategy = HDA_PARSE_MIXER; 4768162922Sariff devinfo->function.audio.parsing_strategy = strategy; 4769163057Sariff HDA_BOOTVERBOSE( 4770162922Sariff device_printf(devinfo->codec->sc->dev, 4771163057Sariff "HDA_DEBUG: HWiP: HDA Widget Parser - Revision %d\n", 4772162922Sariff HDA_WIDGET_PARSER_REV); 4773162922Sariff ); 4774162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 4775162922Sariff if (dacs == 0) { 4776163057Sariff HDA_BOOTVERBOSE( 4777162922Sariff device_printf(devinfo->codec->sc->dev, 4778163057Sariff "HDA_DEBUG: HWiP: 0 DAC path found! " 4779163057Sariff "Retrying parser " 4780162922Sariff "using HDA_PARSE_DIRECT strategy.\n"); 4781162922Sariff ); 4782162922Sariff strategy = HDA_PARSE_DIRECT; 4783162922Sariff devinfo->function.audio.parsing_strategy = strategy; 4784162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 4785162922Sariff } 4786162922Sariff 4787163057Sariff HDA_BOOTVERBOSE( 4788162922Sariff device_printf(devinfo->codec->sc->dev, 4789163057Sariff "HDA_DEBUG: HWiP: Found %d DAC path using HDA_PARSE_%s " 4790163057Sariff "strategy.\n", 4791162922Sariff dacs, (strategy == HDA_PARSE_MIXER) ? "MIXER" : "DIRECT"); 4792162922Sariff ); 4793162922Sariff 4794162922Sariff /* Construct ADC path */ 4795162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4796162922Sariff w = hdac_widget_get(devinfo, i); 4797162922Sariff if (w == NULL || w->enable == 0) 4798162922Sariff continue; 4799162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4800162922Sariff continue; 4801162922Sariff (void)hdac_widget_find_adc_path(devinfo, w->nid, 0); 4802162922Sariff } 4803162922Sariff 4804162922Sariff /* Output mixers */ 4805162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4806162922Sariff w = hdac_widget_get(devinfo, i); 4807162922Sariff if (w == NULL || w->enable == 0) 4808162922Sariff continue; 4809162922Sariff if ((strategy == HDA_PARSE_MIXER && 4810162922Sariff (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 4811162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 4812162922Sariff && (w->pflags & HDA_DAC_PATH)) || 4813162922Sariff (strategy == HDA_PARSE_DIRECT && (w->pflags & 4814162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)))) { 4815162922Sariff w->ctlflags |= hdac_audio_ctl_outamp_build(devinfo, 4816162922Sariff w->nid, devinfo->startnode - 1, 0, 0); 4817162922Sariff } else if (w->type == 4818162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 4819162922Sariff j = 0; 4820162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &j)) != 4821162922Sariff NULL) { 4822162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4823162922Sariff continue; 4824162922Sariff if (ctl->widget->nid != w->nid) 4825162922Sariff continue; 4826162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4827162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 4828162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 4829162922Sariff w->ctlflags |= SOUND_MASK_VOLUME; 4830162922Sariff w->ctlflags |= SOUND_MASK_SPEAKER; 4831162922Sariff } 4832162922Sariff } 4833162922Sariff } 4834162922Sariff 4835162922Sariff /* Input mixers (rec) */ 4836162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4837162922Sariff w = hdac_widget_get(devinfo, i); 4838162922Sariff if (w == NULL || w->enable == 0) 4839162922Sariff continue; 4840162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 4841162922Sariff w->pflags & HDA_ADC_PATH)) 4842162922Sariff continue; 4843162922Sariff hdac_audio_ctl_inamp_build(devinfo, w->nid, 0); 4844162922Sariff hdac_audio_ctl_recsel_build(devinfo, w->nid, 0); 4845162922Sariff } 4846162922Sariff} 4847162922Sariff 4848162922Sariff#define HDA_COMMIT_CONN (1 << 0) 4849162922Sariff#define HDA_COMMIT_CTRL (1 << 1) 4850162922Sariff#define HDA_COMMIT_EAPD (1 << 2) 4851162922Sariff#define HDA_COMMIT_GPIO (1 << 3) 4852169277Sariff#define HDA_COMMIT_MISC (1 << 4) 4853162922Sariff#define HDA_COMMIT_ALL (HDA_COMMIT_CONN | HDA_COMMIT_CTRL | \ 4854169277Sariff HDA_COMMIT_EAPD | HDA_COMMIT_GPIO | HDA_COMMIT_MISC) 4855162922Sariff 4856162922Sariffstatic void 4857162922Sariffhdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl) 4858162922Sariff{ 4859162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4860162922Sariff struct hdac_widget *w; 4861164750Sariff nid_t cad; 4862164750Sariff int i; 4863162922Sariff 4864162922Sariff if (!(cfl & HDA_COMMIT_ALL)) 4865162922Sariff return; 4866162922Sariff 4867162922Sariff cad = devinfo->codec->cad; 4868162922Sariff 4869169277Sariff if ((cfl & HDA_COMMIT_MISC)) { 4870169277Sariff if (sc->pci_subvendor == APPLE_INTEL_MAC) 4871169277Sariff hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 4872169277Sariff 0x7e7, 0), cad); 4873169277Sariff } 4874169277Sariff 4875163057Sariff if (cfl & HDA_COMMIT_GPIO) { 4876165039Sariff uint32_t gdata, gmask, gdir; 4877169277Sariff int commitgpio, numgpio; 4878164828Sariff 4879165039Sariff gdata = 0; 4880165039Sariff gmask = 0; 4881165039Sariff gdir = 0; 4882169277Sariff commitgpio = 0; 4883166796Sariff 4884169277Sariff numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 4885169277Sariff devinfo->function.audio.gpio); 4886165039Sariff 4887165039Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 4888169277Sariff commitgpio = (numgpio > 0) ? 1 : 0; 4889165039Sariff else { 4890169277Sariff for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 4891165039Sariff if (!(devinfo->function.audio.quirks & 4892165039Sariff (1 << i))) 4893165039Sariff continue; 4894165039Sariff if (commitgpio == 0) { 4895165039Sariff commitgpio = 1; 4896165039Sariff HDA_BOOTVERBOSE( 4897169277Sariff gdata = hdac_command(sc, 4898169277Sariff HDA_CMD_GET_GPIO_DATA(cad, 4899169277Sariff devinfo->nid), cad); 4900169277Sariff gmask = hdac_command(sc, 4901169277Sariff HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 4902169277Sariff devinfo->nid), cad); 4903169277Sariff gdir = hdac_command(sc, 4904169277Sariff HDA_CMD_GET_GPIO_DIRECTION(cad, 4905169277Sariff devinfo->nid), cad); 4906165039Sariff device_printf(sc->dev, 4907165039Sariff "GPIO init: data=0x%08x " 4908165039Sariff "mask=0x%08x dir=0x%08x\n", 4909165039Sariff gdata, gmask, gdir); 4910169277Sariff gdata = 0; 4911169277Sariff gmask = 0; 4912169277Sariff gdir = 0; 4913165039Sariff ); 4914165039Sariff } 4915165039Sariff gdata |= 1 << i; 4916165039Sariff gmask |= 1 << i; 4917165039Sariff gdir |= 1 << i; 4918165039Sariff } 4919165039Sariff } 4920165039Sariff 4921165039Sariff if (commitgpio != 0) { 4922165039Sariff HDA_BOOTVERBOSE( 4923165039Sariff device_printf(sc->dev, 4924165039Sariff "GPIO commit: data=0x%08x mask=0x%08x " 4925165039Sariff "dir=0x%08x\n", 4926165039Sariff gdata, gmask, gdir); 4927165039Sariff ); 4928162922Sariff hdac_command(sc, 4929164828Sariff HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 4930164828Sariff gmask), cad); 4931164828Sariff hdac_command(sc, 4932164828Sariff HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 4933164828Sariff gdir), cad); 4934164828Sariff hdac_command(sc, 4935164828Sariff HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 4936164828Sariff gdata), cad); 4937162922Sariff } 4938162922Sariff } 4939162922Sariff 4940162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 4941162922Sariff w = &devinfo->widget[i]; 4942162922Sariff if (w == NULL || w->enable == 0) 4943162922Sariff continue; 4944162922Sariff if (cfl & HDA_COMMIT_CONN) { 4945162922Sariff if (w->selconn == -1) 4946162922Sariff w->selconn = 0; 4947162922Sariff if (w->nconns > 0) 4948162922Sariff hdac_widget_connection_select(w, w->selconn); 4949162922Sariff } 4950162922Sariff if ((cfl & HDA_COMMIT_CTRL) && 4951162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 4952169277Sariff uint32_t pincap; 4953169277Sariff 4954169277Sariff pincap = w->wclass.pin.cap; 4955169277Sariff 4956162922Sariff if ((w->pflags & (HDA_DAC_PATH | HDA_ADC_PATH)) == 4957162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)) 4958162922Sariff device_printf(sc->dev, "WARNING: node %d " 4959162922Sariff "participate both for DAC/ADC!\n", w->nid); 4960162922Sariff if (w->pflags & HDA_DAC_PATH) { 4961162922Sariff w->wclass.pin.ctrl &= 4962162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 4963162922Sariff if ((w->wclass.pin.config & 4964162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) != 4965162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 4966162922Sariff w->wclass.pin.ctrl &= 4967162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 4968169277Sariff if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 4969169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 4970169277Sariff w->wclass.pin.ctrl |= 4971169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 4972169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 4973169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 4974169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 4975169277Sariff w->wclass.pin.ctrl |= 4976169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 4977169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 4978169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 4979169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 4980169277Sariff w->wclass.pin.ctrl |= 4981169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 4982169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 4983162922Sariff } else if (w->pflags & HDA_ADC_PATH) { 4984162922Sariff w->wclass.pin.ctrl &= 4985162922Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 4986162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE); 4987169277Sariff if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 4988169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 4989169277Sariff w->wclass.pin.ctrl |= 4990169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 4991169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 4992169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 4993169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 4994169277Sariff w->wclass.pin.ctrl |= 4995169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 4996169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 4997169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 4998169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 4999169277Sariff w->wclass.pin.ctrl |= 5000169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5001169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5002162922Sariff } else 5003162922Sariff w->wclass.pin.ctrl &= ~( 5004162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 5005162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 5006165069Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 5007165069Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 5008162922Sariff hdac_command(sc, 5009162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 5010162922Sariff w->wclass.pin.ctrl), cad); 5011162922Sariff } 5012162922Sariff if ((cfl & HDA_COMMIT_EAPD) && 5013163276Sariff w->param.eapdbtl != HDAC_INVALID) { 5014163432Sariff uint32_t val; 5015163432Sariff 5016163432Sariff val = w->param.eapdbtl; 5017163276Sariff if (devinfo->function.audio.quirks & 5018163432Sariff HDA_QUIRK_EAPDINV) 5019163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 5020162922Sariff hdac_command(sc, 5021162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 5022163432Sariff val), cad); 5023162922Sariff 5024163276Sariff } 5025162922Sariff DELAY(1000); 5026162922Sariff } 5027162922Sariff} 5028162922Sariff 5029162922Sariffstatic void 5030162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 5031162922Sariff{ 5032162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5033162922Sariff struct hdac_audio_ctl *ctl; 5034162922Sariff int i; 5035162922Sariff 5036162922Sariff devinfo->function.audio.mvol = 100 | (100 << 8); 5037162922Sariff i = 0; 5038162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5039162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) { 5040163057Sariff HDA_BOOTVERBOSE( 5041162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 5042162922Sariff i, (ctl->widget != NULL) ? 5043162922Sariff ctl->widget->nid : -1); 5044162922Sariff if (ctl->childwidget != NULL) 5045162922Sariff printf(" childnid=%d", 5046162922Sariff ctl->childwidget->nid); 5047162922Sariff if (ctl->widget == NULL) 5048162922Sariff printf(" NULL WIDGET!"); 5049162922Sariff printf(" DISABLED\n"); 5050162922Sariff ); 5051162922Sariff continue; 5052162922Sariff } 5053163057Sariff HDA_BOOTVERBOSE( 5054162922Sariff if (ctl->ossmask == 0) { 5055162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 5056162922Sariff i, ctl->widget->nid); 5057162922Sariff if (ctl->childwidget != NULL) 5058162922Sariff printf(" childnid=%d", 5059162922Sariff ctl->childwidget->nid); 5060162922Sariff printf(" Bind to NONE\n"); 5061166294Sariff } 5062162922Sariff ); 5063162922Sariff if (ctl->step > 0) { 5064162922Sariff ctl->ossval = (ctl->left * 100) / ctl->step; 5065162922Sariff ctl->ossval |= ((ctl->right * 100) / ctl->step) << 8; 5066162922Sariff } else 5067162922Sariff ctl->ossval = 0; 5068162922Sariff hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT, 5069162922Sariff ctl->left, ctl->right); 5070162922Sariff } 5071162922Sariff} 5072162922Sariff 5073162922Sariffstatic int 5074162922Sariffhdac_pcmchannel_setup(struct hdac_devinfo *devinfo, int dir) 5075162922Sariff{ 5076162922Sariff struct hdac_chan *ch; 5077162922Sariff struct hdac_widget *w; 5078162922Sariff uint32_t cap, fmtcap, pcmcap, path; 5079162922Sariff int i, type, ret, max; 5080162922Sariff 5081162922Sariff if (dir == PCMDIR_PLAY) { 5082162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT; 5083162922Sariff ch = &devinfo->codec->sc->play; 5084162922Sariff path = HDA_DAC_PATH; 5085162922Sariff } else { 5086162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT; 5087162922Sariff ch = &devinfo->codec->sc->rec; 5088162922Sariff path = HDA_ADC_PATH; 5089162922Sariff } 5090162922Sariff 5091162922Sariff ch->caps = hdac_caps; 5092162922Sariff ch->caps.fmtlist = ch->fmtlist; 5093162922Sariff ch->bit16 = 1; 5094162922Sariff ch->bit32 = 0; 5095162922Sariff ch->pcmrates[0] = 48000; 5096162922Sariff ch->pcmrates[1] = 0; 5097162922Sariff 5098162922Sariff ret = 0; 5099162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 5100162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 5101162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 5102162922Sariff 5103162922Sariff for (i = devinfo->startnode; i < devinfo->endnode && ret < max; i++) { 5104162922Sariff w = hdac_widget_get(devinfo, i); 5105162922Sariff if (w == NULL || w->enable == 0 || w->type != type || 5106163057Sariff !(w->pflags & path)) 5107162922Sariff continue; 5108162922Sariff cap = w->param.widget_cap; 5109162922Sariff /*if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(cap)) 5110162922Sariff continue;*/ 5111162922Sariff if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(cap)) 5112162922Sariff continue; 5113162922Sariff cap = w->param.supp_stream_formats; 5114162922Sariff /*if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) { 5115162922Sariff } 5116162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 5117162922Sariff }*/ 5118162922Sariff if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 5119162922Sariff continue; 5120164614Sariff if (ret == 0) { 5121164614Sariff fmtcap = w->param.supp_stream_formats; 5122164614Sariff pcmcap = w->param.supp_pcm_size_rate; 5123164614Sariff } else { 5124164614Sariff fmtcap &= w->param.supp_stream_formats; 5125164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 5126164614Sariff } 5127162922Sariff ch->io[ret++] = i; 5128162922Sariff } 5129162922Sariff ch->io[ret] = -1; 5130162922Sariff 5131162922Sariff ch->supp_stream_formats = fmtcap; 5132162922Sariff ch->supp_pcm_size_rate = pcmcap; 5133162922Sariff 5134162922Sariff /* 5135162922Sariff * 8bit = 0 5136162922Sariff * 16bit = 1 5137162922Sariff * 20bit = 2 5138162922Sariff * 24bit = 3 5139162922Sariff * 32bit = 4 5140162922Sariff */ 5141162922Sariff if (ret > 0) { 5142162922Sariff cap = pcmcap; 5143162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 5144162922Sariff ch->bit16 = 1; 5145162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 5146162922Sariff ch->bit16 = 0; 5147162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 5148162922Sariff ch->bit32 = 4; 5149162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 5150162922Sariff ch->bit32 = 3; 5151162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 5152162922Sariff ch->bit32 = 2; 5153162922Sariff i = 0; 5154162922Sariff if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 5155162922Sariff ch->fmtlist[i++] = AFMT_S16_LE; 5156162922Sariff ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 5157162922Sariff if (ch->bit32 > 0) { 5158162922Sariff if (!(devinfo->function.audio.quirks & 5159162922Sariff HDA_QUIRK_FORCESTEREO)) 5160162922Sariff ch->fmtlist[i++] = AFMT_S32_LE; 5161162922Sariff ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 5162162922Sariff } 5163162922Sariff ch->fmtlist[i] = 0; 5164162922Sariff i = 0; 5165162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 5166162922Sariff ch->pcmrates[i++] = 8000; 5167162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 5168162922Sariff ch->pcmrates[i++] = 11025; 5169162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 5170162922Sariff ch->pcmrates[i++] = 16000; 5171162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 5172162922Sariff ch->pcmrates[i++] = 22050; 5173162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 5174162922Sariff ch->pcmrates[i++] = 32000; 5175162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 5176162922Sariff ch->pcmrates[i++] = 44100; 5177162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(cap)) */ 5178162922Sariff ch->pcmrates[i++] = 48000; 5179162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 5180162922Sariff ch->pcmrates[i++] = 88200; 5181162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 5182162922Sariff ch->pcmrates[i++] = 96000; 5183162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 5184162922Sariff ch->pcmrates[i++] = 176400; 5185162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 5186162922Sariff ch->pcmrates[i++] = 192000; 5187162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(cap)) */ 5188162922Sariff ch->pcmrates[i] = 0; 5189162922Sariff if (i > 0) { 5190162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 5191162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 5192162922Sariff } 5193162922Sariff } 5194162922Sariff 5195162922Sariff return (ret); 5196162922Sariff} 5197162922Sariff 5198162922Sariffstatic void 5199162922Sariffhdac_dump_ctls(struct hdac_devinfo *devinfo, const char *banner, uint32_t flag) 5200162922Sariff{ 5201162922Sariff struct hdac_audio_ctl *ctl; 5202162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5203162922Sariff int i; 5204162922Sariff uint32_t fl = 0; 5205162922Sariff 5206162922Sariff 5207162922Sariff if (flag == 0) { 5208162922Sariff fl = SOUND_MASK_VOLUME | SOUND_MASK_PCM | 5209162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 5210162922Sariff SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN; 5211162922Sariff } 5212162922Sariff 5213162922Sariff i = 0; 5214162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5215162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 5216169277Sariff ctl->widget->enable == 0 || (ctl->ossmask & 5217169277Sariff (SOUND_MASK_SKIP | SOUND_MASK_DISABLE))) 5218162922Sariff continue; 5219162922Sariff if ((flag == 0 && (ctl->ossmask & ~fl)) || 5220162922Sariff (flag != 0 && (ctl->ossmask & flag))) { 5221162922Sariff if (banner != NULL) { 5222162922Sariff device_printf(sc->dev, "\n"); 5223162922Sariff device_printf(sc->dev, "%s\n", banner); 5224162922Sariff } 5225162922Sariff goto hdac_ctl_dump_it_all; 5226162922Sariff } 5227162922Sariff } 5228162922Sariff 5229162922Sariff return; 5230162922Sariff 5231162922Sariffhdac_ctl_dump_it_all: 5232162922Sariff i = 0; 5233162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5234162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 5235162922Sariff ctl->widget->enable == 0) 5236162922Sariff continue; 5237162922Sariff if (!((flag == 0 && (ctl->ossmask & ~fl)) || 5238162922Sariff (flag != 0 && (ctl->ossmask & flag)))) 5239162922Sariff continue; 5240162922Sariff if (flag == 0) { 5241162922Sariff device_printf(sc->dev, "\n"); 5242162922Sariff device_printf(sc->dev, "Unknown Ctl (OSS: %s)\n", 5243162922Sariff hdac_audio_ctl_ossmixer_mask2name(ctl->ossmask)); 5244162922Sariff } 5245162922Sariff device_printf(sc->dev, " |\n"); 5246162922Sariff device_printf(sc->dev, " +- nid: %2d index: %2d ", 5247162922Sariff ctl->widget->nid, ctl->index); 5248162922Sariff if (ctl->childwidget != NULL) 5249162922Sariff printf("(nid: %2d) ", ctl->childwidget->nid); 5250162922Sariff else 5251162922Sariff printf(" "); 5252162922Sariff printf("mute: %d step: %3d size: %3d off: %3d dir=0x%x ossmask=0x%08x\n", 5253162922Sariff ctl->mute, ctl->step, ctl->size, ctl->offset, ctl->dir, 5254162922Sariff ctl->ossmask); 5255162922Sariff } 5256162922Sariff} 5257162922Sariff 5258162922Sariffstatic void 5259162922Sariffhdac_dump_audio_formats(struct hdac_softc *sc, uint32_t fcap, uint32_t pcmcap) 5260162922Sariff{ 5261162922Sariff uint32_t cap; 5262162922Sariff 5263162922Sariff cap = fcap; 5264162922Sariff if (cap != 0) { 5265162922Sariff device_printf(sc->dev, " Stream cap: 0x%08x\n", cap); 5266162922Sariff device_printf(sc->dev, " Format:"); 5267162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 5268162922Sariff printf(" AC3"); 5269162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 5270162922Sariff printf(" FLOAT32"); 5271162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 5272162922Sariff printf(" PCM"); 5273162922Sariff printf("\n"); 5274162922Sariff } 5275162922Sariff cap = pcmcap; 5276162922Sariff if (cap != 0) { 5277162922Sariff device_printf(sc->dev, " PCM cap: 0x%08x\n", cap); 5278162922Sariff device_printf(sc->dev, " PCM size:"); 5279162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 5280162922Sariff printf(" 8"); 5281162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 5282162922Sariff printf(" 16"); 5283162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 5284162922Sariff printf(" 20"); 5285162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 5286162922Sariff printf(" 24"); 5287162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 5288162922Sariff printf(" 32"); 5289162922Sariff printf("\n"); 5290162922Sariff device_printf(sc->dev, " PCM rate:"); 5291162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 5292162922Sariff printf(" 8"); 5293162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 5294162922Sariff printf(" 11"); 5295162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 5296162922Sariff printf(" 16"); 5297162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 5298162922Sariff printf(" 22"); 5299162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 5300162922Sariff printf(" 32"); 5301162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 5302162922Sariff printf(" 44"); 5303162922Sariff printf(" 48"); 5304162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 5305162922Sariff printf(" 88"); 5306162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 5307162922Sariff printf(" 96"); 5308162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 5309162922Sariff printf(" 176"); 5310162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 5311162922Sariff printf(" 192"); 5312162922Sariff printf("\n"); 5313162922Sariff } 5314162922Sariff} 5315162922Sariff 5316162922Sariffstatic void 5317162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 5318162922Sariff{ 5319162922Sariff uint32_t pincap, wcap; 5320162922Sariff 5321162922Sariff pincap = w->wclass.pin.cap; 5322162922Sariff wcap = w->param.widget_cap; 5323162922Sariff 5324162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 5325162922Sariff device_printf(sc->dev, " "); 5326162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 5327162922Sariff printf(" ISC"); 5328162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 5329162922Sariff printf(" TRQD"); 5330162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 5331162922Sariff printf(" PDC"); 5332162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 5333162922Sariff printf(" HP"); 5334162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 5335162922Sariff printf(" OUT"); 5336162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 5337162922Sariff printf(" IN"); 5338162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 5339162922Sariff printf(" BAL"); 5340165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 5341165069Sariff printf(" VREF["); 5342165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5343165069Sariff printf(" 50"); 5344165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5345165069Sariff printf(" 80"); 5346165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5347165069Sariff printf(" 100"); 5348165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 5349165069Sariff printf(" GROUND"); 5350165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 5351165069Sariff printf(" HIZ"); 5352165069Sariff printf(" ]"); 5353165069Sariff } 5354162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 5355162922Sariff printf(" EAPD"); 5356162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(wcap)) 5357162922Sariff printf(" : UNSOL"); 5358162922Sariff printf("\n"); 5359162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 5360162922Sariff w->wclass.pin.config); 5361162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 5362162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 5363162922Sariff printf(" HP"); 5364162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 5365162922Sariff printf(" IN"); 5366162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 5367162922Sariff printf(" OUT"); 5368162922Sariff printf("\n"); 5369162922Sariff} 5370162922Sariff 5371162922Sariffstatic void 5372162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 5373162922Sariff{ 5374163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 5375162922Sariff device_printf(sc->dev, " " 5376162922Sariff "mute=%d step=%d size=%d offset=%d\n", 5377162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 5378162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 5379162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 5380162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 5381162922Sariff} 5382162922Sariff 5383162922Sariffstatic void 5384162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 5385162922Sariff{ 5386162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5387162922Sariff struct hdac_widget *w, *cw; 5388162922Sariff int i, j; 5389162922Sariff 5390162922Sariff device_printf(sc->dev, "\n"); 5391162922Sariff device_printf(sc->dev, "Default Parameter\n"); 5392162922Sariff device_printf(sc->dev, "-----------------\n"); 5393162922Sariff hdac_dump_audio_formats(sc, 5394162922Sariff devinfo->function.audio.supp_stream_formats, 5395162922Sariff devinfo->function.audio.supp_pcm_size_rate); 5396162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 5397162922Sariff devinfo->function.audio.inamp_cap); 5398162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 5399162922Sariff devinfo->function.audio.outamp_cap); 5400162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5401162922Sariff w = hdac_widget_get(devinfo, i); 5402162922Sariff if (w == NULL) { 5403162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 5404162922Sariff continue; 5405162922Sariff } 5406162922Sariff device_printf(sc->dev, "\n"); 5407162922Sariff device_printf(sc->dev, " nid: %d [%s]%s\n", w->nid, 5408162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) ? 5409162922Sariff "DIGITAL" : "ANALOG", 5410162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 5411162922Sariff device_printf(sc->dev, " name: %s\n", w->name); 5412162922Sariff device_printf(sc->dev, " widget_cap: 0x%08x\n", 5413162922Sariff w->param.widget_cap); 5414162922Sariff device_printf(sc->dev, " Parse flags: 0x%08x\n", 5415162922Sariff w->pflags); 5416162922Sariff device_printf(sc->dev, " Ctl flags: 0x%08x\n", 5417162922Sariff w->ctlflags); 5418162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 5419162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 5420162922Sariff hdac_dump_audio_formats(sc, 5421162922Sariff w->param.supp_stream_formats, 5422162922Sariff w->param.supp_pcm_size_rate); 5423162922Sariff } else if (w->type == 5424162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5425162922Sariff hdac_dump_pin(sc, w); 5426162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 5427162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 5428162922Sariff w->param.eapdbtl); 5429163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 5430163057Sariff w->param.outamp_cap != 0) 5431162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 5432163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 5433163057Sariff w->param.inamp_cap != 0) 5434162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 5435162922Sariff device_printf(sc->dev, " connections: %d\n", w->nconns); 5436162922Sariff for (j = 0; j < w->nconns; j++) { 5437162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 5438162922Sariff device_printf(sc->dev, " |\n"); 5439162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 5440162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 5441162922Sariff if (cw == NULL) 5442162922Sariff printf(" [UNKNOWN]"); 5443162922Sariff else if (cw->enable == 0) 5444162922Sariff printf(" [DISABLED]"); 5445162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 5446162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5447162922Sariff printf(" (selected)"); 5448162922Sariff printf("\n"); 5449162922Sariff } 5450162922Sariff } 5451162922Sariff 5452162922Sariff} 5453162922Sariff 5454163057Sariffstatic int 5455163057Sariffhdac_dump_dac_internal(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5456163057Sariff{ 5457163057Sariff struct hdac_widget *w, *cw; 5458163057Sariff struct hdac_softc *sc = devinfo->codec->sc; 5459163057Sariff int i; 5460163057Sariff 5461163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 5462163057Sariff return (0); 5463163057Sariff 5464163057Sariff w = hdac_widget_get(devinfo, nid); 5465163057Sariff if (w == NULL || w->enable == 0 || !(w->pflags & HDA_DAC_PATH)) 5466163057Sariff return (0); 5467163057Sariff 5468163057Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5469163057Sariff device_printf(sc->dev, "\n"); 5470163057Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 5471163057Sariff device_printf(sc->dev, " ^\n"); 5472163057Sariff device_printf(sc->dev, " |\n"); 5473163057Sariff device_printf(sc->dev, " +-----<------+\n"); 5474163057Sariff } else { 5475163057Sariff device_printf(sc->dev, " ^\n"); 5476163057Sariff device_printf(sc->dev, " |\n"); 5477163057Sariff device_printf(sc->dev, " "); 5478163057Sariff printf(" nid=%d [%s]\n", w->nid, w->name); 5479163057Sariff } 5480163057Sariff 5481163057Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) { 5482163057Sariff return (1); 5483163057Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 5484163057Sariff for (i = 0; i < w->nconns; i++) { 5485163057Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 5486163057Sariff if (cw == NULL || cw->enable == 0 || cw->type == 5487163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5488163057Sariff continue; 5489163057Sariff if (hdac_dump_dac_internal(devinfo, cw->nid, 5490163057Sariff depth + 1) != 0) 5491163057Sariff return (1); 5492163057Sariff } 5493163057Sariff } else if ((w->type == 5494163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR || 5495163057Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5496163057Sariff w->selconn > -1 && w->selconn < w->nconns) { 5497163057Sariff if (hdac_dump_dac_internal(devinfo, w->conns[w->selconn], 5498163057Sariff depth + 1) != 0) 5499163057Sariff return (1); 5500163057Sariff } 5501163057Sariff 5502163057Sariff return (0); 5503163057Sariff} 5504163057Sariff 5505162922Sariffstatic void 5506162922Sariffhdac_dump_dac(struct hdac_devinfo *devinfo) 5507162922Sariff{ 5508163057Sariff struct hdac_widget *w; 5509163057Sariff struct hdac_softc *sc = devinfo->codec->sc; 5510163057Sariff int i, printed = 0; 5511163057Sariff 5512163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5513163057Sariff w = hdac_widget_get(devinfo, i); 5514163057Sariff if (w == NULL || w->enable == 0) 5515163057Sariff continue; 5516163057Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 5517163057Sariff !(w->pflags & HDA_DAC_PATH)) 5518163057Sariff continue; 5519163057Sariff if (printed == 0) { 5520163057Sariff printed = 1; 5521163057Sariff device_printf(sc->dev, "\n"); 5522163057Sariff device_printf(sc->dev, "Playback path:\n"); 5523163057Sariff } 5524163057Sariff hdac_dump_dac_internal(devinfo, w->nid, 0); 5525163057Sariff } 5526162922Sariff} 5527162922Sariff 5528162922Sariffstatic void 5529162922Sariffhdac_dump_adc(struct hdac_devinfo *devinfo) 5530162922Sariff{ 5531162922Sariff struct hdac_widget *w, *cw; 5532162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5533162922Sariff int i, j; 5534162922Sariff int printed = 0; 5535162922Sariff char ossdevs[256]; 5536162922Sariff 5537162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5538162922Sariff w = hdac_widget_get(devinfo, i); 5539162922Sariff if (w == NULL || w->enable == 0) 5540162922Sariff continue; 5541162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 5542162922Sariff continue; 5543162922Sariff if (printed == 0) { 5544162922Sariff printed = 1; 5545162922Sariff device_printf(sc->dev, "\n"); 5546162922Sariff device_printf(sc->dev, "Recording sources:\n"); 5547162922Sariff } 5548162922Sariff device_printf(sc->dev, "\n"); 5549162922Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 5550162922Sariff for (j = 0; j < w->nconns; j++) { 5551162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 5552162922Sariff if (cw == NULL || cw->enable == 0) 5553162922Sariff continue; 5554162922Sariff hdac_audio_ctl_ossmixer_mask2allname(cw->ctlflags, 5555162922Sariff ossdevs, sizeof(ossdevs)); 5556162922Sariff device_printf(sc->dev, " |\n"); 5557162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 5558162922Sariff cw->nid, cw->name); 5559162922Sariff if (strlen(ossdevs) > 0) { 5560162922Sariff printf(" [recsrc: %s]", ossdevs); 5561162922Sariff } 5562162922Sariff printf("\n"); 5563162922Sariff } 5564162922Sariff } 5565162922Sariff} 5566162922Sariff 5567162922Sariffstatic void 5568162922Sariffhdac_dump_pcmchannels(struct hdac_softc *sc, int pcnt, int rcnt) 5569162922Sariff{ 5570162922Sariff nid_t *nids; 5571162922Sariff 5572162922Sariff if (pcnt > 0) { 5573162922Sariff device_printf(sc->dev, "\n"); 5574162922Sariff device_printf(sc->dev, " PCM Playback: %d\n", pcnt); 5575162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 5576162922Sariff sc->play.supp_pcm_size_rate); 5577162922Sariff device_printf(sc->dev, " DAC:"); 5578162922Sariff for (nids = sc->play.io; *nids != -1; nids++) 5579162922Sariff printf(" %d", *nids); 5580162922Sariff printf("\n"); 5581162922Sariff } 5582162922Sariff 5583162922Sariff if (rcnt > 0) { 5584162922Sariff device_printf(sc->dev, "\n"); 5585162922Sariff device_printf(sc->dev, " PCM Record: %d\n", rcnt); 5586162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 5587162922Sariff sc->rec.supp_pcm_size_rate); 5588162922Sariff device_printf(sc->dev, " ADC:"); 5589162922Sariff for (nids = sc->rec.io; *nids != -1; nids++) 5590162922Sariff printf(" %d", *nids); 5591162922Sariff printf("\n"); 5592162922Sariff } 5593162922Sariff} 5594162922Sariff 5595162922Sariffstatic void 5596163057Sariffhdac_release_resources(struct hdac_softc *sc) 5597163057Sariff{ 5598163057Sariff struct hdac_devinfo *devinfo = NULL; 5599163057Sariff device_t *devlist = NULL; 5600163057Sariff int i, devcount; 5601163057Sariff 5602163057Sariff if (sc == NULL) 5603163057Sariff return; 5604163057Sariff 5605163057Sariff hdac_lock(sc); 5606169277Sariff sc->polling = 0; 5607169277Sariff sc->poll_ival = 0; 5608169277Sariff callout_stop(&sc->poll_hdac); 5609169277Sariff callout_stop(&sc->poll_jack); 5610163057Sariff hdac_reset(sc); 5611163057Sariff hdac_unlock(sc); 5612169277Sariff callout_drain(&sc->poll_hdac); 5613169277Sariff callout_drain(&sc->poll_jack); 5614163057Sariff 5615169277Sariff hdac_irq_free(sc); 5616169277Sariff 5617163057Sariff device_get_children(sc->dev, &devlist, &devcount); 5618163057Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 5619163057Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 5620163057Sariff if (devinfo == NULL) 5621163057Sariff continue; 5622163057Sariff if (devinfo->widget != NULL) 5623163057Sariff free(devinfo->widget, M_HDAC); 5624163057Sariff if (devinfo->node_type == 5625163057Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 5626163057Sariff devinfo->function.audio.ctl != NULL) 5627163057Sariff free(devinfo->function.audio.ctl, M_HDAC); 5628163057Sariff free(devinfo, M_HDAC); 5629163057Sariff device_delete_child(sc->dev, devlist[i]); 5630163057Sariff } 5631163057Sariff if (devlist != NULL) 5632163057Sariff free(devlist, M_TEMP); 5633163057Sariff 5634163057Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) { 5635163057Sariff if (sc->codecs[i] != NULL) 5636163057Sariff free(sc->codecs[i], M_HDAC); 5637163057Sariff sc->codecs[i] = NULL; 5638163057Sariff } 5639163057Sariff 5640169277Sariff hdac_dma_free(sc, &sc->pos_dma); 5641169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 5642169277Sariff hdac_dma_free(sc, &sc->corb_dma); 5643163057Sariff if (sc->play.blkcnt > 0) 5644169277Sariff hdac_dma_free(sc, &sc->play.bdl_dma); 5645163057Sariff if (sc->rec.blkcnt > 0) 5646169277Sariff hdac_dma_free(sc, &sc->rec.bdl_dma); 5647167702Sariff if (sc->chan_dmat != NULL) { 5648167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 5649167702Sariff sc->chan_dmat = NULL; 5650167702Sariff } 5651163057Sariff hdac_mem_free(sc); 5652169277Sariff snd_mtxfree(sc->lock); 5653163057Sariff free(sc, M_DEVBUF); 5654163057Sariff} 5655163057Sariff 5656163057Sariff/* This function surely going to make its way into upper level someday. */ 5657163057Sariffstatic void 5658163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 5659163057Sariff{ 5660163057Sariff const char *res = NULL; 5661163057Sariff int i = 0, j, k, len, inv; 5662163057Sariff 5663163057Sariff if (on != NULL) 5664163057Sariff *on = 0; 5665163057Sariff if (off != NULL) 5666163057Sariff *off = 0; 5667163057Sariff if (sc == NULL) 5668163057Sariff return; 5669163057Sariff if (resource_string_value(device_get_name(sc->dev), 5670163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 5671163057Sariff return; 5672163057Sariff if (!(res != NULL && strlen(res) > 0)) 5673163057Sariff return; 5674163057Sariff HDA_BOOTVERBOSE( 5675163057Sariff device_printf(sc->dev, "HDA_DEBUG: HDA Config:"); 5676163057Sariff ); 5677163057Sariff for (;;) { 5678163057Sariff while (res[i] != '\0' && 5679163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 5680163057Sariff i++; 5681163057Sariff if (res[i] == '\0') { 5682163057Sariff HDA_BOOTVERBOSE( 5683163057Sariff printf("\n"); 5684163057Sariff ); 5685163057Sariff return; 5686163057Sariff } 5687163057Sariff j = i; 5688163057Sariff while (res[j] != '\0' && 5689163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 5690163057Sariff j++; 5691163057Sariff len = j - i; 5692163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 5693163057Sariff inv = 2; 5694163057Sariff else 5695163057Sariff inv = 0; 5696163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 5697163057Sariff if (strncmp(res + i + inv, 5698163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 5699163057Sariff continue; 5700163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 5701163057Sariff break; 5702163057Sariff HDA_BOOTVERBOSE( 5703163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 5704163057Sariff hdac_quirks_tab[k].key); 5705163057Sariff ); 5706163057Sariff if (inv == 0 && on != NULL) 5707163057Sariff *on |= hdac_quirks_tab[k].value; 5708163057Sariff else if (inv != 0 && off != NULL) 5709163057Sariff *off |= hdac_quirks_tab[k].value; 5710163057Sariff break; 5711163057Sariff } 5712163057Sariff i = j; 5713163057Sariff } 5714163057Sariff} 5715163057Sariff 5716164614Sariff#ifdef SND_DYNSYSCTL 5717164614Sariffstatic int 5718164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 5719164614Sariff{ 5720164614Sariff struct hdac_softc *sc; 5721164614Sariff struct hdac_devinfo *devinfo; 5722164614Sariff device_t dev; 5723164614Sariff uint32_t ctl; 5724164614Sariff int err, val; 5725164614Sariff 5726164614Sariff dev = oidp->oid_arg1; 5727164614Sariff devinfo = pcm_getdevinfo(dev); 5728164614Sariff if (devinfo == NULL || devinfo->codec == NULL || 5729164614Sariff devinfo->codec->sc == NULL) 5730164614Sariff return (EINVAL); 5731164614Sariff sc = devinfo->codec->sc; 5732164614Sariff hdac_lock(sc); 5733164614Sariff val = sc->polling; 5734164614Sariff hdac_unlock(sc); 5735170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 5736164614Sariff 5737169277Sariff if (err != 0 || req->newptr == NULL) 5738164614Sariff return (err); 5739164614Sariff if (val < 0 || val > 1) 5740164614Sariff return (EINVAL); 5741164614Sariff 5742164614Sariff hdac_lock(sc); 5743164614Sariff if (val != sc->polling) { 5744164614Sariff if (hda_chan_active(sc) != 0) 5745164614Sariff err = EBUSY; 5746164614Sariff else if (val == 0) { 5747164614Sariff callout_stop(&sc->poll_hdac); 5748169277Sariff hdac_unlock(sc); 5749169277Sariff callout_drain(&sc->poll_hdac); 5750169277Sariff hdac_lock(sc); 5751164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 5752164614Sariff sc->rirb_size / 2); 5753164614Sariff ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 5754164614Sariff ctl |= HDAC_RIRBCTL_RINTCTL; 5755164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl); 5756164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 5757164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 5758164614Sariff sc->polling = 0; 5759164614Sariff DELAY(1000); 5760164614Sariff } else { 5761164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 0); 5762164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 0); 5763164614Sariff ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 5764164614Sariff ctl &= ~HDAC_RIRBCTL_RINTCTL; 5765164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl); 5766164614Sariff callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, 5767164614Sariff sc); 5768164614Sariff sc->polling = 1; 5769164614Sariff DELAY(1000); 5770164614Sariff } 5771164614Sariff } 5772164614Sariff hdac_unlock(sc); 5773164614Sariff 5774164614Sariff return (err); 5775164614Sariff} 5776169277Sariff 5777169277Sariffstatic int 5778169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 5779169277Sariff{ 5780169277Sariff struct hdac_softc *sc; 5781169277Sariff struct hdac_devinfo *devinfo; 5782169277Sariff device_t dev; 5783169277Sariff int err, val; 5784169277Sariff 5785169277Sariff dev = oidp->oid_arg1; 5786169277Sariff devinfo = pcm_getdevinfo(dev); 5787169277Sariff if (devinfo == NULL || devinfo->codec == NULL || 5788169277Sariff devinfo->codec->sc == NULL) 5789169277Sariff return (EINVAL); 5790169277Sariff sc = devinfo->codec->sc; 5791169277Sariff hdac_lock(sc); 5792169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 5793169277Sariff hdac_unlock(sc); 5794170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 5795169277Sariff 5796169277Sariff if (err != 0 || req->newptr == NULL) 5797169277Sariff return (err); 5798169277Sariff 5799169277Sariff if (val < 1) 5800169277Sariff val = 1; 5801169277Sariff if (val > 5000) 5802169277Sariff val = 5000; 5803169277Sariff val = ((uint64_t)val * hz) / 1000; 5804169277Sariff if (val < 1) 5805169277Sariff val = 1; 5806169277Sariff if (val > (hz * 5)) 5807169277Sariff val = hz * 5; 5808169277Sariff 5809169277Sariff hdac_lock(sc); 5810169277Sariff sc->poll_ival = val; 5811169277Sariff hdac_unlock(sc); 5812169277Sariff 5813169277Sariff return (err); 5814169277Sariff} 5815169277Sariff 5816169277Sariff#ifdef SND_DEBUG 5817169277Sariffstatic int 5818169277Sariffsysctl_hdac_dump(SYSCTL_HANDLER_ARGS) 5819169277Sariff{ 5820169277Sariff struct hdac_softc *sc; 5821169277Sariff struct hdac_devinfo *devinfo; 5822169277Sariff struct hdac_widget *w; 5823169277Sariff device_t dev; 5824169277Sariff uint32_t res, execres; 5825169277Sariff int i, err, val; 5826169277Sariff nid_t cad; 5827169277Sariff 5828169277Sariff dev = oidp->oid_arg1; 5829169277Sariff devinfo = pcm_getdevinfo(dev); 5830169277Sariff if (devinfo == NULL || devinfo->codec == NULL || 5831169277Sariff devinfo->codec->sc == NULL) 5832169277Sariff return (EINVAL); 5833169277Sariff val = 0; 5834170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 5835169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 5836169277Sariff return (err); 5837169277Sariff sc = devinfo->codec->sc; 5838169277Sariff cad = devinfo->codec->cad; 5839169277Sariff hdac_lock(sc); 5840169277Sariff device_printf(dev, "HDAC Dump AFG [nid=%d]:\n", devinfo->nid); 5841169277Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5842169277Sariff w = hdac_widget_get(devinfo, i); 5843169277Sariff if (w == NULL || w->type != 5844169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5845169277Sariff continue; 5846169277Sariff execres = hdac_command(sc, HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), 5847169277Sariff cad); 5848169277Sariff res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 5849169277Sariff device_printf(dev, "nid=%-3d exec=0x%08x sense=0x%08x [%s]\n", 5850169277Sariff w->nid, execres, res, 5851169277Sariff (w->enable == 0) ? "DISABLED" : "ENABLED"); 5852169277Sariff } 5853169277Sariff device_printf(dev, 5854169277Sariff "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 5855169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 5856169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 5857169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 5858169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 5859169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 5860169277Sariff if (1 || HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 5861169277Sariff device_printf(dev, " GPI:"); 5862169277Sariff res = hdac_command(sc, 5863169277Sariff HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 5864169277Sariff printf(" data=0x%08x", res); 5865169277Sariff res = hdac_command(sc, 5866169277Sariff HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 5867169277Sariff cad); 5868169277Sariff printf(" wake=0x%08x", res); 5869169277Sariff res = hdac_command(sc, 5870169277Sariff HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 5871169277Sariff cad); 5872169277Sariff printf(" unsol=0x%08x", res); 5873169277Sariff res = hdac_command(sc, 5874169277Sariff HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 5875169277Sariff printf(" sticky=0x%08x\n", res); 5876169277Sariff } 5877169277Sariff if (1 || HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 5878169277Sariff device_printf(dev, " GPO:"); 5879169277Sariff res = hdac_command(sc, 5880169277Sariff HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 5881169277Sariff printf(" data=0x%08x\n", res); 5882169277Sariff } 5883169277Sariff if (1 || HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 5884169277Sariff device_printf(dev, "GPI0:"); 5885169277Sariff res = hdac_command(sc, 5886169277Sariff HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 5887169277Sariff printf(" data=0x%08x", res); 5888169277Sariff res = hdac_command(sc, 5889169277Sariff HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 5890169277Sariff printf(" enable=0x%08x", res); 5891169277Sariff res = hdac_command(sc, 5892169277Sariff HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 5893169277Sariff printf(" direction=0x%08x\n", res); 5894169277Sariff res = hdac_command(sc, 5895169277Sariff HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 5896169277Sariff device_printf(dev, " wake=0x%08x", res); 5897169277Sariff res = hdac_command(sc, 5898169277Sariff HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 5899169277Sariff cad); 5900169277Sariff printf(" unsol=0x%08x", res); 5901169277Sariff res = hdac_command(sc, 5902169277Sariff HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 5903169277Sariff printf(" sticky=0x%08x\n", res); 5904169277Sariff } 5905169277Sariff hdac_unlock(sc); 5906169277Sariff return (0); 5907169277Sariff} 5908164614Sariff#endif 5909169277Sariff#endif 5910164614Sariff 5911163057Sariffstatic void 5912162922Sariffhdac_attach2(void *arg) 5913162922Sariff{ 5914162922Sariff struct hdac_softc *sc; 5915162922Sariff struct hdac_widget *w; 5916162922Sariff struct hdac_audio_ctl *ctl; 5917163057Sariff uint32_t quirks_on, quirks_off; 5918162922Sariff int pcnt, rcnt; 5919162922Sariff int i; 5920162922Sariff char status[SND_STATUSLEN]; 5921162965Sariff device_t *devlist = NULL; 5922162922Sariff int devcount; 5923162922Sariff struct hdac_devinfo *devinfo = NULL; 5924162922Sariff 5925162922Sariff sc = (struct hdac_softc *)arg; 5926162922Sariff 5927163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 5928162922Sariff 5929163057Sariff HDA_BOOTVERBOSE( 5930163057Sariff device_printf(sc->dev, "HDA_DEBUG: HDA Config: on=0x%08x off=0x%08x\n", 5931163057Sariff quirks_on, quirks_off); 5932163057Sariff ); 5933163057Sariff 5934162922Sariff hdac_lock(sc); 5935162922Sariff 5936162922Sariff /* Remove ourselves from the config hooks */ 5937162922Sariff if (sc->intrhook.ich_func != NULL) { 5938162922Sariff config_intrhook_disestablish(&sc->intrhook); 5939162922Sariff sc->intrhook.ich_func = NULL; 5940162922Sariff } 5941162922Sariff 5942162922Sariff /* Start the corb and rirb engines */ 5943163057Sariff HDA_BOOTVERBOSE( 5944162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting CORB Engine...\n"); 5945162922Sariff ); 5946162922Sariff hdac_corb_start(sc); 5947163057Sariff HDA_BOOTVERBOSE( 5948162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting RIRB Engine...\n"); 5949162922Sariff ); 5950162922Sariff hdac_rirb_start(sc); 5951162922Sariff 5952163057Sariff HDA_BOOTVERBOSE( 5953162922Sariff device_printf(sc->dev, 5954162922Sariff "HDA_DEBUG: Enabling controller interrupt...\n"); 5955162922Sariff ); 5956164614Sariff if (sc->polling == 0) 5957164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 5958164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 5959163057Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 5960163057Sariff HDAC_GCTL_UNSOL); 5961162922Sariff 5962162922Sariff DELAY(1000); 5963162922Sariff 5964163057Sariff HDA_BOOTVERBOSE( 5965162922Sariff device_printf(sc->dev, "HDA_DEBUG: Scanning HDA codecs...\n"); 5966162922Sariff ); 5967162922Sariff hdac_scan_codecs(sc); 5968162922Sariff 5969162922Sariff device_get_children(sc->dev, &devlist, &devcount); 5970162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 5971162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 5972162965Sariff if (devinfo != NULL && devinfo->node_type == 5973162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 5974162965Sariff break; 5975162965Sariff } else 5976162965Sariff devinfo = NULL; 5977162922Sariff } 5978162965Sariff if (devlist != NULL) 5979162965Sariff free(devlist, M_TEMP); 5980162922Sariff 5981162922Sariff if (devinfo == NULL) { 5982162922Sariff hdac_unlock(sc); 5983162922Sariff device_printf(sc->dev, "Audio Function Group not found!\n"); 5984163057Sariff hdac_release_resources(sc); 5985162922Sariff return; 5986162922Sariff } 5987162922Sariff 5988163057Sariff HDA_BOOTVERBOSE( 5989162922Sariff device_printf(sc->dev, 5990162922Sariff "HDA_DEBUG: Parsing AFG nid=%d cad=%d\n", 5991162922Sariff devinfo->nid, devinfo->codec->cad); 5992162922Sariff ); 5993162922Sariff hdac_audio_parse(devinfo); 5994163057Sariff HDA_BOOTVERBOSE( 5995162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing Ctls...\n"); 5996162922Sariff ); 5997162922Sariff hdac_audio_ctl_parse(devinfo); 5998163057Sariff HDA_BOOTVERBOSE( 5999162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing vendor patch...\n"); 6000162922Sariff ); 6001162922Sariff hdac_vendor_patch_parse(devinfo); 6002163057Sariff if (quirks_on != 0) 6003163057Sariff devinfo->function.audio.quirks |= quirks_on; 6004163057Sariff if (quirks_off != 0) 6005163057Sariff devinfo->function.audio.quirks &= ~quirks_off; 6006162922Sariff 6007162922Sariff /* XXX Disable all DIGITAL path. */ 6008162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6009162922Sariff w = hdac_widget_get(devinfo, i); 6010162922Sariff if (w == NULL) 6011162922Sariff continue; 6012162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 6013162922Sariff w->enable = 0; 6014162922Sariff continue; 6015162922Sariff } 6016162922Sariff /* XXX Disable useless pin ? */ 6017162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6018162922Sariff (w->wclass.pin.config & 6019162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 6020162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 6021162922Sariff w->enable = 0; 6022162922Sariff } 6023162922Sariff i = 0; 6024162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6025162922Sariff if (ctl->widget == NULL) 6026162922Sariff continue; 6027169277Sariff if (ctl->ossmask & SOUND_MASK_DISABLE) 6028169277Sariff ctl->enable = 0; 6029162922Sariff w = ctl->widget; 6030169277Sariff if (w->enable == 0 || 6031169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6032162922Sariff ctl->enable = 0; 6033162922Sariff w = ctl->childwidget; 6034162922Sariff if (w == NULL) 6035162922Sariff continue; 6036162922Sariff if (w->enable == 0 || 6037162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6038162922Sariff ctl->enable = 0; 6039162922Sariff } 6040162922Sariff 6041163057Sariff HDA_BOOTVERBOSE( 6042162922Sariff device_printf(sc->dev, "HDA_DEBUG: Building AFG tree...\n"); 6043162922Sariff ); 6044162922Sariff hdac_audio_build_tree(devinfo); 6045162922Sariff 6046169277Sariff i = 0; 6047169277Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6048169277Sariff if (ctl->ossmask & (SOUND_MASK_SKIP | SOUND_MASK_DISABLE)) 6049169277Sariff ctl->ossmask = 0; 6050169277Sariff } 6051163057Sariff HDA_BOOTVERBOSE( 6052162922Sariff device_printf(sc->dev, "HDA_DEBUG: AFG commit...\n"); 6053162922Sariff ); 6054162922Sariff hdac_audio_commit(devinfo, HDA_COMMIT_ALL); 6055163057Sariff HDA_BOOTVERBOSE( 6056162922Sariff device_printf(sc->dev, "HDA_DEBUG: Ctls commit...\n"); 6057162922Sariff ); 6058162922Sariff hdac_audio_ctl_commit(devinfo); 6059162922Sariff 6060163057Sariff HDA_BOOTVERBOSE( 6061162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_PLAY setup...\n"); 6062162922Sariff ); 6063162922Sariff pcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_PLAY); 6064163057Sariff HDA_BOOTVERBOSE( 6065162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_REC setup...\n"); 6066162922Sariff ); 6067162922Sariff rcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_REC); 6068162922Sariff 6069162922Sariff hdac_unlock(sc); 6070163057Sariff HDA_BOOTVERBOSE( 6071162922Sariff device_printf(sc->dev, 6072162922Sariff "HDA_DEBUG: OSS mixer initialization...\n"); 6073162922Sariff ); 6074163057Sariff 6075163057Sariff /* 6076163057Sariff * There is no point of return after this. If the driver failed, 6077163057Sariff * so be it. Let the detach procedure do all the cleanup. 6078163057Sariff */ 6079163057Sariff if (mixer_init(sc->dev, &hdac_audio_ctl_ossmixer_class, devinfo) != 0) 6080162922Sariff device_printf(sc->dev, "Can't register mixer\n"); 6081162922Sariff 6082162922Sariff if (pcnt > 0) 6083162922Sariff pcnt = 1; 6084162922Sariff if (rcnt > 0) 6085162922Sariff rcnt = 1; 6086162922Sariff 6087163057Sariff HDA_BOOTVERBOSE( 6088162922Sariff device_printf(sc->dev, 6089162922Sariff "HDA_DEBUG: Registering PCM channels...\n"); 6090162922Sariff ); 6091163057Sariff if (pcm_register(sc->dev, devinfo, pcnt, rcnt) != 0) 6092162922Sariff device_printf(sc->dev, "Can't register PCM\n"); 6093162922Sariff 6094162922Sariff sc->registered++; 6095162922Sariff 6096169277Sariff if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 6097169277Sariff hdac_dma_alloc(sc, &sc->pos_dma, 6098169277Sariff (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 6099169277Sariff HDA_BOOTVERBOSE( 6100169277Sariff device_printf(sc->dev, 6101169277Sariff "Failed to allocate DMA pos buffer (non-fatal)\n"); 6102169277Sariff ); 6103169277Sariff } 6104169277Sariff 6105162922Sariff for (i = 0; i < pcnt; i++) 6106162922Sariff pcm_addchan(sc->dev, PCMDIR_PLAY, &hdac_channel_class, devinfo); 6107162922Sariff for (i = 0; i < rcnt; i++) 6108162922Sariff pcm_addchan(sc->dev, PCMDIR_REC, &hdac_channel_class, devinfo); 6109162922Sariff 6110164614Sariff#ifdef SND_DYNSYSCTL 6111164614Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 6112164614Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 6113164614Sariff "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 6114164614Sariff sysctl_hdac_polling, "I", "Enable polling mode"); 6115169277Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 6116169277Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 6117169277Sariff "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 6118169277Sariff sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 6119169277Sariff "Controller/Jack Sense polling interval (1-1000 ms)"); 6120169277Sariff#ifdef SND_DEBUG 6121169277Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 6122169277Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 6123169277Sariff "dump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 6124169277Sariff sysctl_hdac_dump, "I", "Dump states"); 6125164614Sariff#endif 6126169277Sariff#endif 6127164614Sariff 6128162922Sariff snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s [%s]", 6129164614Sariff rman_get_start(sc->mem.mem_res), rman_get_start(sc->irq.irq_res), 6130164614Sariff PCM_KLDSTRING(snd_hda), HDA_DRV_TEST_REV); 6131162922Sariff pcm_setstatus(sc->dev, status); 6132162922Sariff device_printf(sc->dev, "<HDA Codec: %s>\n", hdac_codec_name(devinfo)); 6133163057Sariff HDA_BOOTVERBOSE( 6134163057Sariff device_printf(sc->dev, "<HDA Codec ID: 0x%08x>\n", 6135163057Sariff hdac_codec_id(devinfo)); 6136163057Sariff ); 6137164614Sariff device_printf(sc->dev, "<HDA Driver Revision: %s>\n", 6138164614Sariff HDA_DRV_TEST_REV); 6139162922Sariff 6140163057Sariff HDA_BOOTVERBOSE( 6141162922Sariff if (devinfo->function.audio.quirks != 0) { 6142162922Sariff device_printf(sc->dev, "\n"); 6143163057Sariff device_printf(sc->dev, "HDA config/quirks:"); 6144163057Sariff for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 6145169277Sariff if ((devinfo->function.audio.quirks & 6146169277Sariff hdac_quirks_tab[i].value) == 6147163057Sariff hdac_quirks_tab[i].value) 6148163057Sariff printf(" %s", hdac_quirks_tab[i].key); 6149163057Sariff } 6150162922Sariff printf("\n"); 6151162922Sariff } 6152162922Sariff device_printf(sc->dev, "\n"); 6153162922Sariff device_printf(sc->dev, "+-------------------+\n"); 6154162922Sariff device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 6155162922Sariff device_printf(sc->dev, "+-------------------+\n"); 6156162922Sariff hdac_dump_nodes(devinfo); 6157162922Sariff device_printf(sc->dev, "\n"); 6158162922Sariff device_printf(sc->dev, "+------------------------+\n"); 6159162922Sariff device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 6160162922Sariff device_printf(sc->dev, "+------------------------+\n"); 6161162922Sariff device_printf(sc->dev, "\n"); 6162162922Sariff i = 0; 6163162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6164162922Sariff device_printf(sc->dev, "%3d: nid=%d", i, 6165162922Sariff (ctl->widget != NULL) ? ctl->widget->nid : -1); 6166162922Sariff if (ctl->childwidget != NULL) 6167162922Sariff printf(" cnid=%d", ctl->childwidget->nid); 6168162922Sariff printf(" dir=0x%x index=%d " 6169162922Sariff "ossmask=0x%08x ossdev=%d%s\n", 6170162922Sariff ctl->dir, ctl->index, 6171162922Sariff ctl->ossmask, ctl->ossdev, 6172162922Sariff (ctl->enable == 0) ? " [DISABLED]" : ""); 6173162922Sariff } 6174162922Sariff device_printf(sc->dev, "\n"); 6175162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 6176162922Sariff device_printf(sc->dev, "| DUMPING HDA AUDIO/VOLUME CONTROLS |\n"); 6177162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 6178162922Sariff hdac_dump_ctls(devinfo, "Master Volume (OSS: vol)", SOUND_MASK_VOLUME); 6179162922Sariff hdac_dump_ctls(devinfo, "PCM Volume (OSS: pcm)", SOUND_MASK_PCM); 6180162922Sariff hdac_dump_ctls(devinfo, "CD Volume (OSS: cd)", SOUND_MASK_CD); 6181162922Sariff hdac_dump_ctls(devinfo, "Microphone Volume (OSS: mic)", SOUND_MASK_MIC); 6182162922Sariff hdac_dump_ctls(devinfo, "Line-in Volume (OSS: line)", SOUND_MASK_LINE); 6183162922Sariff hdac_dump_ctls(devinfo, "Recording Level (OSS: rec)", SOUND_MASK_RECLEV); 6184162922Sariff hdac_dump_ctls(devinfo, "Speaker/Beep (OSS: speaker)", SOUND_MASK_SPEAKER); 6185162922Sariff hdac_dump_ctls(devinfo, NULL, 0); 6186162922Sariff hdac_dump_dac(devinfo); 6187162922Sariff hdac_dump_adc(devinfo); 6188162922Sariff device_printf(sc->dev, "\n"); 6189162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 6190162922Sariff device_printf(sc->dev, "| DUMPING PCM Playback/Record Channels |\n"); 6191162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 6192162922Sariff hdac_dump_pcmchannels(sc, pcnt, rcnt); 6193162922Sariff ); 6194164614Sariff 6195164614Sariff if (sc->polling != 0) { 6196164614Sariff hdac_lock(sc); 6197164614Sariff callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 6198164614Sariff hdac_unlock(sc); 6199164614Sariff } 6200162922Sariff} 6201162922Sariff 6202162922Sariff/**************************************************************************** 6203162922Sariff * int hdac_detach(device_t) 6204162922Sariff * 6205162922Sariff * Detach and free up resources utilized by the hdac device. 6206162922Sariff ****************************************************************************/ 6207162922Sariffstatic int 6208162922Sariffhdac_detach(device_t dev) 6209162922Sariff{ 6210162922Sariff struct hdac_softc *sc = NULL; 6211162922Sariff struct hdac_devinfo *devinfo = NULL; 6212163057Sariff int err; 6213162922Sariff 6214162922Sariff devinfo = (struct hdac_devinfo *)pcm_getdevinfo(dev); 6215162922Sariff if (devinfo != NULL && devinfo->codec != NULL) 6216162922Sariff sc = devinfo->codec->sc; 6217162922Sariff if (sc == NULL) 6218163057Sariff return (0); 6219162922Sariff 6220162922Sariff if (sc->registered > 0) { 6221163057Sariff err = pcm_unregister(dev); 6222163057Sariff if (err != 0) 6223163057Sariff return (err); 6224162922Sariff } 6225162922Sariff 6226163057Sariff hdac_release_resources(sc); 6227162922Sariff 6228162922Sariff return (0); 6229162922Sariff} 6230162922Sariff 6231162922Sariffstatic device_method_t hdac_methods[] = { 6232162922Sariff /* device interface */ 6233162922Sariff DEVMETHOD(device_probe, hdac_probe), 6234162922Sariff DEVMETHOD(device_attach, hdac_attach), 6235162922Sariff DEVMETHOD(device_detach, hdac_detach), 6236162922Sariff { 0, 0 } 6237162922Sariff}; 6238162922Sariff 6239162922Sariffstatic driver_t hdac_driver = { 6240162922Sariff "pcm", 6241162922Sariff hdac_methods, 6242162922Sariff PCM_SOFTC_SIZE, 6243162922Sariff}; 6244162922Sariff 6245162922SariffDRIVER_MODULE(snd_hda, pci, hdac_driver, pcm_devclass, 0, 0); 6246162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 6247162922SariffMODULE_VERSION(snd_hda, 1); 6248