hdac.c revision 186511
1162922Sariff/*- 2162922Sariff * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3162922Sariff * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4182999Smav * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org> 5162922Sariff * All rights reserved. 6162922Sariff * 7162922Sariff * Redistribution and use in source and binary forms, with or without 8162922Sariff * modification, are permitted provided that the following conditions 9162922Sariff * are met: 10162922Sariff * 1. Redistributions of source code must retain the above copyright 11162922Sariff * notice, this list of conditions and the following disclaimer. 12162922Sariff * 2. Redistributions in binary form must reproduce the above copyright 13162922Sariff * notice, this list of conditions and the following disclaimer in the 14162922Sariff * documentation and/or other materials provided with the distribution. 15162922Sariff * 16162922Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19162922Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26162922Sariff * SUCH DAMAGE. 27162922Sariff */ 28162922Sariff 29162922Sariff/* 30162922Sariff * Intel High Definition Audio (Controller) driver for FreeBSD. Be advised 31162922Sariff * that this driver still in its early stage, and possible of rewrite are 32162922Sariff * pretty much guaranteed. There are supposedly several distinct parent/child 33162922Sariff * busses to make this "perfect", but as for now and for the sake of 34162922Sariff * simplicity, everything is gobble up within single source. 35162922Sariff * 36162922Sariff * List of subsys: 37162922Sariff * 1) HDA Controller support 38162922Sariff * 2) HDA Codecs support, which may include 39162922Sariff * - HDA 40162922Sariff * - Modem 41162922Sariff * - HDMI 42162922Sariff * 3) Widget parser - the real magic of why this driver works on so 43162922Sariff * many hardwares with minimal vendor specific quirk. The original 44162922Sariff * parser was written using Ruby and can be found at 45162922Sariff * http://people.freebsd.org/~ariff/HDA/parser.rb . This crude 46162922Sariff * ruby parser take the verbose dmesg dump as its input. Refer to 47162922Sariff * http://www.microsoft.com/whdc/device/audio/default.mspx for various 48164614Sariff * interesting documents, especially UAA (Universal Audio Architecture). 49162922Sariff * 4) Possible vendor specific support. 50162922Sariff * (snd_hda_intel, snd_hda_ati, etc..) 51162922Sariff * 52162922Sariff * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the 53162922Sariff * Compaq V3000 with Conexant HDA. 54162922Sariff * 55162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 56162922Sariff * * * 57162922Sariff * * This driver is a collaborative effort made by: * 58162922Sariff * * * 59162922Sariff * * Stephane E. Potvin <sepotvin@videotron.ca> * 60162922Sariff * * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * 61162922Sariff * * Wesley Morgan <morganw@chemikals.org> * 62162922Sariff * * Daniel Eischen <deischen@FreeBSD.org> * 63162922Sariff * * Maxime Guillaud <bsd-ports@mguillaud.net> * 64162922Sariff * * Ariff Abdullah <ariff@FreeBSD.org> * 65182999Smav * * Alexander Motin <mav@FreeBSD.org> * 66162922Sariff * * * 67162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 68162922Sariff * * * 69162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 70162922Sariff */ 71162922Sariff 72162922Sariff#include <dev/sound/pcm/sound.h> 73162922Sariff#include <dev/pci/pcireg.h> 74162922Sariff#include <dev/pci/pcivar.h> 75162922Sariff 76171141Sariff#include <sys/ctype.h> 77171141Sariff#include <sys/taskqueue.h> 78171141Sariff 79162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 80162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 81162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 82162922Sariff#include <dev/sound/pci/hda/hdac.h> 83162922Sariff 84162922Sariff#include "mixer_if.h" 85162922Sariff 86186503Smav#define HDA_DRV_TEST_REV "20081226_0122" 87162922Sariff 88162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 186511 2008-12-27 11:00:20Z mav $"); 89162922Sariff 90169277Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 91169277Sariff if (bootverbose != 0 || snd_verbose > 3) { \ 92169277Sariff stmt \ 93169277Sariff } \ 94162922Sariff} while(0) 95162922Sariff 96183097Smav#define HDA_BOOTHVERBOSE(stmt) do { \ 97183097Smav if (snd_verbose > 3) { \ 98183097Smav stmt \ 99183097Smav } \ 100183097Smav} while(0) 101183097Smav 102162965Sariff#if 1 103162922Sariff#undef HDAC_INTR_EXTRA 104162922Sariff#define HDAC_INTR_EXTRA 1 105162922Sariff#endif 106162922Sariff 107162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 108162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 109163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 110163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 111162922Sariff 112178155Sariff#undef HDAC_MSI_ENABLED 113178155Sariff#if __FreeBSD_version >= 700026 || \ 114178155Sariff (__FreeBSD_version < 700000 && __FreeBSD_version >= 602106) 115178155Sariff#define HDAC_MSI_ENABLED 1 116178155Sariff#endif 117178155Sariff 118162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 119163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 120163257Sariff (fl) == 0xffffffff || \ 121163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 122163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 123163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 124163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 125162965Sariff#define HDA_MATCH_ALL 0xffffffff 126162965Sariff#define HDAC_INVALID 0xffffffff 127162965Sariff 128169277Sariff/* Default controller / jack sense poll: 250ms */ 129169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 130169277Sariff 131171141Sariff/* 132171141Sariff * Make room for possible 4096 playback/record channels, in 100 years to come. 133171141Sariff */ 134171141Sariff#define HDAC_TRIGGER_NONE 0x00000000 135171141Sariff#define HDAC_TRIGGER_PLAY 0x00000fff 136171141Sariff#define HDAC_TRIGGER_REC 0x00fff000 137171141Sariff#define HDAC_TRIGGER_UNSOL 0x80000000 138171141Sariff 139162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 140162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 141162922Sariff 142162922Sariff/* Controller models */ 143162922Sariff 144162922Sariff/* Intel */ 145162922Sariff#define INTEL_VENDORID 0x8086 146162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 147171330Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 148162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 149163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 150171330Sariff#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e) 151184207Smav#define HDA_INTEL_82801J HDA_MODEL_CONSTRUCT(INTEL, 0x3a3e) 152184207Smav#define HDA_INTEL_SCH HDA_MODEL_CONSTRUCT(INTEL, 0x811b) 153162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 154162922Sariff 155162922Sariff/* Nvidia */ 156162922Sariff#define NVIDIA_VENDORID 0x10de 157162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 158162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 159173817Sariff#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 160173817Sariff#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 161173817Sariff#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 162173817Sariff#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 163173817Sariff#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c) 164173817Sariff#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d) 165186511Smav#define HDA_NVIDIA_MCP78_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0774) 166186511Smav#define HDA_NVIDIA_MCP78_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0775) 167186511Smav#define HDA_NVIDIA_MCP78_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0776) 168186511Smav#define HDA_NVIDIA_MCP78_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0777) 169186511Smav#define HDA_NVIDIA_MCP73_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fc) 170186511Smav#define HDA_NVIDIA_MCP73_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fd) 171186511Smav#define HDA_NVIDIA_MCP79_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac0) 172186511Smav#define HDA_NVIDIA_MCP79_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac1) 173186511Smav#define HDA_NVIDIA_MCP79_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac2) 174186511Smav#define HDA_NVIDIA_MCP79_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac3) 175162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 176162922Sariff 177162922Sariff/* ATI */ 178162922Sariff#define ATI_VENDORID 0x1002 179162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 180163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 181162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 182162922Sariff 183163136Sariff/* VIA */ 184163136Sariff#define VIA_VENDORID 0x1106 185163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 186163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 187163136Sariff 188163136Sariff/* SiS */ 189163136Sariff#define SIS_VENDORID 0x1039 190163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 191163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 192163136Sariff 193186301Smav/* ULI */ 194186301Smav#define ULI_VENDORID 0x10b9 195186301Smav#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461) 196186301Smav#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff) 197186301Smav 198162922Sariff/* OEM/subvendors */ 199162922Sariff 200165466Sariff/* Intel */ 201165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 202165466Sariff 203162922Sariff/* HP/Compaq */ 204162922Sariff#define HP_VENDORID 0x103c 205162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 206162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 207162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 208165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 209166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 210169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 211169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 212174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 213172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 214162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 215165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 216165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 217162922Sariff 218162922Sariff/* Dell */ 219162922Sariff#define DELL_VENDORID 0x1028 220180532Sdelphij#define DELL_D630_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01f9) 221162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 222184483Smav#define DELL_V1400_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0227) 223178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 224162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 225169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 226169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 227162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 228162922Sariff 229162922Sariff/* Clevo */ 230162922Sariff#define CLEVO_VENDORID 0x1558 231162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 232162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 233162922Sariff 234162922Sariff/* Acer */ 235162922Sariff#define ACER_VENDORID 0x1025 236165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 237173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 238174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 239182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 240169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 241182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 242162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 243162922Sariff 244162965Sariff/* Asus */ 245162965Sariff#define ASUS_VENDORID 0x1043 246178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 247163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 248178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 249165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 250178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 251178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 252167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 253169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 254178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 255178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 256178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 257170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 258178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 259169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 260171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 261162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 262162922Sariff 263163257Sariff/* IBM / Lenovo */ 264163257Sariff#define IBM_VENDORID 0x1014 265163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 266163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 267162965Sariff 268164614Sariff/* Lenovo */ 269164657Sariff#define LENOVO_VENDORID 0x17aa 270164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 271182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 272172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 273164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 274163257Sariff 275164657Sariff/* Samsung */ 276164657Sariff#define SAMSUNG_VENDORID 0x144d 277164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 278164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 279164614Sariff 280164750Sariff/* Medion ? */ 281164750Sariff#define MEDION_VENDORID 0x161f 282164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 283164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 284164750Sariff 285173817Sariff/* Apple Computer Inc. */ 286173817Sariff#define APPLE_VENDORID 0x106b 287173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 288173817Sariff 289182999Smav/* Sony */ 290182999Smav#define SONY_VENDORID 0x104d 291182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 292182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 293182999Smav 294164828Sariff/* 295164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 296164828Sariff * instead of their own, which is beyond my comprehension 297164828Sariff * (see HDA_CODEC_STAC9221 below). 298164828Sariff */ 299164828Sariff#define APPLE_INTEL_MAC 0x76808384 300164828Sariff 301165281Sariff/* LG Electronics */ 302165281Sariff#define LG_VENDORID 0x1854 303165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 304165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 305165281Sariff 306165351Sariff/* Fujitsu Siemens */ 307165351Sariff#define FS_VENDORID 0x1734 308165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 309172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 310165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 311165351Sariff 312172811Sariff/* Fujitsu Limited */ 313172811Sariff#define FL_VENDORID 0x10cf 314172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 315182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 316172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 317172811Sariff 318165770Sariff/* Toshiba */ 319165770Sariff#define TOSHIBA_VENDORID 0x1179 320165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 321173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 322165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 323165770Sariff 324165992Sariff/* Micro-Star International (MSI) */ 325165992Sariff#define MSI_VENDORID 0x1462 326165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 327172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 328165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 329165992Sariff 330172811Sariff/* Giga-Byte Technology */ 331172811Sariff#define GB_VENDORID 0x1458 332172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 333172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 334172811Sariff 335169277Sariff/* Uniwill ? */ 336169277Sariff#define UNIWILL_VENDORID 0x1584 337169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 338170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 339169277Sariff 340169277Sariff 341162922Sariff/* Misc constants.. */ 342182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 343162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 344162922Sariff#define HDA_AMP_MUTE_NONE (0) 345162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 346162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 347162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 348162922Sariff 349162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 350162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 351162922Sariff 352182999Smav#define HDA_ADC_MONITOR (1 << 0) 353162922Sariff 354182999Smav#define HDA_CTL_OUT 1 355182999Smav#define HDA_CTL_IN 2 356169277Sariff 357169277Sariff#define HDA_GPIO_MAX 8 358169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 359163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 360163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 361163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 362169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 363169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 364169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 365169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 366169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 367169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 368162922Sariff 369169277Sariff/* 9 - 25 = anything else */ 370169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 371169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 372169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 373169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 374169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 375182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 376169277Sariff 377169277Sariff/* 26 - 31 = vrefs */ 378169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 379169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 380169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 381169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 382169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 383169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 384169277Sariff 385169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 386169277Sariff HDA_QUIRK_IVREF100) 387169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 388169277Sariff HDA_QUIRK_OVREF100) 389169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 390169277Sariff 391171141Sariff#if __FreeBSD_version < 600000 392171141Sariff#define taskqueue_drain(...) 393171141Sariff#endif 394171141Sariff 395163057Sariffstatic const struct { 396163057Sariff char *key; 397163057Sariff uint32_t value; 398163057Sariff} hdac_quirks_tab[] = { 399163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 400163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 401163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 402169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 403169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 404169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 405169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 406169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 407165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 408163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 409163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 410163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 411163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 412169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 413182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 414169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 415169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 416169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 417169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 418169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 419169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 420169277Sariff { "ivref", HDA_QUIRK_IVREF }, 421169277Sariff { "ovref", HDA_QUIRK_OVREF }, 422165069Sariff { "vref", HDA_QUIRK_VREF }, 423163057Sariff}; 424163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 425163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 426163057Sariff 427162922Sariff#define HDA_BDL_MIN 2 428162922Sariff#define HDA_BDL_MAX 256 429162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 430162922Sariff 431169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 432167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 433167648Sariff 434162922Sariff#define HDA_BUFSZ_MIN 4096 435162922Sariff#define HDA_BUFSZ_MAX 65536 436162922Sariff#define HDA_BUFSZ_DEFAULT 16384 437162922Sariff 438162922Sariff#define HDA_PARSE_MAXDEPTH 10 439162922Sariff 440169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 441162922Sariff 442165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 443162922Sariff 444182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 445182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 446182999Smav "White", "Other"}; 447162922Sariff 448182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 449182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 450182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 451182999Smav 452182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 453182999Smav 454162922Sariff/* Default */ 455162922Sariffstatic uint32_t hdac_fmt[] = { 456162922Sariff AFMT_STEREO | AFMT_S16_LE, 457162922Sariff 0 458162922Sariff}; 459162922Sariff 460162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 461162922Sariff 462162922Sariffstatic const struct { 463162922Sariff uint32_t model; 464162922Sariff char *desc; 465162922Sariff} hdac_devices[] = { 466162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 467171330Sariff { HDA_INTEL_63XXESB, "Intel 631x/632xESB" }, 468162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 469163136Sariff { HDA_INTEL_82801H, "Intel 82801H" }, 470171330Sariff { HDA_INTEL_82801I, "Intel 82801I" }, 471184207Smav { HDA_INTEL_82801J, "Intel 82801J" }, 472184207Smav { HDA_INTEL_SCH, "Intel SCH" }, 473162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 474162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 475173817Sariff { HDA_NVIDIA_MCP61_1, "NVidia MCP61" }, 476173817Sariff { HDA_NVIDIA_MCP61_2, "NVidia MCP61" }, 477173817Sariff { HDA_NVIDIA_MCP65_1, "NVidia MCP65" }, 478174004Sariff { HDA_NVIDIA_MCP65_2, "NVidia MCP65" }, 479173817Sariff { HDA_NVIDIA_MCP67_1, "NVidia MCP67" }, 480173817Sariff { HDA_NVIDIA_MCP67_2, "NVidia MCP67" }, 481186511Smav { HDA_NVIDIA_MCP73_1, "NVidia MCP73" }, 482186511Smav { HDA_NVIDIA_MCP73_2, "NVidia MCP73" }, 483186511Smav { HDA_NVIDIA_MCP78_1, "NVidia MCP78" }, 484186511Smav { HDA_NVIDIA_MCP78_2, "NVidia MCP78" }, 485186511Smav { HDA_NVIDIA_MCP78_3, "NVidia MCP78" }, 486186511Smav { HDA_NVIDIA_MCP78_4, "NVidia MCP78" }, 487186511Smav { HDA_NVIDIA_MCP79_1, "NVidia MCP79" }, 488186511Smav { HDA_NVIDIA_MCP79_2, "NVidia MCP79" }, 489186511Smav { HDA_NVIDIA_MCP79_3, "NVidia MCP79" }, 490186511Smav { HDA_NVIDIA_MCP79_4, "NVidia MCP79" }, 491162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 492163136Sariff { HDA_ATI_SB600, "ATI SB600" }, 493163136Sariff { HDA_VIA_VT82XX, "VIA VT8251/8237A" }, 494163136Sariff { HDA_SIS_966, "SiS 966" }, 495186301Smav { HDA_ULI_M5461, "ULI M5461" }, 496162922Sariff /* Unknown */ 497162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 498162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 499162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 500163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 501163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 502186301Smav { HDA_ULI_ALL, "ULI (Unknown)" }, 503162922Sariff}; 504162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 505162922Sariff 506162922Sariffstatic const struct { 507169277Sariff uint16_t vendor; 508169277Sariff uint8_t reg; 509169277Sariff uint8_t mask; 510169277Sariff uint8_t enable; 511169277Sariff} hdac_pcie_snoop[] = { 512169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 513169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 514169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 515169277Sariff}; 516169277Sariff#define HDAC_PCIESNOOP_LEN \ 517169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 518169277Sariff 519169277Sariffstatic const struct { 520162922Sariff uint32_t rate; 521162922Sariff int valid; 522162922Sariff uint16_t base; 523162922Sariff uint16_t mul; 524162922Sariff uint16_t div; 525162922Sariff} hda_rate_tab[] = { 526162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 527162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 528162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 529162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 530162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 531162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 532162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 533162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 534162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 535162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 536162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 537162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 538162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 539162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 540162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 541162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 542162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 543162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 544162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 545162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 546162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 547162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 548162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 549162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 550162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 551162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 552162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 553162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 554162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 555162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 556162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 557162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 558162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 559162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 560162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 561162922Sariff}; 562162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 563162922Sariff 564162922Sariff/* All codecs you can eat... */ 565162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 566162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 567162922Sariff 568162922Sariff/* Realtek */ 569162922Sariff#define REALTEK_VENDORID 0x10ec 570162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 571169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 572183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 573171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 574183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 575183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 576170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 577183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 578183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 579162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 580169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 581162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 582163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 583163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 584169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 585165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 586182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 587162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 588162922Sariff 589169277Sariff/* Analog Devices */ 590169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 591186403Smav#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) 592186403Smav#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) 593186403Smav#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) 594186403Smav#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) 595186403Smav#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) 596186403Smav#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) 597169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 598169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 599174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 600169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 601186403Smav#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) 602169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 603170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 604186403Smav#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) 605186403Smav#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) 606169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 607162922Sariff 608162922Sariff/* CMedia */ 609162922Sariff#define CMEDIA_VENDORID 0x434d 610162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 611162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 612162922Sariff 613162922Sariff/* Sigmatel */ 614162922Sariff#define SIGMATEL_VENDORID 0x8384 615182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 616182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 617182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 618182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 619182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 620182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 621182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 622182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 623183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 624183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 625183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 626183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 627183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 628183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 629183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 630182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 631183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 632183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 633183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 634183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 635183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 636183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 637183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 638183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 639182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 640162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 641182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 642183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 643162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 644162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 645183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 646183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 647183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 648183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 649183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 650183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 651183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 652183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 653183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 654162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 655162922Sariff 656183894Smav/* IDT */ 657183894Smav#define IDT_VENDORID 0x111d 658183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 659183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 660183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 661183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 662183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 663183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 664183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 665183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 666183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 667183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 668183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 669183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 670183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 671183894Smav 672182999Smav/* Silicon Image */ 673182999Smav#define SII_VENDORID 0x1095 674186146Smav#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) 675182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 676182999Smav 677182999Smav/* Lucent/Agere */ 678182999Smav#define AGERE_VENDORID 0x11c1 679182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 680182999Smav 681186430Smav/* Conexant */ 682162922Sariff#define CONEXANT_VENDORID 0x14f1 683186430Smav#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 684186430Smav#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 685186430Smav#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) 686162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 687162922Sariff 688169277Sariff/* VIA */ 689169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 690169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 691169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 692169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 693169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 694169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 695169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 696169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 697169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 698169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 699169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 700169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 701186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 702186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 703186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 704186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 705186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 706186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 707186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 708186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 709169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 710162922Sariff 711182999Smav/* ATI */ 712186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 713186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 714186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 715186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 716182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 717169277Sariff 718182999Smav/* NVIDIA */ 719182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 720182999Smav 721183894Smav/* INTEL */ 722183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 723183894Smav 724162922Sariff/* Codecs */ 725162922Sariffstatic const struct { 726162922Sariff uint32_t id; 727162922Sariff char *name; 728162922Sariff} hdac_codecs[] = { 729162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 730169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 731183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 732171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 733183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 734183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 735170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 736183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 737183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 738162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 739169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 740162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 741162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 742163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 743169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 744165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 745182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 746186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 747186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 748186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 749186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 750186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 751169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 752169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 753174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 754186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 755186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 756169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 757186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 758186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 759170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 760186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 761162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 762183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 763183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 764183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 765183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 766183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 767183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 768183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 769183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 770162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 771183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 772162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 773162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 774183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 775183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 776183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 777183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 778183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 779183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 780182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 781182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 782183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 783183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 784183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 785166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 786183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 787183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 788183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 789183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 790183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 791183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 792183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 793183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 794183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 795183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 796183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 797183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 798183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 799183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 800183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 801183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 802183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 803183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 804183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 805183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 806183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 807183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 808183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 809183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 810183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 811183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 812183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 813186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 814186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 815186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 816169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 817169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 818169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 819169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 820169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 821169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 822169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 823169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 824169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 825169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 826169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 827169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 828186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 829186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 830186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 831186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 832186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 833186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 834186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 835186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 836186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 837186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 838186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 839186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 840186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 841162922Sariff /* Unknown codec */ 842162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 843169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 844162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 845162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 846182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 847182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 848162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 849169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 850182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 851182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 852183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 853183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 854162922Sariff}; 855162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 856162922Sariff 857162922Sariff 858162922Sariff/**************************************************************************** 859162922Sariff * Function prototypes 860162922Sariff ****************************************************************************/ 861162922Sariffstatic void hdac_intr_handler(void *); 862182999Smavstatic int hdac_reset(struct hdac_softc *, int); 863162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 864162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 865162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 866162922Sariff struct hdac_dma *, bus_size_t); 867169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 868162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 869162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 870162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 871162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 872162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 873162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 874162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 875162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 876182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 877182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 878182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 879182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 880162922Sariff 881162922Sariffstatic void hdac_attach2(void *); 882162922Sariff 883162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 884162922Sariff uint32_t, int); 885162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 886162922Sariff struct hdac_command_list *, int); 887162922Sariff 888162922Sariffstatic int hdac_probe(device_t); 889162922Sariffstatic int hdac_attach(device_t); 890162922Sariffstatic int hdac_detach(device_t); 891182999Smavstatic int hdac_suspend(device_t); 892182999Smavstatic int hdac_resume(device_t); 893162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 894162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 895162922Sariff uint32_t, int, int); 896162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 897182999Smav nid_t, int, int, int); 898162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 899162922Sariff nid_t, nid_t, int, int, int, int, int, int); 900162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 901162922Sariff 902164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 903164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 904164614Sariff 905182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 906182999Smav 907162922Sariff#define hdac_command(a1, a2, a3) \ 908162922Sariff hdac_command_sendone_internal(a1, a2, a3) 909162922Sariff 910182999Smav#define hdac_codec_id(c) \ 911182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 912182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 913182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 914162922Sariff 915162922Sariffstatic char * 916182999Smavhdac_codec_name(struct hdac_codec *codec) 917162922Sariff{ 918162922Sariff uint32_t id; 919162922Sariff int i; 920162922Sariff 921182999Smav id = hdac_codec_id(codec); 922162922Sariff 923162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 924163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 925162922Sariff return (hdac_codecs[i].name); 926162922Sariff } 927162922Sariff 928162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 929162922Sariff} 930162922Sariff 931162922Sariffstatic char * 932162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 933162922Sariff{ 934162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 935162922Sariff int i, first = 1; 936162922Sariff 937162922Sariff bzero(buf, len); 938162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 939162922Sariff if (mask & (1 << i)) { 940162922Sariff if (first == 0) 941162922Sariff strlcat(buf, ", ", len); 942162922Sariff strlcat(buf, ossname[i], len); 943162922Sariff first = 0; 944162922Sariff } 945162922Sariff } 946182999Smav return (buf); 947162922Sariff} 948162922Sariff 949162922Sariffstatic struct hdac_audio_ctl * 950162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 951162922Sariff{ 952162922Sariff if (devinfo == NULL || 953162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 954162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 955162922Sariff devinfo->function.audio.ctlcnt < 1 || 956162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 957162922Sariff return (NULL); 958162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 959162922Sariff} 960162922Sariff 961162922Sariffstatic struct hdac_audio_ctl * 962182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 963162922Sariff int index, int cnt) 964162922Sariff{ 965182999Smav struct hdac_audio_ctl *ctl; 966182999Smav int i, found = 0; 967162922Sariff 968162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 969162922Sariff return (NULL); 970162922Sariff 971162922Sariff i = 0; 972162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 973182999Smav if (ctl->enable == 0) 974162922Sariff continue; 975182999Smav if (ctl->widget->nid != nid) 976162922Sariff continue; 977182999Smav if (dir && ctl->ndir != dir) 978182999Smav continue; 979182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 980182999Smav ctl->dir == ctl->ndir && ctl->index != index) 981182999Smav continue; 982162922Sariff found++; 983182999Smav if (found == cnt || cnt <= 0) 984162922Sariff return (ctl); 985162922Sariff } 986162922Sariff 987182999Smav return (NULL); 988162922Sariff} 989162922Sariff 990182999Smav/* 991182999Smav * Jack detection (Speaker/HP redirection) event handler. 992182999Smav */ 993162922Sariffstatic void 994162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 995162922Sariff{ 996182999Smav struct hdac_audio_as *as; 997162922Sariff struct hdac_softc *sc; 998162922Sariff struct hdac_widget *w; 999162922Sariff struct hdac_audio_ctl *ctl; 1000182999Smav uint32_t val, res; 1001182999Smav int i, j; 1002162922Sariff nid_t cad; 1003162922Sariff 1004162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1005162922Sariff devinfo->codec->sc == NULL) 1006162922Sariff return; 1007162922Sariff 1008162922Sariff sc = devinfo->codec->sc; 1009162922Sariff cad = devinfo->codec->cad; 1010182999Smav as = devinfo->function.audio.as; 1011182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1012182999Smav if (as[i].hpredir < 0) 1013182999Smav continue; 1014182999Smav 1015182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1016182999Smav if (w == NULL || w->enable == 0 || w->type != 1017182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1018182999Smav continue; 1019162922Sariff 1020171141Sariff res = hdac_command(sc, 1021182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1022171141Sariff 1023182999Smav HDA_BOOTVERBOSE( 1024182999Smav device_printf(sc->dev, 1025182999Smav "Pin sense: nid=%d res=0x%08x\n", 1026182999Smav as[i].pins[15], res); 1027182999Smav ); 1028171141Sariff 1029182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1030182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1031182999Smav res ^= 1; 1032162922Sariff 1033182999Smav /* (Un)Mute headphone pin. */ 1034162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1035182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1036182999Smav if (ctl != NULL && ctl->mute) { 1037182999Smav /* If pin has muter - use it. */ 1038182999Smav val = (res != 0) ? 0 : 1; 1039182999Smav if (val != ctl->forcemute) { 1040182999Smav ctl->forcemute = val; 1041162922Sariff hdac_audio_ctl_amp_set(ctl, 1042182999Smav HDA_AMP_MUTE_DEFAULT, 1043182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1044162922Sariff } 1045182999Smav } else { 1046182999Smav /* If there is no muter - disable pin output. */ 1047182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1048163057Sariff if (w != NULL && w->type == 1049163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1050182999Smav if (res != 0) 1051169277Sariff val = w->wclass.pin.ctrl | 1052162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1053162922Sariff else 1054169277Sariff val = w->wclass.pin.ctrl & 1055162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1056169277Sariff if (val != w->wclass.pin.ctrl) { 1057169277Sariff w->wclass.pin.ctrl = val; 1058169277Sariff hdac_command(sc, 1059169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1060169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1061169277Sariff } 1062162922Sariff } 1063182999Smav } 1064182999Smav /* (Un)Mute other pins. */ 1065182999Smav for (j = 0; j < 15; j++) { 1066182999Smav if (as[i].pins[j] <= 0) 1067182999Smav continue; 1068182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1069182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1070182999Smav if (ctl != NULL && ctl->mute) { 1071182999Smav /* If pin has muter - use it. */ 1072182999Smav val = (res != 0) ? 1 : 0; 1073182999Smav if (val == ctl->forcemute) 1074169277Sariff continue; 1075182999Smav ctl->forcemute = val; 1076182999Smav hdac_audio_ctl_amp_set(ctl, 1077182999Smav HDA_AMP_MUTE_DEFAULT, 1078182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1079182999Smav continue; 1080162922Sariff } 1081182999Smav /* If there is no muter - disable pin output. */ 1082182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1083163057Sariff if (w != NULL && w->type == 1084163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1085182999Smav if (res != 0) 1086182999Smav val = w->wclass.pin.ctrl & 1087182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1088182999Smav else 1089182999Smav val = w->wclass.pin.ctrl | 1090182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1091169277Sariff if (val != w->wclass.pin.ctrl) { 1092169277Sariff w->wclass.pin.ctrl = val; 1093169277Sariff hdac_command(sc, 1094169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1095169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1096169277Sariff } 1097162922Sariff } 1098162922Sariff } 1099182999Smav } 1100182999Smav} 1101182999Smav 1102182999Smav/* 1103182999Smav * Callback for poll based jack detection. 1104182999Smav */ 1105182999Smavstatic void 1106182999Smavhdac_jack_poll_callback(void *arg) 1107182999Smav{ 1108182999Smav struct hdac_devinfo *devinfo = arg; 1109182999Smav struct hdac_softc *sc; 1110182999Smav 1111182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1112182999Smav devinfo->codec->sc == NULL) 1113182999Smav return; 1114182999Smav sc = devinfo->codec->sc; 1115182999Smav hdac_lock(sc); 1116182999Smav if (sc->poll_ival == 0) { 1117182999Smav hdac_unlock(sc); 1118182999Smav return; 1119182999Smav } 1120182999Smav hdac_hp_switch_handler(devinfo); 1121182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1122182999Smav hdac_jack_poll_callback, devinfo); 1123182999Smav hdac_unlock(sc); 1124182999Smav} 1125182999Smav 1126182999Smav/* 1127182999Smav * Jack detection initializer. 1128182999Smav */ 1129182999Smavstatic void 1130182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1131182999Smav{ 1132182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1133182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1134182999Smav struct hdac_widget *w; 1135182999Smav uint32_t id; 1136182999Smav int i, enable = 0, poll = 0; 1137182999Smav nid_t cad; 1138182999Smav 1139182999Smav id = hdac_codec_id(devinfo->codec); 1140182999Smav cad = devinfo->codec->cad; 1141182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1142182999Smav if (as[i].hpredir < 0) 1143182999Smav continue; 1144182999Smav 1145182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1146182999Smav if (w == NULL || w->enable == 0 || w->type != 1147182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1148182999Smav continue; 1149182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1150182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1151182999Smav device_printf(sc->dev, 1152182999Smav "No jack detection support at pin %d\n", 1153182999Smav as[i].pins[15]); 1154182999Smav continue; 1155182999Smav } 1156182999Smav enable = 1; 1157182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1158169277Sariff hdac_command(sc, 1159182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1160182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1161182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1162182999Smav } else 1163182999Smav poll = 1; 1164182999Smav HDA_BOOTVERBOSE( 1165169277Sariff device_printf(sc->dev, 1166182999Smav "Enabling headphone/speaker " 1167182999Smav "audio routing switching:\n"); 1168182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1169182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1170182999Smav ); 1171182999Smav } 1172182999Smav if (enable) { 1173182999Smav hdac_hp_switch_handler(devinfo); 1174182999Smav if (poll) { 1175182999Smav callout_reset(&sc->poll_jack, 1, 1176182999Smav hdac_jack_poll_callback, devinfo); 1177169277Sariff } 1178162922Sariff } 1179162922Sariff} 1180162922Sariff 1181182999Smav/* 1182182999Smav * Unsolicited messages handler. 1183182999Smav */ 1184162922Sariffstatic void 1185162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1186162922Sariff{ 1187162922Sariff struct hdac_softc *sc; 1188162922Sariff struct hdac_devinfo *devinfo = NULL; 1189182999Smav int i; 1190162922Sariff 1191162922Sariff if (codec == NULL || codec->sc == NULL) 1192162922Sariff return; 1193162922Sariff 1194162922Sariff sc = codec->sc; 1195162922Sariff 1196163057Sariff HDA_BOOTVERBOSE( 1197182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1198162922Sariff ); 1199162922Sariff 1200182999Smav for (i = 0; i < codec->num_fgs; i++) { 1201182999Smav if (codec->fgs[i].node_type == 1202182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1203182999Smav devinfo = &codec->fgs[i]; 1204162965Sariff break; 1205182999Smav } 1206162922Sariff } 1207162965Sariff 1208162922Sariff if (devinfo == NULL) 1209162922Sariff return; 1210162922Sariff 1211162922Sariff switch (tag) { 1212162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1213162922Sariff hdac_hp_switch_handler(devinfo); 1214162922Sariff break; 1215162922Sariff default: 1216182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1217162922Sariff break; 1218162922Sariff } 1219162922Sariff} 1220162922Sariff 1221164614Sariffstatic int 1222162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1223162922Sariff{ 1224162922Sariff /* XXX to be removed */ 1225162922Sariff#ifdef HDAC_INTR_EXTRA 1226162922Sariff uint32_t res; 1227162922Sariff#endif 1228162922Sariff 1229171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1230164614Sariff return (0); 1231162922Sariff 1232162922Sariff /* XXX to be removed */ 1233162922Sariff#ifdef HDAC_INTR_EXTRA 1234162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1235162922Sariff#endif 1236162922Sariff 1237162922Sariff /* XXX to be removed */ 1238162922Sariff#ifdef HDAC_INTR_EXTRA 1239163057Sariff HDA_BOOTVERBOSE( 1240163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1241182999Smav device_printf(ch->pdevinfo->dev, 1242163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1243163057Sariff "%08x\n", 1244163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1245163057Sariff ); 1246162922Sariff#endif 1247162922Sariff 1248162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1249163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1250162922Sariff 1251162922Sariff /* XXX to be removed */ 1252162922Sariff#ifdef HDAC_INTR_EXTRA 1253162922Sariff if (res & HDAC_SDSTS_BCIS) { 1254162922Sariff#endif 1255164614Sariff return (1); 1256162922Sariff /* XXX to be removed */ 1257162922Sariff#ifdef HDAC_INTR_EXTRA 1258162922Sariff } 1259162922Sariff#endif 1260164614Sariff 1261164614Sariff return (0); 1262162922Sariff} 1263162922Sariff 1264162922Sariff/**************************************************************************** 1265162922Sariff * void hdac_intr_handler(void *) 1266162922Sariff * 1267162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1268162922Sariff ****************************************************************************/ 1269162922Sariffstatic void 1270162922Sariffhdac_intr_handler(void *context) 1271162922Sariff{ 1272162922Sariff struct hdac_softc *sc; 1273162922Sariff uint32_t intsts; 1274162922Sariff uint8_t rirbsts; 1275164614Sariff struct hdac_rirb *rirb_base; 1276171141Sariff uint32_t trigger; 1277182999Smav int i; 1278162922Sariff 1279162922Sariff sc = (struct hdac_softc *)context; 1280162922Sariff 1281162922Sariff hdac_lock(sc); 1282164614Sariff if (sc->polling != 0) { 1283164614Sariff hdac_unlock(sc); 1284164614Sariff return; 1285164614Sariff } 1286171141Sariff 1287162922Sariff /* Do we have anything to do? */ 1288162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1289163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1290162922Sariff hdac_unlock(sc); 1291162922Sariff return; 1292162922Sariff } 1293162922Sariff 1294171141Sariff trigger = 0; 1295171141Sariff 1296162922Sariff /* Was this a controller interrupt? */ 1297163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1298162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1299162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1300162922Sariff /* Get as many responses that we can */ 1301163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1302164614Sariff HDAC_WRITE_1(&sc->mem, 1303164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1304171141Sariff if (hdac_rirb_flush(sc) != 0) 1305171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1306162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1307162922Sariff } 1308162922Sariff /* XXX to be removed */ 1309162922Sariff /* Clear interrupt and exit */ 1310162922Sariff#ifdef HDAC_INTR_EXTRA 1311162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1312162922Sariff#endif 1313162922Sariff } 1314164614Sariff 1315163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1316182999Smav for (i = 0; i < sc->num_chans; i++) { 1317182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1318182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1319182999Smav trigger |= (1 << i); 1320182999Smav } 1321162922Sariff /* XXX to be removed */ 1322162922Sariff#ifdef HDAC_INTR_EXTRA 1323164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1324164614Sariff HDAC_INTSTS_SIS_MASK); 1325162922Sariff#endif 1326162922Sariff } 1327162922Sariff 1328164614Sariff hdac_unlock(sc); 1329162922Sariff 1330182999Smav for (i = 0; i < sc->num_chans; i++) { 1331182999Smav if (trigger & (1 << i)) 1332182999Smav chn_intr(sc->chans[i].c); 1333182999Smav } 1334171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1335171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1336162922Sariff} 1337162922Sariff 1338162922Sariff/**************************************************************************** 1339182999Smav * int hdac_reset(hdac_softc *, int) 1340162922Sariff * 1341162922Sariff * Reset the hdac to a quiescent and known state. 1342162922Sariff ****************************************************************************/ 1343162922Sariffstatic int 1344182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1345162922Sariff{ 1346162922Sariff uint32_t gctl; 1347162922Sariff int count, i; 1348162922Sariff 1349162922Sariff /* 1350162922Sariff * Stop all Streams DMA engine 1351162922Sariff */ 1352162922Sariff for (i = 0; i < sc->num_iss; i++) 1353162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1354162922Sariff for (i = 0; i < sc->num_oss; i++) 1355162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1356162922Sariff for (i = 0; i < sc->num_bss; i++) 1357162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1358162922Sariff 1359162922Sariff /* 1360169277Sariff * Stop Control DMA engines. 1361162922Sariff */ 1362162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1363162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1364162922Sariff 1365162922Sariff /* 1366169277Sariff * Reset DMA position buffer. 1367169277Sariff */ 1368169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1369169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1370169277Sariff 1371169277Sariff /* 1372162922Sariff * Reset the controller. The reset must remain asserted for 1373162922Sariff * a minimum of 100us. 1374162922Sariff */ 1375162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1376162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1377162922Sariff count = 10000; 1378162922Sariff do { 1379162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1380162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1381162922Sariff break; 1382162922Sariff DELAY(10); 1383162922Sariff } while (--count); 1384162922Sariff if (gctl & HDAC_GCTL_CRST) { 1385162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1386162922Sariff return (ENXIO); 1387162922Sariff } 1388182999Smav 1389182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1390182999Smav if (!wakeup) 1391182999Smav return (0); 1392182999Smav 1393162922Sariff DELAY(100); 1394162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1395162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1396162922Sariff count = 10000; 1397162922Sariff do { 1398162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1399163057Sariff if (gctl & HDAC_GCTL_CRST) 1400162922Sariff break; 1401162922Sariff DELAY(10); 1402162922Sariff } while (--count); 1403162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1404162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1405162922Sariff return (ENXIO); 1406162922Sariff } 1407162922Sariff 1408162922Sariff /* 1409162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1410162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1411162922Sariff * computer. Let's use twice as much as necessary to make sure that 1412162922Sariff * it's reset properly. 1413162922Sariff */ 1414162922Sariff DELAY(1000); 1415162922Sariff 1416162922Sariff return (0); 1417162922Sariff} 1418162922Sariff 1419162922Sariff 1420162922Sariff/**************************************************************************** 1421162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1422162922Sariff * 1423162922Sariff * Retreive the general capabilities of the hdac; 1424162922Sariff * Number of Input Streams 1425162922Sariff * Number of Output Streams 1426162922Sariff * Number of bidirectional Streams 1427162922Sariff * 64bit ready 1428162922Sariff * CORB and RIRB sizes 1429162922Sariff ****************************************************************************/ 1430162922Sariffstatic int 1431162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1432162922Sariff{ 1433162922Sariff uint16_t gcap; 1434162922Sariff uint8_t corbsize, rirbsize; 1435162922Sariff 1436162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1437162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1438162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1439162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1440162922Sariff 1441163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1442162922Sariff 1443162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1444162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1445162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1446162922Sariff sc->corb_size = 256; 1447162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1448162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1449162922Sariff sc->corb_size = 16; 1450162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1451162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1452162922Sariff sc->corb_size = 2; 1453162922Sariff else { 1454162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1455162922Sariff __func__, corbsize); 1456162922Sariff return (ENXIO); 1457162922Sariff } 1458162922Sariff 1459162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1460162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1461162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1462162922Sariff sc->rirb_size = 256; 1463162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1464162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1465162922Sariff sc->rirb_size = 16; 1466162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1467162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1468162922Sariff sc->rirb_size = 2; 1469162922Sariff else { 1470162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1471162922Sariff __func__, rirbsize); 1472162922Sariff return (ENXIO); 1473162922Sariff } 1474162922Sariff 1475183097Smav HDA_BOOTHVERBOSE( 1476182999Smav device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 1477182999Smav device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 1478182999Smav device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 1479182999Smav sc->num_iss, sc->num_oss, sc->num_bss); 1480182999Smav ); 1481182999Smav 1482162922Sariff return (0); 1483162922Sariff} 1484162922Sariff 1485162922Sariff 1486162922Sariff/**************************************************************************** 1487162922Sariff * void hdac_dma_cb 1488162922Sariff * 1489162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1490162922Sariff * established. We just record the physical address of the mapping into 1491162922Sariff * the struct hdac_dma passed in. 1492162922Sariff ****************************************************************************/ 1493162922Sariffstatic void 1494162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1495162922Sariff{ 1496162922Sariff struct hdac_dma *dma; 1497162922Sariff 1498162922Sariff if (error == 0) { 1499162922Sariff dma = (struct hdac_dma *)callback_arg; 1500162922Sariff dma->dma_paddr = segs[0].ds_addr; 1501162922Sariff } 1502162922Sariff} 1503162922Sariff 1504162922Sariff 1505162922Sariff/**************************************************************************** 1506162922Sariff * int hdac_dma_alloc 1507162922Sariff * 1508162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1509162922Sariff * It must be freed by a corresponding hdac_dma_free. 1510162922Sariff ****************************************************************************/ 1511162922Sariffstatic int 1512162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1513162922Sariff{ 1514169277Sariff bus_size_t roundsz; 1515162922Sariff int result; 1516162922Sariff int lowaddr; 1517162922Sariff 1518169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1519162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1520162922Sariff BUS_SPACE_MAXADDR_32BIT; 1521162922Sariff bzero(dma, sizeof(*dma)); 1522162922Sariff 1523162922Sariff /* 1524162922Sariff * Create a DMA tag 1525162922Sariff */ 1526162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1527162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1528162922Sariff 0, /* boundary */ 1529162922Sariff lowaddr, /* lowaddr */ 1530162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1531162922Sariff NULL, /* filtfunc */ 1532162922Sariff NULL, /* fistfuncarg */ 1533169277Sariff roundsz, /* maxsize */ 1534162922Sariff 1, /* nsegments */ 1535169277Sariff roundsz, /* maxsegsz */ 1536162922Sariff 0, /* flags */ 1537162922Sariff NULL, /* lockfunc */ 1538162922Sariff NULL, /* lockfuncarg */ 1539162922Sariff &dma->dma_tag); /* dmat */ 1540162922Sariff if (result != 0) { 1541162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1542162922Sariff __func__, result); 1543167773Sariff goto hdac_dma_alloc_fail; 1544162922Sariff } 1545162922Sariff 1546162922Sariff /* 1547162922Sariff * Allocate DMA memory 1548162922Sariff */ 1549162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1550169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1551171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1552171330Sariff &dma->dma_map); 1553162922Sariff if (result != 0) { 1554162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1555162922Sariff __func__, result); 1556167773Sariff goto hdac_dma_alloc_fail; 1557162922Sariff } 1558162922Sariff 1559169277Sariff dma->dma_size = roundsz; 1560169277Sariff 1561162922Sariff /* 1562162922Sariff * Map the memory 1563162922Sariff */ 1564162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1565169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1566162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1567167773Sariff if (result == 0) 1568167773Sariff result = ENOMEM; 1569162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1570162922Sariff __func__, result); 1571167773Sariff goto hdac_dma_alloc_fail; 1572162922Sariff } 1573162922Sariff 1574183097Smav HDA_BOOTHVERBOSE( 1575169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1576169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1577169277Sariff ); 1578169277Sariff 1579162922Sariff return (0); 1580169277Sariff 1581167773Sariffhdac_dma_alloc_fail: 1582169277Sariff hdac_dma_free(sc, dma); 1583167773Sariff 1584162922Sariff return (result); 1585162922Sariff} 1586162922Sariff 1587162922Sariff 1588162922Sariff/**************************************************************************** 1589169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1590162922Sariff * 1591162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1592162922Sariff * hdac_dma_alloc function. 1593162922Sariff ****************************************************************************/ 1594162922Sariffstatic void 1595169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1596162922Sariff{ 1597167773Sariff if (dma->dma_map != NULL) { 1598169277Sariff#if 0 1599162922Sariff /* Flush caches */ 1600162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1601162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1602169277Sariff#endif 1603162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1604167773Sariff } 1605167773Sariff if (dma->dma_vaddr != NULL) { 1606162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1607167773Sariff dma->dma_vaddr = NULL; 1608167773Sariff } 1609167773Sariff dma->dma_map = NULL; 1610167773Sariff if (dma->dma_tag != NULL) { 1611162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1612167773Sariff dma->dma_tag = NULL; 1613162922Sariff } 1614167773Sariff dma->dma_size = 0; 1615162922Sariff} 1616162922Sariff 1617162922Sariff/**************************************************************************** 1618162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1619162922Sariff * 1620162922Sariff * Allocate all the bus resources necessary to speak with the physical 1621162922Sariff * controller. 1622162922Sariff ****************************************************************************/ 1623162922Sariffstatic int 1624162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1625162922Sariff{ 1626162922Sariff struct hdac_mem *mem; 1627162922Sariff 1628162922Sariff mem = &sc->mem; 1629162922Sariff mem->mem_rid = PCIR_BAR(0); 1630162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1631162922Sariff &mem->mem_rid, RF_ACTIVE); 1632162922Sariff if (mem->mem_res == NULL) { 1633162922Sariff device_printf(sc->dev, 1634162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1635162922Sariff return (ENOMEM); 1636162922Sariff } 1637162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1638162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1639162922Sariff 1640162922Sariff return (0); 1641162922Sariff} 1642162922Sariff 1643162922Sariff/**************************************************************************** 1644162922Sariff * void hdac_mem_free(struct hdac_softc *) 1645162922Sariff * 1646162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1647162922Sariff ****************************************************************************/ 1648162922Sariffstatic void 1649162922Sariffhdac_mem_free(struct hdac_softc *sc) 1650162922Sariff{ 1651162922Sariff struct hdac_mem *mem; 1652162922Sariff 1653162922Sariff mem = &sc->mem; 1654162922Sariff if (mem->mem_res != NULL) 1655162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1656162922Sariff mem->mem_res); 1657164614Sariff mem->mem_res = NULL; 1658162922Sariff} 1659162922Sariff 1660162922Sariff/**************************************************************************** 1661162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1662162922Sariff * 1663162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1664162922Sariff ****************************************************************************/ 1665162922Sariffstatic int 1666162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1667162922Sariff{ 1668162922Sariff struct hdac_irq *irq; 1669162922Sariff int result; 1670162922Sariff 1671162922Sariff irq = &sc->irq; 1672162922Sariff irq->irq_rid = 0x0; 1673171330Sariff 1674178155Sariff#ifdef HDAC_MSI_ENABLED 1675171330Sariff if ((sc->flags & HDAC_F_MSI) && 1676171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1677171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1678171330Sariff irq->irq_rid = 0x1; 1679171330Sariff else 1680171330Sariff#endif 1681171330Sariff sc->flags &= ~HDAC_F_MSI; 1682171330Sariff 1683162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1684162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1685162922Sariff if (irq->irq_res == NULL) { 1686162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1687162922Sariff __func__); 1688167773Sariff goto hdac_irq_alloc_fail; 1689162922Sariff } 1690182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1691182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1692162922Sariff if (result != 0) { 1693162922Sariff device_printf(sc->dev, 1694162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1695162922Sariff __func__, result); 1696167773Sariff goto hdac_irq_alloc_fail; 1697162922Sariff } 1698162922Sariff 1699162922Sariff return (0); 1700162922Sariff 1701167773Sariffhdac_irq_alloc_fail: 1702164614Sariff hdac_irq_free(sc); 1703164614Sariff 1704162922Sariff return (ENXIO); 1705162922Sariff} 1706162922Sariff 1707162922Sariff/**************************************************************************** 1708162922Sariff * void hdac_irq_free(struct hdac_softc *) 1709162922Sariff * 1710162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1711162922Sariff ****************************************************************************/ 1712162922Sariffstatic void 1713162922Sariffhdac_irq_free(struct hdac_softc *sc) 1714162922Sariff{ 1715162922Sariff struct hdac_irq *irq; 1716162922Sariff 1717162922Sariff irq = &sc->irq; 1718164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1719162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1720162922Sariff if (irq->irq_res != NULL) 1721162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1722162922Sariff irq->irq_res); 1723178155Sariff#ifdef HDAC_MSI_ENABLED 1724171330Sariff if ((sc->flags & HDAC_F_MSI) && irq->irq_rid == 0x1) 1725171330Sariff pci_release_msi(sc->dev); 1726171330Sariff#endif 1727164614Sariff irq->irq_handle = NULL; 1728164614Sariff irq->irq_res = NULL; 1729171330Sariff irq->irq_rid = 0x0; 1730162922Sariff} 1731162922Sariff 1732162922Sariff/**************************************************************************** 1733162922Sariff * void hdac_corb_init(struct hdac_softc *) 1734162922Sariff * 1735162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1736162922Sariff * The CORB engine must not be running when this function is called. 1737162922Sariff ****************************************************************************/ 1738162922Sariffstatic void 1739162922Sariffhdac_corb_init(struct hdac_softc *sc) 1740162922Sariff{ 1741162922Sariff uint8_t corbsize; 1742162922Sariff uint64_t corbpaddr; 1743162922Sariff 1744162922Sariff /* Setup the CORB size. */ 1745162922Sariff switch (sc->corb_size) { 1746162922Sariff case 256: 1747162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1748162922Sariff break; 1749162922Sariff case 16: 1750162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1751162922Sariff break; 1752162922Sariff case 2: 1753162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1754162922Sariff break; 1755162922Sariff default: 1756162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1757162922Sariff } 1758162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1759162922Sariff 1760162922Sariff /* Setup the CORB Address in the hdac */ 1761162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1762162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1763162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1764162922Sariff 1765162922Sariff /* Set the WP and RP */ 1766162922Sariff sc->corb_wp = 0; 1767162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1768162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1769162922Sariff /* 1770162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1771162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1772162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1773162922Sariff * manually reset the bit to zero before continuing. 1774162922Sariff */ 1775162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1776162922Sariff 1777162922Sariff /* Enable CORB error reporting */ 1778162922Sariff#if 0 1779162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1780162922Sariff#endif 1781162922Sariff} 1782162922Sariff 1783162922Sariff/**************************************************************************** 1784162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1785162922Sariff * 1786162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1787162922Sariff * The RIRB engine must not be running when this function is called. 1788162922Sariff ****************************************************************************/ 1789162922Sariffstatic void 1790162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1791162922Sariff{ 1792162922Sariff uint8_t rirbsize; 1793162922Sariff uint64_t rirbpaddr; 1794162922Sariff 1795162922Sariff /* Setup the RIRB size. */ 1796162922Sariff switch (sc->rirb_size) { 1797162922Sariff case 256: 1798162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1799162922Sariff break; 1800162922Sariff case 16: 1801162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1802162922Sariff break; 1803162922Sariff case 2: 1804162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1805162922Sariff break; 1806162922Sariff default: 1807162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1808162922Sariff } 1809162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1810162922Sariff 1811162922Sariff /* Setup the RIRB Address in the hdac */ 1812162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1813162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1814162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1815162922Sariff 1816162922Sariff /* Setup the WP and RP */ 1817162922Sariff sc->rirb_rp = 0; 1818162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1819162922Sariff 1820182999Smav /* Setup the interrupt threshold */ 1821182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1822162922Sariff 1823182999Smav /* Enable Overrun and response received reporting */ 1824162922Sariff#if 0 1825182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1826182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1827162922Sariff#else 1828182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1829162922Sariff#endif 1830162922Sariff 1831169277Sariff#if 0 1832162922Sariff /* 1833162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1834162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1835162922Sariff * should be sufficient to do this only once as the rirb is purely 1836162922Sariff * read-only from now on. 1837162922Sariff */ 1838162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1839162922Sariff BUS_DMASYNC_PREREAD); 1840169277Sariff#endif 1841162922Sariff} 1842162922Sariff 1843162922Sariff/**************************************************************************** 1844162922Sariff * void hdac_corb_start(hdac_softc *) 1845162922Sariff * 1846162922Sariff * Startup the corb DMA engine 1847162922Sariff ****************************************************************************/ 1848162922Sariffstatic void 1849162922Sariffhdac_corb_start(struct hdac_softc *sc) 1850162922Sariff{ 1851162922Sariff uint32_t corbctl; 1852162922Sariff 1853162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1854162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1855162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1856162922Sariff} 1857162922Sariff 1858162922Sariff/**************************************************************************** 1859162922Sariff * void hdac_rirb_start(hdac_softc *) 1860162922Sariff * 1861162922Sariff * Startup the rirb DMA engine 1862162922Sariff ****************************************************************************/ 1863162922Sariffstatic void 1864162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1865162922Sariff{ 1866162922Sariff uint32_t rirbctl; 1867162922Sariff 1868162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1869162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1870162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1871162922Sariff} 1872162922Sariff 1873162922Sariff 1874162922Sariff/**************************************************************************** 1875172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 1876162922Sariff * 1877172811Sariff * Scan the bus for available codecs, starting with num. 1878162922Sariff ****************************************************************************/ 1879162922Sariffstatic void 1880182999Smavhdac_scan_codecs(struct hdac_softc *sc) 1881162922Sariff{ 1882162922Sariff struct hdac_codec *codec; 1883162922Sariff int i; 1884162922Sariff uint16_t statests; 1885162922Sariff 1886162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1887182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1888162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1889162922Sariff /* We have found a codec. */ 1890162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1891162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1892162922Sariff if (codec == NULL) { 1893162922Sariff device_printf(sc->dev, 1894162922Sariff "Unable to allocate memory for codec\n"); 1895162922Sariff continue; 1896162922Sariff } 1897164614Sariff codec->commands = NULL; 1898164614Sariff codec->responses_received = 0; 1899162922Sariff codec->verbs_sent = 0; 1900162922Sariff codec->sc = sc; 1901162922Sariff codec->cad = i; 1902162922Sariff sc->codecs[i] = codec; 1903182999Smav hdac_probe_codec(codec); 1904162922Sariff } 1905162922Sariff } 1906162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1907163057Sariff /* bus_generic_attach(sc->dev); */ 1908162922Sariff} 1909162922Sariff 1910162922Sariff/**************************************************************************** 1911162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1912162922Sariff * 1913162922Sariff * Probe a the given codec_id for available function groups. 1914162922Sariff ****************************************************************************/ 1915182999Smavstatic void 1916162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1917162922Sariff{ 1918162922Sariff struct hdac_softc *sc = codec->sc; 1919162922Sariff uint32_t vendorid, revisionid, subnode; 1920162922Sariff int startnode; 1921162922Sariff int endnode; 1922162922Sariff int i; 1923162922Sariff nid_t cad = codec->cad; 1924162922Sariff 1925163057Sariff HDA_BOOTVERBOSE( 1926184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 1927162922Sariff ); 1928162922Sariff vendorid = hdac_command(sc, 1929162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1930162922Sariff cad); 1931162922Sariff revisionid = hdac_command(sc, 1932162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1933162922Sariff cad); 1934182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1935182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1936182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1937182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1938182999Smav 1939182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 1940182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 1941182999Smav " Probing aborted.\n", cad); 1942182999Smav return; 1943182999Smav } 1944182999Smav 1945184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 1946182999Smav cad, hdac_codec_name(codec)); 1947182999Smav HDA_BOOTVERBOSE( 1948184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 1949182999Smav hdac_codec_id(codec)); 1950182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 1951182999Smav codec->vendor_id); 1952182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 1953182999Smav codec->device_id); 1954182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 1955182999Smav codec->revision_id); 1956182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 1957182999Smav codec->stepping_id); 1958182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 1959182999Smav sc->pci_subvendor); 1960182999Smav ); 1961162922Sariff subnode = hdac_command(sc, 1962162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1963162922Sariff cad); 1964162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1965162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1966162922Sariff 1967183097Smav HDA_BOOTHVERBOSE( 1968182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 1969163057Sariff startnode, endnode); 1970162922Sariff ); 1971182999Smav 1972182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 1973182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 1974182999Smav if (codec->fgs == NULL) { 1975183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 1976182999Smav __func__); 1977182999Smav return; 1978162922Sariff } 1979162922Sariff 1980182999Smav for (i = startnode; i < endnode; i++) 1981182999Smav hdac_probe_function(codec, i); 1982182999Smav return; 1983162922Sariff} 1984162922Sariff 1985182999Smav/* 1986182999Smav * Probe codec function and add it to the list. 1987182999Smav */ 1988182999Smavstatic void 1989162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1990162922Sariff{ 1991162922Sariff struct hdac_softc *sc = codec->sc; 1992182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 1993162922Sariff uint32_t fctgrptype; 1994182999Smav uint32_t res; 1995162922Sariff nid_t cad = codec->cad; 1996162922Sariff 1997162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1998162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1999162922Sariff 2000162922Sariff devinfo->nid = nid; 2001162965Sariff devinfo->node_type = fctgrptype; 2002162922Sariff devinfo->codec = codec; 2003162922Sariff 2004182999Smav res = hdac_command(sc, 2005182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2006162922Sariff 2007182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2008182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2009182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2010162922Sariff 2011182999Smav HDA_BOOTVERBOSE( 2012182999Smav device_printf(sc->dev, 2013182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2014182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2015182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2016182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2017182999Smav devinfo->nodecnt); 2018182999Smav ); 2019182999Smav 2020182999Smav if (devinfo->nodecnt > 0) 2021182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2022182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2023182999Smav M_NOWAIT | M_ZERO); 2024182999Smav else 2025182999Smav devinfo->widget = NULL; 2026182999Smav 2027182999Smav if (devinfo->widget == NULL) { 2028182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2029182999Smav devinfo->endnode = devinfo->startnode; 2030182999Smav devinfo->nodecnt = 0; 2031182999Smav return; 2032182999Smav } 2033182999Smav 2034182999Smav codec->num_fgs++; 2035162922Sariff} 2036162922Sariff 2037162922Sariffstatic void 2038162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2039162922Sariff{ 2040162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2041162922Sariff uint32_t res; 2042169277Sariff int i, j, max, ents, entnum; 2043162922Sariff nid_t cad = w->devinfo->codec->cad; 2044162922Sariff nid_t nid = w->nid; 2045169277Sariff nid_t cnid, addcnid, prevcnid; 2046162922Sariff 2047169277Sariff w->nconns = 0; 2048169277Sariff 2049162922Sariff res = hdac_command(sc, 2050162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2051162922Sariff 2052169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2053162922Sariff 2054169277Sariff if (ents < 1) 2055162922Sariff return; 2056162922Sariff 2057162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2058162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2059169277Sariff prevcnid = 0; 2060162922Sariff 2061169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2062169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2063169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2064169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2065169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2066169277Sariff 2067169277Sariff for (i = 0; i < ents; i += entnum) { 2068162922Sariff res = hdac_command(sc, 2069162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2070162922Sariff for (j = 0; j < entnum; j++) { 2071169277Sariff cnid = CONN_CNID(res, entnum, j); 2072169277Sariff if (cnid == 0) { 2073169277Sariff if (w->nconns < ents) 2074169277Sariff device_printf(sc->dev, 2075169277Sariff "%s: nid=%d WARNING: zero cnid " 2076169277Sariff "entnum=%d j=%d index=%d " 2077169277Sariff "entries=%d found=%d res=0x%08x\n", 2078169277Sariff __func__, nid, entnum, j, i, 2079169277Sariff ents, w->nconns, res); 2080169277Sariff else 2081169277Sariff goto getconns_out; 2082169277Sariff } 2083169277Sariff if (cnid < w->devinfo->startnode || 2084169277Sariff cnid >= w->devinfo->endnode) { 2085169277Sariff HDA_BOOTVERBOSE( 2086169277Sariff device_printf(sc->dev, 2087182999Smav "GHOST: nid=%d j=%d " 2088169277Sariff "entnum=%d index=%d res=0x%08x\n", 2089182999Smav nid, j, entnum, i, res); 2090169277Sariff ); 2091169277Sariff } 2092169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2093169277Sariff addcnid = cnid; 2094169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2095162922Sariff device_printf(sc->dev, 2096169277Sariff "%s: WARNING: Invalid child range " 2097169277Sariff "nid=%d index=%d j=%d entnum=%d " 2098169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2099169277Sariff __func__, nid, i, j, entnum, prevcnid, 2100169277Sariff cnid, res); 2101169277Sariff addcnid = cnid; 2102169277Sariff } else 2103169277Sariff addcnid = prevcnid + 1; 2104169277Sariff while (addcnid <= cnid) { 2105169277Sariff if (w->nconns > max) { 2106169277Sariff device_printf(sc->dev, 2107182999Smav "Adding %d (nid=%d): " 2108169277Sariff "Max connection reached! max=%d\n", 2109182999Smav addcnid, nid, max + 1); 2110169277Sariff goto getconns_out; 2111169277Sariff } 2112182999Smav w->connsenable[w->nconns] = 1; 2113169277Sariff w->conns[w->nconns++] = addcnid++; 2114162922Sariff } 2115169277Sariff prevcnid = cnid; 2116162922Sariff } 2117162922Sariff } 2118162922Sariff 2119169277Sariffgetconns_out: 2120169277Sariff return; 2121162922Sariff} 2122162922Sariff 2123162922Sariffstatic uint32_t 2124182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2125182999Smav{ 2126182999Smav char buf[256]; 2127182999Smav char *key, *value, *rest, *bad; 2128182999Smav int ival, i; 2129182999Smav 2130182999Smav strlcpy(buf, str, sizeof(buf)); 2131182999Smav rest = buf; 2132182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2133182999Smav value = strsep(&rest, " \t"); 2134182999Smav if (value == NULL) 2135182999Smav break; 2136182999Smav ival = strtol(value, &bad, 10); 2137182999Smav if (strcmp(key, "seq") == 0) { 2138182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2139182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2140182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2141182999Smav } else if (strcmp(key, "as") == 0) { 2142182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2143182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2144182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2145182999Smav } else if (strcmp(key, "misc") == 0) { 2146182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2147182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2148182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2149182999Smav } else if (strcmp(key, "color") == 0) { 2150182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2151182999Smav if (bad[0] == 0) { 2152182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2153182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2154182999Smav }; 2155182999Smav for (i = 0; i < 16; i++) { 2156182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2157182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2158182999Smav break; 2159182999Smav } 2160182999Smav } 2161182999Smav } else if (strcmp(key, "ctype") == 0) { 2162182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2163182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2164182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2165182999Smav } else if (strcmp(key, "device") == 0) { 2166182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2167182999Smav if (bad[0] == 0) { 2168182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2169182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2170182999Smav continue; 2171182999Smav }; 2172182999Smav for (i = 0; i < 16; i++) { 2173182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2174182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2175182999Smav break; 2176182999Smav } 2177182999Smav } 2178182999Smav } else if (strcmp(key, "loc") == 0) { 2179182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2180182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2181182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2182182999Smav } else if (strcmp(key, "conn") == 0) { 2183182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2184182999Smav if (bad[0] == 0) { 2185182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2186182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2187182999Smav continue; 2188182999Smav }; 2189182999Smav for (i = 0; i < 4; i++) { 2190182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2191182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2192182999Smav break; 2193182999Smav } 2194182999Smav } 2195182999Smav } 2196182999Smav } 2197182999Smav return (config); 2198182999Smav} 2199182999Smav 2200182999Smavstatic uint32_t 2201162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2202162922Sariff{ 2203162922Sariff struct hdac_softc *sc; 2204166965Sariff uint32_t config, orig, id; 2205162922Sariff nid_t cad, nid; 2206182999Smav char buf[32]; 2207182999Smav const char *res = NULL, *patch = NULL; 2208162922Sariff 2209162922Sariff sc = w->devinfo->codec->sc; 2210162922Sariff cad = w->devinfo->codec->cad; 2211162922Sariff nid = w->nid; 2212182999Smav id = hdac_codec_id(w->devinfo->codec); 2213162922Sariff 2214162922Sariff config = hdac_command(sc, 2215162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2216162922Sariff cad); 2217166965Sariff orig = config; 2218166965Sariff 2219182999Smav HDA_BOOTVERBOSE( 2220182999Smav hdac_dump_pin_config(w, orig); 2221182999Smav ); 2222182999Smav 2223182999Smav /* XXX: Old patches require complete review. 2224182999Smav * Now they may create more problem then solve due to 2225182999Smav * incorrect associations. 2226162965Sariff */ 2227165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2228165281Sariff switch (nid) { 2229165281Sariff case 26: 2230165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2231165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2232165281Sariff break; 2233165281Sariff case 27: 2234165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2235165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2236165281Sariff break; 2237167610Sariff default: 2238167610Sariff break; 2239165281Sariff } 2240165281Sariff } else if (id == HDA_CODEC_ALC880 && 2241162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2242162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2243162922Sariff /* 2244162965Sariff * Super broken BIOS 2245162922Sariff */ 2246162922Sariff switch (nid) { 2247162922Sariff case 24: /* MIC1 */ 2248162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2249162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2250162922Sariff break; 2251162922Sariff case 25: /* XXX MIC2 */ 2252162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2253162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2254162922Sariff break; 2255162922Sariff case 26: /* LINE1 */ 2256162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2257162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2258162922Sariff break; 2259162922Sariff case 27: /* XXX LINE2 */ 2260162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2261162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2262162922Sariff break; 2263162922Sariff case 28: /* CD */ 2264162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2265162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2266162922Sariff break; 2267162922Sariff } 2268166965Sariff } else if (id == HDA_CODEC_ALC883 && 2269172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2270172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2271166965Sariff switch (nid) { 2272166965Sariff case 25: 2273166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2274166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2275166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2276166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2277166965Sariff break; 2278169277Sariff case 28: 2279169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2280169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2281169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2282169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2283169277Sariff break; 2284166965Sariff } 2285186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2286166965Sariff HP_V3000_SUBVENDOR) { 2287166965Sariff switch (nid) { 2288166965Sariff case 18: 2289166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2290166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2291166965Sariff break; 2292166965Sariff case 20: 2293166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2294166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2295166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2296166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2297166965Sariff break; 2298167454Sariff case 21: 2299167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2300167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2301167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2302167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2303167454Sariff break; 2304166965Sariff } 2305186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2306169277Sariff HP_DV5000_SUBVENDOR) { 2307169277Sariff switch (nid) { 2308169277Sariff case 20: 2309169277Sariff case 21: 2310169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2311169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2312169277Sariff break; 2313169277Sariff } 2314169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2315169277Sariff ASUS_W6F_SUBVENDOR) { 2316169277Sariff switch (nid) { 2317169277Sariff case 11: 2318169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2319169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2320169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2321169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2322169277Sariff break; 2323178324Sariff case 12: 2324178324Sariff case 14: 2325178324Sariff case 16: 2326178324Sariff case 31: 2327178324Sariff case 32: 2328178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2329178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2330178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2331178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2332178324Sariff break; 2333169277Sariff case 15: 2334169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2335169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2336169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2337169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2338169277Sariff break; 2339169277Sariff } 2340169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2341169277Sariff UNIWILL_9075_SUBVENDOR) { 2342169277Sariff switch (nid) { 2343169277Sariff case 15: 2344169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2345169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2346169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2347169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2348169277Sariff break; 2349169277Sariff } 2350182999Smav } 2351182999Smav 2352182999Smav /* New patches */ 2353182999Smav if (id == HDA_CODEC_AD1986A && 2354171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2355171141Sariff sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) { 2356169277Sariff switch (nid) { 2357182999Smav case 28: /* 5.1 out => 2.0 out + 2 inputs */ 2358182999Smav patch = "device=Line-in as=8 seq=1"; 2359169277Sariff break; 2360182999Smav case 29: 2361182999Smav patch = "device=Mic as=8 seq=2"; 2362169277Sariff break; 2363182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2364182999Smav patch = "as=8 seq=3"; 2365169277Sariff break; 2366182999Smav case 32: 2367182999Smav patch = "as=8 seq=4"; 2368182999Smav break; 2369182999Smav case 34: 2370182999Smav patch = "as=8 seq=5"; 2371182999Smav break; 2372182999Smav case 36: 2373182999Smav patch = "as=8 seq=6"; 2374182999Smav break; 2375169277Sariff } 2376182999Smav } else if (id == HDA_CODEC_ALC260 && 2377182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2378182999Smav switch (nid) { 2379182999Smav case 16: 2380182999Smav patch = "seq=15 device=Headphones"; 2381182999Smav break; 2382182999Smav } 2383174578Sariff } else if (id == HDA_CODEC_ALC268 && 2384174578Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) { 2385174578Sariff switch (nid) { 2386174578Sariff case 28: 2387182999Smav patch = "device=CD conn=fixed"; 2388174578Sariff break; 2389174578Sariff } 2390162922Sariff } 2391162922Sariff 2392182999Smav if (patch != NULL) 2393182999Smav config = hdac_widget_pin_patch(config, patch); 2394182999Smav 2395182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2396182999Smav if (resource_string_value(device_get_name(sc->dev), 2397182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2398182999Smav if (strncmp(res, "0x", 2) == 0) { 2399182999Smav config = strtol(res + 2, NULL, 16); 2400182999Smav } else { 2401182999Smav config = hdac_widget_pin_patch(config, res); 2402182999Smav } 2403182999Smav } 2404182999Smav 2405166965Sariff HDA_BOOTVERBOSE( 2406166965Sariff if (config != orig) 2407166965Sariff device_printf(sc->dev, 2408182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2409166965Sariff nid, orig, config); 2410166965Sariff ); 2411166965Sariff 2412162922Sariff return (config); 2413162922Sariff} 2414162922Sariff 2415166965Sariffstatic uint32_t 2416166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2417166965Sariff{ 2418166965Sariff struct hdac_softc *sc; 2419166965Sariff uint32_t caps, orig, id; 2420166965Sariff nid_t cad, nid; 2421166965Sariff 2422166965Sariff sc = w->devinfo->codec->sc; 2423166965Sariff cad = w->devinfo->codec->cad; 2424166965Sariff nid = w->nid; 2425182999Smav id = hdac_codec_id(w->devinfo->codec); 2426166965Sariff 2427166965Sariff caps = hdac_command(sc, 2428166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2429166965Sariff orig = caps; 2430166965Sariff 2431166965Sariff HDA_BOOTVERBOSE( 2432166965Sariff if (caps != orig) 2433166965Sariff device_printf(sc->dev, 2434182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2435166965Sariff nid, orig, caps); 2436166965Sariff ); 2437166965Sariff 2438166965Sariff return (caps); 2439166965Sariff} 2440166965Sariff 2441162922Sariffstatic void 2442162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2443162922Sariff{ 2444162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2445162922Sariff uint32_t config, pincap; 2446182999Smav const char *devstr, *connstr; 2447162922Sariff nid_t cad = w->devinfo->codec->cad; 2448162922Sariff nid_t nid = w->nid; 2449162922Sariff 2450162922Sariff config = hdac_widget_pin_getconfig(w); 2451162922Sariff w->wclass.pin.config = config; 2452162922Sariff 2453166965Sariff pincap = hdac_widget_pin_getcaps(w); 2454162922Sariff w->wclass.pin.cap = pincap; 2455162922Sariff 2456162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2457182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2458162922Sariff 2459162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2460162922Sariff w->param.eapdbtl = hdac_command(sc, 2461162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2462162922Sariff w->param.eapdbtl &= 0x7; 2463162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2464162922Sariff } else 2465162965Sariff w->param.eapdbtl = HDAC_INVALID; 2466162922Sariff 2467182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2468182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2469162922Sariff 2470182999Smav connstr = HDA_CONNS[(config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2471182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT]; 2472162922Sariff 2473162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2474162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2475162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2476162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 2477162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2478162922Sariff} 2479162922Sariff 2480182999Smavstatic uint32_t 2481182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2482182999Smav{ 2483182999Smav struct hdac_softc *sc; 2484182999Smav uint32_t caps, orig, id; 2485182999Smav nid_t cad, nid, beeper = -1; 2486182999Smav 2487182999Smav sc = w->devinfo->codec->sc; 2488182999Smav cad = w->devinfo->codec->cad; 2489182999Smav nid = w->nid; 2490182999Smav id = hdac_codec_id(w->devinfo->codec); 2491182999Smav 2492182999Smav caps = hdac_command(sc, 2493182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2494182999Smav cad); 2495182999Smav orig = caps; 2496182999Smav 2497182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2498182999Smav alone. Also most of BIOSes does not declare beeper pin. 2499182999Smav Change beeper pin node type to beeper to help parser. */ 2500182999Smav *waspin = 0; 2501182999Smav switch (id) { 2502182999Smav case HDA_CODEC_AD1988: 2503182999Smav case HDA_CODEC_AD1988B: 2504182999Smav beeper = 26; 2505182999Smav break; 2506182999Smav case HDA_CODEC_ALC260: 2507182999Smav beeper = 23; 2508182999Smav break; 2509182999Smav case HDA_CODEC_ALC262: 2510182999Smav case HDA_CODEC_ALC268: 2511182999Smav case HDA_CODEC_ALC880: 2512182999Smav case HDA_CODEC_ALC882: 2513182999Smav case HDA_CODEC_ALC883: 2514182999Smav case HDA_CODEC_ALC885: 2515182999Smav case HDA_CODEC_ALC888: 2516182999Smav case HDA_CODEC_ALC889: 2517182999Smav beeper = 29; 2518182999Smav break; 2519182999Smav } 2520182999Smav if (nid == beeper) { 2521182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2522182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2523182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2524182999Smav *waspin = 1; 2525182999Smav } 2526182999Smav 2527182999Smav HDA_BOOTVERBOSE( 2528182999Smav if (caps != orig) { 2529182999Smav device_printf(sc->dev, 2530182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2531182999Smav nid, orig, caps); 2532182999Smav } 2533182999Smav ); 2534182999Smav 2535182999Smav return (caps); 2536182999Smav} 2537182999Smav 2538162922Sariffstatic void 2539162922Sariffhdac_widget_parse(struct hdac_widget *w) 2540162922Sariff{ 2541162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2542162922Sariff uint32_t wcap, cap; 2543162922Sariff char *typestr; 2544162922Sariff nid_t cad = w->devinfo->codec->cad; 2545162922Sariff nid_t nid = w->nid; 2546162922Sariff 2547182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2548182999Smav 2549162922Sariff w->param.widget_cap = wcap; 2550162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2551162922Sariff 2552162922Sariff switch (w->type) { 2553162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2554162922Sariff typestr = "audio output"; 2555162922Sariff break; 2556162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2557162922Sariff typestr = "audio input"; 2558162922Sariff break; 2559162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2560162922Sariff typestr = "audio mixer"; 2561162922Sariff break; 2562162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2563162922Sariff typestr = "audio selector"; 2564162922Sariff break; 2565162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2566162922Sariff typestr = "pin"; 2567162922Sariff break; 2568162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2569162922Sariff typestr = "power widget"; 2570162922Sariff break; 2571162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2572162922Sariff typestr = "volume widget"; 2573162922Sariff break; 2574162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2575162922Sariff typestr = "beep widget"; 2576162922Sariff break; 2577162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2578162922Sariff typestr = "vendor widget"; 2579162922Sariff break; 2580162922Sariff default: 2581162922Sariff typestr = "unknown type"; 2582162922Sariff break; 2583162922Sariff } 2584162922Sariff 2585162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2586162922Sariff 2587162922Sariff hdac_widget_connection_parse(w); 2588162922Sariff 2589162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2590162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2591162922Sariff w->param.outamp_cap = 2592162922Sariff hdac_command(sc, 2593162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2594162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2595162922Sariff else 2596162922Sariff w->param.outamp_cap = 2597162922Sariff w->devinfo->function.audio.outamp_cap; 2598162922Sariff } else 2599162922Sariff w->param.outamp_cap = 0; 2600162922Sariff 2601162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2602162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2603162922Sariff w->param.inamp_cap = 2604162922Sariff hdac_command(sc, 2605162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2606162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2607162922Sariff else 2608162922Sariff w->param.inamp_cap = 2609162922Sariff w->devinfo->function.audio.inamp_cap; 2610162922Sariff } else 2611162922Sariff w->param.inamp_cap = 0; 2612162922Sariff 2613162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2614162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2615162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2616162922Sariff cap = hdac_command(sc, 2617162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2618162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2619162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2620162922Sariff w->devinfo->function.audio.supp_stream_formats; 2621162922Sariff cap = hdac_command(sc, 2622162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2623162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2624162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2625162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2626162922Sariff } else { 2627162922Sariff w->param.supp_stream_formats = 2628162922Sariff w->devinfo->function.audio.supp_stream_formats; 2629162922Sariff w->param.supp_pcm_size_rate = 2630162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2631162922Sariff } 2632162922Sariff } else { 2633162922Sariff w->param.supp_stream_formats = 0; 2634162922Sariff w->param.supp_pcm_size_rate = 0; 2635162922Sariff } 2636162922Sariff 2637162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2638162922Sariff hdac_widget_pin_parse(w); 2639162922Sariff} 2640162922Sariff 2641162922Sariffstatic struct hdac_widget * 2642162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2643162922Sariff{ 2644162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2645162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2646162922Sariff return (NULL); 2647162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2648162922Sariff} 2649162922Sariff 2650164614Sariffstatic __inline int 2651164614Sariffhda_poll_channel(struct hdac_chan *ch) 2652164614Sariff{ 2653164614Sariff uint32_t sz, delta; 2654164614Sariff volatile uint32_t ptr; 2655164614Sariff 2656171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2657164614Sariff return (0); 2658164614Sariff 2659164614Sariff sz = ch->blksz * ch->blkcnt; 2660169277Sariff if (ch->dmapos != NULL) 2661169277Sariff ptr = *(ch->dmapos); 2662169277Sariff else 2663169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2664169277Sariff ch->off + HDAC_SDLPIB); 2665164614Sariff ch->ptr = ptr; 2666164614Sariff ptr %= sz; 2667164614Sariff ptr &= ~(ch->blksz - 1); 2668164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2669164614Sariff 2670164614Sariff if (delta < ch->blksz) 2671164614Sariff return (0); 2672164614Sariff 2673164614Sariff ch->prevptr = ptr; 2674164614Sariff 2675164614Sariff return (1); 2676164614Sariff} 2677164614Sariff 2678162922Sariffstatic void 2679164614Sariffhda_poll_callback(void *arg) 2680164614Sariff{ 2681164614Sariff struct hdac_softc *sc = arg; 2682171141Sariff uint32_t trigger; 2683182999Smav int i, active = 0; 2684164614Sariff 2685164614Sariff if (sc == NULL) 2686164614Sariff return; 2687164614Sariff 2688164614Sariff hdac_lock(sc); 2689182999Smav if (sc->polling == 0) { 2690164614Sariff hdac_unlock(sc); 2691164614Sariff return; 2692164614Sariff } 2693164614Sariff 2694171141Sariff trigger = 0; 2695182999Smav for (i = 0; i < sc->num_chans; i++) { 2696182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2697182999Smav continue; 2698182999Smav active = 1; 2699182999Smav if (hda_poll_channel(&sc->chans[i])) 2700182999Smav trigger |= (1 << i); 2701182999Smav } 2702164614Sariff 2703164614Sariff /* XXX */ 2704182999Smav if (active) 2705182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2706182999Smav hda_poll_callback, sc); 2707164614Sariff 2708164614Sariff hdac_unlock(sc); 2709164614Sariff 2710182999Smav for (i = 0; i < sc->num_chans; i++) { 2711182999Smav if (trigger & (1 << i)) 2712182999Smav chn_intr(sc->chans[i].c); 2713182999Smav } 2714164614Sariff} 2715164614Sariff 2716164614Sariffstatic int 2717164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2718164614Sariff{ 2719164614Sariff struct hdac_rirb *rirb_base, *rirb; 2720164614Sariff struct hdac_codec *codec; 2721164614Sariff struct hdac_command_list *commands; 2722164614Sariff nid_t cad; 2723164614Sariff uint32_t resp; 2724164614Sariff uint8_t rirbwp; 2725171141Sariff int ret; 2726164614Sariff 2727164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2728164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2729169277Sariff#if 0 2730164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2731164614Sariff BUS_DMASYNC_POSTREAD); 2732169277Sariff#endif 2733164614Sariff 2734171141Sariff ret = 0; 2735171141Sariff 2736164614Sariff while (sc->rirb_rp != rirbwp) { 2737164614Sariff sc->rirb_rp++; 2738164614Sariff sc->rirb_rp %= sc->rirb_size; 2739164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2740164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2741164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2742164614Sariff sc->codecs[cad] == NULL) 2743164614Sariff continue; 2744164614Sariff resp = rirb->response; 2745164614Sariff codec = sc->codecs[cad]; 2746164614Sariff commands = codec->commands; 2747164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2748164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2749164614Sariff ((resp >> 26) & 0xffff); 2750164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2751164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2752164614Sariff codec->responses_received < commands->num_commands) 2753164614Sariff commands->responses[codec->responses_received++] = 2754164614Sariff resp; 2755164614Sariff ret++; 2756164614Sariff } 2757164614Sariff 2758164614Sariff return (ret); 2759164614Sariff} 2760164614Sariff 2761164614Sariffstatic int 2762164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2763164614Sariff{ 2764164614Sariff nid_t cad; 2765164614Sariff uint32_t tag; 2766164614Sariff int ret = 0; 2767164614Sariff 2768164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2769164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2770164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2771164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2772164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2773164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2774164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2775164614Sariff ret++; 2776164614Sariff } 2777164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2778164614Sariff } 2779164614Sariff 2780164614Sariff return (ret); 2781164614Sariff} 2782164614Sariff 2783164614Sariffstatic void 2784164614Sariffhdac_poll_callback(void *arg) 2785164614Sariff{ 2786164614Sariff struct hdac_softc *sc = arg; 2787164614Sariff if (sc == NULL) 2788164614Sariff return; 2789166796Sariff 2790164614Sariff hdac_lock(sc); 2791169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2792164614Sariff hdac_unlock(sc); 2793164614Sariff return; 2794164614Sariff } 2795171141Sariff if (hdac_rirb_flush(sc) != 0) 2796171141Sariff hdac_unsolq_flush(sc); 2797169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2798164614Sariff hdac_unlock(sc); 2799164614Sariff} 2800164614Sariff 2801164614Sariffstatic void 2802182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2803182999Smav{ 2804182999Smav int i, pollticks, min = 1000000; 2805182999Smav struct hdac_chan *ch; 2806182999Smav 2807182999Smav for (i = 0; i < sc->num_chans; i++) { 2808182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2809182999Smav continue; 2810182999Smav ch = &sc->chans[i]; 2811182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2812182999Smav ((uint64_t)sndbuf_getbps(ch->b) * 2813182999Smav sndbuf_getspd(ch->b)); 2814182999Smav pollticks >>= 1; 2815182999Smav if (pollticks > hz) 2816182999Smav pollticks = hz; 2817182999Smav if (pollticks < 1) { 2818182999Smav HDA_BOOTVERBOSE( 2819182999Smav device_printf(sc->dev, 2820182999Smav "%s: pollticks=%d < 1 !\n", 2821182999Smav __func__, pollticks); 2822182999Smav ); 2823182999Smav pollticks = 1; 2824182999Smav } 2825182999Smav if (min > pollticks) 2826182999Smav min = pollticks; 2827182999Smav } 2828182999Smav HDA_BOOTVERBOSE( 2829182999Smav device_printf(sc->dev, 2830182999Smav "%s: pollticks %d -> %d\n", 2831182999Smav __func__, sc->poll_ticks, min); 2832182999Smav ); 2833182999Smav sc->poll_ticks = min; 2834182999Smav if (min == 1000000) 2835182999Smav callout_stop(&sc->poll_hda); 2836182999Smav else 2837182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 2838182999Smav} 2839182999Smav 2840182999Smavstatic void 2841162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2842162922Sariff{ 2843162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2844162922Sariff uint32_t ctl; 2845162922Sariff 2846162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2847162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2848162922Sariff HDAC_SDCTL_RUN); 2849162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2850162922Sariff 2851171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 2852164614Sariff 2853182999Smav if (sc->polling != 0) 2854182999Smav hdac_poll_reinit(sc); 2855164614Sariff 2856182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2857182999Smav ctl &= ~(1 << (ch->off >> 5)); 2858182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2859162922Sariff} 2860162922Sariff 2861162922Sariffstatic void 2862162922Sariffhdac_stream_start(struct hdac_chan *ch) 2863162922Sariff{ 2864162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2865162922Sariff uint32_t ctl; 2866162922Sariff 2867182999Smav ch->flags |= HDAC_CHN_RUNNING; 2868162922Sariff 2869182999Smav if (sc->polling != 0) 2870182999Smav hdac_poll_reinit(sc); 2871182999Smav 2872182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2873182999Smav ctl |= 1 << (ch->off >> 5); 2874182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2875182999Smav 2876182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2877182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2878182999Smav HDAC_SDCTL_RUN; 2879162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2880162922Sariff} 2881162922Sariff 2882162922Sariffstatic void 2883162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2884162922Sariff{ 2885162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2886162922Sariff int timeout = 1000; 2887162922Sariff int to = timeout; 2888162922Sariff uint32_t ctl; 2889162922Sariff 2890162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2891162922Sariff ctl |= HDAC_SDCTL_SRST; 2892162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2893162922Sariff do { 2894162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2895162922Sariff if (ctl & HDAC_SDCTL_SRST) 2896162922Sariff break; 2897162922Sariff DELAY(10); 2898162922Sariff } while (--to); 2899162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2900162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2901162922Sariff } 2902162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2903162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2904162922Sariff to = timeout; 2905162922Sariff do { 2906162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2907162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2908162922Sariff break; 2909162922Sariff DELAY(10); 2910162922Sariff } while (--to); 2911163057Sariff if (ctl & HDAC_SDCTL_SRST) 2912162922Sariff device_printf(sc->dev, "can't reset!\n"); 2913162922Sariff} 2914162922Sariff 2915162922Sariffstatic void 2916162922Sariffhdac_stream_setid(struct hdac_chan *ch) 2917162922Sariff{ 2918162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2919162922Sariff uint32_t ctl; 2920162922Sariff 2921162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 2922162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 2923162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 2924162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 2925162922Sariff} 2926162922Sariff 2927162922Sariffstatic void 2928162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 2929162922Sariff{ 2930162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2931164614Sariff struct hdac_bdle *bdle; 2932162922Sariff uint64_t addr; 2933164614Sariff uint32_t blksz, blkcnt; 2934162922Sariff int i; 2935162922Sariff 2936162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 2937164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 2938162922Sariff 2939182999Smav blksz = ch->blksz; 2940182999Smav blkcnt = ch->blkcnt; 2941164614Sariff 2942164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 2943162922Sariff bdle->addrl = (uint32_t)addr; 2944162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 2945164614Sariff bdle->len = blksz; 2946182999Smav bdle->ioc = 1; 2947164614Sariff addr += blksz; 2948162922Sariff } 2949162922Sariff 2950164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 2951164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 2952162922Sariff addr = ch->bdl_dma.dma_paddr; 2953162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 2954162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 2955169277Sariff if (ch->dmapos != NULL && 2956169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 2957169277Sariff addr = sc->pos_dma.dma_paddr; 2958169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 2959169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 2960169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 2961169277Sariff } 2962162922Sariff} 2963162922Sariff 2964162922Sariffstatic int 2965162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 2966162922Sariff{ 2967162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2968162922Sariff int rc; 2969162922Sariff 2970162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 2971162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 2972162922Sariff if (rc) { 2973162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 2974162922Sariff return (rc); 2975162922Sariff } 2976162922Sariff 2977162922Sariff return (0); 2978162922Sariff} 2979162922Sariff 2980162922Sariffstatic void 2981162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 2982162922Sariff int index, int lmute, int rmute, 2983162922Sariff int left, int right, int dir) 2984162922Sariff{ 2985162922Sariff uint16_t v = 0; 2986162922Sariff 2987162922Sariff if (sc == NULL) 2988162922Sariff return; 2989162922Sariff 2990162922Sariff if (left != right || lmute != rmute) { 2991162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 2992162922Sariff (lmute << 7) | left; 2993162922Sariff hdac_command(sc, 2994164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2995162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 2996162922Sariff (rmute << 7) | right; 2997162922Sariff } else 2998162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 2999162922Sariff (lmute << 7) | left; 3000162922Sariff 3001162922Sariff hdac_command(sc, 3002162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3003162922Sariff} 3004162922Sariff 3005162922Sariffstatic void 3006162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3007162922Sariff int left, int right) 3008162922Sariff{ 3009162922Sariff struct hdac_softc *sc; 3010162922Sariff nid_t nid, cad; 3011162922Sariff int lmute, rmute; 3012162922Sariff 3013162922Sariff sc = ctl->widget->devinfo->codec->sc; 3014162922Sariff cad = ctl->widget->devinfo->codec->cad; 3015162922Sariff nid = ctl->widget->nid; 3016162922Sariff 3017182999Smav /* Save new values if valid. */ 3018182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3019182999Smav ctl->muted = mute; 3020182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3021182999Smav ctl->left = left; 3022182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3023182999Smav ctl->right = right; 3024182999Smav /* Prepare effective values */ 3025182999Smav if (ctl->forcemute) { 3026182999Smav lmute = 1; 3027182999Smav rmute = 1; 3028182999Smav left = 0; 3029182999Smav right = 0; 3030182999Smav } else { 3031162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3032162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3033182999Smav left = ctl->left; 3034182999Smav right = ctl->right; 3035162922Sariff } 3036182999Smav /* Apply effective values */ 3037162922Sariff if (ctl->dir & HDA_CTL_OUT) 3038162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3039162922Sariff lmute, rmute, left, right, 0); 3040162922Sariff if (ctl->dir & HDA_CTL_IN) 3041182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3042162922Sariff lmute, rmute, left, right, 1); 3043162922Sariff} 3044162922Sariff 3045162922Sariffstatic void 3046162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3047162922Sariff{ 3048162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3049162922Sariff return; 3050162922Sariff hdac_command(w->devinfo->codec->sc, 3051162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3052162922Sariff w->nid, index), w->devinfo->codec->cad); 3053162922Sariff w->selconn = index; 3054162922Sariff} 3055162922Sariff 3056162922Sariff 3057162922Sariff/**************************************************************************** 3058162922Sariff * uint32_t hdac_command_sendone_internal 3059162922Sariff * 3060162922Sariff * Wrapper function that sends only one command to a given codec 3061162922Sariff ****************************************************************************/ 3062162922Sariffstatic uint32_t 3063162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3064162922Sariff{ 3065162922Sariff struct hdac_command_list cl; 3066162965Sariff uint32_t response = HDAC_INVALID; 3067162922Sariff 3068163057Sariff if (!hdac_lockowned(sc)) 3069162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3070162922Sariff cl.num_commands = 1; 3071162922Sariff cl.verbs = &verb; 3072162922Sariff cl.responses = &response; 3073162922Sariff 3074162922Sariff hdac_command_send_internal(sc, &cl, cad); 3075162922Sariff 3076162922Sariff return (response); 3077162922Sariff} 3078162922Sariff 3079162922Sariff/**************************************************************************** 3080162922Sariff * hdac_command_send_internal 3081162922Sariff * 3082162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3083162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3084162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3085162922Sariff * if any. 3086162922Sariff ****************************************************************************/ 3087162922Sariffstatic void 3088162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3089162922Sariff struct hdac_command_list *commands, nid_t cad) 3090162922Sariff{ 3091162922Sariff struct hdac_codec *codec; 3092162922Sariff int corbrp; 3093162922Sariff uint32_t *corb; 3094162922Sariff int timeout; 3095162922Sariff int retry = 10; 3096164614Sariff struct hdac_rirb *rirb_base; 3097162922Sariff 3098164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3099164614Sariff commands->num_commands < 1) 3100162922Sariff return; 3101162922Sariff 3102162922Sariff codec = sc->codecs[cad]; 3103162922Sariff codec->commands = commands; 3104162922Sariff codec->responses_received = 0; 3105162922Sariff codec->verbs_sent = 0; 3106162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3107162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3108162922Sariff 3109162922Sariff do { 3110162922Sariff if (codec->verbs_sent != commands->num_commands) { 3111162922Sariff /* Queue as many verbs as possible */ 3112162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3113169277Sariff#if 0 3114162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3115162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3116169277Sariff#endif 3117162922Sariff while (codec->verbs_sent != commands->num_commands && 3118162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3119162922Sariff sc->corb_wp++; 3120162922Sariff sc->corb_wp %= sc->corb_size; 3121162922Sariff corb[sc->corb_wp] = 3122162922Sariff commands->verbs[codec->verbs_sent++]; 3123162922Sariff } 3124162922Sariff 3125162922Sariff /* Send the verbs to the codecs */ 3126169277Sariff#if 0 3127162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3128162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3129169277Sariff#endif 3130162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3131162922Sariff } 3132162922Sariff 3133162922Sariff timeout = 1000; 3134164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3135162922Sariff DELAY(10); 3136162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3137164614Sariff codec->responses_received != commands->num_commands) && --retry); 3138162922Sariff 3139162922Sariff if (retry == 0) 3140162922Sariff device_printf(sc->dev, 3141164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3142164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3143164614Sariff codec->responses_received); 3144162922Sariff 3145164614Sariff codec->commands = NULL; 3146164614Sariff codec->responses_received = 0; 3147162922Sariff codec->verbs_sent = 0; 3148162922Sariff 3149164614Sariff hdac_unsolq_flush(sc); 3150162922Sariff} 3151162922Sariff 3152162922Sariff 3153162922Sariff/**************************************************************************** 3154162922Sariff * Device Methods 3155162922Sariff ****************************************************************************/ 3156162922Sariff 3157162922Sariff/**************************************************************************** 3158162922Sariff * int hdac_probe(device_t) 3159162922Sariff * 3160162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3161162922Sariff * match using the subclass of the device. 3162162922Sariff ****************************************************************************/ 3163162922Sariffstatic int 3164162922Sariffhdac_probe(device_t dev) 3165162922Sariff{ 3166162922Sariff int i, result; 3167163257Sariff uint32_t model; 3168163257Sariff uint16_t class, subclass; 3169162922Sariff char desc[64]; 3170162922Sariff 3171162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3172162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3173162922Sariff class = pci_get_class(dev); 3174162922Sariff subclass = pci_get_subclass(dev); 3175162922Sariff 3176162922Sariff bzero(desc, sizeof(desc)); 3177162922Sariff result = ENXIO; 3178162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3179162922Sariff if (hdac_devices[i].model == model) { 3180162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3181162922Sariff result = BUS_PROBE_DEFAULT; 3182162922Sariff break; 3183162922Sariff } 3184163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3185162922Sariff class == PCIC_MULTIMEDIA && 3186162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3187162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3188162922Sariff result = BUS_PROBE_GENERIC; 3189162922Sariff break; 3190162922Sariff } 3191162922Sariff } 3192162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3193162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3194162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3195162922Sariff result = BUS_PROBE_GENERIC; 3196162922Sariff } 3197162922Sariff if (result != ENXIO) { 3198162922Sariff strlcat(desc, " High Definition Audio Controller", 3199162922Sariff sizeof(desc)); 3200162922Sariff device_set_desc_copy(dev, desc); 3201162922Sariff } 3202162922Sariff 3203162922Sariff return (result); 3204162922Sariff} 3205162922Sariff 3206162922Sariffstatic void * 3207162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3208162922Sariff struct pcm_channel *c, int dir) 3209162922Sariff{ 3210182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3211182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3212162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3213162922Sariff struct hdac_chan *ch; 3214182999Smav int i, ord = 0, chid; 3215162922Sariff 3216162922Sariff hdac_lock(sc); 3217182999Smav 3218182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3219182999Smav ch = &sc->chans[chid]; 3220182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3221182999Smav if (ch->dir == sc->chans[i].dir) 3222182999Smav ord++; 3223182999Smav } 3224162922Sariff if (dir == PCMDIR_PLAY) { 3225182999Smav ch->off = (sc->num_iss + ord) << 5; 3226162922Sariff } else { 3227182999Smav ch->off = ord << 5; 3228162922Sariff } 3229182999Smav 3230162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3231162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3232162922Sariff ch->pcmrates[0] = 48000; 3233162922Sariff ch->pcmrates[1] = 0; 3234162922Sariff } 3235169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3236169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3237169277Sariff (sc->streamcnt * 8)); 3238169277Sariff else 3239169277Sariff ch->dmapos = NULL; 3240169277Sariff ch->sid = ++sc->streamcnt; 3241169277Sariff ch->dir = dir; 3242162922Sariff ch->b = b; 3243162922Sariff ch->c = c; 3244182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3245182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3246162922Sariff hdac_unlock(sc); 3247162922Sariff 3248162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3249162922Sariff ch->blkcnt = 0; 3250162922Sariff return (NULL); 3251162922Sariff } 3252162922Sariff 3253169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3254171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3255182999Smav pdevinfo->chan_size) != 0) 3256162922Sariff return (NULL); 3257162922Sariff 3258162922Sariff return (ch); 3259162922Sariff} 3260162922Sariff 3261162922Sariffstatic int 3262162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3263162922Sariff{ 3264162922Sariff struct hdac_chan *ch = data; 3265162922Sariff int i; 3266162922Sariff 3267162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3268162922Sariff if (format == ch->caps.fmtlist[i]) { 3269162922Sariff ch->fmt = format; 3270162922Sariff return (0); 3271162922Sariff } 3272162922Sariff } 3273162922Sariff 3274162922Sariff return (EINVAL); 3275162922Sariff} 3276162922Sariff 3277162922Sariffstatic int 3278162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3279162922Sariff{ 3280162922Sariff struct hdac_chan *ch = data; 3281164614Sariff uint32_t spd = 0, threshold; 3282162922Sariff int i; 3283162922Sariff 3284162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3285162922Sariff spd = ch->pcmrates[i]; 3286164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3287164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3288164614Sariff if (speed < threshold) 3289162922Sariff break; 3290162922Sariff } 3291162922Sariff 3292164614Sariff if (spd == 0) /* impossible */ 3293162922Sariff ch->spd = 48000; 3294162922Sariff else 3295162922Sariff ch->spd = spd; 3296162922Sariff 3297162922Sariff return (ch->spd); 3298162922Sariff} 3299162922Sariff 3300162922Sariffstatic void 3301162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3302162922Sariff{ 3303162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3304182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3305173817Sariff struct hdac_widget *w; 3306182999Smav int i, chn, totalchn, c; 3307162922Sariff nid_t cad = ch->devinfo->codec->cad; 3308182999Smav uint16_t fmt, dfmt; 3309162922Sariff 3310183097Smav HDA_BOOTHVERBOSE( 3311182999Smav device_printf(ch->pdevinfo->dev, 3312182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3313182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3314182999Smav ch->fmt, ch->spd); 3315182999Smav ); 3316162922Sariff fmt = 0; 3317162922Sariff if (ch->fmt & AFMT_S16_LE) 3318162922Sariff fmt |= ch->bit16 << 4; 3319162922Sariff else if (ch->fmt & AFMT_S32_LE) 3320162922Sariff fmt |= ch->bit32 << 4; 3321162922Sariff else 3322162922Sariff fmt |= 1 << 4; 3323162922Sariff 3324162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3325162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3326162922Sariff fmt |= hda_rate_tab[i].base; 3327162922Sariff fmt |= hda_rate_tab[i].mul; 3328162922Sariff fmt |= hda_rate_tab[i].div; 3329162922Sariff break; 3330162922Sariff } 3331162922Sariff } 3332162922Sariff 3333182999Smav if (ch->fmt & (AFMT_STEREO | AFMT_AC3)) { 3334162922Sariff fmt |= 1; 3335173817Sariff totalchn = 2; 3336173817Sariff } else 3337173817Sariff totalchn = 1; 3338162922Sariff 3339162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3340182999Smav 3341182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3342182999Smav if (ch->fmt & AFMT_AC3) 3343182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3344162922Sariff 3345173817Sariff chn = 0; 3346162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3347173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3348173817Sariff if (w == NULL) 3349173817Sariff continue; 3350182999Smav 3351182999Smav if (as->hpredir >= 0 && i == as->pincnt) 3352182999Smav chn = 0; 3353183097Smav HDA_BOOTHVERBOSE( 3354182999Smav device_printf(ch->pdevinfo->dev, 3355182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3356182999Smav "fmt=0x%04x, dfmt=0x%04x\n", 3357162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3358182999Smav ch->io[i], fmt, dfmt); 3359162922Sariff ); 3360162922Sariff hdac_command(sc, 3361162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3362182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3363174025Sariff hdac_command(sc, 3364182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3365174025Sariff cad); 3366182999Smav } 3367182999Smav /* If HP redirection is enabled, but failed to use same 3368182999Smav DAC make last DAC one to duplicate first one. */ 3369182999Smav if (as->hpredir >= 0 && i == as->pincnt) { 3370182999Smav c = (ch->sid << 4); 3371182999Smav } else if (chn >= totalchn) { 3372182999Smav /* This is until OSS will support multichannel. 3373182999Smav Should be: c = 0; to disable unused DAC */ 3374182999Smav c = (ch->sid << 4); 3375182999Smav }else { 3376182999Smav c = (ch->sid << 4) | chn; 3377182999Smav } 3378182999Smav hdac_command(sc, 3379182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3380173817Sariff chn += 3381173817Sariff HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ? 3382173817Sariff 2 : 1; 3383162922Sariff } 3384162922Sariff} 3385162922Sariff 3386162922Sariffstatic int 3387167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3388167648Sariff uint32_t blksz, uint32_t blkcnt) 3389162922Sariff{ 3390162922Sariff struct hdac_chan *ch = data; 3391164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3392162922Sariff 3393167648Sariff blksz &= HDA_BLK_ALIGN; 3394162922Sariff 3395167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3396167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3397167648Sariff if (blksz < HDA_BLK_MIN) 3398167648Sariff blksz = HDA_BLK_MIN; 3399167648Sariff if (blkcnt > HDA_BDL_MAX) 3400167648Sariff blkcnt = HDA_BDL_MAX; 3401167648Sariff if (blkcnt < HDA_BDL_MIN) 3402167648Sariff blkcnt = HDA_BDL_MIN; 3403164614Sariff 3404167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3405167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3406167648Sariff blkcnt >>= 1; 3407167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3408167648Sariff blksz >>= 1; 3409167648Sariff else 3410167648Sariff break; 3411167648Sariff } 3412167648Sariff 3413164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3414167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3415167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3416164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3417167648Sariff __func__, blksz, blkcnt); 3418164614Sariff 3419164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3420167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3421164614Sariff 3422167648Sariff return (1); 3423167648Sariff} 3424167648Sariff 3425167648Sariffstatic int 3426167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3427167648Sariff{ 3428167648Sariff struct hdac_chan *ch = data; 3429167648Sariff 3430182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3431167648Sariff 3432162922Sariff return (ch->blksz); 3433162922Sariff} 3434162922Sariff 3435162922Sariffstatic void 3436162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3437162922Sariff{ 3438162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3439182999Smav struct hdac_widget *w; 3440162922Sariff nid_t cad = devinfo->codec->cad; 3441162922Sariff int i; 3442162922Sariff 3443162922Sariff hdac_stream_stop(ch); 3444162922Sariff 3445162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3446182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3447182999Smav if (w == NULL) 3448182999Smav continue; 3449182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3450182999Smav hdac_command(sc, 3451182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3452182999Smav cad); 3453182999Smav } 3454162922Sariff hdac_command(sc, 3455162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3456162922Sariff 0), cad); 3457162922Sariff } 3458162922Sariff} 3459162922Sariff 3460162922Sariffstatic void 3461162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3462162922Sariff{ 3463162922Sariff ch->ptr = 0; 3464162922Sariff ch->prevptr = 0; 3465162922Sariff hdac_stream_stop(ch); 3466162922Sariff hdac_stream_reset(ch); 3467162922Sariff hdac_bdl_setup(ch); 3468162922Sariff hdac_stream_setid(ch); 3469162922Sariff hdac_stream_setup(ch); 3470162922Sariff hdac_stream_start(ch); 3471162922Sariff} 3472162922Sariff 3473162922Sariffstatic int 3474162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3475162922Sariff{ 3476162922Sariff struct hdac_chan *ch = data; 3477162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3478162922Sariff 3479170521Sariff if (!PCMTRIG_COMMON(go)) 3480170521Sariff return (0); 3481170521Sariff 3482162922Sariff hdac_lock(sc); 3483162922Sariff switch (go) { 3484162922Sariff case PCMTRIG_START: 3485162922Sariff hdac_channel_start(sc, ch); 3486162922Sariff break; 3487162922Sariff case PCMTRIG_STOP: 3488162922Sariff case PCMTRIG_ABORT: 3489162922Sariff hdac_channel_stop(sc, ch); 3490162922Sariff break; 3491167610Sariff default: 3492167610Sariff break; 3493162922Sariff } 3494162922Sariff hdac_unlock(sc); 3495162922Sariff 3496162922Sariff return (0); 3497162922Sariff} 3498162922Sariff 3499162922Sariffstatic int 3500162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3501162922Sariff{ 3502162922Sariff struct hdac_chan *ch = data; 3503162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3504162922Sariff uint32_t ptr; 3505162922Sariff 3506162922Sariff hdac_lock(sc); 3507164614Sariff if (sc->polling != 0) 3508164614Sariff ptr = ch->ptr; 3509169277Sariff else if (ch->dmapos != NULL) 3510169277Sariff ptr = *(ch->dmapos); 3511164614Sariff else 3512164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3513162922Sariff hdac_unlock(sc); 3514162922Sariff 3515164614Sariff /* 3516164614Sariff * Round to available space and force 128 bytes aligment. 3517164614Sariff */ 3518164614Sariff ptr %= ch->blksz * ch->blkcnt; 3519167648Sariff ptr &= HDA_BLK_ALIGN; 3520162922Sariff 3521162922Sariff return (ptr); 3522162922Sariff} 3523162922Sariff 3524162922Sariffstatic struct pcmchan_caps * 3525162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3526162922Sariff{ 3527162922Sariff return (&((struct hdac_chan *)data)->caps); 3528162922Sariff} 3529162922Sariff 3530162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3531162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3532162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3533162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3534162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3535167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3536162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3537162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3538162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3539162922Sariff { 0, 0 } 3540162922Sariff}; 3541162922SariffCHANNEL_DECLARE(hdac_channel); 3542162922Sariff 3543162922Sariffstatic int 3544162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3545162922Sariff{ 3546182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3547182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3548162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3549162922Sariff struct hdac_widget *w, *cw; 3550162922Sariff struct hdac_audio_ctl *ctl; 3551162922Sariff uint32_t mask, recmask, id; 3552162922Sariff int i, j, softpcmvol; 3553162922Sariff 3554162922Sariff hdac_lock(sc); 3555162922Sariff 3556182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3557182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3558182999Smav pdevinfo->left[i] = 100; 3559182999Smav pdevinfo->right[i] = 100; 3560182999Smav } 3561182999Smav 3562162922Sariff mask = 0; 3563162922Sariff recmask = 0; 3564182999Smav id = hdac_codec_id(devinfo->codec); 3565162922Sariff 3566182999Smav /* Declate EAPD as ogain control. */ 3567182999Smav if (pdevinfo->play >= 0) { 3568182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3569182999Smav w = hdac_widget_get(devinfo, i); 3570182999Smav if (w == NULL || w->enable == 0) 3571182999Smav continue; 3572182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3573182999Smav w->param.eapdbtl == HDAC_INVALID || 3574182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3575182999Smav continue; 3576182999Smav mask |= SOUND_MASK_OGAIN; 3577162922Sariff break; 3578162922Sariff } 3579162922Sariff } 3580162922Sariff 3581182999Smav /* Declare volume controls assigned to this association. */ 3582162922Sariff i = 0; 3583162922Sariff ctl = NULL; 3584162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3585182999Smav if (ctl->enable == 0) 3586162922Sariff continue; 3587182999Smav if ((pdevinfo->play >= 0 && 3588182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3589182999Smav (pdevinfo->rec >= 0 && 3590182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3591182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3592182999Smav mask |= ctl->ossmask; 3593162922Sariff } 3594162922Sariff 3595182999Smav /* Declare record sources available to this association. */ 3596182999Smav if (pdevinfo->rec >= 0) { 3597182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3598182999Smav for (i = 0; ch->io[i] != -1; i++) { 3599182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3600182999Smav if (w == NULL || w->enable == 0) 3601182999Smav continue; 3602182999Smav for (j = 0; j < w->nconns; j++) { 3603182999Smav if (w->connsenable[j] == 0) 3604162922Sariff continue; 3605182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3606182999Smav if (cw == NULL || cw->enable == 0) 3607165992Sariff continue; 3608182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3609182999Smav cw->bindas != -2) 3610165992Sariff continue; 3611182999Smav recmask |= cw->ossmask; 3612165992Sariff } 3613182999Smav } 3614182999Smav } 3615182999Smav 3616185230Smav /* Declare soft PCM volume if needed. */ 3617185230Smav if (pdevinfo->play >= 0 && !pdevinfo->digital) { 3618182999Smav ctl = NULL; 3619182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3620182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3621182999Smav softpcmvol = 1; 3622182999Smav mask |= SOUND_MASK_PCM; 3623162922Sariff } else { 3624182999Smav softpcmvol = 0; 3625182999Smav i = 0; 3626182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3627182999Smav if (ctl->enable == 0) 3628162922Sariff continue; 3629182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3630182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3631162922Sariff continue; 3632182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3633182999Smav continue; 3634182999Smav if (ctl->step > 0) 3635182999Smav break; 3636162922Sariff } 3637162922Sariff } 3638182999Smav 3639182999Smav if (softpcmvol == 1 || ctl == NULL) { 3640182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3641182999Smav HDA_BOOTVERBOSE( 3642182999Smav device_printf(pdevinfo->dev, 3643182999Smav "%s Soft PCM volume\n", 3644182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3645182999Smav ); 3646182999Smav } 3647185230Smav } 3648182999Smav 3649185230Smav /* Declare master volume if needed. */ 3650185230Smav if (pdevinfo->play >= 0) { 3651185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3652185230Smav SOUND_MASK_PCM) { 3653182999Smav mask |= SOUND_MASK_VOLUME; 3654182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3655182999Smav SOUND_MASK_PCM); 3656182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3657182999Smav SOUND_MIXER_NONE); 3658182999Smav HDA_BOOTVERBOSE( 3659182999Smav device_printf(pdevinfo->dev, 3660182999Smav "Forcing master volume with PCM\n"); 3661182999Smav ); 3662182999Smav } 3663162922Sariff } 3664162922Sariff 3665169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3666169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3667162922Sariff 3668162922Sariff mix_setrecdevs(m, recmask); 3669162922Sariff mix_setdevs(m, mask); 3670162922Sariff 3671162922Sariff hdac_unlock(sc); 3672162922Sariff 3673162922Sariff return (0); 3674162922Sariff} 3675162922Sariff 3676162922Sariffstatic int 3677162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3678162922Sariff unsigned left, unsigned right) 3679162922Sariff{ 3680182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3681182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3682162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3683162922Sariff struct hdac_widget *w; 3684162922Sariff struct hdac_audio_ctl *ctl; 3685182999Smav uint32_t mute; 3686182999Smav int lvol, rvol; 3687182999Smav int i, j; 3688162922Sariff 3689162922Sariff hdac_lock(sc); 3690182999Smav /* Save new values. */ 3691182999Smav pdevinfo->left[dev] = left; 3692182999Smav pdevinfo->right[dev] = right; 3693182999Smav 3694182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3695162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3696163257Sariff uint32_t orig; 3697182999Smav w = NULL; 3698182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3699182999Smav w = hdac_widget_get(devinfo, i); 3700182999Smav if (w == NULL || w->enable == 0) 3701182999Smav continue; 3702182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3703182999Smav w->param.eapdbtl == HDAC_INVALID) 3704182999Smav continue; 3705182999Smav break; 3706162922Sariff } 3707182999Smav if (i >= devinfo->endnode) { 3708162922Sariff hdac_unlock(sc); 3709162922Sariff return (-1); 3710162922Sariff } 3711163257Sariff orig = w->param.eapdbtl; 3712163432Sariff if (left == 0) 3713162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3714162922Sariff else 3715162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3716163257Sariff if (orig != w->param.eapdbtl) { 3717163432Sariff uint32_t val; 3718163432Sariff 3719163432Sariff val = w->param.eapdbtl; 3720163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3721163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3722163257Sariff hdac_command(sc, 3723163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3724163432Sariff w->nid, val), devinfo->codec->cad); 3725163257Sariff } 3726162922Sariff hdac_unlock(sc); 3727162922Sariff return (left | (left << 8)); 3728162922Sariff } 3729162922Sariff 3730182999Smav /* Recalculate all controls related to this OSS device. */ 3731162922Sariff i = 0; 3732162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3733182999Smav if (ctl->enable == 0 || 3734162922Sariff !(ctl->ossmask & (1 << dev))) 3735162922Sariff continue; 3736182999Smav if (!((pdevinfo->play >= 0 && 3737182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3738182999Smav (pdevinfo->rec >= 0 && 3739182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3740182999Smav ctl->widget->bindas == -2)) 3741182999Smav continue; 3742182999Smav 3743182999Smav lvol = 100; 3744182999Smav rvol = 100; 3745182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3746182999Smav if (ctl->ossmask & (1 << j)) { 3747182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3748182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3749162922Sariff } 3750162922Sariff } 3751182999Smav mute = (left == 0) ? HDA_AMP_MUTE_LEFT : 0; 3752182999Smav mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3753182999Smav lvol = (lvol * ctl->step + 50) / 100; 3754182999Smav rvol = (rvol * ctl->step + 50) / 100; 3755162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3756162922Sariff } 3757162922Sariff hdac_unlock(sc); 3758162922Sariff 3759162922Sariff return (left | (right << 8)); 3760162922Sariff} 3761162922Sariff 3762182999Smav/* 3763182999Smav * Commutate specified record source. 3764182999Smav */ 3765182999Smavstatic uint32_t 3766182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3767162922Sariff{ 3768182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3769162922Sariff struct hdac_widget *w, *cw; 3770182999Smav struct hdac_audio_ctl *ctl; 3771182999Smav char buf[64]; 3772182999Smav int i, muted; 3773182999Smav uint32_t res = 0; 3774162922Sariff 3775182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3776182999Smav return (0); 3777182999Smav 3778182999Smav w = hdac_widget_get(devinfo, nid); 3779182999Smav if (w == NULL || w->enable == 0) 3780182999Smav return (0); 3781182999Smav 3782182999Smav for (i = 0; i < w->nconns; i++) { 3783182999Smav if (w->connsenable[i] == 0) 3784182999Smav continue; 3785182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3786182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3787182999Smav continue; 3788182999Smav /* Call recursively to trace signal to it's source if needed. */ 3789182999Smav if ((src & cw->ossmask) != 0) { 3790182999Smav if (cw->ossdev < 0) { 3791182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 3792182999Smav w->conns[i], depth + 1); 3793182999Smav } else { 3794182999Smav res |= cw->ossmask; 3795182999Smav } 3796182999Smav } 3797182999Smav /* We have two special cases: mixers and others (selectors). */ 3798182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 3799182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 3800182999Smav w->nid, HDA_CTL_IN, i, 1); 3801182999Smav if (ctl == NULL) 3802182999Smav continue; 3803182999Smav /* If we have input control on this node mute them 3804182999Smav * according to requested sources. */ 3805182999Smav muted = (src & cw->ossmask) ? 0 : 1; 3806182999Smav if (muted != ctl->forcemute) { 3807182999Smav ctl->forcemute = muted; 3808182999Smav hdac_audio_ctl_amp_set(ctl, 3809182999Smav HDA_AMP_MUTE_DEFAULT, 3810182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 3811182999Smav } 3812183097Smav HDA_BOOTHVERBOSE( 3813182999Smav device_printf(pdevinfo->dev, 3814182999Smav "Recsel (%s): nid %d source %d %s\n", 3815182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3816182999Smav src, buf, sizeof(buf)), 3817182999Smav nid, i, muted?"mute":"unmute"); 3818182999Smav ); 3819182999Smav } else { 3820182999Smav if (w->nconns == 1) 3821182999Smav break; 3822182999Smav if ((src & cw->ossmask) == 0) 3823182999Smav continue; 3824182999Smav /* If we found requested source - select it and exit. */ 3825182999Smav hdac_widget_connection_select(w, i); 3826183097Smav HDA_BOOTHVERBOSE( 3827182999Smav device_printf(pdevinfo->dev, 3828182999Smav "Recsel (%s): nid %d source %d select\n", 3829182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3830182999Smav src, buf, sizeof(buf)), 3831182999Smav nid, i); 3832182999Smav ); 3833162922Sariff break; 3834162922Sariff } 3835162922Sariff } 3836182999Smav return (res); 3837182999Smav} 3838162922Sariff 3839182999Smavstatic uint32_t 3840182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3841182999Smav{ 3842182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3843182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3844182999Smav struct hdac_widget *w; 3845182999Smav struct hdac_softc *sc = devinfo->codec->sc; 3846182999Smav struct hdac_chan *ch; 3847182999Smav int i; 3848182999Smav uint32_t ret = 0xffffffff; 3849182999Smav 3850162922Sariff hdac_lock(sc); 3851162922Sariff 3852182999Smav /* Commutate requested recsrc for each ADC. */ 3853182999Smav ch = &sc->chans[pdevinfo->rec]; 3854182999Smav for (i = 0; ch->io[i] != -1; i++) { 3855182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3856162965Sariff if (w == NULL || w->enable == 0) 3857162922Sariff continue; 3858182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 3859162922Sariff } 3860162922Sariff 3861162922Sariff hdac_unlock(sc); 3862162922Sariff 3863182999Smav return ((ret == 0xffffffff)? 0 : ret); 3864162922Sariff} 3865162922Sariff 3866162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3867162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3868162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3869162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3870162922Sariff { 0, 0 } 3871162922Sariff}; 3872162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3873162922Sariff 3874171141Sariffstatic void 3875171141Sariffhdac_unsolq_task(void *context, int pending) 3876171141Sariff{ 3877171141Sariff struct hdac_softc *sc; 3878171141Sariff 3879171141Sariff sc = (struct hdac_softc *)context; 3880171141Sariff 3881171141Sariff hdac_lock(sc); 3882171141Sariff hdac_unsolq_flush(sc); 3883171141Sariff hdac_unlock(sc); 3884171141Sariff} 3885171141Sariff 3886162922Sariff/**************************************************************************** 3887162922Sariff * int hdac_attach(device_t) 3888162922Sariff * 3889162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3890162922Sariff * when this function is called. Setup everything that doesn't require 3891162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3892162922Sariff ****************************************************************************/ 3893162922Sariffstatic int 3894162922Sariffhdac_attach(device_t dev) 3895162922Sariff{ 3896162922Sariff struct hdac_softc *sc; 3897162922Sariff int result; 3898169277Sariff int i; 3899169277Sariff uint16_t vendor; 3900169277Sariff uint8_t v; 3901162922Sariff 3902184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 3903182999Smav 3904182999Smav sc = device_get_softc(dev); 3905163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 3906162922Sariff sc->dev = dev; 3907163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 3908163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 3909169277Sariff vendor = pci_get_vendor(dev); 3910162922Sariff 3911165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 3912165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 3913165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 3914165281Sariff } 3915165281Sariff 3916164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 3917164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 3918169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 3919164614Sariff 3920171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 3921171141Sariff 3922182999Smav sc->poll_ticks = 1000000; 3923169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 3924169277Sariff if (resource_int_value(device_get_name(dev), 3925169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 3926164614Sariff sc->polling = 1; 3927164614Sariff else 3928164614Sariff sc->polling = 0; 3929164614Sariff 3930162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 3931162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 3932162922Sariff 0, /* boundary */ 3933162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 3934162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 3935162922Sariff NULL, /* filtfunc */ 3936162922Sariff NULL, /* fistfuncarg */ 3937182999Smav HDA_BUFSZ_MAX, /* maxsize */ 3938162922Sariff 1, /* nsegments */ 3939182999Smav HDA_BUFSZ_MAX, /* maxsegsz */ 3940162922Sariff 0, /* flags */ 3941162922Sariff NULL, /* lockfunc */ 3942162922Sariff NULL, /* lockfuncarg */ 3943162922Sariff &sc->chan_dmat); /* dmat */ 3944162922Sariff if (result != 0) { 3945169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 3946162922Sariff __func__, result); 3947163057Sariff snd_mtxfree(sc->lock); 3948162922Sariff free(sc, M_DEVBUF); 3949162922Sariff return (ENXIO); 3950162922Sariff } 3951162922Sariff 3952162922Sariff 3953162922Sariff sc->hdabus = NULL; 3954162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 3955162922Sariff sc->codecs[i] = NULL; 3956162922Sariff 3957162922Sariff pci_enable_busmaster(dev); 3958162922Sariff 3959169277Sariff if (vendor == INTEL_VENDORID) { 3960169277Sariff /* TCSEL -> TC0 */ 3961169277Sariff v = pci_read_config(dev, 0x44, 1); 3962169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 3963183097Smav HDA_BOOTHVERBOSE( 3964169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 3965169277Sariff pci_read_config(dev, 0x44, 1)); 3966169277Sariff ); 3967169277Sariff } 3968169277Sariff 3969178155Sariff#ifdef HDAC_MSI_ENABLED 3970171330Sariff if (resource_int_value(device_get_name(dev), 3971171330Sariff device_get_unit(dev), "msi", &i) == 0 && i != 0 && 3972171330Sariff pci_msi_count(dev) == 1) 3973171330Sariff sc->flags |= HDAC_F_MSI; 3974171330Sariff else 3975171330Sariff#endif 3976171330Sariff sc->flags &= ~HDAC_F_MSI; 3977171330Sariff 3978169277Sariff#if defined(__i386__) || defined(__amd64__) 3979171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3980169277Sariff 3981169277Sariff if (resource_int_value(device_get_name(dev), 3982169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 3983169277Sariff#else 3984171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3985169277Sariff#endif 3986169277Sariff /* 3987169277Sariff * Try to enable PCIe snoop to avoid messing around with 3988169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 3989169277Sariff * config is pretty much vendor specific, there are no 3990169277Sariff * general solutions on how to enable it, forcing us (even 3991169277Sariff * Microsoft) to enable uncacheable or write combined DMA 3992169277Sariff * by default. 3993169277Sariff * 3994169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 3995169277Sariff */ 3996169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 3997169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 3998169277Sariff continue; 3999171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4000169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4001169277Sariff break; 4002169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4003169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4004169277Sariff hdac_pcie_snoop[i].enable) 4005169277Sariff break; 4006169277Sariff v &= hdac_pcie_snoop[i].mask; 4007169277Sariff v |= hdac_pcie_snoop[i].enable; 4008169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4009169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4010169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4011169277Sariff hdac_pcie_snoop[i].enable) { 4012169277Sariff HDA_BOOTVERBOSE( 4013169277Sariff device_printf(dev, 4014169277Sariff "WARNING: Failed to enable PCIe " 4015169277Sariff "snoop!\n"); 4016169277Sariff ); 4017169277Sariff#if defined(__i386__) || defined(__amd64__) 4018171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4019169277Sariff#endif 4020169277Sariff } 4021169277Sariff break; 4022169277Sariff } 4023169277Sariff#if defined(__i386__) || defined(__amd64__) 4024169277Sariff } 4025169277Sariff#endif 4026169277Sariff 4027183097Smav HDA_BOOTHVERBOSE( 4028169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4029171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4030171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4031169277Sariff ); 4032169277Sariff 4033162922Sariff /* Allocate resources */ 4034162922Sariff result = hdac_mem_alloc(sc); 4035162922Sariff if (result != 0) 4036163057Sariff goto hdac_attach_fail; 4037162922Sariff result = hdac_irq_alloc(sc); 4038162922Sariff if (result != 0) 4039163057Sariff goto hdac_attach_fail; 4040162922Sariff 4041162922Sariff /* Get Capabilities */ 4042162922Sariff result = hdac_get_capabilities(sc); 4043162922Sariff if (result != 0) 4044163057Sariff goto hdac_attach_fail; 4045162922Sariff 4046162922Sariff /* Allocate CORB and RIRB dma memory */ 4047162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4048162922Sariff sc->corb_size * sizeof(uint32_t)); 4049162922Sariff if (result != 0) 4050163057Sariff goto hdac_attach_fail; 4051162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4052162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4053162922Sariff if (result != 0) 4054163057Sariff goto hdac_attach_fail; 4055162922Sariff 4056162922Sariff /* Quiesce everything */ 4057183097Smav HDA_BOOTHVERBOSE( 4058182999Smav device_printf(dev, "Reset controller...\n"); 4059182999Smav ); 4060182999Smav hdac_reset(sc, 1); 4061162922Sariff 4062162922Sariff /* Initialize the CORB and RIRB */ 4063162922Sariff hdac_corb_init(sc); 4064162922Sariff hdac_rirb_init(sc); 4065162922Sariff 4066162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4067162922Sariff sc->intrhook.ich_func = hdac_attach2; 4068162922Sariff sc->intrhook.ich_arg = (void *)sc; 4069162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4070162922Sariff sc->intrhook.ich_func = NULL; 4071162922Sariff hdac_attach2((void *)sc); 4072162922Sariff } 4073162922Sariff 4074163057Sariff return (0); 4075162922Sariff 4076163057Sariffhdac_attach_fail: 4077162922Sariff hdac_irq_free(sc); 4078169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4079169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4080162922Sariff hdac_mem_free(sc); 4081162922Sariff snd_mtxfree(sc->lock); 4082163057Sariff free(sc, M_DEVBUF); 4083162922Sariff 4084163057Sariff return (ENXIO); 4085162922Sariff} 4086162922Sariff 4087162922Sariffstatic void 4088162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4089162922Sariff{ 4090182999Smav struct hdac_codec *codec = devinfo->codec; 4091182999Smav struct hdac_softc *sc = codec->sc; 4092162922Sariff struct hdac_widget *w; 4093162922Sariff uint32_t res; 4094162922Sariff int i; 4095162922Sariff nid_t cad, nid; 4096162922Sariff 4097162922Sariff cad = devinfo->codec->cad; 4098162922Sariff nid = devinfo->nid; 4099162922Sariff 4100162922Sariff res = hdac_command(sc, 4101169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4102169277Sariff devinfo->function.audio.gpio = res; 4103169277Sariff 4104163057Sariff HDA_BOOTVERBOSE( 4105183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4106183097Smav "NumGPIO=%d NumGPO=%d " 4107169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4108183097Smav devinfo->function.audio.gpio, 4109169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4110169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4111169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4112169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4113169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4114162922Sariff ); 4115162922Sariff 4116162922Sariff res = hdac_command(sc, 4117162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4118162922Sariff cad); 4119162922Sariff devinfo->function.audio.supp_stream_formats = res; 4120162922Sariff 4121162922Sariff res = hdac_command(sc, 4122162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4123162922Sariff cad); 4124162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4125162922Sariff 4126162922Sariff res = hdac_command(sc, 4127162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4128162922Sariff cad); 4129162922Sariff devinfo->function.audio.outamp_cap = res; 4130162922Sariff 4131162922Sariff res = hdac_command(sc, 4132162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4133162922Sariff cad); 4134162922Sariff devinfo->function.audio.inamp_cap = res; 4135162922Sariff 4136162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4137162922Sariff w = hdac_widget_get(devinfo, i); 4138162922Sariff if (w == NULL) 4139162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4140162922Sariff else { 4141162922Sariff w->devinfo = devinfo; 4142162922Sariff w->nid = i; 4143162922Sariff w->enable = 1; 4144162922Sariff w->selconn = -1; 4145162922Sariff w->pflags = 0; 4146182999Smav w->ossdev = -1; 4147182999Smav w->bindas = -1; 4148162965Sariff w->param.eapdbtl = HDAC_INVALID; 4149162922Sariff hdac_widget_parse(w); 4150162922Sariff } 4151162922Sariff } 4152162922Sariff} 4153162922Sariff 4154162922Sariffstatic void 4155162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4156162922Sariff{ 4157162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4158162922Sariff struct hdac_audio_ctl *ctls; 4159162922Sariff struct hdac_widget *w, *cw; 4160162922Sariff int i, j, cnt, max, ocap, icap; 4161163057Sariff int mute, offset, step, size; 4162162922Sariff 4163162922Sariff /* XXX This is redundant */ 4164162922Sariff max = 0; 4165162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4166162922Sariff w = hdac_widget_get(devinfo, i); 4167162922Sariff if (w == NULL || w->enable == 0) 4168162922Sariff continue; 4169162922Sariff if (w->param.outamp_cap != 0) 4170162922Sariff max++; 4171162922Sariff if (w->param.inamp_cap != 0) { 4172162922Sariff switch (w->type) { 4173162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4174162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4175162922Sariff for (j = 0; j < w->nconns; j++) { 4176162922Sariff cw = hdac_widget_get(devinfo, 4177162922Sariff w->conns[j]); 4178162922Sariff if (cw == NULL || cw->enable == 0) 4179162922Sariff continue; 4180162922Sariff max++; 4181162922Sariff } 4182162922Sariff break; 4183162922Sariff default: 4184162922Sariff max++; 4185162922Sariff break; 4186162922Sariff } 4187162922Sariff } 4188162922Sariff } 4189162922Sariff 4190162922Sariff devinfo->function.audio.ctlcnt = max; 4191162922Sariff 4192162922Sariff if (max < 1) 4193162922Sariff return; 4194162922Sariff 4195162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4196162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4197162922Sariff 4198162922Sariff if (ctls == NULL) { 4199162922Sariff /* Blekh! */ 4200162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4201162922Sariff devinfo->function.audio.ctlcnt = 0; 4202162922Sariff return; 4203162922Sariff } 4204162922Sariff 4205162922Sariff cnt = 0; 4206162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4207162922Sariff if (cnt >= max) { 4208162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4209162922Sariff __func__); 4210162922Sariff break; 4211162922Sariff } 4212162922Sariff w = hdac_widget_get(devinfo, i); 4213162922Sariff if (w == NULL || w->enable == 0) 4214162922Sariff continue; 4215162922Sariff ocap = w->param.outamp_cap; 4216162922Sariff icap = w->param.inamp_cap; 4217162922Sariff if (ocap != 0) { 4218163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4219163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4220163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4221163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4222163057Sariff /*if (offset > step) { 4223163057Sariff HDA_BOOTVERBOSE( 4224163057Sariff device_printf(sc->dev, 4225182999Smav "BUGGY outamp: nid=%d " 4226163057Sariff "[offset=%d > step=%d]\n", 4227163057Sariff w->nid, offset, step); 4228163057Sariff ); 4229163057Sariff offset = step; 4230163057Sariff }*/ 4231162922Sariff ctls[cnt].enable = 1; 4232162922Sariff ctls[cnt].widget = w; 4233163057Sariff ctls[cnt].mute = mute; 4234163057Sariff ctls[cnt].step = step; 4235163057Sariff ctls[cnt].size = size; 4236163057Sariff ctls[cnt].offset = offset; 4237163057Sariff ctls[cnt].left = offset; 4238163057Sariff ctls[cnt].right = offset; 4239182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4240182999Smav w->waspin) 4241182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4242182999Smav else 4243182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4244162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4245162922Sariff } 4246162922Sariff 4247162922Sariff if (icap != 0) { 4248163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4249163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4250163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4251163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4252163057Sariff /*if (offset > step) { 4253163057Sariff HDA_BOOTVERBOSE( 4254163057Sariff device_printf(sc->dev, 4255182999Smav "BUGGY inamp: nid=%d " 4256163057Sariff "[offset=%d > step=%d]\n", 4257163057Sariff w->nid, offset, step); 4258163057Sariff ); 4259163057Sariff offset = step; 4260163057Sariff }*/ 4261162922Sariff switch (w->type) { 4262162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4263162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4264162922Sariff for (j = 0; j < w->nconns; j++) { 4265162922Sariff if (cnt >= max) { 4266162922Sariff device_printf(sc->dev, 4267162922Sariff "%s: Ctl overflow!\n", 4268162922Sariff __func__); 4269162922Sariff break; 4270162922Sariff } 4271162922Sariff cw = hdac_widget_get(devinfo, 4272162922Sariff w->conns[j]); 4273162922Sariff if (cw == NULL || cw->enable == 0) 4274162922Sariff continue; 4275162922Sariff ctls[cnt].enable = 1; 4276162922Sariff ctls[cnt].widget = w; 4277162922Sariff ctls[cnt].childwidget = cw; 4278162922Sariff ctls[cnt].index = j; 4279163057Sariff ctls[cnt].mute = mute; 4280163057Sariff ctls[cnt].step = step; 4281163057Sariff ctls[cnt].size = size; 4282163057Sariff ctls[cnt].offset = offset; 4283163057Sariff ctls[cnt].left = offset; 4284163057Sariff ctls[cnt].right = offset; 4285182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4286162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4287162922Sariff } 4288162922Sariff break; 4289162922Sariff default: 4290162922Sariff if (cnt >= max) { 4291162922Sariff device_printf(sc->dev, 4292162922Sariff "%s: Ctl overflow!\n", 4293162922Sariff __func__); 4294162922Sariff break; 4295162922Sariff } 4296162922Sariff ctls[cnt].enable = 1; 4297162922Sariff ctls[cnt].widget = w; 4298163057Sariff ctls[cnt].mute = mute; 4299163057Sariff ctls[cnt].step = step; 4300163057Sariff ctls[cnt].size = size; 4301163057Sariff ctls[cnt].offset = offset; 4302163057Sariff ctls[cnt].left = offset; 4303163057Sariff ctls[cnt].right = offset; 4304182999Smav if (w->type == 4305182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4306182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4307182999Smav else 4308182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4309162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4310162922Sariff break; 4311162922Sariff } 4312162922Sariff } 4313162922Sariff } 4314162922Sariff 4315162922Sariff devinfo->function.audio.ctl = ctls; 4316162922Sariff} 4317162922Sariff 4318182999Smavstatic void 4319182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4320182999Smav{ 4321182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4322182999Smav struct hdac_audio_as *as; 4323182999Smav struct hdac_widget *w; 4324182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4325182999Smav 4326184991Smav /* Count present associations */ 4327182999Smav max = 0; 4328184991Smav for (j = 1; j < 16; j++) { 4329182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4330182999Smav w = hdac_widget_get(devinfo, i); 4331182999Smav if (w == NULL || w->enable == 0) 4332182999Smav continue; 4333182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4334182999Smav continue; 4335182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4336182999Smav != j) 4337182999Smav continue; 4338182999Smav max++; 4339182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4340182999Smav break; 4341182999Smav } 4342182999Smav } 4343182999Smav 4344182999Smav devinfo->function.audio.ascnt = max; 4345182999Smav 4346182999Smav if (max < 1) 4347182999Smav return; 4348182999Smav 4349182999Smav as = (struct hdac_audio_as *)malloc( 4350182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4351182999Smav 4352182999Smav if (as == NULL) { 4353182999Smav /* Blekh! */ 4354182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4355182999Smav devinfo->function.audio.ascnt = 0; 4356182999Smav return; 4357182999Smav } 4358182999Smav 4359182999Smav for (i = 0; i < max; i++) { 4360182999Smav as[i].hpredir = -1; 4361182999Smav as[i].chan = -1; 4362185225Smav as[i].digital = 1; 4363182999Smav } 4364182999Smav 4365182999Smav /* Scan associations skipping as=0. */ 4366182999Smav cnt = 0; 4367182999Smav for (j = 1; j < 16; j++) { 4368182999Smav first = 16; 4369182999Smav hpredir = 0; 4370182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4371182999Smav w = hdac_widget_get(devinfo, i); 4372182999Smav if (w == NULL || w->enable == 0) 4373182999Smav continue; 4374182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4375182999Smav continue; 4376182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4377182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4378182999Smav if (assoc != j) { 4379182999Smav continue; 4380182999Smav } 4381182999Smav KASSERT(cnt < max, 4382182999Smav ("%s: Associations owerflow (%d of %d)", 4383182999Smav __func__, cnt, max)); 4384182999Smav type = w->wclass.pin.config & 4385182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4386182999Smav /* Get pin direction. */ 4387182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4388182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4389182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4390182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4391182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4392182999Smav dir = HDA_CTL_OUT; 4393182999Smav else 4394182999Smav dir = HDA_CTL_IN; 4395182999Smav /* If this is a first pin - create new association. */ 4396182999Smav if (as[cnt].pincnt == 0) { 4397182999Smav as[cnt].enable = 1; 4398182999Smav as[cnt].index = j; 4399182999Smav as[cnt].dir = dir; 4400182999Smav } 4401182999Smav if (seq < first) 4402182999Smav first = seq; 4403182999Smav /* Check association correctness. */ 4404182999Smav if (as[cnt].pins[seq] != 0) { 4405182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4406182999Smav "in association %d! Disabling association.\n", 4407182999Smav __func__, seq, w->nid, j); 4408182999Smav as[cnt].enable = 0; 4409182999Smav } 4410182999Smav if (dir != as[cnt].dir) { 4411182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4412182999Smav "direction for association %d! Disabling " 4413182999Smav "association.\n", 4414182999Smav __func__, w->nid, j); 4415182999Smav as[cnt].enable = 0; 4416182999Smav } 4417185225Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 4418185225Smav as[cnt].digital = 0; 4419182999Smav /* Headphones with seq=15 may mean redirection. */ 4420182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4421182999Smav seq == 15) 4422182999Smav hpredir = 1; 4423182999Smav as[cnt].pins[seq] = w->nid; 4424182999Smav as[cnt].pincnt++; 4425182999Smav /* Association 15 is a multiple unassociated pins. */ 4426182999Smav if (j == 15) 4427182999Smav cnt++; 4428182999Smav } 4429182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4430182999Smav if (hpredir && as[cnt].pincnt > 1) 4431182999Smav as[cnt].hpredir = first; 4432182999Smav cnt++; 4433182999Smav } 4434182999Smav } 4435182999Smav HDA_BOOTVERBOSE( 4436182999Smav device_printf(sc->dev, 4437183097Smav "%d associations found:\n", max); 4438182999Smav for (i = 0; i < max; i++) { 4439182999Smav device_printf(sc->dev, 4440182999Smav "Association %d (%d) %s%s:\n", 4441182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4442182999Smav as[i].enable?"":" (disabled)"); 4443182999Smav for (j = 0; j < 16; j++) { 4444182999Smav if (as[i].pins[j] == 0) 4445182999Smav continue; 4446182999Smav device_printf(sc->dev, 4447183097Smav " Pin nid=%d seq=%d\n", 4448182999Smav as[i].pins[j], j); 4449182999Smav } 4450182999Smav } 4451182999Smav ); 4452182999Smav 4453182999Smav devinfo->function.audio.as = as; 4454182999Smav} 4455182999Smav 4456162965Sariffstatic const struct { 4457162965Sariff uint32_t model; 4458162965Sariff uint32_t id; 4459162965Sariff uint32_t set, unset; 4460162965Sariff} hdac_quirks[] = { 4461163057Sariff /* 4462163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4463163057Sariff * on few codecs (especially ALC880) seems broken or 4464163057Sariff * perhaps unsupported. 4465163057Sariff */ 4466163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4467169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4468162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4469165039Sariff HDA_QUIRK_GPIO0, 0 }, 4470178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4471178155Sariff HDA_QUIRK_GPIO0, 0 }, 4472162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4473165039Sariff HDA_QUIRK_GPIO0, 0 }, 4474165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4475165281Sariff HDA_QUIRK_GPIO0, 0 }, 4476167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4477167623Sariff HDA_QUIRK_GPIO0, 0 }, 4478169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4479169277Sariff HDA_QUIRK_GPIO0, 0 }, 4480163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4481163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4482178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4483163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4484169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4485169277Sariff HDA_QUIRK_OVREF, 0 }, 4486169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4487169277Sariff HDA_QUIRK_OVREF, 0 }, 4488169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4489169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4490165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4491165281Sariff HDA_QUIRK_GPIO1, 0 }, 4492164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4493182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4494164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4495164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4496173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4497173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4498165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4499165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4500183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4501180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4502184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4503184483Smav HDA_QUIRK_GPIO2, 0 }, 4504183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4505178155Sariff HDA_QUIRK_GPIO0, 0 }, 4506169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4507169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4508170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4509170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4510186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4511182999Smav 0, HDA_QUIRK_FORCESTEREO } 4512162965Sariff}; 4513162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4514162965Sariff 4515162922Sariffstatic void 4516162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4517162922Sariff{ 4518162922Sariff struct hdac_widget *w; 4519162965Sariff uint32_t id, subvendor; 4520162922Sariff int i; 4521162922Sariff 4522182999Smav id = hdac_codec_id(devinfo->codec); 4523163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4524163057Sariff 4525162922Sariff /* 4526163057Sariff * Quirks 4527162922Sariff */ 4528163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4529163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4530163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4531163057Sariff continue; 4532163057Sariff if (hdac_quirks[i].set != 0) 4533163057Sariff devinfo->function.audio.quirks |= 4534163057Sariff hdac_quirks[i].set; 4535163057Sariff if (hdac_quirks[i].unset != 0) 4536163057Sariff devinfo->function.audio.quirks &= 4537163057Sariff ~(hdac_quirks[i].unset); 4538163057Sariff } 4539163057Sariff 4540162922Sariff switch (id) { 4541166965Sariff case HDA_CODEC_ALC883: 4542166965Sariff /* 4543166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4544166965Sariff * Clear vref cap for jack connectivity. 4545166965Sariff */ 4546166965Sariff w = hdac_widget_get(devinfo, 24); 4547166965Sariff if (w != NULL && w->enable != 0 && w->type == 4548166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4549166965Sariff (w->wclass.pin.config & 4550166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4551166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4552166965Sariff w->wclass.pin.cap &= ~( 4553166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4554166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4555166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4556166965Sariff w = hdac_widget_get(devinfo, 25); 4557166965Sariff if (w != NULL && w->enable != 0 && w->type == 4558166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4559166965Sariff (w->wclass.pin.config & 4560166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4561166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4562166965Sariff w->wclass.pin.cap &= ~( 4563166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4564166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4565166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4566166965Sariff /* 4567166965Sariff * nid: 26 = Line-in, leave it alone. 4568166965Sariff */ 4569166965Sariff break; 4570162922Sariff case HDA_CODEC_AD1986A: 4571186503Smav /* 4572186503Smav * This codec has overcomplicated input mixing. 4573186503Smav * Make some cleaning there. 4574186503Smav */ 4575186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4576186503Smav w = hdac_widget_get(devinfo, 43); 4577186503Smav if (w != NULL) 4578186503Smav w->enable = 0; 4579186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4580186503Smav w = hdac_widget_get(devinfo, 39); 4581186503Smav if (w != NULL) 4582186503Smav w->enable = 0; 4583186503Smav w = hdac_widget_get(devinfo, 40); 4584186503Smav if (w != NULL) 4585186503Smav w->enable = 0; 4586186503Smav w = hdac_widget_get(devinfo, 41); 4587186503Smav if (w != NULL) 4588186503Smav w->enable = 0; 4589186503Smav w = hdac_widget_get(devinfo, 42); 4590186503Smav if (w != NULL) 4591186503Smav w->enable = 0; 4592186503Smav /* Disable duplicate mixer node connector. */ 4593186503Smav w = hdac_widget_get(devinfo, 15); 4594186503Smav if (w != NULL) 4595186503Smav w->connsenable[3] = 0; 4596186503Smav 4597182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4598178155Sariff /* 4599178155Sariff * This is just plain ridiculous.. There 4600178155Sariff * are several A8 series that share the same 4601178155Sariff * pci id but works differently (EAPD). 4602178155Sariff */ 4603178155Sariff w = hdac_widget_get(devinfo, 26); 4604178155Sariff if (w != NULL && w->type == 4605178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4606178155Sariff (w->wclass.pin.config & 4607178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4608178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4609178155Sariff devinfo->function.audio.quirks &= 4610178155Sariff ~HDA_QUIRK_EAPDINV; 4611169277Sariff } 4612162922Sariff break; 4613184230Smav case HDA_CODEC_AD1981HD: 4614184230Smav /* 4615184230Smav * This codec has very unusual design with several 4616184254Smav * points inappropriate for the present parser. 4617184230Smav */ 4618184230Smav /* Disable recording from mono playback mix. */ 4619184230Smav w = hdac_widget_get(devinfo, 21); 4620184230Smav if (w != NULL) 4621184230Smav w->connsenable[3] = 0; 4622184230Smav /* Disable rear to front mic mixer, use separately. */ 4623184230Smav w = hdac_widget_get(devinfo, 31); 4624184230Smav if (w != NULL) 4625184230Smav w->enable = 0; 4626184230Smav /* Disable playback mixer, use direct bypass. */ 4627184230Smav w = hdac_widget_get(devinfo, 14); 4628184230Smav if (w != NULL) 4629184230Smav w->enable = 0; 4630184230Smav break; 4631182999Smav } 4632182999Smav} 4633182999Smav 4634182999Smav/* 4635182999Smav * Trace path from DAC to pin. 4636182999Smav */ 4637182999Smavstatic nid_t 4638182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4639182999Smav int dupseq, int min, int only, int depth) 4640182999Smav{ 4641182999Smav struct hdac_widget *w; 4642182999Smav int i, im = -1; 4643182999Smav nid_t m = 0, ret; 4644182999Smav 4645182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4646182999Smav return (0); 4647182999Smav w = hdac_widget_get(devinfo, nid); 4648182999Smav if (w == NULL || w->enable == 0) 4649182999Smav return (0); 4650183097Smav HDA_BOOTHVERBOSE( 4651182999Smav if (!only) { 4652182999Smav device_printf(devinfo->codec->sc->dev, 4653182999Smav " %*stracing via nid %d\n", 4654182999Smav depth + 1, "", w->nid); 4655169277Sariff } 4656182999Smav ); 4657182999Smav /* Use only unused widgets */ 4658182999Smav if (w->bindas >= 0 && w->bindas != as) { 4659183097Smav HDA_BOOTHVERBOSE( 4660182999Smav if (!only) { 4661182999Smav device_printf(devinfo->codec->sc->dev, 4662182999Smav " %*snid %d busy by association %d\n", 4663182999Smav depth + 1, "", w->nid, w->bindas); 4664182999Smav } 4665182999Smav ); 4666182999Smav return (0); 4667182999Smav } 4668182999Smav if (dupseq < 0) { 4669182999Smav if (w->bindseqmask != 0) { 4670183097Smav HDA_BOOTHVERBOSE( 4671182999Smav if (!only) { 4672182999Smav device_printf(devinfo->codec->sc->dev, 4673182999Smav " %*snid %d busy by seqmask %x\n", 4674182999Smav depth + 1, "", w->nid, w->bindseqmask); 4675182999Smav } 4676182999Smav ); 4677182999Smav return (0); 4678169277Sariff } 4679182999Smav } else { 4680182999Smav /* If this is headphones - allow duplicate first pin. */ 4681182999Smav if (w->bindseqmask != 0 && 4682182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4683183097Smav HDA_BOOTHVERBOSE( 4684182999Smav device_printf(devinfo->codec->sc->dev, 4685182999Smav " %*snid %d busy by seqmask %x\n", 4686182999Smav depth + 1, "", w->nid, w->bindseqmask); 4687182999Smav ); 4688182999Smav return (0); 4689169277Sariff } 4690182999Smav } 4691182999Smav 4692182999Smav switch (w->type) { 4693182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4694182999Smav /* Do not traverse input. AD1988 has digital monitor 4695182999Smav for which we are not ready. */ 4696169277Sariff break; 4697182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4698182999Smav /* If we are tracing HP take only dac of first pin. */ 4699182999Smav if ((only == 0 || only == w->nid) && 4700182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4701182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4702182999Smav m = w->nid; 4703178155Sariff break; 4704182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4705182999Smav if (depth > 0) 4706169277Sariff break; 4707182999Smav /* Fall */ 4708182999Smav default: 4709182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4710182999Smav for (i = 0; i < w->nconns; i++) { 4711182999Smav if (w->connsenable[i] == 0) 4712162922Sariff continue; 4713182999Smav if (w->selconn != -1 && w->selconn != i) 4714162922Sariff continue; 4715182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4716182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4717182999Smav if (m == 0 || ret < m) { 4718182999Smav m = ret; 4719182999Smav im = i; 4720182999Smav } 4721182999Smav if (only || dupseq >= 0) 4722182999Smav break; 4723182999Smav } 4724162922Sariff } 4725182999Smav if (m && only && ((w->nconns > 1 && 4726182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4727182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4728182999Smav w->selconn = im; 4729162922Sariff break; 4730182999Smav } 4731182999Smav if (m && only) { 4732182999Smav w->bindas = as; 4733182999Smav w->bindseqmask |= (1 << seq); 4734182999Smav } 4735183097Smav HDA_BOOTHVERBOSE( 4736182999Smav if (!only) { 4737182999Smav device_printf(devinfo->codec->sc->dev, 4738182999Smav " %*snid %d returned %d\n", 4739182999Smav depth + 1, "", w->nid, m); 4740182999Smav } 4741182999Smav ); 4742182999Smav return (m); 4743182999Smav} 4744162922Sariff 4745182999Smav/* 4746182999Smav * Trace path from widget to ADC. 4747182999Smav */ 4748182999Smavstatic nid_t 4749182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4750182999Smav int only, int depth) 4751182999Smav{ 4752182999Smav struct hdac_widget *w, *wc; 4753182999Smav int i, j; 4754182999Smav nid_t res = 0; 4755182999Smav 4756182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4757182999Smav return (0); 4758182999Smav w = hdac_widget_get(devinfo, nid); 4759182999Smav if (w == NULL || w->enable == 0) 4760182999Smav return (0); 4761183097Smav HDA_BOOTHVERBOSE( 4762182999Smav device_printf(devinfo->codec->sc->dev, 4763182999Smav " %*stracing via nid %d\n", 4764182999Smav depth + 1, "", w->nid); 4765182999Smav ); 4766182999Smav /* Use only unused widgets */ 4767182999Smav if (w->bindas >= 0 && w->bindas != as) { 4768183097Smav HDA_BOOTHVERBOSE( 4769182999Smav device_printf(devinfo->codec->sc->dev, 4770182999Smav " %*snid %d busy by association %d\n", 4771182999Smav depth + 1, "", w->nid, w->bindas); 4772182999Smav ); 4773182999Smav return (0); 4774182999Smav } 4775182999Smav 4776182999Smav switch (w->type) { 4777182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4778182999Smav /* If we are tracing HP take only dac of first pin. */ 4779182999Smav if (only == w->nid) 4780182999Smav res = 1; 4781162922Sariff break; 4782182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4783182999Smav if (depth > 0) 4784182999Smav break; 4785182999Smav /* Fall */ 4786182999Smav default: 4787182999Smav /* Try to find reachable ADCs with specified nid. */ 4788182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4789182999Smav wc = hdac_widget_get(devinfo, j); 4790182999Smav if (wc == NULL || wc->enable == 0) 4791182999Smav continue; 4792182999Smav for (i = 0; i < wc->nconns; i++) { 4793182999Smav if (wc->connsenable[i] == 0) 4794182999Smav continue; 4795182999Smav if (wc->conns[i] != nid) 4796182999Smav continue; 4797182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 4798182999Smav j, only, depth + 1) != 0) { 4799182999Smav res = 1; 4800182999Smav if (((wc->nconns > 1 && 4801182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4802182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 4803182999Smav wc->selconn == -1) 4804182999Smav wc->selconn = i; 4805182999Smav } 4806182999Smav } 4807169277Sariff } 4808169277Sariff break; 4809162922Sariff } 4810182999Smav if (res) { 4811182999Smav w->bindas = as; 4812182999Smav w->bindseqmask |= (1 << seq); 4813182999Smav } 4814183097Smav HDA_BOOTHVERBOSE( 4815182999Smav device_printf(devinfo->codec->sc->dev, 4816182999Smav " %*snid %d returned %d\n", 4817182999Smav depth + 1, "", w->nid, res); 4818182999Smav ); 4819182999Smav return (res); 4820162922Sariff} 4821162922Sariff 4822182999Smav/* 4823182999Smav * Erase trace path of the specified association. 4824182999Smav */ 4825182999Smavstatic void 4826182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 4827182999Smav{ 4828182999Smav struct hdac_widget *w; 4829182999Smav int i; 4830182999Smav 4831182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4832182999Smav w = hdac_widget_get(devinfo, i); 4833182999Smav if (w == NULL || w->enable == 0) 4834182999Smav continue; 4835182999Smav if (w->bindas == as) { 4836182999Smav if (seq >= 0) { 4837182999Smav w->bindseqmask &= ~(1 << seq); 4838182999Smav if (w->bindseqmask == 0) { 4839182999Smav w->bindas = -1; 4840182999Smav w->selconn = -1; 4841182999Smav } 4842182999Smav } else { 4843182999Smav w->bindas = -1; 4844182999Smav w->bindseqmask = 0; 4845182999Smav w->selconn = -1; 4846182999Smav } 4847182999Smav } 4848182999Smav } 4849182999Smav} 4850182999Smav 4851182999Smav/* 4852182999Smav * Trace association path from DAC to output 4853182999Smav */ 4854162922Sariffstatic int 4855182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 4856162922Sariff{ 4857182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4858182999Smav int i, hpredir; 4859182999Smav nid_t min, res; 4860162922Sariff 4861182999Smav /* Find next pin */ 4862185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 4863182999Smav ; 4864182999Smav /* Check if there is no any left. If so - we succeded. */ 4865182999Smav if (i == 16) 4866182999Smav return (1); 4867182999Smav 4868182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 4869182999Smav min = 0; 4870182999Smav res = 0; 4871182999Smav do { 4872183097Smav HDA_BOOTHVERBOSE( 4873182999Smav device_printf(devinfo->codec->sc->dev, 4874182999Smav " Tracing pin %d with min nid %d", 4875182999Smav ases[as].pins[i], min); 4876182999Smav if (hpredir >= 0) 4877183097Smav printf(" and hpredir %d", hpredir); 4878183097Smav printf("\n"); 4879182999Smav ); 4880182999Smav /* Trace this pin taking min nid into account. */ 4881182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 4882182999Smav ases[as].pins[i], hpredir, min, 0, 0); 4883182999Smav if (res == 0) { 4884182999Smav /* If we failed - return to previous and redo it. */ 4885182999Smav HDA_BOOTVERBOSE( 4886182999Smav device_printf(devinfo->codec->sc->dev, 4887182999Smav " Unable to trace pin %d seq %d with min " 4888183097Smav "nid %d", 4889183097Smav ases[as].pins[i], i, min); 4890183097Smav if (hpredir >= 0) 4891183097Smav printf(" and hpredir %d", hpredir); 4892183097Smav printf("\n"); 4893182999Smav ); 4894182999Smav return (0); 4895162922Sariff } 4896182999Smav HDA_BOOTVERBOSE( 4897182999Smav device_printf(devinfo->codec->sc->dev, 4898183097Smav " Pin %d traced to DAC %d", 4899183097Smav ases[as].pins[i], res); 4900183097Smav if (hpredir >= 0) 4901183097Smav printf(" and hpredir %d", hpredir); 4902183097Smav if (ases[as].fakeredir) 4903183097Smav printf(" with fake redirection"); 4904183097Smav printf("\n"); 4905182999Smav ); 4906182999Smav /* Trace again to mark the path */ 4907182999Smav hdac_audio_trace_dac(devinfo, as, i, 4908182999Smav ases[as].pins[i], hpredir, min, res, 0); 4909182999Smav ases[as].dacs[i] = res; 4910182999Smav /* We succeded, so call next. */ 4911182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 4912182999Smav return (1); 4913182999Smav /* If next failed, we should retry with next min */ 4914182999Smav hdac_audio_undo_trace(devinfo, as, i); 4915182999Smav ases[as].dacs[i] = 0; 4916182999Smav min = res + 1; 4917182999Smav } while (1); 4918162922Sariff} 4919162922Sariff 4920182999Smav/* 4921182999Smav * Trace association path from input to ADC 4922182999Smav */ 4923162922Sariffstatic int 4924182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 4925162922Sariff{ 4926182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4927162922Sariff struct hdac_widget *w; 4928182999Smav int i, j, k; 4929162922Sariff 4930182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4931182999Smav w = hdac_widget_get(devinfo, j); 4932182999Smav if (w == NULL || w->enable == 0) 4933182999Smav continue; 4934182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4935182999Smav continue; 4936182999Smav if (w->bindas >= 0 && w->bindas != as) 4937182999Smav continue; 4938182999Smav 4939182999Smav /* Find next pin */ 4940182999Smav for (i = 0; i < 16; i++) { 4941182999Smav if (ases[as].pins[i] == 0) 4942182999Smav continue; 4943182999Smav 4944183097Smav HDA_BOOTHVERBOSE( 4945182999Smav device_printf(devinfo->codec->sc->dev, 4946182999Smav " Tracing pin %d to ADC %d\n", 4947182999Smav ases[as].pins[i], j); 4948182999Smav ); 4949182999Smav /* Trace this pin taking goal into account. */ 4950182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 4951182999Smav ases[as].pins[i], j, 0) == 0) { 4952182999Smav /* If we failed - return to previous and redo it. */ 4953182999Smav HDA_BOOTVERBOSE( 4954182999Smav device_printf(devinfo->codec->sc->dev, 4955183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 4956182999Smav ases[as].pins[i], j); 4957182999Smav ); 4958182999Smav hdac_audio_undo_trace(devinfo, as, -1); 4959182999Smav for (k = 0; k < 16; k++) 4960182999Smav ases[as].dacs[k] = 0; 4961182999Smav break; 4962162922Sariff } 4963182999Smav HDA_BOOTVERBOSE( 4964182999Smav device_printf(devinfo->codec->sc->dev, 4965183097Smav " Pin %d traced to ADC %d\n", 4966183097Smav ases[as].pins[i], j); 4967182999Smav ); 4968182999Smav ases[as].dacs[i] = j; 4969162922Sariff } 4970182999Smav if (i == 16) 4971182999Smav return (1); 4972162922Sariff } 4973182999Smav return (0); 4974162922Sariff} 4975162922Sariff 4976182999Smav/* 4977182999Smav * Trace input monitor path from mixer to output association. 4978182999Smav */ 4979183097Smavstatic int 4980182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4981162922Sariff{ 4982182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4983182999Smav struct hdac_widget *w, *wc; 4984182999Smav int i, j; 4985182999Smav nid_t res = 0; 4986162922Sariff 4987162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4988162922Sariff return (0); 4989162922Sariff w = hdac_widget_get(devinfo, nid); 4990162922Sariff if (w == NULL || w->enable == 0) 4991162922Sariff return (0); 4992183097Smav HDA_BOOTHVERBOSE( 4993182999Smav device_printf(devinfo->codec->sc->dev, 4994182999Smav " %*stracing via nid %d\n", 4995182999Smav depth + 1, "", w->nid); 4996182999Smav ); 4997182999Smav /* Use only unused widgets */ 4998182999Smav if (depth > 0 && w->bindas != -1) { 4999182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5000183097Smav HDA_BOOTHVERBOSE( 5001182999Smav device_printf(devinfo->codec->sc->dev, 5002182999Smav " %*snid %d found output association %d\n", 5003182999Smav depth + 1, "", w->nid, w->bindas); 5004182999Smav ); 5005182999Smav return (1); 5006182999Smav } else { 5007183097Smav HDA_BOOTHVERBOSE( 5008182999Smav device_printf(devinfo->codec->sc->dev, 5009182999Smav " %*snid %d busy by input association %d\n", 5010182999Smav depth + 1, "", w->nid, w->bindas); 5011182999Smav ); 5012182999Smav return (0); 5013182999Smav } 5014182999Smav } 5015182999Smav 5016162922Sariff switch (w->type) { 5017162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5018182999Smav /* Do not traverse input. AD1988 has digital monitor 5019182999Smav for which we are not ready. */ 5020162922Sariff break; 5021162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5022182999Smav if (depth > 0) 5023182999Smav break; 5024182999Smav /* Fall */ 5025182999Smav default: 5026182999Smav /* Try to find reachable ADCs with specified nid. */ 5027182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5028182999Smav wc = hdac_widget_get(devinfo, j); 5029182999Smav if (wc == NULL || wc->enable == 0) 5030182999Smav continue; 5031182999Smav for (i = 0; i < wc->nconns; i++) { 5032182999Smav if (wc->connsenable[i] == 0) 5033182999Smav continue; 5034182999Smav if (wc->conns[i] != nid) 5035182999Smav continue; 5036182999Smav if (hdac_audio_trace_to_out(devinfo, 5037182999Smav j, depth + 1) != 0) { 5038182999Smav res = 1; 5039182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5040182999Smav wc->selconn == -1) 5041182999Smav wc->selconn = i; 5042182999Smav } 5043182999Smav } 5044162922Sariff } 5045162922Sariff break; 5046182999Smav } 5047182999Smav if (res) 5048182999Smav w->bindas = -2; 5049182999Smav 5050183097Smav HDA_BOOTHVERBOSE( 5051182999Smav device_printf(devinfo->codec->sc->dev, 5052182999Smav " %*snid %d returned %d\n", 5053182999Smav depth + 1, "", w->nid, res); 5054182999Smav ); 5055182999Smav return (res); 5056182999Smav} 5057182999Smav 5058182999Smav/* 5059182999Smav * Trace extra associations (beeper, monitor) 5060182999Smav */ 5061182999Smavstatic void 5062182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5063182999Smav{ 5064182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5065182999Smav struct hdac_widget *w; 5066182999Smav int j; 5067182999Smav 5068182999Smav /* Input monitor */ 5069182999Smav /* Find mixer associated with input, but supplying signal 5070182999Smav for output associations. Hope it will be input monitor. */ 5071182999Smav HDA_BOOTVERBOSE( 5072182999Smav device_printf(devinfo->codec->sc->dev, 5073182999Smav "Tracing input monitor\n"); 5074182999Smav ); 5075182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5076182999Smav w = hdac_widget_get(devinfo, j); 5077182999Smav if (w == NULL || w->enable == 0) 5078182999Smav continue; 5079182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5080182999Smav continue; 5081182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5082182999Smav continue; 5083182999Smav HDA_BOOTVERBOSE( 5084182999Smav device_printf(devinfo->codec->sc->dev, 5085182999Smav " Tracing nid %d to out\n", 5086182999Smav j); 5087182999Smav ); 5088182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5089182999Smav HDA_BOOTVERBOSE( 5090182999Smav device_printf(devinfo->codec->sc->dev, 5091182999Smav " nid %d is input monitor\n", 5092182999Smav w->nid); 5093182999Smav ); 5094182999Smav w->pflags |= HDA_ADC_MONITOR; 5095182999Smav w->ossdev = SOUND_MIXER_IMIX; 5096162922Sariff } 5097162922Sariff } 5098182999Smav 5099182999Smav /* Beeper */ 5100182999Smav HDA_BOOTVERBOSE( 5101182999Smav device_printf(devinfo->codec->sc->dev, 5102182999Smav "Tracing beeper\n"); 5103182999Smav ); 5104182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5105182999Smav w = hdac_widget_get(devinfo, j); 5106182999Smav if (w == NULL || w->enable == 0) 5107182999Smav continue; 5108182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5109182999Smav continue; 5110183097Smav HDA_BOOTHVERBOSE( 5111182999Smav device_printf(devinfo->codec->sc->dev, 5112182999Smav " Tracing nid %d to out\n", 5113182999Smav j); 5114182999Smav ); 5115183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5116183097Smav HDA_BOOTVERBOSE( 5117183097Smav device_printf(devinfo->codec->sc->dev, 5118183097Smav " nid %d traced to out\n", 5119183097Smav j); 5120183097Smav ); 5121183097Smav } 5122182999Smav w->bindas = -2; 5123182999Smav } 5124162922Sariff} 5125162922Sariff 5126182999Smav/* 5127182999Smav * Bind assotiations to PCM channels 5128182999Smav */ 5129182999Smavstatic void 5130182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5131162922Sariff{ 5132182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5133182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5134182999Smav int j, cnt = 0, free; 5135162922Sariff 5136182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5137182999Smav if (as[j].enable) 5138182999Smav cnt++; 5139182999Smav } 5140182999Smav if (sc->num_chans == 0) { 5141182999Smav sc->chans = (struct hdac_chan *)malloc( 5142182999Smav sizeof(struct hdac_chan) * cnt, 5143182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5144182999Smav if (sc->chans == NULL) { 5145182999Smav device_printf(devinfo->codec->sc->dev, 5146182999Smav "Channels memory allocation failed!\n"); 5147182999Smav return; 5148182999Smav } 5149182999Smav } else { 5150182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5151183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5152182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5153182999Smav if (sc->chans == NULL) { 5154182999Smav sc->num_chans = 0; 5155182999Smav device_printf(devinfo->codec->sc->dev, 5156182999Smav "Channels memory allocation failed!\n"); 5157182999Smav return; 5158182999Smav } 5159182999Smav } 5160182999Smav free = sc->num_chans; 5161182999Smav sc->num_chans += cnt; 5162162922Sariff 5163182999Smav for (j = free; j < free + cnt; j++) { 5164182999Smav devinfo->codec->sc->chans[j].devinfo = devinfo; 5165182999Smav devinfo->codec->sc->chans[j].as = -1; 5166182999Smav } 5167162922Sariff 5168182999Smav /* Assign associations in order of their numbers, */ 5169182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5170182999Smav if (as[j].enable == 0) 5171182999Smav continue; 5172182999Smav 5173182999Smav as[j].chan = free; 5174182999Smav devinfo->codec->sc->chans[free].as = j; 5175185225Smav devinfo->codec->sc->chans[free].dir = 5176185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5177182999Smav hdac_pcmchannel_setup(&devinfo->codec->sc->chans[free]); 5178182999Smav free++; 5179182999Smav } 5180182999Smav} 5181162922Sariff 5182182999Smavstatic void 5183182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5184182999Smav{ 5185182999Smav struct hdac_widget *w; 5186182999Smav int i; 5187182999Smav 5188182999Smav /* Disable power and volume widgets. */ 5189182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5190182999Smav w = hdac_widget_get(devinfo, i); 5191182999Smav if (w == NULL || w->enable == 0) 5192182999Smav continue; 5193182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5194182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5195182999Smav w->enable = 0; 5196183097Smav HDA_BOOTHVERBOSE( 5197182999Smav device_printf(devinfo->codec->sc->dev, 5198182999Smav " Disabling nid %d due to it's" 5199182999Smav " non-audio type.\n", 5200182999Smav w->nid); 5201182999Smav ); 5202162922Sariff } 5203182999Smav } 5204182999Smav} 5205182999Smav 5206182999Smavstatic void 5207182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5208182999Smav{ 5209182999Smav struct hdac_widget *w, *cw; 5210182999Smav struct hdac_audio_ctl *ctl; 5211182999Smav int done, found, i, j, k; 5212182999Smav 5213182999Smav /* Disable useless pins. */ 5214182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5215182999Smav w = hdac_widget_get(devinfo, i); 5216182999Smav if (w == NULL || w->enable == 0) 5217182999Smav continue; 5218184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5219184991Smav if ((w->wclass.pin.config & 5220184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5221184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5222184991Smav w->enable = 0; 5223184991Smav HDA_BOOTHVERBOSE( 5224184991Smav device_printf(devinfo->codec->sc->dev, 5225184991Smav " Disabling pin nid %d due" 5226184991Smav " to None connectivity.\n", 5227184991Smav w->nid); 5228184991Smav ); 5229184991Smav } else if ((w->wclass.pin.config & 5230184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5231184991Smav w->enable = 0; 5232184991Smav HDA_BOOTHVERBOSE( 5233184991Smav device_printf(devinfo->codec->sc->dev, 5234184991Smav " Disabling unassociated" 5235184991Smav " pin nid %d.\n", 5236184991Smav w->nid); 5237184991Smav ); 5238184991Smav } 5239182999Smav } 5240182999Smav } 5241182999Smav do { 5242182999Smav done = 1; 5243182999Smav /* Disable and mute controls for disabled widgets. */ 5244162922Sariff i = 0; 5245162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5246182999Smav if (ctl->enable == 0) 5247162922Sariff continue; 5248182999Smav if (ctl->widget->enable == 0 || 5249182999Smav (ctl->childwidget != NULL && 5250182999Smav ctl->childwidget->enable == 0)) { 5251182999Smav ctl->forcemute = 1; 5252182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5253182999Smav ctl->left = 0; 5254182999Smav ctl->right = 0; 5255182999Smav ctl->enable = 0; 5256182999Smav if (ctl->ndir == HDA_CTL_IN) 5257182999Smav ctl->widget->connsenable[ctl->index] = 0; 5258182999Smav done = 0; 5259183097Smav HDA_BOOTHVERBOSE( 5260182999Smav device_printf(devinfo->codec->sc->dev, 5261182999Smav " Disabling ctl %d nid %d cnid %d due" 5262182999Smav " to disabled widget.\n", i, 5263182999Smav ctl->widget->nid, 5264182999Smav (ctl->childwidget != NULL)? 5265182999Smav ctl->childwidget->nid:-1); 5266182999Smav ); 5267182999Smav } 5268182999Smav } 5269182999Smav /* Disable useless widgets. */ 5270182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5271182999Smav w = hdac_widget_get(devinfo, i); 5272182999Smav if (w == NULL || w->enable == 0) 5273182999Smav continue; 5274182999Smav /* Disable inputs with disabled child widgets. */ 5275182999Smav for (j = 0; j < w->nconns; j++) { 5276182999Smav if (w->connsenable[j]) { 5277182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5278182999Smav if (cw == NULL || cw->enable == 0) { 5279182999Smav w->connsenable[j] = 0; 5280183097Smav HDA_BOOTHVERBOSE( 5281182999Smav device_printf(devinfo->codec->sc->dev, 5282182999Smav " Disabling nid %d connection %d due" 5283182999Smav " to disabled child widget.\n", 5284182999Smav i, j); 5285182999Smav ); 5286163057Sariff } 5287163057Sariff } 5288162922Sariff } 5289182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5290182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5291162922Sariff continue; 5292182999Smav /* Disable mixers and selectors without inputs. */ 5293182999Smav found = 0; 5294182999Smav for (j = 0; j < w->nconns; j++) { 5295182999Smav if (w->connsenable[j]) { 5296182999Smav found = 1; 5297162922Sariff break; 5298162922Sariff } 5299182999Smav } 5300182999Smav if (found == 0) { 5301182999Smav w->enable = 0; 5302182999Smav done = 0; 5303183097Smav HDA_BOOTHVERBOSE( 5304182999Smav device_printf(devinfo->codec->sc->dev, 5305182999Smav " Disabling nid %d due to all it's" 5306182999Smav " inputs disabled.\n", w->nid); 5307182999Smav ); 5308182999Smav } 5309182999Smav /* Disable nodes without consumers. */ 5310182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5311182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5312182999Smav continue; 5313182999Smav found = 0; 5314182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5315182999Smav cw = hdac_widget_get(devinfo, k); 5316182999Smav if (cw == NULL || cw->enable == 0) 5317182999Smav continue; 5318182999Smav for (j = 0; j < cw->nconns; j++) { 5319182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5320182999Smav found = 1; 5321182999Smav break; 5322182999Smav } 5323162922Sariff } 5324162922Sariff } 5325182999Smav if (found == 0) { 5326182999Smav w->enable = 0; 5327182999Smav done = 0; 5328183097Smav HDA_BOOTHVERBOSE( 5329182999Smav device_printf(devinfo->codec->sc->dev, 5330182999Smav " Disabling nid %d due to all it's" 5331182999Smav " consumers disabled.\n", w->nid); 5332182999Smav ); 5333182999Smav } 5334162922Sariff } 5335182999Smav } while (done == 0); 5336182999Smav 5337182999Smav} 5338182999Smav 5339182999Smavstatic void 5340182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5341182999Smav{ 5342182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5343182999Smav struct hdac_widget *w, *cw; 5344182999Smav struct hdac_audio_ctl *ctl; 5345182999Smav int i, j, k; 5346182999Smav 5347182999Smav /* Disable unassosiated widgets. */ 5348182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5349182999Smav w = hdac_widget_get(devinfo, i); 5350182999Smav if (w == NULL || w->enable == 0) 5351182999Smav continue; 5352182999Smav if (w->bindas == -1) { 5353182999Smav w->enable = 0; 5354183097Smav HDA_BOOTHVERBOSE( 5355182999Smav device_printf(devinfo->codec->sc->dev, 5356182999Smav " Disabling unassociated nid %d.\n", 5357182999Smav w->nid); 5358182999Smav ); 5359182999Smav } 5360182999Smav } 5361182999Smav /* Disable input connections on input pin and 5362182999Smav * output on output. */ 5363182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5364182999Smav w = hdac_widget_get(devinfo, i); 5365182999Smav if (w == NULL || w->enable == 0) 5366182999Smav continue; 5367182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5368182999Smav continue; 5369182999Smav if (w->bindas < 0) 5370182999Smav continue; 5371182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5372182999Smav for (j = 0; j < w->nconns; j++) { 5373182999Smav if (w->connsenable[j] == 0) 5374182999Smav continue; 5375182999Smav w->connsenable[j] = 0; 5376183097Smav HDA_BOOTHVERBOSE( 5377182999Smav device_printf(devinfo->codec->sc->dev, 5378182999Smav " Disabling connection to input pin " 5379182999Smav "nid %d conn %d.\n", 5380182999Smav i, j); 5381182999Smav ); 5382162922Sariff } 5383182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5384182999Smav HDA_CTL_IN, -1, 1); 5385182999Smav if (ctl && ctl->enable) { 5386182999Smav ctl->forcemute = 1; 5387182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5388182999Smav ctl->left = 0; 5389182999Smav ctl->right = 0; 5390182999Smav ctl->enable = 0; 5391182999Smav } 5392182999Smav } else { 5393182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5394182999Smav HDA_CTL_OUT, -1, 1); 5395182999Smav if (ctl && ctl->enable) { 5396182999Smav ctl->forcemute = 1; 5397182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5398182999Smav ctl->left = 0; 5399182999Smav ctl->right = 0; 5400182999Smav ctl->enable = 0; 5401182999Smav } 5402182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5403182999Smav cw = hdac_widget_get(devinfo, k); 5404182999Smav if (cw == NULL || cw->enable == 0) 5405182999Smav continue; 5406182999Smav for (j = 0; j < cw->nconns; j++) { 5407182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5408182999Smav cw->connsenable[j] = 0; 5409183097Smav HDA_BOOTHVERBOSE( 5410182999Smav device_printf(devinfo->codec->sc->dev, 5411182999Smav " Disabling connection from output pin " 5412182999Smav "nid %d conn %d cnid %d.\n", 5413182999Smav k, j, i); 5414182999Smav ); 5415182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5416182999Smav cw->nconns > 1) 5417182999Smav continue; 5418182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5419182999Smav HDA_CTL_IN, j, 1); 5420182999Smav if (ctl && ctl->enable) { 5421182999Smav ctl->forcemute = 1; 5422182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5423182999Smav ctl->left = 0; 5424182999Smav ctl->right = 0; 5425182999Smav ctl->enable = 0; 5426182999Smav } 5427182999Smav } 5428182999Smav } 5429182999Smav } 5430162922Sariff } 5431162922Sariff } 5432162922Sariff} 5433162922Sariff 5434182999Smavstatic void 5435182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5436162922Sariff{ 5437182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5438182999Smav struct hdac_widget *w; 5439182999Smav int i, j; 5440182999Smav 5441182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5442182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5443182999Smav w = hdac_widget_get(devinfo, i); 5444182999Smav if (w == NULL || w->enable == 0) 5445182999Smav continue; 5446182999Smav if (w->nconns <= 1) 5447182999Smav continue; 5448182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5449182999Smav continue; 5450182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5451182999Smav continue; 5452182999Smav for (j = 0; j < w->nconns; j++) { 5453182999Smav if (w->connsenable[j] == 0) 5454182999Smav continue; 5455182999Smav if (w->selconn < 0 || w->selconn == j) 5456182999Smav continue; 5457182999Smav w->connsenable[j] = 0; 5458183097Smav HDA_BOOTHVERBOSE( 5459182999Smav device_printf(devinfo->codec->sc->dev, 5460182999Smav " Disabling unselected connection " 5461182999Smav "nid %d conn %d.\n", 5462182999Smav i, j); 5463182999Smav ); 5464182999Smav } 5465182999Smav } 5466182999Smav} 5467182999Smav 5468182999Smavstatic void 5469182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5470182999Smav{ 5471162922Sariff struct hdac_widget *w, *cw; 5472162922Sariff struct hdac_audio_ctl *ctl; 5473182999Smav int i, j; 5474162922Sariff 5475182999Smav /* Disable crossassociatement connections. */ 5476182999Smav /* ... using selectors */ 5477182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5478182999Smav w = hdac_widget_get(devinfo, i); 5479182999Smav if (w == NULL || w->enable == 0) 5480182999Smav continue; 5481182999Smav if (w->nconns <= 1) 5482182999Smav continue; 5483182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5484182999Smav continue; 5485182999Smav if (w->bindas == -2) 5486182999Smav continue; 5487182999Smav for (j = 0; j < w->nconns; j++) { 5488182999Smav if (w->connsenable[j] == 0) 5489182999Smav continue; 5490182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5491182999Smav if (cw == NULL || w->enable == 0) 5492182999Smav continue; 5493182999Smav if (w->bindas == cw->bindas || cw->bindas == -2) 5494182999Smav continue; 5495182999Smav w->connsenable[j] = 0; 5496183097Smav HDA_BOOTHVERBOSE( 5497182999Smav device_printf(devinfo->codec->sc->dev, 5498182999Smav " Disabling crossassociatement connection " 5499182999Smav "nid %d conn %d cnid %d.\n", 5500182999Smav i, j, cw->nid); 5501182999Smav ); 5502182999Smav } 5503182999Smav } 5504182999Smav /* ... using controls */ 5505182999Smav i = 0; 5506182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5507182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5508182999Smav continue; 5509182999Smav if (ctl->widget->bindas == -2 || 5510182999Smav ctl->childwidget->bindas == -2) 5511182999Smav continue; 5512182999Smav if (ctl->widget->bindas != ctl->childwidget->bindas) { 5513182999Smav ctl->forcemute = 1; 5514182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5515182999Smav ctl->left = 0; 5516182999Smav ctl->right = 0; 5517182999Smav ctl->enable = 0; 5518182999Smav if (ctl->ndir == HDA_CTL_IN) 5519182999Smav ctl->widget->connsenable[ctl->index] = 0; 5520183097Smav HDA_BOOTHVERBOSE( 5521182999Smav device_printf(devinfo->codec->sc->dev, 5522182999Smav " Disabling crossassociatement connection " 5523182999Smav "ctl %d nid %d cnid %d.\n", i, 5524182999Smav ctl->widget->nid, 5525182999Smav ctl->childwidget->nid); 5526182999Smav ); 5527182999Smav } 5528182999Smav } 5529182999Smav 5530182999Smav} 5531182999Smav 5532182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5533182999Smav 5534182999Smav/* 5535182999Smav * Find controls to control amplification for source. 5536182999Smav */ 5537182999Smavstatic int 5538182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5539182999Smav int ossdev, int ctlable, int depth, int need) 5540182999Smav{ 5541182999Smav struct hdac_widget *w, *wc; 5542182999Smav struct hdac_audio_ctl *ctl; 5543182999Smav int i, j, conns = 0, rneed; 5544182999Smav 5545162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5546182999Smav return (need); 5547162922Sariff 5548162922Sariff w = hdac_widget_get(devinfo, nid); 5549162922Sariff if (w == NULL || w->enable == 0) 5550182999Smav return (need); 5551182999Smav 5552182999Smav /* Count number of active inputs. */ 5553182999Smav if (depth > 0) { 5554182999Smav for (j = 0; j < w->nconns; j++) { 5555182999Smav if (w->connsenable[j]) 5556182999Smav conns++; 5557162922Sariff } 5558162922Sariff } 5559182999Smav 5560182999Smav /* If this is not a first step - use input mixer. 5561182999Smav Pins have common input ctl so care must be taken. */ 5562182999Smav if (depth > 0 && ctlable && (conns == 1 || 5563182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5564182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5565182999Smav index, 1); 5566182999Smav if (ctl) { 5567182999Smav if (HDA_CTL_GIVE(ctl) & need) 5568182999Smav ctl->ossmask |= (1 << ossdev); 5569182999Smav else 5570182999Smav ctl->possmask |= (1 << ossdev); 5571182999Smav need &= ~HDA_CTL_GIVE(ctl); 5572182999Smav } 5573182999Smav } 5574182999Smav 5575182999Smav /* If widget has own ossdev - not traverse it. 5576182999Smav It will be traversed on it's own. */ 5577182999Smav if (w->ossdev >= 0 && depth > 0) 5578182999Smav return (need); 5579182999Smav 5580182999Smav /* We must not traverse pin */ 5581182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5582182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5583182999Smav depth > 0) 5584182999Smav return (need); 5585182999Smav 5586182999Smav /* record that this widget exports such signal, */ 5587182999Smav w->ossmask |= (1 << ossdev); 5588182999Smav 5589182999Smav /* If signals mixed, we can't assign controls farther. 5590182999Smav * Ignore this on depth zero. Caller must knows why. 5591182999Smav * Ignore this for static selectors if this input selected. 5592182999Smav */ 5593182999Smav if (conns > 1) 5594182999Smav ctlable = 0; 5595182999Smav 5596182999Smav if (ctlable) { 5597182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5598182999Smav if (ctl) { 5599182999Smav if (HDA_CTL_GIVE(ctl) & need) 5600182999Smav ctl->ossmask |= (1 << ossdev); 5601182999Smav else 5602182999Smav ctl->possmask |= (1 << ossdev); 5603182999Smav need &= ~HDA_CTL_GIVE(ctl); 5604182999Smav } 5605182999Smav } 5606182999Smav 5607182999Smav rneed = 0; 5608182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5609182999Smav wc = hdac_widget_get(devinfo, i); 5610182999Smav if (wc == NULL || wc->enable == 0) 5611162922Sariff continue; 5612182999Smav for (j = 0; j < wc->nconns; j++) { 5613182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5614182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5615182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5616182999Smav } 5617162922Sariff } 5618162922Sariff } 5619182999Smav rneed &= need; 5620182999Smav 5621182999Smav return (rneed); 5622162922Sariff} 5623162922Sariff 5624182999Smav/* 5625182999Smav * Find controls to control amplification for destination. 5626182999Smav */ 5627182999Smavstatic void 5628182999Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, 5629182999Smav int ossdev, int depth, int need) 5630162922Sariff{ 5631182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5632182999Smav struct hdac_widget *w, *wc; 5633182999Smav struct hdac_audio_ctl *ctl; 5634182999Smav int i, j, consumers; 5635182999Smav 5636162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5637182999Smav return; 5638162922Sariff 5639162922Sariff w = hdac_widget_get(devinfo, nid); 5640162922Sariff if (w == NULL || w->enable == 0) 5641182999Smav return; 5642182999Smav 5643182999Smav if (depth > 0) { 5644182999Smav /* If this node produce output for several consumers, 5645182999Smav we can't touch it. */ 5646182999Smav consumers = 0; 5647182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5648182999Smav wc = hdac_widget_get(devinfo, i); 5649182999Smav if (wc == NULL || wc->enable == 0) 5650182999Smav continue; 5651182999Smav for (j = 0; j < wc->nconns; j++) { 5652182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5653182999Smav consumers++; 5654182999Smav } 5655182999Smav } 5656182999Smav /* The only exception is if real HP redirection is configured 5657182999Smav and this is a duplication point. 5658182999Smav XXX: Actually exception is not completely correct. 5659182999Smav XXX: Duplication point check is not perfect. */ 5660182999Smav if ((consumers == 2 && (w->bindas < 0 || 5661182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5662182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5663182999Smav consumers > 2) 5664182999Smav return; 5665182999Smav 5666182999Smav /* Else use it's output mixer. */ 5667182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5668182999Smav HDA_CTL_OUT, -1, 1); 5669182999Smav if (ctl) { 5670182999Smav if (HDA_CTL_GIVE(ctl) & need) 5671182999Smav ctl->ossmask |= (1 << ossdev); 5672182999Smav else 5673182999Smav ctl->possmask |= (1 << ossdev); 5674182999Smav need &= ~HDA_CTL_GIVE(ctl); 5675182999Smav } 5676182999Smav } 5677182999Smav 5678182999Smav /* We must not traverse pin */ 5679182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5680182999Smav depth > 0) 5681182999Smav return; 5682182999Smav 5683162922Sariff for (i = 0; i < w->nconns; i++) { 5684182999Smav int tneed = need; 5685182999Smav if (w->connsenable[i] == 0) 5686162922Sariff continue; 5687182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5688182999Smav HDA_CTL_IN, i, 1); 5689182999Smav if (ctl) { 5690182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 5691182999Smav ctl->ossmask |= (1 << ossdev); 5692182999Smav else 5693182999Smav ctl->possmask |= (1 << ossdev); 5694182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 5695162922Sariff } 5696182999Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev, 5697182999Smav depth + 1, tneed); 5698162922Sariff } 5699162922Sariff} 5700162922Sariff 5701182999Smav/* 5702182999Smav * Assign OSS names to sound sources 5703182999Smav */ 5704182999Smavstatic void 5705182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 5706162922Sariff{ 5707182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5708182999Smav struct hdac_widget *w; 5709182999Smav int i, j; 5710182999Smav int type = -1, use, used = 0; 5711182999Smav static const int types[7][13] = { 5712182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5713182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 5714182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 5715182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 5716182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 5717182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 5718182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 5719182999Smav -1 }, /* digital */ 5720182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5721182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 5722182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 5723182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 5724182999Smav -1 } /* others */ 5725182999Smav }; 5726162922Sariff 5727182999Smav /* Surely known names */ 5728162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5729162922Sariff w = hdac_widget_get(devinfo, i); 5730162922Sariff if (w == NULL || w->enable == 0) 5731162922Sariff continue; 5732182999Smav if (w->bindas == -1) 5733182999Smav continue; 5734182999Smav use = -1; 5735182999Smav switch (w->type) { 5736182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5737182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5738182999Smav break; 5739182999Smav type = -1; 5740182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5741182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 5742182999Smav type = 0; 5743182999Smav break; 5744182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5745182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 5746182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 5747182999Smav break; 5748182999Smav type = 1; 5749182999Smav break; 5750182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 5751182999Smav type = 3; 5752182999Smav break; 5753182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5754182999Smav type = 4; 5755182999Smav break; 5756182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 5757182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 5758182999Smav type = 5; 5759182999Smav break; 5760182999Smav } 5761182999Smav if (type == -1) 5762182999Smav break; 5763182999Smav j = 0; 5764182999Smav while (types[type][j] >= 0 && 5765182999Smav (used & (1 << types[type][j])) != 0) { 5766182999Smav j++; 5767182999Smav } 5768182999Smav if (types[type][j] >= 0) 5769182999Smav use = types[type][j]; 5770182999Smav break; 5771182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5772182999Smav use = SOUND_MIXER_PCM; 5773182999Smav break; 5774182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 5775182999Smav use = SOUND_MIXER_SPEAKER; 5776182999Smav break; 5777182999Smav default: 5778182999Smav break; 5779182999Smav } 5780182999Smav if (use >= 0) { 5781182999Smav w->ossdev = use; 5782182999Smav used |= (1 << use); 5783182999Smav } 5784182999Smav } 5785182999Smav /* Semi-known names */ 5786182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5787182999Smav w = hdac_widget_get(devinfo, i); 5788182999Smav if (w == NULL || w->enable == 0) 5789182999Smav continue; 5790182999Smav if (w->ossdev >= 0) 5791182999Smav continue; 5792182999Smav if (w->bindas == -1) 5793182999Smav continue; 5794162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5795162922Sariff continue; 5796182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5797162922Sariff continue; 5798182999Smav type = -1; 5799182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5800182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 5801182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5802182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 5803182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 5804182999Smav type = 0; 5805182999Smav break; 5806182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5807182999Smav type = 2; 5808182999Smav break; 5809182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 5810182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 5811182999Smav type = 5; 5812182999Smav break; 5813182999Smav } 5814182999Smav if (type == -1) 5815182999Smav break; 5816182999Smav j = 0; 5817182999Smav while (types[type][j] >= 0 && 5818182999Smav (used & (1 << types[type][j])) != 0) { 5819182999Smav j++; 5820182999Smav } 5821182999Smav if (types[type][j] >= 0) { 5822182999Smav w->ossdev = types[type][j]; 5823182999Smav used |= (1 << types[type][j]); 5824182999Smav } 5825182999Smav } 5826182999Smav /* Others */ 5827182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5828182999Smav w = hdac_widget_get(devinfo, i); 5829182999Smav if (w == NULL || w->enable == 0) 5830162922Sariff continue; 5831182999Smav if (w->ossdev >= 0) 5832182999Smav continue; 5833182999Smav if (w->bindas == -1) 5834182999Smav continue; 5835182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5836182999Smav continue; 5837182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5838182999Smav continue; 5839182999Smav j = 0; 5840182999Smav while (types[6][j] >= 0 && 5841182999Smav (used & (1 << types[6][j])) != 0) { 5842182999Smav j++; 5843162922Sariff } 5844182999Smav if (types[6][j] >= 0) { 5845182999Smav w->ossdev = types[6][j]; 5846182999Smav used |= (1 << types[6][j]); 5847182999Smav } 5848162922Sariff } 5849162922Sariff} 5850162922Sariff 5851162922Sariffstatic void 5852162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5853162922Sariff{ 5854182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5855182999Smav int j, res; 5856162922Sariff 5857182999Smav /* Trace all associations in order of their numbers, */ 5858182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5859182999Smav if (as[j].enable == 0) 5860182999Smav continue; 5861163057Sariff HDA_BOOTVERBOSE( 5862162922Sariff device_printf(devinfo->codec->sc->dev, 5863182999Smav "Tracing association %d (%d)\n", j, as[j].index); 5864162922Sariff ); 5865182999Smav if (as[j].dir == HDA_CTL_OUT) { 5866182999Smavretry: 5867182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 5868182999Smav if (res == 0 && as[j].hpredir >= 0 && 5869182999Smav as[j].fakeredir == 0) { 5870182999Smav /* If codec can't do analog HP redirection 5871182999Smav try to make it using one more DAC. */ 5872182999Smav as[j].fakeredir = 1; 5873182999Smav goto retry; 5874182999Smav } 5875182999Smav } else { 5876182999Smav res = hdac_audio_trace_as_in(devinfo, j); 5877182999Smav } 5878182999Smav if (res) { 5879182999Smav HDA_BOOTVERBOSE( 5880182999Smav device_printf(devinfo->codec->sc->dev, 5881182999Smav "Association %d (%d) trace succeded\n", 5882182999Smav j, as[j].index); 5883182999Smav ); 5884182999Smav } else { 5885182999Smav HDA_BOOTVERBOSE( 5886182999Smav device_printf(devinfo->codec->sc->dev, 5887182999Smav "Association %d (%d) trace failed\n", 5888182999Smav j, as[j].index); 5889182999Smav ); 5890182999Smav as[j].enable = 0; 5891182999Smav } 5892162922Sariff } 5893162922Sariff 5894182999Smav /* Trace mixer and beeper pseudo associations. */ 5895182999Smav hdac_audio_trace_as_extra(devinfo); 5896182999Smav} 5897162922Sariff 5898182999Smavstatic void 5899182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 5900182999Smav{ 5901182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5902182999Smav struct hdac_audio_ctl *ctl; 5903182999Smav struct hdac_widget *w; 5904182999Smav int i; 5905162922Sariff 5906182999Smav /* Assign mixers to the tree. */ 5907162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5908162922Sariff w = hdac_widget_get(devinfo, i); 5909162922Sariff if (w == NULL || w->enable == 0) 5910162922Sariff continue; 5911182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 5912182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 5913182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5914182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 5915182999Smav if (w->ossdev < 0) 5916182999Smav continue; 5917182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 5918182999Smav w->ossdev, 1, 0, 1); 5919182999Smav } else if ((w->pflags & HDA_ADC_MONITOR) != 0) { 5920182999Smav if (w->ossdev < 0) 5921182999Smav continue; 5922182999Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 5923182999Smav w->ossdev, 1, 0, 1)) { 5924182999Smav /* If we are unable to control input monitor 5925182999Smav as source - try to control it as destination. */ 5926182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5927182999Smav w->ossdev, 0, 1); 5928162922Sariff } 5929182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 5930182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5931182999Smav SOUND_MIXER_RECLEV, 0, 1); 5932182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5933182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 5934182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5935182999Smav SOUND_MIXER_VOLUME, 0, 1); 5936162922Sariff } 5937162922Sariff } 5938182999Smav /* Treat unrequired as possible. */ 5939182999Smav i = 0; 5940182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5941182999Smav if (ctl->ossmask == 0) 5942182999Smav ctl->ossmask = ctl->possmask; 5943182999Smav } 5944182999Smav} 5945162922Sariff 5946182999Smavstatic void 5947182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 5948182999Smav{ 5949182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5950182999Smav struct hdac_widget *w; 5951182999Smav uint32_t pincap; 5952182999Smav int i; 5953182999Smav 5954182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 5955182999Smav w = &devinfo->widget[i]; 5956182999Smav if (w == NULL) 5957162922Sariff continue; 5958182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5959162922Sariff continue; 5960182999Smav 5961182999Smav pincap = w->wclass.pin.cap; 5962182999Smav 5963182999Smav /* Disable everything. */ 5964182999Smav w->wclass.pin.ctrl &= ~( 5965182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 5966182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 5967182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 5968182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 5969182999Smav 5970182999Smav if (w->enable == 0 || 5971182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 5972182999Smav /* Pin is unused so left it disabled. */ 5973182999Smav continue; 5974182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 5975182999Smav /* Input pin, configure for input. */ 5976182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 5977182999Smav w->wclass.pin.ctrl |= 5978182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 5979182999Smav 5980182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 5981182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5982182999Smav w->wclass.pin.ctrl |= 5983182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5984182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5985182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 5986182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5987182999Smav w->wclass.pin.ctrl |= 5988182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5989182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5990182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 5991182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5992182999Smav w->wclass.pin.ctrl |= 5993182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5994182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5995182999Smav } else { 5996182999Smav /* Output pin, configure for output. */ 5997182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 5998182999Smav w->wclass.pin.ctrl |= 5999182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6000182999Smav 6001182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6002182999Smav (w->wclass.pin.config & 6003182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6004182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6005182999Smav w->wclass.pin.ctrl |= 6006182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6007182999Smav 6008182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6009182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6010182999Smav w->wclass.pin.ctrl |= 6011182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6012182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6013182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6014182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6015182999Smav w->wclass.pin.ctrl |= 6016182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6017182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6018182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6019182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6020182999Smav w->wclass.pin.ctrl |= 6021182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6022182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6023182999Smav } 6024162922Sariff } 6025162922Sariff} 6026162922Sariff 6027162922Sariffstatic void 6028182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6029162922Sariff{ 6030162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6031162922Sariff struct hdac_widget *w; 6032164750Sariff nid_t cad; 6033182999Smav uint32_t gdata, gmask, gdir; 6034182999Smav int commitgpio, numgpio; 6035164750Sariff int i; 6036162922Sariff 6037162922Sariff cad = devinfo->codec->cad; 6038162922Sariff 6039182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6040182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6041182999Smav 0x7e7, 0), cad); 6042169277Sariff 6043182999Smav gdata = 0; 6044182999Smav gmask = 0; 6045182999Smav gdir = 0; 6046182999Smav commitgpio = 0; 6047164828Sariff 6048182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6049182999Smav devinfo->function.audio.gpio); 6050166796Sariff 6051182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6052182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6053182999Smav else { 6054182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6055182999Smav if (!(devinfo->function.audio.quirks & 6056182999Smav (1 << i))) 6057182999Smav continue; 6058182999Smav if (commitgpio == 0) { 6059182999Smav commitgpio = 1; 6060182999Smav HDA_BOOTVERBOSE( 6061182999Smav gdata = hdac_command(sc, 6062182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6063182999Smav devinfo->nid), cad); 6064182999Smav gmask = hdac_command(sc, 6065182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6066182999Smav devinfo->nid), cad); 6067182999Smav gdir = hdac_command(sc, 6068182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6069182999Smav devinfo->nid), cad); 6070182999Smav device_printf(sc->dev, 6071182999Smav "GPIO init: data=0x%08x " 6072182999Smav "mask=0x%08x dir=0x%08x\n", 6073182999Smav gdata, gmask, gdir); 6074182999Smav gdata = 0; 6075182999Smav gmask = 0; 6076182999Smav gdir = 0; 6077182999Smav ); 6078165039Sariff } 6079182999Smav gdata |= 1 << i; 6080182999Smav gmask |= 1 << i; 6081182999Smav gdir |= 1 << i; 6082165039Sariff } 6083182999Smav } 6084165039Sariff 6085182999Smav if (commitgpio != 0) { 6086182999Smav HDA_BOOTVERBOSE( 6087182999Smav device_printf(sc->dev, 6088182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6089182999Smav "dir=0x%08x\n", 6090182999Smav gdata, gmask, gdir); 6091182999Smav ); 6092182999Smav hdac_command(sc, 6093182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6094182999Smav gmask), cad); 6095182999Smav hdac_command(sc, 6096182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6097182999Smav gdir), cad); 6098182999Smav hdac_command(sc, 6099182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6100182999Smav gdata), cad); 6101162922Sariff } 6102162922Sariff 6103162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 6104162922Sariff w = &devinfo->widget[i]; 6105182999Smav if (w == NULL) 6106162922Sariff continue; 6107182999Smav if (w->selconn == -1) 6108182999Smav w->selconn = 0; 6109182999Smav if (w->nconns > 0) 6110182999Smav hdac_widget_connection_select(w, w->selconn); 6111182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6112162922Sariff hdac_command(sc, 6113162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6114162922Sariff w->wclass.pin.ctrl), cad); 6115162922Sariff } 6116182999Smav if (w->param.eapdbtl != HDAC_INVALID) { 6117163432Sariff uint32_t val; 6118163432Sariff 6119163432Sariff val = w->param.eapdbtl; 6120163276Sariff if (devinfo->function.audio.quirks & 6121163432Sariff HDA_QUIRK_EAPDINV) 6122163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6123162922Sariff hdac_command(sc, 6124162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6125163432Sariff val), cad); 6126162922Sariff 6127163276Sariff } 6128162922Sariff } 6129162922Sariff} 6130162922Sariff 6131162922Sariffstatic void 6132162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6133162922Sariff{ 6134162922Sariff struct hdac_audio_ctl *ctl; 6135182999Smav int i, z; 6136162922Sariff 6137162922Sariff i = 0; 6138162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6139182999Smav if (ctl->enable == 0) { 6140182999Smav /* Mute disabled controls. */ 6141182999Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6142162922Sariff continue; 6143162922Sariff } 6144182999Smav /* Init controls to 0dB amplification. */ 6145182999Smav z = ctl->offset; 6146182999Smav if (z > ctl->step) 6147182999Smav z = ctl->step; 6148182999Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6149162922Sariff } 6150162922Sariff} 6151162922Sariff 6152182999Smavstatic void 6153182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6154182999Smav{ 6155182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6156182999Smav nid_t cad = devinfo->codec->cad; 6157182999Smav int i; 6158182999Smav 6159182999Smav hdac_command(sc, 6160182999Smav HDA_CMD_SET_POWER_STATE(cad, 6161182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6162182999Smav cad); 6163182999Smav DELAY(100); 6164182999Smav 6165182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6166182999Smav hdac_command(sc, 6167182999Smav HDA_CMD_SET_POWER_STATE(cad, 6168182999Smav i, HDA_CMD_POWER_STATE_D0), 6169182999Smav cad); 6170182999Smav } 6171182999Smav DELAY(1000); 6172182999Smav} 6173182999Smav 6174162922Sariffstatic int 6175182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6176162922Sariff{ 6177182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6178182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6179162922Sariff struct hdac_widget *w; 6180182999Smav uint32_t cap, fmtcap, pcmcap; 6181182999Smav int i, j, ret, max; 6182162922Sariff 6183162922Sariff ch->caps = hdac_caps; 6184162922Sariff ch->caps.fmtlist = ch->fmtlist; 6185162922Sariff ch->bit16 = 1; 6186162922Sariff ch->bit32 = 0; 6187162922Sariff ch->pcmrates[0] = 48000; 6188162922Sariff ch->pcmrates[1] = 0; 6189162922Sariff 6190162922Sariff ret = 0; 6191162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6192162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6193162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 6194162922Sariff 6195182999Smav for (i = 0; i < 16 && ret < max; i++) { 6196182999Smav /* Check as is correct */ 6197182999Smav if (ch->as < 0) 6198182999Smav break; 6199182999Smav /* Cound only present DACs */ 6200182999Smav if (as[ch->as].dacs[i] <= 0) 6201162922Sariff continue; 6202182999Smav /* Ignore duplicates */ 6203182999Smav for (j = 0; j < ret; j++) { 6204182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6205182999Smav break; 6206182999Smav } 6207182999Smav if (j < ret) 6208162922Sariff continue; 6209182999Smav 6210182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6211182999Smav if (w == NULL || w->enable == 0) 6212182999Smav continue; 6213182999Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6214182999Smav continue; 6215162922Sariff cap = w->param.supp_stream_formats; 6216182999Smav /*if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 6217162922Sariff }*/ 6218182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6219182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6220162922Sariff continue; 6221182999Smav /* Many codec does not declare AC3 support on SPDIF. 6222182999Smav I don't beleave that they doesn't support it! */ 6223182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6224182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6225164614Sariff if (ret == 0) { 6226182999Smav fmtcap = cap; 6227164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6228164614Sariff } else { 6229182999Smav fmtcap &= cap; 6230164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6231164614Sariff } 6232182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6233162922Sariff } 6234162922Sariff ch->io[ret] = -1; 6235162922Sariff 6236162922Sariff ch->supp_stream_formats = fmtcap; 6237162922Sariff ch->supp_pcm_size_rate = pcmcap; 6238162922Sariff 6239162922Sariff /* 6240162922Sariff * 8bit = 0 6241162922Sariff * 16bit = 1 6242162922Sariff * 20bit = 2 6243162922Sariff * 24bit = 3 6244162922Sariff * 32bit = 4 6245162922Sariff */ 6246162922Sariff if (ret > 0) { 6247162922Sariff i = 0; 6248182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6249182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6250182999Smav ch->bit16 = 1; 6251182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6252182999Smav ch->bit16 = 0; 6253182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6254182999Smav ch->bit32 = 4; 6255182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6256182999Smav ch->bit32 = 3; 6257182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6258182999Smav ch->bit32 = 2; 6259182999Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 6260182999Smav ch->fmtlist[i++] = AFMT_S16_LE; 6261182999Smav ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 6262182999Smav if (ch->bit32 > 0) { 6263182999Smav if (!(devinfo->function.audio.quirks & 6264182999Smav HDA_QUIRK_FORCESTEREO)) 6265182999Smav ch->fmtlist[i++] = AFMT_S32_LE; 6266182999Smav ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 6267182999Smav } 6268162922Sariff } 6269182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6270182999Smav ch->fmtlist[i++] = AFMT_AC3; 6271182999Smav } 6272162922Sariff ch->fmtlist[i] = 0; 6273162922Sariff i = 0; 6274182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6275162922Sariff ch->pcmrates[i++] = 8000; 6276182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6277162922Sariff ch->pcmrates[i++] = 11025; 6278182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6279162922Sariff ch->pcmrates[i++] = 16000; 6280182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6281162922Sariff ch->pcmrates[i++] = 22050; 6282182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6283162922Sariff ch->pcmrates[i++] = 32000; 6284182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6285162922Sariff ch->pcmrates[i++] = 44100; 6286182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6287162922Sariff ch->pcmrates[i++] = 48000; 6288182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6289162922Sariff ch->pcmrates[i++] = 88200; 6290182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6291162922Sariff ch->pcmrates[i++] = 96000; 6292182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6293162922Sariff ch->pcmrates[i++] = 176400; 6294182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6295162922Sariff ch->pcmrates[i++] = 192000; 6296182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6297162922Sariff ch->pcmrates[i] = 0; 6298162922Sariff if (i > 0) { 6299162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6300162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6301162922Sariff } 6302162922Sariff } 6303162922Sariff 6304162922Sariff return (ret); 6305162922Sariff} 6306162922Sariff 6307162922Sariffstatic void 6308185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6309185225Smav{ 6310185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6311185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6312185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6313185225Smav 6314185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6315185225Smav if (as[i].enable == 0) 6316185225Smav continue; 6317185225Smav if (as[i].dir == HDA_CTL_IN) { 6318185225Smav if (as[i].digital) 6319185225Smav drdev++; 6320185225Smav else 6321185225Smav ardev++; 6322185225Smav } else { 6323185225Smav if (as[i].digital) 6324185225Smav dpdev++; 6325185225Smav else 6326185225Smav apdev++; 6327185225Smav } 6328185225Smav } 6329185225Smav devinfo->function.audio.num_devs = 6330185225Smav max(ardev, apdev) + max(drdev, dpdev); 6331185225Smav devinfo->function.audio.devs = 6332185225Smav (struct hdac_pcm_devinfo *)malloc( 6333185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6334185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6335185225Smav if (devinfo->function.audio.devs == NULL) { 6336185225Smav device_printf(sc->dev, 6337185225Smav "Unable to allocate memory for devices\n"); 6338185225Smav return; 6339185225Smav } 6340185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6341185225Smav devinfo->function.audio.devs[i].index = i; 6342185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6343185225Smav devinfo->function.audio.devs[i].play = -1; 6344185225Smav devinfo->function.audio.devs[i].rec = -1; 6345185225Smav devinfo->function.audio.devs[i].digital = 2; 6346185225Smav } 6347185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6348185225Smav if (as[i].enable == 0) 6349185225Smav continue; 6350185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6351185225Smav if (devinfo->function.audio.devs[j].digital != 2 && 6352185225Smav devinfo->function.audio.devs[j].digital != 6353185225Smav as[i].digital) 6354185225Smav continue; 6355185225Smav if (as[i].dir == HDA_CTL_IN) { 6356185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6357185225Smav continue; 6358185225Smav devinfo->function.audio.devs[j].rec 6359185225Smav = as[i].chan; 6360185225Smav } else { 6361185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6362185225Smav continue; 6363185225Smav devinfo->function.audio.devs[j].play 6364185225Smav = as[i].chan; 6365185225Smav } 6366185225Smav sc->chans[as[i].chan].pdevinfo = 6367185225Smav &devinfo->function.audio.devs[j]; 6368185225Smav devinfo->function.audio.devs[j].digital = 6369185225Smav as[i].digital; 6370185225Smav break; 6371185225Smav } 6372185225Smav } 6373185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6374185225Smav struct hdac_pcm_devinfo *pdevinfo = 6375185225Smav &devinfo->function.audio.devs[i]; 6376185225Smav pdevinfo->dev = 6377185225Smav device_add_child(sc->dev, "pcm", -1); 6378185225Smav device_set_ivars(pdevinfo->dev, 6379185225Smav (void *)pdevinfo); 6380185225Smav } 6381185225Smav} 6382185225Smav 6383185225Smavstatic void 6384182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6385162922Sariff{ 6386182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6387162922Sariff struct hdac_audio_ctl *ctl; 6388162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6389182999Smav char buf[64]; 6390182999Smav int i, j, printed; 6391162922Sariff 6392162922Sariff if (flag == 0) { 6393182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6394162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6395182999Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN | 6396182999Smav SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6397162922Sariff } 6398162922Sariff 6399182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6400182999Smav if ((flag & (1 << j)) == 0) 6401162922Sariff continue; 6402182999Smav i = 0; 6403182999Smav printed = 0; 6404182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6405182999Smav if (ctl->enable == 0 || 6406182999Smav ctl->widget->enable == 0) 6407182999Smav continue; 6408182999Smav if (!((pdevinfo->play >= 0 && 6409182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6410182999Smav (pdevinfo->rec >= 0 && 6411182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6412182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6413182999Smav continue; 6414182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6415182999Smav continue; 6416182999Smav 6417182999Smav if (printed == 0) { 6418182999Smav device_printf(pdevinfo->dev, "\n"); 6419182999Smav if (banner != NULL) { 6420182999Smav device_printf(pdevinfo->dev, "%s", banner); 6421182999Smav } else { 6422182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6423182999Smav } 6424182999Smav printf(" (OSS: %s)\n", 6425182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6426182999Smav buf, sizeof(buf))); 6427182999Smav device_printf(pdevinfo->dev, " |\n"); 6428182999Smav printed = 1; 6429162922Sariff } 6430182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6431182999Smav ctl->widget->nid, 6432182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6433182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6434182999Smav printf(" %2d): ", ctl->index); 6435182999Smav else 6436182999Smav printf("): "); 6437182999Smav if (ctl->step > 0) { 6438182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6439182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6440182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6441182999Smav ctl->step + 1, 6442182999Smav ctl->mute?" + mute":""); 6443182999Smav } else 6444182999Smav printf("%s\n", ctl->mute?"mute":""); 6445162922Sariff } 6446162922Sariff } 6447162922Sariff} 6448162922Sariff 6449162922Sariffstatic void 6450182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6451162922Sariff{ 6452162922Sariff uint32_t cap; 6453162922Sariff 6454162922Sariff cap = fcap; 6455162922Sariff if (cap != 0) { 6456182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6457183097Smav device_printf(dev, " "); 6458162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6459162922Sariff printf(" AC3"); 6460162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6461162922Sariff printf(" FLOAT32"); 6462162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6463162922Sariff printf(" PCM"); 6464162922Sariff printf("\n"); 6465162922Sariff } 6466162922Sariff cap = pcmcap; 6467162922Sariff if (cap != 0) { 6468182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6469183097Smav device_printf(dev, " "); 6470162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6471162922Sariff printf(" 8"); 6472162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6473162922Sariff printf(" 16"); 6474162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6475162922Sariff printf(" 20"); 6476162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6477162922Sariff printf(" 24"); 6478162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6479162922Sariff printf(" 32"); 6480183097Smav printf(" bits,"); 6481162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6482162922Sariff printf(" 8"); 6483162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6484162922Sariff printf(" 11"); 6485162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6486162922Sariff printf(" 16"); 6487162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6488162922Sariff printf(" 22"); 6489162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6490162922Sariff printf(" 32"); 6491162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6492162922Sariff printf(" 44"); 6493162922Sariff printf(" 48"); 6494162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6495162922Sariff printf(" 88"); 6496162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6497162922Sariff printf(" 96"); 6498162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6499162922Sariff printf(" 176"); 6500162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6501162922Sariff printf(" 192"); 6502183097Smav printf(" KHz\n"); 6503162922Sariff } 6504162922Sariff} 6505162922Sariff 6506162922Sariffstatic void 6507162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6508162922Sariff{ 6509183097Smav uint32_t pincap; 6510162922Sariff 6511162922Sariff pincap = w->wclass.pin.cap; 6512162922Sariff 6513162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6514162922Sariff device_printf(sc->dev, " "); 6515162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6516162922Sariff printf(" ISC"); 6517162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6518162922Sariff printf(" TRQD"); 6519162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6520162922Sariff printf(" PDC"); 6521162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6522162922Sariff printf(" HP"); 6523162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6524162922Sariff printf(" OUT"); 6525162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6526162922Sariff printf(" IN"); 6527162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6528162922Sariff printf(" BAL"); 6529165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6530165069Sariff printf(" VREF["); 6531165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6532165069Sariff printf(" 50"); 6533165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6534165069Sariff printf(" 80"); 6535165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6536165069Sariff printf(" 100"); 6537165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6538165069Sariff printf(" GROUND"); 6539165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6540165069Sariff printf(" HIZ"); 6541165069Sariff printf(" ]"); 6542165069Sariff } 6543162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6544162922Sariff printf(" EAPD"); 6545162922Sariff printf("\n"); 6546162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6547162922Sariff w->wclass.pin.config); 6548162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6549162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6550162922Sariff printf(" HP"); 6551162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6552162922Sariff printf(" IN"); 6553162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6554162922Sariff printf(" OUT"); 6555182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6556182999Smav printf(" VREFs"); 6557162922Sariff printf("\n"); 6558162922Sariff} 6559162922Sariff 6560162922Sariffstatic void 6561182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6562182999Smav{ 6563182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6564182999Smav 6565183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6566182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6567182999Smav w->nid, conf, 6568182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6569182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6570182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6571182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6572182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6573182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6574182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6575182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6576182999Smav (w->enable == 0)?" [DISABLED]":""); 6577182999Smav} 6578182999Smav 6579182999Smavstatic void 6580182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6581182999Smav{ 6582182999Smav struct hdac_widget *w; 6583182999Smav int i; 6584182999Smav 6585182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6586182999Smav w = hdac_widget_get(devinfo, i); 6587182999Smav if (w == NULL) 6588182999Smav continue; 6589182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6590182999Smav continue; 6591182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6592182999Smav } 6593182999Smav} 6594182999Smav 6595182999Smavstatic void 6596162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6597162922Sariff{ 6598163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6599162922Sariff device_printf(sc->dev, " " 6600162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6601162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6602162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6603162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6604162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6605162922Sariff} 6606162922Sariff 6607162922Sariffstatic void 6608162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6609162922Sariff{ 6610162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6611182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6612162922Sariff struct hdac_widget *w, *cw; 6613182999Smav char buf[64]; 6614162922Sariff int i, j; 6615162922Sariff 6616162922Sariff device_printf(sc->dev, "\n"); 6617162922Sariff device_printf(sc->dev, "Default Parameter\n"); 6618162922Sariff device_printf(sc->dev, "-----------------\n"); 6619182999Smav hdac_dump_audio_formats(sc->dev, 6620162922Sariff devinfo->function.audio.supp_stream_formats, 6621162922Sariff devinfo->function.audio.supp_pcm_size_rate); 6622162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 6623162922Sariff devinfo->function.audio.inamp_cap); 6624162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 6625162922Sariff devinfo->function.audio.outamp_cap); 6626162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6627162922Sariff w = hdac_widget_get(devinfo, i); 6628162922Sariff if (w == NULL) { 6629162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 6630162922Sariff continue; 6631162922Sariff } 6632162922Sariff device_printf(sc->dev, "\n"); 6633183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 6634162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 6635183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 6636183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 6637162922Sariff w->param.widget_cap); 6638183097Smav if (w->param.widget_cap & 0x0ee1) { 6639183097Smav device_printf(sc->dev, " "); 6640183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 6641183097Smav printf(" LRSWAP"); 6642183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 6643183097Smav printf(" PWR"); 6644183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6645183097Smav printf(" DIGITAL"); 6646183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 6647183097Smav printf(" UNSOL"); 6648183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 6649183097Smav printf(" PROC"); 6650183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 6651183097Smav printf(" STRIPE"); 6652183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6653183097Smav printf(" STEREO"); 6654183097Smav printf("\n"); 6655183097Smav } 6656183097Smav if (w->bindas != -1) { 6657183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 6658183097Smav w->bindas, w->bindseqmask); 6659183097Smav } 6660183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 6661183097Smav device_printf(sc->dev, " OSS: %s", 6662183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 6663183097Smav if (w->ossdev >= 0) 6664183097Smav printf(" (%s)", ossname[w->ossdev]); 6665183097Smav printf("\n"); 6666183097Smav } 6667162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6668162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6669182999Smav hdac_dump_audio_formats(sc->dev, 6670162922Sariff w->param.supp_stream_formats, 6671162922Sariff w->param.supp_pcm_size_rate); 6672162922Sariff } else if (w->type == 6673162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6674162922Sariff hdac_dump_pin(sc, w); 6675162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 6676162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 6677162922Sariff w->param.eapdbtl); 6678163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 6679163057Sariff w->param.outamp_cap != 0) 6680162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 6681163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 6682163057Sariff w->param.inamp_cap != 0) 6683162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 6684183097Smav if (w->nconns > 0) { 6685183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 6686182999Smav device_printf(sc->dev, " |\n"); 6687183097Smav } 6688162922Sariff for (j = 0; j < w->nconns; j++) { 6689162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 6690182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 6691182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 6692162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 6693162922Sariff if (cw == NULL) 6694162922Sariff printf(" [UNKNOWN]"); 6695162922Sariff else if (cw->enable == 0) 6696162922Sariff printf(" [DISABLED]"); 6697162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 6698162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 6699162922Sariff printf(" (selected)"); 6700162922Sariff printf("\n"); 6701162922Sariff } 6702162922Sariff } 6703162922Sariff 6704162922Sariff} 6705162922Sariff 6706182999Smavstatic void 6707182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 6708163057Sariff{ 6709182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6710163057Sariff struct hdac_widget *w, *cw; 6711182999Smav char buf[64]; 6712182999Smav int i, printed = 0; 6713163057Sariff 6714163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 6715182999Smav return; 6716163057Sariff 6717163057Sariff w = hdac_widget_get(devinfo, nid); 6718182999Smav if (w == NULL || w->enable == 0) 6719182999Smav return; 6720163057Sariff 6721182999Smav if (depth == 0) 6722182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 6723182999Smav else 6724182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 6725182999Smav printf("nid=%d [%s]", w->nid, w->name); 6726163057Sariff 6727182999Smav if (depth > 0) { 6728182999Smav if (w->ossmask == 0) { 6729182999Smav printf("\n"); 6730182999Smav return; 6731163057Sariff } 6732182999Smav printf(" [src: %s]", 6733182999Smav hdac_audio_ctl_ossmixer_mask2allname( 6734182999Smav w->ossmask, buf, sizeof(buf))); 6735182999Smav if (w->ossdev >= 0) { 6736182999Smav printf("\n"); 6737182999Smav return; 6738182999Smav } 6739163057Sariff } 6740182999Smav printf("\n"); 6741182999Smav 6742182999Smav for (i = 0; i < w->nconns; i++) { 6743182999Smav if (w->connsenable[i] == 0) 6744182999Smav continue; 6745182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 6746182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 6747182999Smav continue; 6748182999Smav if (printed == 0) { 6749182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 6750182999Smav printed = 1; 6751182999Smav } 6752182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 6753182999Smav } 6754163057Sariff 6755163057Sariff} 6756163057Sariff 6757162922Sariffstatic void 6758182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 6759162922Sariff{ 6760182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6761182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6762163057Sariff struct hdac_widget *w; 6763163057Sariff int i, printed = 0; 6764163057Sariff 6765182999Smav if (pdevinfo->play < 0) 6766182999Smav return; 6767182999Smav 6768163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6769163057Sariff w = hdac_widget_get(devinfo, i); 6770163057Sariff if (w == NULL || w->enable == 0) 6771163057Sariff continue; 6772182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6773163057Sariff continue; 6774182999Smav if (w->bindas != sc->chans[pdevinfo->play].as) 6775182999Smav continue; 6776163057Sariff if (printed == 0) { 6777163057Sariff printed = 1; 6778182999Smav device_printf(pdevinfo->dev, "\n"); 6779182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6780163057Sariff } 6781182999Smav device_printf(pdevinfo->dev, "\n"); 6782182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6783163057Sariff } 6784162922Sariff} 6785162922Sariff 6786162922Sariffstatic void 6787182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 6788162922Sariff{ 6789182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6790162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6791182999Smav struct hdac_widget *w; 6792182999Smav int i; 6793162922Sariff int printed = 0; 6794162922Sariff 6795182999Smav if (pdevinfo->rec < 0) 6796182999Smav return; 6797182999Smav 6798162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6799162922Sariff w = hdac_widget_get(devinfo, i); 6800162922Sariff if (w == NULL || w->enable == 0) 6801162922Sariff continue; 6802182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 6803162922Sariff continue; 6804182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 6805182999Smav continue; 6806162922Sariff if (printed == 0) { 6807162922Sariff printed = 1; 6808182999Smav device_printf(pdevinfo->dev, "\n"); 6809182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6810162922Sariff } 6811182999Smav device_printf(pdevinfo->dev, "\n"); 6812182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6813182999Smav } 6814182999Smav} 6815182999Smav 6816182999Smavstatic void 6817182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 6818182999Smav{ 6819182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6820182999Smav struct hdac_widget *w; 6821182999Smav int i; 6822182999Smav int printed = 0; 6823182999Smav 6824182999Smav if (pdevinfo->index != 0) 6825182999Smav return; 6826182999Smav 6827182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6828182999Smav w = hdac_widget_get(devinfo, i); 6829182999Smav if (w == NULL || w->enable == 0) 6830182999Smav continue; 6831182999Smav if ((w->pflags & HDA_ADC_MONITOR) == 0) 6832182999Smav continue; 6833182999Smav if (printed == 0) { 6834182999Smav printed = 1; 6835182999Smav device_printf(pdevinfo->dev, "\n"); 6836182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 6837162922Sariff } 6838182999Smav device_printf(pdevinfo->dev, "\n"); 6839182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6840162922Sariff } 6841162922Sariff} 6842162922Sariff 6843162922Sariffstatic void 6844182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 6845162922Sariff{ 6846182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 6847162922Sariff nid_t *nids; 6848182999Smav int i; 6849162922Sariff 6850182999Smav if (pdevinfo->play >= 0) { 6851182999Smav i = pdevinfo->play; 6852182999Smav device_printf(pdevinfo->dev, "\n"); 6853182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6854182999Smav device_printf(pdevinfo->dev, "\n"); 6855182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 6856182999Smav sc->chans[i].supp_pcm_size_rate); 6857182999Smav device_printf(pdevinfo->dev, " DAC:"); 6858182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 6859162922Sariff printf(" %d", *nids); 6860162922Sariff printf("\n"); 6861162922Sariff } 6862182999Smav if (pdevinfo->rec >= 0) { 6863182999Smav i = pdevinfo->rec; 6864182999Smav device_printf(pdevinfo->dev, "\n"); 6865182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6866182999Smav device_printf(pdevinfo->dev, "\n"); 6867182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 6868182999Smav sc->chans[i].supp_pcm_size_rate); 6869182999Smav device_printf(pdevinfo->dev, " ADC:"); 6870182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 6871162922Sariff printf(" %d", *nids); 6872162922Sariff printf("\n"); 6873162922Sariff } 6874162922Sariff} 6875162922Sariff 6876162922Sariffstatic void 6877163057Sariffhdac_release_resources(struct hdac_softc *sc) 6878163057Sariff{ 6879182999Smav int i, j; 6880163057Sariff 6881163057Sariff if (sc == NULL) 6882163057Sariff return; 6883163057Sariff 6884163057Sariff hdac_lock(sc); 6885169277Sariff sc->polling = 0; 6886169277Sariff sc->poll_ival = 0; 6887170721Sariff callout_stop(&sc->poll_hda); 6888169277Sariff callout_stop(&sc->poll_hdac); 6889169277Sariff callout_stop(&sc->poll_jack); 6890182999Smav hdac_reset(sc, 0); 6891163057Sariff hdac_unlock(sc); 6892171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 6893170721Sariff callout_drain(&sc->poll_hda); 6894169277Sariff callout_drain(&sc->poll_hdac); 6895169277Sariff callout_drain(&sc->poll_jack); 6896163057Sariff 6897169277Sariff hdac_irq_free(sc); 6898169277Sariff 6899182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 6900182999Smav if (sc->codecs[i] == NULL) 6901163057Sariff continue; 6902182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 6903182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 6904182999Smav if (sc->codecs[i]->fgs[j].node_type == 6905182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 6906182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 6907182999Smav M_HDAC); 6908182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 6909182999Smav M_HDAC); 6910182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 6911182999Smav M_HDAC); 6912182999Smav } 6913182999Smav } 6914182999Smav free(sc->codecs[i]->fgs, M_HDAC); 6915182999Smav free(sc->codecs[i], M_HDAC); 6916163057Sariff sc->codecs[i] = NULL; 6917163057Sariff } 6918163057Sariff 6919169277Sariff hdac_dma_free(sc, &sc->pos_dma); 6920169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 6921169277Sariff hdac_dma_free(sc, &sc->corb_dma); 6922182999Smav for (i = 0; i < sc->num_chans; i++) { 6923182999Smav if (sc->chans[i].blkcnt > 0) 6924182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 6925182999Smav } 6926182999Smav free(sc->chans, M_HDAC); 6927167702Sariff if (sc->chan_dmat != NULL) { 6928167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 6929167702Sariff sc->chan_dmat = NULL; 6930167702Sariff } 6931163057Sariff hdac_mem_free(sc); 6932169277Sariff snd_mtxfree(sc->lock); 6933163057Sariff} 6934163057Sariff 6935163057Sariff/* This function surely going to make its way into upper level someday. */ 6936163057Sariffstatic void 6937163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 6938163057Sariff{ 6939163057Sariff const char *res = NULL; 6940163057Sariff int i = 0, j, k, len, inv; 6941163057Sariff 6942163057Sariff if (on != NULL) 6943163057Sariff *on = 0; 6944163057Sariff if (off != NULL) 6945163057Sariff *off = 0; 6946163057Sariff if (sc == NULL) 6947163057Sariff return; 6948163057Sariff if (resource_string_value(device_get_name(sc->dev), 6949163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 6950163057Sariff return; 6951163057Sariff if (!(res != NULL && strlen(res) > 0)) 6952163057Sariff return; 6953163057Sariff HDA_BOOTVERBOSE( 6954182999Smav device_printf(sc->dev, "HDA Config:"); 6955163057Sariff ); 6956163057Sariff for (;;) { 6957163057Sariff while (res[i] != '\0' && 6958163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 6959163057Sariff i++; 6960163057Sariff if (res[i] == '\0') { 6961163057Sariff HDA_BOOTVERBOSE( 6962163057Sariff printf("\n"); 6963163057Sariff ); 6964163057Sariff return; 6965163057Sariff } 6966163057Sariff j = i; 6967163057Sariff while (res[j] != '\0' && 6968163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 6969163057Sariff j++; 6970163057Sariff len = j - i; 6971163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 6972163057Sariff inv = 2; 6973163057Sariff else 6974163057Sariff inv = 0; 6975163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 6976163057Sariff if (strncmp(res + i + inv, 6977163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 6978163057Sariff continue; 6979163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 6980163057Sariff break; 6981163057Sariff HDA_BOOTVERBOSE( 6982163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 6983163057Sariff hdac_quirks_tab[k].key); 6984163057Sariff ); 6985163057Sariff if (inv == 0 && on != NULL) 6986163057Sariff *on |= hdac_quirks_tab[k].value; 6987163057Sariff else if (inv != 0 && off != NULL) 6988163057Sariff *off |= hdac_quirks_tab[k].value; 6989163057Sariff break; 6990163057Sariff } 6991163057Sariff i = j; 6992163057Sariff } 6993163057Sariff} 6994163057Sariff 6995164614Sariff#ifdef SND_DYNSYSCTL 6996164614Sariffstatic int 6997164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 6998164614Sariff{ 6999164614Sariff struct hdac_softc *sc; 7000164614Sariff device_t dev; 7001164614Sariff uint32_t ctl; 7002164614Sariff int err, val; 7003164614Sariff 7004164614Sariff dev = oidp->oid_arg1; 7005182999Smav sc = device_get_softc(dev); 7006182999Smav if (sc == NULL) 7007164614Sariff return (EINVAL); 7008164614Sariff hdac_lock(sc); 7009164614Sariff val = sc->polling; 7010164614Sariff hdac_unlock(sc); 7011170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7012164614Sariff 7013169277Sariff if (err != 0 || req->newptr == NULL) 7014164614Sariff return (err); 7015164614Sariff if (val < 0 || val > 1) 7016164614Sariff return (EINVAL); 7017164614Sariff 7018164614Sariff hdac_lock(sc); 7019164614Sariff if (val != sc->polling) { 7020182999Smav if (val == 0) { 7021182999Smav callout_stop(&sc->poll_hda); 7022164614Sariff callout_stop(&sc->poll_hdac); 7023169277Sariff hdac_unlock(sc); 7024182999Smav callout_drain(&sc->poll_hda); 7025169277Sariff callout_drain(&sc->poll_hdac); 7026169277Sariff hdac_lock(sc); 7027164614Sariff sc->polling = 0; 7028182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7029182999Smav ctl |= HDAC_INTCTL_GIE; 7030182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7031164614Sariff } else { 7032182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7033182999Smav ctl &= ~HDAC_INTCTL_GIE; 7034182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7035171141Sariff hdac_unlock(sc); 7036171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7037171141Sariff hdac_lock(sc); 7038164614Sariff sc->polling = 1; 7039182999Smav hdac_poll_reinit(sc); 7040182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7041164614Sariff } 7042164614Sariff } 7043164614Sariff hdac_unlock(sc); 7044164614Sariff 7045164614Sariff return (err); 7046164614Sariff} 7047169277Sariff 7048169277Sariffstatic int 7049169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7050169277Sariff{ 7051169277Sariff struct hdac_softc *sc; 7052169277Sariff device_t dev; 7053169277Sariff int err, val; 7054169277Sariff 7055169277Sariff dev = oidp->oid_arg1; 7056182999Smav sc = device_get_softc(dev); 7057182999Smav if (sc == NULL) 7058169277Sariff return (EINVAL); 7059169277Sariff hdac_lock(sc); 7060169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7061169277Sariff hdac_unlock(sc); 7062170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7063169277Sariff 7064169277Sariff if (err != 0 || req->newptr == NULL) 7065169277Sariff return (err); 7066169277Sariff 7067169277Sariff if (val < 1) 7068169277Sariff val = 1; 7069169277Sariff if (val > 5000) 7070169277Sariff val = 5000; 7071169277Sariff val = ((uint64_t)val * hz) / 1000; 7072169277Sariff if (val < 1) 7073169277Sariff val = 1; 7074169277Sariff if (val > (hz * 5)) 7075169277Sariff val = hz * 5; 7076169277Sariff 7077169277Sariff hdac_lock(sc); 7078169277Sariff sc->poll_ival = val; 7079169277Sariff hdac_unlock(sc); 7080169277Sariff 7081169277Sariff return (err); 7082169277Sariff} 7083169277Sariff 7084169277Sariffstatic int 7085171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7086169277Sariff{ 7087169277Sariff struct hdac_softc *sc; 7088182999Smav struct hdac_codec *codec; 7089169277Sariff struct hdac_devinfo *devinfo; 7090169277Sariff struct hdac_widget *w; 7091169277Sariff device_t dev; 7092182999Smav uint32_t res, pincap, delay; 7093182999Smav int codec_index, fg_index; 7094169277Sariff int i, err, val; 7095169277Sariff nid_t cad; 7096169277Sariff 7097169277Sariff dev = oidp->oid_arg1; 7098182999Smav sc = device_get_softc(dev); 7099182999Smav if (sc == NULL) 7100169277Sariff return (EINVAL); 7101169277Sariff val = 0; 7102170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7103169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7104169277Sariff return (err); 7105182999Smav 7106182999Smav /* XXX: Temporary. For debugging. */ 7107182999Smav if (val == 100) { 7108182999Smav hdac_suspend(dev); 7109182999Smav return (0); 7110182999Smav } else if (val == 101) { 7111182999Smav hdac_resume(dev); 7112182999Smav return (0); 7113182999Smav } 7114182999Smav 7115169277Sariff hdac_lock(sc); 7116182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7117182999Smav codec = sc->codecs[codec_index]; 7118182999Smav if (codec == NULL) 7119169277Sariff continue; 7120182999Smav cad = codec->cad; 7121182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7122182999Smav devinfo = &codec->fgs[fg_index]; 7123182999Smav if (devinfo->node_type != 7124182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7125182999Smav continue; 7126182999Smav 7127182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7128182999Smav codec_index, devinfo->nid); 7129182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7130182999Smav w = hdac_widget_get(devinfo, i); 7131182999Smav if (w == NULL || w->type != 7132182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7133182999Smav continue; 7134182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7135182999Smav pincap = w->wclass.pin.cap; 7136182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7137182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7138182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7139182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7140182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7141182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7142182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7143182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7144182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7145182999Smav delay = 0; 7146182999Smav hdac_command(sc, 7147182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7148182999Smav do { 7149182999Smav res = hdac_command(sc, 7150182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7151182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7152182999Smav break; 7153182999Smav DELAY(10); 7154182999Smav } while (++delay < 10000); 7155182999Smav } else { 7156182999Smav delay = 0; 7157182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7158182999Smav w->nid), cad); 7159182999Smav } 7160182999Smav printf(" Sense: 0x%08x", res); 7161182999Smav if (delay > 0) 7162182999Smav printf(" delay %dus", delay * 10); 7163182999Smav } 7164182999Smav printf("\n"); 7165182999Smav } 7166182999Smav device_printf(dev, 7167182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7168182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7169182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7170182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7171182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7172182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7173182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7174182999Smav device_printf(dev, " GPI:"); 7175171141Sariff res = hdac_command(sc, 7176182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7177182999Smav printf(" data=0x%08x", res); 7178182999Smav res = hdac_command(sc, 7179182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7180182999Smav cad); 7181182999Smav printf(" wake=0x%08x", res); 7182182999Smav res = hdac_command(sc, 7183182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7184182999Smav cad); 7185182999Smav printf(" unsol=0x%08x", res); 7186182999Smav res = hdac_command(sc, 7187182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7188182999Smav printf(" sticky=0x%08x\n", res); 7189182999Smav } 7190182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7191182999Smav device_printf(dev, " GPO:"); 7192182999Smav res = hdac_command(sc, 7193182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7194182999Smav printf(" data=0x%08x\n", res); 7195182999Smav } 7196182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7197182999Smav device_printf(dev, "GPIO:"); 7198182999Smav res = hdac_command(sc, 7199182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7200182999Smav printf(" data=0x%08x", res); 7201182999Smav res = hdac_command(sc, 7202182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7203182999Smav printf(" enable=0x%08x", res); 7204182999Smav res = hdac_command(sc, 7205182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7206182999Smav printf(" direction=0x%08x\n", res); 7207182999Smav res = hdac_command(sc, 7208182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7209182999Smav device_printf(dev, " wake=0x%08x", res); 7210182999Smav res = hdac_command(sc, 7211182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7212182999Smav cad); 7213182999Smav printf(" unsol=0x%08x", res); 7214182999Smav res = hdac_command(sc, 7215182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7216182999Smav printf(" sticky=0x%08x\n", res); 7217182999Smav } 7218171141Sariff } 7219169277Sariff } 7220169277Sariff hdac_unlock(sc); 7221169277Sariff return (0); 7222169277Sariff} 7223164614Sariff#endif 7224164614Sariff 7225163057Sariffstatic void 7226162922Sariffhdac_attach2(void *arg) 7227162922Sariff{ 7228182999Smav struct hdac_codec *codec; 7229162922Sariff struct hdac_softc *sc; 7230162922Sariff struct hdac_audio_ctl *ctl; 7231163057Sariff uint32_t quirks_on, quirks_off; 7232182999Smav int codec_index, fg_index; 7233185225Smav int i, dmaalloc = 0; 7234182999Smav struct hdac_devinfo *devinfo; 7235162922Sariff 7236162922Sariff sc = (struct hdac_softc *)arg; 7237162922Sariff 7238163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7239162922Sariff 7240183097Smav HDA_BOOTHVERBOSE( 7241182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7242163057Sariff quirks_on, quirks_off); 7243163057Sariff ); 7244163057Sariff 7245162922Sariff hdac_lock(sc); 7246162922Sariff 7247162922Sariff /* Remove ourselves from the config hooks */ 7248162922Sariff if (sc->intrhook.ich_func != NULL) { 7249162922Sariff config_intrhook_disestablish(&sc->intrhook); 7250162922Sariff sc->intrhook.ich_func = NULL; 7251162922Sariff } 7252162922Sariff 7253162922Sariff /* Start the corb and rirb engines */ 7254183097Smav HDA_BOOTHVERBOSE( 7255182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7256162922Sariff ); 7257162922Sariff hdac_corb_start(sc); 7258183097Smav HDA_BOOTHVERBOSE( 7259182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7260162922Sariff ); 7261162922Sariff hdac_rirb_start(sc); 7262162922Sariff 7263183097Smav HDA_BOOTHVERBOSE( 7264162922Sariff device_printf(sc->dev, 7265182999Smav "Enabling controller interrupt...\n"); 7266162922Sariff ); 7267182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7268182999Smav HDAC_GCTL_UNSOL); 7269182999Smav if (sc->polling == 0) { 7270164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7271164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7272182999Smav } else { 7273182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7274182999Smav } 7275162922Sariff DELAY(1000); 7276162922Sariff 7277183097Smav HDA_BOOTHVERBOSE( 7278172811Sariff device_printf(sc->dev, 7279182999Smav "Scanning HDA codecs ...\n"); 7280162922Sariff ); 7281182999Smav hdac_scan_codecs(sc); 7282182999Smav 7283182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7284182999Smav codec = sc->codecs[codec_index]; 7285182999Smav if (codec == NULL) 7286182999Smav continue; 7287182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7288182999Smav devinfo = &codec->fgs[fg_index]; 7289183019Smav HDA_BOOTVERBOSE( 7290183019Smav device_printf(sc->dev, "\n"); 7291183097Smav device_printf(sc->dev, 7292183097Smav "Processing %s FG cad=%d nid=%d...\n", 7293183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7294183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7295183097Smav "unknown", 7296183097Smav devinfo->codec->cad, devinfo->nid); 7297183019Smav ); 7298182999Smav if (devinfo->node_type != 7299182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7300183097Smav HDA_BOOTHVERBOSE( 7301182999Smav device_printf(sc->dev, 7302183097Smav "Powering down...\n"); 7303182999Smav ); 7304182999Smav hdac_command(sc, 7305182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7306182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7307182999Smav codec->cad); 7308182999Smav continue; 7309182999Smav } 7310162922Sariff 7311183097Smav HDA_BOOTHVERBOSE( 7312183097Smav device_printf(sc->dev, "Powering up...\n"); 7313182999Smav ); 7314182999Smav hdac_powerup(devinfo); 7315183097Smav HDA_BOOTHVERBOSE( 7316182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7317182999Smav ); 7318182999Smav hdac_audio_parse(devinfo); 7319183097Smav HDA_BOOTHVERBOSE( 7320182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7321182999Smav ); 7322182999Smav hdac_audio_ctl_parse(devinfo); 7323183097Smav HDA_BOOTHVERBOSE( 7324182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7325182999Smav ); 7326182999Smav hdac_vendor_patch_parse(devinfo); 7327182999Smav devinfo->function.audio.quirks |= quirks_on; 7328182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7329162922Sariff 7330183097Smav HDA_BOOTHVERBOSE( 7331182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7332182999Smav ); 7333182999Smav hdac_audio_disable_nonaudio(devinfo); 7334183097Smav HDA_BOOTHVERBOSE( 7335182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7336182999Smav ); 7337182999Smav hdac_audio_disable_useless(devinfo); 7338182999Smav HDA_BOOTVERBOSE( 7339182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7340182999Smav hdac_dump_pin_configs(devinfo); 7341183097Smav ); 7342183097Smav HDA_BOOTHVERBOSE( 7343182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7344182999Smav ); 7345182999Smav hdac_audio_as_parse(devinfo); 7346183097Smav HDA_BOOTHVERBOSE( 7347182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7348182999Smav ); 7349182999Smav hdac_audio_build_tree(devinfo); 7350183097Smav HDA_BOOTHVERBOSE( 7351182999Smav device_printf(sc->dev, "Disabling unassociated " 7352182999Smav "widgets...\n"); 7353182999Smav ); 7354182999Smav hdac_audio_disable_unas(devinfo); 7355183097Smav HDA_BOOTHVERBOSE( 7356182999Smav device_printf(sc->dev, "Disabling nonselected " 7357182999Smav "inputs...\n"); 7358182999Smav ); 7359182999Smav hdac_audio_disable_notselected(devinfo); 7360183097Smav HDA_BOOTHVERBOSE( 7361182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7362182999Smav ); 7363182999Smav hdac_audio_disable_useless(devinfo); 7364183097Smav HDA_BOOTHVERBOSE( 7365182999Smav device_printf(sc->dev, "Disabling " 7366182999Smav "crossassociatement connections...\n"); 7367182999Smav ); 7368182999Smav hdac_audio_disable_crossas(devinfo); 7369183097Smav HDA_BOOTHVERBOSE( 7370182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7371182999Smav ); 7372182999Smav hdac_audio_disable_useless(devinfo); 7373183097Smav HDA_BOOTHVERBOSE( 7374182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7375182999Smav ); 7376182999Smav hdac_audio_bind_as(devinfo); 7377183097Smav HDA_BOOTHVERBOSE( 7378182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7379182999Smav ); 7380182999Smav hdac_audio_assign_names(devinfo); 7381183097Smav HDA_BOOTHVERBOSE( 7382182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7383182999Smav ); 7384182999Smav hdac_audio_assign_mixers(devinfo); 7385183097Smav HDA_BOOTHVERBOSE( 7386182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7387182999Smav ); 7388182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7389183097Smav HDA_BOOTHVERBOSE( 7390182999Smav device_printf(sc->dev, "AFG commit...\n"); 7391182999Smav ); 7392182999Smav hdac_audio_commit(devinfo); 7393183097Smav HDA_BOOTHVERBOSE( 7394182999Smav device_printf(sc->dev, "Ctls commit...\n"); 7395182999Smav ); 7396182999Smav hdac_audio_ctl_commit(devinfo); 7397183097Smav HDA_BOOTHVERBOSE( 7398182999Smav device_printf(sc->dev, "HP switch init...\n"); 7399182999Smav ); 7400182999Smav hdac_hp_switch_init(devinfo); 7401182999Smav 7402182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7403182999Smav dmaalloc == 0) { 7404182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7405182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7406182999Smav HDA_BOOTVERBOSE( 7407182999Smav device_printf(sc->dev, "Failed to " 7408182999Smav "allocate DMA pos buffer " 7409182999Smav "(non-fatal)\n"); 7410182999Smav ); 7411182999Smav } else 7412182999Smav dmaalloc = 1; 7413182999Smav } 7414182999Smav 7415185225Smav HDA_BOOTHVERBOSE( 7416185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7417185225Smav ); 7418185225Smav hdac_create_pcms(devinfo); 7419182999Smav 7420182999Smav HDA_BOOTVERBOSE( 7421182999Smav if (devinfo->function.audio.quirks != 0) { 7422183097Smav device_printf(sc->dev, "FG config/quirks:"); 7423182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7424182999Smav if ((devinfo->function.audio.quirks & 7425182999Smav hdac_quirks_tab[i].value) == 7426182999Smav hdac_quirks_tab[i].value) 7427182999Smav printf(" %s", hdac_quirks_tab[i].key); 7428182999Smav } 7429182999Smav printf("\n"); 7430182999Smav } 7431182999Smav 7432182999Smav device_printf(sc->dev, "\n"); 7433182999Smav device_printf(sc->dev, "+-------------------+\n"); 7434182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7435182999Smav device_printf(sc->dev, "+-------------------+\n"); 7436182999Smav hdac_dump_nodes(devinfo); 7437183097Smav ); 7438182999Smav 7439183097Smav HDA_BOOTHVERBOSE( 7440182999Smav device_printf(sc->dev, "\n"); 7441182999Smav device_printf(sc->dev, "+------------------------+\n"); 7442182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7443182999Smav device_printf(sc->dev, "+------------------------+\n"); 7444182999Smav device_printf(sc->dev, "\n"); 7445182999Smav i = 0; 7446182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7447182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7448182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7449182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7450182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7451182999Smav ctl->index); 7452182999Smav if (ctl->childwidget != NULL) 7453182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7454182999Smav else 7455182999Smav printf(" "); 7456182999Smav printf(" ossmask=0x%08x\n", 7457182999Smav ctl->ossmask); 7458182999Smav device_printf(sc->dev, 7459182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7460182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7461182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7462182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7463182999Smav } 7464182999Smav ); 7465182999Smav } 7466162922Sariff } 7467182999Smav hdac_unlock(sc); 7468162922Sariff 7469163057Sariff HDA_BOOTVERBOSE( 7470182999Smav device_printf(sc->dev, "\n"); 7471162922Sariff ); 7472182999Smav 7473182999Smav bus_generic_attach(sc->dev); 7474182999Smav 7475182999Smav#ifdef SND_DYNSYSCTL 7476182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7477182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7478182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7479182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7480182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7481182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7482182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7483182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7484182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7485182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7486182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7487182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7488182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7489182999Smav#endif 7490182999Smav} 7491182999Smav 7492182999Smav/**************************************************************************** 7493182999Smav * int hdac_suspend(device_t) 7494182999Smav * 7495182999Smav * Suspend and power down HDA bus and codecs. 7496182999Smav ****************************************************************************/ 7497182999Smavstatic int 7498182999Smavhdac_suspend(device_t dev) 7499182999Smav{ 7500182999Smav struct hdac_softc *sc; 7501182999Smav struct hdac_codec *codec; 7502182999Smav struct hdac_devinfo *devinfo; 7503182999Smav int codec_index, fg_index, i; 7504182999Smav 7505183097Smav HDA_BOOTHVERBOSE( 7506182999Smav device_printf(dev, "Suspend...\n"); 7507162922Sariff ); 7508182999Smav 7509182999Smav sc = device_get_softc(dev); 7510182999Smav hdac_lock(sc); 7511182999Smav 7512183097Smav HDA_BOOTHVERBOSE( 7513182999Smav device_printf(dev, "Stop streams...\n"); 7514162922Sariff ); 7515182999Smav for (i = 0; i < sc->num_chans; i++) { 7516182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7517182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7518182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7519182999Smav } 7520182999Smav } 7521162922Sariff 7522182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7523182999Smav codec = sc->codecs[codec_index]; 7524182999Smav if (codec == NULL) 7525162922Sariff continue; 7526182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7527182999Smav devinfo = &codec->fgs[fg_index]; 7528183097Smav HDA_BOOTHVERBOSE( 7529182999Smav device_printf(dev, 7530182999Smav "Power down FG" 7531182999Smav " cad=%d nid=%d to the D3 state...\n", 7532182999Smav codec->cad, devinfo->nid); 7533182999Smav ); 7534182999Smav hdac_command(sc, 7535182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7536182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7537182999Smav codec->cad); 7538162922Sariff } 7539162922Sariff } 7540162922Sariff 7541183097Smav HDA_BOOTHVERBOSE( 7542182999Smav device_printf(dev, "Reset controller...\n"); 7543162922Sariff ); 7544182999Smav callout_stop(&sc->poll_hda); 7545182999Smav callout_stop(&sc->poll_hdac); 7546182999Smav callout_stop(&sc->poll_jack); 7547182999Smav hdac_reset(sc, 0); 7548182999Smav hdac_unlock(sc); 7549182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7550182999Smav callout_drain(&sc->poll_hda); 7551182999Smav callout_drain(&sc->poll_hdac); 7552182999Smav callout_drain(&sc->poll_jack); 7553162922Sariff 7554183097Smav HDA_BOOTHVERBOSE( 7555182999Smav device_printf(dev, "Suspend done\n"); 7556162922Sariff ); 7557182999Smav 7558182999Smav return (0); 7559182999Smav} 7560182999Smav 7561182999Smav/**************************************************************************** 7562182999Smav * int hdac_resume(device_t) 7563182999Smav * 7564182999Smav * Powerup and restore HDA bus and codecs state. 7565182999Smav ****************************************************************************/ 7566182999Smavstatic int 7567182999Smavhdac_resume(device_t dev) 7568182999Smav{ 7569182999Smav struct hdac_softc *sc; 7570182999Smav struct hdac_codec *codec; 7571182999Smav struct hdac_devinfo *devinfo; 7572182999Smav int codec_index, fg_index, i; 7573182999Smav 7574183097Smav HDA_BOOTHVERBOSE( 7575182999Smav device_printf(dev, "Resume...\n"); 7576162922Sariff ); 7577162922Sariff 7578182999Smav sc = device_get_softc(dev); 7579182999Smav hdac_lock(sc); 7580182999Smav 7581182999Smav /* Quiesce everything */ 7582183097Smav HDA_BOOTHVERBOSE( 7583182999Smav device_printf(dev, "Reset controller...\n"); 7584162922Sariff ); 7585182999Smav hdac_reset(sc, 1); 7586182999Smav 7587182999Smav /* Initialize the CORB and RIRB */ 7588182999Smav hdac_corb_init(sc); 7589182999Smav hdac_rirb_init(sc); 7590182999Smav 7591182999Smav /* Start the corb and rirb engines */ 7592183097Smav HDA_BOOTHVERBOSE( 7593182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7594162922Sariff ); 7595182999Smav hdac_corb_start(sc); 7596183097Smav HDA_BOOTHVERBOSE( 7597182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7598162922Sariff ); 7599182999Smav hdac_rirb_start(sc); 7600163057Sariff 7601183097Smav HDA_BOOTHVERBOSE( 7602182999Smav device_printf(dev, 7603182999Smav "Enabling controller interrupt...\n"); 7604162922Sariff ); 7605182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7606182999Smav HDAC_GCTL_UNSOL); 7607182999Smav if (sc->polling == 0) { 7608182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7609182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7610182999Smav } else { 7611182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7612182999Smav } 7613182999Smav DELAY(1000); 7614162922Sariff 7615182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7616182999Smav codec = sc->codecs[codec_index]; 7617182999Smav if (codec == NULL) 7618182999Smav continue; 7619182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7620182999Smav devinfo = &codec->fgs[fg_index]; 7621182999Smav if (devinfo->node_type != 7622182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7623183097Smav HDA_BOOTHVERBOSE( 7624182999Smav device_printf(dev, 7625182999Smav "Power down unsupported non-audio FG" 7626182999Smav " cad=%d nid=%d to the D3 state...\n", 7627182999Smav codec->cad, devinfo->nid); 7628182999Smav ); 7629182999Smav hdac_command(sc, 7630182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7631182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7632182999Smav codec->cad); 7633182999Smav continue; 7634182999Smav } 7635162922Sariff 7636183097Smav HDA_BOOTHVERBOSE( 7637182999Smav device_printf(dev, 7638182999Smav "Power up audio FG cad=%d nid=%d...\n", 7639182999Smav devinfo->codec->cad, devinfo->nid); 7640182999Smav ); 7641182999Smav hdac_powerup(devinfo); 7642183097Smav HDA_BOOTHVERBOSE( 7643182999Smav device_printf(dev, "AFG commit...\n"); 7644182999Smav ); 7645182999Smav hdac_audio_commit(devinfo); 7646183097Smav HDA_BOOTHVERBOSE( 7647182999Smav device_printf(dev, "Ctls commit...\n"); 7648182999Smav ); 7649182999Smav hdac_audio_ctl_commit(devinfo); 7650183097Smav HDA_BOOTHVERBOSE( 7651182999Smav device_printf(dev, "HP switch init...\n"); 7652182999Smav ); 7653182999Smav hdac_hp_switch_init(devinfo); 7654182999Smav 7655182999Smav hdac_unlock(sc); 7656182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7657182999Smav struct hdac_pcm_devinfo *pdevinfo = 7658182999Smav &devinfo->function.audio.devs[i]; 7659183097Smav HDA_BOOTHVERBOSE( 7660182999Smav device_printf(pdevinfo->dev, 7661182999Smav "OSS mixer reinitialization...\n"); 7662182999Smav ); 7663182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 7664182999Smav device_printf(pdevinfo->dev, 7665182999Smav "unable to reinitialize the mixer\n"); 7666182999Smav } 7667182999Smav hdac_lock(sc); 7668182999Smav } 7669169277Sariff } 7670169277Sariff 7671183097Smav HDA_BOOTHVERBOSE( 7672182999Smav device_printf(dev, "Start streams...\n"); 7673163057Sariff ); 7674182999Smav for (i = 0; i < sc->num_chans; i++) { 7675182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 7676182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 7677182999Smav hdac_channel_start(sc, &sc->chans[i]); 7678182999Smav } 7679182999Smav } 7680162922Sariff 7681182999Smav hdac_unlock(sc); 7682182999Smav 7683183097Smav HDA_BOOTHVERBOSE( 7684182999Smav device_printf(dev, "Resume done\n"); 7685162922Sariff ); 7686164614Sariff 7687182999Smav return (0); 7688162922Sariff} 7689162922Sariff/**************************************************************************** 7690162922Sariff * int hdac_detach(device_t) 7691162922Sariff * 7692162922Sariff * Detach and free up resources utilized by the hdac device. 7693162922Sariff ****************************************************************************/ 7694162922Sariffstatic int 7695162922Sariffhdac_detach(device_t dev) 7696162922Sariff{ 7697182999Smav struct hdac_softc *sc; 7698185177Smav device_t *devlist; 7699185177Smav int i, devcount, error; 7700162922Sariff 7701185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 7702185177Smav return (error); 7703185177Smav for (i = 0; i < devcount; i++) { 7704185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 7705185178Smav free(devlist, M_TEMP); 7706185178Smav return (error); 7707185178Smav } 7708185177Smav } 7709185177Smav free(devlist, M_TEMP); 7710185177Smav 7711182999Smav sc = device_get_softc(dev); 7712163057Sariff hdac_release_resources(sc); 7713162922Sariff 7714162922Sariff return (0); 7715162922Sariff} 7716162922Sariff 7717184095Smavstatic int 7718184095Smavhdac_print_child(device_t dev, device_t child) 7719184095Smav{ 7720184095Smav struct hdac_pcm_devinfo *pdevinfo = 7721184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 7722184095Smav int retval; 7723184095Smav 7724184095Smav retval = bus_print_child_header(dev, child); 7725184095Smav retval += printf(" at cad %d nid %d", 7726184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 7727184095Smav retval += bus_print_child_footer(dev, child); 7728184095Smav 7729184095Smav return (retval); 7730184095Smav} 7731184095Smav 7732162922Sariffstatic device_method_t hdac_methods[] = { 7733162922Sariff /* device interface */ 7734162922Sariff DEVMETHOD(device_probe, hdac_probe), 7735162922Sariff DEVMETHOD(device_attach, hdac_attach), 7736162922Sariff DEVMETHOD(device_detach, hdac_detach), 7737182999Smav DEVMETHOD(device_suspend, hdac_suspend), 7738182999Smav DEVMETHOD(device_resume, hdac_resume), 7739184095Smav /* Bus interface */ 7740184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 7741162922Sariff { 0, 0 } 7742162922Sariff}; 7743162922Sariff 7744162922Sariffstatic driver_t hdac_driver = { 7745182999Smav "hdac", 7746162922Sariff hdac_methods, 7747182999Smav sizeof(struct hdac_softc), 7748162922Sariff}; 7749162922Sariff 7750182999Smavstatic devclass_t hdac_devclass; 7751182999Smav 7752182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 7753162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 7754162922SariffMODULE_VERSION(snd_hda, 1); 7755182999Smav 7756182999Smavstatic int 7757182999Smavhdac_pcm_probe(device_t dev) 7758182999Smav{ 7759182999Smav struct hdac_pcm_devinfo *pdevinfo = 7760182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7761182999Smav char buf[128]; 7762182999Smav 7763185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 7764182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 7765185225Smav pdevinfo->index, 7766185225Smav pdevinfo->digital?"Digital":"Analog"); 7767182999Smav device_set_desc_copy(dev, buf); 7768182999Smav return (0); 7769182999Smav} 7770182999Smav 7771182999Smavstatic int 7772182999Smavhdac_pcm_attach(device_t dev) 7773182999Smav{ 7774182999Smav struct hdac_pcm_devinfo *pdevinfo = 7775182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7776182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7777182999Smav char status[SND_STATUSLEN]; 7778182999Smav int i; 7779182999Smav 7780182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 7781182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 7782182999Smav 7783182999Smav HDA_BOOTVERBOSE( 7784182999Smav device_printf(dev, "+--------------------------------------+\n"); 7785182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 7786182999Smav device_printf(dev, "+--------------------------------------+\n"); 7787182999Smav hdac_dump_pcmchannels(pdevinfo); 7788182999Smav device_printf(dev, "\n"); 7789182999Smav device_printf(dev, "+--------------------------------+\n"); 7790182999Smav device_printf(dev, "| DUMPING Playback/Record Pathes |\n"); 7791182999Smav device_printf(dev, "+--------------------------------+\n"); 7792182999Smav hdac_dump_dac(pdevinfo); 7793182999Smav hdac_dump_adc(pdevinfo); 7794182999Smav hdac_dump_mix(pdevinfo); 7795182999Smav device_printf(dev, "\n"); 7796182999Smav device_printf(dev, "+-------------------------+\n"); 7797182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 7798182999Smav device_printf(dev, "+-------------------------+\n"); 7799182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 7800182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 7801182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 7802182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 7803182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 7804182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 7805182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 7806182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 7807182999Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 7808182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 7809182999Smav device_printf(dev, "\n"); 7810182999Smav ); 7811182999Smav 7812182999Smav if (resource_int_value(device_get_name(dev), 7813182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 7814182999Smav i &= HDA_BLK_ALIGN; 7815182999Smav if (i < HDA_BLK_MIN) 7816182999Smav i = HDA_BLK_MIN; 7817182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 7818182999Smav i = 0; 7819182999Smav while (pdevinfo->chan_blkcnt >> i) 7820182999Smav i++; 7821182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 7822182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 7823182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 7824182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 7825182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 7826182999Smav } else 7827182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 7828182999Smav 7829182999Smav /* 7830182999Smav * We don't register interrupt handler with snd_setup_intr 7831182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 7832182999Smav */ 7833182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 7834182999Smav 7835183097Smav HDA_BOOTHVERBOSE( 7836182999Smav device_printf(dev, "OSS mixer initialization...\n"); 7837182999Smav ); 7838182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 7839182999Smav device_printf(dev, "Can't register mixer\n"); 7840182999Smav 7841183097Smav HDA_BOOTHVERBOSE( 7842182999Smav device_printf(dev, "Registering PCM channels...\n"); 7843182999Smav ); 7844182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 7845182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 7846182999Smav device_printf(dev, "Can't register PCM\n"); 7847182999Smav 7848182999Smav pdevinfo->registered++; 7849182999Smav 7850182999Smav if (pdevinfo->play >= 0) 7851182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 7852182999Smav if (pdevinfo->rec >= 0) 7853182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 7854182999Smav 7855184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 7856184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 7857184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 7858182999Smav pcm_setstatus(dev, status); 7859182999Smav 7860182999Smav return (0); 7861182999Smav} 7862182999Smav 7863182999Smavstatic int 7864182999Smavhdac_pcm_detach(device_t dev) 7865182999Smav{ 7866182999Smav struct hdac_pcm_devinfo *pdevinfo = 7867182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7868182999Smav int err; 7869182999Smav 7870182999Smav if (pdevinfo->registered > 0) { 7871182999Smav err = pcm_unregister(dev); 7872182999Smav if (err != 0) 7873182999Smav return (err); 7874182999Smav } 7875182999Smav 7876182999Smav return (0); 7877182999Smav} 7878182999Smav 7879182999Smavstatic device_method_t hdac_pcm_methods[] = { 7880182999Smav /* device interface */ 7881182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 7882182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 7883182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 7884182999Smav { 0, 0 } 7885182999Smav}; 7886182999Smav 7887182999Smavstatic driver_t hdac_pcm_driver = { 7888182999Smav "pcm", 7889182999Smav hdac_pcm_methods, 7890182999Smav PCM_SOFTC_SIZE, 7891182999Smav}; 7892182999Smav 7893182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 7894182999Smav 7895