hdac.c revision 189876
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 86189086Smav#define HDA_DRV_TEST_REV "20090226_0129" 87162922Sariff 88162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 189876 2009-03-16 12:42:23Z 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 112162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 113163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 114163257Sariff (fl) == 0xffffffff || \ 115163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 116163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 117163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 118163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 119162965Sariff#define HDA_MATCH_ALL 0xffffffff 120162965Sariff#define HDAC_INVALID 0xffffffff 121162965Sariff 122169277Sariff/* Default controller / jack sense poll: 250ms */ 123169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 124169277Sariff 125171141Sariff/* 126171141Sariff * Make room for possible 4096 playback/record channels, in 100 years to come. 127171141Sariff */ 128171141Sariff#define HDAC_TRIGGER_NONE 0x00000000 129171141Sariff#define HDAC_TRIGGER_PLAY 0x00000fff 130171141Sariff#define HDAC_TRIGGER_REC 0x00fff000 131171141Sariff#define HDAC_TRIGGER_UNSOL 0x80000000 132171141Sariff 133162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 134162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 135162922Sariff 136162922Sariff/* Controller models */ 137162922Sariff 138162922Sariff/* Intel */ 139162922Sariff#define INTEL_VENDORID 0x8086 140162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 141171330Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 142162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 143163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 144171330Sariff#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e) 145184207Smav#define HDA_INTEL_82801J HDA_MODEL_CONSTRUCT(INTEL, 0x3a3e) 146187020Smav#define HDA_INTEL_PCH HDA_MODEL_CONSTRUCT(INTEL, 0x3b56) 147184207Smav#define HDA_INTEL_SCH HDA_MODEL_CONSTRUCT(INTEL, 0x811b) 148162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 149162922Sariff 150162922Sariff/* Nvidia */ 151162922Sariff#define NVIDIA_VENDORID 0x10de 152162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 153162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 154173817Sariff#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 155173817Sariff#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 156173817Sariff#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 157173817Sariff#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 158173817Sariff#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c) 159173817Sariff#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d) 160186511Smav#define HDA_NVIDIA_MCP78_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0774) 161186511Smav#define HDA_NVIDIA_MCP78_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0775) 162186511Smav#define HDA_NVIDIA_MCP78_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0776) 163186511Smav#define HDA_NVIDIA_MCP78_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0777) 164186511Smav#define HDA_NVIDIA_MCP73_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fc) 165186511Smav#define HDA_NVIDIA_MCP73_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fd) 166186511Smav#define HDA_NVIDIA_MCP79_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac0) 167186511Smav#define HDA_NVIDIA_MCP79_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac1) 168186511Smav#define HDA_NVIDIA_MCP79_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac2) 169186511Smav#define HDA_NVIDIA_MCP79_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac3) 170162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 171162922Sariff 172162922Sariff/* ATI */ 173162922Sariff#define ATI_VENDORID 0x1002 174162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 175163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 176187020Smav#define HDA_ATI_RS600 HDA_MODEL_CONSTRUCT(ATI, 0x793b) 177187020Smav#define HDA_ATI_RS690 HDA_MODEL_CONSTRUCT(ATI, 0x7919) 178187020Smav#define HDA_ATI_RS780 HDA_MODEL_CONSTRUCT(ATI, 0x960f) 179187020Smav#define HDA_ATI_R600 HDA_MODEL_CONSTRUCT(ATI, 0xaa00) 180187020Smav#define HDA_ATI_RV630 HDA_MODEL_CONSTRUCT(ATI, 0xaa08) 181187020Smav#define HDA_ATI_RV610 HDA_MODEL_CONSTRUCT(ATI, 0xaa10) 182187020Smav#define HDA_ATI_RV670 HDA_MODEL_CONSTRUCT(ATI, 0xaa18) 183187020Smav#define HDA_ATI_RV635 HDA_MODEL_CONSTRUCT(ATI, 0xaa20) 184187020Smav#define HDA_ATI_RV620 HDA_MODEL_CONSTRUCT(ATI, 0xaa28) 185187020Smav#define HDA_ATI_RV770 HDA_MODEL_CONSTRUCT(ATI, 0xaa30) 186187020Smav#define HDA_ATI_RV730 HDA_MODEL_CONSTRUCT(ATI, 0xaa38) 187187020Smav#define HDA_ATI_RV710 HDA_MODEL_CONSTRUCT(ATI, 0xaa40) 188187020Smav#define HDA_ATI_RV740 HDA_MODEL_CONSTRUCT(ATI, 0xaa48) 189162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 190162922Sariff 191163136Sariff/* VIA */ 192163136Sariff#define VIA_VENDORID 0x1106 193163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 194163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 195163136Sariff 196163136Sariff/* SiS */ 197163136Sariff#define SIS_VENDORID 0x1039 198163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 199163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 200163136Sariff 201186301Smav/* ULI */ 202186301Smav#define ULI_VENDORID 0x10b9 203186301Smav#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461) 204186301Smav#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff) 205186301Smav 206162922Sariff/* OEM/subvendors */ 207162922Sariff 208165466Sariff/* Intel */ 209165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 210165466Sariff 211162922Sariff/* HP/Compaq */ 212162922Sariff#define HP_VENDORID 0x103c 213162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 214162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 215162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 216165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 217166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 218169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 219169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 220174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 221172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 222162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 223165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 224165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 225162922Sariff 226162922Sariff/* Dell */ 227162922Sariff#define DELL_VENDORID 0x1028 228180532Sdelphij#define DELL_D630_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01f9) 229162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 230184483Smav#define DELL_V1400_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0227) 231178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 232162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 233169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 234169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 235162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 236162922Sariff 237162922Sariff/* Clevo */ 238162922Sariff#define CLEVO_VENDORID 0x1558 239162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 240162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 241162922Sariff 242162922Sariff/* Acer */ 243162922Sariff#define ACER_VENDORID 0x1025 244165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 245173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 246174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 247182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 248169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 249182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 250162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 251162922Sariff 252162965Sariff/* Asus */ 253162965Sariff#define ASUS_VENDORID 0x1043 254178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 255163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 256178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 257165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 258178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 259178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 260167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 261169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 262178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 263178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 264178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 265170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 266178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 267169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 268171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 269162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 270162922Sariff 271163257Sariff/* IBM / Lenovo */ 272163257Sariff#define IBM_VENDORID 0x1014 273163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 274163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 275162965Sariff 276164614Sariff/* Lenovo */ 277164657Sariff#define LENOVO_VENDORID 0x17aa 278164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 279182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 280172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 281164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 282163257Sariff 283164657Sariff/* Samsung */ 284164657Sariff#define SAMSUNG_VENDORID 0x144d 285164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 286164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 287164614Sariff 288164750Sariff/* Medion ? */ 289164750Sariff#define MEDION_VENDORID 0x161f 290164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 291164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 292164750Sariff 293173817Sariff/* Apple Computer Inc. */ 294173817Sariff#define APPLE_VENDORID 0x106b 295173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 296173817Sariff 297182999Smav/* Sony */ 298182999Smav#define SONY_VENDORID 0x104d 299182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 300182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 301182999Smav 302164828Sariff/* 303164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 304164828Sariff * instead of their own, which is beyond my comprehension 305164828Sariff * (see HDA_CODEC_STAC9221 below). 306164828Sariff */ 307164828Sariff#define APPLE_INTEL_MAC 0x76808384 308164828Sariff 309165281Sariff/* LG Electronics */ 310165281Sariff#define LG_VENDORID 0x1854 311165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 312165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 313165281Sariff 314165351Sariff/* Fujitsu Siemens */ 315165351Sariff#define FS_VENDORID 0x1734 316165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 317172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 318165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 319165351Sariff 320172811Sariff/* Fujitsu Limited */ 321172811Sariff#define FL_VENDORID 0x10cf 322172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 323182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 324172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 325172811Sariff 326165770Sariff/* Toshiba */ 327165770Sariff#define TOSHIBA_VENDORID 0x1179 328165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 329173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 330165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 331165770Sariff 332165992Sariff/* Micro-Star International (MSI) */ 333165992Sariff#define MSI_VENDORID 0x1462 334165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 335172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 336165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 337165992Sariff 338172811Sariff/* Giga-Byte Technology */ 339172811Sariff#define GB_VENDORID 0x1458 340172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 341172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 342172811Sariff 343169277Sariff/* Uniwill ? */ 344169277Sariff#define UNIWILL_VENDORID 0x1584 345169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 346170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 347169277Sariff 348169277Sariff 349162922Sariff/* Misc constants.. */ 350182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 351162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 352162922Sariff#define HDA_AMP_MUTE_NONE (0) 353162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 354162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 355162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 356162922Sariff 357162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 358162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 359162922Sariff 360182999Smav#define HDA_ADC_MONITOR (1 << 0) 361162922Sariff 362182999Smav#define HDA_CTL_OUT 1 363182999Smav#define HDA_CTL_IN 2 364169277Sariff 365169277Sariff#define HDA_GPIO_MAX 8 366169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 367163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 368163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 369163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 370169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 371169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 372169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 373169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 374169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 375169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 376162922Sariff 377169277Sariff/* 9 - 25 = anything else */ 378169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 379169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 380169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 381169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 382169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 383182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 384169277Sariff 385169277Sariff/* 26 - 31 = vrefs */ 386169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 387169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 388169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 389169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 390169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 391169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 392169277Sariff 393169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 394169277Sariff HDA_QUIRK_IVREF100) 395169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 396169277Sariff HDA_QUIRK_OVREF100) 397169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 398169277Sariff 399171141Sariff#if __FreeBSD_version < 600000 400171141Sariff#define taskqueue_drain(...) 401171141Sariff#endif 402171141Sariff 403163057Sariffstatic const struct { 404163057Sariff char *key; 405163057Sariff uint32_t value; 406163057Sariff} hdac_quirks_tab[] = { 407163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 408163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 409163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 410169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 411169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 412169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 413169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 414169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 415165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 416163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 417163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 418163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 419163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 420169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 421182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 422169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 423169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 424169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 425169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 426169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 427169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 428169277Sariff { "ivref", HDA_QUIRK_IVREF }, 429169277Sariff { "ovref", HDA_QUIRK_OVREF }, 430165069Sariff { "vref", HDA_QUIRK_VREF }, 431163057Sariff}; 432163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 433163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 434163057Sariff 435162922Sariff#define HDA_BDL_MIN 2 436162922Sariff#define HDA_BDL_MAX 256 437162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 438162922Sariff 439169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 440167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 441167648Sariff 442162922Sariff#define HDA_BUFSZ_MIN 4096 443162922Sariff#define HDA_BUFSZ_MAX 65536 444162922Sariff#define HDA_BUFSZ_DEFAULT 16384 445162922Sariff 446162922Sariff#define HDA_PARSE_MAXDEPTH 10 447162922Sariff 448169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 449162922Sariff 450165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 451162922Sariff 452182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 453182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 454182999Smav "White", "Other"}; 455162922Sariff 456182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 457182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 458182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 459182999Smav 460182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 461182999Smav 462162922Sariff/* Default */ 463162922Sariffstatic uint32_t hdac_fmt[] = { 464162922Sariff AFMT_STEREO | AFMT_S16_LE, 465162922Sariff 0 466162922Sariff}; 467162922Sariff 468162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 469162922Sariff 470189086Smav#define HDAC_NO_MSI 1 471189086Smav 472162922Sariffstatic const struct { 473162922Sariff uint32_t model; 474162922Sariff char *desc; 475189086Smav char flags; 476162922Sariff} hdac_devices[] = { 477189086Smav { HDA_INTEL_82801F, "Intel 82801F", 0 }, 478189086Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, 479189086Smav { HDA_INTEL_82801G, "Intel 82801G", 0 }, 480189086Smav { HDA_INTEL_82801H, "Intel 82801H", 0 }, 481189086Smav { HDA_INTEL_82801I, "Intel 82801I", 0 }, 482189086Smav { HDA_INTEL_82801J, "Intel 82801J", 0 }, 483189086Smav { HDA_INTEL_PCH, "Intel PCH", 0 }, 484189086Smav { HDA_INTEL_SCH, "Intel SCH", 0 }, 485189086Smav { HDA_NVIDIA_MCP51, "NVidia MCP51", HDAC_NO_MSI }, 486189086Smav { HDA_NVIDIA_MCP55, "NVidia MCP55", 0 }, 487189086Smav { HDA_NVIDIA_MCP61_1, "NVidia MCP61", 0 }, 488189086Smav { HDA_NVIDIA_MCP61_2, "NVidia MCP61", 0 }, 489189086Smav { HDA_NVIDIA_MCP65_1, "NVidia MCP65", 0 }, 490189086Smav { HDA_NVIDIA_MCP65_2, "NVidia MCP65", 0 }, 491189086Smav { HDA_NVIDIA_MCP67_1, "NVidia MCP67", 0 }, 492189086Smav { HDA_NVIDIA_MCP67_2, "NVidia MCP67", 0 }, 493189086Smav { HDA_NVIDIA_MCP73_1, "NVidia MCP73", 0 }, 494189086Smav { HDA_NVIDIA_MCP73_2, "NVidia MCP73", 0 }, 495189086Smav { HDA_NVIDIA_MCP78_1, "NVidia MCP78", 0 }, 496189086Smav { HDA_NVIDIA_MCP78_2, "NVidia MCP78", 0 }, 497189086Smav { HDA_NVIDIA_MCP78_3, "NVidia MCP78", 0 }, 498189086Smav { HDA_NVIDIA_MCP78_4, "NVidia MCP78", 0 }, 499189086Smav { HDA_NVIDIA_MCP79_1, "NVidia MCP79", 0 }, 500189086Smav { HDA_NVIDIA_MCP79_2, "NVidia MCP79", 0 }, 501189086Smav { HDA_NVIDIA_MCP79_3, "NVidia MCP79", 0 }, 502189086Smav { HDA_NVIDIA_MCP79_4, "NVidia MCP79", 0 }, 503189086Smav { HDA_ATI_SB450, "ATI SB450", 0 }, 504189086Smav { HDA_ATI_SB600, "ATI SB600", 0 }, 505189086Smav { HDA_ATI_RS600, "ATI RS600", 0 }, 506189086Smav { HDA_ATI_RS690, "ATI RS690", 0 }, 507189086Smav { HDA_ATI_RS780, "ATI RS780", 0 }, 508189086Smav { HDA_ATI_R600, "ATI R600", 0 }, 509189086Smav { HDA_ATI_RV610, "ATI RV610", 0 }, 510189086Smav { HDA_ATI_RV620, "ATI RV620", 0 }, 511189086Smav { HDA_ATI_RV630, "ATI RV630", 0 }, 512189086Smav { HDA_ATI_RV635, "ATI RV635", 0 }, 513189086Smav { HDA_ATI_RV710, "ATI RV710", 0 }, 514189086Smav { HDA_ATI_RV730, "ATI RV730", 0 }, 515189086Smav { HDA_ATI_RV740, "ATI RV740", 0 }, 516189086Smav { HDA_ATI_RV770, "ATI RV770", 0 }, 517189086Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0 }, 518189086Smav { HDA_SIS_966, "SiS 966", 0 }, 519189086Smav { HDA_ULI_M5461, "ULI M5461", 0 }, 520162922Sariff /* Unknown */ 521162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 522162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 523162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 524163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 525163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 526186301Smav { HDA_ULI_ALL, "ULI (Unknown)" }, 527162922Sariff}; 528162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 529162922Sariff 530162922Sariffstatic const struct { 531169277Sariff uint16_t vendor; 532169277Sariff uint8_t reg; 533169277Sariff uint8_t mask; 534169277Sariff uint8_t enable; 535169277Sariff} hdac_pcie_snoop[] = { 536169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 537169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 538169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 539169277Sariff}; 540169277Sariff#define HDAC_PCIESNOOP_LEN \ 541169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 542169277Sariff 543169277Sariffstatic const struct { 544162922Sariff uint32_t rate; 545162922Sariff int valid; 546162922Sariff uint16_t base; 547162922Sariff uint16_t mul; 548162922Sariff uint16_t div; 549162922Sariff} hda_rate_tab[] = { 550162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 551162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 552162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 553162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 554162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 555162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 556162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 557162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 558162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 559162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 560162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 561162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 562162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 563162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 564162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 565162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 566162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 567162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 568162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 569162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 570162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 571162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 572162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 573162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 574162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 575162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 576162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 577162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 578162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 579162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 580162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 581162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 582162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 583162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 584162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 585162922Sariff}; 586162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 587162922Sariff 588162922Sariff/* All codecs you can eat... */ 589162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 590162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 591162922Sariff 592162922Sariff/* Realtek */ 593162922Sariff#define REALTEK_VENDORID 0x10ec 594162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 595169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 596183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 597171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 598183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 599183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 600170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 601183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 602183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 603162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 604169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 605162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 606163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 607163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 608169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 609165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 610182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 611162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 612162922Sariff 613169277Sariff/* Analog Devices */ 614169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 615186403Smav#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) 616186403Smav#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) 617186403Smav#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) 618186403Smav#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) 619186403Smav#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) 620186403Smav#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) 621169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 622169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 623174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 624169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 625186403Smav#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) 626169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 627170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 628186403Smav#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) 629186403Smav#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) 630169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 631162922Sariff 632162922Sariff/* CMedia */ 633162922Sariff#define CMEDIA_VENDORID 0x434d 634162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 635162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 636162922Sariff 637162922Sariff/* Sigmatel */ 638162922Sariff#define SIGMATEL_VENDORID 0x8384 639182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 640182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 641182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 642182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 643182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 644182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 645182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 646182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 647183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 648183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 649183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 650183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 651183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 652183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 653183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 654182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 655183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 656183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 657183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 658183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 659183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 660183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 661183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 662183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 663182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 664162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 665182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 666183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 667162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 668162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 669183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 670183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 671183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 672183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 673183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 674183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 675183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 676183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 677183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 678162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 679162922Sariff 680183894Smav/* IDT */ 681183894Smav#define IDT_VENDORID 0x111d 682183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 683183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 684183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 685183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 686183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 687183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 688183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 689183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 690183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 691183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 692183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 693183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 694183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 695183894Smav 696182999Smav/* Silicon Image */ 697182999Smav#define SII_VENDORID 0x1095 698187020Smav#define HDA_CODEC_SII1390 HDA_CODEC_CONSTRUCT(SII, 0x1390) 699186146Smav#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) 700182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 701182999Smav 702182999Smav/* Lucent/Agere */ 703182999Smav#define AGERE_VENDORID 0x11c1 704182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 705182999Smav 706186430Smav/* Conexant */ 707162922Sariff#define CONEXANT_VENDORID 0x14f1 708186430Smav#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 709186430Smav#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 710186430Smav#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) 711162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 712162922Sariff 713169277Sariff/* VIA */ 714169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 715169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 716169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 717169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 718169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 719169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 720169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 721169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 722169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 723169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 724169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 725169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 726186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 727186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 728186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 729186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 730186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 731186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 732186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 733186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 734187020Smav#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) 735187020Smav#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) 736187020Smav#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) 737187020Smav#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) 738187020Smav#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) 739187020Smav#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) 740187020Smav#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) 741187020Smav#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) 742187020Smav#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) 743187020Smav#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) 744187020Smav#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) 745187020Smav#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) 746187020Smav#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) 747187020Smav#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) 748187020Smav#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) 749187020Smav#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) 750169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 751162922Sariff 752182999Smav/* ATI */ 753186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 754186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 755186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 756186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 757182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 758169277Sariff 759182999Smav/* NVIDIA */ 760187020Smav#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) 761187445Smav#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) 762187020Smav#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) 763187020Smav#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) 764187445Smav#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) 765182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 766182999Smav 767183894Smav/* INTEL */ 768187020Smav#define HDA_CODEC_INTELG45_1 HDA_CODEC_CONSTRUCT(INTEL, 0x2801) 769187020Smav#define HDA_CODEC_INTELG45_2 HDA_CODEC_CONSTRUCT(INTEL, 0x2802) 770187020Smav#define HDA_CODEC_INTELG45_3 HDA_CODEC_CONSTRUCT(INTEL, 0x2803) 771187020Smav#define HDA_CODEC_INTELG45_4 HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) 772183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 773183894Smav 774162922Sariff/* Codecs */ 775162922Sariffstatic const struct { 776162922Sariff uint32_t id; 777162922Sariff char *name; 778162922Sariff} hdac_codecs[] = { 779162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 780169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 781183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 782171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 783183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 784183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 785170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 786183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 787183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 788162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 789169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 790162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 791162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 792163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 793169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 794165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 795182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 796186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 797186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 798186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 799186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 800186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 801169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 802169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 803174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 804186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 805186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 806169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 807186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 808186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 809170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 810186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 811162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 812183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 813183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 814183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 815183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 816183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 817183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 818183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 819183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 820162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 821183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 822162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 823162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 824183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 825183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 826183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 827183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 828183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 829183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 830182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 831182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 832183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 833183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 834183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 835166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 836183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 837183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 838183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 839183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 840183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 841183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 842183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 843183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 844183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 845183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 846183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 847183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 848183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 849183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 850183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 851183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 852183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 853183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 854183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 855183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 856183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 857183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 858183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 859183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 860183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 861183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 862183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 863186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 864186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 865186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 866169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 867169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 868169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 869169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 870169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 871169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 872169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 873169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 874169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 875169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 876169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 877169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 878186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 879186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 880186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 881186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 882186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 883186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 884186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 885186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 886187020Smav { HDA_CODEC_VT1708S_0, "VIA VT1708S_0" }, 887187020Smav { HDA_CODEC_VT1708S_1, "VIA VT1708S_1" }, 888187020Smav { HDA_CODEC_VT1708S_2, "VIA VT1708S_2" }, 889187020Smav { HDA_CODEC_VT1708S_3, "VIA VT1708S_3" }, 890187020Smav { HDA_CODEC_VT1708S_4, "VIA VT1708S_4" }, 891187020Smav { HDA_CODEC_VT1708S_5, "VIA VT1708S_5" }, 892187020Smav { HDA_CODEC_VT1708S_6, "VIA VT1708S_6" }, 893187020Smav { HDA_CODEC_VT1708S_7, "VIA VT1708S_7" }, 894187020Smav { HDA_CODEC_VT1702_0, "VIA VT1702_0" }, 895187020Smav { HDA_CODEC_VT1702_1, "VIA VT1702_1" }, 896187020Smav { HDA_CODEC_VT1702_2, "VIA VT1702_2" }, 897187020Smav { HDA_CODEC_VT1702_3, "VIA VT1702_3" }, 898187020Smav { HDA_CODEC_VT1702_4, "VIA VT1702_4" }, 899187020Smav { HDA_CODEC_VT1702_5, "VIA VT1702_5" }, 900187020Smav { HDA_CODEC_VT1702_6, "VIA VT1702_6" }, 901187020Smav { HDA_CODEC_VT1702_7, "VIA VT1702_7" }, 902186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 903186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 904186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 905186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 906187020Smav { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, 907187445Smav { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, 908187020Smav { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, 909187445Smav { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, 910187020Smav { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, 911187020Smav { HDA_CODEC_INTELG45_1, "Intel G45 HDMI" }, 912187020Smav { HDA_CODEC_INTELG45_2, "Intel G45 HDMI" }, 913187020Smav { HDA_CODEC_INTELG45_3, "Intel G45 HDMI" }, 914187020Smav { HDA_CODEC_INTELG45_4, "Intel G45 HDMI" }, 915187020Smav { HDA_CODEC_SII1390, "Silicon Image SiI1390 HDMI" }, 916186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 917162922Sariff /* Unknown codec */ 918162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 919169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 920162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 921162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 922182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 923182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 924162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 925169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 926182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 927182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 928183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 929183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 930162922Sariff}; 931162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 932162922Sariff 933162922Sariff 934162922Sariff/**************************************************************************** 935162922Sariff * Function prototypes 936162922Sariff ****************************************************************************/ 937162922Sariffstatic void hdac_intr_handler(void *); 938182999Smavstatic int hdac_reset(struct hdac_softc *, int); 939162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 940162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 941162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 942162922Sariff struct hdac_dma *, bus_size_t); 943169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 944162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 945162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 946162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 947162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 948162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 949162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 950162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 951162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 952182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 953182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 954182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 955182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 956162922Sariff 957162922Sariffstatic void hdac_attach2(void *); 958162922Sariff 959162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 960162922Sariff uint32_t, int); 961162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 962162922Sariff struct hdac_command_list *, int); 963162922Sariff 964162922Sariffstatic int hdac_probe(device_t); 965162922Sariffstatic int hdac_attach(device_t); 966162922Sariffstatic int hdac_detach(device_t); 967182999Smavstatic int hdac_suspend(device_t); 968182999Smavstatic int hdac_resume(device_t); 969162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 970162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 971162922Sariff uint32_t, int, int); 972162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 973182999Smav nid_t, int, int, int); 974162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 975162922Sariff nid_t, nid_t, int, int, int, int, int, int); 976162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 977162922Sariff 978164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 979164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 980164614Sariff 981182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 982182999Smav 983162922Sariff#define hdac_command(a1, a2, a3) \ 984162922Sariff hdac_command_sendone_internal(a1, a2, a3) 985162922Sariff 986182999Smav#define hdac_codec_id(c) \ 987182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 988182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 989182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 990162922Sariff 991162922Sariffstatic char * 992182999Smavhdac_codec_name(struct hdac_codec *codec) 993162922Sariff{ 994162922Sariff uint32_t id; 995162922Sariff int i; 996162922Sariff 997182999Smav id = hdac_codec_id(codec); 998162922Sariff 999162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 1000163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 1001162922Sariff return (hdac_codecs[i].name); 1002162922Sariff } 1003162922Sariff 1004162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 1005162922Sariff} 1006162922Sariff 1007162922Sariffstatic char * 1008162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 1009162922Sariff{ 1010162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 1011162922Sariff int i, first = 1; 1012162922Sariff 1013162922Sariff bzero(buf, len); 1014162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 1015162922Sariff if (mask & (1 << i)) { 1016162922Sariff if (first == 0) 1017162922Sariff strlcat(buf, ", ", len); 1018162922Sariff strlcat(buf, ossname[i], len); 1019162922Sariff first = 0; 1020162922Sariff } 1021162922Sariff } 1022182999Smav return (buf); 1023162922Sariff} 1024162922Sariff 1025162922Sariffstatic struct hdac_audio_ctl * 1026162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 1027162922Sariff{ 1028162922Sariff if (devinfo == NULL || 1029162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 1030162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 1031162922Sariff devinfo->function.audio.ctlcnt < 1 || 1032162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 1033162922Sariff return (NULL); 1034162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 1035162922Sariff} 1036162922Sariff 1037162922Sariffstatic struct hdac_audio_ctl * 1038182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 1039162922Sariff int index, int cnt) 1040162922Sariff{ 1041182999Smav struct hdac_audio_ctl *ctl; 1042182999Smav int i, found = 0; 1043162922Sariff 1044162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 1045162922Sariff return (NULL); 1046162922Sariff 1047162922Sariff i = 0; 1048162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 1049182999Smav if (ctl->enable == 0) 1050162922Sariff continue; 1051182999Smav if (ctl->widget->nid != nid) 1052162922Sariff continue; 1053182999Smav if (dir && ctl->ndir != dir) 1054182999Smav continue; 1055182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 1056182999Smav ctl->dir == ctl->ndir && ctl->index != index) 1057182999Smav continue; 1058162922Sariff found++; 1059182999Smav if (found == cnt || cnt <= 0) 1060162922Sariff return (ctl); 1061162922Sariff } 1062162922Sariff 1063182999Smav return (NULL); 1064162922Sariff} 1065162922Sariff 1066182999Smav/* 1067182999Smav * Jack detection (Speaker/HP redirection) event handler. 1068182999Smav */ 1069162922Sariffstatic void 1070162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 1071162922Sariff{ 1072182999Smav struct hdac_audio_as *as; 1073162922Sariff struct hdac_softc *sc; 1074162922Sariff struct hdac_widget *w; 1075162922Sariff struct hdac_audio_ctl *ctl; 1076182999Smav uint32_t val, res; 1077182999Smav int i, j; 1078162922Sariff nid_t cad; 1079162922Sariff 1080162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1081162922Sariff devinfo->codec->sc == NULL) 1082162922Sariff return; 1083162922Sariff 1084162922Sariff sc = devinfo->codec->sc; 1085162922Sariff cad = devinfo->codec->cad; 1086182999Smav as = devinfo->function.audio.as; 1087182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1088182999Smav if (as[i].hpredir < 0) 1089182999Smav continue; 1090182999Smav 1091182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1092182999Smav if (w == NULL || w->enable == 0 || w->type != 1093182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1094182999Smav continue; 1095162922Sariff 1096171141Sariff res = hdac_command(sc, 1097182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1098171141Sariff 1099182999Smav HDA_BOOTVERBOSE( 1100182999Smav device_printf(sc->dev, 1101182999Smav "Pin sense: nid=%d res=0x%08x\n", 1102182999Smav as[i].pins[15], res); 1103182999Smav ); 1104171141Sariff 1105182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1106182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1107182999Smav res ^= 1; 1108162922Sariff 1109182999Smav /* (Un)Mute headphone pin. */ 1110162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1111182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1112182999Smav if (ctl != NULL && ctl->mute) { 1113182999Smav /* If pin has muter - use it. */ 1114182999Smav val = (res != 0) ? 0 : 1; 1115182999Smav if (val != ctl->forcemute) { 1116182999Smav ctl->forcemute = val; 1117162922Sariff hdac_audio_ctl_amp_set(ctl, 1118182999Smav HDA_AMP_MUTE_DEFAULT, 1119182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1120162922Sariff } 1121182999Smav } else { 1122182999Smav /* If there is no muter - disable pin output. */ 1123182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1124163057Sariff if (w != NULL && w->type == 1125163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1126182999Smav if (res != 0) 1127169277Sariff val = w->wclass.pin.ctrl | 1128162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1129162922Sariff else 1130169277Sariff val = w->wclass.pin.ctrl & 1131162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1132169277Sariff if (val != w->wclass.pin.ctrl) { 1133169277Sariff w->wclass.pin.ctrl = val; 1134169277Sariff hdac_command(sc, 1135169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1136169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1137169277Sariff } 1138162922Sariff } 1139182999Smav } 1140182999Smav /* (Un)Mute other pins. */ 1141182999Smav for (j = 0; j < 15; j++) { 1142182999Smav if (as[i].pins[j] <= 0) 1143182999Smav continue; 1144182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1145182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1146182999Smav if (ctl != NULL && ctl->mute) { 1147182999Smav /* If pin has muter - use it. */ 1148182999Smav val = (res != 0) ? 1 : 0; 1149182999Smav if (val == ctl->forcemute) 1150169277Sariff continue; 1151182999Smav ctl->forcemute = val; 1152182999Smav hdac_audio_ctl_amp_set(ctl, 1153182999Smav HDA_AMP_MUTE_DEFAULT, 1154182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1155182999Smav continue; 1156162922Sariff } 1157182999Smav /* If there is no muter - disable pin output. */ 1158182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1159163057Sariff if (w != NULL && w->type == 1160163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1161182999Smav if (res != 0) 1162182999Smav val = w->wclass.pin.ctrl & 1163182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1164182999Smav else 1165182999Smav val = w->wclass.pin.ctrl | 1166182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1167169277Sariff if (val != w->wclass.pin.ctrl) { 1168169277Sariff w->wclass.pin.ctrl = val; 1169169277Sariff hdac_command(sc, 1170169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1171169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1172169277Sariff } 1173162922Sariff } 1174162922Sariff } 1175182999Smav } 1176182999Smav} 1177182999Smav 1178182999Smav/* 1179182999Smav * Callback for poll based jack detection. 1180182999Smav */ 1181182999Smavstatic void 1182182999Smavhdac_jack_poll_callback(void *arg) 1183182999Smav{ 1184182999Smav struct hdac_devinfo *devinfo = arg; 1185182999Smav struct hdac_softc *sc; 1186182999Smav 1187182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1188182999Smav devinfo->codec->sc == NULL) 1189182999Smav return; 1190182999Smav sc = devinfo->codec->sc; 1191182999Smav hdac_lock(sc); 1192182999Smav if (sc->poll_ival == 0) { 1193182999Smav hdac_unlock(sc); 1194182999Smav return; 1195182999Smav } 1196182999Smav hdac_hp_switch_handler(devinfo); 1197182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1198182999Smav hdac_jack_poll_callback, devinfo); 1199182999Smav hdac_unlock(sc); 1200182999Smav} 1201182999Smav 1202182999Smav/* 1203182999Smav * Jack detection initializer. 1204182999Smav */ 1205182999Smavstatic void 1206182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1207182999Smav{ 1208182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1209182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1210182999Smav struct hdac_widget *w; 1211182999Smav uint32_t id; 1212182999Smav int i, enable = 0, poll = 0; 1213182999Smav nid_t cad; 1214182999Smav 1215182999Smav id = hdac_codec_id(devinfo->codec); 1216182999Smav cad = devinfo->codec->cad; 1217182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1218182999Smav if (as[i].hpredir < 0) 1219182999Smav continue; 1220182999Smav 1221182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1222182999Smav if (w == NULL || w->enable == 0 || w->type != 1223182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1224182999Smav continue; 1225182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1226182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1227182999Smav device_printf(sc->dev, 1228182999Smav "No jack detection support at pin %d\n", 1229182999Smav as[i].pins[15]); 1230182999Smav continue; 1231182999Smav } 1232182999Smav enable = 1; 1233182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1234169277Sariff hdac_command(sc, 1235182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1236182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1237182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1238182999Smav } else 1239182999Smav poll = 1; 1240182999Smav HDA_BOOTVERBOSE( 1241169277Sariff device_printf(sc->dev, 1242182999Smav "Enabling headphone/speaker " 1243182999Smav "audio routing switching:\n"); 1244182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1245182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1246182999Smav ); 1247182999Smav } 1248182999Smav if (enable) { 1249182999Smav hdac_hp_switch_handler(devinfo); 1250182999Smav if (poll) { 1251182999Smav callout_reset(&sc->poll_jack, 1, 1252182999Smav hdac_jack_poll_callback, devinfo); 1253169277Sariff } 1254162922Sariff } 1255162922Sariff} 1256162922Sariff 1257182999Smav/* 1258182999Smav * Unsolicited messages handler. 1259182999Smav */ 1260162922Sariffstatic void 1261162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1262162922Sariff{ 1263162922Sariff struct hdac_softc *sc; 1264162922Sariff struct hdac_devinfo *devinfo = NULL; 1265182999Smav int i; 1266162922Sariff 1267162922Sariff if (codec == NULL || codec->sc == NULL) 1268162922Sariff return; 1269162922Sariff 1270162922Sariff sc = codec->sc; 1271162922Sariff 1272163057Sariff HDA_BOOTVERBOSE( 1273182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1274162922Sariff ); 1275162922Sariff 1276182999Smav for (i = 0; i < codec->num_fgs; i++) { 1277182999Smav if (codec->fgs[i].node_type == 1278182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1279182999Smav devinfo = &codec->fgs[i]; 1280162965Sariff break; 1281182999Smav } 1282162922Sariff } 1283162965Sariff 1284162922Sariff if (devinfo == NULL) 1285162922Sariff return; 1286162922Sariff 1287162922Sariff switch (tag) { 1288162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1289162922Sariff hdac_hp_switch_handler(devinfo); 1290162922Sariff break; 1291162922Sariff default: 1292182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1293162922Sariff break; 1294162922Sariff } 1295162922Sariff} 1296162922Sariff 1297164614Sariffstatic int 1298162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1299162922Sariff{ 1300162922Sariff /* XXX to be removed */ 1301162922Sariff#ifdef HDAC_INTR_EXTRA 1302162922Sariff uint32_t res; 1303162922Sariff#endif 1304162922Sariff 1305171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1306164614Sariff return (0); 1307162922Sariff 1308162922Sariff /* XXX to be removed */ 1309162922Sariff#ifdef HDAC_INTR_EXTRA 1310162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1311162922Sariff#endif 1312162922Sariff 1313162922Sariff /* XXX to be removed */ 1314162922Sariff#ifdef HDAC_INTR_EXTRA 1315163057Sariff HDA_BOOTVERBOSE( 1316163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1317182999Smav device_printf(ch->pdevinfo->dev, 1318163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1319163057Sariff "%08x\n", 1320163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1321163057Sariff ); 1322162922Sariff#endif 1323162922Sariff 1324162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1325163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1326162922Sariff 1327162922Sariff /* XXX to be removed */ 1328162922Sariff#ifdef HDAC_INTR_EXTRA 1329162922Sariff if (res & HDAC_SDSTS_BCIS) { 1330162922Sariff#endif 1331164614Sariff return (1); 1332162922Sariff /* XXX to be removed */ 1333162922Sariff#ifdef HDAC_INTR_EXTRA 1334162922Sariff } 1335162922Sariff#endif 1336164614Sariff 1337164614Sariff return (0); 1338162922Sariff} 1339162922Sariff 1340162922Sariff/**************************************************************************** 1341162922Sariff * void hdac_intr_handler(void *) 1342162922Sariff * 1343162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1344162922Sariff ****************************************************************************/ 1345162922Sariffstatic void 1346162922Sariffhdac_intr_handler(void *context) 1347162922Sariff{ 1348162922Sariff struct hdac_softc *sc; 1349162922Sariff uint32_t intsts; 1350162922Sariff uint8_t rirbsts; 1351164614Sariff struct hdac_rirb *rirb_base; 1352171141Sariff uint32_t trigger; 1353182999Smav int i; 1354162922Sariff 1355162922Sariff sc = (struct hdac_softc *)context; 1356162922Sariff 1357162922Sariff hdac_lock(sc); 1358164614Sariff if (sc->polling != 0) { 1359164614Sariff hdac_unlock(sc); 1360164614Sariff return; 1361164614Sariff } 1362171141Sariff 1363162922Sariff /* Do we have anything to do? */ 1364162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1365163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1366162922Sariff hdac_unlock(sc); 1367162922Sariff return; 1368162922Sariff } 1369162922Sariff 1370171141Sariff trigger = 0; 1371171141Sariff 1372162922Sariff /* Was this a controller interrupt? */ 1373163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1374162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1375162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1376162922Sariff /* Get as many responses that we can */ 1377163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1378164614Sariff HDAC_WRITE_1(&sc->mem, 1379164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1380171141Sariff if (hdac_rirb_flush(sc) != 0) 1381171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1382162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1383162922Sariff } 1384162922Sariff /* XXX to be removed */ 1385162922Sariff /* Clear interrupt and exit */ 1386162922Sariff#ifdef HDAC_INTR_EXTRA 1387162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1388162922Sariff#endif 1389162922Sariff } 1390164614Sariff 1391163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1392182999Smav for (i = 0; i < sc->num_chans; i++) { 1393182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1394182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1395182999Smav trigger |= (1 << i); 1396182999Smav } 1397162922Sariff /* XXX to be removed */ 1398162922Sariff#ifdef HDAC_INTR_EXTRA 1399164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1400164614Sariff HDAC_INTSTS_SIS_MASK); 1401162922Sariff#endif 1402162922Sariff } 1403162922Sariff 1404164614Sariff hdac_unlock(sc); 1405162922Sariff 1406182999Smav for (i = 0; i < sc->num_chans; i++) { 1407182999Smav if (trigger & (1 << i)) 1408182999Smav chn_intr(sc->chans[i].c); 1409182999Smav } 1410171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1411171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1412162922Sariff} 1413162922Sariff 1414162922Sariff/**************************************************************************** 1415182999Smav * int hdac_reset(hdac_softc *, int) 1416162922Sariff * 1417162922Sariff * Reset the hdac to a quiescent and known state. 1418162922Sariff ****************************************************************************/ 1419162922Sariffstatic int 1420182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1421162922Sariff{ 1422162922Sariff uint32_t gctl; 1423162922Sariff int count, i; 1424162922Sariff 1425162922Sariff /* 1426162922Sariff * Stop all Streams DMA engine 1427162922Sariff */ 1428162922Sariff for (i = 0; i < sc->num_iss; i++) 1429162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1430162922Sariff for (i = 0; i < sc->num_oss; i++) 1431162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1432162922Sariff for (i = 0; i < sc->num_bss; i++) 1433162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1434162922Sariff 1435162922Sariff /* 1436169277Sariff * Stop Control DMA engines. 1437162922Sariff */ 1438162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1439162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1440162922Sariff 1441162922Sariff /* 1442169277Sariff * Reset DMA position buffer. 1443169277Sariff */ 1444169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1445169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1446169277Sariff 1447169277Sariff /* 1448162922Sariff * Reset the controller. The reset must remain asserted for 1449162922Sariff * a minimum of 100us. 1450162922Sariff */ 1451162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1452162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1453162922Sariff count = 10000; 1454162922Sariff do { 1455162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1456162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1457162922Sariff break; 1458162922Sariff DELAY(10); 1459162922Sariff } while (--count); 1460162922Sariff if (gctl & HDAC_GCTL_CRST) { 1461162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1462162922Sariff return (ENXIO); 1463162922Sariff } 1464182999Smav 1465182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1466182999Smav if (!wakeup) 1467182999Smav return (0); 1468182999Smav 1469162922Sariff DELAY(100); 1470162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1471162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1472162922Sariff count = 10000; 1473162922Sariff do { 1474162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1475163057Sariff if (gctl & HDAC_GCTL_CRST) 1476162922Sariff break; 1477162922Sariff DELAY(10); 1478162922Sariff } while (--count); 1479162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1480162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1481162922Sariff return (ENXIO); 1482162922Sariff } 1483162922Sariff 1484162922Sariff /* 1485162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1486162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1487162922Sariff * computer. Let's use twice as much as necessary to make sure that 1488162922Sariff * it's reset properly. 1489162922Sariff */ 1490162922Sariff DELAY(1000); 1491162922Sariff 1492162922Sariff return (0); 1493162922Sariff} 1494162922Sariff 1495162922Sariff 1496162922Sariff/**************************************************************************** 1497162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1498162922Sariff * 1499162922Sariff * Retreive the general capabilities of the hdac; 1500162922Sariff * Number of Input Streams 1501162922Sariff * Number of Output Streams 1502162922Sariff * Number of bidirectional Streams 1503162922Sariff * 64bit ready 1504162922Sariff * CORB and RIRB sizes 1505162922Sariff ****************************************************************************/ 1506162922Sariffstatic int 1507162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1508162922Sariff{ 1509162922Sariff uint16_t gcap; 1510162922Sariff uint8_t corbsize, rirbsize; 1511162922Sariff 1512162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1513162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1514162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1515162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1516162922Sariff 1517163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1518162922Sariff 1519162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1520162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1521162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1522162922Sariff sc->corb_size = 256; 1523162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1524162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1525162922Sariff sc->corb_size = 16; 1526162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1527162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1528162922Sariff sc->corb_size = 2; 1529162922Sariff else { 1530162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1531162922Sariff __func__, corbsize); 1532162922Sariff return (ENXIO); 1533162922Sariff } 1534162922Sariff 1535162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1536162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1537162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1538162922Sariff sc->rirb_size = 256; 1539162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1540162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1541162922Sariff sc->rirb_size = 16; 1542162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1543162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1544162922Sariff sc->rirb_size = 2; 1545162922Sariff else { 1546162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1547162922Sariff __func__, rirbsize); 1548162922Sariff return (ENXIO); 1549162922Sariff } 1550162922Sariff 1551183097Smav HDA_BOOTHVERBOSE( 1552182999Smav device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 1553182999Smav device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 1554182999Smav device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 1555182999Smav sc->num_iss, sc->num_oss, sc->num_bss); 1556182999Smav ); 1557182999Smav 1558162922Sariff return (0); 1559162922Sariff} 1560162922Sariff 1561162922Sariff 1562162922Sariff/**************************************************************************** 1563162922Sariff * void hdac_dma_cb 1564162922Sariff * 1565162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1566162922Sariff * established. We just record the physical address of the mapping into 1567162922Sariff * the struct hdac_dma passed in. 1568162922Sariff ****************************************************************************/ 1569162922Sariffstatic void 1570162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1571162922Sariff{ 1572162922Sariff struct hdac_dma *dma; 1573162922Sariff 1574162922Sariff if (error == 0) { 1575162922Sariff dma = (struct hdac_dma *)callback_arg; 1576162922Sariff dma->dma_paddr = segs[0].ds_addr; 1577162922Sariff } 1578162922Sariff} 1579162922Sariff 1580162922Sariff 1581162922Sariff/**************************************************************************** 1582162922Sariff * int hdac_dma_alloc 1583162922Sariff * 1584162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1585162922Sariff * It must be freed by a corresponding hdac_dma_free. 1586162922Sariff ****************************************************************************/ 1587162922Sariffstatic int 1588162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1589162922Sariff{ 1590169277Sariff bus_size_t roundsz; 1591162922Sariff int result; 1592162922Sariff int lowaddr; 1593162922Sariff 1594169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1595162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1596162922Sariff BUS_SPACE_MAXADDR_32BIT; 1597162922Sariff bzero(dma, sizeof(*dma)); 1598162922Sariff 1599162922Sariff /* 1600162922Sariff * Create a DMA tag 1601162922Sariff */ 1602162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1603162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1604162922Sariff 0, /* boundary */ 1605162922Sariff lowaddr, /* lowaddr */ 1606162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1607162922Sariff NULL, /* filtfunc */ 1608162922Sariff NULL, /* fistfuncarg */ 1609169277Sariff roundsz, /* maxsize */ 1610162922Sariff 1, /* nsegments */ 1611169277Sariff roundsz, /* maxsegsz */ 1612162922Sariff 0, /* flags */ 1613162922Sariff NULL, /* lockfunc */ 1614162922Sariff NULL, /* lockfuncarg */ 1615162922Sariff &dma->dma_tag); /* dmat */ 1616162922Sariff if (result != 0) { 1617162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1618162922Sariff __func__, result); 1619167773Sariff goto hdac_dma_alloc_fail; 1620162922Sariff } 1621162922Sariff 1622162922Sariff /* 1623162922Sariff * Allocate DMA memory 1624162922Sariff */ 1625162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1626169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1627171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1628171330Sariff &dma->dma_map); 1629162922Sariff if (result != 0) { 1630162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1631162922Sariff __func__, result); 1632167773Sariff goto hdac_dma_alloc_fail; 1633162922Sariff } 1634162922Sariff 1635169277Sariff dma->dma_size = roundsz; 1636169277Sariff 1637162922Sariff /* 1638162922Sariff * Map the memory 1639162922Sariff */ 1640162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1641169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1642162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1643167773Sariff if (result == 0) 1644167773Sariff result = ENOMEM; 1645162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1646162922Sariff __func__, result); 1647167773Sariff goto hdac_dma_alloc_fail; 1648162922Sariff } 1649162922Sariff 1650183097Smav HDA_BOOTHVERBOSE( 1651169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1652169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1653169277Sariff ); 1654169277Sariff 1655162922Sariff return (0); 1656169277Sariff 1657167773Sariffhdac_dma_alloc_fail: 1658169277Sariff hdac_dma_free(sc, dma); 1659167773Sariff 1660162922Sariff return (result); 1661162922Sariff} 1662162922Sariff 1663162922Sariff 1664162922Sariff/**************************************************************************** 1665169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1666162922Sariff * 1667162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1668162922Sariff * hdac_dma_alloc function. 1669162922Sariff ****************************************************************************/ 1670162922Sariffstatic void 1671169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1672162922Sariff{ 1673167773Sariff if (dma->dma_map != NULL) { 1674169277Sariff#if 0 1675162922Sariff /* Flush caches */ 1676162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1677162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1678169277Sariff#endif 1679162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1680167773Sariff } 1681167773Sariff if (dma->dma_vaddr != NULL) { 1682162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1683167773Sariff dma->dma_vaddr = NULL; 1684167773Sariff } 1685167773Sariff dma->dma_map = NULL; 1686167773Sariff if (dma->dma_tag != NULL) { 1687162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1688167773Sariff dma->dma_tag = NULL; 1689162922Sariff } 1690167773Sariff dma->dma_size = 0; 1691162922Sariff} 1692162922Sariff 1693162922Sariff/**************************************************************************** 1694162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1695162922Sariff * 1696162922Sariff * Allocate all the bus resources necessary to speak with the physical 1697162922Sariff * controller. 1698162922Sariff ****************************************************************************/ 1699162922Sariffstatic int 1700162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1701162922Sariff{ 1702162922Sariff struct hdac_mem *mem; 1703162922Sariff 1704162922Sariff mem = &sc->mem; 1705162922Sariff mem->mem_rid = PCIR_BAR(0); 1706162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1707162922Sariff &mem->mem_rid, RF_ACTIVE); 1708162922Sariff if (mem->mem_res == NULL) { 1709162922Sariff device_printf(sc->dev, 1710162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1711162922Sariff return (ENOMEM); 1712162922Sariff } 1713162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1714162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1715162922Sariff 1716162922Sariff return (0); 1717162922Sariff} 1718162922Sariff 1719162922Sariff/**************************************************************************** 1720162922Sariff * void hdac_mem_free(struct hdac_softc *) 1721162922Sariff * 1722162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1723162922Sariff ****************************************************************************/ 1724162922Sariffstatic void 1725162922Sariffhdac_mem_free(struct hdac_softc *sc) 1726162922Sariff{ 1727162922Sariff struct hdac_mem *mem; 1728162922Sariff 1729162922Sariff mem = &sc->mem; 1730162922Sariff if (mem->mem_res != NULL) 1731162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1732162922Sariff mem->mem_res); 1733164614Sariff mem->mem_res = NULL; 1734162922Sariff} 1735162922Sariff 1736162922Sariff/**************************************************************************** 1737162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1738162922Sariff * 1739162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1740162922Sariff ****************************************************************************/ 1741162922Sariffstatic int 1742162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1743162922Sariff{ 1744162922Sariff struct hdac_irq *irq; 1745162922Sariff int result; 1746162922Sariff 1747162922Sariff irq = &sc->irq; 1748162922Sariff irq->irq_rid = 0x0; 1749171330Sariff 1750171330Sariff if ((sc->flags & HDAC_F_MSI) && 1751171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1752171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1753171330Sariff irq->irq_rid = 0x1; 1754171330Sariff else 1755171330Sariff sc->flags &= ~HDAC_F_MSI; 1756171330Sariff 1757162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1758162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1759162922Sariff if (irq->irq_res == NULL) { 1760162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1761162922Sariff __func__); 1762167773Sariff goto hdac_irq_alloc_fail; 1763162922Sariff } 1764182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1765182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1766162922Sariff if (result != 0) { 1767162922Sariff device_printf(sc->dev, 1768162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1769162922Sariff __func__, result); 1770167773Sariff goto hdac_irq_alloc_fail; 1771162922Sariff } 1772162922Sariff 1773162922Sariff return (0); 1774162922Sariff 1775167773Sariffhdac_irq_alloc_fail: 1776164614Sariff hdac_irq_free(sc); 1777164614Sariff 1778162922Sariff return (ENXIO); 1779162922Sariff} 1780162922Sariff 1781162922Sariff/**************************************************************************** 1782162922Sariff * void hdac_irq_free(struct hdac_softc *) 1783162922Sariff * 1784162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1785162922Sariff ****************************************************************************/ 1786162922Sariffstatic void 1787162922Sariffhdac_irq_free(struct hdac_softc *sc) 1788162922Sariff{ 1789162922Sariff struct hdac_irq *irq; 1790162922Sariff 1791162922Sariff irq = &sc->irq; 1792164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1793162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1794162922Sariff if (irq->irq_res != NULL) 1795162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1796162922Sariff irq->irq_res); 1797188656Smav if (irq->irq_rid == 0x1) 1798171330Sariff pci_release_msi(sc->dev); 1799164614Sariff irq->irq_handle = NULL; 1800164614Sariff irq->irq_res = NULL; 1801171330Sariff irq->irq_rid = 0x0; 1802162922Sariff} 1803162922Sariff 1804162922Sariff/**************************************************************************** 1805162922Sariff * void hdac_corb_init(struct hdac_softc *) 1806162922Sariff * 1807162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1808162922Sariff * The CORB engine must not be running when this function is called. 1809162922Sariff ****************************************************************************/ 1810162922Sariffstatic void 1811162922Sariffhdac_corb_init(struct hdac_softc *sc) 1812162922Sariff{ 1813162922Sariff uint8_t corbsize; 1814162922Sariff uint64_t corbpaddr; 1815162922Sariff 1816162922Sariff /* Setup the CORB size. */ 1817162922Sariff switch (sc->corb_size) { 1818162922Sariff case 256: 1819162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1820162922Sariff break; 1821162922Sariff case 16: 1822162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1823162922Sariff break; 1824162922Sariff case 2: 1825162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1826162922Sariff break; 1827162922Sariff default: 1828162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1829162922Sariff } 1830162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1831162922Sariff 1832162922Sariff /* Setup the CORB Address in the hdac */ 1833162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1834162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1835162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1836162922Sariff 1837162922Sariff /* Set the WP and RP */ 1838162922Sariff sc->corb_wp = 0; 1839162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1840162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1841162922Sariff /* 1842162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1843162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1844162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1845162922Sariff * manually reset the bit to zero before continuing. 1846162922Sariff */ 1847162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1848162922Sariff 1849162922Sariff /* Enable CORB error reporting */ 1850162922Sariff#if 0 1851162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1852162922Sariff#endif 1853162922Sariff} 1854162922Sariff 1855162922Sariff/**************************************************************************** 1856162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1857162922Sariff * 1858162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1859162922Sariff * The RIRB engine must not be running when this function is called. 1860162922Sariff ****************************************************************************/ 1861162922Sariffstatic void 1862162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1863162922Sariff{ 1864162922Sariff uint8_t rirbsize; 1865162922Sariff uint64_t rirbpaddr; 1866162922Sariff 1867162922Sariff /* Setup the RIRB size. */ 1868162922Sariff switch (sc->rirb_size) { 1869162922Sariff case 256: 1870162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1871162922Sariff break; 1872162922Sariff case 16: 1873162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1874162922Sariff break; 1875162922Sariff case 2: 1876162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1877162922Sariff break; 1878162922Sariff default: 1879162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1880162922Sariff } 1881162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1882162922Sariff 1883162922Sariff /* Setup the RIRB Address in the hdac */ 1884162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1885162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1886162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1887162922Sariff 1888162922Sariff /* Setup the WP and RP */ 1889162922Sariff sc->rirb_rp = 0; 1890162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1891162922Sariff 1892182999Smav /* Setup the interrupt threshold */ 1893182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1894162922Sariff 1895182999Smav /* Enable Overrun and response received reporting */ 1896162922Sariff#if 0 1897182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1898182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1899162922Sariff#else 1900182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1901162922Sariff#endif 1902162922Sariff 1903169277Sariff#if 0 1904162922Sariff /* 1905162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1906162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1907162922Sariff * should be sufficient to do this only once as the rirb is purely 1908162922Sariff * read-only from now on. 1909162922Sariff */ 1910162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1911162922Sariff BUS_DMASYNC_PREREAD); 1912169277Sariff#endif 1913162922Sariff} 1914162922Sariff 1915162922Sariff/**************************************************************************** 1916162922Sariff * void hdac_corb_start(hdac_softc *) 1917162922Sariff * 1918162922Sariff * Startup the corb DMA engine 1919162922Sariff ****************************************************************************/ 1920162922Sariffstatic void 1921162922Sariffhdac_corb_start(struct hdac_softc *sc) 1922162922Sariff{ 1923162922Sariff uint32_t corbctl; 1924162922Sariff 1925162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1926162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1927162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1928162922Sariff} 1929162922Sariff 1930162922Sariff/**************************************************************************** 1931162922Sariff * void hdac_rirb_start(hdac_softc *) 1932162922Sariff * 1933162922Sariff * Startup the rirb DMA engine 1934162922Sariff ****************************************************************************/ 1935162922Sariffstatic void 1936162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1937162922Sariff{ 1938162922Sariff uint32_t rirbctl; 1939162922Sariff 1940162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1941162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1942162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1943162922Sariff} 1944162922Sariff 1945162922Sariff 1946162922Sariff/**************************************************************************** 1947172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 1948162922Sariff * 1949172811Sariff * Scan the bus for available codecs, starting with num. 1950162922Sariff ****************************************************************************/ 1951162922Sariffstatic void 1952182999Smavhdac_scan_codecs(struct hdac_softc *sc) 1953162922Sariff{ 1954162922Sariff struct hdac_codec *codec; 1955162922Sariff int i; 1956162922Sariff uint16_t statests; 1957162922Sariff 1958162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1959182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1960162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1961162922Sariff /* We have found a codec. */ 1962162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1963162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1964162922Sariff if (codec == NULL) { 1965162922Sariff device_printf(sc->dev, 1966162922Sariff "Unable to allocate memory for codec\n"); 1967162922Sariff continue; 1968162922Sariff } 1969164614Sariff codec->commands = NULL; 1970164614Sariff codec->responses_received = 0; 1971162922Sariff codec->verbs_sent = 0; 1972162922Sariff codec->sc = sc; 1973162922Sariff codec->cad = i; 1974162922Sariff sc->codecs[i] = codec; 1975182999Smav hdac_probe_codec(codec); 1976162922Sariff } 1977162922Sariff } 1978162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1979163057Sariff /* bus_generic_attach(sc->dev); */ 1980162922Sariff} 1981162922Sariff 1982162922Sariff/**************************************************************************** 1983162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1984162922Sariff * 1985162922Sariff * Probe a the given codec_id for available function groups. 1986162922Sariff ****************************************************************************/ 1987182999Smavstatic void 1988162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1989162922Sariff{ 1990162922Sariff struct hdac_softc *sc = codec->sc; 1991162922Sariff uint32_t vendorid, revisionid, subnode; 1992162922Sariff int startnode; 1993162922Sariff int endnode; 1994162922Sariff int i; 1995162922Sariff nid_t cad = codec->cad; 1996162922Sariff 1997163057Sariff HDA_BOOTVERBOSE( 1998184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 1999162922Sariff ); 2000162922Sariff vendorid = hdac_command(sc, 2001162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 2002162922Sariff cad); 2003162922Sariff revisionid = hdac_command(sc, 2004162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 2005162922Sariff cad); 2006182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 2007182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 2008182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 2009182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 2010182999Smav 2011182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 2012182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 2013182999Smav " Probing aborted.\n", cad); 2014182999Smav return; 2015182999Smav } 2016182999Smav 2017184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 2018182999Smav cad, hdac_codec_name(codec)); 2019182999Smav HDA_BOOTVERBOSE( 2020184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 2021182999Smav hdac_codec_id(codec)); 2022182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 2023182999Smav codec->vendor_id); 2024182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 2025182999Smav codec->device_id); 2026182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 2027182999Smav codec->revision_id); 2028182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 2029182999Smav codec->stepping_id); 2030182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2031182999Smav sc->pci_subvendor); 2032182999Smav ); 2033162922Sariff subnode = hdac_command(sc, 2034162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 2035162922Sariff cad); 2036162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 2037162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 2038162922Sariff 2039183097Smav HDA_BOOTHVERBOSE( 2040182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 2041163057Sariff startnode, endnode); 2042162922Sariff ); 2043182999Smav 2044182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 2045182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 2046182999Smav if (codec->fgs == NULL) { 2047183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 2048182999Smav __func__); 2049182999Smav return; 2050162922Sariff } 2051162922Sariff 2052182999Smav for (i = startnode; i < endnode; i++) 2053182999Smav hdac_probe_function(codec, i); 2054182999Smav return; 2055162922Sariff} 2056162922Sariff 2057182999Smav/* 2058182999Smav * Probe codec function and add it to the list. 2059182999Smav */ 2060182999Smavstatic void 2061162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 2062162922Sariff{ 2063162922Sariff struct hdac_softc *sc = codec->sc; 2064182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 2065162922Sariff uint32_t fctgrptype; 2066182999Smav uint32_t res; 2067162922Sariff nid_t cad = codec->cad; 2068162922Sariff 2069162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 2070162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 2071162922Sariff 2072162922Sariff devinfo->nid = nid; 2073162965Sariff devinfo->node_type = fctgrptype; 2074162922Sariff devinfo->codec = codec; 2075162922Sariff 2076182999Smav res = hdac_command(sc, 2077182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2078162922Sariff 2079182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2080182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2081182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2082162922Sariff 2083182999Smav HDA_BOOTVERBOSE( 2084182999Smav device_printf(sc->dev, 2085182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2086182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2087182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2088182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2089182999Smav devinfo->nodecnt); 2090182999Smav ); 2091182999Smav 2092182999Smav if (devinfo->nodecnt > 0) 2093182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2094182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2095182999Smav M_NOWAIT | M_ZERO); 2096182999Smav else 2097182999Smav devinfo->widget = NULL; 2098182999Smav 2099182999Smav if (devinfo->widget == NULL) { 2100182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2101182999Smav devinfo->endnode = devinfo->startnode; 2102182999Smav devinfo->nodecnt = 0; 2103182999Smav return; 2104182999Smav } 2105182999Smav 2106182999Smav codec->num_fgs++; 2107162922Sariff} 2108162922Sariff 2109162922Sariffstatic void 2110162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2111162922Sariff{ 2112162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2113162922Sariff uint32_t res; 2114169277Sariff int i, j, max, ents, entnum; 2115162922Sariff nid_t cad = w->devinfo->codec->cad; 2116162922Sariff nid_t nid = w->nid; 2117169277Sariff nid_t cnid, addcnid, prevcnid; 2118162922Sariff 2119169277Sariff w->nconns = 0; 2120169277Sariff 2121162922Sariff res = hdac_command(sc, 2122162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2123162922Sariff 2124169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2125162922Sariff 2126169277Sariff if (ents < 1) 2127162922Sariff return; 2128162922Sariff 2129162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2130162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2131169277Sariff prevcnid = 0; 2132162922Sariff 2133169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2134169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2135169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2136169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2137169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2138169277Sariff 2139169277Sariff for (i = 0; i < ents; i += entnum) { 2140162922Sariff res = hdac_command(sc, 2141162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2142162922Sariff for (j = 0; j < entnum; j++) { 2143169277Sariff cnid = CONN_CNID(res, entnum, j); 2144169277Sariff if (cnid == 0) { 2145169277Sariff if (w->nconns < ents) 2146169277Sariff device_printf(sc->dev, 2147169277Sariff "%s: nid=%d WARNING: zero cnid " 2148169277Sariff "entnum=%d j=%d index=%d " 2149169277Sariff "entries=%d found=%d res=0x%08x\n", 2150169277Sariff __func__, nid, entnum, j, i, 2151169277Sariff ents, w->nconns, res); 2152169277Sariff else 2153169277Sariff goto getconns_out; 2154169277Sariff } 2155169277Sariff if (cnid < w->devinfo->startnode || 2156169277Sariff cnid >= w->devinfo->endnode) { 2157169277Sariff HDA_BOOTVERBOSE( 2158169277Sariff device_printf(sc->dev, 2159182999Smav "GHOST: nid=%d j=%d " 2160169277Sariff "entnum=%d index=%d res=0x%08x\n", 2161182999Smav nid, j, entnum, i, res); 2162169277Sariff ); 2163169277Sariff } 2164169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2165169277Sariff addcnid = cnid; 2166169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2167162922Sariff device_printf(sc->dev, 2168169277Sariff "%s: WARNING: Invalid child range " 2169169277Sariff "nid=%d index=%d j=%d entnum=%d " 2170169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2171169277Sariff __func__, nid, i, j, entnum, prevcnid, 2172169277Sariff cnid, res); 2173169277Sariff addcnid = cnid; 2174169277Sariff } else 2175169277Sariff addcnid = prevcnid + 1; 2176169277Sariff while (addcnid <= cnid) { 2177169277Sariff if (w->nconns > max) { 2178169277Sariff device_printf(sc->dev, 2179182999Smav "Adding %d (nid=%d): " 2180169277Sariff "Max connection reached! max=%d\n", 2181182999Smav addcnid, nid, max + 1); 2182169277Sariff goto getconns_out; 2183169277Sariff } 2184182999Smav w->connsenable[w->nconns] = 1; 2185169277Sariff w->conns[w->nconns++] = addcnid++; 2186162922Sariff } 2187169277Sariff prevcnid = cnid; 2188162922Sariff } 2189162922Sariff } 2190162922Sariff 2191169277Sariffgetconns_out: 2192169277Sariff return; 2193162922Sariff} 2194162922Sariff 2195162922Sariffstatic uint32_t 2196182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2197182999Smav{ 2198182999Smav char buf[256]; 2199182999Smav char *key, *value, *rest, *bad; 2200182999Smav int ival, i; 2201182999Smav 2202182999Smav strlcpy(buf, str, sizeof(buf)); 2203182999Smav rest = buf; 2204182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2205182999Smav value = strsep(&rest, " \t"); 2206182999Smav if (value == NULL) 2207182999Smav break; 2208182999Smav ival = strtol(value, &bad, 10); 2209182999Smav if (strcmp(key, "seq") == 0) { 2210182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2211182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2212182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2213182999Smav } else if (strcmp(key, "as") == 0) { 2214182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2215182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2216182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2217182999Smav } else if (strcmp(key, "misc") == 0) { 2218182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2219182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2220182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2221182999Smav } else if (strcmp(key, "color") == 0) { 2222182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2223182999Smav if (bad[0] == 0) { 2224182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2225182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2226182999Smav }; 2227182999Smav for (i = 0; i < 16; i++) { 2228182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2229182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2230182999Smav break; 2231182999Smav } 2232182999Smav } 2233182999Smav } else if (strcmp(key, "ctype") == 0) { 2234182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2235182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2236182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2237182999Smav } else if (strcmp(key, "device") == 0) { 2238182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2239182999Smav if (bad[0] == 0) { 2240182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2241182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2242182999Smav continue; 2243182999Smav }; 2244182999Smav for (i = 0; i < 16; i++) { 2245182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2246182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2247182999Smav break; 2248182999Smav } 2249182999Smav } 2250182999Smav } else if (strcmp(key, "loc") == 0) { 2251182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2252182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2253182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2254182999Smav } else if (strcmp(key, "conn") == 0) { 2255182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2256182999Smav if (bad[0] == 0) { 2257182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2258182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2259182999Smav continue; 2260182999Smav }; 2261182999Smav for (i = 0; i < 4; i++) { 2262182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2263182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2264182999Smav break; 2265182999Smav } 2266182999Smav } 2267182999Smav } 2268182999Smav } 2269182999Smav return (config); 2270182999Smav} 2271182999Smav 2272182999Smavstatic uint32_t 2273162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2274162922Sariff{ 2275162922Sariff struct hdac_softc *sc; 2276166965Sariff uint32_t config, orig, id; 2277162922Sariff nid_t cad, nid; 2278182999Smav char buf[32]; 2279182999Smav const char *res = NULL, *patch = NULL; 2280162922Sariff 2281162922Sariff sc = w->devinfo->codec->sc; 2282162922Sariff cad = w->devinfo->codec->cad; 2283162922Sariff nid = w->nid; 2284182999Smav id = hdac_codec_id(w->devinfo->codec); 2285162922Sariff 2286162922Sariff config = hdac_command(sc, 2287162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2288162922Sariff cad); 2289166965Sariff orig = config; 2290166965Sariff 2291182999Smav HDA_BOOTVERBOSE( 2292182999Smav hdac_dump_pin_config(w, orig); 2293182999Smav ); 2294182999Smav 2295182999Smav /* XXX: Old patches require complete review. 2296182999Smav * Now they may create more problem then solve due to 2297182999Smav * incorrect associations. 2298162965Sariff */ 2299165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2300165281Sariff switch (nid) { 2301165281Sariff case 26: 2302165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2303165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2304165281Sariff break; 2305165281Sariff case 27: 2306165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2307165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2308165281Sariff break; 2309167610Sariff default: 2310167610Sariff break; 2311165281Sariff } 2312165281Sariff } else if (id == HDA_CODEC_ALC880 && 2313162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2314162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2315162922Sariff /* 2316162965Sariff * Super broken BIOS 2317162922Sariff */ 2318162922Sariff switch (nid) { 2319162922Sariff case 24: /* MIC1 */ 2320162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2321162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2322162922Sariff break; 2323162922Sariff case 25: /* XXX MIC2 */ 2324162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2325162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2326162922Sariff break; 2327162922Sariff case 26: /* LINE1 */ 2328162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2329162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2330162922Sariff break; 2331162922Sariff case 27: /* XXX LINE2 */ 2332162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2333162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2334162922Sariff break; 2335162922Sariff case 28: /* CD */ 2336162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2337162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2338162922Sariff break; 2339162922Sariff } 2340166965Sariff } else if (id == HDA_CODEC_ALC883 && 2341172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2342172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2343166965Sariff switch (nid) { 2344166965Sariff case 25: 2345166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2346166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2347166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2348166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2349166965Sariff break; 2350169277Sariff case 28: 2351169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2352169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2353169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2354169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2355169277Sariff break; 2356166965Sariff } 2357186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2358166965Sariff HP_V3000_SUBVENDOR) { 2359166965Sariff switch (nid) { 2360166965Sariff case 18: 2361166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2362166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2363166965Sariff break; 2364166965Sariff case 20: 2365166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2366166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2367166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2368166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2369166965Sariff break; 2370167454Sariff case 21: 2371167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2372167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2373167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2374167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2375167454Sariff break; 2376166965Sariff } 2377186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2378169277Sariff HP_DV5000_SUBVENDOR) { 2379169277Sariff switch (nid) { 2380169277Sariff case 20: 2381169277Sariff case 21: 2382169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2383169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2384169277Sariff break; 2385169277Sariff } 2386169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2387169277Sariff ASUS_W6F_SUBVENDOR) { 2388169277Sariff switch (nid) { 2389169277Sariff case 11: 2390169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2391169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2392169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2393169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2394169277Sariff break; 2395178324Sariff case 12: 2396178324Sariff case 14: 2397178324Sariff case 16: 2398178324Sariff case 31: 2399178324Sariff case 32: 2400178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2401178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2402178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2403178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2404178324Sariff break; 2405169277Sariff case 15: 2406169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2407169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2408169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2409169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2410169277Sariff break; 2411169277Sariff } 2412169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2413169277Sariff UNIWILL_9075_SUBVENDOR) { 2414169277Sariff switch (nid) { 2415169277Sariff case 15: 2416169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2417169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2418169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2419169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2420169277Sariff break; 2421169277Sariff } 2422182999Smav } 2423182999Smav 2424182999Smav /* New patches */ 2425182999Smav if (id == HDA_CODEC_AD1986A && 2426171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2427171141Sariff sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) { 2428169277Sariff switch (nid) { 2429182999Smav case 28: /* 5.1 out => 2.0 out + 2 inputs */ 2430182999Smav patch = "device=Line-in as=8 seq=1"; 2431169277Sariff break; 2432182999Smav case 29: 2433182999Smav patch = "device=Mic as=8 seq=2"; 2434169277Sariff break; 2435182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2436182999Smav patch = "as=8 seq=3"; 2437169277Sariff break; 2438182999Smav case 32: 2439182999Smav patch = "as=8 seq=4"; 2440182999Smav break; 2441182999Smav case 34: 2442182999Smav patch = "as=8 seq=5"; 2443182999Smav break; 2444182999Smav case 36: 2445182999Smav patch = "as=8 seq=6"; 2446182999Smav break; 2447169277Sariff } 2448182999Smav } else if (id == HDA_CODEC_ALC260 && 2449182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2450182999Smav switch (nid) { 2451182999Smav case 16: 2452182999Smav patch = "seq=15 device=Headphones"; 2453182999Smav break; 2454182999Smav } 2455174578Sariff } else if (id == HDA_CODEC_ALC268 && 2456174578Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) { 2457174578Sariff switch (nid) { 2458174578Sariff case 28: 2459182999Smav patch = "device=CD conn=fixed"; 2460174578Sariff break; 2461174578Sariff } 2462162922Sariff } 2463162922Sariff 2464182999Smav if (patch != NULL) 2465182999Smav config = hdac_widget_pin_patch(config, patch); 2466182999Smav 2467182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2468182999Smav if (resource_string_value(device_get_name(sc->dev), 2469182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2470182999Smav if (strncmp(res, "0x", 2) == 0) { 2471182999Smav config = strtol(res + 2, NULL, 16); 2472182999Smav } else { 2473182999Smav config = hdac_widget_pin_patch(config, res); 2474182999Smav } 2475182999Smav } 2476182999Smav 2477166965Sariff HDA_BOOTVERBOSE( 2478166965Sariff if (config != orig) 2479166965Sariff device_printf(sc->dev, 2480182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2481166965Sariff nid, orig, config); 2482166965Sariff ); 2483166965Sariff 2484162922Sariff return (config); 2485162922Sariff} 2486162922Sariff 2487166965Sariffstatic uint32_t 2488166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2489166965Sariff{ 2490166965Sariff struct hdac_softc *sc; 2491166965Sariff uint32_t caps, orig, id; 2492166965Sariff nid_t cad, nid; 2493166965Sariff 2494166965Sariff sc = w->devinfo->codec->sc; 2495166965Sariff cad = w->devinfo->codec->cad; 2496166965Sariff nid = w->nid; 2497182999Smav id = hdac_codec_id(w->devinfo->codec); 2498166965Sariff 2499166965Sariff caps = hdac_command(sc, 2500166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2501166965Sariff orig = caps; 2502166965Sariff 2503166965Sariff HDA_BOOTVERBOSE( 2504166965Sariff if (caps != orig) 2505166965Sariff device_printf(sc->dev, 2506182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2507166965Sariff nid, orig, caps); 2508166965Sariff ); 2509166965Sariff 2510166965Sariff return (caps); 2511166965Sariff} 2512166965Sariff 2513162922Sariffstatic void 2514162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2515162922Sariff{ 2516162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2517162922Sariff uint32_t config, pincap; 2518186912Smav const char *devstr; 2519162922Sariff nid_t cad = w->devinfo->codec->cad; 2520162922Sariff nid_t nid = w->nid; 2521186912Smav int conn, color; 2522162922Sariff 2523162922Sariff config = hdac_widget_pin_getconfig(w); 2524162922Sariff w->wclass.pin.config = config; 2525162922Sariff 2526166965Sariff pincap = hdac_widget_pin_getcaps(w); 2527162922Sariff w->wclass.pin.cap = pincap; 2528162922Sariff 2529162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2530182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2531162922Sariff 2532162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2533162922Sariff w->param.eapdbtl = hdac_command(sc, 2534162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2535162922Sariff w->param.eapdbtl &= 0x7; 2536162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2537162922Sariff } else 2538162965Sariff w->param.eapdbtl = HDAC_INVALID; 2539162922Sariff 2540182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2541182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2542162922Sariff 2543186912Smav conn = (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2544186912Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT; 2545186912Smav color = (config & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> 2546186912Smav HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT; 2547162922Sariff 2548162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2549162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2550162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2551186912Smav if (conn == 0 && color != 0 && color != 15) { 2552186912Smav strlcat(w->name, HDA_COLORS[color], sizeof(w->name)); 2553186912Smav strlcat(w->name, " ", sizeof(w->name)); 2554186912Smav } 2555186912Smav strlcat(w->name, HDA_CONNS[conn], sizeof(w->name)); 2556162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2557162922Sariff} 2558162922Sariff 2559182999Smavstatic uint32_t 2560182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2561182999Smav{ 2562182999Smav struct hdac_softc *sc; 2563182999Smav uint32_t caps, orig, id; 2564182999Smav nid_t cad, nid, beeper = -1; 2565182999Smav 2566182999Smav sc = w->devinfo->codec->sc; 2567182999Smav cad = w->devinfo->codec->cad; 2568182999Smav nid = w->nid; 2569182999Smav id = hdac_codec_id(w->devinfo->codec); 2570182999Smav 2571182999Smav caps = hdac_command(sc, 2572182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2573182999Smav cad); 2574182999Smav orig = caps; 2575182999Smav 2576182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2577182999Smav alone. Also most of BIOSes does not declare beeper pin. 2578182999Smav Change beeper pin node type to beeper to help parser. */ 2579182999Smav *waspin = 0; 2580182999Smav switch (id) { 2581187721Smav case HDA_CODEC_AD1882: 2582187721Smav case HDA_CODEC_AD1883: 2583187721Smav case HDA_CODEC_AD1984: 2584187721Smav case HDA_CODEC_AD1984A: 2585187721Smav case HDA_CODEC_AD1984B: 2586187721Smav case HDA_CODEC_AD1987: 2587182999Smav case HDA_CODEC_AD1988: 2588182999Smav case HDA_CODEC_AD1988B: 2589187721Smav case HDA_CODEC_AD1989B: 2590182999Smav beeper = 26; 2591182999Smav break; 2592182999Smav case HDA_CODEC_ALC260: 2593182999Smav beeper = 23; 2594182999Smav break; 2595182999Smav case HDA_CODEC_ALC262: 2596182999Smav case HDA_CODEC_ALC268: 2597182999Smav case HDA_CODEC_ALC880: 2598182999Smav case HDA_CODEC_ALC882: 2599182999Smav case HDA_CODEC_ALC883: 2600182999Smav case HDA_CODEC_ALC885: 2601182999Smav case HDA_CODEC_ALC888: 2602182999Smav case HDA_CODEC_ALC889: 2603182999Smav beeper = 29; 2604182999Smav break; 2605182999Smav } 2606182999Smav if (nid == beeper) { 2607182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2608182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2609182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2610182999Smav *waspin = 1; 2611182999Smav } 2612182999Smav 2613182999Smav HDA_BOOTVERBOSE( 2614182999Smav if (caps != orig) { 2615182999Smav device_printf(sc->dev, 2616182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2617182999Smav nid, orig, caps); 2618182999Smav } 2619182999Smav ); 2620182999Smav 2621182999Smav return (caps); 2622182999Smav} 2623182999Smav 2624162922Sariffstatic void 2625162922Sariffhdac_widget_parse(struct hdac_widget *w) 2626162922Sariff{ 2627162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2628162922Sariff uint32_t wcap, cap; 2629162922Sariff char *typestr; 2630162922Sariff nid_t cad = w->devinfo->codec->cad; 2631162922Sariff nid_t nid = w->nid; 2632162922Sariff 2633182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2634182999Smav 2635162922Sariff w->param.widget_cap = wcap; 2636162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2637162922Sariff 2638162922Sariff switch (w->type) { 2639162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2640162922Sariff typestr = "audio output"; 2641162922Sariff break; 2642162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2643162922Sariff typestr = "audio input"; 2644162922Sariff break; 2645162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2646162922Sariff typestr = "audio mixer"; 2647162922Sariff break; 2648162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2649162922Sariff typestr = "audio selector"; 2650162922Sariff break; 2651162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2652162922Sariff typestr = "pin"; 2653162922Sariff break; 2654162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2655162922Sariff typestr = "power widget"; 2656162922Sariff break; 2657162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2658162922Sariff typestr = "volume widget"; 2659162922Sariff break; 2660162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2661162922Sariff typestr = "beep widget"; 2662162922Sariff break; 2663162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2664162922Sariff typestr = "vendor widget"; 2665162922Sariff break; 2666162922Sariff default: 2667162922Sariff typestr = "unknown type"; 2668162922Sariff break; 2669162922Sariff } 2670162922Sariff 2671162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2672162922Sariff 2673162922Sariff hdac_widget_connection_parse(w); 2674162922Sariff 2675162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2676162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2677162922Sariff w->param.outamp_cap = 2678162922Sariff hdac_command(sc, 2679162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2680162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2681162922Sariff else 2682162922Sariff w->param.outamp_cap = 2683162922Sariff w->devinfo->function.audio.outamp_cap; 2684162922Sariff } else 2685162922Sariff w->param.outamp_cap = 0; 2686162922Sariff 2687162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2688162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2689162922Sariff w->param.inamp_cap = 2690162922Sariff hdac_command(sc, 2691162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2692162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2693162922Sariff else 2694162922Sariff w->param.inamp_cap = 2695162922Sariff w->devinfo->function.audio.inamp_cap; 2696162922Sariff } else 2697162922Sariff w->param.inamp_cap = 0; 2698162922Sariff 2699162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2700162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2701162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2702162922Sariff cap = hdac_command(sc, 2703162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2704162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2705162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2706162922Sariff w->devinfo->function.audio.supp_stream_formats; 2707162922Sariff cap = hdac_command(sc, 2708162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2709162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2710162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2711162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2712162922Sariff } else { 2713162922Sariff w->param.supp_stream_formats = 2714162922Sariff w->devinfo->function.audio.supp_stream_formats; 2715162922Sariff w->param.supp_pcm_size_rate = 2716162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2717162922Sariff } 2718162922Sariff } else { 2719162922Sariff w->param.supp_stream_formats = 0; 2720162922Sariff w->param.supp_pcm_size_rate = 0; 2721162922Sariff } 2722162922Sariff 2723162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2724162922Sariff hdac_widget_pin_parse(w); 2725162922Sariff} 2726162922Sariff 2727162922Sariffstatic struct hdac_widget * 2728162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2729162922Sariff{ 2730162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2731162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2732162922Sariff return (NULL); 2733162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2734162922Sariff} 2735162922Sariff 2736164614Sariffstatic __inline int 2737164614Sariffhda_poll_channel(struct hdac_chan *ch) 2738164614Sariff{ 2739164614Sariff uint32_t sz, delta; 2740164614Sariff volatile uint32_t ptr; 2741164614Sariff 2742171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2743164614Sariff return (0); 2744164614Sariff 2745164614Sariff sz = ch->blksz * ch->blkcnt; 2746169277Sariff if (ch->dmapos != NULL) 2747169277Sariff ptr = *(ch->dmapos); 2748169277Sariff else 2749169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2750169277Sariff ch->off + HDAC_SDLPIB); 2751164614Sariff ch->ptr = ptr; 2752164614Sariff ptr %= sz; 2753164614Sariff ptr &= ~(ch->blksz - 1); 2754164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2755164614Sariff 2756164614Sariff if (delta < ch->blksz) 2757164614Sariff return (0); 2758164614Sariff 2759164614Sariff ch->prevptr = ptr; 2760164614Sariff 2761164614Sariff return (1); 2762164614Sariff} 2763164614Sariff 2764162922Sariffstatic void 2765164614Sariffhda_poll_callback(void *arg) 2766164614Sariff{ 2767164614Sariff struct hdac_softc *sc = arg; 2768171141Sariff uint32_t trigger; 2769182999Smav int i, active = 0; 2770164614Sariff 2771164614Sariff if (sc == NULL) 2772164614Sariff return; 2773164614Sariff 2774164614Sariff hdac_lock(sc); 2775182999Smav if (sc->polling == 0) { 2776164614Sariff hdac_unlock(sc); 2777164614Sariff return; 2778164614Sariff } 2779164614Sariff 2780171141Sariff trigger = 0; 2781182999Smav for (i = 0; i < sc->num_chans; i++) { 2782182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2783182999Smav continue; 2784182999Smav active = 1; 2785182999Smav if (hda_poll_channel(&sc->chans[i])) 2786182999Smav trigger |= (1 << i); 2787182999Smav } 2788164614Sariff 2789164614Sariff /* XXX */ 2790182999Smav if (active) 2791182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2792182999Smav hda_poll_callback, sc); 2793164614Sariff 2794164614Sariff hdac_unlock(sc); 2795164614Sariff 2796182999Smav for (i = 0; i < sc->num_chans; i++) { 2797182999Smav if (trigger & (1 << i)) 2798182999Smav chn_intr(sc->chans[i].c); 2799182999Smav } 2800164614Sariff} 2801164614Sariff 2802164614Sariffstatic int 2803164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2804164614Sariff{ 2805164614Sariff struct hdac_rirb *rirb_base, *rirb; 2806164614Sariff struct hdac_codec *codec; 2807164614Sariff struct hdac_command_list *commands; 2808164614Sariff nid_t cad; 2809164614Sariff uint32_t resp; 2810164614Sariff uint8_t rirbwp; 2811171141Sariff int ret; 2812164614Sariff 2813164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2814164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2815169277Sariff#if 0 2816164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2817164614Sariff BUS_DMASYNC_POSTREAD); 2818169277Sariff#endif 2819164614Sariff 2820171141Sariff ret = 0; 2821171141Sariff 2822164614Sariff while (sc->rirb_rp != rirbwp) { 2823164614Sariff sc->rirb_rp++; 2824164614Sariff sc->rirb_rp %= sc->rirb_size; 2825164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2826164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2827164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2828164614Sariff sc->codecs[cad] == NULL) 2829164614Sariff continue; 2830164614Sariff resp = rirb->response; 2831164614Sariff codec = sc->codecs[cad]; 2832164614Sariff commands = codec->commands; 2833164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2834164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2835164614Sariff ((resp >> 26) & 0xffff); 2836164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2837164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2838164614Sariff codec->responses_received < commands->num_commands) 2839164614Sariff commands->responses[codec->responses_received++] = 2840164614Sariff resp; 2841164614Sariff ret++; 2842164614Sariff } 2843164614Sariff 2844164614Sariff return (ret); 2845164614Sariff} 2846164614Sariff 2847164614Sariffstatic int 2848164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2849164614Sariff{ 2850164614Sariff nid_t cad; 2851164614Sariff uint32_t tag; 2852164614Sariff int ret = 0; 2853164614Sariff 2854164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2855164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2856164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2857164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2858164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2859164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2860164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2861164614Sariff ret++; 2862164614Sariff } 2863164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2864164614Sariff } 2865164614Sariff 2866164614Sariff return (ret); 2867164614Sariff} 2868164614Sariff 2869164614Sariffstatic void 2870164614Sariffhdac_poll_callback(void *arg) 2871164614Sariff{ 2872164614Sariff struct hdac_softc *sc = arg; 2873164614Sariff if (sc == NULL) 2874164614Sariff return; 2875166796Sariff 2876164614Sariff hdac_lock(sc); 2877169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2878164614Sariff hdac_unlock(sc); 2879164614Sariff return; 2880164614Sariff } 2881171141Sariff if (hdac_rirb_flush(sc) != 0) 2882171141Sariff hdac_unsolq_flush(sc); 2883169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2884164614Sariff hdac_unlock(sc); 2885164614Sariff} 2886164614Sariff 2887164614Sariffstatic void 2888182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2889182999Smav{ 2890182999Smav int i, pollticks, min = 1000000; 2891182999Smav struct hdac_chan *ch; 2892182999Smav 2893182999Smav for (i = 0; i < sc->num_chans; i++) { 2894182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2895182999Smav continue; 2896182999Smav ch = &sc->chans[i]; 2897182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2898182999Smav ((uint64_t)sndbuf_getbps(ch->b) * 2899182999Smav sndbuf_getspd(ch->b)); 2900182999Smav pollticks >>= 1; 2901182999Smav if (pollticks > hz) 2902182999Smav pollticks = hz; 2903182999Smav if (pollticks < 1) { 2904182999Smav HDA_BOOTVERBOSE( 2905182999Smav device_printf(sc->dev, 2906182999Smav "%s: pollticks=%d < 1 !\n", 2907182999Smav __func__, pollticks); 2908182999Smav ); 2909182999Smav pollticks = 1; 2910182999Smav } 2911182999Smav if (min > pollticks) 2912182999Smav min = pollticks; 2913182999Smav } 2914182999Smav HDA_BOOTVERBOSE( 2915182999Smav device_printf(sc->dev, 2916182999Smav "%s: pollticks %d -> %d\n", 2917182999Smav __func__, sc->poll_ticks, min); 2918182999Smav ); 2919182999Smav sc->poll_ticks = min; 2920182999Smav if (min == 1000000) 2921182999Smav callout_stop(&sc->poll_hda); 2922182999Smav else 2923182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 2924182999Smav} 2925182999Smav 2926182999Smavstatic void 2927162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2928162922Sariff{ 2929162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2930162922Sariff uint32_t ctl; 2931162922Sariff 2932162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2933162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2934162922Sariff HDAC_SDCTL_RUN); 2935162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2936162922Sariff 2937171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 2938164614Sariff 2939182999Smav if (sc->polling != 0) 2940182999Smav hdac_poll_reinit(sc); 2941164614Sariff 2942182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2943182999Smav ctl &= ~(1 << (ch->off >> 5)); 2944182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2945162922Sariff} 2946162922Sariff 2947162922Sariffstatic void 2948162922Sariffhdac_stream_start(struct hdac_chan *ch) 2949162922Sariff{ 2950162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2951162922Sariff uint32_t ctl; 2952162922Sariff 2953182999Smav ch->flags |= HDAC_CHN_RUNNING; 2954162922Sariff 2955182999Smav if (sc->polling != 0) 2956182999Smav hdac_poll_reinit(sc); 2957182999Smav 2958182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2959182999Smav ctl |= 1 << (ch->off >> 5); 2960182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2961182999Smav 2962182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2963182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2964182999Smav HDAC_SDCTL_RUN; 2965162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2966162922Sariff} 2967162922Sariff 2968162922Sariffstatic void 2969162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2970162922Sariff{ 2971162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2972162922Sariff int timeout = 1000; 2973162922Sariff int to = timeout; 2974162922Sariff uint32_t ctl; 2975162922Sariff 2976162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2977162922Sariff ctl |= HDAC_SDCTL_SRST; 2978162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2979162922Sariff do { 2980162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2981162922Sariff if (ctl & HDAC_SDCTL_SRST) 2982162922Sariff break; 2983162922Sariff DELAY(10); 2984162922Sariff } while (--to); 2985162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2986162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2987162922Sariff } 2988162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2989162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2990162922Sariff to = timeout; 2991162922Sariff do { 2992162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2993162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2994162922Sariff break; 2995162922Sariff DELAY(10); 2996162922Sariff } while (--to); 2997163057Sariff if (ctl & HDAC_SDCTL_SRST) 2998162922Sariff device_printf(sc->dev, "can't reset!\n"); 2999162922Sariff} 3000162922Sariff 3001162922Sariffstatic void 3002162922Sariffhdac_stream_setid(struct hdac_chan *ch) 3003162922Sariff{ 3004162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3005162922Sariff uint32_t ctl; 3006162922Sariff 3007162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 3008162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 3009162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 3010162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 3011162922Sariff} 3012162922Sariff 3013162922Sariffstatic void 3014162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 3015162922Sariff{ 3016162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3017164614Sariff struct hdac_bdle *bdle; 3018162922Sariff uint64_t addr; 3019164614Sariff uint32_t blksz, blkcnt; 3020162922Sariff int i; 3021162922Sariff 3022162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 3023164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 3024162922Sariff 3025182999Smav blksz = ch->blksz; 3026182999Smav blkcnt = ch->blkcnt; 3027164614Sariff 3028164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 3029162922Sariff bdle->addrl = (uint32_t)addr; 3030162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 3031164614Sariff bdle->len = blksz; 3032182999Smav bdle->ioc = 1; 3033164614Sariff addr += blksz; 3034162922Sariff } 3035162922Sariff 3036164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 3037164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 3038162922Sariff addr = ch->bdl_dma.dma_paddr; 3039162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 3040162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 3041169277Sariff if (ch->dmapos != NULL && 3042169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 3043169277Sariff addr = sc->pos_dma.dma_paddr; 3044169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 3045169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 3046169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 3047169277Sariff } 3048162922Sariff} 3049162922Sariff 3050162922Sariffstatic int 3051162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 3052162922Sariff{ 3053162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3054162922Sariff int rc; 3055162922Sariff 3056162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 3057162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 3058162922Sariff if (rc) { 3059162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 3060162922Sariff return (rc); 3061162922Sariff } 3062162922Sariff 3063162922Sariff return (0); 3064162922Sariff} 3065162922Sariff 3066162922Sariffstatic void 3067162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 3068162922Sariff int index, int lmute, int rmute, 3069162922Sariff int left, int right, int dir) 3070162922Sariff{ 3071162922Sariff uint16_t v = 0; 3072162922Sariff 3073162922Sariff if (sc == NULL) 3074162922Sariff return; 3075162922Sariff 3076162922Sariff if (left != right || lmute != rmute) { 3077162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 3078162922Sariff (lmute << 7) | left; 3079162922Sariff hdac_command(sc, 3080164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3081162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 3082162922Sariff (rmute << 7) | right; 3083162922Sariff } else 3084162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 3085162922Sariff (lmute << 7) | left; 3086162922Sariff 3087162922Sariff hdac_command(sc, 3088162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3089162922Sariff} 3090162922Sariff 3091162922Sariffstatic void 3092162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3093162922Sariff int left, int right) 3094162922Sariff{ 3095162922Sariff struct hdac_softc *sc; 3096162922Sariff nid_t nid, cad; 3097162922Sariff int lmute, rmute; 3098162922Sariff 3099162922Sariff sc = ctl->widget->devinfo->codec->sc; 3100162922Sariff cad = ctl->widget->devinfo->codec->cad; 3101162922Sariff nid = ctl->widget->nid; 3102162922Sariff 3103182999Smav /* Save new values if valid. */ 3104182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3105182999Smav ctl->muted = mute; 3106182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3107182999Smav ctl->left = left; 3108182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3109182999Smav ctl->right = right; 3110182999Smav /* Prepare effective values */ 3111182999Smav if (ctl->forcemute) { 3112182999Smav lmute = 1; 3113182999Smav rmute = 1; 3114182999Smav left = 0; 3115182999Smav right = 0; 3116182999Smav } else { 3117162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3118162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3119182999Smav left = ctl->left; 3120182999Smav right = ctl->right; 3121162922Sariff } 3122182999Smav /* Apply effective values */ 3123162922Sariff if (ctl->dir & HDA_CTL_OUT) 3124162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3125162922Sariff lmute, rmute, left, right, 0); 3126162922Sariff if (ctl->dir & HDA_CTL_IN) 3127182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3128162922Sariff lmute, rmute, left, right, 1); 3129162922Sariff} 3130162922Sariff 3131162922Sariffstatic void 3132162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3133162922Sariff{ 3134162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3135162922Sariff return; 3136162922Sariff hdac_command(w->devinfo->codec->sc, 3137162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3138162922Sariff w->nid, index), w->devinfo->codec->cad); 3139162922Sariff w->selconn = index; 3140162922Sariff} 3141162922Sariff 3142162922Sariff 3143162922Sariff/**************************************************************************** 3144162922Sariff * uint32_t hdac_command_sendone_internal 3145162922Sariff * 3146162922Sariff * Wrapper function that sends only one command to a given codec 3147162922Sariff ****************************************************************************/ 3148162922Sariffstatic uint32_t 3149162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3150162922Sariff{ 3151162922Sariff struct hdac_command_list cl; 3152162965Sariff uint32_t response = HDAC_INVALID; 3153162922Sariff 3154163057Sariff if (!hdac_lockowned(sc)) 3155162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3156162922Sariff cl.num_commands = 1; 3157162922Sariff cl.verbs = &verb; 3158162922Sariff cl.responses = &response; 3159162922Sariff 3160162922Sariff hdac_command_send_internal(sc, &cl, cad); 3161162922Sariff 3162162922Sariff return (response); 3163162922Sariff} 3164162922Sariff 3165162922Sariff/**************************************************************************** 3166162922Sariff * hdac_command_send_internal 3167162922Sariff * 3168162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3169162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3170162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3171162922Sariff * if any. 3172162922Sariff ****************************************************************************/ 3173162922Sariffstatic void 3174162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3175162922Sariff struct hdac_command_list *commands, nid_t cad) 3176162922Sariff{ 3177162922Sariff struct hdac_codec *codec; 3178162922Sariff int corbrp; 3179162922Sariff uint32_t *corb; 3180162922Sariff int timeout; 3181162922Sariff int retry = 10; 3182164614Sariff struct hdac_rirb *rirb_base; 3183162922Sariff 3184164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3185164614Sariff commands->num_commands < 1) 3186162922Sariff return; 3187162922Sariff 3188162922Sariff codec = sc->codecs[cad]; 3189162922Sariff codec->commands = commands; 3190162922Sariff codec->responses_received = 0; 3191162922Sariff codec->verbs_sent = 0; 3192162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3193162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3194162922Sariff 3195162922Sariff do { 3196162922Sariff if (codec->verbs_sent != commands->num_commands) { 3197162922Sariff /* Queue as many verbs as possible */ 3198162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3199169277Sariff#if 0 3200162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3201162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3202169277Sariff#endif 3203162922Sariff while (codec->verbs_sent != commands->num_commands && 3204162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3205162922Sariff sc->corb_wp++; 3206162922Sariff sc->corb_wp %= sc->corb_size; 3207162922Sariff corb[sc->corb_wp] = 3208162922Sariff commands->verbs[codec->verbs_sent++]; 3209162922Sariff } 3210162922Sariff 3211162922Sariff /* Send the verbs to the codecs */ 3212169277Sariff#if 0 3213162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3214162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3215169277Sariff#endif 3216162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3217162922Sariff } 3218162922Sariff 3219162922Sariff timeout = 1000; 3220164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3221162922Sariff DELAY(10); 3222162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3223164614Sariff codec->responses_received != commands->num_commands) && --retry); 3224162922Sariff 3225162922Sariff if (retry == 0) 3226162922Sariff device_printf(sc->dev, 3227164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3228164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3229164614Sariff codec->responses_received); 3230162922Sariff 3231164614Sariff codec->commands = NULL; 3232164614Sariff codec->responses_received = 0; 3233162922Sariff codec->verbs_sent = 0; 3234162922Sariff 3235164614Sariff hdac_unsolq_flush(sc); 3236162922Sariff} 3237162922Sariff 3238162922Sariff 3239162922Sariff/**************************************************************************** 3240162922Sariff * Device Methods 3241162922Sariff ****************************************************************************/ 3242162922Sariff 3243162922Sariff/**************************************************************************** 3244162922Sariff * int hdac_probe(device_t) 3245162922Sariff * 3246162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3247162922Sariff * match using the subclass of the device. 3248162922Sariff ****************************************************************************/ 3249162922Sariffstatic int 3250162922Sariffhdac_probe(device_t dev) 3251162922Sariff{ 3252162922Sariff int i, result; 3253163257Sariff uint32_t model; 3254163257Sariff uint16_t class, subclass; 3255162922Sariff char desc[64]; 3256162922Sariff 3257162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3258162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3259162922Sariff class = pci_get_class(dev); 3260162922Sariff subclass = pci_get_subclass(dev); 3261162922Sariff 3262162922Sariff bzero(desc, sizeof(desc)); 3263162922Sariff result = ENXIO; 3264162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3265162922Sariff if (hdac_devices[i].model == model) { 3266162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3267162922Sariff result = BUS_PROBE_DEFAULT; 3268162922Sariff break; 3269162922Sariff } 3270163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3271162922Sariff class == PCIC_MULTIMEDIA && 3272162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3273162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3274162922Sariff result = BUS_PROBE_GENERIC; 3275162922Sariff break; 3276162922Sariff } 3277162922Sariff } 3278162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3279162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3280162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3281162922Sariff result = BUS_PROBE_GENERIC; 3282162922Sariff } 3283162922Sariff if (result != ENXIO) { 3284162922Sariff strlcat(desc, " High Definition Audio Controller", 3285162922Sariff sizeof(desc)); 3286162922Sariff device_set_desc_copy(dev, desc); 3287162922Sariff } 3288162922Sariff 3289162922Sariff return (result); 3290162922Sariff} 3291162922Sariff 3292162922Sariffstatic void * 3293162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3294162922Sariff struct pcm_channel *c, int dir) 3295162922Sariff{ 3296182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3297182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3298162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3299162922Sariff struct hdac_chan *ch; 3300182999Smav int i, ord = 0, chid; 3301162922Sariff 3302162922Sariff hdac_lock(sc); 3303182999Smav 3304182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3305182999Smav ch = &sc->chans[chid]; 3306182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3307182999Smav if (ch->dir == sc->chans[i].dir) 3308182999Smav ord++; 3309182999Smav } 3310162922Sariff if (dir == PCMDIR_PLAY) { 3311182999Smav ch->off = (sc->num_iss + ord) << 5; 3312162922Sariff } else { 3313182999Smav ch->off = ord << 5; 3314162922Sariff } 3315182999Smav 3316162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3317162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3318162922Sariff ch->pcmrates[0] = 48000; 3319162922Sariff ch->pcmrates[1] = 0; 3320162922Sariff } 3321169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3322169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3323169277Sariff (sc->streamcnt * 8)); 3324169277Sariff else 3325169277Sariff ch->dmapos = NULL; 3326169277Sariff ch->sid = ++sc->streamcnt; 3327169277Sariff ch->dir = dir; 3328162922Sariff ch->b = b; 3329162922Sariff ch->c = c; 3330182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3331182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3332162922Sariff hdac_unlock(sc); 3333162922Sariff 3334162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3335162922Sariff ch->blkcnt = 0; 3336162922Sariff return (NULL); 3337162922Sariff } 3338162922Sariff 3339169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3340171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3341182999Smav pdevinfo->chan_size) != 0) 3342162922Sariff return (NULL); 3343162922Sariff 3344162922Sariff return (ch); 3345162922Sariff} 3346162922Sariff 3347162922Sariffstatic int 3348162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3349162922Sariff{ 3350162922Sariff struct hdac_chan *ch = data; 3351162922Sariff int i; 3352162922Sariff 3353162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3354162922Sariff if (format == ch->caps.fmtlist[i]) { 3355162922Sariff ch->fmt = format; 3356162922Sariff return (0); 3357162922Sariff } 3358162922Sariff } 3359162922Sariff 3360162922Sariff return (EINVAL); 3361162922Sariff} 3362162922Sariff 3363162922Sariffstatic int 3364162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3365162922Sariff{ 3366162922Sariff struct hdac_chan *ch = data; 3367164614Sariff uint32_t spd = 0, threshold; 3368162922Sariff int i; 3369162922Sariff 3370162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3371162922Sariff spd = ch->pcmrates[i]; 3372164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3373164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3374164614Sariff if (speed < threshold) 3375162922Sariff break; 3376162922Sariff } 3377162922Sariff 3378164614Sariff if (spd == 0) /* impossible */ 3379162922Sariff ch->spd = 48000; 3380162922Sariff else 3381162922Sariff ch->spd = spd; 3382162922Sariff 3383162922Sariff return (ch->spd); 3384162922Sariff} 3385162922Sariff 3386162922Sariffstatic void 3387162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3388162922Sariff{ 3389162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3390182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3391173817Sariff struct hdac_widget *w; 3392182999Smav int i, chn, totalchn, c; 3393162922Sariff nid_t cad = ch->devinfo->codec->cad; 3394182999Smav uint16_t fmt, dfmt; 3395162922Sariff 3396183097Smav HDA_BOOTHVERBOSE( 3397182999Smav device_printf(ch->pdevinfo->dev, 3398182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3399182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3400182999Smav ch->fmt, ch->spd); 3401182999Smav ); 3402162922Sariff fmt = 0; 3403162922Sariff if (ch->fmt & AFMT_S16_LE) 3404162922Sariff fmt |= ch->bit16 << 4; 3405162922Sariff else if (ch->fmt & AFMT_S32_LE) 3406162922Sariff fmt |= ch->bit32 << 4; 3407162922Sariff else 3408162922Sariff fmt |= 1 << 4; 3409162922Sariff 3410162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3411162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3412162922Sariff fmt |= hda_rate_tab[i].base; 3413162922Sariff fmt |= hda_rate_tab[i].mul; 3414162922Sariff fmt |= hda_rate_tab[i].div; 3415162922Sariff break; 3416162922Sariff } 3417162922Sariff } 3418162922Sariff 3419182999Smav if (ch->fmt & (AFMT_STEREO | AFMT_AC3)) { 3420162922Sariff fmt |= 1; 3421173817Sariff totalchn = 2; 3422173817Sariff } else 3423173817Sariff totalchn = 1; 3424162922Sariff 3425162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3426182999Smav 3427182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3428182999Smav if (ch->fmt & AFMT_AC3) 3429182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3430162922Sariff 3431173817Sariff chn = 0; 3432162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3433173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3434173817Sariff if (w == NULL) 3435173817Sariff continue; 3436182999Smav 3437182999Smav if (as->hpredir >= 0 && i == as->pincnt) 3438182999Smav chn = 0; 3439183097Smav HDA_BOOTHVERBOSE( 3440182999Smav device_printf(ch->pdevinfo->dev, 3441182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3442182999Smav "fmt=0x%04x, dfmt=0x%04x\n", 3443162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3444182999Smav ch->io[i], fmt, dfmt); 3445162922Sariff ); 3446162922Sariff hdac_command(sc, 3447162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3448182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3449174025Sariff hdac_command(sc, 3450182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3451174025Sariff cad); 3452182999Smav } 3453182999Smav /* If HP redirection is enabled, but failed to use same 3454182999Smav DAC make last DAC one to duplicate first one. */ 3455182999Smav if (as->hpredir >= 0 && i == as->pincnt) { 3456182999Smav c = (ch->sid << 4); 3457182999Smav } else if (chn >= totalchn) { 3458182999Smav /* This is until OSS will support multichannel. 3459182999Smav Should be: c = 0; to disable unused DAC */ 3460182999Smav c = (ch->sid << 4); 3461182999Smav }else { 3462182999Smav c = (ch->sid << 4) | chn; 3463182999Smav } 3464182999Smav hdac_command(sc, 3465182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3466173817Sariff chn += 3467173817Sariff HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ? 3468173817Sariff 2 : 1; 3469162922Sariff } 3470162922Sariff} 3471162922Sariff 3472162922Sariffstatic int 3473167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3474167648Sariff uint32_t blksz, uint32_t blkcnt) 3475162922Sariff{ 3476162922Sariff struct hdac_chan *ch = data; 3477164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3478162922Sariff 3479167648Sariff blksz &= HDA_BLK_ALIGN; 3480162922Sariff 3481167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3482167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3483167648Sariff if (blksz < HDA_BLK_MIN) 3484167648Sariff blksz = HDA_BLK_MIN; 3485167648Sariff if (blkcnt > HDA_BDL_MAX) 3486167648Sariff blkcnt = HDA_BDL_MAX; 3487167648Sariff if (blkcnt < HDA_BDL_MIN) 3488167648Sariff blkcnt = HDA_BDL_MIN; 3489164614Sariff 3490167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3491167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3492167648Sariff blkcnt >>= 1; 3493167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3494167648Sariff blksz >>= 1; 3495167648Sariff else 3496167648Sariff break; 3497167648Sariff } 3498167648Sariff 3499164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3500167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3501167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3502164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3503167648Sariff __func__, blksz, blkcnt); 3504164614Sariff 3505164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3506167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3507164614Sariff 3508167648Sariff return (1); 3509167648Sariff} 3510167648Sariff 3511167648Sariffstatic int 3512167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3513167648Sariff{ 3514167648Sariff struct hdac_chan *ch = data; 3515167648Sariff 3516182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3517167648Sariff 3518162922Sariff return (ch->blksz); 3519162922Sariff} 3520162922Sariff 3521162922Sariffstatic void 3522162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3523162922Sariff{ 3524162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3525182999Smav struct hdac_widget *w; 3526162922Sariff nid_t cad = devinfo->codec->cad; 3527162922Sariff int i; 3528162922Sariff 3529162922Sariff hdac_stream_stop(ch); 3530162922Sariff 3531162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3532182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3533182999Smav if (w == NULL) 3534182999Smav continue; 3535182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3536182999Smav hdac_command(sc, 3537182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3538182999Smav cad); 3539182999Smav } 3540162922Sariff hdac_command(sc, 3541162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3542162922Sariff 0), cad); 3543162922Sariff } 3544162922Sariff} 3545162922Sariff 3546162922Sariffstatic void 3547162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3548162922Sariff{ 3549162922Sariff ch->ptr = 0; 3550162922Sariff ch->prevptr = 0; 3551162922Sariff hdac_stream_stop(ch); 3552162922Sariff hdac_stream_reset(ch); 3553162922Sariff hdac_bdl_setup(ch); 3554162922Sariff hdac_stream_setid(ch); 3555162922Sariff hdac_stream_setup(ch); 3556162922Sariff hdac_stream_start(ch); 3557162922Sariff} 3558162922Sariff 3559162922Sariffstatic int 3560162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3561162922Sariff{ 3562162922Sariff struct hdac_chan *ch = data; 3563162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3564162922Sariff 3565170521Sariff if (!PCMTRIG_COMMON(go)) 3566170521Sariff return (0); 3567170521Sariff 3568162922Sariff hdac_lock(sc); 3569162922Sariff switch (go) { 3570162922Sariff case PCMTRIG_START: 3571162922Sariff hdac_channel_start(sc, ch); 3572162922Sariff break; 3573162922Sariff case PCMTRIG_STOP: 3574162922Sariff case PCMTRIG_ABORT: 3575162922Sariff hdac_channel_stop(sc, ch); 3576162922Sariff break; 3577167610Sariff default: 3578167610Sariff break; 3579162922Sariff } 3580162922Sariff hdac_unlock(sc); 3581162922Sariff 3582162922Sariff return (0); 3583162922Sariff} 3584162922Sariff 3585162922Sariffstatic int 3586162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3587162922Sariff{ 3588162922Sariff struct hdac_chan *ch = data; 3589162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3590162922Sariff uint32_t ptr; 3591162922Sariff 3592162922Sariff hdac_lock(sc); 3593164614Sariff if (sc->polling != 0) 3594164614Sariff ptr = ch->ptr; 3595169277Sariff else if (ch->dmapos != NULL) 3596169277Sariff ptr = *(ch->dmapos); 3597164614Sariff else 3598164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3599162922Sariff hdac_unlock(sc); 3600162922Sariff 3601164614Sariff /* 3602164614Sariff * Round to available space and force 128 bytes aligment. 3603164614Sariff */ 3604164614Sariff ptr %= ch->blksz * ch->blkcnt; 3605167648Sariff ptr &= HDA_BLK_ALIGN; 3606162922Sariff 3607162922Sariff return (ptr); 3608162922Sariff} 3609162922Sariff 3610162922Sariffstatic struct pcmchan_caps * 3611162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3612162922Sariff{ 3613162922Sariff return (&((struct hdac_chan *)data)->caps); 3614162922Sariff} 3615162922Sariff 3616162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3617162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3618162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3619162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3620162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3621167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3622162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3623162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3624162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3625162922Sariff { 0, 0 } 3626162922Sariff}; 3627162922SariffCHANNEL_DECLARE(hdac_channel); 3628162922Sariff 3629162922Sariffstatic int 3630162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3631162922Sariff{ 3632182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3633182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3634162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3635162922Sariff struct hdac_widget *w, *cw; 3636162922Sariff struct hdac_audio_ctl *ctl; 3637162922Sariff uint32_t mask, recmask, id; 3638162922Sariff int i, j, softpcmvol; 3639162922Sariff 3640162922Sariff hdac_lock(sc); 3641162922Sariff 3642182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3643182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3644182999Smav pdevinfo->left[i] = 100; 3645182999Smav pdevinfo->right[i] = 100; 3646182999Smav } 3647182999Smav 3648162922Sariff mask = 0; 3649162922Sariff recmask = 0; 3650182999Smav id = hdac_codec_id(devinfo->codec); 3651162922Sariff 3652182999Smav /* Declate EAPD as ogain control. */ 3653182999Smav if (pdevinfo->play >= 0) { 3654182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3655182999Smav w = hdac_widget_get(devinfo, i); 3656182999Smav if (w == NULL || w->enable == 0) 3657182999Smav continue; 3658182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3659182999Smav w->param.eapdbtl == HDAC_INVALID || 3660182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3661182999Smav continue; 3662182999Smav mask |= SOUND_MASK_OGAIN; 3663162922Sariff break; 3664162922Sariff } 3665162922Sariff } 3666162922Sariff 3667182999Smav /* Declare volume controls assigned to this association. */ 3668162922Sariff i = 0; 3669162922Sariff ctl = NULL; 3670162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3671182999Smav if (ctl->enable == 0) 3672162922Sariff continue; 3673182999Smav if ((pdevinfo->play >= 0 && 3674182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3675182999Smav (pdevinfo->rec >= 0 && 3676182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3677182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3678182999Smav mask |= ctl->ossmask; 3679162922Sariff } 3680162922Sariff 3681182999Smav /* Declare record sources available to this association. */ 3682182999Smav if (pdevinfo->rec >= 0) { 3683182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3684182999Smav for (i = 0; ch->io[i] != -1; i++) { 3685182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3686182999Smav if (w == NULL || w->enable == 0) 3687182999Smav continue; 3688182999Smav for (j = 0; j < w->nconns; j++) { 3689182999Smav if (w->connsenable[j] == 0) 3690162922Sariff continue; 3691182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3692182999Smav if (cw == NULL || cw->enable == 0) 3693165992Sariff continue; 3694182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3695182999Smav cw->bindas != -2) 3696165992Sariff continue; 3697182999Smav recmask |= cw->ossmask; 3698165992Sariff } 3699182999Smav } 3700182999Smav } 3701182999Smav 3702185230Smav /* Declare soft PCM volume if needed. */ 3703185230Smav if (pdevinfo->play >= 0 && !pdevinfo->digital) { 3704182999Smav ctl = NULL; 3705182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3706182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3707182999Smav softpcmvol = 1; 3708182999Smav mask |= SOUND_MASK_PCM; 3709162922Sariff } else { 3710182999Smav softpcmvol = 0; 3711182999Smav i = 0; 3712182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3713182999Smav if (ctl->enable == 0) 3714162922Sariff continue; 3715182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3716182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3717162922Sariff continue; 3718182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3719182999Smav continue; 3720182999Smav if (ctl->step > 0) 3721182999Smav break; 3722162922Sariff } 3723162922Sariff } 3724182999Smav 3725182999Smav if (softpcmvol == 1 || ctl == NULL) { 3726182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3727182999Smav HDA_BOOTVERBOSE( 3728182999Smav device_printf(pdevinfo->dev, 3729182999Smav "%s Soft PCM volume\n", 3730182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3731182999Smav ); 3732182999Smav } 3733185230Smav } 3734182999Smav 3735185230Smav /* Declare master volume if needed. */ 3736185230Smav if (pdevinfo->play >= 0) { 3737185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3738185230Smav SOUND_MASK_PCM) { 3739182999Smav mask |= SOUND_MASK_VOLUME; 3740182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3741182999Smav SOUND_MASK_PCM); 3742182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3743182999Smav SOUND_MIXER_NONE); 3744182999Smav HDA_BOOTVERBOSE( 3745182999Smav device_printf(pdevinfo->dev, 3746182999Smav "Forcing master volume with PCM\n"); 3747182999Smav ); 3748182999Smav } 3749162922Sariff } 3750162922Sariff 3751169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3752169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3753162922Sariff 3754162922Sariff mix_setrecdevs(m, recmask); 3755162922Sariff mix_setdevs(m, mask); 3756162922Sariff 3757162922Sariff hdac_unlock(sc); 3758162922Sariff 3759162922Sariff return (0); 3760162922Sariff} 3761162922Sariff 3762162922Sariffstatic int 3763162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3764162922Sariff unsigned left, unsigned right) 3765162922Sariff{ 3766182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3767182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3768162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3769162922Sariff struct hdac_widget *w; 3770162922Sariff struct hdac_audio_ctl *ctl; 3771182999Smav uint32_t mute; 3772182999Smav int lvol, rvol; 3773182999Smav int i, j; 3774162922Sariff 3775162922Sariff hdac_lock(sc); 3776182999Smav /* Save new values. */ 3777182999Smav pdevinfo->left[dev] = left; 3778182999Smav pdevinfo->right[dev] = right; 3779182999Smav 3780182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3781162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3782163257Sariff uint32_t orig; 3783182999Smav w = NULL; 3784182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3785182999Smav w = hdac_widget_get(devinfo, i); 3786182999Smav if (w == NULL || w->enable == 0) 3787182999Smav continue; 3788182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3789182999Smav w->param.eapdbtl == HDAC_INVALID) 3790182999Smav continue; 3791182999Smav break; 3792162922Sariff } 3793182999Smav if (i >= devinfo->endnode) { 3794162922Sariff hdac_unlock(sc); 3795162922Sariff return (-1); 3796162922Sariff } 3797163257Sariff orig = w->param.eapdbtl; 3798163432Sariff if (left == 0) 3799162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3800162922Sariff else 3801162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3802163257Sariff if (orig != w->param.eapdbtl) { 3803163432Sariff uint32_t val; 3804163432Sariff 3805163432Sariff val = w->param.eapdbtl; 3806163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3807163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3808163257Sariff hdac_command(sc, 3809163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3810163432Sariff w->nid, val), devinfo->codec->cad); 3811163257Sariff } 3812162922Sariff hdac_unlock(sc); 3813162922Sariff return (left | (left << 8)); 3814162922Sariff } 3815162922Sariff 3816182999Smav /* Recalculate all controls related to this OSS device. */ 3817162922Sariff i = 0; 3818162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3819182999Smav if (ctl->enable == 0 || 3820162922Sariff !(ctl->ossmask & (1 << dev))) 3821162922Sariff continue; 3822182999Smav if (!((pdevinfo->play >= 0 && 3823182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3824182999Smav (pdevinfo->rec >= 0 && 3825182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3826182999Smav ctl->widget->bindas == -2)) 3827182999Smav continue; 3828182999Smav 3829182999Smav lvol = 100; 3830182999Smav rvol = 100; 3831182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3832182999Smav if (ctl->ossmask & (1 << j)) { 3833182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3834182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3835162922Sariff } 3836162922Sariff } 3837182999Smav mute = (left == 0) ? HDA_AMP_MUTE_LEFT : 0; 3838182999Smav mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3839182999Smav lvol = (lvol * ctl->step + 50) / 100; 3840182999Smav rvol = (rvol * ctl->step + 50) / 100; 3841162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3842162922Sariff } 3843162922Sariff hdac_unlock(sc); 3844162922Sariff 3845162922Sariff return (left | (right << 8)); 3846162922Sariff} 3847162922Sariff 3848182999Smav/* 3849182999Smav * Commutate specified record source. 3850182999Smav */ 3851182999Smavstatic uint32_t 3852182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3853162922Sariff{ 3854182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3855162922Sariff struct hdac_widget *w, *cw; 3856182999Smav struct hdac_audio_ctl *ctl; 3857182999Smav char buf[64]; 3858182999Smav int i, muted; 3859182999Smav uint32_t res = 0; 3860162922Sariff 3861182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3862182999Smav return (0); 3863182999Smav 3864182999Smav w = hdac_widget_get(devinfo, nid); 3865182999Smav if (w == NULL || w->enable == 0) 3866182999Smav return (0); 3867182999Smav 3868182999Smav for (i = 0; i < w->nconns; i++) { 3869182999Smav if (w->connsenable[i] == 0) 3870182999Smav continue; 3871182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3872182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3873182999Smav continue; 3874182999Smav /* Call recursively to trace signal to it's source if needed. */ 3875182999Smav if ((src & cw->ossmask) != 0) { 3876182999Smav if (cw->ossdev < 0) { 3877182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 3878182999Smav w->conns[i], depth + 1); 3879182999Smav } else { 3880182999Smav res |= cw->ossmask; 3881182999Smav } 3882182999Smav } 3883182999Smav /* We have two special cases: mixers and others (selectors). */ 3884182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 3885182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 3886182999Smav w->nid, HDA_CTL_IN, i, 1); 3887182999Smav if (ctl == NULL) 3888182999Smav continue; 3889182999Smav /* If we have input control on this node mute them 3890182999Smav * according to requested sources. */ 3891182999Smav muted = (src & cw->ossmask) ? 0 : 1; 3892182999Smav if (muted != ctl->forcemute) { 3893182999Smav ctl->forcemute = muted; 3894182999Smav hdac_audio_ctl_amp_set(ctl, 3895182999Smav HDA_AMP_MUTE_DEFAULT, 3896182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 3897182999Smav } 3898183097Smav HDA_BOOTHVERBOSE( 3899182999Smav device_printf(pdevinfo->dev, 3900182999Smav "Recsel (%s): nid %d source %d %s\n", 3901182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3902182999Smav src, buf, sizeof(buf)), 3903182999Smav nid, i, muted?"mute":"unmute"); 3904182999Smav ); 3905182999Smav } else { 3906182999Smav if (w->nconns == 1) 3907182999Smav break; 3908182999Smav if ((src & cw->ossmask) == 0) 3909182999Smav continue; 3910182999Smav /* If we found requested source - select it and exit. */ 3911182999Smav hdac_widget_connection_select(w, i); 3912183097Smav HDA_BOOTHVERBOSE( 3913182999Smav device_printf(pdevinfo->dev, 3914182999Smav "Recsel (%s): nid %d source %d select\n", 3915182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3916182999Smav src, buf, sizeof(buf)), 3917182999Smav nid, i); 3918182999Smav ); 3919162922Sariff break; 3920162922Sariff } 3921162922Sariff } 3922182999Smav return (res); 3923182999Smav} 3924162922Sariff 3925182999Smavstatic uint32_t 3926182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3927182999Smav{ 3928182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3929182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3930182999Smav struct hdac_widget *w; 3931182999Smav struct hdac_softc *sc = devinfo->codec->sc; 3932182999Smav struct hdac_chan *ch; 3933182999Smav int i; 3934182999Smav uint32_t ret = 0xffffffff; 3935182999Smav 3936162922Sariff hdac_lock(sc); 3937162922Sariff 3938182999Smav /* Commutate requested recsrc for each ADC. */ 3939182999Smav ch = &sc->chans[pdevinfo->rec]; 3940182999Smav for (i = 0; ch->io[i] != -1; i++) { 3941182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3942162965Sariff if (w == NULL || w->enable == 0) 3943162922Sariff continue; 3944182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 3945162922Sariff } 3946162922Sariff 3947162922Sariff hdac_unlock(sc); 3948162922Sariff 3949182999Smav return ((ret == 0xffffffff)? 0 : ret); 3950162922Sariff} 3951162922Sariff 3952162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3953162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3954162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3955162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3956162922Sariff { 0, 0 } 3957162922Sariff}; 3958162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3959162922Sariff 3960171141Sariffstatic void 3961171141Sariffhdac_unsolq_task(void *context, int pending) 3962171141Sariff{ 3963171141Sariff struct hdac_softc *sc; 3964171141Sariff 3965171141Sariff sc = (struct hdac_softc *)context; 3966171141Sariff 3967171141Sariff hdac_lock(sc); 3968171141Sariff hdac_unsolq_flush(sc); 3969171141Sariff hdac_unlock(sc); 3970171141Sariff} 3971171141Sariff 3972162922Sariff/**************************************************************************** 3973162922Sariff * int hdac_attach(device_t) 3974162922Sariff * 3975162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3976162922Sariff * when this function is called. Setup everything that doesn't require 3977162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3978162922Sariff ****************************************************************************/ 3979162922Sariffstatic int 3980162922Sariffhdac_attach(device_t dev) 3981162922Sariff{ 3982162922Sariff struct hdac_softc *sc; 3983162922Sariff int result; 3984189086Smav int i, devid = -1; 3985189086Smav uint32_t model; 3986189086Smav uint16_t class, subclass; 3987169277Sariff uint16_t vendor; 3988169277Sariff uint8_t v; 3989162922Sariff 3990184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 3991182999Smav 3992189086Smav model = (uint32_t)pci_get_device(dev) << 16; 3993189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3994189086Smav class = pci_get_class(dev); 3995189086Smav subclass = pci_get_subclass(dev); 3996189086Smav 3997189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3998189086Smav if (hdac_devices[i].model == model) { 3999189086Smav devid = i; 4000189086Smav break; 4001189086Smav } 4002189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 4003189086Smav class == PCIC_MULTIMEDIA && 4004189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 4005189086Smav devid = i; 4006189086Smav break; 4007189086Smav } 4008189086Smav } 4009189086Smav 4010182999Smav sc = device_get_softc(dev); 4011163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 4012162922Sariff sc->dev = dev; 4013163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 4014163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 4015169277Sariff vendor = pci_get_vendor(dev); 4016162922Sariff 4017165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 4018165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 4019165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 4020165281Sariff } 4021165281Sariff 4022164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 4023164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 4024169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 4025164614Sariff 4026171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 4027171141Sariff 4028182999Smav sc->poll_ticks = 1000000; 4029169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 4030169277Sariff if (resource_int_value(device_get_name(dev), 4031169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 4032164614Sariff sc->polling = 1; 4033164614Sariff else 4034164614Sariff sc->polling = 0; 4035164614Sariff 4036162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 4037162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 4038162922Sariff 0, /* boundary */ 4039162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 4040162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 4041162922Sariff NULL, /* filtfunc */ 4042162922Sariff NULL, /* fistfuncarg */ 4043182999Smav HDA_BUFSZ_MAX, /* maxsize */ 4044162922Sariff 1, /* nsegments */ 4045182999Smav HDA_BUFSZ_MAX, /* maxsegsz */ 4046162922Sariff 0, /* flags */ 4047162922Sariff NULL, /* lockfunc */ 4048162922Sariff NULL, /* lockfuncarg */ 4049162922Sariff &sc->chan_dmat); /* dmat */ 4050162922Sariff if (result != 0) { 4051169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 4052162922Sariff __func__, result); 4053163057Sariff snd_mtxfree(sc->lock); 4054162922Sariff free(sc, M_DEVBUF); 4055162922Sariff return (ENXIO); 4056162922Sariff } 4057162922Sariff 4058162922Sariff 4059162922Sariff sc->hdabus = NULL; 4060162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 4061162922Sariff sc->codecs[i] = NULL; 4062162922Sariff 4063162922Sariff pci_enable_busmaster(dev); 4064162922Sariff 4065169277Sariff if (vendor == INTEL_VENDORID) { 4066169277Sariff /* TCSEL -> TC0 */ 4067169277Sariff v = pci_read_config(dev, 0x44, 1); 4068169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 4069183097Smav HDA_BOOTHVERBOSE( 4070169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 4071169277Sariff pci_read_config(dev, 0x44, 1)); 4072169277Sariff ); 4073169277Sariff } 4074169277Sariff 4075189127Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_MSI)) 4076188656Smav sc->flags &= ~HDAC_F_MSI; 4077188656Smav else 4078171330Sariff sc->flags |= HDAC_F_MSI; 4079189086Smav if (resource_int_value(device_get_name(dev), 4080189086Smav device_get_unit(dev), "msi", &i) == 0) { 4081189086Smav if (i == 0) 4082189086Smav sc->flags &= ~HDAC_F_MSI; 4083189086Smav else 4084189086Smav sc->flags |= HDAC_F_MSI; 4085189086Smav } 4086171330Sariff 4087169277Sariff#if defined(__i386__) || defined(__amd64__) 4088171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4089169277Sariff 4090169277Sariff if (resource_int_value(device_get_name(dev), 4091169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 4092169277Sariff#else 4093171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4094169277Sariff#endif 4095169277Sariff /* 4096169277Sariff * Try to enable PCIe snoop to avoid messing around with 4097169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 4098169277Sariff * config is pretty much vendor specific, there are no 4099169277Sariff * general solutions on how to enable it, forcing us (even 4100169277Sariff * Microsoft) to enable uncacheable or write combined DMA 4101169277Sariff * by default. 4102169277Sariff * 4103169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 4104169277Sariff */ 4105169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 4106169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 4107169277Sariff continue; 4108171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4109169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4110169277Sariff break; 4111169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4112169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4113169277Sariff hdac_pcie_snoop[i].enable) 4114169277Sariff break; 4115169277Sariff v &= hdac_pcie_snoop[i].mask; 4116169277Sariff v |= hdac_pcie_snoop[i].enable; 4117169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4118169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4119169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4120169277Sariff hdac_pcie_snoop[i].enable) { 4121169277Sariff HDA_BOOTVERBOSE( 4122169277Sariff device_printf(dev, 4123169277Sariff "WARNING: Failed to enable PCIe " 4124169277Sariff "snoop!\n"); 4125169277Sariff ); 4126169277Sariff#if defined(__i386__) || defined(__amd64__) 4127171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4128169277Sariff#endif 4129169277Sariff } 4130169277Sariff break; 4131169277Sariff } 4132169277Sariff#if defined(__i386__) || defined(__amd64__) 4133169277Sariff } 4134169277Sariff#endif 4135169277Sariff 4136183097Smav HDA_BOOTHVERBOSE( 4137169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4138171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4139171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4140169277Sariff ); 4141169277Sariff 4142162922Sariff /* Allocate resources */ 4143162922Sariff result = hdac_mem_alloc(sc); 4144162922Sariff if (result != 0) 4145163057Sariff goto hdac_attach_fail; 4146162922Sariff result = hdac_irq_alloc(sc); 4147162922Sariff if (result != 0) 4148163057Sariff goto hdac_attach_fail; 4149162922Sariff 4150162922Sariff /* Get Capabilities */ 4151162922Sariff result = hdac_get_capabilities(sc); 4152162922Sariff if (result != 0) 4153163057Sariff goto hdac_attach_fail; 4154162922Sariff 4155162922Sariff /* Allocate CORB and RIRB dma memory */ 4156162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4157162922Sariff sc->corb_size * sizeof(uint32_t)); 4158162922Sariff if (result != 0) 4159163057Sariff goto hdac_attach_fail; 4160162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4161162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4162162922Sariff if (result != 0) 4163163057Sariff goto hdac_attach_fail; 4164162922Sariff 4165162922Sariff /* Quiesce everything */ 4166183097Smav HDA_BOOTHVERBOSE( 4167182999Smav device_printf(dev, "Reset controller...\n"); 4168182999Smav ); 4169182999Smav hdac_reset(sc, 1); 4170162922Sariff 4171162922Sariff /* Initialize the CORB and RIRB */ 4172162922Sariff hdac_corb_init(sc); 4173162922Sariff hdac_rirb_init(sc); 4174162922Sariff 4175162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4176162922Sariff sc->intrhook.ich_func = hdac_attach2; 4177162922Sariff sc->intrhook.ich_arg = (void *)sc; 4178162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4179162922Sariff sc->intrhook.ich_func = NULL; 4180162922Sariff hdac_attach2((void *)sc); 4181162922Sariff } 4182162922Sariff 4183163057Sariff return (0); 4184162922Sariff 4185163057Sariffhdac_attach_fail: 4186162922Sariff hdac_irq_free(sc); 4187169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4188169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4189162922Sariff hdac_mem_free(sc); 4190162922Sariff snd_mtxfree(sc->lock); 4191163057Sariff free(sc, M_DEVBUF); 4192162922Sariff 4193163057Sariff return (ENXIO); 4194162922Sariff} 4195162922Sariff 4196162922Sariffstatic void 4197162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4198162922Sariff{ 4199182999Smav struct hdac_codec *codec = devinfo->codec; 4200182999Smav struct hdac_softc *sc = codec->sc; 4201162922Sariff struct hdac_widget *w; 4202162922Sariff uint32_t res; 4203162922Sariff int i; 4204162922Sariff nid_t cad, nid; 4205162922Sariff 4206162922Sariff cad = devinfo->codec->cad; 4207162922Sariff nid = devinfo->nid; 4208162922Sariff 4209162922Sariff res = hdac_command(sc, 4210169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4211169277Sariff devinfo->function.audio.gpio = res; 4212169277Sariff 4213163057Sariff HDA_BOOTVERBOSE( 4214183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4215183097Smav "NumGPIO=%d NumGPO=%d " 4216169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4217183097Smav devinfo->function.audio.gpio, 4218169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4219169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4220169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4221169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4222169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4223162922Sariff ); 4224162922Sariff 4225162922Sariff res = hdac_command(sc, 4226162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4227162922Sariff cad); 4228162922Sariff devinfo->function.audio.supp_stream_formats = res; 4229162922Sariff 4230162922Sariff res = hdac_command(sc, 4231162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4232162922Sariff cad); 4233162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4234162922Sariff 4235162922Sariff res = hdac_command(sc, 4236162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4237162922Sariff cad); 4238162922Sariff devinfo->function.audio.outamp_cap = res; 4239162922Sariff 4240162922Sariff res = hdac_command(sc, 4241162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4242162922Sariff cad); 4243162922Sariff devinfo->function.audio.inamp_cap = res; 4244162922Sariff 4245162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4246162922Sariff w = hdac_widget_get(devinfo, i); 4247162922Sariff if (w == NULL) 4248162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4249162922Sariff else { 4250162922Sariff w->devinfo = devinfo; 4251162922Sariff w->nid = i; 4252162922Sariff w->enable = 1; 4253162922Sariff w->selconn = -1; 4254162922Sariff w->pflags = 0; 4255182999Smav w->ossdev = -1; 4256182999Smav w->bindas = -1; 4257162965Sariff w->param.eapdbtl = HDAC_INVALID; 4258162922Sariff hdac_widget_parse(w); 4259162922Sariff } 4260162922Sariff } 4261162922Sariff} 4262162922Sariff 4263162922Sariffstatic void 4264162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4265162922Sariff{ 4266162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4267162922Sariff struct hdac_audio_ctl *ctls; 4268162922Sariff struct hdac_widget *w, *cw; 4269162922Sariff int i, j, cnt, max, ocap, icap; 4270163057Sariff int mute, offset, step, size; 4271162922Sariff 4272162922Sariff /* XXX This is redundant */ 4273162922Sariff max = 0; 4274162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4275162922Sariff w = hdac_widget_get(devinfo, i); 4276162922Sariff if (w == NULL || w->enable == 0) 4277162922Sariff continue; 4278162922Sariff if (w->param.outamp_cap != 0) 4279162922Sariff max++; 4280162922Sariff if (w->param.inamp_cap != 0) { 4281162922Sariff switch (w->type) { 4282162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4283162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4284162922Sariff for (j = 0; j < w->nconns; j++) { 4285162922Sariff cw = hdac_widget_get(devinfo, 4286162922Sariff w->conns[j]); 4287162922Sariff if (cw == NULL || cw->enable == 0) 4288162922Sariff continue; 4289162922Sariff max++; 4290162922Sariff } 4291162922Sariff break; 4292162922Sariff default: 4293162922Sariff max++; 4294162922Sariff break; 4295162922Sariff } 4296162922Sariff } 4297162922Sariff } 4298162922Sariff 4299162922Sariff devinfo->function.audio.ctlcnt = max; 4300162922Sariff 4301162922Sariff if (max < 1) 4302162922Sariff return; 4303162922Sariff 4304162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4305162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4306162922Sariff 4307162922Sariff if (ctls == NULL) { 4308162922Sariff /* Blekh! */ 4309162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4310162922Sariff devinfo->function.audio.ctlcnt = 0; 4311162922Sariff return; 4312162922Sariff } 4313162922Sariff 4314162922Sariff cnt = 0; 4315162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4316162922Sariff if (cnt >= max) { 4317162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4318162922Sariff __func__); 4319162922Sariff break; 4320162922Sariff } 4321162922Sariff w = hdac_widget_get(devinfo, i); 4322162922Sariff if (w == NULL || w->enable == 0) 4323162922Sariff continue; 4324162922Sariff ocap = w->param.outamp_cap; 4325162922Sariff icap = w->param.inamp_cap; 4326162922Sariff if (ocap != 0) { 4327163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4328163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4329163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4330163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4331163057Sariff /*if (offset > step) { 4332163057Sariff HDA_BOOTVERBOSE( 4333163057Sariff device_printf(sc->dev, 4334182999Smav "BUGGY outamp: nid=%d " 4335163057Sariff "[offset=%d > step=%d]\n", 4336163057Sariff w->nid, offset, step); 4337163057Sariff ); 4338163057Sariff offset = step; 4339163057Sariff }*/ 4340162922Sariff ctls[cnt].enable = 1; 4341162922Sariff ctls[cnt].widget = w; 4342163057Sariff ctls[cnt].mute = mute; 4343163057Sariff ctls[cnt].step = step; 4344163057Sariff ctls[cnt].size = size; 4345163057Sariff ctls[cnt].offset = offset; 4346163057Sariff ctls[cnt].left = offset; 4347163057Sariff ctls[cnt].right = offset; 4348182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4349182999Smav w->waspin) 4350182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4351182999Smav else 4352182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4353162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4354162922Sariff } 4355162922Sariff 4356162922Sariff if (icap != 0) { 4357163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4358163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4359163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4360163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4361163057Sariff /*if (offset > step) { 4362163057Sariff HDA_BOOTVERBOSE( 4363163057Sariff device_printf(sc->dev, 4364182999Smav "BUGGY inamp: nid=%d " 4365163057Sariff "[offset=%d > step=%d]\n", 4366163057Sariff w->nid, offset, step); 4367163057Sariff ); 4368163057Sariff offset = step; 4369163057Sariff }*/ 4370162922Sariff switch (w->type) { 4371162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4372162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4373162922Sariff for (j = 0; j < w->nconns; j++) { 4374162922Sariff if (cnt >= max) { 4375162922Sariff device_printf(sc->dev, 4376162922Sariff "%s: Ctl overflow!\n", 4377162922Sariff __func__); 4378162922Sariff break; 4379162922Sariff } 4380162922Sariff cw = hdac_widget_get(devinfo, 4381162922Sariff w->conns[j]); 4382162922Sariff if (cw == NULL || cw->enable == 0) 4383162922Sariff continue; 4384162922Sariff ctls[cnt].enable = 1; 4385162922Sariff ctls[cnt].widget = w; 4386162922Sariff ctls[cnt].childwidget = cw; 4387162922Sariff ctls[cnt].index = j; 4388163057Sariff ctls[cnt].mute = mute; 4389163057Sariff ctls[cnt].step = step; 4390163057Sariff ctls[cnt].size = size; 4391163057Sariff ctls[cnt].offset = offset; 4392163057Sariff ctls[cnt].left = offset; 4393163057Sariff ctls[cnt].right = offset; 4394182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4395162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4396162922Sariff } 4397162922Sariff break; 4398162922Sariff default: 4399162922Sariff if (cnt >= max) { 4400162922Sariff device_printf(sc->dev, 4401162922Sariff "%s: Ctl overflow!\n", 4402162922Sariff __func__); 4403162922Sariff break; 4404162922Sariff } 4405162922Sariff ctls[cnt].enable = 1; 4406162922Sariff ctls[cnt].widget = w; 4407163057Sariff ctls[cnt].mute = mute; 4408163057Sariff ctls[cnt].step = step; 4409163057Sariff ctls[cnt].size = size; 4410163057Sariff ctls[cnt].offset = offset; 4411163057Sariff ctls[cnt].left = offset; 4412163057Sariff ctls[cnt].right = offset; 4413182999Smav if (w->type == 4414182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4415182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4416182999Smav else 4417182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4418162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4419162922Sariff break; 4420162922Sariff } 4421162922Sariff } 4422162922Sariff } 4423162922Sariff 4424162922Sariff devinfo->function.audio.ctl = ctls; 4425162922Sariff} 4426162922Sariff 4427182999Smavstatic void 4428182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4429182999Smav{ 4430182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4431182999Smav struct hdac_audio_as *as; 4432182999Smav struct hdac_widget *w; 4433182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4434182999Smav 4435184991Smav /* Count present associations */ 4436182999Smav max = 0; 4437184991Smav for (j = 1; j < 16; j++) { 4438182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4439182999Smav w = hdac_widget_get(devinfo, i); 4440182999Smav if (w == NULL || w->enable == 0) 4441182999Smav continue; 4442182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4443182999Smav continue; 4444182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4445182999Smav != j) 4446182999Smav continue; 4447182999Smav max++; 4448182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4449182999Smav break; 4450182999Smav } 4451182999Smav } 4452182999Smav 4453182999Smav devinfo->function.audio.ascnt = max; 4454182999Smav 4455182999Smav if (max < 1) 4456182999Smav return; 4457182999Smav 4458182999Smav as = (struct hdac_audio_as *)malloc( 4459182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4460182999Smav 4461182999Smav if (as == NULL) { 4462182999Smav /* Blekh! */ 4463182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4464182999Smav devinfo->function.audio.ascnt = 0; 4465182999Smav return; 4466182999Smav } 4467182999Smav 4468182999Smav for (i = 0; i < max; i++) { 4469182999Smav as[i].hpredir = -1; 4470182999Smav as[i].chan = -1; 4471185225Smav as[i].digital = 1; 4472182999Smav } 4473182999Smav 4474182999Smav /* Scan associations skipping as=0. */ 4475182999Smav cnt = 0; 4476182999Smav for (j = 1; j < 16; j++) { 4477182999Smav first = 16; 4478182999Smav hpredir = 0; 4479182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4480182999Smav w = hdac_widget_get(devinfo, i); 4481182999Smav if (w == NULL || w->enable == 0) 4482182999Smav continue; 4483182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4484182999Smav continue; 4485182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4486182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4487182999Smav if (assoc != j) { 4488182999Smav continue; 4489182999Smav } 4490182999Smav KASSERT(cnt < max, 4491182999Smav ("%s: Associations owerflow (%d of %d)", 4492182999Smav __func__, cnt, max)); 4493182999Smav type = w->wclass.pin.config & 4494182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4495182999Smav /* Get pin direction. */ 4496182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4497182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4498182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4499182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4500182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4501182999Smav dir = HDA_CTL_OUT; 4502182999Smav else 4503182999Smav dir = HDA_CTL_IN; 4504182999Smav /* If this is a first pin - create new association. */ 4505182999Smav if (as[cnt].pincnt == 0) { 4506182999Smav as[cnt].enable = 1; 4507182999Smav as[cnt].index = j; 4508182999Smav as[cnt].dir = dir; 4509182999Smav } 4510182999Smav if (seq < first) 4511182999Smav first = seq; 4512182999Smav /* Check association correctness. */ 4513182999Smav if (as[cnt].pins[seq] != 0) { 4514182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4515182999Smav "in association %d! Disabling association.\n", 4516182999Smav __func__, seq, w->nid, j); 4517182999Smav as[cnt].enable = 0; 4518182999Smav } 4519182999Smav if (dir != as[cnt].dir) { 4520182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4521182999Smav "direction for association %d! Disabling " 4522182999Smav "association.\n", 4523182999Smav __func__, w->nid, j); 4524182999Smav as[cnt].enable = 0; 4525182999Smav } 4526185225Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 4527185225Smav as[cnt].digital = 0; 4528182999Smav /* Headphones with seq=15 may mean redirection. */ 4529182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4530182999Smav seq == 15) 4531182999Smav hpredir = 1; 4532182999Smav as[cnt].pins[seq] = w->nid; 4533182999Smav as[cnt].pincnt++; 4534182999Smav /* Association 15 is a multiple unassociated pins. */ 4535182999Smav if (j == 15) 4536182999Smav cnt++; 4537182999Smav } 4538182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4539182999Smav if (hpredir && as[cnt].pincnt > 1) 4540182999Smav as[cnt].hpredir = first; 4541182999Smav cnt++; 4542182999Smav } 4543182999Smav } 4544182999Smav HDA_BOOTVERBOSE( 4545182999Smav device_printf(sc->dev, 4546183097Smav "%d associations found:\n", max); 4547182999Smav for (i = 0; i < max; i++) { 4548182999Smav device_printf(sc->dev, 4549182999Smav "Association %d (%d) %s%s:\n", 4550182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4551182999Smav as[i].enable?"":" (disabled)"); 4552182999Smav for (j = 0; j < 16; j++) { 4553182999Smav if (as[i].pins[j] == 0) 4554182999Smav continue; 4555182999Smav device_printf(sc->dev, 4556183097Smav " Pin nid=%d seq=%d\n", 4557182999Smav as[i].pins[j], j); 4558182999Smav } 4559182999Smav } 4560182999Smav ); 4561182999Smav 4562182999Smav devinfo->function.audio.as = as; 4563182999Smav} 4564182999Smav 4565162965Sariffstatic const struct { 4566162965Sariff uint32_t model; 4567162965Sariff uint32_t id; 4568162965Sariff uint32_t set, unset; 4569162965Sariff} hdac_quirks[] = { 4570163057Sariff /* 4571163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4572163057Sariff * on few codecs (especially ALC880) seems broken or 4573163057Sariff * perhaps unsupported. 4574163057Sariff */ 4575163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4576169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4577162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4578165039Sariff HDA_QUIRK_GPIO0, 0 }, 4579178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4580178155Sariff HDA_QUIRK_GPIO0, 0 }, 4581162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4582165039Sariff HDA_QUIRK_GPIO0, 0 }, 4583165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4584165281Sariff HDA_QUIRK_GPIO0, 0 }, 4585167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4586167623Sariff HDA_QUIRK_GPIO0, 0 }, 4587169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4588169277Sariff HDA_QUIRK_GPIO0, 0 }, 4589163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4590163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4591178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4592163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4593169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4594169277Sariff HDA_QUIRK_OVREF, 0 }, 4595169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4596169277Sariff HDA_QUIRK_OVREF, 0 }, 4597169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4598169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4599165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4600165281Sariff HDA_QUIRK_GPIO1, 0 }, 4601164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4602182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4603164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4604164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4605173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4606173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4607165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4608165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4609183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4610180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4611184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4612184483Smav HDA_QUIRK_GPIO2, 0 }, 4613183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4614178155Sariff HDA_QUIRK_GPIO0, 0 }, 4615169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4616169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4617170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4618170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4619186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4620182999Smav 0, HDA_QUIRK_FORCESTEREO } 4621162965Sariff}; 4622162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4623162965Sariff 4624162922Sariffstatic void 4625162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4626162922Sariff{ 4627162922Sariff struct hdac_widget *w; 4628162965Sariff uint32_t id, subvendor; 4629162922Sariff int i; 4630162922Sariff 4631182999Smav id = hdac_codec_id(devinfo->codec); 4632163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4633163057Sariff 4634162922Sariff /* 4635163057Sariff * Quirks 4636162922Sariff */ 4637163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4638163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4639163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4640163057Sariff continue; 4641163057Sariff if (hdac_quirks[i].set != 0) 4642163057Sariff devinfo->function.audio.quirks |= 4643163057Sariff hdac_quirks[i].set; 4644163057Sariff if (hdac_quirks[i].unset != 0) 4645163057Sariff devinfo->function.audio.quirks &= 4646163057Sariff ~(hdac_quirks[i].unset); 4647163057Sariff } 4648163057Sariff 4649162922Sariff switch (id) { 4650166965Sariff case HDA_CODEC_ALC883: 4651166965Sariff /* 4652166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4653166965Sariff * Clear vref cap for jack connectivity. 4654166965Sariff */ 4655166965Sariff w = hdac_widget_get(devinfo, 24); 4656166965Sariff if (w != NULL && w->enable != 0 && w->type == 4657166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4658166965Sariff (w->wclass.pin.config & 4659166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4660166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4661166965Sariff w->wclass.pin.cap &= ~( 4662166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4663166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4664166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4665166965Sariff w = hdac_widget_get(devinfo, 25); 4666166965Sariff if (w != NULL && w->enable != 0 && w->type == 4667166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4668166965Sariff (w->wclass.pin.config & 4669166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4670166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4671166965Sariff w->wclass.pin.cap &= ~( 4672166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4673166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4674166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4675166965Sariff /* 4676166965Sariff * nid: 26 = Line-in, leave it alone. 4677166965Sariff */ 4678166965Sariff break; 4679187196Smav case HDA_CODEC_AD1983: 4680187196Smav /* 4681187202Smav * This codec has several possible usages, but none 4682187202Smav * fit the parser best. Help parser to choose better. 4683187196Smav */ 4684187196Smav /* Disable direct unmixed playback to get pcm volume. */ 4685187196Smav w = hdac_widget_get(devinfo, 5); 4686187196Smav if (w != NULL) 4687187196Smav w->connsenable[0] = 0; 4688187196Smav w = hdac_widget_get(devinfo, 6); 4689187196Smav if (w != NULL) 4690187196Smav w->connsenable[0] = 0; 4691187196Smav w = hdac_widget_get(devinfo, 11); 4692187196Smav if (w != NULL) 4693187196Smav w->connsenable[0] = 0; 4694187196Smav /* Disable mic and line selectors. */ 4695187196Smav w = hdac_widget_get(devinfo, 12); 4696187196Smav if (w != NULL) 4697187196Smav w->connsenable[1] = 0; 4698187196Smav w = hdac_widget_get(devinfo, 13); 4699187196Smav if (w != NULL) 4700187196Smav w->connsenable[1] = 0; 4701187196Smav /* Disable recording from mono playback mix. */ 4702187196Smav w = hdac_widget_get(devinfo, 20); 4703187196Smav if (w != NULL) 4704187196Smav w->connsenable[3] = 0; 4705187196Smav break; 4706162922Sariff case HDA_CODEC_AD1986A: 4707186503Smav /* 4708186503Smav * This codec has overcomplicated input mixing. 4709186503Smav * Make some cleaning there. 4710186503Smav */ 4711186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4712186503Smav w = hdac_widget_get(devinfo, 43); 4713186503Smav if (w != NULL) 4714186503Smav w->enable = 0; 4715186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4716186503Smav w = hdac_widget_get(devinfo, 39); 4717186503Smav if (w != NULL) 4718186503Smav w->enable = 0; 4719186503Smav w = hdac_widget_get(devinfo, 40); 4720186503Smav if (w != NULL) 4721186503Smav w->enable = 0; 4722186503Smav w = hdac_widget_get(devinfo, 41); 4723186503Smav if (w != NULL) 4724186503Smav w->enable = 0; 4725186503Smav w = hdac_widget_get(devinfo, 42); 4726186503Smav if (w != NULL) 4727186503Smav w->enable = 0; 4728186503Smav /* Disable duplicate mixer node connector. */ 4729186503Smav w = hdac_widget_get(devinfo, 15); 4730186503Smav if (w != NULL) 4731186503Smav w->connsenable[3] = 0; 4732186503Smav 4733182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4734178155Sariff /* 4735178155Sariff * This is just plain ridiculous.. There 4736178155Sariff * are several A8 series that share the same 4737178155Sariff * pci id but works differently (EAPD). 4738178155Sariff */ 4739178155Sariff w = hdac_widget_get(devinfo, 26); 4740178155Sariff if (w != NULL && w->type == 4741178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4742178155Sariff (w->wclass.pin.config & 4743178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4744178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4745178155Sariff devinfo->function.audio.quirks &= 4746178155Sariff ~HDA_QUIRK_EAPDINV; 4747169277Sariff } 4748162922Sariff break; 4749184230Smav case HDA_CODEC_AD1981HD: 4750184230Smav /* 4751184230Smav * This codec has very unusual design with several 4752184254Smav * points inappropriate for the present parser. 4753184230Smav */ 4754184230Smav /* Disable recording from mono playback mix. */ 4755184230Smav w = hdac_widget_get(devinfo, 21); 4756184230Smav if (w != NULL) 4757184230Smav w->connsenable[3] = 0; 4758184230Smav /* Disable rear to front mic mixer, use separately. */ 4759184230Smav w = hdac_widget_get(devinfo, 31); 4760184230Smav if (w != NULL) 4761184230Smav w->enable = 0; 4762184230Smav /* Disable playback mixer, use direct bypass. */ 4763184230Smav w = hdac_widget_get(devinfo, 14); 4764184230Smav if (w != NULL) 4765184230Smav w->enable = 0; 4766184230Smav break; 4767182999Smav } 4768182999Smav} 4769182999Smav 4770182999Smav/* 4771182999Smav * Trace path from DAC to pin. 4772182999Smav */ 4773182999Smavstatic nid_t 4774182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4775182999Smav int dupseq, int min, int only, int depth) 4776182999Smav{ 4777182999Smav struct hdac_widget *w; 4778182999Smav int i, im = -1; 4779182999Smav nid_t m = 0, ret; 4780182999Smav 4781182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4782182999Smav return (0); 4783182999Smav w = hdac_widget_get(devinfo, nid); 4784182999Smav if (w == NULL || w->enable == 0) 4785182999Smav return (0); 4786183097Smav HDA_BOOTHVERBOSE( 4787182999Smav if (!only) { 4788182999Smav device_printf(devinfo->codec->sc->dev, 4789182999Smav " %*stracing via nid %d\n", 4790182999Smav depth + 1, "", w->nid); 4791169277Sariff } 4792182999Smav ); 4793182999Smav /* Use only unused widgets */ 4794182999Smav if (w->bindas >= 0 && w->bindas != as) { 4795183097Smav HDA_BOOTHVERBOSE( 4796182999Smav if (!only) { 4797182999Smav device_printf(devinfo->codec->sc->dev, 4798182999Smav " %*snid %d busy by association %d\n", 4799182999Smav depth + 1, "", w->nid, w->bindas); 4800182999Smav } 4801182999Smav ); 4802182999Smav return (0); 4803182999Smav } 4804182999Smav if (dupseq < 0) { 4805182999Smav if (w->bindseqmask != 0) { 4806183097Smav HDA_BOOTHVERBOSE( 4807182999Smav if (!only) { 4808182999Smav device_printf(devinfo->codec->sc->dev, 4809182999Smav " %*snid %d busy by seqmask %x\n", 4810182999Smav depth + 1, "", w->nid, w->bindseqmask); 4811182999Smav } 4812182999Smav ); 4813182999Smav return (0); 4814169277Sariff } 4815182999Smav } else { 4816182999Smav /* If this is headphones - allow duplicate first pin. */ 4817182999Smav if (w->bindseqmask != 0 && 4818182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4819183097Smav HDA_BOOTHVERBOSE( 4820182999Smav device_printf(devinfo->codec->sc->dev, 4821182999Smav " %*snid %d busy by seqmask %x\n", 4822182999Smav depth + 1, "", w->nid, w->bindseqmask); 4823182999Smav ); 4824182999Smav return (0); 4825169277Sariff } 4826182999Smav } 4827182999Smav 4828182999Smav switch (w->type) { 4829182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4830182999Smav /* Do not traverse input. AD1988 has digital monitor 4831182999Smav for which we are not ready. */ 4832169277Sariff break; 4833182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4834182999Smav /* If we are tracing HP take only dac of first pin. */ 4835182999Smav if ((only == 0 || only == w->nid) && 4836182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4837182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4838182999Smav m = w->nid; 4839178155Sariff break; 4840182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4841182999Smav if (depth > 0) 4842169277Sariff break; 4843182999Smav /* Fall */ 4844182999Smav default: 4845182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4846182999Smav for (i = 0; i < w->nconns; i++) { 4847182999Smav if (w->connsenable[i] == 0) 4848162922Sariff continue; 4849182999Smav if (w->selconn != -1 && w->selconn != i) 4850162922Sariff continue; 4851182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4852182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4853182999Smav if (m == 0 || ret < m) { 4854182999Smav m = ret; 4855182999Smav im = i; 4856182999Smav } 4857182999Smav if (only || dupseq >= 0) 4858182999Smav break; 4859182999Smav } 4860162922Sariff } 4861182999Smav if (m && only && ((w->nconns > 1 && 4862182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4863182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4864182999Smav w->selconn = im; 4865162922Sariff break; 4866182999Smav } 4867182999Smav if (m && only) { 4868182999Smav w->bindas = as; 4869182999Smav w->bindseqmask |= (1 << seq); 4870182999Smav } 4871183097Smav HDA_BOOTHVERBOSE( 4872182999Smav if (!only) { 4873182999Smav device_printf(devinfo->codec->sc->dev, 4874182999Smav " %*snid %d returned %d\n", 4875182999Smav depth + 1, "", w->nid, m); 4876182999Smav } 4877182999Smav ); 4878182999Smav return (m); 4879182999Smav} 4880162922Sariff 4881182999Smav/* 4882182999Smav * Trace path from widget to ADC. 4883182999Smav */ 4884182999Smavstatic nid_t 4885182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4886182999Smav int only, int depth) 4887182999Smav{ 4888182999Smav struct hdac_widget *w, *wc; 4889182999Smav int i, j; 4890182999Smav nid_t res = 0; 4891182999Smav 4892182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4893182999Smav return (0); 4894182999Smav w = hdac_widget_get(devinfo, nid); 4895182999Smav if (w == NULL || w->enable == 0) 4896182999Smav return (0); 4897183097Smav HDA_BOOTHVERBOSE( 4898182999Smav device_printf(devinfo->codec->sc->dev, 4899182999Smav " %*stracing via nid %d\n", 4900182999Smav depth + 1, "", w->nid); 4901182999Smav ); 4902182999Smav /* Use only unused widgets */ 4903182999Smav if (w->bindas >= 0 && w->bindas != as) { 4904183097Smav HDA_BOOTHVERBOSE( 4905182999Smav device_printf(devinfo->codec->sc->dev, 4906182999Smav " %*snid %d busy by association %d\n", 4907182999Smav depth + 1, "", w->nid, w->bindas); 4908182999Smav ); 4909182999Smav return (0); 4910182999Smav } 4911182999Smav 4912182999Smav switch (w->type) { 4913182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4914182999Smav /* If we are tracing HP take only dac of first pin. */ 4915182999Smav if (only == w->nid) 4916182999Smav res = 1; 4917162922Sariff break; 4918182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4919182999Smav if (depth > 0) 4920182999Smav break; 4921182999Smav /* Fall */ 4922182999Smav default: 4923182999Smav /* Try to find reachable ADCs with specified nid. */ 4924182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4925182999Smav wc = hdac_widget_get(devinfo, j); 4926182999Smav if (wc == NULL || wc->enable == 0) 4927182999Smav continue; 4928182999Smav for (i = 0; i < wc->nconns; i++) { 4929182999Smav if (wc->connsenable[i] == 0) 4930182999Smav continue; 4931182999Smav if (wc->conns[i] != nid) 4932182999Smav continue; 4933182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 4934182999Smav j, only, depth + 1) != 0) { 4935182999Smav res = 1; 4936182999Smav if (((wc->nconns > 1 && 4937182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4938182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 4939182999Smav wc->selconn == -1) 4940182999Smav wc->selconn = i; 4941182999Smav } 4942182999Smav } 4943169277Sariff } 4944169277Sariff break; 4945162922Sariff } 4946182999Smav if (res) { 4947182999Smav w->bindas = as; 4948182999Smav w->bindseqmask |= (1 << seq); 4949182999Smav } 4950183097Smav HDA_BOOTHVERBOSE( 4951182999Smav device_printf(devinfo->codec->sc->dev, 4952182999Smav " %*snid %d returned %d\n", 4953182999Smav depth + 1, "", w->nid, res); 4954182999Smav ); 4955182999Smav return (res); 4956162922Sariff} 4957162922Sariff 4958182999Smav/* 4959182999Smav * Erase trace path of the specified association. 4960182999Smav */ 4961182999Smavstatic void 4962182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 4963182999Smav{ 4964182999Smav struct hdac_widget *w; 4965182999Smav int i; 4966182999Smav 4967182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4968182999Smav w = hdac_widget_get(devinfo, i); 4969182999Smav if (w == NULL || w->enable == 0) 4970182999Smav continue; 4971182999Smav if (w->bindas == as) { 4972182999Smav if (seq >= 0) { 4973182999Smav w->bindseqmask &= ~(1 << seq); 4974182999Smav if (w->bindseqmask == 0) { 4975182999Smav w->bindas = -1; 4976182999Smav w->selconn = -1; 4977182999Smav } 4978182999Smav } else { 4979182999Smav w->bindas = -1; 4980182999Smav w->bindseqmask = 0; 4981182999Smav w->selconn = -1; 4982182999Smav } 4983182999Smav } 4984182999Smav } 4985182999Smav} 4986182999Smav 4987182999Smav/* 4988182999Smav * Trace association path from DAC to output 4989182999Smav */ 4990162922Sariffstatic int 4991182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 4992162922Sariff{ 4993182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4994182999Smav int i, hpredir; 4995182999Smav nid_t min, res; 4996162922Sariff 4997182999Smav /* Find next pin */ 4998185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 4999182999Smav ; 5000188510Smav /* Check if there is no any left. If so - we succeeded. */ 5001182999Smav if (i == 16) 5002182999Smav return (1); 5003182999Smav 5004182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 5005182999Smav min = 0; 5006182999Smav res = 0; 5007182999Smav do { 5008183097Smav HDA_BOOTHVERBOSE( 5009182999Smav device_printf(devinfo->codec->sc->dev, 5010182999Smav " Tracing pin %d with min nid %d", 5011182999Smav ases[as].pins[i], min); 5012182999Smav if (hpredir >= 0) 5013183097Smav printf(" and hpredir %d", hpredir); 5014183097Smav printf("\n"); 5015182999Smav ); 5016182999Smav /* Trace this pin taking min nid into account. */ 5017182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 5018182999Smav ases[as].pins[i], hpredir, min, 0, 0); 5019182999Smav if (res == 0) { 5020182999Smav /* If we failed - return to previous and redo it. */ 5021182999Smav HDA_BOOTVERBOSE( 5022182999Smav device_printf(devinfo->codec->sc->dev, 5023182999Smav " Unable to trace pin %d seq %d with min " 5024183097Smav "nid %d", 5025183097Smav ases[as].pins[i], i, min); 5026183097Smav if (hpredir >= 0) 5027183097Smav printf(" and hpredir %d", hpredir); 5028183097Smav printf("\n"); 5029182999Smav ); 5030182999Smav return (0); 5031162922Sariff } 5032182999Smav HDA_BOOTVERBOSE( 5033182999Smav device_printf(devinfo->codec->sc->dev, 5034183097Smav " Pin %d traced to DAC %d", 5035183097Smav ases[as].pins[i], res); 5036183097Smav if (hpredir >= 0) 5037183097Smav printf(" and hpredir %d", hpredir); 5038183097Smav if (ases[as].fakeredir) 5039183097Smav printf(" with fake redirection"); 5040183097Smav printf("\n"); 5041182999Smav ); 5042182999Smav /* Trace again to mark the path */ 5043182999Smav hdac_audio_trace_dac(devinfo, as, i, 5044182999Smav ases[as].pins[i], hpredir, min, res, 0); 5045182999Smav ases[as].dacs[i] = res; 5046188510Smav /* We succeeded, so call next. */ 5047182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 5048182999Smav return (1); 5049182999Smav /* If next failed, we should retry with next min */ 5050182999Smav hdac_audio_undo_trace(devinfo, as, i); 5051182999Smav ases[as].dacs[i] = 0; 5052182999Smav min = res + 1; 5053182999Smav } while (1); 5054162922Sariff} 5055162922Sariff 5056182999Smav/* 5057182999Smav * Trace association path from input to ADC 5058182999Smav */ 5059162922Sariffstatic int 5060182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 5061162922Sariff{ 5062182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5063162922Sariff struct hdac_widget *w; 5064182999Smav int i, j, k; 5065162922Sariff 5066182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5067182999Smav w = hdac_widget_get(devinfo, j); 5068182999Smav if (w == NULL || w->enable == 0) 5069182999Smav continue; 5070182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5071182999Smav continue; 5072182999Smav if (w->bindas >= 0 && w->bindas != as) 5073182999Smav continue; 5074182999Smav 5075182999Smav /* Find next pin */ 5076182999Smav for (i = 0; i < 16; i++) { 5077182999Smav if (ases[as].pins[i] == 0) 5078182999Smav continue; 5079182999Smav 5080183097Smav HDA_BOOTHVERBOSE( 5081182999Smav device_printf(devinfo->codec->sc->dev, 5082182999Smav " Tracing pin %d to ADC %d\n", 5083182999Smav ases[as].pins[i], j); 5084182999Smav ); 5085182999Smav /* Trace this pin taking goal into account. */ 5086182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 5087182999Smav ases[as].pins[i], j, 0) == 0) { 5088182999Smav /* If we failed - return to previous and redo it. */ 5089182999Smav HDA_BOOTVERBOSE( 5090182999Smav device_printf(devinfo->codec->sc->dev, 5091183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 5092182999Smav ases[as].pins[i], j); 5093182999Smav ); 5094182999Smav hdac_audio_undo_trace(devinfo, as, -1); 5095182999Smav for (k = 0; k < 16; k++) 5096182999Smav ases[as].dacs[k] = 0; 5097182999Smav break; 5098162922Sariff } 5099182999Smav HDA_BOOTVERBOSE( 5100182999Smav device_printf(devinfo->codec->sc->dev, 5101183097Smav " Pin %d traced to ADC %d\n", 5102183097Smav ases[as].pins[i], j); 5103182999Smav ); 5104182999Smav ases[as].dacs[i] = j; 5105162922Sariff } 5106182999Smav if (i == 16) 5107182999Smav return (1); 5108162922Sariff } 5109182999Smav return (0); 5110162922Sariff} 5111162922Sariff 5112182999Smav/* 5113182999Smav * Trace input monitor path from mixer to output association. 5114182999Smav */ 5115183097Smavstatic int 5116182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5117162922Sariff{ 5118182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5119182999Smav struct hdac_widget *w, *wc; 5120182999Smav int i, j; 5121182999Smav nid_t res = 0; 5122162922Sariff 5123162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5124162922Sariff return (0); 5125162922Sariff w = hdac_widget_get(devinfo, nid); 5126162922Sariff if (w == NULL || w->enable == 0) 5127162922Sariff return (0); 5128183097Smav HDA_BOOTHVERBOSE( 5129182999Smav device_printf(devinfo->codec->sc->dev, 5130182999Smav " %*stracing via nid %d\n", 5131182999Smav depth + 1, "", w->nid); 5132182999Smav ); 5133182999Smav /* Use only unused widgets */ 5134182999Smav if (depth > 0 && w->bindas != -1) { 5135182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5136183097Smav HDA_BOOTHVERBOSE( 5137182999Smav device_printf(devinfo->codec->sc->dev, 5138182999Smav " %*snid %d found output association %d\n", 5139182999Smav depth + 1, "", w->nid, w->bindas); 5140182999Smav ); 5141182999Smav return (1); 5142182999Smav } else { 5143183097Smav HDA_BOOTHVERBOSE( 5144182999Smav device_printf(devinfo->codec->sc->dev, 5145182999Smav " %*snid %d busy by input association %d\n", 5146182999Smav depth + 1, "", w->nid, w->bindas); 5147182999Smav ); 5148182999Smav return (0); 5149182999Smav } 5150182999Smav } 5151182999Smav 5152162922Sariff switch (w->type) { 5153162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5154182999Smav /* Do not traverse input. AD1988 has digital monitor 5155182999Smav for which we are not ready. */ 5156162922Sariff break; 5157162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5158182999Smav if (depth > 0) 5159182999Smav break; 5160182999Smav /* Fall */ 5161182999Smav default: 5162182999Smav /* Try to find reachable ADCs with specified nid. */ 5163182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5164182999Smav wc = hdac_widget_get(devinfo, j); 5165182999Smav if (wc == NULL || wc->enable == 0) 5166182999Smav continue; 5167182999Smav for (i = 0; i < wc->nconns; i++) { 5168182999Smav if (wc->connsenable[i] == 0) 5169182999Smav continue; 5170182999Smav if (wc->conns[i] != nid) 5171182999Smav continue; 5172182999Smav if (hdac_audio_trace_to_out(devinfo, 5173182999Smav j, depth + 1) != 0) { 5174182999Smav res = 1; 5175182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5176182999Smav wc->selconn == -1) 5177182999Smav wc->selconn = i; 5178182999Smav } 5179182999Smav } 5180162922Sariff } 5181162922Sariff break; 5182182999Smav } 5183182999Smav if (res) 5184182999Smav w->bindas = -2; 5185182999Smav 5186183097Smav HDA_BOOTHVERBOSE( 5187182999Smav device_printf(devinfo->codec->sc->dev, 5188182999Smav " %*snid %d returned %d\n", 5189182999Smav depth + 1, "", w->nid, res); 5190182999Smav ); 5191182999Smav return (res); 5192182999Smav} 5193182999Smav 5194182999Smav/* 5195182999Smav * Trace extra associations (beeper, monitor) 5196182999Smav */ 5197182999Smavstatic void 5198182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5199182999Smav{ 5200182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5201182999Smav struct hdac_widget *w; 5202182999Smav int j; 5203182999Smav 5204182999Smav /* Input monitor */ 5205182999Smav /* Find mixer associated with input, but supplying signal 5206182999Smav for output associations. Hope it will be input monitor. */ 5207182999Smav HDA_BOOTVERBOSE( 5208182999Smav device_printf(devinfo->codec->sc->dev, 5209182999Smav "Tracing input monitor\n"); 5210182999Smav ); 5211182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5212182999Smav w = hdac_widget_get(devinfo, j); 5213182999Smav if (w == NULL || w->enable == 0) 5214182999Smav continue; 5215182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5216182999Smav continue; 5217182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5218182999Smav continue; 5219182999Smav HDA_BOOTVERBOSE( 5220182999Smav device_printf(devinfo->codec->sc->dev, 5221182999Smav " Tracing nid %d to out\n", 5222182999Smav j); 5223182999Smav ); 5224182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5225182999Smav HDA_BOOTVERBOSE( 5226182999Smav device_printf(devinfo->codec->sc->dev, 5227182999Smav " nid %d is input monitor\n", 5228182999Smav w->nid); 5229182999Smav ); 5230182999Smav w->pflags |= HDA_ADC_MONITOR; 5231182999Smav w->ossdev = SOUND_MIXER_IMIX; 5232162922Sariff } 5233162922Sariff } 5234182999Smav 5235182999Smav /* Beeper */ 5236182999Smav HDA_BOOTVERBOSE( 5237182999Smav device_printf(devinfo->codec->sc->dev, 5238182999Smav "Tracing beeper\n"); 5239182999Smav ); 5240182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5241182999Smav w = hdac_widget_get(devinfo, j); 5242182999Smav if (w == NULL || w->enable == 0) 5243182999Smav continue; 5244182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5245182999Smav continue; 5246183097Smav HDA_BOOTHVERBOSE( 5247182999Smav device_printf(devinfo->codec->sc->dev, 5248182999Smav " Tracing nid %d to out\n", 5249182999Smav j); 5250182999Smav ); 5251183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5252183097Smav HDA_BOOTVERBOSE( 5253183097Smav device_printf(devinfo->codec->sc->dev, 5254183097Smav " nid %d traced to out\n", 5255183097Smav j); 5256183097Smav ); 5257183097Smav } 5258182999Smav w->bindas = -2; 5259182999Smav } 5260162922Sariff} 5261162922Sariff 5262182999Smav/* 5263182999Smav * Bind assotiations to PCM channels 5264182999Smav */ 5265182999Smavstatic void 5266182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5267162922Sariff{ 5268182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5269182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5270182999Smav int j, cnt = 0, free; 5271162922Sariff 5272182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5273182999Smav if (as[j].enable) 5274182999Smav cnt++; 5275182999Smav } 5276182999Smav if (sc->num_chans == 0) { 5277182999Smav sc->chans = (struct hdac_chan *)malloc( 5278182999Smav sizeof(struct hdac_chan) * cnt, 5279182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5280182999Smav if (sc->chans == NULL) { 5281182999Smav device_printf(devinfo->codec->sc->dev, 5282182999Smav "Channels memory allocation failed!\n"); 5283182999Smav return; 5284182999Smav } 5285182999Smav } else { 5286182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5287183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5288182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5289182999Smav if (sc->chans == NULL) { 5290182999Smav sc->num_chans = 0; 5291182999Smav device_printf(devinfo->codec->sc->dev, 5292182999Smav "Channels memory allocation failed!\n"); 5293182999Smav return; 5294182999Smav } 5295182999Smav } 5296182999Smav free = sc->num_chans; 5297182999Smav sc->num_chans += cnt; 5298162922Sariff 5299182999Smav for (j = free; j < free + cnt; j++) { 5300182999Smav devinfo->codec->sc->chans[j].devinfo = devinfo; 5301182999Smav devinfo->codec->sc->chans[j].as = -1; 5302182999Smav } 5303162922Sariff 5304182999Smav /* Assign associations in order of their numbers, */ 5305182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5306182999Smav if (as[j].enable == 0) 5307182999Smav continue; 5308182999Smav 5309182999Smav as[j].chan = free; 5310182999Smav devinfo->codec->sc->chans[free].as = j; 5311185225Smav devinfo->codec->sc->chans[free].dir = 5312185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5313182999Smav hdac_pcmchannel_setup(&devinfo->codec->sc->chans[free]); 5314182999Smav free++; 5315182999Smav } 5316182999Smav} 5317162922Sariff 5318182999Smavstatic void 5319182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5320182999Smav{ 5321182999Smav struct hdac_widget *w; 5322182999Smav int i; 5323182999Smav 5324182999Smav /* Disable power and volume widgets. */ 5325182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5326182999Smav w = hdac_widget_get(devinfo, i); 5327182999Smav if (w == NULL || w->enable == 0) 5328182999Smav continue; 5329182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5330182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5331182999Smav w->enable = 0; 5332183097Smav HDA_BOOTHVERBOSE( 5333182999Smav device_printf(devinfo->codec->sc->dev, 5334182999Smav " Disabling nid %d due to it's" 5335182999Smav " non-audio type.\n", 5336182999Smav w->nid); 5337182999Smav ); 5338162922Sariff } 5339182999Smav } 5340182999Smav} 5341182999Smav 5342182999Smavstatic void 5343182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5344182999Smav{ 5345182999Smav struct hdac_widget *w, *cw; 5346182999Smav struct hdac_audio_ctl *ctl; 5347182999Smav int done, found, i, j, k; 5348182999Smav 5349182999Smav /* Disable useless pins. */ 5350182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5351182999Smav w = hdac_widget_get(devinfo, i); 5352182999Smav if (w == NULL || w->enable == 0) 5353182999Smav continue; 5354184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5355184991Smav if ((w->wclass.pin.config & 5356184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5357184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5358184991Smav w->enable = 0; 5359184991Smav HDA_BOOTHVERBOSE( 5360184991Smav device_printf(devinfo->codec->sc->dev, 5361184991Smav " Disabling pin nid %d due" 5362184991Smav " to None connectivity.\n", 5363184991Smav w->nid); 5364184991Smav ); 5365184991Smav } else if ((w->wclass.pin.config & 5366184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5367184991Smav w->enable = 0; 5368184991Smav HDA_BOOTHVERBOSE( 5369184991Smav device_printf(devinfo->codec->sc->dev, 5370184991Smav " Disabling unassociated" 5371184991Smav " pin nid %d.\n", 5372184991Smav w->nid); 5373184991Smav ); 5374184991Smav } 5375182999Smav } 5376182999Smav } 5377182999Smav do { 5378182999Smav done = 1; 5379182999Smav /* Disable and mute controls for disabled widgets. */ 5380162922Sariff i = 0; 5381162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5382182999Smav if (ctl->enable == 0) 5383162922Sariff continue; 5384182999Smav if (ctl->widget->enable == 0 || 5385182999Smav (ctl->childwidget != NULL && 5386182999Smav ctl->childwidget->enable == 0)) { 5387182999Smav ctl->forcemute = 1; 5388182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5389182999Smav ctl->left = 0; 5390182999Smav ctl->right = 0; 5391182999Smav ctl->enable = 0; 5392182999Smav if (ctl->ndir == HDA_CTL_IN) 5393182999Smav ctl->widget->connsenable[ctl->index] = 0; 5394182999Smav done = 0; 5395183097Smav HDA_BOOTHVERBOSE( 5396182999Smav device_printf(devinfo->codec->sc->dev, 5397182999Smav " Disabling ctl %d nid %d cnid %d due" 5398182999Smav " to disabled widget.\n", i, 5399182999Smav ctl->widget->nid, 5400182999Smav (ctl->childwidget != NULL)? 5401182999Smav ctl->childwidget->nid:-1); 5402182999Smav ); 5403182999Smav } 5404182999Smav } 5405182999Smav /* Disable useless widgets. */ 5406182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5407182999Smav w = hdac_widget_get(devinfo, i); 5408182999Smav if (w == NULL || w->enable == 0) 5409182999Smav continue; 5410182999Smav /* Disable inputs with disabled child widgets. */ 5411182999Smav for (j = 0; j < w->nconns; j++) { 5412182999Smav if (w->connsenable[j]) { 5413182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5414182999Smav if (cw == NULL || cw->enable == 0) { 5415182999Smav w->connsenable[j] = 0; 5416183097Smav HDA_BOOTHVERBOSE( 5417182999Smav device_printf(devinfo->codec->sc->dev, 5418182999Smav " Disabling nid %d connection %d due" 5419182999Smav " to disabled child widget.\n", 5420182999Smav i, j); 5421182999Smav ); 5422163057Sariff } 5423163057Sariff } 5424162922Sariff } 5425182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5426182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5427162922Sariff continue; 5428182999Smav /* Disable mixers and selectors without inputs. */ 5429182999Smav found = 0; 5430182999Smav for (j = 0; j < w->nconns; j++) { 5431182999Smav if (w->connsenable[j]) { 5432182999Smav found = 1; 5433162922Sariff break; 5434162922Sariff } 5435182999Smav } 5436182999Smav if (found == 0) { 5437182999Smav w->enable = 0; 5438182999Smav done = 0; 5439183097Smav HDA_BOOTHVERBOSE( 5440182999Smav device_printf(devinfo->codec->sc->dev, 5441182999Smav " Disabling nid %d due to all it's" 5442182999Smav " inputs disabled.\n", w->nid); 5443182999Smav ); 5444182999Smav } 5445182999Smav /* Disable nodes without consumers. */ 5446182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5447182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5448182999Smav continue; 5449182999Smav found = 0; 5450182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5451182999Smav cw = hdac_widget_get(devinfo, k); 5452182999Smav if (cw == NULL || cw->enable == 0) 5453182999Smav continue; 5454182999Smav for (j = 0; j < cw->nconns; j++) { 5455182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5456182999Smav found = 1; 5457182999Smav break; 5458182999Smav } 5459162922Sariff } 5460162922Sariff } 5461182999Smav if (found == 0) { 5462182999Smav w->enable = 0; 5463182999Smav done = 0; 5464183097Smav HDA_BOOTHVERBOSE( 5465182999Smav device_printf(devinfo->codec->sc->dev, 5466182999Smav " Disabling nid %d due to all it's" 5467182999Smav " consumers disabled.\n", w->nid); 5468182999Smav ); 5469182999Smav } 5470162922Sariff } 5471182999Smav } while (done == 0); 5472182999Smav 5473182999Smav} 5474182999Smav 5475182999Smavstatic void 5476182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5477182999Smav{ 5478182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5479182999Smav struct hdac_widget *w, *cw; 5480182999Smav struct hdac_audio_ctl *ctl; 5481182999Smav int i, j, k; 5482182999Smav 5483182999Smav /* Disable unassosiated widgets. */ 5484182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5485182999Smav w = hdac_widget_get(devinfo, i); 5486182999Smav if (w == NULL || w->enable == 0) 5487182999Smav continue; 5488182999Smav if (w->bindas == -1) { 5489182999Smav w->enable = 0; 5490183097Smav HDA_BOOTHVERBOSE( 5491182999Smav device_printf(devinfo->codec->sc->dev, 5492182999Smav " Disabling unassociated nid %d.\n", 5493182999Smav w->nid); 5494182999Smav ); 5495182999Smav } 5496182999Smav } 5497182999Smav /* Disable input connections on input pin and 5498182999Smav * output on output. */ 5499182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5500182999Smav w = hdac_widget_get(devinfo, i); 5501182999Smav if (w == NULL || w->enable == 0) 5502182999Smav continue; 5503182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5504182999Smav continue; 5505182999Smav if (w->bindas < 0) 5506182999Smav continue; 5507182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5508182999Smav for (j = 0; j < w->nconns; j++) { 5509182999Smav if (w->connsenable[j] == 0) 5510182999Smav continue; 5511182999Smav w->connsenable[j] = 0; 5512183097Smav HDA_BOOTHVERBOSE( 5513182999Smav device_printf(devinfo->codec->sc->dev, 5514182999Smav " Disabling connection to input pin " 5515182999Smav "nid %d conn %d.\n", 5516182999Smav i, j); 5517182999Smav ); 5518162922Sariff } 5519182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5520182999Smav HDA_CTL_IN, -1, 1); 5521182999Smav if (ctl && ctl->enable) { 5522182999Smav ctl->forcemute = 1; 5523182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5524182999Smav ctl->left = 0; 5525182999Smav ctl->right = 0; 5526182999Smav ctl->enable = 0; 5527182999Smav } 5528182999Smav } else { 5529182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5530182999Smav HDA_CTL_OUT, -1, 1); 5531182999Smav if (ctl && ctl->enable) { 5532182999Smav ctl->forcemute = 1; 5533182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5534182999Smav ctl->left = 0; 5535182999Smav ctl->right = 0; 5536182999Smav ctl->enable = 0; 5537182999Smav } 5538182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5539182999Smav cw = hdac_widget_get(devinfo, k); 5540182999Smav if (cw == NULL || cw->enable == 0) 5541182999Smav continue; 5542182999Smav for (j = 0; j < cw->nconns; j++) { 5543182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5544182999Smav cw->connsenable[j] = 0; 5545183097Smav HDA_BOOTHVERBOSE( 5546182999Smav device_printf(devinfo->codec->sc->dev, 5547182999Smav " Disabling connection from output pin " 5548182999Smav "nid %d conn %d cnid %d.\n", 5549182999Smav k, j, i); 5550182999Smav ); 5551182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5552182999Smav cw->nconns > 1) 5553182999Smav continue; 5554182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5555182999Smav HDA_CTL_IN, j, 1); 5556182999Smav if (ctl && ctl->enable) { 5557182999Smav ctl->forcemute = 1; 5558182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5559182999Smav ctl->left = 0; 5560182999Smav ctl->right = 0; 5561182999Smav ctl->enable = 0; 5562182999Smav } 5563182999Smav } 5564182999Smav } 5565182999Smav } 5566162922Sariff } 5567162922Sariff } 5568162922Sariff} 5569162922Sariff 5570182999Smavstatic void 5571182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5572162922Sariff{ 5573182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5574182999Smav struct hdac_widget *w; 5575182999Smav int i, j; 5576182999Smav 5577182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5578182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5579182999Smav w = hdac_widget_get(devinfo, i); 5580182999Smav if (w == NULL || w->enable == 0) 5581182999Smav continue; 5582182999Smav if (w->nconns <= 1) 5583182999Smav continue; 5584182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5585182999Smav continue; 5586182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5587182999Smav continue; 5588182999Smav for (j = 0; j < w->nconns; j++) { 5589182999Smav if (w->connsenable[j] == 0) 5590182999Smav continue; 5591182999Smav if (w->selconn < 0 || w->selconn == j) 5592182999Smav continue; 5593182999Smav w->connsenable[j] = 0; 5594183097Smav HDA_BOOTHVERBOSE( 5595182999Smav device_printf(devinfo->codec->sc->dev, 5596182999Smav " Disabling unselected connection " 5597182999Smav "nid %d conn %d.\n", 5598182999Smav i, j); 5599182999Smav ); 5600182999Smav } 5601182999Smav } 5602182999Smav} 5603182999Smav 5604182999Smavstatic void 5605182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5606182999Smav{ 5607162922Sariff struct hdac_widget *w, *cw; 5608162922Sariff struct hdac_audio_ctl *ctl; 5609182999Smav int i, j; 5610162922Sariff 5611187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5612182999Smav /* ... using selectors */ 5613182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5614182999Smav w = hdac_widget_get(devinfo, i); 5615182999Smav if (w == NULL || w->enable == 0) 5616182999Smav continue; 5617182999Smav if (w->nconns <= 1) 5618182999Smav continue; 5619182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5620182999Smav continue; 5621182999Smav if (w->bindas == -2) 5622182999Smav continue; 5623182999Smav for (j = 0; j < w->nconns; j++) { 5624182999Smav if (w->connsenable[j] == 0) 5625182999Smav continue; 5626182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5627182999Smav if (cw == NULL || w->enable == 0) 5628182999Smav continue; 5629187052Smav if (cw->bindas == -2) 5630182999Smav continue; 5631187052Smav if (w->bindas == cw->bindas && 5632187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5633187052Smav continue; 5634182999Smav w->connsenable[j] = 0; 5635183097Smav HDA_BOOTHVERBOSE( 5636182999Smav device_printf(devinfo->codec->sc->dev, 5637182999Smav " Disabling crossassociatement connection " 5638182999Smav "nid %d conn %d cnid %d.\n", 5639182999Smav i, j, cw->nid); 5640182999Smav ); 5641182999Smav } 5642182999Smav } 5643182999Smav /* ... using controls */ 5644182999Smav i = 0; 5645182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5646182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5647182999Smav continue; 5648182999Smav if (ctl->widget->bindas == -2 || 5649182999Smav ctl->childwidget->bindas == -2) 5650182999Smav continue; 5651187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5652187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5653182999Smav ctl->forcemute = 1; 5654182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5655182999Smav ctl->left = 0; 5656182999Smav ctl->right = 0; 5657182999Smav ctl->enable = 0; 5658182999Smav if (ctl->ndir == HDA_CTL_IN) 5659182999Smav ctl->widget->connsenable[ctl->index] = 0; 5660183097Smav HDA_BOOTHVERBOSE( 5661182999Smav device_printf(devinfo->codec->sc->dev, 5662182999Smav " Disabling crossassociatement connection " 5663182999Smav "ctl %d nid %d cnid %d.\n", i, 5664182999Smav ctl->widget->nid, 5665182999Smav ctl->childwidget->nid); 5666182999Smav ); 5667182999Smav } 5668182999Smav } 5669182999Smav 5670182999Smav} 5671182999Smav 5672182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5673182999Smav 5674182999Smav/* 5675182999Smav * Find controls to control amplification for source. 5676182999Smav */ 5677182999Smavstatic int 5678182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5679182999Smav int ossdev, int ctlable, int depth, int need) 5680182999Smav{ 5681182999Smav struct hdac_widget *w, *wc; 5682182999Smav struct hdac_audio_ctl *ctl; 5683182999Smav int i, j, conns = 0, rneed; 5684182999Smav 5685162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5686182999Smav return (need); 5687162922Sariff 5688162922Sariff w = hdac_widget_get(devinfo, nid); 5689162922Sariff if (w == NULL || w->enable == 0) 5690182999Smav return (need); 5691182999Smav 5692182999Smav /* Count number of active inputs. */ 5693182999Smav if (depth > 0) { 5694182999Smav for (j = 0; j < w->nconns; j++) { 5695182999Smav if (w->connsenable[j]) 5696182999Smav conns++; 5697162922Sariff } 5698162922Sariff } 5699182999Smav 5700182999Smav /* If this is not a first step - use input mixer. 5701182999Smav Pins have common input ctl so care must be taken. */ 5702182999Smav if (depth > 0 && ctlable && (conns == 1 || 5703182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5704182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5705182999Smav index, 1); 5706182999Smav if (ctl) { 5707182999Smav if (HDA_CTL_GIVE(ctl) & need) 5708182999Smav ctl->ossmask |= (1 << ossdev); 5709182999Smav else 5710182999Smav ctl->possmask |= (1 << ossdev); 5711182999Smav need &= ~HDA_CTL_GIVE(ctl); 5712182999Smav } 5713182999Smav } 5714182999Smav 5715182999Smav /* If widget has own ossdev - not traverse it. 5716182999Smav It will be traversed on it's own. */ 5717182999Smav if (w->ossdev >= 0 && depth > 0) 5718182999Smav return (need); 5719182999Smav 5720182999Smav /* We must not traverse pin */ 5721182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5722182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5723182999Smav depth > 0) 5724182999Smav return (need); 5725182999Smav 5726182999Smav /* record that this widget exports such signal, */ 5727182999Smav w->ossmask |= (1 << ossdev); 5728182999Smav 5729182999Smav /* If signals mixed, we can't assign controls farther. 5730182999Smav * Ignore this on depth zero. Caller must knows why. 5731182999Smav * Ignore this for static selectors if this input selected. 5732182999Smav */ 5733182999Smav if (conns > 1) 5734182999Smav ctlable = 0; 5735182999Smav 5736182999Smav if (ctlable) { 5737182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5738182999Smav if (ctl) { 5739182999Smav if (HDA_CTL_GIVE(ctl) & need) 5740182999Smav ctl->ossmask |= (1 << ossdev); 5741182999Smav else 5742182999Smav ctl->possmask |= (1 << ossdev); 5743182999Smav need &= ~HDA_CTL_GIVE(ctl); 5744182999Smav } 5745182999Smav } 5746182999Smav 5747182999Smav rneed = 0; 5748182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5749182999Smav wc = hdac_widget_get(devinfo, i); 5750182999Smav if (wc == NULL || wc->enable == 0) 5751162922Sariff continue; 5752182999Smav for (j = 0; j < wc->nconns; j++) { 5753182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5754182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5755182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5756182999Smav } 5757162922Sariff } 5758162922Sariff } 5759182999Smav rneed &= need; 5760182999Smav 5761182999Smav return (rneed); 5762162922Sariff} 5763162922Sariff 5764182999Smav/* 5765182999Smav * Find controls to control amplification for destination. 5766182999Smav */ 5767182999Smavstatic void 5768182999Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, 5769182999Smav int ossdev, int depth, int need) 5770162922Sariff{ 5771182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5772182999Smav struct hdac_widget *w, *wc; 5773182999Smav struct hdac_audio_ctl *ctl; 5774182999Smav int i, j, consumers; 5775182999Smav 5776162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5777182999Smav return; 5778162922Sariff 5779162922Sariff w = hdac_widget_get(devinfo, nid); 5780162922Sariff if (w == NULL || w->enable == 0) 5781182999Smav return; 5782182999Smav 5783182999Smav if (depth > 0) { 5784182999Smav /* If this node produce output for several consumers, 5785182999Smav we can't touch it. */ 5786182999Smav consumers = 0; 5787182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5788182999Smav wc = hdac_widget_get(devinfo, i); 5789182999Smav if (wc == NULL || wc->enable == 0) 5790182999Smav continue; 5791182999Smav for (j = 0; j < wc->nconns; j++) { 5792182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5793182999Smav consumers++; 5794182999Smav } 5795182999Smav } 5796182999Smav /* The only exception is if real HP redirection is configured 5797182999Smav and this is a duplication point. 5798182999Smav XXX: Actually exception is not completely correct. 5799182999Smav XXX: Duplication point check is not perfect. */ 5800182999Smav if ((consumers == 2 && (w->bindas < 0 || 5801182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5802182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5803182999Smav consumers > 2) 5804182999Smav return; 5805182999Smav 5806182999Smav /* Else use it's output mixer. */ 5807182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5808182999Smav HDA_CTL_OUT, -1, 1); 5809182999Smav if (ctl) { 5810182999Smav if (HDA_CTL_GIVE(ctl) & need) 5811182999Smav ctl->ossmask |= (1 << ossdev); 5812182999Smav else 5813182999Smav ctl->possmask |= (1 << ossdev); 5814182999Smav need &= ~HDA_CTL_GIVE(ctl); 5815182999Smav } 5816182999Smav } 5817182999Smav 5818182999Smav /* We must not traverse pin */ 5819182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5820182999Smav depth > 0) 5821182999Smav return; 5822182999Smav 5823162922Sariff for (i = 0; i < w->nconns; i++) { 5824182999Smav int tneed = need; 5825182999Smav if (w->connsenable[i] == 0) 5826162922Sariff continue; 5827182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5828182999Smav HDA_CTL_IN, i, 1); 5829182999Smav if (ctl) { 5830182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 5831182999Smav ctl->ossmask |= (1 << ossdev); 5832182999Smav else 5833182999Smav ctl->possmask |= (1 << ossdev); 5834182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 5835162922Sariff } 5836182999Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev, 5837182999Smav depth + 1, tneed); 5838162922Sariff } 5839162922Sariff} 5840162922Sariff 5841182999Smav/* 5842182999Smav * Assign OSS names to sound sources 5843182999Smav */ 5844182999Smavstatic void 5845182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 5846162922Sariff{ 5847182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5848182999Smav struct hdac_widget *w; 5849182999Smav int i, j; 5850182999Smav int type = -1, use, used = 0; 5851182999Smav static const int types[7][13] = { 5852182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5853182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 5854182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 5855182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 5856182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 5857182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 5858182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 5859182999Smav -1 }, /* digital */ 5860182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5861182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 5862182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 5863182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 5864182999Smav -1 } /* others */ 5865182999Smav }; 5866162922Sariff 5867182999Smav /* Surely known names */ 5868162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5869162922Sariff w = hdac_widget_get(devinfo, i); 5870162922Sariff if (w == NULL || w->enable == 0) 5871162922Sariff continue; 5872182999Smav if (w->bindas == -1) 5873182999Smav continue; 5874182999Smav use = -1; 5875182999Smav switch (w->type) { 5876182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5877182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5878182999Smav break; 5879182999Smav type = -1; 5880182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5881182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 5882182999Smav type = 0; 5883182999Smav break; 5884182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5885182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 5886182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 5887182999Smav break; 5888182999Smav type = 1; 5889182999Smav break; 5890182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 5891182999Smav type = 3; 5892182999Smav break; 5893182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5894182999Smav type = 4; 5895182999Smav break; 5896182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 5897182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 5898182999Smav type = 5; 5899182999Smav break; 5900182999Smav } 5901182999Smav if (type == -1) 5902182999Smav break; 5903182999Smav j = 0; 5904182999Smav while (types[type][j] >= 0 && 5905182999Smav (used & (1 << types[type][j])) != 0) { 5906182999Smav j++; 5907182999Smav } 5908182999Smav if (types[type][j] >= 0) 5909182999Smav use = types[type][j]; 5910182999Smav break; 5911182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5912182999Smav use = SOUND_MIXER_PCM; 5913182999Smav break; 5914182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 5915182999Smav use = SOUND_MIXER_SPEAKER; 5916182999Smav break; 5917182999Smav default: 5918182999Smav break; 5919182999Smav } 5920182999Smav if (use >= 0) { 5921182999Smav w->ossdev = use; 5922182999Smav used |= (1 << use); 5923182999Smav } 5924182999Smav } 5925182999Smav /* Semi-known names */ 5926182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5927182999Smav w = hdac_widget_get(devinfo, i); 5928182999Smav if (w == NULL || w->enable == 0) 5929182999Smav continue; 5930182999Smav if (w->ossdev >= 0) 5931182999Smav continue; 5932182999Smav if (w->bindas == -1) 5933182999Smav continue; 5934162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5935162922Sariff continue; 5936182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5937162922Sariff continue; 5938182999Smav type = -1; 5939182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5940182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 5941182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5942182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 5943182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 5944182999Smav type = 0; 5945182999Smav break; 5946182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5947182999Smav type = 2; 5948182999Smav break; 5949182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 5950182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 5951182999Smav type = 5; 5952182999Smav break; 5953182999Smav } 5954182999Smav if (type == -1) 5955182999Smav break; 5956182999Smav j = 0; 5957182999Smav while (types[type][j] >= 0 && 5958182999Smav (used & (1 << types[type][j])) != 0) { 5959182999Smav j++; 5960182999Smav } 5961182999Smav if (types[type][j] >= 0) { 5962182999Smav w->ossdev = types[type][j]; 5963182999Smav used |= (1 << types[type][j]); 5964182999Smav } 5965182999Smav } 5966182999Smav /* Others */ 5967182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5968182999Smav w = hdac_widget_get(devinfo, i); 5969182999Smav if (w == NULL || w->enable == 0) 5970162922Sariff continue; 5971182999Smav if (w->ossdev >= 0) 5972182999Smav continue; 5973182999Smav if (w->bindas == -1) 5974182999Smav continue; 5975182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5976182999Smav continue; 5977182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5978182999Smav continue; 5979182999Smav j = 0; 5980182999Smav while (types[6][j] >= 0 && 5981182999Smav (used & (1 << types[6][j])) != 0) { 5982182999Smav j++; 5983162922Sariff } 5984182999Smav if (types[6][j] >= 0) { 5985182999Smav w->ossdev = types[6][j]; 5986182999Smav used |= (1 << types[6][j]); 5987182999Smav } 5988162922Sariff } 5989162922Sariff} 5990162922Sariff 5991162922Sariffstatic void 5992162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5993162922Sariff{ 5994182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5995182999Smav int j, res; 5996162922Sariff 5997182999Smav /* Trace all associations in order of their numbers, */ 5998182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5999182999Smav if (as[j].enable == 0) 6000182999Smav continue; 6001163057Sariff HDA_BOOTVERBOSE( 6002162922Sariff device_printf(devinfo->codec->sc->dev, 6003182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6004162922Sariff ); 6005182999Smav if (as[j].dir == HDA_CTL_OUT) { 6006182999Smavretry: 6007182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6008182999Smav if (res == 0 && as[j].hpredir >= 0 && 6009182999Smav as[j].fakeredir == 0) { 6010182999Smav /* If codec can't do analog HP redirection 6011182999Smav try to make it using one more DAC. */ 6012182999Smav as[j].fakeredir = 1; 6013182999Smav goto retry; 6014182999Smav } 6015182999Smav } else { 6016182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6017182999Smav } 6018182999Smav if (res) { 6019182999Smav HDA_BOOTVERBOSE( 6020182999Smav device_printf(devinfo->codec->sc->dev, 6021188510Smav "Association %d (%d) trace succeeded\n", 6022182999Smav j, as[j].index); 6023182999Smav ); 6024182999Smav } else { 6025182999Smav HDA_BOOTVERBOSE( 6026182999Smav device_printf(devinfo->codec->sc->dev, 6027182999Smav "Association %d (%d) trace failed\n", 6028182999Smav j, as[j].index); 6029182999Smav ); 6030182999Smav as[j].enable = 0; 6031182999Smav } 6032162922Sariff } 6033162922Sariff 6034182999Smav /* Trace mixer and beeper pseudo associations. */ 6035182999Smav hdac_audio_trace_as_extra(devinfo); 6036182999Smav} 6037162922Sariff 6038182999Smavstatic void 6039182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6040182999Smav{ 6041182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6042182999Smav struct hdac_audio_ctl *ctl; 6043182999Smav struct hdac_widget *w; 6044182999Smav int i; 6045162922Sariff 6046182999Smav /* Assign mixers to the tree. */ 6047162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6048162922Sariff w = hdac_widget_get(devinfo, i); 6049162922Sariff if (w == NULL || w->enable == 0) 6050162922Sariff continue; 6051182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6052182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6053182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6054182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6055182999Smav if (w->ossdev < 0) 6056182999Smav continue; 6057182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6058182999Smav w->ossdev, 1, 0, 1); 6059182999Smav } else if ((w->pflags & HDA_ADC_MONITOR) != 0) { 6060182999Smav if (w->ossdev < 0) 6061182999Smav continue; 6062182999Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6063182999Smav w->ossdev, 1, 0, 1)) { 6064182999Smav /* If we are unable to control input monitor 6065182999Smav as source - try to control it as destination. */ 6066182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6067182999Smav w->ossdev, 0, 1); 6068162922Sariff } 6069182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6070182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6071182999Smav SOUND_MIXER_RECLEV, 0, 1); 6072182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6073182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6074182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6075182999Smav SOUND_MIXER_VOLUME, 0, 1); 6076162922Sariff } 6077162922Sariff } 6078182999Smav /* Treat unrequired as possible. */ 6079182999Smav i = 0; 6080182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6081182999Smav if (ctl->ossmask == 0) 6082182999Smav ctl->ossmask = ctl->possmask; 6083182999Smav } 6084182999Smav} 6085162922Sariff 6086182999Smavstatic void 6087182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6088182999Smav{ 6089182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6090182999Smav struct hdac_widget *w; 6091182999Smav uint32_t pincap; 6092182999Smav int i; 6093182999Smav 6094182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6095182999Smav w = &devinfo->widget[i]; 6096182999Smav if (w == NULL) 6097162922Sariff continue; 6098182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6099162922Sariff continue; 6100182999Smav 6101182999Smav pincap = w->wclass.pin.cap; 6102182999Smav 6103182999Smav /* Disable everything. */ 6104182999Smav w->wclass.pin.ctrl &= ~( 6105182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6106182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6107182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6108182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6109182999Smav 6110182999Smav if (w->enable == 0 || 6111182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6112182999Smav /* Pin is unused so left it disabled. */ 6113182999Smav continue; 6114182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6115182999Smav /* Input pin, configure for input. */ 6116182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6117182999Smav w->wclass.pin.ctrl |= 6118182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6119182999Smav 6120182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6121182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6122182999Smav w->wclass.pin.ctrl |= 6123182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6124182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6125182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6126182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6127182999Smav w->wclass.pin.ctrl |= 6128182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6129182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6130182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6131182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6132182999Smav w->wclass.pin.ctrl |= 6133182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6134182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6135182999Smav } else { 6136182999Smav /* Output pin, configure for output. */ 6137182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6138182999Smav w->wclass.pin.ctrl |= 6139182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6140182999Smav 6141182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6142182999Smav (w->wclass.pin.config & 6143182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6144182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6145182999Smav w->wclass.pin.ctrl |= 6146182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6147182999Smav 6148182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6149182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6150182999Smav w->wclass.pin.ctrl |= 6151182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6152182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6153182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6154182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6155182999Smav w->wclass.pin.ctrl |= 6156182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6157182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6158182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6159182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6160182999Smav w->wclass.pin.ctrl |= 6161182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6162182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6163182999Smav } 6164162922Sariff } 6165162922Sariff} 6166162922Sariff 6167162922Sariffstatic void 6168187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6169187154Smav{ 6170187154Smav struct hdac_audio_ctl *ctl; 6171187154Smav int i, z; 6172187154Smav 6173187154Smav i = 0; 6174187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6175187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6176187154Smav /* Mute disabled and mixer controllable controls. 6177187154Smav * Last will be initialized by mixer_init(). 6178187154Smav * This expected to reduce click on startup. */ 6179187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6180187154Smav continue; 6181187154Smav } 6182187154Smav /* Init fixed controls to 0dB amplification. */ 6183187154Smav z = ctl->offset; 6184187154Smav if (z > ctl->step) 6185187154Smav z = ctl->step; 6186187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6187187154Smav } 6188187154Smav} 6189187154Smav 6190187154Smavstatic void 6191182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6192162922Sariff{ 6193162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6194162922Sariff struct hdac_widget *w; 6195164750Sariff nid_t cad; 6196182999Smav uint32_t gdata, gmask, gdir; 6197182999Smav int commitgpio, numgpio; 6198164750Sariff int i; 6199162922Sariff 6200162922Sariff cad = devinfo->codec->cad; 6201162922Sariff 6202182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6203182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6204182999Smav 0x7e7, 0), cad); 6205169277Sariff 6206187154Smav /* Commit controls. */ 6207187154Smav hdac_audio_ctl_commit(devinfo); 6208187154Smav 6209187154Smav /* Commit selectors, pins and EAPD. */ 6210187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6211187154Smav w = &devinfo->widget[i]; 6212187154Smav if (w == NULL) 6213187154Smav continue; 6214187154Smav if (w->selconn == -1) 6215187154Smav w->selconn = 0; 6216187154Smav if (w->nconns > 0) 6217187154Smav hdac_widget_connection_select(w, w->selconn); 6218187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6219187154Smav hdac_command(sc, 6220187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6221187154Smav w->wclass.pin.ctrl), cad); 6222187154Smav } 6223187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6224187154Smav uint32_t val; 6225187154Smav 6226187154Smav val = w->param.eapdbtl; 6227187154Smav if (devinfo->function.audio.quirks & 6228187154Smav HDA_QUIRK_EAPDINV) 6229187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6230187154Smav hdac_command(sc, 6231187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6232187154Smav val), cad); 6233187154Smav } 6234187154Smav } 6235187154Smav 6236187154Smav /* Commit GPIOs. */ 6237182999Smav gdata = 0; 6238182999Smav gmask = 0; 6239182999Smav gdir = 0; 6240182999Smav commitgpio = 0; 6241182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6242182999Smav devinfo->function.audio.gpio); 6243166796Sariff 6244182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6245182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6246182999Smav else { 6247182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6248182999Smav if (!(devinfo->function.audio.quirks & 6249182999Smav (1 << i))) 6250182999Smav continue; 6251182999Smav if (commitgpio == 0) { 6252182999Smav commitgpio = 1; 6253182999Smav HDA_BOOTVERBOSE( 6254182999Smav gdata = hdac_command(sc, 6255182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6256182999Smav devinfo->nid), cad); 6257182999Smav gmask = hdac_command(sc, 6258182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6259182999Smav devinfo->nid), cad); 6260182999Smav gdir = hdac_command(sc, 6261182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6262182999Smav devinfo->nid), cad); 6263182999Smav device_printf(sc->dev, 6264182999Smav "GPIO init: data=0x%08x " 6265182999Smav "mask=0x%08x dir=0x%08x\n", 6266182999Smav gdata, gmask, gdir); 6267182999Smav gdata = 0; 6268182999Smav gmask = 0; 6269182999Smav gdir = 0; 6270182999Smav ); 6271165039Sariff } 6272182999Smav gdata |= 1 << i; 6273182999Smav gmask |= 1 << i; 6274182999Smav gdir |= 1 << i; 6275165039Sariff } 6276182999Smav } 6277165039Sariff 6278182999Smav if (commitgpio != 0) { 6279182999Smav HDA_BOOTVERBOSE( 6280182999Smav device_printf(sc->dev, 6281182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6282182999Smav "dir=0x%08x\n", 6283182999Smav gdata, gmask, gdir); 6284182999Smav ); 6285182999Smav hdac_command(sc, 6286182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6287182999Smav gmask), cad); 6288182999Smav hdac_command(sc, 6289182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6290182999Smav gdir), cad); 6291182999Smav hdac_command(sc, 6292182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6293182999Smav gdata), cad); 6294162922Sariff } 6295162922Sariff} 6296162922Sariff 6297162922Sariffstatic void 6298182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6299182999Smav{ 6300182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6301182999Smav nid_t cad = devinfo->codec->cad; 6302182999Smav int i; 6303182999Smav 6304182999Smav hdac_command(sc, 6305182999Smav HDA_CMD_SET_POWER_STATE(cad, 6306182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6307182999Smav cad); 6308182999Smav DELAY(100); 6309182999Smav 6310182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6311182999Smav hdac_command(sc, 6312182999Smav HDA_CMD_SET_POWER_STATE(cad, 6313182999Smav i, HDA_CMD_POWER_STATE_D0), 6314182999Smav cad); 6315182999Smav } 6316182999Smav DELAY(1000); 6317182999Smav} 6318182999Smav 6319162922Sariffstatic int 6320182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6321162922Sariff{ 6322182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6323182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6324162922Sariff struct hdac_widget *w; 6325182999Smav uint32_t cap, fmtcap, pcmcap; 6326182999Smav int i, j, ret, max; 6327162922Sariff 6328162922Sariff ch->caps = hdac_caps; 6329162922Sariff ch->caps.fmtlist = ch->fmtlist; 6330162922Sariff ch->bit16 = 1; 6331162922Sariff ch->bit32 = 0; 6332162922Sariff ch->pcmrates[0] = 48000; 6333162922Sariff ch->pcmrates[1] = 0; 6334162922Sariff 6335162922Sariff ret = 0; 6336162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6337162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6338162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 6339162922Sariff 6340182999Smav for (i = 0; i < 16 && ret < max; i++) { 6341182999Smav /* Check as is correct */ 6342182999Smav if (ch->as < 0) 6343182999Smav break; 6344182999Smav /* Cound only present DACs */ 6345182999Smav if (as[ch->as].dacs[i] <= 0) 6346162922Sariff continue; 6347182999Smav /* Ignore duplicates */ 6348182999Smav for (j = 0; j < ret; j++) { 6349182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6350182999Smav break; 6351182999Smav } 6352182999Smav if (j < ret) 6353162922Sariff continue; 6354182999Smav 6355182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6356182999Smav if (w == NULL || w->enable == 0) 6357182999Smav continue; 6358182999Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6359182999Smav continue; 6360162922Sariff cap = w->param.supp_stream_formats; 6361182999Smav /*if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 6362162922Sariff }*/ 6363182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6364182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6365162922Sariff continue; 6366182999Smav /* Many codec does not declare AC3 support on SPDIF. 6367182999Smav I don't beleave that they doesn't support it! */ 6368182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6369182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6370164614Sariff if (ret == 0) { 6371182999Smav fmtcap = cap; 6372164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6373164614Sariff } else { 6374182999Smav fmtcap &= cap; 6375164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6376164614Sariff } 6377182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6378162922Sariff } 6379162922Sariff ch->io[ret] = -1; 6380162922Sariff 6381162922Sariff ch->supp_stream_formats = fmtcap; 6382162922Sariff ch->supp_pcm_size_rate = pcmcap; 6383162922Sariff 6384162922Sariff /* 6385162922Sariff * 8bit = 0 6386162922Sariff * 16bit = 1 6387162922Sariff * 20bit = 2 6388162922Sariff * 24bit = 3 6389162922Sariff * 32bit = 4 6390162922Sariff */ 6391162922Sariff if (ret > 0) { 6392162922Sariff i = 0; 6393182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6394182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6395182999Smav ch->bit16 = 1; 6396182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6397182999Smav ch->bit16 = 0; 6398182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6399182999Smav ch->bit32 = 4; 6400182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6401182999Smav ch->bit32 = 3; 6402182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6403182999Smav ch->bit32 = 2; 6404182999Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 6405182999Smav ch->fmtlist[i++] = AFMT_S16_LE; 6406182999Smav ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 6407182999Smav if (ch->bit32 > 0) { 6408182999Smav if (!(devinfo->function.audio.quirks & 6409182999Smav HDA_QUIRK_FORCESTEREO)) 6410182999Smav ch->fmtlist[i++] = AFMT_S32_LE; 6411182999Smav ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 6412182999Smav } 6413162922Sariff } 6414182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6415182999Smav ch->fmtlist[i++] = AFMT_AC3; 6416182999Smav } 6417162922Sariff ch->fmtlist[i] = 0; 6418162922Sariff i = 0; 6419182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6420162922Sariff ch->pcmrates[i++] = 8000; 6421182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6422162922Sariff ch->pcmrates[i++] = 11025; 6423182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6424162922Sariff ch->pcmrates[i++] = 16000; 6425182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6426162922Sariff ch->pcmrates[i++] = 22050; 6427182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6428162922Sariff ch->pcmrates[i++] = 32000; 6429182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6430162922Sariff ch->pcmrates[i++] = 44100; 6431182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6432162922Sariff ch->pcmrates[i++] = 48000; 6433182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6434162922Sariff ch->pcmrates[i++] = 88200; 6435182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6436162922Sariff ch->pcmrates[i++] = 96000; 6437182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6438162922Sariff ch->pcmrates[i++] = 176400; 6439182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6440162922Sariff ch->pcmrates[i++] = 192000; 6441182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6442162922Sariff ch->pcmrates[i] = 0; 6443162922Sariff if (i > 0) { 6444162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6445162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6446162922Sariff } 6447162922Sariff } 6448162922Sariff 6449162922Sariff return (ret); 6450162922Sariff} 6451162922Sariff 6452162922Sariffstatic void 6453185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6454185225Smav{ 6455185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6456185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6457185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6458185225Smav 6459185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6460185225Smav if (as[i].enable == 0) 6461185225Smav continue; 6462185225Smav if (as[i].dir == HDA_CTL_IN) { 6463185225Smav if (as[i].digital) 6464185225Smav drdev++; 6465185225Smav else 6466185225Smav ardev++; 6467185225Smav } else { 6468185225Smav if (as[i].digital) 6469185225Smav dpdev++; 6470185225Smav else 6471185225Smav apdev++; 6472185225Smav } 6473185225Smav } 6474185225Smav devinfo->function.audio.num_devs = 6475185225Smav max(ardev, apdev) + max(drdev, dpdev); 6476185225Smav devinfo->function.audio.devs = 6477185225Smav (struct hdac_pcm_devinfo *)malloc( 6478185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6479185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6480185225Smav if (devinfo->function.audio.devs == NULL) { 6481185225Smav device_printf(sc->dev, 6482185225Smav "Unable to allocate memory for devices\n"); 6483185225Smav return; 6484185225Smav } 6485185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6486185225Smav devinfo->function.audio.devs[i].index = i; 6487185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6488185225Smav devinfo->function.audio.devs[i].play = -1; 6489185225Smav devinfo->function.audio.devs[i].rec = -1; 6490185225Smav devinfo->function.audio.devs[i].digital = 2; 6491185225Smav } 6492185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6493185225Smav if (as[i].enable == 0) 6494185225Smav continue; 6495185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6496185225Smav if (devinfo->function.audio.devs[j].digital != 2 && 6497185225Smav devinfo->function.audio.devs[j].digital != 6498185225Smav as[i].digital) 6499185225Smav continue; 6500185225Smav if (as[i].dir == HDA_CTL_IN) { 6501185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6502185225Smav continue; 6503185225Smav devinfo->function.audio.devs[j].rec 6504185225Smav = as[i].chan; 6505185225Smav } else { 6506185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6507185225Smav continue; 6508185225Smav devinfo->function.audio.devs[j].play 6509185225Smav = as[i].chan; 6510185225Smav } 6511185225Smav sc->chans[as[i].chan].pdevinfo = 6512185225Smav &devinfo->function.audio.devs[j]; 6513185225Smav devinfo->function.audio.devs[j].digital = 6514185225Smav as[i].digital; 6515185225Smav break; 6516185225Smav } 6517185225Smav } 6518185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6519185225Smav struct hdac_pcm_devinfo *pdevinfo = 6520185225Smav &devinfo->function.audio.devs[i]; 6521185225Smav pdevinfo->dev = 6522185225Smav device_add_child(sc->dev, "pcm", -1); 6523185225Smav device_set_ivars(pdevinfo->dev, 6524185225Smav (void *)pdevinfo); 6525185225Smav } 6526185225Smav} 6527185225Smav 6528185225Smavstatic void 6529182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6530162922Sariff{ 6531182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6532162922Sariff struct hdac_audio_ctl *ctl; 6533162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6534182999Smav char buf[64]; 6535182999Smav int i, j, printed; 6536162922Sariff 6537162922Sariff if (flag == 0) { 6538182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6539162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6540182999Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN | 6541182999Smav SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6542162922Sariff } 6543162922Sariff 6544182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6545182999Smav if ((flag & (1 << j)) == 0) 6546162922Sariff continue; 6547182999Smav i = 0; 6548182999Smav printed = 0; 6549182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6550182999Smav if (ctl->enable == 0 || 6551182999Smav ctl->widget->enable == 0) 6552182999Smav continue; 6553182999Smav if (!((pdevinfo->play >= 0 && 6554182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6555182999Smav (pdevinfo->rec >= 0 && 6556182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6557182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6558182999Smav continue; 6559182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6560182999Smav continue; 6561182999Smav 6562182999Smav if (printed == 0) { 6563182999Smav device_printf(pdevinfo->dev, "\n"); 6564182999Smav if (banner != NULL) { 6565182999Smav device_printf(pdevinfo->dev, "%s", banner); 6566182999Smav } else { 6567182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6568182999Smav } 6569182999Smav printf(" (OSS: %s)\n", 6570182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6571182999Smav buf, sizeof(buf))); 6572182999Smav device_printf(pdevinfo->dev, " |\n"); 6573182999Smav printed = 1; 6574162922Sariff } 6575182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6576182999Smav ctl->widget->nid, 6577182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6578182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6579182999Smav printf(" %2d): ", ctl->index); 6580182999Smav else 6581182999Smav printf("): "); 6582182999Smav if (ctl->step > 0) { 6583182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6584182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6585182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6586182999Smav ctl->step + 1, 6587182999Smav ctl->mute?" + mute":""); 6588182999Smav } else 6589182999Smav printf("%s\n", ctl->mute?"mute":""); 6590162922Sariff } 6591162922Sariff } 6592162922Sariff} 6593162922Sariff 6594162922Sariffstatic void 6595182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6596162922Sariff{ 6597162922Sariff uint32_t cap; 6598162922Sariff 6599162922Sariff cap = fcap; 6600162922Sariff if (cap != 0) { 6601182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6602183097Smav device_printf(dev, " "); 6603162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6604162922Sariff printf(" AC3"); 6605162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6606162922Sariff printf(" FLOAT32"); 6607162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6608162922Sariff printf(" PCM"); 6609162922Sariff printf("\n"); 6610162922Sariff } 6611162922Sariff cap = pcmcap; 6612162922Sariff if (cap != 0) { 6613182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6614183097Smav device_printf(dev, " "); 6615162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6616162922Sariff printf(" 8"); 6617162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6618162922Sariff printf(" 16"); 6619162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6620162922Sariff printf(" 20"); 6621162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6622162922Sariff printf(" 24"); 6623162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6624162922Sariff printf(" 32"); 6625183097Smav printf(" bits,"); 6626162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6627162922Sariff printf(" 8"); 6628162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6629162922Sariff printf(" 11"); 6630162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6631162922Sariff printf(" 16"); 6632162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6633162922Sariff printf(" 22"); 6634162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6635162922Sariff printf(" 32"); 6636162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6637162922Sariff printf(" 44"); 6638162922Sariff printf(" 48"); 6639162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6640162922Sariff printf(" 88"); 6641162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6642162922Sariff printf(" 96"); 6643162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6644162922Sariff printf(" 176"); 6645162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6646162922Sariff printf(" 192"); 6647183097Smav printf(" KHz\n"); 6648162922Sariff } 6649162922Sariff} 6650162922Sariff 6651162922Sariffstatic void 6652162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6653162922Sariff{ 6654183097Smav uint32_t pincap; 6655162922Sariff 6656162922Sariff pincap = w->wclass.pin.cap; 6657162922Sariff 6658162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6659162922Sariff device_printf(sc->dev, " "); 6660162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6661162922Sariff printf(" ISC"); 6662162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6663162922Sariff printf(" TRQD"); 6664162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6665162922Sariff printf(" PDC"); 6666162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6667162922Sariff printf(" HP"); 6668162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6669162922Sariff printf(" OUT"); 6670162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6671162922Sariff printf(" IN"); 6672162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6673162922Sariff printf(" BAL"); 6674165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6675165069Sariff printf(" VREF["); 6676165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6677165069Sariff printf(" 50"); 6678165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6679165069Sariff printf(" 80"); 6680165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6681165069Sariff printf(" 100"); 6682165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6683165069Sariff printf(" GROUND"); 6684165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6685165069Sariff printf(" HIZ"); 6686165069Sariff printf(" ]"); 6687165069Sariff } 6688162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6689162922Sariff printf(" EAPD"); 6690162922Sariff printf("\n"); 6691162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6692162922Sariff w->wclass.pin.config); 6693162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6694162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6695162922Sariff printf(" HP"); 6696162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6697162922Sariff printf(" IN"); 6698162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6699162922Sariff printf(" OUT"); 6700182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6701182999Smav printf(" VREFs"); 6702162922Sariff printf("\n"); 6703162922Sariff} 6704162922Sariff 6705162922Sariffstatic void 6706182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6707182999Smav{ 6708182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6709182999Smav 6710183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6711182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6712182999Smav w->nid, conf, 6713182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6714182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6715182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6716182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6717182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6718182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6719182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6720182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6721182999Smav (w->enable == 0)?" [DISABLED]":""); 6722182999Smav} 6723182999Smav 6724182999Smavstatic void 6725182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6726182999Smav{ 6727182999Smav struct hdac_widget *w; 6728182999Smav int i; 6729182999Smav 6730182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6731182999Smav w = hdac_widget_get(devinfo, i); 6732182999Smav if (w == NULL) 6733182999Smav continue; 6734182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6735182999Smav continue; 6736182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6737182999Smav } 6738182999Smav} 6739182999Smav 6740182999Smavstatic void 6741162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6742162922Sariff{ 6743163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6744162922Sariff device_printf(sc->dev, " " 6745162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6746162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6747162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6748162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6749162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6750162922Sariff} 6751162922Sariff 6752162922Sariffstatic void 6753162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6754162922Sariff{ 6755162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6756182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6757162922Sariff struct hdac_widget *w, *cw; 6758182999Smav char buf[64]; 6759162922Sariff int i, j; 6760162922Sariff 6761162922Sariff device_printf(sc->dev, "\n"); 6762162922Sariff device_printf(sc->dev, "Default Parameter\n"); 6763162922Sariff device_printf(sc->dev, "-----------------\n"); 6764182999Smav hdac_dump_audio_formats(sc->dev, 6765162922Sariff devinfo->function.audio.supp_stream_formats, 6766162922Sariff devinfo->function.audio.supp_pcm_size_rate); 6767162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 6768162922Sariff devinfo->function.audio.inamp_cap); 6769162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 6770162922Sariff devinfo->function.audio.outamp_cap); 6771162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6772162922Sariff w = hdac_widget_get(devinfo, i); 6773162922Sariff if (w == NULL) { 6774162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 6775162922Sariff continue; 6776162922Sariff } 6777162922Sariff device_printf(sc->dev, "\n"); 6778183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 6779162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 6780183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 6781183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 6782162922Sariff w->param.widget_cap); 6783183097Smav if (w->param.widget_cap & 0x0ee1) { 6784183097Smav device_printf(sc->dev, " "); 6785183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 6786183097Smav printf(" LRSWAP"); 6787183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 6788183097Smav printf(" PWR"); 6789183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6790183097Smav printf(" DIGITAL"); 6791183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 6792183097Smav printf(" UNSOL"); 6793183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 6794183097Smav printf(" PROC"); 6795183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 6796183097Smav printf(" STRIPE"); 6797183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6798183097Smav printf(" STEREO"); 6799183097Smav printf("\n"); 6800183097Smav } 6801183097Smav if (w->bindas != -1) { 6802183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 6803183097Smav w->bindas, w->bindseqmask); 6804183097Smav } 6805183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 6806183097Smav device_printf(sc->dev, " OSS: %s", 6807183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 6808183097Smav if (w->ossdev >= 0) 6809183097Smav printf(" (%s)", ossname[w->ossdev]); 6810183097Smav printf("\n"); 6811183097Smav } 6812162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6813162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6814182999Smav hdac_dump_audio_formats(sc->dev, 6815162922Sariff w->param.supp_stream_formats, 6816162922Sariff w->param.supp_pcm_size_rate); 6817162922Sariff } else if (w->type == 6818162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6819162922Sariff hdac_dump_pin(sc, w); 6820162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 6821162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 6822162922Sariff w->param.eapdbtl); 6823163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 6824163057Sariff w->param.outamp_cap != 0) 6825162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 6826163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 6827163057Sariff w->param.inamp_cap != 0) 6828162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 6829183097Smav if (w->nconns > 0) { 6830183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 6831182999Smav device_printf(sc->dev, " |\n"); 6832183097Smav } 6833162922Sariff for (j = 0; j < w->nconns; j++) { 6834162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 6835182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 6836182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 6837162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 6838162922Sariff if (cw == NULL) 6839162922Sariff printf(" [UNKNOWN]"); 6840162922Sariff else if (cw->enable == 0) 6841162922Sariff printf(" [DISABLED]"); 6842162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 6843162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 6844162922Sariff printf(" (selected)"); 6845162922Sariff printf("\n"); 6846162922Sariff } 6847162922Sariff } 6848162922Sariff 6849162922Sariff} 6850162922Sariff 6851182999Smavstatic void 6852182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 6853163057Sariff{ 6854182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6855163057Sariff struct hdac_widget *w, *cw; 6856182999Smav char buf[64]; 6857182999Smav int i, printed = 0; 6858163057Sariff 6859163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 6860182999Smav return; 6861163057Sariff 6862163057Sariff w = hdac_widget_get(devinfo, nid); 6863182999Smav if (w == NULL || w->enable == 0) 6864182999Smav return; 6865163057Sariff 6866182999Smav if (depth == 0) 6867182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 6868182999Smav else 6869182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 6870182999Smav printf("nid=%d [%s]", w->nid, w->name); 6871163057Sariff 6872182999Smav if (depth > 0) { 6873182999Smav if (w->ossmask == 0) { 6874182999Smav printf("\n"); 6875182999Smav return; 6876163057Sariff } 6877182999Smav printf(" [src: %s]", 6878182999Smav hdac_audio_ctl_ossmixer_mask2allname( 6879182999Smav w->ossmask, buf, sizeof(buf))); 6880182999Smav if (w->ossdev >= 0) { 6881182999Smav printf("\n"); 6882182999Smav return; 6883182999Smav } 6884163057Sariff } 6885182999Smav printf("\n"); 6886182999Smav 6887182999Smav for (i = 0; i < w->nconns; i++) { 6888182999Smav if (w->connsenable[i] == 0) 6889182999Smav continue; 6890182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 6891182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 6892182999Smav continue; 6893182999Smav if (printed == 0) { 6894182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 6895182999Smav printed = 1; 6896182999Smav } 6897182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 6898182999Smav } 6899163057Sariff 6900163057Sariff} 6901163057Sariff 6902162922Sariffstatic void 6903182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 6904162922Sariff{ 6905182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6906182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6907163057Sariff struct hdac_widget *w; 6908163057Sariff int i, printed = 0; 6909163057Sariff 6910182999Smav if (pdevinfo->play < 0) 6911182999Smav return; 6912182999Smav 6913163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6914163057Sariff w = hdac_widget_get(devinfo, i); 6915163057Sariff if (w == NULL || w->enable == 0) 6916163057Sariff continue; 6917182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6918163057Sariff continue; 6919182999Smav if (w->bindas != sc->chans[pdevinfo->play].as) 6920182999Smav continue; 6921163057Sariff if (printed == 0) { 6922163057Sariff printed = 1; 6923182999Smav device_printf(pdevinfo->dev, "\n"); 6924182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6925163057Sariff } 6926182999Smav device_printf(pdevinfo->dev, "\n"); 6927182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6928163057Sariff } 6929162922Sariff} 6930162922Sariff 6931162922Sariffstatic void 6932182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 6933162922Sariff{ 6934182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6935162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6936182999Smav struct hdac_widget *w; 6937182999Smav int i; 6938162922Sariff int printed = 0; 6939162922Sariff 6940182999Smav if (pdevinfo->rec < 0) 6941182999Smav return; 6942182999Smav 6943162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6944162922Sariff w = hdac_widget_get(devinfo, i); 6945162922Sariff if (w == NULL || w->enable == 0) 6946162922Sariff continue; 6947182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 6948162922Sariff continue; 6949182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 6950182999Smav continue; 6951162922Sariff if (printed == 0) { 6952162922Sariff printed = 1; 6953182999Smav device_printf(pdevinfo->dev, "\n"); 6954182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6955162922Sariff } 6956182999Smav device_printf(pdevinfo->dev, "\n"); 6957182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6958182999Smav } 6959182999Smav} 6960182999Smav 6961182999Smavstatic void 6962182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 6963182999Smav{ 6964182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6965182999Smav struct hdac_widget *w; 6966182999Smav int i; 6967182999Smav int printed = 0; 6968182999Smav 6969182999Smav if (pdevinfo->index != 0) 6970182999Smav return; 6971182999Smav 6972182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6973182999Smav w = hdac_widget_get(devinfo, i); 6974182999Smav if (w == NULL || w->enable == 0) 6975182999Smav continue; 6976182999Smav if ((w->pflags & HDA_ADC_MONITOR) == 0) 6977182999Smav continue; 6978182999Smav if (printed == 0) { 6979182999Smav printed = 1; 6980182999Smav device_printf(pdevinfo->dev, "\n"); 6981182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 6982162922Sariff } 6983182999Smav device_printf(pdevinfo->dev, "\n"); 6984182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6985162922Sariff } 6986162922Sariff} 6987162922Sariff 6988162922Sariffstatic void 6989182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 6990162922Sariff{ 6991182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 6992162922Sariff nid_t *nids; 6993182999Smav int i; 6994162922Sariff 6995182999Smav if (pdevinfo->play >= 0) { 6996182999Smav i = pdevinfo->play; 6997182999Smav device_printf(pdevinfo->dev, "\n"); 6998182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6999182999Smav device_printf(pdevinfo->dev, "\n"); 7000182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7001182999Smav sc->chans[i].supp_pcm_size_rate); 7002182999Smav device_printf(pdevinfo->dev, " DAC:"); 7003182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7004162922Sariff printf(" %d", *nids); 7005162922Sariff printf("\n"); 7006162922Sariff } 7007182999Smav if (pdevinfo->rec >= 0) { 7008182999Smav i = pdevinfo->rec; 7009182999Smav device_printf(pdevinfo->dev, "\n"); 7010182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7011182999Smav device_printf(pdevinfo->dev, "\n"); 7012182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7013182999Smav sc->chans[i].supp_pcm_size_rate); 7014182999Smav device_printf(pdevinfo->dev, " ADC:"); 7015182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7016162922Sariff printf(" %d", *nids); 7017162922Sariff printf("\n"); 7018162922Sariff } 7019162922Sariff} 7020162922Sariff 7021162922Sariffstatic void 7022163057Sariffhdac_release_resources(struct hdac_softc *sc) 7023163057Sariff{ 7024182999Smav int i, j; 7025163057Sariff 7026163057Sariff if (sc == NULL) 7027163057Sariff return; 7028163057Sariff 7029163057Sariff hdac_lock(sc); 7030169277Sariff sc->polling = 0; 7031169277Sariff sc->poll_ival = 0; 7032170721Sariff callout_stop(&sc->poll_hda); 7033169277Sariff callout_stop(&sc->poll_hdac); 7034169277Sariff callout_stop(&sc->poll_jack); 7035182999Smav hdac_reset(sc, 0); 7036163057Sariff hdac_unlock(sc); 7037171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7038170721Sariff callout_drain(&sc->poll_hda); 7039169277Sariff callout_drain(&sc->poll_hdac); 7040169277Sariff callout_drain(&sc->poll_jack); 7041163057Sariff 7042169277Sariff hdac_irq_free(sc); 7043169277Sariff 7044182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7045182999Smav if (sc->codecs[i] == NULL) 7046163057Sariff continue; 7047182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7048182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7049182999Smav if (sc->codecs[i]->fgs[j].node_type == 7050182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7051182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7052182999Smav M_HDAC); 7053182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7054182999Smav M_HDAC); 7055182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7056182999Smav M_HDAC); 7057182999Smav } 7058182999Smav } 7059182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7060182999Smav free(sc->codecs[i], M_HDAC); 7061163057Sariff sc->codecs[i] = NULL; 7062163057Sariff } 7063163057Sariff 7064169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7065169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7066169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7067182999Smav for (i = 0; i < sc->num_chans; i++) { 7068182999Smav if (sc->chans[i].blkcnt > 0) 7069182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7070182999Smav } 7071182999Smav free(sc->chans, M_HDAC); 7072167702Sariff if (sc->chan_dmat != NULL) { 7073167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7074167702Sariff sc->chan_dmat = NULL; 7075167702Sariff } 7076163057Sariff hdac_mem_free(sc); 7077169277Sariff snd_mtxfree(sc->lock); 7078163057Sariff} 7079163057Sariff 7080163057Sariff/* This function surely going to make its way into upper level someday. */ 7081163057Sariffstatic void 7082163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7083163057Sariff{ 7084163057Sariff const char *res = NULL; 7085163057Sariff int i = 0, j, k, len, inv; 7086163057Sariff 7087163057Sariff if (on != NULL) 7088163057Sariff *on = 0; 7089163057Sariff if (off != NULL) 7090163057Sariff *off = 0; 7091163057Sariff if (sc == NULL) 7092163057Sariff return; 7093163057Sariff if (resource_string_value(device_get_name(sc->dev), 7094163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7095163057Sariff return; 7096163057Sariff if (!(res != NULL && strlen(res) > 0)) 7097163057Sariff return; 7098163057Sariff HDA_BOOTVERBOSE( 7099182999Smav device_printf(sc->dev, "HDA Config:"); 7100163057Sariff ); 7101163057Sariff for (;;) { 7102163057Sariff while (res[i] != '\0' && 7103163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7104163057Sariff i++; 7105163057Sariff if (res[i] == '\0') { 7106163057Sariff HDA_BOOTVERBOSE( 7107163057Sariff printf("\n"); 7108163057Sariff ); 7109163057Sariff return; 7110163057Sariff } 7111163057Sariff j = i; 7112163057Sariff while (res[j] != '\0' && 7113163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7114163057Sariff j++; 7115163057Sariff len = j - i; 7116163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7117163057Sariff inv = 2; 7118163057Sariff else 7119163057Sariff inv = 0; 7120163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7121163057Sariff if (strncmp(res + i + inv, 7122163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7123163057Sariff continue; 7124163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7125187944Smav continue; 7126163057Sariff HDA_BOOTVERBOSE( 7127163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7128163057Sariff hdac_quirks_tab[k].key); 7129163057Sariff ); 7130163057Sariff if (inv == 0 && on != NULL) 7131163057Sariff *on |= hdac_quirks_tab[k].value; 7132163057Sariff else if (inv != 0 && off != NULL) 7133163057Sariff *off |= hdac_quirks_tab[k].value; 7134163057Sariff break; 7135163057Sariff } 7136163057Sariff i = j; 7137163057Sariff } 7138163057Sariff} 7139163057Sariff 7140164614Sariff#ifdef SND_DYNSYSCTL 7141164614Sariffstatic int 7142164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7143164614Sariff{ 7144164614Sariff struct hdac_softc *sc; 7145164614Sariff device_t dev; 7146164614Sariff uint32_t ctl; 7147164614Sariff int err, val; 7148164614Sariff 7149164614Sariff dev = oidp->oid_arg1; 7150182999Smav sc = device_get_softc(dev); 7151182999Smav if (sc == NULL) 7152164614Sariff return (EINVAL); 7153164614Sariff hdac_lock(sc); 7154164614Sariff val = sc->polling; 7155164614Sariff hdac_unlock(sc); 7156170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7157164614Sariff 7158169277Sariff if (err != 0 || req->newptr == NULL) 7159164614Sariff return (err); 7160164614Sariff if (val < 0 || val > 1) 7161164614Sariff return (EINVAL); 7162164614Sariff 7163164614Sariff hdac_lock(sc); 7164164614Sariff if (val != sc->polling) { 7165182999Smav if (val == 0) { 7166182999Smav callout_stop(&sc->poll_hda); 7167164614Sariff callout_stop(&sc->poll_hdac); 7168169277Sariff hdac_unlock(sc); 7169182999Smav callout_drain(&sc->poll_hda); 7170169277Sariff callout_drain(&sc->poll_hdac); 7171169277Sariff hdac_lock(sc); 7172164614Sariff sc->polling = 0; 7173182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7174182999Smav ctl |= HDAC_INTCTL_GIE; 7175182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7176164614Sariff } else { 7177182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7178182999Smav ctl &= ~HDAC_INTCTL_GIE; 7179182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7180171141Sariff hdac_unlock(sc); 7181171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7182171141Sariff hdac_lock(sc); 7183164614Sariff sc->polling = 1; 7184182999Smav hdac_poll_reinit(sc); 7185182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7186164614Sariff } 7187164614Sariff } 7188164614Sariff hdac_unlock(sc); 7189164614Sariff 7190164614Sariff return (err); 7191164614Sariff} 7192169277Sariff 7193169277Sariffstatic int 7194169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7195169277Sariff{ 7196169277Sariff struct hdac_softc *sc; 7197169277Sariff device_t dev; 7198169277Sariff int err, val; 7199169277Sariff 7200169277Sariff dev = oidp->oid_arg1; 7201182999Smav sc = device_get_softc(dev); 7202182999Smav if (sc == NULL) 7203169277Sariff return (EINVAL); 7204169277Sariff hdac_lock(sc); 7205169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7206169277Sariff hdac_unlock(sc); 7207170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7208169277Sariff 7209169277Sariff if (err != 0 || req->newptr == NULL) 7210169277Sariff return (err); 7211169277Sariff 7212169277Sariff if (val < 1) 7213169277Sariff val = 1; 7214169277Sariff if (val > 5000) 7215169277Sariff val = 5000; 7216169277Sariff val = ((uint64_t)val * hz) / 1000; 7217169277Sariff if (val < 1) 7218169277Sariff val = 1; 7219169277Sariff if (val > (hz * 5)) 7220169277Sariff val = hz * 5; 7221169277Sariff 7222169277Sariff hdac_lock(sc); 7223169277Sariff sc->poll_ival = val; 7224169277Sariff hdac_unlock(sc); 7225169277Sariff 7226169277Sariff return (err); 7227169277Sariff} 7228169277Sariff 7229169277Sariffstatic int 7230171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7231169277Sariff{ 7232169277Sariff struct hdac_softc *sc; 7233182999Smav struct hdac_codec *codec; 7234169277Sariff struct hdac_devinfo *devinfo; 7235169277Sariff struct hdac_widget *w; 7236169277Sariff device_t dev; 7237182999Smav uint32_t res, pincap, delay; 7238182999Smav int codec_index, fg_index; 7239169277Sariff int i, err, val; 7240169277Sariff nid_t cad; 7241169277Sariff 7242169277Sariff dev = oidp->oid_arg1; 7243182999Smav sc = device_get_softc(dev); 7244182999Smav if (sc == NULL) 7245169277Sariff return (EINVAL); 7246169277Sariff val = 0; 7247170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7248169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7249169277Sariff return (err); 7250182999Smav 7251182999Smav /* XXX: Temporary. For debugging. */ 7252182999Smav if (val == 100) { 7253182999Smav hdac_suspend(dev); 7254182999Smav return (0); 7255182999Smav } else if (val == 101) { 7256182999Smav hdac_resume(dev); 7257182999Smav return (0); 7258182999Smav } 7259182999Smav 7260169277Sariff hdac_lock(sc); 7261182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7262182999Smav codec = sc->codecs[codec_index]; 7263182999Smav if (codec == NULL) 7264169277Sariff continue; 7265182999Smav cad = codec->cad; 7266182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7267182999Smav devinfo = &codec->fgs[fg_index]; 7268182999Smav if (devinfo->node_type != 7269182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7270182999Smav continue; 7271182999Smav 7272182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7273182999Smav codec_index, devinfo->nid); 7274182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7275182999Smav w = hdac_widget_get(devinfo, i); 7276182999Smav if (w == NULL || w->type != 7277182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7278182999Smav continue; 7279182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7280182999Smav pincap = w->wclass.pin.cap; 7281182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7282182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7283182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7284182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7285182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7286182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7287182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7288182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7289182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7290182999Smav delay = 0; 7291182999Smav hdac_command(sc, 7292182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7293182999Smav do { 7294182999Smav res = hdac_command(sc, 7295182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7296182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7297182999Smav break; 7298182999Smav DELAY(10); 7299182999Smav } while (++delay < 10000); 7300182999Smav } else { 7301182999Smav delay = 0; 7302182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7303182999Smav w->nid), cad); 7304182999Smav } 7305182999Smav printf(" Sense: 0x%08x", res); 7306182999Smav if (delay > 0) 7307182999Smav printf(" delay %dus", delay * 10); 7308182999Smav } 7309182999Smav printf("\n"); 7310182999Smav } 7311182999Smav device_printf(dev, 7312182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7313182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7314182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7315182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7316182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7317182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7318182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7319182999Smav device_printf(dev, " GPI:"); 7320171141Sariff res = hdac_command(sc, 7321182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7322182999Smav printf(" data=0x%08x", res); 7323182999Smav res = hdac_command(sc, 7324182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7325182999Smav cad); 7326182999Smav printf(" wake=0x%08x", res); 7327182999Smav res = hdac_command(sc, 7328182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7329182999Smav cad); 7330182999Smav printf(" unsol=0x%08x", res); 7331182999Smav res = hdac_command(sc, 7332182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7333182999Smav printf(" sticky=0x%08x\n", res); 7334182999Smav } 7335182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7336182999Smav device_printf(dev, " GPO:"); 7337182999Smav res = hdac_command(sc, 7338182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7339182999Smav printf(" data=0x%08x\n", res); 7340182999Smav } 7341182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7342182999Smav device_printf(dev, "GPIO:"); 7343182999Smav res = hdac_command(sc, 7344182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7345182999Smav printf(" data=0x%08x", res); 7346182999Smav res = hdac_command(sc, 7347182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7348182999Smav printf(" enable=0x%08x", res); 7349182999Smav res = hdac_command(sc, 7350182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7351182999Smav printf(" direction=0x%08x\n", res); 7352182999Smav res = hdac_command(sc, 7353182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7354182999Smav device_printf(dev, " wake=0x%08x", res); 7355182999Smav res = hdac_command(sc, 7356182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7357182999Smav cad); 7358182999Smav printf(" unsol=0x%08x", res); 7359182999Smav res = hdac_command(sc, 7360182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7361182999Smav printf(" sticky=0x%08x\n", res); 7362182999Smav } 7363171141Sariff } 7364169277Sariff } 7365169277Sariff hdac_unlock(sc); 7366169277Sariff return (0); 7367169277Sariff} 7368164614Sariff#endif 7369164614Sariff 7370163057Sariffstatic void 7371162922Sariffhdac_attach2(void *arg) 7372162922Sariff{ 7373182999Smav struct hdac_codec *codec; 7374162922Sariff struct hdac_softc *sc; 7375162922Sariff struct hdac_audio_ctl *ctl; 7376163057Sariff uint32_t quirks_on, quirks_off; 7377182999Smav int codec_index, fg_index; 7378185225Smav int i, dmaalloc = 0; 7379182999Smav struct hdac_devinfo *devinfo; 7380162922Sariff 7381162922Sariff sc = (struct hdac_softc *)arg; 7382162922Sariff 7383163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7384162922Sariff 7385183097Smav HDA_BOOTHVERBOSE( 7386182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7387163057Sariff quirks_on, quirks_off); 7388163057Sariff ); 7389163057Sariff 7390162922Sariff hdac_lock(sc); 7391162922Sariff 7392162922Sariff /* Remove ourselves from the config hooks */ 7393162922Sariff if (sc->intrhook.ich_func != NULL) { 7394162922Sariff config_intrhook_disestablish(&sc->intrhook); 7395162922Sariff sc->intrhook.ich_func = NULL; 7396162922Sariff } 7397162922Sariff 7398162922Sariff /* Start the corb and rirb engines */ 7399183097Smav HDA_BOOTHVERBOSE( 7400182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7401162922Sariff ); 7402162922Sariff hdac_corb_start(sc); 7403183097Smav HDA_BOOTHVERBOSE( 7404182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7405162922Sariff ); 7406162922Sariff hdac_rirb_start(sc); 7407162922Sariff 7408183097Smav HDA_BOOTHVERBOSE( 7409162922Sariff device_printf(sc->dev, 7410182999Smav "Enabling controller interrupt...\n"); 7411162922Sariff ); 7412182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7413182999Smav HDAC_GCTL_UNSOL); 7414182999Smav if (sc->polling == 0) { 7415164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7416164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7417182999Smav } else { 7418182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7419182999Smav } 7420162922Sariff DELAY(1000); 7421162922Sariff 7422183097Smav HDA_BOOTHVERBOSE( 7423172811Sariff device_printf(sc->dev, 7424182999Smav "Scanning HDA codecs ...\n"); 7425162922Sariff ); 7426182999Smav hdac_scan_codecs(sc); 7427182999Smav 7428182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7429182999Smav codec = sc->codecs[codec_index]; 7430182999Smav if (codec == NULL) 7431182999Smav continue; 7432182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7433182999Smav devinfo = &codec->fgs[fg_index]; 7434183019Smav HDA_BOOTVERBOSE( 7435183019Smav device_printf(sc->dev, "\n"); 7436183097Smav device_printf(sc->dev, 7437183097Smav "Processing %s FG cad=%d nid=%d...\n", 7438183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7439183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7440183097Smav "unknown", 7441183097Smav devinfo->codec->cad, devinfo->nid); 7442183019Smav ); 7443182999Smav if (devinfo->node_type != 7444182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7445183097Smav HDA_BOOTHVERBOSE( 7446182999Smav device_printf(sc->dev, 7447183097Smav "Powering down...\n"); 7448182999Smav ); 7449182999Smav hdac_command(sc, 7450182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7451182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7452182999Smav codec->cad); 7453182999Smav continue; 7454182999Smav } 7455162922Sariff 7456183097Smav HDA_BOOTHVERBOSE( 7457183097Smav device_printf(sc->dev, "Powering up...\n"); 7458182999Smav ); 7459182999Smav hdac_powerup(devinfo); 7460183097Smav HDA_BOOTHVERBOSE( 7461182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7462182999Smav ); 7463182999Smav hdac_audio_parse(devinfo); 7464183097Smav HDA_BOOTHVERBOSE( 7465182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7466182999Smav ); 7467182999Smav hdac_audio_ctl_parse(devinfo); 7468183097Smav HDA_BOOTHVERBOSE( 7469182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7470182999Smav ); 7471182999Smav hdac_vendor_patch_parse(devinfo); 7472182999Smav devinfo->function.audio.quirks |= quirks_on; 7473182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7474162922Sariff 7475183097Smav HDA_BOOTHVERBOSE( 7476182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7477182999Smav ); 7478182999Smav hdac_audio_disable_nonaudio(devinfo); 7479183097Smav HDA_BOOTHVERBOSE( 7480182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7481182999Smav ); 7482182999Smav hdac_audio_disable_useless(devinfo); 7483182999Smav HDA_BOOTVERBOSE( 7484182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7485182999Smav hdac_dump_pin_configs(devinfo); 7486183097Smav ); 7487183097Smav HDA_BOOTHVERBOSE( 7488182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7489182999Smav ); 7490182999Smav hdac_audio_as_parse(devinfo); 7491183097Smav HDA_BOOTHVERBOSE( 7492182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7493182999Smav ); 7494182999Smav hdac_audio_build_tree(devinfo); 7495183097Smav HDA_BOOTHVERBOSE( 7496182999Smav device_printf(sc->dev, "Disabling unassociated " 7497182999Smav "widgets...\n"); 7498182999Smav ); 7499182999Smav hdac_audio_disable_unas(devinfo); 7500183097Smav HDA_BOOTHVERBOSE( 7501182999Smav device_printf(sc->dev, "Disabling nonselected " 7502182999Smav "inputs...\n"); 7503182999Smav ); 7504182999Smav hdac_audio_disable_notselected(devinfo); 7505183097Smav HDA_BOOTHVERBOSE( 7506182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7507182999Smav ); 7508182999Smav hdac_audio_disable_useless(devinfo); 7509183097Smav HDA_BOOTHVERBOSE( 7510182999Smav device_printf(sc->dev, "Disabling " 7511182999Smav "crossassociatement connections...\n"); 7512182999Smav ); 7513182999Smav hdac_audio_disable_crossas(devinfo); 7514183097Smav HDA_BOOTHVERBOSE( 7515182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7516182999Smav ); 7517182999Smav hdac_audio_disable_useless(devinfo); 7518183097Smav HDA_BOOTHVERBOSE( 7519182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7520182999Smav ); 7521182999Smav hdac_audio_bind_as(devinfo); 7522183097Smav HDA_BOOTHVERBOSE( 7523182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7524182999Smav ); 7525182999Smav hdac_audio_assign_names(devinfo); 7526183097Smav HDA_BOOTHVERBOSE( 7527182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7528182999Smav ); 7529182999Smav hdac_audio_assign_mixers(devinfo); 7530183097Smav HDA_BOOTHVERBOSE( 7531182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7532182999Smav ); 7533182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7534183097Smav HDA_BOOTHVERBOSE( 7535182999Smav device_printf(sc->dev, "AFG commit...\n"); 7536182999Smav ); 7537182999Smav hdac_audio_commit(devinfo); 7538183097Smav HDA_BOOTHVERBOSE( 7539182999Smav device_printf(sc->dev, "HP switch init...\n"); 7540182999Smav ); 7541182999Smav hdac_hp_switch_init(devinfo); 7542182999Smav 7543182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7544182999Smav dmaalloc == 0) { 7545182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7546182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7547182999Smav HDA_BOOTVERBOSE( 7548182999Smav device_printf(sc->dev, "Failed to " 7549182999Smav "allocate DMA pos buffer " 7550182999Smav "(non-fatal)\n"); 7551182999Smav ); 7552182999Smav } else 7553182999Smav dmaalloc = 1; 7554182999Smav } 7555182999Smav 7556185225Smav HDA_BOOTHVERBOSE( 7557185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7558185225Smav ); 7559185225Smav hdac_create_pcms(devinfo); 7560182999Smav 7561182999Smav HDA_BOOTVERBOSE( 7562182999Smav if (devinfo->function.audio.quirks != 0) { 7563183097Smav device_printf(sc->dev, "FG config/quirks:"); 7564182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7565182999Smav if ((devinfo->function.audio.quirks & 7566182999Smav hdac_quirks_tab[i].value) == 7567182999Smav hdac_quirks_tab[i].value) 7568182999Smav printf(" %s", hdac_quirks_tab[i].key); 7569182999Smav } 7570182999Smav printf("\n"); 7571182999Smav } 7572182999Smav 7573182999Smav device_printf(sc->dev, "\n"); 7574182999Smav device_printf(sc->dev, "+-------------------+\n"); 7575182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7576182999Smav device_printf(sc->dev, "+-------------------+\n"); 7577182999Smav hdac_dump_nodes(devinfo); 7578183097Smav ); 7579182999Smav 7580183097Smav HDA_BOOTHVERBOSE( 7581182999Smav device_printf(sc->dev, "\n"); 7582182999Smav device_printf(sc->dev, "+------------------------+\n"); 7583182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7584182999Smav device_printf(sc->dev, "+------------------------+\n"); 7585182999Smav device_printf(sc->dev, "\n"); 7586182999Smav i = 0; 7587182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7588182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7589182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7590182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7591182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7592182999Smav ctl->index); 7593182999Smav if (ctl->childwidget != NULL) 7594182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7595182999Smav else 7596182999Smav printf(" "); 7597182999Smav printf(" ossmask=0x%08x\n", 7598182999Smav ctl->ossmask); 7599182999Smav device_printf(sc->dev, 7600182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7601182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7602182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7603182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7604182999Smav } 7605182999Smav ); 7606182999Smav } 7607162922Sariff } 7608182999Smav hdac_unlock(sc); 7609162922Sariff 7610163057Sariff HDA_BOOTVERBOSE( 7611182999Smav device_printf(sc->dev, "\n"); 7612162922Sariff ); 7613182999Smav 7614182999Smav bus_generic_attach(sc->dev); 7615182999Smav 7616182999Smav#ifdef SND_DYNSYSCTL 7617182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7618182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7619182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7620182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7621182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7622182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7623182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7624182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7625182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7626182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7627182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7628182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7629182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7630182999Smav#endif 7631182999Smav} 7632182999Smav 7633182999Smav/**************************************************************************** 7634182999Smav * int hdac_suspend(device_t) 7635182999Smav * 7636182999Smav * Suspend and power down HDA bus and codecs. 7637182999Smav ****************************************************************************/ 7638182999Smavstatic int 7639182999Smavhdac_suspend(device_t dev) 7640182999Smav{ 7641182999Smav struct hdac_softc *sc; 7642182999Smav struct hdac_codec *codec; 7643182999Smav struct hdac_devinfo *devinfo; 7644182999Smav int codec_index, fg_index, i; 7645182999Smav 7646183097Smav HDA_BOOTHVERBOSE( 7647182999Smav device_printf(dev, "Suspend...\n"); 7648162922Sariff ); 7649182999Smav 7650182999Smav sc = device_get_softc(dev); 7651182999Smav hdac_lock(sc); 7652182999Smav 7653183097Smav HDA_BOOTHVERBOSE( 7654182999Smav device_printf(dev, "Stop streams...\n"); 7655162922Sariff ); 7656182999Smav for (i = 0; i < sc->num_chans; i++) { 7657182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7658182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7659182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7660182999Smav } 7661182999Smav } 7662162922Sariff 7663182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7664182999Smav codec = sc->codecs[codec_index]; 7665182999Smav if (codec == NULL) 7666162922Sariff continue; 7667182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7668182999Smav devinfo = &codec->fgs[fg_index]; 7669183097Smav HDA_BOOTHVERBOSE( 7670182999Smav device_printf(dev, 7671182999Smav "Power down FG" 7672182999Smav " cad=%d nid=%d to the D3 state...\n", 7673182999Smav codec->cad, devinfo->nid); 7674182999Smav ); 7675182999Smav hdac_command(sc, 7676182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7677182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7678182999Smav codec->cad); 7679162922Sariff } 7680162922Sariff } 7681162922Sariff 7682183097Smav HDA_BOOTHVERBOSE( 7683182999Smav device_printf(dev, "Reset controller...\n"); 7684162922Sariff ); 7685182999Smav callout_stop(&sc->poll_hda); 7686182999Smav callout_stop(&sc->poll_hdac); 7687182999Smav callout_stop(&sc->poll_jack); 7688182999Smav hdac_reset(sc, 0); 7689182999Smav hdac_unlock(sc); 7690182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7691182999Smav callout_drain(&sc->poll_hda); 7692182999Smav callout_drain(&sc->poll_hdac); 7693182999Smav callout_drain(&sc->poll_jack); 7694162922Sariff 7695183097Smav HDA_BOOTHVERBOSE( 7696182999Smav device_printf(dev, "Suspend done\n"); 7697162922Sariff ); 7698182999Smav 7699182999Smav return (0); 7700182999Smav} 7701182999Smav 7702182999Smav/**************************************************************************** 7703182999Smav * int hdac_resume(device_t) 7704182999Smav * 7705182999Smav * Powerup and restore HDA bus and codecs state. 7706182999Smav ****************************************************************************/ 7707182999Smavstatic int 7708182999Smavhdac_resume(device_t dev) 7709182999Smav{ 7710182999Smav struct hdac_softc *sc; 7711182999Smav struct hdac_codec *codec; 7712182999Smav struct hdac_devinfo *devinfo; 7713182999Smav int codec_index, fg_index, i; 7714182999Smav 7715183097Smav HDA_BOOTHVERBOSE( 7716182999Smav device_printf(dev, "Resume...\n"); 7717162922Sariff ); 7718162922Sariff 7719182999Smav sc = device_get_softc(dev); 7720182999Smav hdac_lock(sc); 7721182999Smav 7722182999Smav /* Quiesce everything */ 7723183097Smav HDA_BOOTHVERBOSE( 7724182999Smav device_printf(dev, "Reset controller...\n"); 7725162922Sariff ); 7726182999Smav hdac_reset(sc, 1); 7727182999Smav 7728182999Smav /* Initialize the CORB and RIRB */ 7729182999Smav hdac_corb_init(sc); 7730182999Smav hdac_rirb_init(sc); 7731182999Smav 7732182999Smav /* Start the corb and rirb engines */ 7733183097Smav HDA_BOOTHVERBOSE( 7734182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7735162922Sariff ); 7736182999Smav hdac_corb_start(sc); 7737183097Smav HDA_BOOTHVERBOSE( 7738182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7739162922Sariff ); 7740182999Smav hdac_rirb_start(sc); 7741163057Sariff 7742183097Smav HDA_BOOTHVERBOSE( 7743182999Smav device_printf(dev, 7744182999Smav "Enabling controller interrupt...\n"); 7745162922Sariff ); 7746182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7747182999Smav HDAC_GCTL_UNSOL); 7748182999Smav if (sc->polling == 0) { 7749182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7750182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7751182999Smav } else { 7752182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7753182999Smav } 7754182999Smav DELAY(1000); 7755162922Sariff 7756182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7757182999Smav codec = sc->codecs[codec_index]; 7758182999Smav if (codec == NULL) 7759182999Smav continue; 7760182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7761182999Smav devinfo = &codec->fgs[fg_index]; 7762182999Smav if (devinfo->node_type != 7763182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7764183097Smav HDA_BOOTHVERBOSE( 7765182999Smav device_printf(dev, 7766182999Smav "Power down unsupported non-audio FG" 7767182999Smav " cad=%d nid=%d to the D3 state...\n", 7768182999Smav codec->cad, devinfo->nid); 7769182999Smav ); 7770182999Smav hdac_command(sc, 7771182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7772182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7773182999Smav codec->cad); 7774182999Smav continue; 7775182999Smav } 7776162922Sariff 7777183097Smav HDA_BOOTHVERBOSE( 7778182999Smav device_printf(dev, 7779182999Smav "Power up audio FG cad=%d nid=%d...\n", 7780182999Smav devinfo->codec->cad, devinfo->nid); 7781182999Smav ); 7782182999Smav hdac_powerup(devinfo); 7783183097Smav HDA_BOOTHVERBOSE( 7784182999Smav device_printf(dev, "AFG commit...\n"); 7785182999Smav ); 7786182999Smav hdac_audio_commit(devinfo); 7787183097Smav HDA_BOOTHVERBOSE( 7788182999Smav device_printf(dev, "HP switch init...\n"); 7789182999Smav ); 7790182999Smav hdac_hp_switch_init(devinfo); 7791182999Smav 7792182999Smav hdac_unlock(sc); 7793182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7794182999Smav struct hdac_pcm_devinfo *pdevinfo = 7795182999Smav &devinfo->function.audio.devs[i]; 7796183097Smav HDA_BOOTHVERBOSE( 7797182999Smav device_printf(pdevinfo->dev, 7798182999Smav "OSS mixer reinitialization...\n"); 7799182999Smav ); 7800182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 7801182999Smav device_printf(pdevinfo->dev, 7802182999Smav "unable to reinitialize the mixer\n"); 7803182999Smav } 7804182999Smav hdac_lock(sc); 7805182999Smav } 7806169277Sariff } 7807169277Sariff 7808183097Smav HDA_BOOTHVERBOSE( 7809182999Smav device_printf(dev, "Start streams...\n"); 7810163057Sariff ); 7811182999Smav for (i = 0; i < sc->num_chans; i++) { 7812182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 7813182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 7814182999Smav hdac_channel_start(sc, &sc->chans[i]); 7815182999Smav } 7816182999Smav } 7817162922Sariff 7818182999Smav hdac_unlock(sc); 7819182999Smav 7820183097Smav HDA_BOOTHVERBOSE( 7821182999Smav device_printf(dev, "Resume done\n"); 7822162922Sariff ); 7823164614Sariff 7824182999Smav return (0); 7825162922Sariff} 7826162922Sariff/**************************************************************************** 7827162922Sariff * int hdac_detach(device_t) 7828162922Sariff * 7829162922Sariff * Detach and free up resources utilized by the hdac device. 7830162922Sariff ****************************************************************************/ 7831162922Sariffstatic int 7832162922Sariffhdac_detach(device_t dev) 7833162922Sariff{ 7834182999Smav struct hdac_softc *sc; 7835185177Smav device_t *devlist; 7836185177Smav int i, devcount, error; 7837162922Sariff 7838185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 7839185177Smav return (error); 7840185177Smav for (i = 0; i < devcount; i++) { 7841185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 7842185178Smav free(devlist, M_TEMP); 7843185178Smav return (error); 7844185178Smav } 7845185177Smav } 7846185177Smav free(devlist, M_TEMP); 7847185177Smav 7848182999Smav sc = device_get_softc(dev); 7849163057Sariff hdac_release_resources(sc); 7850162922Sariff 7851162922Sariff return (0); 7852162922Sariff} 7853162922Sariff 7854184095Smavstatic int 7855184095Smavhdac_print_child(device_t dev, device_t child) 7856184095Smav{ 7857184095Smav struct hdac_pcm_devinfo *pdevinfo = 7858184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 7859184095Smav int retval; 7860184095Smav 7861184095Smav retval = bus_print_child_header(dev, child); 7862184095Smav retval += printf(" at cad %d nid %d", 7863184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 7864184095Smav retval += bus_print_child_footer(dev, child); 7865184095Smav 7866184095Smav return (retval); 7867184095Smav} 7868184095Smav 7869162922Sariffstatic device_method_t hdac_methods[] = { 7870162922Sariff /* device interface */ 7871162922Sariff DEVMETHOD(device_probe, hdac_probe), 7872162922Sariff DEVMETHOD(device_attach, hdac_attach), 7873162922Sariff DEVMETHOD(device_detach, hdac_detach), 7874182999Smav DEVMETHOD(device_suspend, hdac_suspend), 7875182999Smav DEVMETHOD(device_resume, hdac_resume), 7876184095Smav /* Bus interface */ 7877184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 7878162922Sariff { 0, 0 } 7879162922Sariff}; 7880162922Sariff 7881162922Sariffstatic driver_t hdac_driver = { 7882182999Smav "hdac", 7883162922Sariff hdac_methods, 7884182999Smav sizeof(struct hdac_softc), 7885162922Sariff}; 7886162922Sariff 7887182999Smavstatic devclass_t hdac_devclass; 7888182999Smav 7889182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 7890162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 7891162922SariffMODULE_VERSION(snd_hda, 1); 7892182999Smav 7893182999Smavstatic int 7894182999Smavhdac_pcm_probe(device_t dev) 7895182999Smav{ 7896182999Smav struct hdac_pcm_devinfo *pdevinfo = 7897182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7898182999Smav char buf[128]; 7899182999Smav 7900185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 7901182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 7902185225Smav pdevinfo->index, 7903185225Smav pdevinfo->digital?"Digital":"Analog"); 7904182999Smav device_set_desc_copy(dev, buf); 7905182999Smav return (0); 7906182999Smav} 7907182999Smav 7908182999Smavstatic int 7909182999Smavhdac_pcm_attach(device_t dev) 7910182999Smav{ 7911182999Smav struct hdac_pcm_devinfo *pdevinfo = 7912182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7913182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7914182999Smav char status[SND_STATUSLEN]; 7915182999Smav int i; 7916182999Smav 7917182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 7918182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 7919182999Smav 7920182999Smav HDA_BOOTVERBOSE( 7921182999Smav device_printf(dev, "+--------------------------------------+\n"); 7922182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 7923182999Smav device_printf(dev, "+--------------------------------------+\n"); 7924182999Smav hdac_dump_pcmchannels(pdevinfo); 7925182999Smav device_printf(dev, "\n"); 7926189876Smav device_printf(dev, "+-------------------------------+\n"); 7927189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 7928189876Smav device_printf(dev, "+-------------------------------+\n"); 7929182999Smav hdac_dump_dac(pdevinfo); 7930182999Smav hdac_dump_adc(pdevinfo); 7931182999Smav hdac_dump_mix(pdevinfo); 7932182999Smav device_printf(dev, "\n"); 7933182999Smav device_printf(dev, "+-------------------------+\n"); 7934182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 7935182999Smav device_printf(dev, "+-------------------------+\n"); 7936182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 7937182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 7938182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 7939182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 7940182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 7941182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 7942182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 7943182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 7944182999Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 7945182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 7946182999Smav device_printf(dev, "\n"); 7947182999Smav ); 7948182999Smav 7949182999Smav if (resource_int_value(device_get_name(dev), 7950182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 7951182999Smav i &= HDA_BLK_ALIGN; 7952182999Smav if (i < HDA_BLK_MIN) 7953182999Smav i = HDA_BLK_MIN; 7954182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 7955182999Smav i = 0; 7956182999Smav while (pdevinfo->chan_blkcnt >> i) 7957182999Smav i++; 7958182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 7959182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 7960182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 7961182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 7962182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 7963182999Smav } else 7964182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 7965182999Smav 7966182999Smav /* 7967182999Smav * We don't register interrupt handler with snd_setup_intr 7968182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 7969182999Smav */ 7970182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 7971182999Smav 7972183097Smav HDA_BOOTHVERBOSE( 7973182999Smav device_printf(dev, "OSS mixer initialization...\n"); 7974182999Smav ); 7975182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 7976182999Smav device_printf(dev, "Can't register mixer\n"); 7977182999Smav 7978183097Smav HDA_BOOTHVERBOSE( 7979182999Smav device_printf(dev, "Registering PCM channels...\n"); 7980182999Smav ); 7981182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 7982182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 7983182999Smav device_printf(dev, "Can't register PCM\n"); 7984182999Smav 7985182999Smav pdevinfo->registered++; 7986182999Smav 7987182999Smav if (pdevinfo->play >= 0) 7988182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 7989182999Smav if (pdevinfo->rec >= 0) 7990182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 7991182999Smav 7992184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 7993184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 7994184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 7995182999Smav pcm_setstatus(dev, status); 7996182999Smav 7997182999Smav return (0); 7998182999Smav} 7999182999Smav 8000182999Smavstatic int 8001182999Smavhdac_pcm_detach(device_t dev) 8002182999Smav{ 8003182999Smav struct hdac_pcm_devinfo *pdevinfo = 8004182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8005182999Smav int err; 8006182999Smav 8007182999Smav if (pdevinfo->registered > 0) { 8008182999Smav err = pcm_unregister(dev); 8009182999Smav if (err != 0) 8010182999Smav return (err); 8011182999Smav } 8012182999Smav 8013182999Smav return (0); 8014182999Smav} 8015182999Smav 8016182999Smavstatic device_method_t hdac_pcm_methods[] = { 8017182999Smav /* device interface */ 8018182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8019182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8020182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8021182999Smav { 0, 0 } 8022182999Smav}; 8023182999Smav 8024182999Smavstatic driver_t hdac_pcm_driver = { 8025182999Smav "pcm", 8026182999Smav hdac_pcm_methods, 8027182999Smav PCM_SOFTC_SIZE, 8028182999Smav}; 8029182999Smav 8030182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8031182999Smav 8032