hdac.c revision 190519
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 86190519Smav#define HDA_DRV_TEST_REV "20090329_0131" 87162922Sariff 88162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 190519 2009-03-29 07:10:52Z 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) 250189879Smav#define ACER_T5320_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011f) 251162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 252162922Sariff 253162965Sariff/* Asus */ 254162965Sariff#define ASUS_VENDORID 0x1043 255178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 256163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 257178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 258165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 259178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 260178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 261167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 262169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 263178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 264178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 265178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 266170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 267178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 268169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 269171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 270162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 271162922Sariff 272163257Sariff/* IBM / Lenovo */ 273163257Sariff#define IBM_VENDORID 0x1014 274163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 275163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 276162965Sariff 277164614Sariff/* Lenovo */ 278164657Sariff#define LENOVO_VENDORID 0x17aa 279164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 280182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 281172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 282164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 283163257Sariff 284164657Sariff/* Samsung */ 285164657Sariff#define SAMSUNG_VENDORID 0x144d 286164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 287164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 288164614Sariff 289164750Sariff/* Medion ? */ 290164750Sariff#define MEDION_VENDORID 0x161f 291164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 292164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 293164750Sariff 294173817Sariff/* Apple Computer Inc. */ 295173817Sariff#define APPLE_VENDORID 0x106b 296173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 297173817Sariff 298182999Smav/* Sony */ 299182999Smav#define SONY_VENDORID 0x104d 300182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 301182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 302182999Smav 303164828Sariff/* 304164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 305164828Sariff * instead of their own, which is beyond my comprehension 306164828Sariff * (see HDA_CODEC_STAC9221 below). 307164828Sariff */ 308164828Sariff#define APPLE_INTEL_MAC 0x76808384 309164828Sariff 310165281Sariff/* LG Electronics */ 311165281Sariff#define LG_VENDORID 0x1854 312165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 313165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 314165281Sariff 315165351Sariff/* Fujitsu Siemens */ 316165351Sariff#define FS_VENDORID 0x1734 317165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 318172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 319165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 320165351Sariff 321172811Sariff/* Fujitsu Limited */ 322172811Sariff#define FL_VENDORID 0x10cf 323172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 324182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 325172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 326172811Sariff 327165770Sariff/* Toshiba */ 328165770Sariff#define TOSHIBA_VENDORID 0x1179 329165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 330173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 331165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 332165770Sariff 333165992Sariff/* Micro-Star International (MSI) */ 334165992Sariff#define MSI_VENDORID 0x1462 335165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 336172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 337165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 338165992Sariff 339172811Sariff/* Giga-Byte Technology */ 340172811Sariff#define GB_VENDORID 0x1458 341172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 342172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 343172811Sariff 344169277Sariff/* Uniwill ? */ 345169277Sariff#define UNIWILL_VENDORID 0x1584 346169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 347170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 348169277Sariff 349169277Sariff 350162922Sariff/* Misc constants.. */ 351182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 352162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 353162922Sariff#define HDA_AMP_MUTE_NONE (0) 354162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 355162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 356162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 357162922Sariff 358162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 359162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 360162922Sariff 361182999Smav#define HDA_ADC_MONITOR (1 << 0) 362162922Sariff 363182999Smav#define HDA_CTL_OUT 1 364182999Smav#define HDA_CTL_IN 2 365169277Sariff 366169277Sariff#define HDA_GPIO_MAX 8 367169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 368163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 369163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 370163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 371169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 372169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 373169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 374169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 375169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 376169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 377162922Sariff 378169277Sariff/* 9 - 25 = anything else */ 379169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 380169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 381169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 382169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 383169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 384182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 385169277Sariff 386169277Sariff/* 26 - 31 = vrefs */ 387169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 388169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 389169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 390169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 391169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 392169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 393169277Sariff 394169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 395169277Sariff HDA_QUIRK_IVREF100) 396169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 397169277Sariff HDA_QUIRK_OVREF100) 398169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 399169277Sariff 400171141Sariff#if __FreeBSD_version < 600000 401171141Sariff#define taskqueue_drain(...) 402171141Sariff#endif 403171141Sariff 404163057Sariffstatic const struct { 405163057Sariff char *key; 406163057Sariff uint32_t value; 407163057Sariff} hdac_quirks_tab[] = { 408163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 409163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 410163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 411169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 412169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 413169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 414169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 415169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 416165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 417163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 418163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 419163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 420163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 421169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 422182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 423169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 424169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 425169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 426169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 427169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 428169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 429169277Sariff { "ivref", HDA_QUIRK_IVREF }, 430169277Sariff { "ovref", HDA_QUIRK_OVREF }, 431165069Sariff { "vref", HDA_QUIRK_VREF }, 432163057Sariff}; 433163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 434163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 435163057Sariff 436162922Sariff#define HDA_BDL_MIN 2 437162922Sariff#define HDA_BDL_MAX 256 438162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 439162922Sariff 440169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 441167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 442167648Sariff 443162922Sariff#define HDA_BUFSZ_MIN 4096 444162922Sariff#define HDA_BUFSZ_MAX 65536 445162922Sariff#define HDA_BUFSZ_DEFAULT 16384 446162922Sariff 447162922Sariff#define HDA_PARSE_MAXDEPTH 10 448162922Sariff 449169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 450162922Sariff 451165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 452162922Sariff 453182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 454182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 455182999Smav "White", "Other"}; 456162922Sariff 457182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 458182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 459182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 460182999Smav 461182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 462182999Smav 463162922Sariff/* Default */ 464162922Sariffstatic uint32_t hdac_fmt[] = { 465162922Sariff AFMT_STEREO | AFMT_S16_LE, 466162922Sariff 0 467162922Sariff}; 468162922Sariff 469162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 470162922Sariff 471189086Smav#define HDAC_NO_MSI 1 472189086Smav 473162922Sariffstatic const struct { 474162922Sariff uint32_t model; 475162922Sariff char *desc; 476189086Smav char flags; 477162922Sariff} hdac_devices[] = { 478189086Smav { HDA_INTEL_82801F, "Intel 82801F", 0 }, 479189086Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, 480189086Smav { HDA_INTEL_82801G, "Intel 82801G", 0 }, 481189086Smav { HDA_INTEL_82801H, "Intel 82801H", 0 }, 482189086Smav { HDA_INTEL_82801I, "Intel 82801I", 0 }, 483189086Smav { HDA_INTEL_82801J, "Intel 82801J", 0 }, 484189086Smav { HDA_INTEL_PCH, "Intel PCH", 0 }, 485189086Smav { HDA_INTEL_SCH, "Intel SCH", 0 }, 486189086Smav { HDA_NVIDIA_MCP51, "NVidia MCP51", HDAC_NO_MSI }, 487189086Smav { HDA_NVIDIA_MCP55, "NVidia MCP55", 0 }, 488189086Smav { HDA_NVIDIA_MCP61_1, "NVidia MCP61", 0 }, 489189086Smav { HDA_NVIDIA_MCP61_2, "NVidia MCP61", 0 }, 490189086Smav { HDA_NVIDIA_MCP65_1, "NVidia MCP65", 0 }, 491189086Smav { HDA_NVIDIA_MCP65_2, "NVidia MCP65", 0 }, 492189086Smav { HDA_NVIDIA_MCP67_1, "NVidia MCP67", 0 }, 493189086Smav { HDA_NVIDIA_MCP67_2, "NVidia MCP67", 0 }, 494189086Smav { HDA_NVIDIA_MCP73_1, "NVidia MCP73", 0 }, 495189086Smav { HDA_NVIDIA_MCP73_2, "NVidia MCP73", 0 }, 496189086Smav { HDA_NVIDIA_MCP78_1, "NVidia MCP78", 0 }, 497189086Smav { HDA_NVIDIA_MCP78_2, "NVidia MCP78", 0 }, 498189086Smav { HDA_NVIDIA_MCP78_3, "NVidia MCP78", 0 }, 499189086Smav { HDA_NVIDIA_MCP78_4, "NVidia MCP78", 0 }, 500189086Smav { HDA_NVIDIA_MCP79_1, "NVidia MCP79", 0 }, 501189086Smav { HDA_NVIDIA_MCP79_2, "NVidia MCP79", 0 }, 502189086Smav { HDA_NVIDIA_MCP79_3, "NVidia MCP79", 0 }, 503189086Smav { HDA_NVIDIA_MCP79_4, "NVidia MCP79", 0 }, 504189086Smav { HDA_ATI_SB450, "ATI SB450", 0 }, 505189086Smav { HDA_ATI_SB600, "ATI SB600", 0 }, 506189086Smav { HDA_ATI_RS600, "ATI RS600", 0 }, 507189086Smav { HDA_ATI_RS690, "ATI RS690", 0 }, 508189086Smav { HDA_ATI_RS780, "ATI RS780", 0 }, 509189086Smav { HDA_ATI_R600, "ATI R600", 0 }, 510189086Smav { HDA_ATI_RV610, "ATI RV610", 0 }, 511189086Smav { HDA_ATI_RV620, "ATI RV620", 0 }, 512189086Smav { HDA_ATI_RV630, "ATI RV630", 0 }, 513189086Smav { HDA_ATI_RV635, "ATI RV635", 0 }, 514189086Smav { HDA_ATI_RV710, "ATI RV710", 0 }, 515189086Smav { HDA_ATI_RV730, "ATI RV730", 0 }, 516189086Smav { HDA_ATI_RV740, "ATI RV740", 0 }, 517189086Smav { HDA_ATI_RV770, "ATI RV770", 0 }, 518189086Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0 }, 519189086Smav { HDA_SIS_966, "SiS 966", 0 }, 520189086Smav { HDA_ULI_M5461, "ULI M5461", 0 }, 521162922Sariff /* Unknown */ 522162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 523162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 524162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 525163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 526163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 527186301Smav { HDA_ULI_ALL, "ULI (Unknown)" }, 528162922Sariff}; 529162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 530162922Sariff 531162922Sariffstatic const struct { 532169277Sariff uint16_t vendor; 533169277Sariff uint8_t reg; 534169277Sariff uint8_t mask; 535169277Sariff uint8_t enable; 536169277Sariff} hdac_pcie_snoop[] = { 537169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 538169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 539169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 540169277Sariff}; 541169277Sariff#define HDAC_PCIESNOOP_LEN \ 542169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 543169277Sariff 544169277Sariffstatic const struct { 545162922Sariff uint32_t rate; 546162922Sariff int valid; 547162922Sariff uint16_t base; 548162922Sariff uint16_t mul; 549162922Sariff uint16_t div; 550162922Sariff} hda_rate_tab[] = { 551162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 552162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 553162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 554162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 555162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 556162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 557162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 558162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 559162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 560162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 561162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 562162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 563162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 564162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 565162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 566162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 567162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 568162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 569162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 570162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 571162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 572162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 573162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 574162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 575162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 576162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 577162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 578162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 579162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 580162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 581162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 582162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 583162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 584162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 585162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 586162922Sariff}; 587162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 588162922Sariff 589162922Sariff/* All codecs you can eat... */ 590162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 591162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 592162922Sariff 593162922Sariff/* Realtek */ 594162922Sariff#define REALTEK_VENDORID 0x10ec 595162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 596169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 597183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 598171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 599183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 600183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 601170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 602183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 603183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 604162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 605169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 606162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 607163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 608163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 609169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 610165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 611182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 612162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 613162922Sariff 614169277Sariff/* Analog Devices */ 615169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 616186403Smav#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) 617186403Smav#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) 618186403Smav#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) 619186403Smav#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) 620186403Smav#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) 621186403Smav#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) 622169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 623169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 624174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 625169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 626186403Smav#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) 627169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 628170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 629186403Smav#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) 630186403Smav#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) 631169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 632162922Sariff 633162922Sariff/* CMedia */ 634162922Sariff#define CMEDIA_VENDORID 0x434d 635162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 636162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 637162922Sariff 638162922Sariff/* Sigmatel */ 639162922Sariff#define SIGMATEL_VENDORID 0x8384 640182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 641182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 642182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 643182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 644182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 645182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 646182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 647182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 648183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 649183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 650183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 651183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 652183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 653183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 654183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 655182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 656183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 657183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 658183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 659183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 660183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 661183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 662183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 663183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 664182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 665162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 666182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 667183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 668162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 669162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 670183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 671183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 672183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 673183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 674183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 675183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 676183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 677183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 678183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 679162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 680162922Sariff 681183894Smav/* IDT */ 682183894Smav#define IDT_VENDORID 0x111d 683183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 684183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 685183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 686183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 687183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 688183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 689183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 690183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 691183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 692183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 693183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 694183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 695183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 696183894Smav 697182999Smav/* Silicon Image */ 698182999Smav#define SII_VENDORID 0x1095 699187020Smav#define HDA_CODEC_SII1390 HDA_CODEC_CONSTRUCT(SII, 0x1390) 700186146Smav#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) 701182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 702182999Smav 703182999Smav/* Lucent/Agere */ 704182999Smav#define AGERE_VENDORID 0x11c1 705182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 706182999Smav 707186430Smav/* Conexant */ 708162922Sariff#define CONEXANT_VENDORID 0x14f1 709186430Smav#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 710186430Smav#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 711186430Smav#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) 712162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 713162922Sariff 714169277Sariff/* VIA */ 715169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 716169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 717169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 718169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 719169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 720169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 721169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 722169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 723169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 724169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 725169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 726169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 727186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 728186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 729186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 730186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 731186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 732186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 733186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 734186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 735187020Smav#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) 736187020Smav#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) 737187020Smav#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) 738187020Smav#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) 739187020Smav#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) 740187020Smav#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) 741187020Smav#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) 742187020Smav#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) 743187020Smav#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) 744187020Smav#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) 745187020Smav#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) 746187020Smav#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) 747187020Smav#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) 748187020Smav#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) 749187020Smav#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) 750187020Smav#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) 751169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 752162922Sariff 753182999Smav/* ATI */ 754186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 755186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 756186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 757186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 758182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 759169277Sariff 760182999Smav/* NVIDIA */ 761187020Smav#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) 762187445Smav#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) 763187020Smav#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) 764187020Smav#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) 765187445Smav#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) 766182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 767182999Smav 768183894Smav/* INTEL */ 769187020Smav#define HDA_CODEC_INTELG45_1 HDA_CODEC_CONSTRUCT(INTEL, 0x2801) 770187020Smav#define HDA_CODEC_INTELG45_2 HDA_CODEC_CONSTRUCT(INTEL, 0x2802) 771187020Smav#define HDA_CODEC_INTELG45_3 HDA_CODEC_CONSTRUCT(INTEL, 0x2803) 772187020Smav#define HDA_CODEC_INTELG45_4 HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) 773183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 774183894Smav 775162922Sariff/* Codecs */ 776162922Sariffstatic const struct { 777162922Sariff uint32_t id; 778162922Sariff char *name; 779162922Sariff} hdac_codecs[] = { 780162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 781169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 782183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 783171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 784183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 785183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 786170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 787183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 788183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 789162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 790169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 791162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 792162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 793163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 794169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 795165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 796182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 797186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 798186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 799186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 800186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 801186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 802169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 803169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 804174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 805186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 806186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 807169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 808186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 809186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 810170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 811186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 812162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 813183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 814183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 815183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 816183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 817183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 818183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 819183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 820183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 821162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 822183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 823162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 824162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 825183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 826183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 827183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 828183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 829183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 830183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 831182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 832182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 833183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 834183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 835183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 836166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 837183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 838183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 839183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 840183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 841183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 842183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 843183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 844183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 845183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 846183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 847183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 848183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 849183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 850183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 851183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 852183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 853183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 854183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 855183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 856183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 857183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 858183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 859183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 860183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 861183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 862183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 863183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 864186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 865186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 866186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 867169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 868169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 869169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 870169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 871169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 872169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 873169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 874169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 875169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 876169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 877169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 878169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 879186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 880186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 881186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 882186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 883186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 884186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 885186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 886186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 887187020Smav { HDA_CODEC_VT1708S_0, "VIA VT1708S_0" }, 888187020Smav { HDA_CODEC_VT1708S_1, "VIA VT1708S_1" }, 889187020Smav { HDA_CODEC_VT1708S_2, "VIA VT1708S_2" }, 890187020Smav { HDA_CODEC_VT1708S_3, "VIA VT1708S_3" }, 891187020Smav { HDA_CODEC_VT1708S_4, "VIA VT1708S_4" }, 892187020Smav { HDA_CODEC_VT1708S_5, "VIA VT1708S_5" }, 893187020Smav { HDA_CODEC_VT1708S_6, "VIA VT1708S_6" }, 894187020Smav { HDA_CODEC_VT1708S_7, "VIA VT1708S_7" }, 895187020Smav { HDA_CODEC_VT1702_0, "VIA VT1702_0" }, 896187020Smav { HDA_CODEC_VT1702_1, "VIA VT1702_1" }, 897187020Smav { HDA_CODEC_VT1702_2, "VIA VT1702_2" }, 898187020Smav { HDA_CODEC_VT1702_3, "VIA VT1702_3" }, 899187020Smav { HDA_CODEC_VT1702_4, "VIA VT1702_4" }, 900187020Smav { HDA_CODEC_VT1702_5, "VIA VT1702_5" }, 901187020Smav { HDA_CODEC_VT1702_6, "VIA VT1702_6" }, 902187020Smav { HDA_CODEC_VT1702_7, "VIA VT1702_7" }, 903186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 904186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 905186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 906186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 907187020Smav { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, 908187445Smav { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, 909187020Smav { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, 910187445Smav { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, 911187020Smav { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, 912187020Smav { HDA_CODEC_INTELG45_1, "Intel G45 HDMI" }, 913187020Smav { HDA_CODEC_INTELG45_2, "Intel G45 HDMI" }, 914187020Smav { HDA_CODEC_INTELG45_3, "Intel G45 HDMI" }, 915187020Smav { HDA_CODEC_INTELG45_4, "Intel G45 HDMI" }, 916187020Smav { HDA_CODEC_SII1390, "Silicon Image SiI1390 HDMI" }, 917186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 918162922Sariff /* Unknown codec */ 919162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 920169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 921162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 922162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 923182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 924182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 925162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 926169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 927182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 928182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 929183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 930183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 931162922Sariff}; 932162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 933162922Sariff 934162922Sariff 935162922Sariff/**************************************************************************** 936162922Sariff * Function prototypes 937162922Sariff ****************************************************************************/ 938162922Sariffstatic void hdac_intr_handler(void *); 939182999Smavstatic int hdac_reset(struct hdac_softc *, int); 940162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 941162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 942162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 943162922Sariff struct hdac_dma *, bus_size_t); 944169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 945162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 946162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 947162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 948162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 949162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 950162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 951162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 952162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 953182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 954182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 955182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 956182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 957162922Sariff 958162922Sariffstatic void hdac_attach2(void *); 959162922Sariff 960162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 961162922Sariff uint32_t, int); 962162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 963162922Sariff struct hdac_command_list *, int); 964162922Sariff 965162922Sariffstatic int hdac_probe(device_t); 966162922Sariffstatic int hdac_attach(device_t); 967162922Sariffstatic int hdac_detach(device_t); 968182999Smavstatic int hdac_suspend(device_t); 969182999Smavstatic int hdac_resume(device_t); 970162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 971162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 972162922Sariff uint32_t, int, int); 973162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 974182999Smav nid_t, int, int, int); 975162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 976162922Sariff nid_t, nid_t, int, int, int, int, int, int); 977162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 978162922Sariff 979164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 980164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 981164614Sariff 982182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 983182999Smav 984162922Sariff#define hdac_command(a1, a2, a3) \ 985162922Sariff hdac_command_sendone_internal(a1, a2, a3) 986162922Sariff 987182999Smav#define hdac_codec_id(c) \ 988182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 989182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 990182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 991162922Sariff 992162922Sariffstatic char * 993182999Smavhdac_codec_name(struct hdac_codec *codec) 994162922Sariff{ 995162922Sariff uint32_t id; 996162922Sariff int i; 997162922Sariff 998182999Smav id = hdac_codec_id(codec); 999162922Sariff 1000162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 1001163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 1002162922Sariff return (hdac_codecs[i].name); 1003162922Sariff } 1004162922Sariff 1005162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 1006162922Sariff} 1007162922Sariff 1008162922Sariffstatic char * 1009162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 1010162922Sariff{ 1011162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 1012162922Sariff int i, first = 1; 1013162922Sariff 1014162922Sariff bzero(buf, len); 1015162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 1016162922Sariff if (mask & (1 << i)) { 1017162922Sariff if (first == 0) 1018162922Sariff strlcat(buf, ", ", len); 1019162922Sariff strlcat(buf, ossname[i], len); 1020162922Sariff first = 0; 1021162922Sariff } 1022162922Sariff } 1023182999Smav return (buf); 1024162922Sariff} 1025162922Sariff 1026162922Sariffstatic struct hdac_audio_ctl * 1027162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 1028162922Sariff{ 1029162922Sariff if (devinfo == NULL || 1030162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 1031162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 1032162922Sariff devinfo->function.audio.ctlcnt < 1 || 1033162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 1034162922Sariff return (NULL); 1035162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 1036162922Sariff} 1037162922Sariff 1038162922Sariffstatic struct hdac_audio_ctl * 1039182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 1040162922Sariff int index, int cnt) 1041162922Sariff{ 1042182999Smav struct hdac_audio_ctl *ctl; 1043182999Smav int i, found = 0; 1044162922Sariff 1045162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 1046162922Sariff return (NULL); 1047162922Sariff 1048162922Sariff i = 0; 1049162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 1050182999Smav if (ctl->enable == 0) 1051162922Sariff continue; 1052182999Smav if (ctl->widget->nid != nid) 1053162922Sariff continue; 1054182999Smav if (dir && ctl->ndir != dir) 1055182999Smav continue; 1056182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 1057182999Smav ctl->dir == ctl->ndir && ctl->index != index) 1058182999Smav continue; 1059162922Sariff found++; 1060182999Smav if (found == cnt || cnt <= 0) 1061162922Sariff return (ctl); 1062162922Sariff } 1063162922Sariff 1064182999Smav return (NULL); 1065162922Sariff} 1066162922Sariff 1067182999Smav/* 1068182999Smav * Jack detection (Speaker/HP redirection) event handler. 1069182999Smav */ 1070162922Sariffstatic void 1071162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 1072162922Sariff{ 1073182999Smav struct hdac_audio_as *as; 1074162922Sariff struct hdac_softc *sc; 1075162922Sariff struct hdac_widget *w; 1076162922Sariff struct hdac_audio_ctl *ctl; 1077182999Smav uint32_t val, res; 1078182999Smav int i, j; 1079162922Sariff nid_t cad; 1080162922Sariff 1081162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1082162922Sariff devinfo->codec->sc == NULL) 1083162922Sariff return; 1084162922Sariff 1085162922Sariff sc = devinfo->codec->sc; 1086162922Sariff cad = devinfo->codec->cad; 1087182999Smav as = devinfo->function.audio.as; 1088182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1089182999Smav if (as[i].hpredir < 0) 1090182999Smav continue; 1091182999Smav 1092182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1093182999Smav if (w == NULL || w->enable == 0 || w->type != 1094182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1095182999Smav continue; 1096162922Sariff 1097171141Sariff res = hdac_command(sc, 1098182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1099171141Sariff 1100182999Smav HDA_BOOTVERBOSE( 1101182999Smav device_printf(sc->dev, 1102182999Smav "Pin sense: nid=%d res=0x%08x\n", 1103182999Smav as[i].pins[15], res); 1104182999Smav ); 1105171141Sariff 1106182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1107182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1108182999Smav res ^= 1; 1109162922Sariff 1110182999Smav /* (Un)Mute headphone pin. */ 1111162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1112182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1113182999Smav if (ctl != NULL && ctl->mute) { 1114182999Smav /* If pin has muter - use it. */ 1115182999Smav val = (res != 0) ? 0 : 1; 1116182999Smav if (val != ctl->forcemute) { 1117182999Smav ctl->forcemute = val; 1118162922Sariff hdac_audio_ctl_amp_set(ctl, 1119182999Smav HDA_AMP_MUTE_DEFAULT, 1120182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1121162922Sariff } 1122182999Smav } else { 1123182999Smav /* If there is no muter - disable pin output. */ 1124182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1125163057Sariff if (w != NULL && w->type == 1126163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1127182999Smav if (res != 0) 1128169277Sariff val = w->wclass.pin.ctrl | 1129162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1130162922Sariff else 1131169277Sariff val = w->wclass.pin.ctrl & 1132162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1133169277Sariff if (val != w->wclass.pin.ctrl) { 1134169277Sariff w->wclass.pin.ctrl = val; 1135169277Sariff hdac_command(sc, 1136169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1137169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1138169277Sariff } 1139162922Sariff } 1140182999Smav } 1141182999Smav /* (Un)Mute other pins. */ 1142182999Smav for (j = 0; j < 15; j++) { 1143182999Smav if (as[i].pins[j] <= 0) 1144182999Smav continue; 1145182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1146182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1147182999Smav if (ctl != NULL && ctl->mute) { 1148182999Smav /* If pin has muter - use it. */ 1149182999Smav val = (res != 0) ? 1 : 0; 1150182999Smav if (val == ctl->forcemute) 1151169277Sariff continue; 1152182999Smav ctl->forcemute = val; 1153182999Smav hdac_audio_ctl_amp_set(ctl, 1154182999Smav HDA_AMP_MUTE_DEFAULT, 1155182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1156182999Smav continue; 1157162922Sariff } 1158182999Smav /* If there is no muter - disable pin output. */ 1159182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1160163057Sariff if (w != NULL && w->type == 1161163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1162182999Smav if (res != 0) 1163182999Smav val = w->wclass.pin.ctrl & 1164182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1165182999Smav else 1166182999Smav val = w->wclass.pin.ctrl | 1167182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1168169277Sariff if (val != w->wclass.pin.ctrl) { 1169169277Sariff w->wclass.pin.ctrl = val; 1170169277Sariff hdac_command(sc, 1171169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1172169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1173169277Sariff } 1174162922Sariff } 1175162922Sariff } 1176182999Smav } 1177182999Smav} 1178182999Smav 1179182999Smav/* 1180182999Smav * Callback for poll based jack detection. 1181182999Smav */ 1182182999Smavstatic void 1183182999Smavhdac_jack_poll_callback(void *arg) 1184182999Smav{ 1185182999Smav struct hdac_devinfo *devinfo = arg; 1186182999Smav struct hdac_softc *sc; 1187182999Smav 1188182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1189182999Smav devinfo->codec->sc == NULL) 1190182999Smav return; 1191182999Smav sc = devinfo->codec->sc; 1192182999Smav hdac_lock(sc); 1193182999Smav if (sc->poll_ival == 0) { 1194182999Smav hdac_unlock(sc); 1195182999Smav return; 1196182999Smav } 1197182999Smav hdac_hp_switch_handler(devinfo); 1198182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1199182999Smav hdac_jack_poll_callback, devinfo); 1200182999Smav hdac_unlock(sc); 1201182999Smav} 1202182999Smav 1203182999Smav/* 1204182999Smav * Jack detection initializer. 1205182999Smav */ 1206182999Smavstatic void 1207182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1208182999Smav{ 1209182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1210182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1211182999Smav struct hdac_widget *w; 1212182999Smav uint32_t id; 1213182999Smav int i, enable = 0, poll = 0; 1214182999Smav nid_t cad; 1215182999Smav 1216182999Smav id = hdac_codec_id(devinfo->codec); 1217182999Smav cad = devinfo->codec->cad; 1218182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1219182999Smav if (as[i].hpredir < 0) 1220182999Smav continue; 1221182999Smav 1222182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1223182999Smav if (w == NULL || w->enable == 0 || w->type != 1224182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1225182999Smav continue; 1226182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1227182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1228182999Smav device_printf(sc->dev, 1229182999Smav "No jack detection support at pin %d\n", 1230182999Smav as[i].pins[15]); 1231182999Smav continue; 1232182999Smav } 1233182999Smav enable = 1; 1234182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1235169277Sariff hdac_command(sc, 1236182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1237182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1238182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1239182999Smav } else 1240182999Smav poll = 1; 1241182999Smav HDA_BOOTVERBOSE( 1242169277Sariff device_printf(sc->dev, 1243182999Smav "Enabling headphone/speaker " 1244182999Smav "audio routing switching:\n"); 1245182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1246182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1247182999Smav ); 1248182999Smav } 1249182999Smav if (enable) { 1250182999Smav hdac_hp_switch_handler(devinfo); 1251182999Smav if (poll) { 1252182999Smav callout_reset(&sc->poll_jack, 1, 1253182999Smav hdac_jack_poll_callback, devinfo); 1254169277Sariff } 1255162922Sariff } 1256162922Sariff} 1257162922Sariff 1258182999Smav/* 1259182999Smav * Unsolicited messages handler. 1260182999Smav */ 1261162922Sariffstatic void 1262162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1263162922Sariff{ 1264162922Sariff struct hdac_softc *sc; 1265162922Sariff struct hdac_devinfo *devinfo = NULL; 1266182999Smav int i; 1267162922Sariff 1268162922Sariff if (codec == NULL || codec->sc == NULL) 1269162922Sariff return; 1270162922Sariff 1271162922Sariff sc = codec->sc; 1272162922Sariff 1273163057Sariff HDA_BOOTVERBOSE( 1274182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1275162922Sariff ); 1276162922Sariff 1277182999Smav for (i = 0; i < codec->num_fgs; i++) { 1278182999Smav if (codec->fgs[i].node_type == 1279182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1280182999Smav devinfo = &codec->fgs[i]; 1281162965Sariff break; 1282182999Smav } 1283162922Sariff } 1284162965Sariff 1285162922Sariff if (devinfo == NULL) 1286162922Sariff return; 1287162922Sariff 1288162922Sariff switch (tag) { 1289162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1290162922Sariff hdac_hp_switch_handler(devinfo); 1291162922Sariff break; 1292162922Sariff default: 1293182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1294162922Sariff break; 1295162922Sariff } 1296162922Sariff} 1297162922Sariff 1298164614Sariffstatic int 1299162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1300162922Sariff{ 1301162922Sariff /* XXX to be removed */ 1302162922Sariff#ifdef HDAC_INTR_EXTRA 1303162922Sariff uint32_t res; 1304162922Sariff#endif 1305162922Sariff 1306171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1307164614Sariff return (0); 1308162922Sariff 1309162922Sariff /* XXX to be removed */ 1310162922Sariff#ifdef HDAC_INTR_EXTRA 1311162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1312162922Sariff#endif 1313162922Sariff 1314162922Sariff /* XXX to be removed */ 1315162922Sariff#ifdef HDAC_INTR_EXTRA 1316163057Sariff HDA_BOOTVERBOSE( 1317163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1318182999Smav device_printf(ch->pdevinfo->dev, 1319163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1320163057Sariff "%08x\n", 1321163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1322163057Sariff ); 1323162922Sariff#endif 1324162922Sariff 1325162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1326163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1327162922Sariff 1328162922Sariff /* XXX to be removed */ 1329162922Sariff#ifdef HDAC_INTR_EXTRA 1330162922Sariff if (res & HDAC_SDSTS_BCIS) { 1331162922Sariff#endif 1332164614Sariff return (1); 1333162922Sariff /* XXX to be removed */ 1334162922Sariff#ifdef HDAC_INTR_EXTRA 1335162922Sariff } 1336162922Sariff#endif 1337164614Sariff 1338164614Sariff return (0); 1339162922Sariff} 1340162922Sariff 1341162922Sariff/**************************************************************************** 1342162922Sariff * void hdac_intr_handler(void *) 1343162922Sariff * 1344162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1345162922Sariff ****************************************************************************/ 1346162922Sariffstatic void 1347162922Sariffhdac_intr_handler(void *context) 1348162922Sariff{ 1349162922Sariff struct hdac_softc *sc; 1350162922Sariff uint32_t intsts; 1351162922Sariff uint8_t rirbsts; 1352164614Sariff struct hdac_rirb *rirb_base; 1353171141Sariff uint32_t trigger; 1354182999Smav int i; 1355162922Sariff 1356162922Sariff sc = (struct hdac_softc *)context; 1357162922Sariff 1358162922Sariff hdac_lock(sc); 1359164614Sariff if (sc->polling != 0) { 1360164614Sariff hdac_unlock(sc); 1361164614Sariff return; 1362164614Sariff } 1363171141Sariff 1364162922Sariff /* Do we have anything to do? */ 1365162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1366163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1367162922Sariff hdac_unlock(sc); 1368162922Sariff return; 1369162922Sariff } 1370162922Sariff 1371171141Sariff trigger = 0; 1372171141Sariff 1373162922Sariff /* Was this a controller interrupt? */ 1374163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1375162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1376162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1377162922Sariff /* Get as many responses that we can */ 1378163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1379164614Sariff HDAC_WRITE_1(&sc->mem, 1380164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1381171141Sariff if (hdac_rirb_flush(sc) != 0) 1382171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1383162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1384162922Sariff } 1385162922Sariff /* XXX to be removed */ 1386162922Sariff /* Clear interrupt and exit */ 1387162922Sariff#ifdef HDAC_INTR_EXTRA 1388162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1389162922Sariff#endif 1390162922Sariff } 1391164614Sariff 1392163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1393182999Smav for (i = 0; i < sc->num_chans; i++) { 1394182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1395182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1396182999Smav trigger |= (1 << i); 1397182999Smav } 1398162922Sariff /* XXX to be removed */ 1399162922Sariff#ifdef HDAC_INTR_EXTRA 1400164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1401164614Sariff HDAC_INTSTS_SIS_MASK); 1402162922Sariff#endif 1403162922Sariff } 1404162922Sariff 1405164614Sariff hdac_unlock(sc); 1406162922Sariff 1407182999Smav for (i = 0; i < sc->num_chans; i++) { 1408182999Smav if (trigger & (1 << i)) 1409182999Smav chn_intr(sc->chans[i].c); 1410182999Smav } 1411171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1412171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1413162922Sariff} 1414162922Sariff 1415162922Sariff/**************************************************************************** 1416182999Smav * int hdac_reset(hdac_softc *, int) 1417162922Sariff * 1418162922Sariff * Reset the hdac to a quiescent and known state. 1419162922Sariff ****************************************************************************/ 1420162922Sariffstatic int 1421182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1422162922Sariff{ 1423162922Sariff uint32_t gctl; 1424162922Sariff int count, i; 1425162922Sariff 1426162922Sariff /* 1427162922Sariff * Stop all Streams DMA engine 1428162922Sariff */ 1429162922Sariff for (i = 0; i < sc->num_iss; i++) 1430162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1431162922Sariff for (i = 0; i < sc->num_oss; i++) 1432162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1433162922Sariff for (i = 0; i < sc->num_bss; i++) 1434162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1435162922Sariff 1436162922Sariff /* 1437169277Sariff * Stop Control DMA engines. 1438162922Sariff */ 1439162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1440162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1441162922Sariff 1442162922Sariff /* 1443169277Sariff * Reset DMA position buffer. 1444169277Sariff */ 1445169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1446169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1447169277Sariff 1448169277Sariff /* 1449162922Sariff * Reset the controller. The reset must remain asserted for 1450162922Sariff * a minimum of 100us. 1451162922Sariff */ 1452162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1453162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1454162922Sariff count = 10000; 1455162922Sariff do { 1456162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1457162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1458162922Sariff break; 1459162922Sariff DELAY(10); 1460162922Sariff } while (--count); 1461162922Sariff if (gctl & HDAC_GCTL_CRST) { 1462162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1463162922Sariff return (ENXIO); 1464162922Sariff } 1465182999Smav 1466182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1467182999Smav if (!wakeup) 1468182999Smav return (0); 1469182999Smav 1470162922Sariff DELAY(100); 1471162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1472162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1473162922Sariff count = 10000; 1474162922Sariff do { 1475162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1476163057Sariff if (gctl & HDAC_GCTL_CRST) 1477162922Sariff break; 1478162922Sariff DELAY(10); 1479162922Sariff } while (--count); 1480162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1481162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1482162922Sariff return (ENXIO); 1483162922Sariff } 1484162922Sariff 1485162922Sariff /* 1486162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1487162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1488162922Sariff * computer. Let's use twice as much as necessary to make sure that 1489162922Sariff * it's reset properly. 1490162922Sariff */ 1491162922Sariff DELAY(1000); 1492162922Sariff 1493162922Sariff return (0); 1494162922Sariff} 1495162922Sariff 1496162922Sariff 1497162922Sariff/**************************************************************************** 1498162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1499162922Sariff * 1500162922Sariff * Retreive the general capabilities of the hdac; 1501162922Sariff * Number of Input Streams 1502162922Sariff * Number of Output Streams 1503162922Sariff * Number of bidirectional Streams 1504162922Sariff * 64bit ready 1505162922Sariff * CORB and RIRB sizes 1506162922Sariff ****************************************************************************/ 1507162922Sariffstatic int 1508162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1509162922Sariff{ 1510162922Sariff uint16_t gcap; 1511162922Sariff uint8_t corbsize, rirbsize; 1512162922Sariff 1513162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1514162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1515162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1516162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1517162922Sariff 1518163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1519162922Sariff 1520162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1521162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1522162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1523162922Sariff sc->corb_size = 256; 1524162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1525162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1526162922Sariff sc->corb_size = 16; 1527162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1528162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1529162922Sariff sc->corb_size = 2; 1530162922Sariff else { 1531162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1532162922Sariff __func__, corbsize); 1533162922Sariff return (ENXIO); 1534162922Sariff } 1535162922Sariff 1536162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1537162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1538162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1539162922Sariff sc->rirb_size = 256; 1540162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1541162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1542162922Sariff sc->rirb_size = 16; 1543162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1544162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1545162922Sariff sc->rirb_size = 2; 1546162922Sariff else { 1547162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1548162922Sariff __func__, rirbsize); 1549162922Sariff return (ENXIO); 1550162922Sariff } 1551162922Sariff 1552183097Smav HDA_BOOTHVERBOSE( 1553182999Smav device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 1554182999Smav device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 1555182999Smav device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 1556182999Smav sc->num_iss, sc->num_oss, sc->num_bss); 1557182999Smav ); 1558182999Smav 1559162922Sariff return (0); 1560162922Sariff} 1561162922Sariff 1562162922Sariff 1563162922Sariff/**************************************************************************** 1564162922Sariff * void hdac_dma_cb 1565162922Sariff * 1566162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1567162922Sariff * established. We just record the physical address of the mapping into 1568162922Sariff * the struct hdac_dma passed in. 1569162922Sariff ****************************************************************************/ 1570162922Sariffstatic void 1571162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1572162922Sariff{ 1573162922Sariff struct hdac_dma *dma; 1574162922Sariff 1575162922Sariff if (error == 0) { 1576162922Sariff dma = (struct hdac_dma *)callback_arg; 1577162922Sariff dma->dma_paddr = segs[0].ds_addr; 1578162922Sariff } 1579162922Sariff} 1580162922Sariff 1581162922Sariff 1582162922Sariff/**************************************************************************** 1583162922Sariff * int hdac_dma_alloc 1584162922Sariff * 1585162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1586162922Sariff * It must be freed by a corresponding hdac_dma_free. 1587162922Sariff ****************************************************************************/ 1588162922Sariffstatic int 1589162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1590162922Sariff{ 1591169277Sariff bus_size_t roundsz; 1592162922Sariff int result; 1593162922Sariff int lowaddr; 1594162922Sariff 1595169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1596162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1597162922Sariff BUS_SPACE_MAXADDR_32BIT; 1598162922Sariff bzero(dma, sizeof(*dma)); 1599162922Sariff 1600162922Sariff /* 1601162922Sariff * Create a DMA tag 1602162922Sariff */ 1603162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1604162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1605162922Sariff 0, /* boundary */ 1606162922Sariff lowaddr, /* lowaddr */ 1607162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1608162922Sariff NULL, /* filtfunc */ 1609162922Sariff NULL, /* fistfuncarg */ 1610169277Sariff roundsz, /* maxsize */ 1611162922Sariff 1, /* nsegments */ 1612169277Sariff roundsz, /* maxsegsz */ 1613162922Sariff 0, /* flags */ 1614162922Sariff NULL, /* lockfunc */ 1615162922Sariff NULL, /* lockfuncarg */ 1616162922Sariff &dma->dma_tag); /* dmat */ 1617162922Sariff if (result != 0) { 1618162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1619162922Sariff __func__, result); 1620167773Sariff goto hdac_dma_alloc_fail; 1621162922Sariff } 1622162922Sariff 1623162922Sariff /* 1624162922Sariff * Allocate DMA memory 1625162922Sariff */ 1626162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1627169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1628171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1629171330Sariff &dma->dma_map); 1630162922Sariff if (result != 0) { 1631162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1632162922Sariff __func__, result); 1633167773Sariff goto hdac_dma_alloc_fail; 1634162922Sariff } 1635162922Sariff 1636169277Sariff dma->dma_size = roundsz; 1637169277Sariff 1638162922Sariff /* 1639162922Sariff * Map the memory 1640162922Sariff */ 1641162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1642169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1643162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1644167773Sariff if (result == 0) 1645167773Sariff result = ENOMEM; 1646162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1647162922Sariff __func__, result); 1648167773Sariff goto hdac_dma_alloc_fail; 1649162922Sariff } 1650162922Sariff 1651183097Smav HDA_BOOTHVERBOSE( 1652169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1653169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1654169277Sariff ); 1655169277Sariff 1656162922Sariff return (0); 1657169277Sariff 1658167773Sariffhdac_dma_alloc_fail: 1659169277Sariff hdac_dma_free(sc, dma); 1660167773Sariff 1661162922Sariff return (result); 1662162922Sariff} 1663162922Sariff 1664162922Sariff 1665162922Sariff/**************************************************************************** 1666169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1667162922Sariff * 1668162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1669162922Sariff * hdac_dma_alloc function. 1670162922Sariff ****************************************************************************/ 1671162922Sariffstatic void 1672169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1673162922Sariff{ 1674167773Sariff if (dma->dma_map != NULL) { 1675169277Sariff#if 0 1676162922Sariff /* Flush caches */ 1677162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1678162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1679169277Sariff#endif 1680162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1681167773Sariff } 1682167773Sariff if (dma->dma_vaddr != NULL) { 1683162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1684167773Sariff dma->dma_vaddr = NULL; 1685167773Sariff } 1686167773Sariff dma->dma_map = NULL; 1687167773Sariff if (dma->dma_tag != NULL) { 1688162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1689167773Sariff dma->dma_tag = NULL; 1690162922Sariff } 1691167773Sariff dma->dma_size = 0; 1692162922Sariff} 1693162922Sariff 1694162922Sariff/**************************************************************************** 1695162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1696162922Sariff * 1697162922Sariff * Allocate all the bus resources necessary to speak with the physical 1698162922Sariff * controller. 1699162922Sariff ****************************************************************************/ 1700162922Sariffstatic int 1701162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1702162922Sariff{ 1703162922Sariff struct hdac_mem *mem; 1704162922Sariff 1705162922Sariff mem = &sc->mem; 1706162922Sariff mem->mem_rid = PCIR_BAR(0); 1707162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1708162922Sariff &mem->mem_rid, RF_ACTIVE); 1709162922Sariff if (mem->mem_res == NULL) { 1710162922Sariff device_printf(sc->dev, 1711162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1712162922Sariff return (ENOMEM); 1713162922Sariff } 1714162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1715162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1716162922Sariff 1717162922Sariff return (0); 1718162922Sariff} 1719162922Sariff 1720162922Sariff/**************************************************************************** 1721162922Sariff * void hdac_mem_free(struct hdac_softc *) 1722162922Sariff * 1723162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1724162922Sariff ****************************************************************************/ 1725162922Sariffstatic void 1726162922Sariffhdac_mem_free(struct hdac_softc *sc) 1727162922Sariff{ 1728162922Sariff struct hdac_mem *mem; 1729162922Sariff 1730162922Sariff mem = &sc->mem; 1731162922Sariff if (mem->mem_res != NULL) 1732162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1733162922Sariff mem->mem_res); 1734164614Sariff mem->mem_res = NULL; 1735162922Sariff} 1736162922Sariff 1737162922Sariff/**************************************************************************** 1738162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1739162922Sariff * 1740162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1741162922Sariff ****************************************************************************/ 1742162922Sariffstatic int 1743162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1744162922Sariff{ 1745162922Sariff struct hdac_irq *irq; 1746162922Sariff int result; 1747162922Sariff 1748162922Sariff irq = &sc->irq; 1749162922Sariff irq->irq_rid = 0x0; 1750171330Sariff 1751171330Sariff if ((sc->flags & HDAC_F_MSI) && 1752171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1753171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1754171330Sariff irq->irq_rid = 0x1; 1755171330Sariff else 1756171330Sariff sc->flags &= ~HDAC_F_MSI; 1757171330Sariff 1758162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1759162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1760162922Sariff if (irq->irq_res == NULL) { 1761162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1762162922Sariff __func__); 1763167773Sariff goto hdac_irq_alloc_fail; 1764162922Sariff } 1765182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1766182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1767162922Sariff if (result != 0) { 1768162922Sariff device_printf(sc->dev, 1769162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1770162922Sariff __func__, result); 1771167773Sariff goto hdac_irq_alloc_fail; 1772162922Sariff } 1773162922Sariff 1774162922Sariff return (0); 1775162922Sariff 1776167773Sariffhdac_irq_alloc_fail: 1777164614Sariff hdac_irq_free(sc); 1778164614Sariff 1779162922Sariff return (ENXIO); 1780162922Sariff} 1781162922Sariff 1782162922Sariff/**************************************************************************** 1783162922Sariff * void hdac_irq_free(struct hdac_softc *) 1784162922Sariff * 1785162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1786162922Sariff ****************************************************************************/ 1787162922Sariffstatic void 1788162922Sariffhdac_irq_free(struct hdac_softc *sc) 1789162922Sariff{ 1790162922Sariff struct hdac_irq *irq; 1791162922Sariff 1792162922Sariff irq = &sc->irq; 1793164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1794162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1795162922Sariff if (irq->irq_res != NULL) 1796162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1797162922Sariff irq->irq_res); 1798188656Smav if (irq->irq_rid == 0x1) 1799171330Sariff pci_release_msi(sc->dev); 1800164614Sariff irq->irq_handle = NULL; 1801164614Sariff irq->irq_res = NULL; 1802171330Sariff irq->irq_rid = 0x0; 1803162922Sariff} 1804162922Sariff 1805162922Sariff/**************************************************************************** 1806162922Sariff * void hdac_corb_init(struct hdac_softc *) 1807162922Sariff * 1808162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1809162922Sariff * The CORB engine must not be running when this function is called. 1810162922Sariff ****************************************************************************/ 1811162922Sariffstatic void 1812162922Sariffhdac_corb_init(struct hdac_softc *sc) 1813162922Sariff{ 1814162922Sariff uint8_t corbsize; 1815162922Sariff uint64_t corbpaddr; 1816162922Sariff 1817162922Sariff /* Setup the CORB size. */ 1818162922Sariff switch (sc->corb_size) { 1819162922Sariff case 256: 1820162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1821162922Sariff break; 1822162922Sariff case 16: 1823162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1824162922Sariff break; 1825162922Sariff case 2: 1826162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1827162922Sariff break; 1828162922Sariff default: 1829162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1830162922Sariff } 1831162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1832162922Sariff 1833162922Sariff /* Setup the CORB Address in the hdac */ 1834162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1835162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1836162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1837162922Sariff 1838162922Sariff /* Set the WP and RP */ 1839162922Sariff sc->corb_wp = 0; 1840162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1841162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1842162922Sariff /* 1843162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1844162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1845162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1846162922Sariff * manually reset the bit to zero before continuing. 1847162922Sariff */ 1848162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1849162922Sariff 1850162922Sariff /* Enable CORB error reporting */ 1851162922Sariff#if 0 1852162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1853162922Sariff#endif 1854162922Sariff} 1855162922Sariff 1856162922Sariff/**************************************************************************** 1857162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1858162922Sariff * 1859162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1860162922Sariff * The RIRB engine must not be running when this function is called. 1861162922Sariff ****************************************************************************/ 1862162922Sariffstatic void 1863162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1864162922Sariff{ 1865162922Sariff uint8_t rirbsize; 1866162922Sariff uint64_t rirbpaddr; 1867162922Sariff 1868162922Sariff /* Setup the RIRB size. */ 1869162922Sariff switch (sc->rirb_size) { 1870162922Sariff case 256: 1871162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1872162922Sariff break; 1873162922Sariff case 16: 1874162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1875162922Sariff break; 1876162922Sariff case 2: 1877162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1878162922Sariff break; 1879162922Sariff default: 1880162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1881162922Sariff } 1882162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1883162922Sariff 1884162922Sariff /* Setup the RIRB Address in the hdac */ 1885162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1886162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1887162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1888162922Sariff 1889162922Sariff /* Setup the WP and RP */ 1890162922Sariff sc->rirb_rp = 0; 1891162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1892162922Sariff 1893182999Smav /* Setup the interrupt threshold */ 1894182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1895162922Sariff 1896182999Smav /* Enable Overrun and response received reporting */ 1897162922Sariff#if 0 1898182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1899182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1900162922Sariff#else 1901182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1902162922Sariff#endif 1903162922Sariff 1904169277Sariff#if 0 1905162922Sariff /* 1906162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1907162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1908162922Sariff * should be sufficient to do this only once as the rirb is purely 1909162922Sariff * read-only from now on. 1910162922Sariff */ 1911162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1912162922Sariff BUS_DMASYNC_PREREAD); 1913169277Sariff#endif 1914162922Sariff} 1915162922Sariff 1916162922Sariff/**************************************************************************** 1917162922Sariff * void hdac_corb_start(hdac_softc *) 1918162922Sariff * 1919162922Sariff * Startup the corb DMA engine 1920162922Sariff ****************************************************************************/ 1921162922Sariffstatic void 1922162922Sariffhdac_corb_start(struct hdac_softc *sc) 1923162922Sariff{ 1924162922Sariff uint32_t corbctl; 1925162922Sariff 1926162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1927162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1928162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1929162922Sariff} 1930162922Sariff 1931162922Sariff/**************************************************************************** 1932162922Sariff * void hdac_rirb_start(hdac_softc *) 1933162922Sariff * 1934162922Sariff * Startup the rirb DMA engine 1935162922Sariff ****************************************************************************/ 1936162922Sariffstatic void 1937162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1938162922Sariff{ 1939162922Sariff uint32_t rirbctl; 1940162922Sariff 1941162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1942162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1943162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1944162922Sariff} 1945162922Sariff 1946162922Sariff 1947162922Sariff/**************************************************************************** 1948172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 1949162922Sariff * 1950172811Sariff * Scan the bus for available codecs, starting with num. 1951162922Sariff ****************************************************************************/ 1952162922Sariffstatic void 1953182999Smavhdac_scan_codecs(struct hdac_softc *sc) 1954162922Sariff{ 1955162922Sariff struct hdac_codec *codec; 1956162922Sariff int i; 1957162922Sariff uint16_t statests; 1958162922Sariff 1959162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1960182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1961162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1962162922Sariff /* We have found a codec. */ 1963162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1964162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1965162922Sariff if (codec == NULL) { 1966162922Sariff device_printf(sc->dev, 1967162922Sariff "Unable to allocate memory for codec\n"); 1968162922Sariff continue; 1969162922Sariff } 1970164614Sariff codec->commands = NULL; 1971164614Sariff codec->responses_received = 0; 1972162922Sariff codec->verbs_sent = 0; 1973162922Sariff codec->sc = sc; 1974162922Sariff codec->cad = i; 1975162922Sariff sc->codecs[i] = codec; 1976182999Smav hdac_probe_codec(codec); 1977162922Sariff } 1978162922Sariff } 1979162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1980163057Sariff /* bus_generic_attach(sc->dev); */ 1981162922Sariff} 1982162922Sariff 1983162922Sariff/**************************************************************************** 1984162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1985162922Sariff * 1986162922Sariff * Probe a the given codec_id for available function groups. 1987162922Sariff ****************************************************************************/ 1988182999Smavstatic void 1989162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1990162922Sariff{ 1991162922Sariff struct hdac_softc *sc = codec->sc; 1992162922Sariff uint32_t vendorid, revisionid, subnode; 1993162922Sariff int startnode; 1994162922Sariff int endnode; 1995162922Sariff int i; 1996162922Sariff nid_t cad = codec->cad; 1997162922Sariff 1998163057Sariff HDA_BOOTVERBOSE( 1999184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 2000162922Sariff ); 2001162922Sariff vendorid = hdac_command(sc, 2002162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 2003162922Sariff cad); 2004162922Sariff revisionid = hdac_command(sc, 2005162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 2006162922Sariff cad); 2007182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 2008182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 2009182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 2010182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 2011182999Smav 2012182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 2013182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 2014182999Smav " Probing aborted.\n", cad); 2015182999Smav return; 2016182999Smav } 2017182999Smav 2018184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 2019182999Smav cad, hdac_codec_name(codec)); 2020182999Smav HDA_BOOTVERBOSE( 2021184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 2022182999Smav hdac_codec_id(codec)); 2023182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 2024182999Smav codec->vendor_id); 2025182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 2026182999Smav codec->device_id); 2027182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 2028182999Smav codec->revision_id); 2029182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 2030182999Smav codec->stepping_id); 2031182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2032182999Smav sc->pci_subvendor); 2033182999Smav ); 2034162922Sariff subnode = hdac_command(sc, 2035162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 2036162922Sariff cad); 2037162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 2038162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 2039162922Sariff 2040183097Smav HDA_BOOTHVERBOSE( 2041182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 2042163057Sariff startnode, endnode); 2043162922Sariff ); 2044182999Smav 2045182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 2046182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 2047182999Smav if (codec->fgs == NULL) { 2048183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 2049182999Smav __func__); 2050182999Smav return; 2051162922Sariff } 2052162922Sariff 2053182999Smav for (i = startnode; i < endnode; i++) 2054182999Smav hdac_probe_function(codec, i); 2055182999Smav return; 2056162922Sariff} 2057162922Sariff 2058182999Smav/* 2059182999Smav * Probe codec function and add it to the list. 2060182999Smav */ 2061182999Smavstatic void 2062162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 2063162922Sariff{ 2064162922Sariff struct hdac_softc *sc = codec->sc; 2065182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 2066162922Sariff uint32_t fctgrptype; 2067182999Smav uint32_t res; 2068162922Sariff nid_t cad = codec->cad; 2069162922Sariff 2070162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 2071162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 2072162922Sariff 2073162922Sariff devinfo->nid = nid; 2074162965Sariff devinfo->node_type = fctgrptype; 2075162922Sariff devinfo->codec = codec; 2076162922Sariff 2077182999Smav res = hdac_command(sc, 2078182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2079162922Sariff 2080182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2081182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2082182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2083162922Sariff 2084182999Smav HDA_BOOTVERBOSE( 2085182999Smav device_printf(sc->dev, 2086182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2087182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2088182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2089182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2090182999Smav devinfo->nodecnt); 2091182999Smav ); 2092182999Smav 2093182999Smav if (devinfo->nodecnt > 0) 2094182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2095182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2096182999Smav M_NOWAIT | M_ZERO); 2097182999Smav else 2098182999Smav devinfo->widget = NULL; 2099182999Smav 2100182999Smav if (devinfo->widget == NULL) { 2101182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2102182999Smav devinfo->endnode = devinfo->startnode; 2103182999Smav devinfo->nodecnt = 0; 2104182999Smav return; 2105182999Smav } 2106182999Smav 2107182999Smav codec->num_fgs++; 2108162922Sariff} 2109162922Sariff 2110162922Sariffstatic void 2111162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2112162922Sariff{ 2113162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2114162922Sariff uint32_t res; 2115169277Sariff int i, j, max, ents, entnum; 2116162922Sariff nid_t cad = w->devinfo->codec->cad; 2117162922Sariff nid_t nid = w->nid; 2118169277Sariff nid_t cnid, addcnid, prevcnid; 2119162922Sariff 2120169277Sariff w->nconns = 0; 2121169277Sariff 2122162922Sariff res = hdac_command(sc, 2123162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2124162922Sariff 2125169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2126162922Sariff 2127169277Sariff if (ents < 1) 2128162922Sariff return; 2129162922Sariff 2130162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2131162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2132169277Sariff prevcnid = 0; 2133162922Sariff 2134169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2135169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2136169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2137169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2138169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2139169277Sariff 2140169277Sariff for (i = 0; i < ents; i += entnum) { 2141162922Sariff res = hdac_command(sc, 2142162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2143162922Sariff for (j = 0; j < entnum; j++) { 2144169277Sariff cnid = CONN_CNID(res, entnum, j); 2145169277Sariff if (cnid == 0) { 2146169277Sariff if (w->nconns < ents) 2147169277Sariff device_printf(sc->dev, 2148169277Sariff "%s: nid=%d WARNING: zero cnid " 2149169277Sariff "entnum=%d j=%d index=%d " 2150169277Sariff "entries=%d found=%d res=0x%08x\n", 2151169277Sariff __func__, nid, entnum, j, i, 2152169277Sariff ents, w->nconns, res); 2153169277Sariff else 2154169277Sariff goto getconns_out; 2155169277Sariff } 2156169277Sariff if (cnid < w->devinfo->startnode || 2157169277Sariff cnid >= w->devinfo->endnode) { 2158169277Sariff HDA_BOOTVERBOSE( 2159169277Sariff device_printf(sc->dev, 2160182999Smav "GHOST: nid=%d j=%d " 2161169277Sariff "entnum=%d index=%d res=0x%08x\n", 2162182999Smav nid, j, entnum, i, res); 2163169277Sariff ); 2164169277Sariff } 2165169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2166169277Sariff addcnid = cnid; 2167169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2168162922Sariff device_printf(sc->dev, 2169169277Sariff "%s: WARNING: Invalid child range " 2170169277Sariff "nid=%d index=%d j=%d entnum=%d " 2171169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2172169277Sariff __func__, nid, i, j, entnum, prevcnid, 2173169277Sariff cnid, res); 2174169277Sariff addcnid = cnid; 2175169277Sariff } else 2176169277Sariff addcnid = prevcnid + 1; 2177169277Sariff while (addcnid <= cnid) { 2178169277Sariff if (w->nconns > max) { 2179169277Sariff device_printf(sc->dev, 2180182999Smav "Adding %d (nid=%d): " 2181169277Sariff "Max connection reached! max=%d\n", 2182182999Smav addcnid, nid, max + 1); 2183169277Sariff goto getconns_out; 2184169277Sariff } 2185182999Smav w->connsenable[w->nconns] = 1; 2186169277Sariff w->conns[w->nconns++] = addcnid++; 2187162922Sariff } 2188169277Sariff prevcnid = cnid; 2189162922Sariff } 2190162922Sariff } 2191162922Sariff 2192169277Sariffgetconns_out: 2193169277Sariff return; 2194162922Sariff} 2195162922Sariff 2196162922Sariffstatic uint32_t 2197182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2198182999Smav{ 2199182999Smav char buf[256]; 2200182999Smav char *key, *value, *rest, *bad; 2201182999Smav int ival, i; 2202182999Smav 2203182999Smav strlcpy(buf, str, sizeof(buf)); 2204182999Smav rest = buf; 2205182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2206182999Smav value = strsep(&rest, " \t"); 2207182999Smav if (value == NULL) 2208182999Smav break; 2209182999Smav ival = strtol(value, &bad, 10); 2210182999Smav if (strcmp(key, "seq") == 0) { 2211182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2212182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2213182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2214182999Smav } else if (strcmp(key, "as") == 0) { 2215182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2216182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2217182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2218182999Smav } else if (strcmp(key, "misc") == 0) { 2219182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2220182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2221182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2222182999Smav } else if (strcmp(key, "color") == 0) { 2223182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2224182999Smav if (bad[0] == 0) { 2225182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2226182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2227182999Smav }; 2228182999Smav for (i = 0; i < 16; i++) { 2229182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2230182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2231182999Smav break; 2232182999Smav } 2233182999Smav } 2234182999Smav } else if (strcmp(key, "ctype") == 0) { 2235182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2236182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2237182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2238182999Smav } else if (strcmp(key, "device") == 0) { 2239182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2240182999Smav if (bad[0] == 0) { 2241182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2242182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2243182999Smav continue; 2244182999Smav }; 2245182999Smav for (i = 0; i < 16; i++) { 2246182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2247182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2248182999Smav break; 2249182999Smav } 2250182999Smav } 2251182999Smav } else if (strcmp(key, "loc") == 0) { 2252182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2253182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2254182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2255182999Smav } else if (strcmp(key, "conn") == 0) { 2256182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2257182999Smav if (bad[0] == 0) { 2258182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2259182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2260182999Smav continue; 2261182999Smav }; 2262182999Smav for (i = 0; i < 4; i++) { 2263182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2264182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2265182999Smav break; 2266182999Smav } 2267182999Smav } 2268182999Smav } 2269182999Smav } 2270182999Smav return (config); 2271182999Smav} 2272182999Smav 2273182999Smavstatic uint32_t 2274162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2275162922Sariff{ 2276162922Sariff struct hdac_softc *sc; 2277166965Sariff uint32_t config, orig, id; 2278162922Sariff nid_t cad, nid; 2279182999Smav char buf[32]; 2280182999Smav const char *res = NULL, *patch = NULL; 2281162922Sariff 2282162922Sariff sc = w->devinfo->codec->sc; 2283162922Sariff cad = w->devinfo->codec->cad; 2284162922Sariff nid = w->nid; 2285182999Smav id = hdac_codec_id(w->devinfo->codec); 2286162922Sariff 2287162922Sariff config = hdac_command(sc, 2288162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2289162922Sariff cad); 2290166965Sariff orig = config; 2291166965Sariff 2292182999Smav HDA_BOOTVERBOSE( 2293182999Smav hdac_dump_pin_config(w, orig); 2294182999Smav ); 2295182999Smav 2296182999Smav /* XXX: Old patches require complete review. 2297182999Smav * Now they may create more problem then solve due to 2298182999Smav * incorrect associations. 2299162965Sariff */ 2300165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2301165281Sariff switch (nid) { 2302165281Sariff case 26: 2303165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2304165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2305165281Sariff break; 2306165281Sariff case 27: 2307165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2308165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2309165281Sariff break; 2310167610Sariff default: 2311167610Sariff break; 2312165281Sariff } 2313165281Sariff } else if (id == HDA_CODEC_ALC880 && 2314162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2315162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2316162922Sariff /* 2317162965Sariff * Super broken BIOS 2318162922Sariff */ 2319162922Sariff switch (nid) { 2320162922Sariff case 24: /* MIC1 */ 2321162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2322162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2323162922Sariff break; 2324162922Sariff case 25: /* XXX MIC2 */ 2325162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2326162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2327162922Sariff break; 2328162922Sariff case 26: /* LINE1 */ 2329162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2330162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2331162922Sariff break; 2332162922Sariff case 27: /* XXX LINE2 */ 2333162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2334162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2335162922Sariff break; 2336162922Sariff case 28: /* CD */ 2337162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2338162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2339162922Sariff break; 2340162922Sariff } 2341166965Sariff } else if (id == HDA_CODEC_ALC883 && 2342172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2343172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2344166965Sariff switch (nid) { 2345166965Sariff case 25: 2346166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2347166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2348166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2349166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2350166965Sariff break; 2351169277Sariff case 28: 2352169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2353169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2354169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2355169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2356169277Sariff break; 2357166965Sariff } 2358186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2359166965Sariff HP_V3000_SUBVENDOR) { 2360166965Sariff switch (nid) { 2361166965Sariff case 18: 2362166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2363166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2364166965Sariff break; 2365166965Sariff case 20: 2366166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2367166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2368166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2369166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2370166965Sariff break; 2371167454Sariff case 21: 2372167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2373167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2374167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2375167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2376167454Sariff break; 2377166965Sariff } 2378186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2379169277Sariff HP_DV5000_SUBVENDOR) { 2380169277Sariff switch (nid) { 2381169277Sariff case 20: 2382169277Sariff case 21: 2383169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2384169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2385169277Sariff break; 2386169277Sariff } 2387169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2388169277Sariff ASUS_W6F_SUBVENDOR) { 2389169277Sariff switch (nid) { 2390169277Sariff case 11: 2391169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2392169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2393169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2394169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2395169277Sariff break; 2396178324Sariff case 12: 2397178324Sariff case 14: 2398178324Sariff case 16: 2399178324Sariff case 31: 2400178324Sariff case 32: 2401178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2402178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2403178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2404178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2405178324Sariff break; 2406169277Sariff case 15: 2407169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2408169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2409169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2410169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2411169277Sariff break; 2412169277Sariff } 2413169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2414169277Sariff UNIWILL_9075_SUBVENDOR) { 2415169277Sariff switch (nid) { 2416169277Sariff case 15: 2417169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2418169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2419169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2420169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2421169277Sariff break; 2422169277Sariff } 2423182999Smav } 2424182999Smav 2425182999Smav /* New patches */ 2426182999Smav if (id == HDA_CODEC_AD1986A && 2427171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2428171141Sariff sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) { 2429169277Sariff switch (nid) { 2430182999Smav case 28: /* 5.1 out => 2.0 out + 2 inputs */ 2431182999Smav patch = "device=Line-in as=8 seq=1"; 2432169277Sariff break; 2433182999Smav case 29: 2434182999Smav patch = "device=Mic as=8 seq=2"; 2435169277Sariff break; 2436182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2437182999Smav patch = "as=8 seq=3"; 2438169277Sariff break; 2439182999Smav case 32: 2440182999Smav patch = "as=8 seq=4"; 2441182999Smav break; 2442182999Smav case 34: 2443182999Smav patch = "as=8 seq=5"; 2444182999Smav break; 2445182999Smav case 36: 2446182999Smav patch = "as=8 seq=6"; 2447182999Smav break; 2448169277Sariff } 2449182999Smav } else if (id == HDA_CODEC_ALC260 && 2450182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2451182999Smav switch (nid) { 2452182999Smav case 16: 2453182999Smav patch = "seq=15 device=Headphones"; 2454182999Smav break; 2455182999Smav } 2456189879Smav } else if (id == HDA_CODEC_ALC268) { 2457189879Smav if (sc->pci_subvendor == ACER_T5320_SUBVENDOR) { 2458174578Sariff switch (nid) { 2459189879Smav case 20: /* Headphones Jack */ 2460189879Smav patch = "as=1 seq=15"; 2461174578Sariff break; 2462174578Sariff } 2463189879Smav } 2464162922Sariff } 2465162922Sariff 2466182999Smav if (patch != NULL) 2467182999Smav config = hdac_widget_pin_patch(config, patch); 2468182999Smav 2469182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2470182999Smav if (resource_string_value(device_get_name(sc->dev), 2471182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2472182999Smav if (strncmp(res, "0x", 2) == 0) { 2473182999Smav config = strtol(res + 2, NULL, 16); 2474182999Smav } else { 2475182999Smav config = hdac_widget_pin_patch(config, res); 2476182999Smav } 2477182999Smav } 2478182999Smav 2479166965Sariff HDA_BOOTVERBOSE( 2480166965Sariff if (config != orig) 2481166965Sariff device_printf(sc->dev, 2482182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2483166965Sariff nid, orig, config); 2484166965Sariff ); 2485166965Sariff 2486162922Sariff return (config); 2487162922Sariff} 2488162922Sariff 2489166965Sariffstatic uint32_t 2490166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2491166965Sariff{ 2492166965Sariff struct hdac_softc *sc; 2493166965Sariff uint32_t caps, orig, id; 2494166965Sariff nid_t cad, nid; 2495166965Sariff 2496166965Sariff sc = w->devinfo->codec->sc; 2497166965Sariff cad = w->devinfo->codec->cad; 2498166965Sariff nid = w->nid; 2499182999Smav id = hdac_codec_id(w->devinfo->codec); 2500166965Sariff 2501166965Sariff caps = hdac_command(sc, 2502166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2503166965Sariff orig = caps; 2504166965Sariff 2505166965Sariff HDA_BOOTVERBOSE( 2506166965Sariff if (caps != orig) 2507166965Sariff device_printf(sc->dev, 2508182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2509166965Sariff nid, orig, caps); 2510166965Sariff ); 2511166965Sariff 2512166965Sariff return (caps); 2513166965Sariff} 2514166965Sariff 2515162922Sariffstatic void 2516162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2517162922Sariff{ 2518162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2519162922Sariff uint32_t config, pincap; 2520186912Smav const char *devstr; 2521162922Sariff nid_t cad = w->devinfo->codec->cad; 2522162922Sariff nid_t nid = w->nid; 2523186912Smav int conn, color; 2524162922Sariff 2525162922Sariff config = hdac_widget_pin_getconfig(w); 2526162922Sariff w->wclass.pin.config = config; 2527162922Sariff 2528166965Sariff pincap = hdac_widget_pin_getcaps(w); 2529162922Sariff w->wclass.pin.cap = pincap; 2530162922Sariff 2531162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2532182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2533162922Sariff 2534162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2535162922Sariff w->param.eapdbtl = hdac_command(sc, 2536162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2537162922Sariff w->param.eapdbtl &= 0x7; 2538162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2539162922Sariff } else 2540162965Sariff w->param.eapdbtl = HDAC_INVALID; 2541162922Sariff 2542182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2543182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2544162922Sariff 2545186912Smav conn = (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2546186912Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT; 2547186912Smav color = (config & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> 2548186912Smav HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT; 2549162922Sariff 2550162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2551162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2552162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2553186912Smav if (conn == 0 && color != 0 && color != 15) { 2554186912Smav strlcat(w->name, HDA_COLORS[color], sizeof(w->name)); 2555186912Smav strlcat(w->name, " ", sizeof(w->name)); 2556186912Smav } 2557186912Smav strlcat(w->name, HDA_CONNS[conn], sizeof(w->name)); 2558162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2559162922Sariff} 2560162922Sariff 2561182999Smavstatic uint32_t 2562182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2563182999Smav{ 2564182999Smav struct hdac_softc *sc; 2565182999Smav uint32_t caps, orig, id; 2566182999Smav nid_t cad, nid, beeper = -1; 2567182999Smav 2568182999Smav sc = w->devinfo->codec->sc; 2569182999Smav cad = w->devinfo->codec->cad; 2570182999Smav nid = w->nid; 2571182999Smav id = hdac_codec_id(w->devinfo->codec); 2572182999Smav 2573182999Smav caps = hdac_command(sc, 2574182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2575182999Smav cad); 2576182999Smav orig = caps; 2577182999Smav 2578182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2579182999Smav alone. Also most of BIOSes does not declare beeper pin. 2580182999Smav Change beeper pin node type to beeper to help parser. */ 2581182999Smav *waspin = 0; 2582182999Smav switch (id) { 2583187721Smav case HDA_CODEC_AD1882: 2584187721Smav case HDA_CODEC_AD1883: 2585187721Smav case HDA_CODEC_AD1984: 2586187721Smav case HDA_CODEC_AD1984A: 2587187721Smav case HDA_CODEC_AD1984B: 2588187721Smav case HDA_CODEC_AD1987: 2589182999Smav case HDA_CODEC_AD1988: 2590182999Smav case HDA_CODEC_AD1988B: 2591187721Smav case HDA_CODEC_AD1989B: 2592182999Smav beeper = 26; 2593182999Smav break; 2594182999Smav case HDA_CODEC_ALC260: 2595182999Smav beeper = 23; 2596182999Smav break; 2597182999Smav case HDA_CODEC_ALC262: 2598182999Smav case HDA_CODEC_ALC268: 2599182999Smav case HDA_CODEC_ALC880: 2600182999Smav case HDA_CODEC_ALC882: 2601182999Smav case HDA_CODEC_ALC883: 2602182999Smav case HDA_CODEC_ALC885: 2603182999Smav case HDA_CODEC_ALC888: 2604182999Smav case HDA_CODEC_ALC889: 2605182999Smav beeper = 29; 2606182999Smav break; 2607182999Smav } 2608182999Smav if (nid == beeper) { 2609182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2610182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2611182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2612182999Smav *waspin = 1; 2613182999Smav } 2614182999Smav 2615182999Smav HDA_BOOTVERBOSE( 2616182999Smav if (caps != orig) { 2617182999Smav device_printf(sc->dev, 2618182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2619182999Smav nid, orig, caps); 2620182999Smav } 2621182999Smav ); 2622182999Smav 2623182999Smav return (caps); 2624182999Smav} 2625182999Smav 2626162922Sariffstatic void 2627162922Sariffhdac_widget_parse(struct hdac_widget *w) 2628162922Sariff{ 2629162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2630162922Sariff uint32_t wcap, cap; 2631162922Sariff char *typestr; 2632162922Sariff nid_t cad = w->devinfo->codec->cad; 2633162922Sariff nid_t nid = w->nid; 2634162922Sariff 2635182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2636182999Smav 2637162922Sariff w->param.widget_cap = wcap; 2638162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2639162922Sariff 2640162922Sariff switch (w->type) { 2641162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2642162922Sariff typestr = "audio output"; 2643162922Sariff break; 2644162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2645162922Sariff typestr = "audio input"; 2646162922Sariff break; 2647162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2648162922Sariff typestr = "audio mixer"; 2649162922Sariff break; 2650162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2651162922Sariff typestr = "audio selector"; 2652162922Sariff break; 2653162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2654162922Sariff typestr = "pin"; 2655162922Sariff break; 2656162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2657162922Sariff typestr = "power widget"; 2658162922Sariff break; 2659162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2660162922Sariff typestr = "volume widget"; 2661162922Sariff break; 2662162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2663162922Sariff typestr = "beep widget"; 2664162922Sariff break; 2665162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2666162922Sariff typestr = "vendor widget"; 2667162922Sariff break; 2668162922Sariff default: 2669162922Sariff typestr = "unknown type"; 2670162922Sariff break; 2671162922Sariff } 2672162922Sariff 2673162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2674162922Sariff 2675162922Sariff hdac_widget_connection_parse(w); 2676162922Sariff 2677162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2678162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2679162922Sariff w->param.outamp_cap = 2680162922Sariff hdac_command(sc, 2681162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2682162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2683162922Sariff else 2684162922Sariff w->param.outamp_cap = 2685162922Sariff w->devinfo->function.audio.outamp_cap; 2686162922Sariff } else 2687162922Sariff w->param.outamp_cap = 0; 2688162922Sariff 2689162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2690162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2691162922Sariff w->param.inamp_cap = 2692162922Sariff hdac_command(sc, 2693162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2694162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2695162922Sariff else 2696162922Sariff w->param.inamp_cap = 2697162922Sariff w->devinfo->function.audio.inamp_cap; 2698162922Sariff } else 2699162922Sariff w->param.inamp_cap = 0; 2700162922Sariff 2701162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2702162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2703162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2704162922Sariff cap = hdac_command(sc, 2705162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2706162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2707162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2708162922Sariff w->devinfo->function.audio.supp_stream_formats; 2709162922Sariff cap = hdac_command(sc, 2710162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2711162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2712162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2713162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2714162922Sariff } else { 2715162922Sariff w->param.supp_stream_formats = 2716162922Sariff w->devinfo->function.audio.supp_stream_formats; 2717162922Sariff w->param.supp_pcm_size_rate = 2718162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2719162922Sariff } 2720162922Sariff } else { 2721162922Sariff w->param.supp_stream_formats = 0; 2722162922Sariff w->param.supp_pcm_size_rate = 0; 2723162922Sariff } 2724162922Sariff 2725162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2726162922Sariff hdac_widget_pin_parse(w); 2727162922Sariff} 2728162922Sariff 2729162922Sariffstatic struct hdac_widget * 2730162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2731162922Sariff{ 2732162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2733162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2734162922Sariff return (NULL); 2735162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2736162922Sariff} 2737162922Sariff 2738164614Sariffstatic __inline int 2739164614Sariffhda_poll_channel(struct hdac_chan *ch) 2740164614Sariff{ 2741164614Sariff uint32_t sz, delta; 2742164614Sariff volatile uint32_t ptr; 2743164614Sariff 2744171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2745164614Sariff return (0); 2746164614Sariff 2747164614Sariff sz = ch->blksz * ch->blkcnt; 2748169277Sariff if (ch->dmapos != NULL) 2749169277Sariff ptr = *(ch->dmapos); 2750169277Sariff else 2751169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2752169277Sariff ch->off + HDAC_SDLPIB); 2753164614Sariff ch->ptr = ptr; 2754164614Sariff ptr %= sz; 2755164614Sariff ptr &= ~(ch->blksz - 1); 2756164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2757164614Sariff 2758164614Sariff if (delta < ch->blksz) 2759164614Sariff return (0); 2760164614Sariff 2761164614Sariff ch->prevptr = ptr; 2762164614Sariff 2763164614Sariff return (1); 2764164614Sariff} 2765164614Sariff 2766162922Sariffstatic void 2767164614Sariffhda_poll_callback(void *arg) 2768164614Sariff{ 2769164614Sariff struct hdac_softc *sc = arg; 2770171141Sariff uint32_t trigger; 2771182999Smav int i, active = 0; 2772164614Sariff 2773164614Sariff if (sc == NULL) 2774164614Sariff return; 2775164614Sariff 2776164614Sariff hdac_lock(sc); 2777182999Smav if (sc->polling == 0) { 2778164614Sariff hdac_unlock(sc); 2779164614Sariff return; 2780164614Sariff } 2781164614Sariff 2782171141Sariff trigger = 0; 2783182999Smav for (i = 0; i < sc->num_chans; i++) { 2784182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2785182999Smav continue; 2786182999Smav active = 1; 2787182999Smav if (hda_poll_channel(&sc->chans[i])) 2788182999Smav trigger |= (1 << i); 2789182999Smav } 2790164614Sariff 2791164614Sariff /* XXX */ 2792182999Smav if (active) 2793182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2794182999Smav hda_poll_callback, sc); 2795164614Sariff 2796164614Sariff hdac_unlock(sc); 2797164614Sariff 2798182999Smav for (i = 0; i < sc->num_chans; i++) { 2799182999Smav if (trigger & (1 << i)) 2800182999Smav chn_intr(sc->chans[i].c); 2801182999Smav } 2802164614Sariff} 2803164614Sariff 2804164614Sariffstatic int 2805164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2806164614Sariff{ 2807164614Sariff struct hdac_rirb *rirb_base, *rirb; 2808164614Sariff struct hdac_codec *codec; 2809164614Sariff struct hdac_command_list *commands; 2810164614Sariff nid_t cad; 2811164614Sariff uint32_t resp; 2812164614Sariff uint8_t rirbwp; 2813171141Sariff int ret; 2814164614Sariff 2815164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2816164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2817169277Sariff#if 0 2818164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2819164614Sariff BUS_DMASYNC_POSTREAD); 2820169277Sariff#endif 2821164614Sariff 2822171141Sariff ret = 0; 2823171141Sariff 2824164614Sariff while (sc->rirb_rp != rirbwp) { 2825164614Sariff sc->rirb_rp++; 2826164614Sariff sc->rirb_rp %= sc->rirb_size; 2827164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2828164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2829164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2830164614Sariff sc->codecs[cad] == NULL) 2831164614Sariff continue; 2832164614Sariff resp = rirb->response; 2833164614Sariff codec = sc->codecs[cad]; 2834164614Sariff commands = codec->commands; 2835164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2836164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2837164614Sariff ((resp >> 26) & 0xffff); 2838164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2839164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2840164614Sariff codec->responses_received < commands->num_commands) 2841164614Sariff commands->responses[codec->responses_received++] = 2842164614Sariff resp; 2843164614Sariff ret++; 2844164614Sariff } 2845164614Sariff 2846164614Sariff return (ret); 2847164614Sariff} 2848164614Sariff 2849164614Sariffstatic int 2850164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2851164614Sariff{ 2852164614Sariff nid_t cad; 2853164614Sariff uint32_t tag; 2854164614Sariff int ret = 0; 2855164614Sariff 2856164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2857164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2858164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2859164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2860164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2861164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2862164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2863164614Sariff ret++; 2864164614Sariff } 2865164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2866164614Sariff } 2867164614Sariff 2868164614Sariff return (ret); 2869164614Sariff} 2870164614Sariff 2871164614Sariffstatic void 2872164614Sariffhdac_poll_callback(void *arg) 2873164614Sariff{ 2874164614Sariff struct hdac_softc *sc = arg; 2875164614Sariff if (sc == NULL) 2876164614Sariff return; 2877166796Sariff 2878164614Sariff hdac_lock(sc); 2879169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2880164614Sariff hdac_unlock(sc); 2881164614Sariff return; 2882164614Sariff } 2883171141Sariff if (hdac_rirb_flush(sc) != 0) 2884171141Sariff hdac_unsolq_flush(sc); 2885169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2886164614Sariff hdac_unlock(sc); 2887164614Sariff} 2888164614Sariff 2889164614Sariffstatic void 2890182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2891182999Smav{ 2892182999Smav int i, pollticks, min = 1000000; 2893182999Smav struct hdac_chan *ch; 2894182999Smav 2895182999Smav for (i = 0; i < sc->num_chans; i++) { 2896182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2897182999Smav continue; 2898182999Smav ch = &sc->chans[i]; 2899182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2900182999Smav ((uint64_t)sndbuf_getbps(ch->b) * 2901182999Smav sndbuf_getspd(ch->b)); 2902182999Smav pollticks >>= 1; 2903182999Smav if (pollticks > hz) 2904182999Smav pollticks = hz; 2905182999Smav if (pollticks < 1) { 2906182999Smav HDA_BOOTVERBOSE( 2907182999Smav device_printf(sc->dev, 2908182999Smav "%s: pollticks=%d < 1 !\n", 2909182999Smav __func__, pollticks); 2910182999Smav ); 2911182999Smav pollticks = 1; 2912182999Smav } 2913182999Smav if (min > pollticks) 2914182999Smav min = pollticks; 2915182999Smav } 2916182999Smav HDA_BOOTVERBOSE( 2917182999Smav device_printf(sc->dev, 2918182999Smav "%s: pollticks %d -> %d\n", 2919182999Smav __func__, sc->poll_ticks, min); 2920182999Smav ); 2921182999Smav sc->poll_ticks = min; 2922182999Smav if (min == 1000000) 2923182999Smav callout_stop(&sc->poll_hda); 2924182999Smav else 2925182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 2926182999Smav} 2927182999Smav 2928182999Smavstatic void 2929162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2930162922Sariff{ 2931162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2932162922Sariff uint32_t ctl; 2933162922Sariff 2934162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2935162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2936162922Sariff HDAC_SDCTL_RUN); 2937162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2938162922Sariff 2939171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 2940164614Sariff 2941182999Smav if (sc->polling != 0) 2942182999Smav hdac_poll_reinit(sc); 2943164614Sariff 2944182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2945182999Smav ctl &= ~(1 << (ch->off >> 5)); 2946182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2947162922Sariff} 2948162922Sariff 2949162922Sariffstatic void 2950162922Sariffhdac_stream_start(struct hdac_chan *ch) 2951162922Sariff{ 2952162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2953162922Sariff uint32_t ctl; 2954162922Sariff 2955182999Smav ch->flags |= HDAC_CHN_RUNNING; 2956162922Sariff 2957182999Smav if (sc->polling != 0) 2958182999Smav hdac_poll_reinit(sc); 2959182999Smav 2960182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2961182999Smav ctl |= 1 << (ch->off >> 5); 2962182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2963182999Smav 2964182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2965182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2966182999Smav HDAC_SDCTL_RUN; 2967162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2968162922Sariff} 2969162922Sariff 2970162922Sariffstatic void 2971162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2972162922Sariff{ 2973162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2974162922Sariff int timeout = 1000; 2975162922Sariff int to = timeout; 2976162922Sariff uint32_t ctl; 2977162922Sariff 2978162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2979162922Sariff ctl |= HDAC_SDCTL_SRST; 2980162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2981162922Sariff do { 2982162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2983162922Sariff if (ctl & HDAC_SDCTL_SRST) 2984162922Sariff break; 2985162922Sariff DELAY(10); 2986162922Sariff } while (--to); 2987162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2988162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2989162922Sariff } 2990162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2991162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2992162922Sariff to = timeout; 2993162922Sariff do { 2994162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2995162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2996162922Sariff break; 2997162922Sariff DELAY(10); 2998162922Sariff } while (--to); 2999163057Sariff if (ctl & HDAC_SDCTL_SRST) 3000162922Sariff device_printf(sc->dev, "can't reset!\n"); 3001162922Sariff} 3002162922Sariff 3003162922Sariffstatic void 3004162922Sariffhdac_stream_setid(struct hdac_chan *ch) 3005162922Sariff{ 3006162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3007162922Sariff uint32_t ctl; 3008162922Sariff 3009162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 3010162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 3011162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 3012162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 3013162922Sariff} 3014162922Sariff 3015162922Sariffstatic void 3016162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 3017162922Sariff{ 3018162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3019164614Sariff struct hdac_bdle *bdle; 3020162922Sariff uint64_t addr; 3021164614Sariff uint32_t blksz, blkcnt; 3022162922Sariff int i; 3023162922Sariff 3024162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 3025164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 3026162922Sariff 3027182999Smav blksz = ch->blksz; 3028182999Smav blkcnt = ch->blkcnt; 3029164614Sariff 3030164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 3031162922Sariff bdle->addrl = (uint32_t)addr; 3032162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 3033164614Sariff bdle->len = blksz; 3034182999Smav bdle->ioc = 1; 3035164614Sariff addr += blksz; 3036162922Sariff } 3037162922Sariff 3038164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 3039164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 3040162922Sariff addr = ch->bdl_dma.dma_paddr; 3041162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 3042162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 3043169277Sariff if (ch->dmapos != NULL && 3044169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 3045169277Sariff addr = sc->pos_dma.dma_paddr; 3046169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 3047169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 3048169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 3049169277Sariff } 3050162922Sariff} 3051162922Sariff 3052162922Sariffstatic int 3053162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 3054162922Sariff{ 3055162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3056162922Sariff int rc; 3057162922Sariff 3058162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 3059162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 3060162922Sariff if (rc) { 3061162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 3062162922Sariff return (rc); 3063162922Sariff } 3064162922Sariff 3065162922Sariff return (0); 3066162922Sariff} 3067162922Sariff 3068162922Sariffstatic void 3069162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 3070162922Sariff int index, int lmute, int rmute, 3071162922Sariff int left, int right, int dir) 3072162922Sariff{ 3073162922Sariff uint16_t v = 0; 3074162922Sariff 3075162922Sariff if (sc == NULL) 3076162922Sariff return; 3077162922Sariff 3078162922Sariff if (left != right || lmute != rmute) { 3079162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 3080162922Sariff (lmute << 7) | left; 3081162922Sariff hdac_command(sc, 3082164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3083162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 3084162922Sariff (rmute << 7) | right; 3085162922Sariff } else 3086162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 3087162922Sariff (lmute << 7) | left; 3088162922Sariff 3089162922Sariff hdac_command(sc, 3090162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3091162922Sariff} 3092162922Sariff 3093162922Sariffstatic void 3094162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3095162922Sariff int left, int right) 3096162922Sariff{ 3097162922Sariff struct hdac_softc *sc; 3098162922Sariff nid_t nid, cad; 3099162922Sariff int lmute, rmute; 3100162922Sariff 3101162922Sariff sc = ctl->widget->devinfo->codec->sc; 3102162922Sariff cad = ctl->widget->devinfo->codec->cad; 3103162922Sariff nid = ctl->widget->nid; 3104162922Sariff 3105182999Smav /* Save new values if valid. */ 3106182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3107182999Smav ctl->muted = mute; 3108182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3109182999Smav ctl->left = left; 3110182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3111182999Smav ctl->right = right; 3112182999Smav /* Prepare effective values */ 3113182999Smav if (ctl->forcemute) { 3114182999Smav lmute = 1; 3115182999Smav rmute = 1; 3116182999Smav left = 0; 3117182999Smav right = 0; 3118182999Smav } else { 3119162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3120162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3121182999Smav left = ctl->left; 3122182999Smav right = ctl->right; 3123162922Sariff } 3124182999Smav /* Apply effective values */ 3125162922Sariff if (ctl->dir & HDA_CTL_OUT) 3126162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3127162922Sariff lmute, rmute, left, right, 0); 3128162922Sariff if (ctl->dir & HDA_CTL_IN) 3129182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3130162922Sariff lmute, rmute, left, right, 1); 3131162922Sariff} 3132162922Sariff 3133162922Sariffstatic void 3134162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3135162922Sariff{ 3136162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3137162922Sariff return; 3138162922Sariff hdac_command(w->devinfo->codec->sc, 3139162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3140162922Sariff w->nid, index), w->devinfo->codec->cad); 3141162922Sariff w->selconn = index; 3142162922Sariff} 3143162922Sariff 3144162922Sariff 3145162922Sariff/**************************************************************************** 3146162922Sariff * uint32_t hdac_command_sendone_internal 3147162922Sariff * 3148162922Sariff * Wrapper function that sends only one command to a given codec 3149162922Sariff ****************************************************************************/ 3150162922Sariffstatic uint32_t 3151162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3152162922Sariff{ 3153162922Sariff struct hdac_command_list cl; 3154162965Sariff uint32_t response = HDAC_INVALID; 3155162922Sariff 3156163057Sariff if (!hdac_lockowned(sc)) 3157162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3158162922Sariff cl.num_commands = 1; 3159162922Sariff cl.verbs = &verb; 3160162922Sariff cl.responses = &response; 3161162922Sariff 3162162922Sariff hdac_command_send_internal(sc, &cl, cad); 3163162922Sariff 3164162922Sariff return (response); 3165162922Sariff} 3166162922Sariff 3167162922Sariff/**************************************************************************** 3168162922Sariff * hdac_command_send_internal 3169162922Sariff * 3170162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3171162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3172162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3173162922Sariff * if any. 3174162922Sariff ****************************************************************************/ 3175162922Sariffstatic void 3176162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3177162922Sariff struct hdac_command_list *commands, nid_t cad) 3178162922Sariff{ 3179162922Sariff struct hdac_codec *codec; 3180162922Sariff int corbrp; 3181162922Sariff uint32_t *corb; 3182162922Sariff int timeout; 3183162922Sariff int retry = 10; 3184164614Sariff struct hdac_rirb *rirb_base; 3185162922Sariff 3186164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3187164614Sariff commands->num_commands < 1) 3188162922Sariff return; 3189162922Sariff 3190162922Sariff codec = sc->codecs[cad]; 3191162922Sariff codec->commands = commands; 3192162922Sariff codec->responses_received = 0; 3193162922Sariff codec->verbs_sent = 0; 3194162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3195162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3196162922Sariff 3197162922Sariff do { 3198162922Sariff if (codec->verbs_sent != commands->num_commands) { 3199162922Sariff /* Queue as many verbs as possible */ 3200162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3201169277Sariff#if 0 3202162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3203162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3204169277Sariff#endif 3205162922Sariff while (codec->verbs_sent != commands->num_commands && 3206162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3207162922Sariff sc->corb_wp++; 3208162922Sariff sc->corb_wp %= sc->corb_size; 3209162922Sariff corb[sc->corb_wp] = 3210162922Sariff commands->verbs[codec->verbs_sent++]; 3211162922Sariff } 3212162922Sariff 3213162922Sariff /* Send the verbs to the codecs */ 3214169277Sariff#if 0 3215162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3216162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3217169277Sariff#endif 3218162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3219162922Sariff } 3220162922Sariff 3221162922Sariff timeout = 1000; 3222164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3223162922Sariff DELAY(10); 3224162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3225164614Sariff codec->responses_received != commands->num_commands) && --retry); 3226162922Sariff 3227162922Sariff if (retry == 0) 3228162922Sariff device_printf(sc->dev, 3229164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3230164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3231164614Sariff codec->responses_received); 3232162922Sariff 3233164614Sariff codec->commands = NULL; 3234164614Sariff codec->responses_received = 0; 3235162922Sariff codec->verbs_sent = 0; 3236162922Sariff 3237164614Sariff hdac_unsolq_flush(sc); 3238162922Sariff} 3239162922Sariff 3240162922Sariff 3241162922Sariff/**************************************************************************** 3242162922Sariff * Device Methods 3243162922Sariff ****************************************************************************/ 3244162922Sariff 3245162922Sariff/**************************************************************************** 3246162922Sariff * int hdac_probe(device_t) 3247162922Sariff * 3248162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3249162922Sariff * match using the subclass of the device. 3250162922Sariff ****************************************************************************/ 3251162922Sariffstatic int 3252162922Sariffhdac_probe(device_t dev) 3253162922Sariff{ 3254162922Sariff int i, result; 3255163257Sariff uint32_t model; 3256163257Sariff uint16_t class, subclass; 3257162922Sariff char desc[64]; 3258162922Sariff 3259162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3260162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3261162922Sariff class = pci_get_class(dev); 3262162922Sariff subclass = pci_get_subclass(dev); 3263162922Sariff 3264162922Sariff bzero(desc, sizeof(desc)); 3265162922Sariff result = ENXIO; 3266162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3267162922Sariff if (hdac_devices[i].model == model) { 3268162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3269162922Sariff result = BUS_PROBE_DEFAULT; 3270162922Sariff break; 3271162922Sariff } 3272163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3273162922Sariff class == PCIC_MULTIMEDIA && 3274162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3275162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3276162922Sariff result = BUS_PROBE_GENERIC; 3277162922Sariff break; 3278162922Sariff } 3279162922Sariff } 3280162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3281162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3282162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3283162922Sariff result = BUS_PROBE_GENERIC; 3284162922Sariff } 3285162922Sariff if (result != ENXIO) { 3286162922Sariff strlcat(desc, " High Definition Audio Controller", 3287162922Sariff sizeof(desc)); 3288162922Sariff device_set_desc_copy(dev, desc); 3289162922Sariff } 3290162922Sariff 3291162922Sariff return (result); 3292162922Sariff} 3293162922Sariff 3294162922Sariffstatic void * 3295162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3296162922Sariff struct pcm_channel *c, int dir) 3297162922Sariff{ 3298182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3299182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3300162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3301162922Sariff struct hdac_chan *ch; 3302182999Smav int i, ord = 0, chid; 3303162922Sariff 3304162922Sariff hdac_lock(sc); 3305182999Smav 3306182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3307182999Smav ch = &sc->chans[chid]; 3308182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3309182999Smav if (ch->dir == sc->chans[i].dir) 3310182999Smav ord++; 3311182999Smav } 3312162922Sariff if (dir == PCMDIR_PLAY) { 3313182999Smav ch->off = (sc->num_iss + ord) << 5; 3314162922Sariff } else { 3315182999Smav ch->off = ord << 5; 3316162922Sariff } 3317182999Smav 3318162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3319162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3320162922Sariff ch->pcmrates[0] = 48000; 3321162922Sariff ch->pcmrates[1] = 0; 3322162922Sariff } 3323169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3324169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3325169277Sariff (sc->streamcnt * 8)); 3326169277Sariff else 3327169277Sariff ch->dmapos = NULL; 3328169277Sariff ch->sid = ++sc->streamcnt; 3329169277Sariff ch->dir = dir; 3330162922Sariff ch->b = b; 3331162922Sariff ch->c = c; 3332182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3333182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3334162922Sariff hdac_unlock(sc); 3335162922Sariff 3336162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3337162922Sariff ch->blkcnt = 0; 3338162922Sariff return (NULL); 3339162922Sariff } 3340162922Sariff 3341169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3342171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3343182999Smav pdevinfo->chan_size) != 0) 3344162922Sariff return (NULL); 3345162922Sariff 3346162922Sariff return (ch); 3347162922Sariff} 3348162922Sariff 3349162922Sariffstatic int 3350162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3351162922Sariff{ 3352162922Sariff struct hdac_chan *ch = data; 3353162922Sariff int i; 3354162922Sariff 3355162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3356162922Sariff if (format == ch->caps.fmtlist[i]) { 3357162922Sariff ch->fmt = format; 3358162922Sariff return (0); 3359162922Sariff } 3360162922Sariff } 3361162922Sariff 3362162922Sariff return (EINVAL); 3363162922Sariff} 3364162922Sariff 3365162922Sariffstatic int 3366162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3367162922Sariff{ 3368162922Sariff struct hdac_chan *ch = data; 3369164614Sariff uint32_t spd = 0, threshold; 3370162922Sariff int i; 3371162922Sariff 3372162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3373162922Sariff spd = ch->pcmrates[i]; 3374164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3375164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3376164614Sariff if (speed < threshold) 3377162922Sariff break; 3378162922Sariff } 3379162922Sariff 3380164614Sariff if (spd == 0) /* impossible */ 3381162922Sariff ch->spd = 48000; 3382162922Sariff else 3383162922Sariff ch->spd = spd; 3384162922Sariff 3385162922Sariff return (ch->spd); 3386162922Sariff} 3387162922Sariff 3388162922Sariffstatic void 3389162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3390162922Sariff{ 3391162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3392182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3393173817Sariff struct hdac_widget *w; 3394182999Smav int i, chn, totalchn, c; 3395162922Sariff nid_t cad = ch->devinfo->codec->cad; 3396182999Smav uint16_t fmt, dfmt; 3397162922Sariff 3398183097Smav HDA_BOOTHVERBOSE( 3399182999Smav device_printf(ch->pdevinfo->dev, 3400182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3401182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3402182999Smav ch->fmt, ch->spd); 3403182999Smav ); 3404162922Sariff fmt = 0; 3405162922Sariff if (ch->fmt & AFMT_S16_LE) 3406162922Sariff fmt |= ch->bit16 << 4; 3407162922Sariff else if (ch->fmt & AFMT_S32_LE) 3408162922Sariff fmt |= ch->bit32 << 4; 3409162922Sariff else 3410162922Sariff fmt |= 1 << 4; 3411162922Sariff 3412162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3413162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3414162922Sariff fmt |= hda_rate_tab[i].base; 3415162922Sariff fmt |= hda_rate_tab[i].mul; 3416162922Sariff fmt |= hda_rate_tab[i].div; 3417162922Sariff break; 3418162922Sariff } 3419162922Sariff } 3420162922Sariff 3421182999Smav if (ch->fmt & (AFMT_STEREO | AFMT_AC3)) { 3422162922Sariff fmt |= 1; 3423173817Sariff totalchn = 2; 3424173817Sariff } else 3425173817Sariff totalchn = 1; 3426162922Sariff 3427162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3428182999Smav 3429182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3430182999Smav if (ch->fmt & AFMT_AC3) 3431182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3432162922Sariff 3433173817Sariff chn = 0; 3434162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3435173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3436173817Sariff if (w == NULL) 3437173817Sariff continue; 3438182999Smav 3439182999Smav if (as->hpredir >= 0 && i == as->pincnt) 3440182999Smav chn = 0; 3441183097Smav HDA_BOOTHVERBOSE( 3442182999Smav device_printf(ch->pdevinfo->dev, 3443182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3444182999Smav "fmt=0x%04x, dfmt=0x%04x\n", 3445162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3446182999Smav ch->io[i], fmt, dfmt); 3447162922Sariff ); 3448162922Sariff hdac_command(sc, 3449162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3450182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3451174025Sariff hdac_command(sc, 3452182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3453174025Sariff cad); 3454182999Smav } 3455182999Smav /* If HP redirection is enabled, but failed to use same 3456182999Smav DAC make last DAC one to duplicate first one. */ 3457182999Smav if (as->hpredir >= 0 && i == as->pincnt) { 3458182999Smav c = (ch->sid << 4); 3459182999Smav } else if (chn >= totalchn) { 3460182999Smav /* This is until OSS will support multichannel. 3461182999Smav Should be: c = 0; to disable unused DAC */ 3462182999Smav c = (ch->sid << 4); 3463182999Smav }else { 3464182999Smav c = (ch->sid << 4) | chn; 3465182999Smav } 3466182999Smav hdac_command(sc, 3467182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3468173817Sariff chn += 3469173817Sariff HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ? 3470173817Sariff 2 : 1; 3471162922Sariff } 3472162922Sariff} 3473162922Sariff 3474162922Sariffstatic int 3475167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3476167648Sariff uint32_t blksz, uint32_t blkcnt) 3477162922Sariff{ 3478162922Sariff struct hdac_chan *ch = data; 3479164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3480162922Sariff 3481167648Sariff blksz &= HDA_BLK_ALIGN; 3482162922Sariff 3483167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3484167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3485167648Sariff if (blksz < HDA_BLK_MIN) 3486167648Sariff blksz = HDA_BLK_MIN; 3487167648Sariff if (blkcnt > HDA_BDL_MAX) 3488167648Sariff blkcnt = HDA_BDL_MAX; 3489167648Sariff if (blkcnt < HDA_BDL_MIN) 3490167648Sariff blkcnt = HDA_BDL_MIN; 3491164614Sariff 3492167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3493167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3494167648Sariff blkcnt >>= 1; 3495167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3496167648Sariff blksz >>= 1; 3497167648Sariff else 3498167648Sariff break; 3499167648Sariff } 3500167648Sariff 3501164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3502167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3503167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3504164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3505167648Sariff __func__, blksz, blkcnt); 3506164614Sariff 3507164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3508167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3509164614Sariff 3510167648Sariff return (1); 3511167648Sariff} 3512167648Sariff 3513167648Sariffstatic int 3514167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3515167648Sariff{ 3516167648Sariff struct hdac_chan *ch = data; 3517167648Sariff 3518182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3519167648Sariff 3520162922Sariff return (ch->blksz); 3521162922Sariff} 3522162922Sariff 3523162922Sariffstatic void 3524162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3525162922Sariff{ 3526162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3527182999Smav struct hdac_widget *w; 3528162922Sariff nid_t cad = devinfo->codec->cad; 3529162922Sariff int i; 3530162922Sariff 3531162922Sariff hdac_stream_stop(ch); 3532162922Sariff 3533162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3534182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3535182999Smav if (w == NULL) 3536182999Smav continue; 3537182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3538182999Smav hdac_command(sc, 3539182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3540182999Smav cad); 3541182999Smav } 3542162922Sariff hdac_command(sc, 3543162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3544162922Sariff 0), cad); 3545162922Sariff } 3546162922Sariff} 3547162922Sariff 3548162922Sariffstatic void 3549162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3550162922Sariff{ 3551162922Sariff ch->ptr = 0; 3552162922Sariff ch->prevptr = 0; 3553162922Sariff hdac_stream_stop(ch); 3554162922Sariff hdac_stream_reset(ch); 3555162922Sariff hdac_bdl_setup(ch); 3556162922Sariff hdac_stream_setid(ch); 3557162922Sariff hdac_stream_setup(ch); 3558162922Sariff hdac_stream_start(ch); 3559162922Sariff} 3560162922Sariff 3561162922Sariffstatic int 3562162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3563162922Sariff{ 3564162922Sariff struct hdac_chan *ch = data; 3565162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3566162922Sariff 3567170521Sariff if (!PCMTRIG_COMMON(go)) 3568170521Sariff return (0); 3569170521Sariff 3570162922Sariff hdac_lock(sc); 3571162922Sariff switch (go) { 3572162922Sariff case PCMTRIG_START: 3573162922Sariff hdac_channel_start(sc, ch); 3574162922Sariff break; 3575162922Sariff case PCMTRIG_STOP: 3576162922Sariff case PCMTRIG_ABORT: 3577162922Sariff hdac_channel_stop(sc, ch); 3578162922Sariff break; 3579167610Sariff default: 3580167610Sariff break; 3581162922Sariff } 3582162922Sariff hdac_unlock(sc); 3583162922Sariff 3584162922Sariff return (0); 3585162922Sariff} 3586162922Sariff 3587162922Sariffstatic int 3588162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3589162922Sariff{ 3590162922Sariff struct hdac_chan *ch = data; 3591162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3592162922Sariff uint32_t ptr; 3593162922Sariff 3594162922Sariff hdac_lock(sc); 3595164614Sariff if (sc->polling != 0) 3596164614Sariff ptr = ch->ptr; 3597169277Sariff else if (ch->dmapos != NULL) 3598169277Sariff ptr = *(ch->dmapos); 3599164614Sariff else 3600164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3601162922Sariff hdac_unlock(sc); 3602162922Sariff 3603164614Sariff /* 3604164614Sariff * Round to available space and force 128 bytes aligment. 3605164614Sariff */ 3606164614Sariff ptr %= ch->blksz * ch->blkcnt; 3607167648Sariff ptr &= HDA_BLK_ALIGN; 3608162922Sariff 3609162922Sariff return (ptr); 3610162922Sariff} 3611162922Sariff 3612162922Sariffstatic struct pcmchan_caps * 3613162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3614162922Sariff{ 3615162922Sariff return (&((struct hdac_chan *)data)->caps); 3616162922Sariff} 3617162922Sariff 3618162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3619162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3620162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3621162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3622162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3623167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3624162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3625162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3626162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3627162922Sariff { 0, 0 } 3628162922Sariff}; 3629162922SariffCHANNEL_DECLARE(hdac_channel); 3630162922Sariff 3631162922Sariffstatic int 3632162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3633162922Sariff{ 3634182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3635182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3636162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3637162922Sariff struct hdac_widget *w, *cw; 3638162922Sariff struct hdac_audio_ctl *ctl; 3639162922Sariff uint32_t mask, recmask, id; 3640162922Sariff int i, j, softpcmvol; 3641162922Sariff 3642162922Sariff hdac_lock(sc); 3643162922Sariff 3644182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3645182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3646182999Smav pdevinfo->left[i] = 100; 3647182999Smav pdevinfo->right[i] = 100; 3648182999Smav } 3649182999Smav 3650162922Sariff mask = 0; 3651162922Sariff recmask = 0; 3652182999Smav id = hdac_codec_id(devinfo->codec); 3653162922Sariff 3654182999Smav /* Declate EAPD as ogain control. */ 3655182999Smav if (pdevinfo->play >= 0) { 3656182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3657182999Smav w = hdac_widget_get(devinfo, i); 3658182999Smav if (w == NULL || w->enable == 0) 3659182999Smav continue; 3660182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3661182999Smav w->param.eapdbtl == HDAC_INVALID || 3662182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3663182999Smav continue; 3664182999Smav mask |= SOUND_MASK_OGAIN; 3665162922Sariff break; 3666162922Sariff } 3667162922Sariff } 3668162922Sariff 3669182999Smav /* Declare volume controls assigned to this association. */ 3670162922Sariff i = 0; 3671162922Sariff ctl = NULL; 3672162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3673182999Smav if (ctl->enable == 0) 3674162922Sariff continue; 3675182999Smav if ((pdevinfo->play >= 0 && 3676182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3677182999Smav (pdevinfo->rec >= 0 && 3678182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3679182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3680182999Smav mask |= ctl->ossmask; 3681162922Sariff } 3682162922Sariff 3683182999Smav /* Declare record sources available to this association. */ 3684182999Smav if (pdevinfo->rec >= 0) { 3685182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3686182999Smav for (i = 0; ch->io[i] != -1; i++) { 3687182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3688182999Smav if (w == NULL || w->enable == 0) 3689182999Smav continue; 3690182999Smav for (j = 0; j < w->nconns; j++) { 3691182999Smav if (w->connsenable[j] == 0) 3692162922Sariff continue; 3693182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3694182999Smav if (cw == NULL || cw->enable == 0) 3695165992Sariff continue; 3696182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3697182999Smav cw->bindas != -2) 3698165992Sariff continue; 3699182999Smav recmask |= cw->ossmask; 3700165992Sariff } 3701182999Smav } 3702182999Smav } 3703182999Smav 3704185230Smav /* Declare soft PCM volume if needed. */ 3705185230Smav if (pdevinfo->play >= 0 && !pdevinfo->digital) { 3706182999Smav ctl = NULL; 3707182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3708182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3709182999Smav softpcmvol = 1; 3710182999Smav mask |= SOUND_MASK_PCM; 3711162922Sariff } else { 3712182999Smav softpcmvol = 0; 3713182999Smav i = 0; 3714182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3715182999Smav if (ctl->enable == 0) 3716162922Sariff continue; 3717182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3718182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3719162922Sariff continue; 3720182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3721182999Smav continue; 3722182999Smav if (ctl->step > 0) 3723182999Smav break; 3724162922Sariff } 3725162922Sariff } 3726182999Smav 3727182999Smav if (softpcmvol == 1 || ctl == NULL) { 3728182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3729182999Smav HDA_BOOTVERBOSE( 3730182999Smav device_printf(pdevinfo->dev, 3731182999Smav "%s Soft PCM volume\n", 3732182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3733182999Smav ); 3734182999Smav } 3735185230Smav } 3736182999Smav 3737185230Smav /* Declare master volume if needed. */ 3738185230Smav if (pdevinfo->play >= 0) { 3739185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3740185230Smav SOUND_MASK_PCM) { 3741182999Smav mask |= SOUND_MASK_VOLUME; 3742182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3743182999Smav SOUND_MASK_PCM); 3744182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3745182999Smav SOUND_MIXER_NONE); 3746182999Smav HDA_BOOTVERBOSE( 3747182999Smav device_printf(pdevinfo->dev, 3748182999Smav "Forcing master volume with PCM\n"); 3749182999Smav ); 3750182999Smav } 3751162922Sariff } 3752162922Sariff 3753169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3754169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3755162922Sariff 3756162922Sariff mix_setrecdevs(m, recmask); 3757162922Sariff mix_setdevs(m, mask); 3758162922Sariff 3759162922Sariff hdac_unlock(sc); 3760162922Sariff 3761162922Sariff return (0); 3762162922Sariff} 3763162922Sariff 3764162922Sariffstatic int 3765162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3766162922Sariff unsigned left, unsigned right) 3767162922Sariff{ 3768182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3769182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3770162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3771162922Sariff struct hdac_widget *w; 3772162922Sariff struct hdac_audio_ctl *ctl; 3773182999Smav uint32_t mute; 3774182999Smav int lvol, rvol; 3775182999Smav int i, j; 3776162922Sariff 3777162922Sariff hdac_lock(sc); 3778182999Smav /* Save new values. */ 3779182999Smav pdevinfo->left[dev] = left; 3780182999Smav pdevinfo->right[dev] = right; 3781182999Smav 3782182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3783162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3784163257Sariff uint32_t orig; 3785182999Smav w = NULL; 3786182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3787182999Smav w = hdac_widget_get(devinfo, i); 3788182999Smav if (w == NULL || w->enable == 0) 3789182999Smav continue; 3790182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3791182999Smav w->param.eapdbtl == HDAC_INVALID) 3792182999Smav continue; 3793182999Smav break; 3794162922Sariff } 3795182999Smav if (i >= devinfo->endnode) { 3796162922Sariff hdac_unlock(sc); 3797162922Sariff return (-1); 3798162922Sariff } 3799163257Sariff orig = w->param.eapdbtl; 3800163432Sariff if (left == 0) 3801162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3802162922Sariff else 3803162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3804163257Sariff if (orig != w->param.eapdbtl) { 3805163432Sariff uint32_t val; 3806163432Sariff 3807163432Sariff val = w->param.eapdbtl; 3808163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3809163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3810163257Sariff hdac_command(sc, 3811163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3812163432Sariff w->nid, val), devinfo->codec->cad); 3813163257Sariff } 3814162922Sariff hdac_unlock(sc); 3815162922Sariff return (left | (left << 8)); 3816162922Sariff } 3817162922Sariff 3818182999Smav /* Recalculate all controls related to this OSS device. */ 3819162922Sariff i = 0; 3820162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3821182999Smav if (ctl->enable == 0 || 3822162922Sariff !(ctl->ossmask & (1 << dev))) 3823162922Sariff continue; 3824182999Smav if (!((pdevinfo->play >= 0 && 3825182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3826182999Smav (pdevinfo->rec >= 0 && 3827182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3828182999Smav ctl->widget->bindas == -2)) 3829182999Smav continue; 3830182999Smav 3831182999Smav lvol = 100; 3832182999Smav rvol = 100; 3833182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3834182999Smav if (ctl->ossmask & (1 << j)) { 3835182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3836182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3837162922Sariff } 3838162922Sariff } 3839182999Smav mute = (left == 0) ? HDA_AMP_MUTE_LEFT : 0; 3840182999Smav mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3841182999Smav lvol = (lvol * ctl->step + 50) / 100; 3842182999Smav rvol = (rvol * ctl->step + 50) / 100; 3843162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3844162922Sariff } 3845162922Sariff hdac_unlock(sc); 3846162922Sariff 3847162922Sariff return (left | (right << 8)); 3848162922Sariff} 3849162922Sariff 3850182999Smav/* 3851182999Smav * Commutate specified record source. 3852182999Smav */ 3853182999Smavstatic uint32_t 3854182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3855162922Sariff{ 3856182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3857162922Sariff struct hdac_widget *w, *cw; 3858182999Smav struct hdac_audio_ctl *ctl; 3859182999Smav char buf[64]; 3860182999Smav int i, muted; 3861182999Smav uint32_t res = 0; 3862162922Sariff 3863182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3864182999Smav return (0); 3865182999Smav 3866182999Smav w = hdac_widget_get(devinfo, nid); 3867182999Smav if (w == NULL || w->enable == 0) 3868182999Smav return (0); 3869182999Smav 3870182999Smav for (i = 0; i < w->nconns; i++) { 3871182999Smav if (w->connsenable[i] == 0) 3872182999Smav continue; 3873182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3874182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3875182999Smav continue; 3876182999Smav /* Call recursively to trace signal to it's source if needed. */ 3877182999Smav if ((src & cw->ossmask) != 0) { 3878182999Smav if (cw->ossdev < 0) { 3879182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 3880182999Smav w->conns[i], depth + 1); 3881182999Smav } else { 3882182999Smav res |= cw->ossmask; 3883182999Smav } 3884182999Smav } 3885182999Smav /* We have two special cases: mixers and others (selectors). */ 3886182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 3887182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 3888182999Smav w->nid, HDA_CTL_IN, i, 1); 3889182999Smav if (ctl == NULL) 3890182999Smav continue; 3891182999Smav /* If we have input control on this node mute them 3892182999Smav * according to requested sources. */ 3893182999Smav muted = (src & cw->ossmask) ? 0 : 1; 3894182999Smav if (muted != ctl->forcemute) { 3895182999Smav ctl->forcemute = muted; 3896182999Smav hdac_audio_ctl_amp_set(ctl, 3897182999Smav HDA_AMP_MUTE_DEFAULT, 3898182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 3899182999Smav } 3900183097Smav HDA_BOOTHVERBOSE( 3901182999Smav device_printf(pdevinfo->dev, 3902182999Smav "Recsel (%s): nid %d source %d %s\n", 3903182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3904182999Smav src, buf, sizeof(buf)), 3905182999Smav nid, i, muted?"mute":"unmute"); 3906182999Smav ); 3907182999Smav } else { 3908182999Smav if (w->nconns == 1) 3909182999Smav break; 3910182999Smav if ((src & cw->ossmask) == 0) 3911182999Smav continue; 3912182999Smav /* If we found requested source - select it and exit. */ 3913182999Smav hdac_widget_connection_select(w, i); 3914183097Smav HDA_BOOTHVERBOSE( 3915182999Smav device_printf(pdevinfo->dev, 3916182999Smav "Recsel (%s): nid %d source %d select\n", 3917182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3918182999Smav src, buf, sizeof(buf)), 3919182999Smav nid, i); 3920182999Smav ); 3921162922Sariff break; 3922162922Sariff } 3923162922Sariff } 3924182999Smav return (res); 3925182999Smav} 3926162922Sariff 3927182999Smavstatic uint32_t 3928182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3929182999Smav{ 3930182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3931182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3932182999Smav struct hdac_widget *w; 3933182999Smav struct hdac_softc *sc = devinfo->codec->sc; 3934182999Smav struct hdac_chan *ch; 3935182999Smav int i; 3936182999Smav uint32_t ret = 0xffffffff; 3937182999Smav 3938162922Sariff hdac_lock(sc); 3939162922Sariff 3940182999Smav /* Commutate requested recsrc for each ADC. */ 3941182999Smav ch = &sc->chans[pdevinfo->rec]; 3942182999Smav for (i = 0; ch->io[i] != -1; i++) { 3943182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3944162965Sariff if (w == NULL || w->enable == 0) 3945162922Sariff continue; 3946182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 3947162922Sariff } 3948162922Sariff 3949162922Sariff hdac_unlock(sc); 3950162922Sariff 3951182999Smav return ((ret == 0xffffffff)? 0 : ret); 3952162922Sariff} 3953162922Sariff 3954162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3955162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3956162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3957162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3958162922Sariff { 0, 0 } 3959162922Sariff}; 3960162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3961162922Sariff 3962171141Sariffstatic void 3963171141Sariffhdac_unsolq_task(void *context, int pending) 3964171141Sariff{ 3965171141Sariff struct hdac_softc *sc; 3966171141Sariff 3967171141Sariff sc = (struct hdac_softc *)context; 3968171141Sariff 3969171141Sariff hdac_lock(sc); 3970171141Sariff hdac_unsolq_flush(sc); 3971171141Sariff hdac_unlock(sc); 3972171141Sariff} 3973171141Sariff 3974162922Sariff/**************************************************************************** 3975162922Sariff * int hdac_attach(device_t) 3976162922Sariff * 3977162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3978162922Sariff * when this function is called. Setup everything that doesn't require 3979162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3980162922Sariff ****************************************************************************/ 3981162922Sariffstatic int 3982162922Sariffhdac_attach(device_t dev) 3983162922Sariff{ 3984162922Sariff struct hdac_softc *sc; 3985162922Sariff int result; 3986189086Smav int i, devid = -1; 3987189086Smav uint32_t model; 3988189086Smav uint16_t class, subclass; 3989169277Sariff uint16_t vendor; 3990169277Sariff uint8_t v; 3991162922Sariff 3992184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 3993182999Smav 3994189086Smav model = (uint32_t)pci_get_device(dev) << 16; 3995189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3996189086Smav class = pci_get_class(dev); 3997189086Smav subclass = pci_get_subclass(dev); 3998189086Smav 3999189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 4000189086Smav if (hdac_devices[i].model == model) { 4001189086Smav devid = i; 4002189086Smav break; 4003189086Smav } 4004189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 4005189086Smav class == PCIC_MULTIMEDIA && 4006189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 4007189086Smav devid = i; 4008189086Smav break; 4009189086Smav } 4010189086Smav } 4011189086Smav 4012182999Smav sc = device_get_softc(dev); 4013163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 4014162922Sariff sc->dev = dev; 4015163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 4016163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 4017169277Sariff vendor = pci_get_vendor(dev); 4018162922Sariff 4019165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 4020165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 4021165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 4022165281Sariff } 4023165281Sariff 4024164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 4025164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 4026169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 4027164614Sariff 4028171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 4029171141Sariff 4030182999Smav sc->poll_ticks = 1000000; 4031169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 4032169277Sariff if (resource_int_value(device_get_name(dev), 4033169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 4034164614Sariff sc->polling = 1; 4035164614Sariff else 4036164614Sariff sc->polling = 0; 4037164614Sariff 4038162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 4039162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 4040162922Sariff 0, /* boundary */ 4041162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 4042162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 4043162922Sariff NULL, /* filtfunc */ 4044162922Sariff NULL, /* fistfuncarg */ 4045182999Smav HDA_BUFSZ_MAX, /* maxsize */ 4046162922Sariff 1, /* nsegments */ 4047182999Smav HDA_BUFSZ_MAX, /* maxsegsz */ 4048162922Sariff 0, /* flags */ 4049162922Sariff NULL, /* lockfunc */ 4050162922Sariff NULL, /* lockfuncarg */ 4051162922Sariff &sc->chan_dmat); /* dmat */ 4052162922Sariff if (result != 0) { 4053169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 4054162922Sariff __func__, result); 4055163057Sariff snd_mtxfree(sc->lock); 4056162922Sariff free(sc, M_DEVBUF); 4057162922Sariff return (ENXIO); 4058162922Sariff } 4059162922Sariff 4060162922Sariff 4061162922Sariff sc->hdabus = NULL; 4062162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 4063162922Sariff sc->codecs[i] = NULL; 4064162922Sariff 4065162922Sariff pci_enable_busmaster(dev); 4066162922Sariff 4067169277Sariff if (vendor == INTEL_VENDORID) { 4068169277Sariff /* TCSEL -> TC0 */ 4069169277Sariff v = pci_read_config(dev, 0x44, 1); 4070169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 4071183097Smav HDA_BOOTHVERBOSE( 4072169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 4073169277Sariff pci_read_config(dev, 0x44, 1)); 4074169277Sariff ); 4075169277Sariff } 4076169277Sariff 4077189127Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_MSI)) 4078188656Smav sc->flags &= ~HDAC_F_MSI; 4079188656Smav else 4080171330Sariff sc->flags |= HDAC_F_MSI; 4081189086Smav if (resource_int_value(device_get_name(dev), 4082189086Smav device_get_unit(dev), "msi", &i) == 0) { 4083189086Smav if (i == 0) 4084189086Smav sc->flags &= ~HDAC_F_MSI; 4085189086Smav else 4086189086Smav sc->flags |= HDAC_F_MSI; 4087189086Smav } 4088171330Sariff 4089169277Sariff#if defined(__i386__) || defined(__amd64__) 4090171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4091169277Sariff 4092169277Sariff if (resource_int_value(device_get_name(dev), 4093169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 4094169277Sariff#else 4095171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4096169277Sariff#endif 4097169277Sariff /* 4098169277Sariff * Try to enable PCIe snoop to avoid messing around with 4099169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 4100169277Sariff * config is pretty much vendor specific, there are no 4101169277Sariff * general solutions on how to enable it, forcing us (even 4102169277Sariff * Microsoft) to enable uncacheable or write combined DMA 4103169277Sariff * by default. 4104169277Sariff * 4105169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 4106169277Sariff */ 4107169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 4108169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 4109169277Sariff continue; 4110171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4111169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4112169277Sariff break; 4113169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4114169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4115169277Sariff hdac_pcie_snoop[i].enable) 4116169277Sariff break; 4117169277Sariff v &= hdac_pcie_snoop[i].mask; 4118169277Sariff v |= hdac_pcie_snoop[i].enable; 4119169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4120169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4121169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4122169277Sariff hdac_pcie_snoop[i].enable) { 4123169277Sariff HDA_BOOTVERBOSE( 4124169277Sariff device_printf(dev, 4125169277Sariff "WARNING: Failed to enable PCIe " 4126169277Sariff "snoop!\n"); 4127169277Sariff ); 4128169277Sariff#if defined(__i386__) || defined(__amd64__) 4129171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4130169277Sariff#endif 4131169277Sariff } 4132169277Sariff break; 4133169277Sariff } 4134169277Sariff#if defined(__i386__) || defined(__amd64__) 4135169277Sariff } 4136169277Sariff#endif 4137169277Sariff 4138183097Smav HDA_BOOTHVERBOSE( 4139169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4140171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4141171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4142169277Sariff ); 4143169277Sariff 4144162922Sariff /* Allocate resources */ 4145162922Sariff result = hdac_mem_alloc(sc); 4146162922Sariff if (result != 0) 4147163057Sariff goto hdac_attach_fail; 4148162922Sariff result = hdac_irq_alloc(sc); 4149162922Sariff if (result != 0) 4150163057Sariff goto hdac_attach_fail; 4151162922Sariff 4152162922Sariff /* Get Capabilities */ 4153162922Sariff result = hdac_get_capabilities(sc); 4154162922Sariff if (result != 0) 4155163057Sariff goto hdac_attach_fail; 4156162922Sariff 4157162922Sariff /* Allocate CORB and RIRB dma memory */ 4158162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4159162922Sariff sc->corb_size * sizeof(uint32_t)); 4160162922Sariff if (result != 0) 4161163057Sariff goto hdac_attach_fail; 4162162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4163162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4164162922Sariff if (result != 0) 4165163057Sariff goto hdac_attach_fail; 4166162922Sariff 4167162922Sariff /* Quiesce everything */ 4168183097Smav HDA_BOOTHVERBOSE( 4169182999Smav device_printf(dev, "Reset controller...\n"); 4170182999Smav ); 4171182999Smav hdac_reset(sc, 1); 4172162922Sariff 4173162922Sariff /* Initialize the CORB and RIRB */ 4174162922Sariff hdac_corb_init(sc); 4175162922Sariff hdac_rirb_init(sc); 4176162922Sariff 4177162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4178162922Sariff sc->intrhook.ich_func = hdac_attach2; 4179162922Sariff sc->intrhook.ich_arg = (void *)sc; 4180162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4181162922Sariff sc->intrhook.ich_func = NULL; 4182162922Sariff hdac_attach2((void *)sc); 4183162922Sariff } 4184162922Sariff 4185163057Sariff return (0); 4186162922Sariff 4187163057Sariffhdac_attach_fail: 4188162922Sariff hdac_irq_free(sc); 4189169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4190169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4191162922Sariff hdac_mem_free(sc); 4192162922Sariff snd_mtxfree(sc->lock); 4193163057Sariff free(sc, M_DEVBUF); 4194162922Sariff 4195163057Sariff return (ENXIO); 4196162922Sariff} 4197162922Sariff 4198162922Sariffstatic void 4199162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4200162922Sariff{ 4201182999Smav struct hdac_codec *codec = devinfo->codec; 4202182999Smav struct hdac_softc *sc = codec->sc; 4203162922Sariff struct hdac_widget *w; 4204162922Sariff uint32_t res; 4205162922Sariff int i; 4206162922Sariff nid_t cad, nid; 4207162922Sariff 4208162922Sariff cad = devinfo->codec->cad; 4209162922Sariff nid = devinfo->nid; 4210162922Sariff 4211162922Sariff res = hdac_command(sc, 4212169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4213169277Sariff devinfo->function.audio.gpio = res; 4214169277Sariff 4215163057Sariff HDA_BOOTVERBOSE( 4216183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4217183097Smav "NumGPIO=%d NumGPO=%d " 4218169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4219183097Smav devinfo->function.audio.gpio, 4220169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4221169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4222169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4223169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4224169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4225162922Sariff ); 4226162922Sariff 4227162922Sariff res = hdac_command(sc, 4228162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4229162922Sariff cad); 4230162922Sariff devinfo->function.audio.supp_stream_formats = res; 4231162922Sariff 4232162922Sariff res = hdac_command(sc, 4233162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4234162922Sariff cad); 4235162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4236162922Sariff 4237162922Sariff res = hdac_command(sc, 4238162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4239162922Sariff cad); 4240162922Sariff devinfo->function.audio.outamp_cap = res; 4241162922Sariff 4242162922Sariff res = hdac_command(sc, 4243162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4244162922Sariff cad); 4245162922Sariff devinfo->function.audio.inamp_cap = res; 4246162922Sariff 4247162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4248162922Sariff w = hdac_widget_get(devinfo, i); 4249162922Sariff if (w == NULL) 4250162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4251162922Sariff else { 4252162922Sariff w->devinfo = devinfo; 4253162922Sariff w->nid = i; 4254162922Sariff w->enable = 1; 4255162922Sariff w->selconn = -1; 4256162922Sariff w->pflags = 0; 4257182999Smav w->ossdev = -1; 4258182999Smav w->bindas = -1; 4259162965Sariff w->param.eapdbtl = HDAC_INVALID; 4260162922Sariff hdac_widget_parse(w); 4261162922Sariff } 4262162922Sariff } 4263162922Sariff} 4264162922Sariff 4265162922Sariffstatic void 4266162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4267162922Sariff{ 4268162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4269162922Sariff struct hdac_audio_ctl *ctls; 4270162922Sariff struct hdac_widget *w, *cw; 4271162922Sariff int i, j, cnt, max, ocap, icap; 4272163057Sariff int mute, offset, step, size; 4273162922Sariff 4274162922Sariff /* XXX This is redundant */ 4275162922Sariff max = 0; 4276162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4277162922Sariff w = hdac_widget_get(devinfo, i); 4278162922Sariff if (w == NULL || w->enable == 0) 4279162922Sariff continue; 4280162922Sariff if (w->param.outamp_cap != 0) 4281162922Sariff max++; 4282162922Sariff if (w->param.inamp_cap != 0) { 4283162922Sariff switch (w->type) { 4284162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4285162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4286162922Sariff for (j = 0; j < w->nconns; j++) { 4287162922Sariff cw = hdac_widget_get(devinfo, 4288162922Sariff w->conns[j]); 4289162922Sariff if (cw == NULL || cw->enable == 0) 4290162922Sariff continue; 4291162922Sariff max++; 4292162922Sariff } 4293162922Sariff break; 4294162922Sariff default: 4295162922Sariff max++; 4296162922Sariff break; 4297162922Sariff } 4298162922Sariff } 4299162922Sariff } 4300162922Sariff 4301162922Sariff devinfo->function.audio.ctlcnt = max; 4302162922Sariff 4303162922Sariff if (max < 1) 4304162922Sariff return; 4305162922Sariff 4306162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4307162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4308162922Sariff 4309162922Sariff if (ctls == NULL) { 4310162922Sariff /* Blekh! */ 4311162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4312162922Sariff devinfo->function.audio.ctlcnt = 0; 4313162922Sariff return; 4314162922Sariff } 4315162922Sariff 4316162922Sariff cnt = 0; 4317162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4318162922Sariff if (cnt >= max) { 4319162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4320162922Sariff __func__); 4321162922Sariff break; 4322162922Sariff } 4323162922Sariff w = hdac_widget_get(devinfo, i); 4324162922Sariff if (w == NULL || w->enable == 0) 4325162922Sariff continue; 4326162922Sariff ocap = w->param.outamp_cap; 4327162922Sariff icap = w->param.inamp_cap; 4328162922Sariff if (ocap != 0) { 4329163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4330163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4331163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4332163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4333163057Sariff /*if (offset > step) { 4334163057Sariff HDA_BOOTVERBOSE( 4335163057Sariff device_printf(sc->dev, 4336182999Smav "BUGGY outamp: nid=%d " 4337163057Sariff "[offset=%d > step=%d]\n", 4338163057Sariff w->nid, offset, step); 4339163057Sariff ); 4340163057Sariff offset = step; 4341163057Sariff }*/ 4342162922Sariff ctls[cnt].enable = 1; 4343162922Sariff ctls[cnt].widget = w; 4344163057Sariff ctls[cnt].mute = mute; 4345163057Sariff ctls[cnt].step = step; 4346163057Sariff ctls[cnt].size = size; 4347163057Sariff ctls[cnt].offset = offset; 4348163057Sariff ctls[cnt].left = offset; 4349163057Sariff ctls[cnt].right = offset; 4350182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4351182999Smav w->waspin) 4352182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4353182999Smav else 4354182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4355162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4356162922Sariff } 4357162922Sariff 4358162922Sariff if (icap != 0) { 4359163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4360163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4361163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4362163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4363163057Sariff /*if (offset > step) { 4364163057Sariff HDA_BOOTVERBOSE( 4365163057Sariff device_printf(sc->dev, 4366182999Smav "BUGGY inamp: nid=%d " 4367163057Sariff "[offset=%d > step=%d]\n", 4368163057Sariff w->nid, offset, step); 4369163057Sariff ); 4370163057Sariff offset = step; 4371163057Sariff }*/ 4372162922Sariff switch (w->type) { 4373162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4374162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4375162922Sariff for (j = 0; j < w->nconns; j++) { 4376162922Sariff if (cnt >= max) { 4377162922Sariff device_printf(sc->dev, 4378162922Sariff "%s: Ctl overflow!\n", 4379162922Sariff __func__); 4380162922Sariff break; 4381162922Sariff } 4382162922Sariff cw = hdac_widget_get(devinfo, 4383162922Sariff w->conns[j]); 4384162922Sariff if (cw == NULL || cw->enable == 0) 4385162922Sariff continue; 4386162922Sariff ctls[cnt].enable = 1; 4387162922Sariff ctls[cnt].widget = w; 4388162922Sariff ctls[cnt].childwidget = cw; 4389162922Sariff ctls[cnt].index = j; 4390163057Sariff ctls[cnt].mute = mute; 4391163057Sariff ctls[cnt].step = step; 4392163057Sariff ctls[cnt].size = size; 4393163057Sariff ctls[cnt].offset = offset; 4394163057Sariff ctls[cnt].left = offset; 4395163057Sariff ctls[cnt].right = offset; 4396182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4397162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4398162922Sariff } 4399162922Sariff break; 4400162922Sariff default: 4401162922Sariff if (cnt >= max) { 4402162922Sariff device_printf(sc->dev, 4403162922Sariff "%s: Ctl overflow!\n", 4404162922Sariff __func__); 4405162922Sariff break; 4406162922Sariff } 4407162922Sariff ctls[cnt].enable = 1; 4408162922Sariff ctls[cnt].widget = w; 4409163057Sariff ctls[cnt].mute = mute; 4410163057Sariff ctls[cnt].step = step; 4411163057Sariff ctls[cnt].size = size; 4412163057Sariff ctls[cnt].offset = offset; 4413163057Sariff ctls[cnt].left = offset; 4414163057Sariff ctls[cnt].right = offset; 4415182999Smav if (w->type == 4416182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4417182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4418182999Smav else 4419182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4420162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4421162922Sariff break; 4422162922Sariff } 4423162922Sariff } 4424162922Sariff } 4425162922Sariff 4426162922Sariff devinfo->function.audio.ctl = ctls; 4427162922Sariff} 4428162922Sariff 4429182999Smavstatic void 4430182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4431182999Smav{ 4432182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4433182999Smav struct hdac_audio_as *as; 4434182999Smav struct hdac_widget *w; 4435182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4436182999Smav 4437184991Smav /* Count present associations */ 4438182999Smav max = 0; 4439184991Smav for (j = 1; j < 16; j++) { 4440182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4441182999Smav w = hdac_widget_get(devinfo, i); 4442182999Smav if (w == NULL || w->enable == 0) 4443182999Smav continue; 4444182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4445182999Smav continue; 4446182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4447182999Smav != j) 4448182999Smav continue; 4449182999Smav max++; 4450182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4451182999Smav break; 4452182999Smav } 4453182999Smav } 4454182999Smav 4455182999Smav devinfo->function.audio.ascnt = max; 4456182999Smav 4457182999Smav if (max < 1) 4458182999Smav return; 4459182999Smav 4460182999Smav as = (struct hdac_audio_as *)malloc( 4461182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4462182999Smav 4463182999Smav if (as == NULL) { 4464182999Smav /* Blekh! */ 4465182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4466182999Smav devinfo->function.audio.ascnt = 0; 4467182999Smav return; 4468182999Smav } 4469182999Smav 4470182999Smav for (i = 0; i < max; i++) { 4471182999Smav as[i].hpredir = -1; 4472182999Smav as[i].chan = -1; 4473185225Smav as[i].digital = 1; 4474182999Smav } 4475182999Smav 4476182999Smav /* Scan associations skipping as=0. */ 4477182999Smav cnt = 0; 4478182999Smav for (j = 1; j < 16; j++) { 4479182999Smav first = 16; 4480182999Smav hpredir = 0; 4481182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4482182999Smav w = hdac_widget_get(devinfo, i); 4483182999Smav if (w == NULL || w->enable == 0) 4484182999Smav continue; 4485182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4486182999Smav continue; 4487182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4488182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4489182999Smav if (assoc != j) { 4490182999Smav continue; 4491182999Smav } 4492182999Smav KASSERT(cnt < max, 4493182999Smav ("%s: Associations owerflow (%d of %d)", 4494182999Smav __func__, cnt, max)); 4495182999Smav type = w->wclass.pin.config & 4496182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4497182999Smav /* Get pin direction. */ 4498182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4499182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4500182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4501182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4502182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4503182999Smav dir = HDA_CTL_OUT; 4504182999Smav else 4505182999Smav dir = HDA_CTL_IN; 4506182999Smav /* If this is a first pin - create new association. */ 4507182999Smav if (as[cnt].pincnt == 0) { 4508182999Smav as[cnt].enable = 1; 4509182999Smav as[cnt].index = j; 4510182999Smav as[cnt].dir = dir; 4511182999Smav } 4512182999Smav if (seq < first) 4513182999Smav first = seq; 4514182999Smav /* Check association correctness. */ 4515182999Smav if (as[cnt].pins[seq] != 0) { 4516182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4517182999Smav "in association %d! Disabling association.\n", 4518182999Smav __func__, seq, w->nid, j); 4519182999Smav as[cnt].enable = 0; 4520182999Smav } 4521182999Smav if (dir != as[cnt].dir) { 4522182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4523182999Smav "direction for association %d! Disabling " 4524182999Smav "association.\n", 4525182999Smav __func__, w->nid, j); 4526182999Smav as[cnt].enable = 0; 4527182999Smav } 4528185225Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 4529185225Smav as[cnt].digital = 0; 4530182999Smav /* Headphones with seq=15 may mean redirection. */ 4531182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4532182999Smav seq == 15) 4533182999Smav hpredir = 1; 4534182999Smav as[cnt].pins[seq] = w->nid; 4535182999Smav as[cnt].pincnt++; 4536182999Smav /* Association 15 is a multiple unassociated pins. */ 4537182999Smav if (j == 15) 4538182999Smav cnt++; 4539182999Smav } 4540182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4541182999Smav if (hpredir && as[cnt].pincnt > 1) 4542182999Smav as[cnt].hpredir = first; 4543182999Smav cnt++; 4544182999Smav } 4545182999Smav } 4546182999Smav HDA_BOOTVERBOSE( 4547182999Smav device_printf(sc->dev, 4548183097Smav "%d associations found:\n", max); 4549182999Smav for (i = 0; i < max; i++) { 4550182999Smav device_printf(sc->dev, 4551182999Smav "Association %d (%d) %s%s:\n", 4552182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4553182999Smav as[i].enable?"":" (disabled)"); 4554182999Smav for (j = 0; j < 16; j++) { 4555182999Smav if (as[i].pins[j] == 0) 4556182999Smav continue; 4557182999Smav device_printf(sc->dev, 4558183097Smav " Pin nid=%d seq=%d\n", 4559182999Smav as[i].pins[j], j); 4560182999Smav } 4561182999Smav } 4562182999Smav ); 4563182999Smav 4564182999Smav devinfo->function.audio.as = as; 4565182999Smav} 4566182999Smav 4567162965Sariffstatic const struct { 4568162965Sariff uint32_t model; 4569162965Sariff uint32_t id; 4570162965Sariff uint32_t set, unset; 4571162965Sariff} hdac_quirks[] = { 4572163057Sariff /* 4573163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4574163057Sariff * on few codecs (especially ALC880) seems broken or 4575163057Sariff * perhaps unsupported. 4576163057Sariff */ 4577163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4578169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4579162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4580165039Sariff HDA_QUIRK_GPIO0, 0 }, 4581178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4582178155Sariff HDA_QUIRK_GPIO0, 0 }, 4583162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4584165039Sariff HDA_QUIRK_GPIO0, 0 }, 4585165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4586165281Sariff HDA_QUIRK_GPIO0, 0 }, 4587167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4588167623Sariff HDA_QUIRK_GPIO0, 0 }, 4589169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4590169277Sariff HDA_QUIRK_GPIO0, 0 }, 4591163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4592163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4593178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4594163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4595169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4596169277Sariff HDA_QUIRK_OVREF, 0 }, 4597169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4598169277Sariff HDA_QUIRK_OVREF, 0 }, 4599169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4600169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4601165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4602165281Sariff HDA_QUIRK_GPIO1, 0 }, 4603164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4604182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4605164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4606164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4607173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4608173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4609165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4610165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4611183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4612180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4613184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4614184483Smav HDA_QUIRK_GPIO2, 0 }, 4615183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4616178155Sariff HDA_QUIRK_GPIO0, 0 }, 4617169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4618169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4619170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4620170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4621186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4622182999Smav 0, HDA_QUIRK_FORCESTEREO } 4623162965Sariff}; 4624162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4625162965Sariff 4626162922Sariffstatic void 4627162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4628162922Sariff{ 4629162922Sariff struct hdac_widget *w; 4630162965Sariff uint32_t id, subvendor; 4631162922Sariff int i; 4632162922Sariff 4633182999Smav id = hdac_codec_id(devinfo->codec); 4634163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4635163057Sariff 4636162922Sariff /* 4637163057Sariff * Quirks 4638162922Sariff */ 4639163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4640163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4641163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4642163057Sariff continue; 4643163057Sariff if (hdac_quirks[i].set != 0) 4644163057Sariff devinfo->function.audio.quirks |= 4645163057Sariff hdac_quirks[i].set; 4646163057Sariff if (hdac_quirks[i].unset != 0) 4647163057Sariff devinfo->function.audio.quirks &= 4648163057Sariff ~(hdac_quirks[i].unset); 4649163057Sariff } 4650163057Sariff 4651162922Sariff switch (id) { 4652166965Sariff case HDA_CODEC_ALC883: 4653166965Sariff /* 4654166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4655166965Sariff * Clear vref cap for jack connectivity. 4656166965Sariff */ 4657166965Sariff w = hdac_widget_get(devinfo, 24); 4658166965Sariff if (w != NULL && w->enable != 0 && w->type == 4659166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4660166965Sariff (w->wclass.pin.config & 4661166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4662166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4663166965Sariff w->wclass.pin.cap &= ~( 4664166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4665166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4666166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4667166965Sariff w = hdac_widget_get(devinfo, 25); 4668166965Sariff if (w != NULL && w->enable != 0 && w->type == 4669166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4670166965Sariff (w->wclass.pin.config & 4671166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4672166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4673166965Sariff w->wclass.pin.cap &= ~( 4674166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4675166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4676166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4677166965Sariff /* 4678166965Sariff * nid: 26 = Line-in, leave it alone. 4679166965Sariff */ 4680166965Sariff break; 4681187196Smav case HDA_CODEC_AD1983: 4682187196Smav /* 4683187202Smav * This codec has several possible usages, but none 4684187202Smav * fit the parser best. Help parser to choose better. 4685187196Smav */ 4686187196Smav /* Disable direct unmixed playback to get pcm volume. */ 4687187196Smav w = hdac_widget_get(devinfo, 5); 4688187196Smav if (w != NULL) 4689187196Smav w->connsenable[0] = 0; 4690187196Smav w = hdac_widget_get(devinfo, 6); 4691187196Smav if (w != NULL) 4692187196Smav w->connsenable[0] = 0; 4693187196Smav w = hdac_widget_get(devinfo, 11); 4694187196Smav if (w != NULL) 4695187196Smav w->connsenable[0] = 0; 4696187196Smav /* Disable mic and line selectors. */ 4697187196Smav w = hdac_widget_get(devinfo, 12); 4698187196Smav if (w != NULL) 4699187196Smav w->connsenable[1] = 0; 4700187196Smav w = hdac_widget_get(devinfo, 13); 4701187196Smav if (w != NULL) 4702187196Smav w->connsenable[1] = 0; 4703187196Smav /* Disable recording from mono playback mix. */ 4704187196Smav w = hdac_widget_get(devinfo, 20); 4705187196Smav if (w != NULL) 4706187196Smav w->connsenable[3] = 0; 4707187196Smav break; 4708162922Sariff case HDA_CODEC_AD1986A: 4709186503Smav /* 4710186503Smav * This codec has overcomplicated input mixing. 4711186503Smav * Make some cleaning there. 4712186503Smav */ 4713186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4714186503Smav w = hdac_widget_get(devinfo, 43); 4715186503Smav if (w != NULL) 4716186503Smav w->enable = 0; 4717186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4718186503Smav w = hdac_widget_get(devinfo, 39); 4719186503Smav if (w != NULL) 4720186503Smav w->enable = 0; 4721186503Smav w = hdac_widget_get(devinfo, 40); 4722186503Smav if (w != NULL) 4723186503Smav w->enable = 0; 4724186503Smav w = hdac_widget_get(devinfo, 41); 4725186503Smav if (w != NULL) 4726186503Smav w->enable = 0; 4727186503Smav w = hdac_widget_get(devinfo, 42); 4728186503Smav if (w != NULL) 4729186503Smav w->enable = 0; 4730186503Smav /* Disable duplicate mixer node connector. */ 4731186503Smav w = hdac_widget_get(devinfo, 15); 4732186503Smav if (w != NULL) 4733186503Smav w->connsenable[3] = 0; 4734186503Smav 4735182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4736178155Sariff /* 4737178155Sariff * This is just plain ridiculous.. There 4738178155Sariff * are several A8 series that share the same 4739178155Sariff * pci id but works differently (EAPD). 4740178155Sariff */ 4741178155Sariff w = hdac_widget_get(devinfo, 26); 4742178155Sariff if (w != NULL && w->type == 4743178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4744178155Sariff (w->wclass.pin.config & 4745178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4746178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4747178155Sariff devinfo->function.audio.quirks &= 4748178155Sariff ~HDA_QUIRK_EAPDINV; 4749169277Sariff } 4750162922Sariff break; 4751184230Smav case HDA_CODEC_AD1981HD: 4752184230Smav /* 4753184230Smav * This codec has very unusual design with several 4754184254Smav * points inappropriate for the present parser. 4755184230Smav */ 4756184230Smav /* Disable recording from mono playback mix. */ 4757184230Smav w = hdac_widget_get(devinfo, 21); 4758184230Smav if (w != NULL) 4759184230Smav w->connsenable[3] = 0; 4760184230Smav /* Disable rear to front mic mixer, use separately. */ 4761184230Smav w = hdac_widget_get(devinfo, 31); 4762184230Smav if (w != NULL) 4763184230Smav w->enable = 0; 4764184230Smav /* Disable playback mixer, use direct bypass. */ 4765184230Smav w = hdac_widget_get(devinfo, 14); 4766184230Smav if (w != NULL) 4767184230Smav w->enable = 0; 4768184230Smav break; 4769182999Smav } 4770182999Smav} 4771182999Smav 4772182999Smav/* 4773182999Smav * Trace path from DAC to pin. 4774182999Smav */ 4775182999Smavstatic nid_t 4776182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4777182999Smav int dupseq, int min, int only, int depth) 4778182999Smav{ 4779182999Smav struct hdac_widget *w; 4780182999Smav int i, im = -1; 4781182999Smav nid_t m = 0, ret; 4782182999Smav 4783182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4784182999Smav return (0); 4785182999Smav w = hdac_widget_get(devinfo, nid); 4786182999Smav if (w == NULL || w->enable == 0) 4787182999Smav return (0); 4788183097Smav HDA_BOOTHVERBOSE( 4789182999Smav if (!only) { 4790182999Smav device_printf(devinfo->codec->sc->dev, 4791182999Smav " %*stracing via nid %d\n", 4792182999Smav depth + 1, "", w->nid); 4793169277Sariff } 4794182999Smav ); 4795182999Smav /* Use only unused widgets */ 4796182999Smav if (w->bindas >= 0 && w->bindas != as) { 4797183097Smav HDA_BOOTHVERBOSE( 4798182999Smav if (!only) { 4799182999Smav device_printf(devinfo->codec->sc->dev, 4800182999Smav " %*snid %d busy by association %d\n", 4801182999Smav depth + 1, "", w->nid, w->bindas); 4802182999Smav } 4803182999Smav ); 4804182999Smav return (0); 4805182999Smav } 4806182999Smav if (dupseq < 0) { 4807182999Smav if (w->bindseqmask != 0) { 4808183097Smav HDA_BOOTHVERBOSE( 4809182999Smav if (!only) { 4810182999Smav device_printf(devinfo->codec->sc->dev, 4811182999Smav " %*snid %d busy by seqmask %x\n", 4812182999Smav depth + 1, "", w->nid, w->bindseqmask); 4813182999Smav } 4814182999Smav ); 4815182999Smav return (0); 4816169277Sariff } 4817182999Smav } else { 4818182999Smav /* If this is headphones - allow duplicate first pin. */ 4819182999Smav if (w->bindseqmask != 0 && 4820182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4821183097Smav HDA_BOOTHVERBOSE( 4822182999Smav device_printf(devinfo->codec->sc->dev, 4823182999Smav " %*snid %d busy by seqmask %x\n", 4824182999Smav depth + 1, "", w->nid, w->bindseqmask); 4825182999Smav ); 4826182999Smav return (0); 4827169277Sariff } 4828182999Smav } 4829182999Smav 4830182999Smav switch (w->type) { 4831182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4832182999Smav /* Do not traverse input. AD1988 has digital monitor 4833182999Smav for which we are not ready. */ 4834169277Sariff break; 4835182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4836182999Smav /* If we are tracing HP take only dac of first pin. */ 4837182999Smav if ((only == 0 || only == w->nid) && 4838182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4839182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4840182999Smav m = w->nid; 4841178155Sariff break; 4842182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4843182999Smav if (depth > 0) 4844169277Sariff break; 4845182999Smav /* Fall */ 4846182999Smav default: 4847182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4848182999Smav for (i = 0; i < w->nconns; i++) { 4849182999Smav if (w->connsenable[i] == 0) 4850162922Sariff continue; 4851182999Smav if (w->selconn != -1 && w->selconn != i) 4852162922Sariff continue; 4853182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4854182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4855182999Smav if (m == 0 || ret < m) { 4856182999Smav m = ret; 4857182999Smav im = i; 4858182999Smav } 4859182999Smav if (only || dupseq >= 0) 4860182999Smav break; 4861182999Smav } 4862162922Sariff } 4863182999Smav if (m && only && ((w->nconns > 1 && 4864182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4865182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4866182999Smav w->selconn = im; 4867162922Sariff break; 4868182999Smav } 4869182999Smav if (m && only) { 4870182999Smav w->bindas = as; 4871182999Smav w->bindseqmask |= (1 << seq); 4872182999Smav } 4873183097Smav HDA_BOOTHVERBOSE( 4874182999Smav if (!only) { 4875182999Smav device_printf(devinfo->codec->sc->dev, 4876182999Smav " %*snid %d returned %d\n", 4877182999Smav depth + 1, "", w->nid, m); 4878182999Smav } 4879182999Smav ); 4880182999Smav return (m); 4881182999Smav} 4882162922Sariff 4883182999Smav/* 4884182999Smav * Trace path from widget to ADC. 4885182999Smav */ 4886182999Smavstatic nid_t 4887182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4888182999Smav int only, int depth) 4889182999Smav{ 4890182999Smav struct hdac_widget *w, *wc; 4891182999Smav int i, j; 4892182999Smav nid_t res = 0; 4893182999Smav 4894182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4895182999Smav return (0); 4896182999Smav w = hdac_widget_get(devinfo, nid); 4897182999Smav if (w == NULL || w->enable == 0) 4898182999Smav return (0); 4899183097Smav HDA_BOOTHVERBOSE( 4900182999Smav device_printf(devinfo->codec->sc->dev, 4901182999Smav " %*stracing via nid %d\n", 4902182999Smav depth + 1, "", w->nid); 4903182999Smav ); 4904182999Smav /* Use only unused widgets */ 4905182999Smav if (w->bindas >= 0 && w->bindas != as) { 4906183097Smav HDA_BOOTHVERBOSE( 4907182999Smav device_printf(devinfo->codec->sc->dev, 4908182999Smav " %*snid %d busy by association %d\n", 4909182999Smav depth + 1, "", w->nid, w->bindas); 4910182999Smav ); 4911182999Smav return (0); 4912182999Smav } 4913182999Smav 4914182999Smav switch (w->type) { 4915182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4916182999Smav /* If we are tracing HP take only dac of first pin. */ 4917182999Smav if (only == w->nid) 4918182999Smav res = 1; 4919162922Sariff break; 4920182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4921182999Smav if (depth > 0) 4922182999Smav break; 4923182999Smav /* Fall */ 4924182999Smav default: 4925182999Smav /* Try to find reachable ADCs with specified nid. */ 4926182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4927182999Smav wc = hdac_widget_get(devinfo, j); 4928182999Smav if (wc == NULL || wc->enable == 0) 4929182999Smav continue; 4930182999Smav for (i = 0; i < wc->nconns; i++) { 4931182999Smav if (wc->connsenable[i] == 0) 4932182999Smav continue; 4933182999Smav if (wc->conns[i] != nid) 4934182999Smav continue; 4935182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 4936182999Smav j, only, depth + 1) != 0) { 4937182999Smav res = 1; 4938182999Smav if (((wc->nconns > 1 && 4939182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4940182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 4941182999Smav wc->selconn == -1) 4942182999Smav wc->selconn = i; 4943182999Smav } 4944182999Smav } 4945169277Sariff } 4946169277Sariff break; 4947162922Sariff } 4948182999Smav if (res) { 4949182999Smav w->bindas = as; 4950182999Smav w->bindseqmask |= (1 << seq); 4951182999Smav } 4952183097Smav HDA_BOOTHVERBOSE( 4953182999Smav device_printf(devinfo->codec->sc->dev, 4954182999Smav " %*snid %d returned %d\n", 4955182999Smav depth + 1, "", w->nid, res); 4956182999Smav ); 4957182999Smav return (res); 4958162922Sariff} 4959162922Sariff 4960182999Smav/* 4961182999Smav * Erase trace path of the specified association. 4962182999Smav */ 4963182999Smavstatic void 4964182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 4965182999Smav{ 4966182999Smav struct hdac_widget *w; 4967182999Smav int i; 4968182999Smav 4969182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4970182999Smav w = hdac_widget_get(devinfo, i); 4971182999Smav if (w == NULL || w->enable == 0) 4972182999Smav continue; 4973182999Smav if (w->bindas == as) { 4974182999Smav if (seq >= 0) { 4975182999Smav w->bindseqmask &= ~(1 << seq); 4976182999Smav if (w->bindseqmask == 0) { 4977182999Smav w->bindas = -1; 4978182999Smav w->selconn = -1; 4979182999Smav } 4980182999Smav } else { 4981182999Smav w->bindas = -1; 4982182999Smav w->bindseqmask = 0; 4983182999Smav w->selconn = -1; 4984182999Smav } 4985182999Smav } 4986182999Smav } 4987182999Smav} 4988182999Smav 4989182999Smav/* 4990182999Smav * Trace association path from DAC to output 4991182999Smav */ 4992162922Sariffstatic int 4993182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 4994162922Sariff{ 4995182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4996182999Smav int i, hpredir; 4997182999Smav nid_t min, res; 4998162922Sariff 4999182999Smav /* Find next pin */ 5000185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 5001182999Smav ; 5002188510Smav /* Check if there is no any left. If so - we succeeded. */ 5003182999Smav if (i == 16) 5004182999Smav return (1); 5005182999Smav 5006182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 5007182999Smav min = 0; 5008182999Smav res = 0; 5009182999Smav do { 5010183097Smav HDA_BOOTHVERBOSE( 5011182999Smav device_printf(devinfo->codec->sc->dev, 5012182999Smav " Tracing pin %d with min nid %d", 5013182999Smav ases[as].pins[i], min); 5014182999Smav if (hpredir >= 0) 5015183097Smav printf(" and hpredir %d", hpredir); 5016183097Smav printf("\n"); 5017182999Smav ); 5018182999Smav /* Trace this pin taking min nid into account. */ 5019182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 5020182999Smav ases[as].pins[i], hpredir, min, 0, 0); 5021182999Smav if (res == 0) { 5022182999Smav /* If we failed - return to previous and redo it. */ 5023182999Smav HDA_BOOTVERBOSE( 5024182999Smav device_printf(devinfo->codec->sc->dev, 5025182999Smav " Unable to trace pin %d seq %d with min " 5026183097Smav "nid %d", 5027183097Smav ases[as].pins[i], i, min); 5028183097Smav if (hpredir >= 0) 5029183097Smav printf(" and hpredir %d", hpredir); 5030183097Smav printf("\n"); 5031182999Smav ); 5032182999Smav return (0); 5033162922Sariff } 5034182999Smav HDA_BOOTVERBOSE( 5035182999Smav device_printf(devinfo->codec->sc->dev, 5036183097Smav " Pin %d traced to DAC %d", 5037183097Smav ases[as].pins[i], res); 5038183097Smav if (hpredir >= 0) 5039183097Smav printf(" and hpredir %d", hpredir); 5040183097Smav if (ases[as].fakeredir) 5041183097Smav printf(" with fake redirection"); 5042183097Smav printf("\n"); 5043182999Smav ); 5044182999Smav /* Trace again to mark the path */ 5045182999Smav hdac_audio_trace_dac(devinfo, as, i, 5046182999Smav ases[as].pins[i], hpredir, min, res, 0); 5047182999Smav ases[as].dacs[i] = res; 5048188510Smav /* We succeeded, so call next. */ 5049182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 5050182999Smav return (1); 5051182999Smav /* If next failed, we should retry with next min */ 5052182999Smav hdac_audio_undo_trace(devinfo, as, i); 5053182999Smav ases[as].dacs[i] = 0; 5054182999Smav min = res + 1; 5055182999Smav } while (1); 5056162922Sariff} 5057162922Sariff 5058182999Smav/* 5059182999Smav * Trace association path from input to ADC 5060182999Smav */ 5061162922Sariffstatic int 5062182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 5063162922Sariff{ 5064182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5065162922Sariff struct hdac_widget *w; 5066182999Smav int i, j, k; 5067162922Sariff 5068182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5069182999Smav w = hdac_widget_get(devinfo, j); 5070182999Smav if (w == NULL || w->enable == 0) 5071182999Smav continue; 5072182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5073182999Smav continue; 5074182999Smav if (w->bindas >= 0 && w->bindas != as) 5075182999Smav continue; 5076182999Smav 5077182999Smav /* Find next pin */ 5078182999Smav for (i = 0; i < 16; i++) { 5079182999Smav if (ases[as].pins[i] == 0) 5080182999Smav continue; 5081182999Smav 5082183097Smav HDA_BOOTHVERBOSE( 5083182999Smav device_printf(devinfo->codec->sc->dev, 5084182999Smav " Tracing pin %d to ADC %d\n", 5085182999Smav ases[as].pins[i], j); 5086182999Smav ); 5087182999Smav /* Trace this pin taking goal into account. */ 5088182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 5089182999Smav ases[as].pins[i], j, 0) == 0) { 5090182999Smav /* If we failed - return to previous and redo it. */ 5091182999Smav HDA_BOOTVERBOSE( 5092182999Smav device_printf(devinfo->codec->sc->dev, 5093183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 5094182999Smav ases[as].pins[i], j); 5095182999Smav ); 5096182999Smav hdac_audio_undo_trace(devinfo, as, -1); 5097182999Smav for (k = 0; k < 16; k++) 5098182999Smav ases[as].dacs[k] = 0; 5099182999Smav break; 5100162922Sariff } 5101182999Smav HDA_BOOTVERBOSE( 5102182999Smav device_printf(devinfo->codec->sc->dev, 5103183097Smav " Pin %d traced to ADC %d\n", 5104183097Smav ases[as].pins[i], j); 5105182999Smav ); 5106182999Smav ases[as].dacs[i] = j; 5107162922Sariff } 5108182999Smav if (i == 16) 5109182999Smav return (1); 5110162922Sariff } 5111182999Smav return (0); 5112162922Sariff} 5113162922Sariff 5114182999Smav/* 5115182999Smav * Trace input monitor path from mixer to output association. 5116182999Smav */ 5117183097Smavstatic int 5118182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5119162922Sariff{ 5120182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5121182999Smav struct hdac_widget *w, *wc; 5122182999Smav int i, j; 5123182999Smav nid_t res = 0; 5124162922Sariff 5125162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5126162922Sariff return (0); 5127162922Sariff w = hdac_widget_get(devinfo, nid); 5128162922Sariff if (w == NULL || w->enable == 0) 5129162922Sariff return (0); 5130183097Smav HDA_BOOTHVERBOSE( 5131182999Smav device_printf(devinfo->codec->sc->dev, 5132182999Smav " %*stracing via nid %d\n", 5133182999Smav depth + 1, "", w->nid); 5134182999Smav ); 5135182999Smav /* Use only unused widgets */ 5136182999Smav if (depth > 0 && w->bindas != -1) { 5137182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5138183097Smav HDA_BOOTHVERBOSE( 5139182999Smav device_printf(devinfo->codec->sc->dev, 5140182999Smav " %*snid %d found output association %d\n", 5141182999Smav depth + 1, "", w->nid, w->bindas); 5142182999Smav ); 5143182999Smav return (1); 5144182999Smav } else { 5145183097Smav HDA_BOOTHVERBOSE( 5146182999Smav device_printf(devinfo->codec->sc->dev, 5147182999Smav " %*snid %d busy by input association %d\n", 5148182999Smav depth + 1, "", w->nid, w->bindas); 5149182999Smav ); 5150182999Smav return (0); 5151182999Smav } 5152182999Smav } 5153182999Smav 5154162922Sariff switch (w->type) { 5155162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5156182999Smav /* Do not traverse input. AD1988 has digital monitor 5157182999Smav for which we are not ready. */ 5158162922Sariff break; 5159162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5160182999Smav if (depth > 0) 5161182999Smav break; 5162182999Smav /* Fall */ 5163182999Smav default: 5164182999Smav /* Try to find reachable ADCs with specified nid. */ 5165182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5166182999Smav wc = hdac_widget_get(devinfo, j); 5167182999Smav if (wc == NULL || wc->enable == 0) 5168182999Smav continue; 5169182999Smav for (i = 0; i < wc->nconns; i++) { 5170182999Smav if (wc->connsenable[i] == 0) 5171182999Smav continue; 5172182999Smav if (wc->conns[i] != nid) 5173182999Smav continue; 5174182999Smav if (hdac_audio_trace_to_out(devinfo, 5175182999Smav j, depth + 1) != 0) { 5176182999Smav res = 1; 5177182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5178182999Smav wc->selconn == -1) 5179182999Smav wc->selconn = i; 5180182999Smav } 5181182999Smav } 5182162922Sariff } 5183162922Sariff break; 5184182999Smav } 5185182999Smav if (res) 5186182999Smav w->bindas = -2; 5187182999Smav 5188183097Smav HDA_BOOTHVERBOSE( 5189182999Smav device_printf(devinfo->codec->sc->dev, 5190182999Smav " %*snid %d returned %d\n", 5191182999Smav depth + 1, "", w->nid, res); 5192182999Smav ); 5193182999Smav return (res); 5194182999Smav} 5195182999Smav 5196182999Smav/* 5197182999Smav * Trace extra associations (beeper, monitor) 5198182999Smav */ 5199182999Smavstatic void 5200182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5201182999Smav{ 5202182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5203182999Smav struct hdac_widget *w; 5204182999Smav int j; 5205182999Smav 5206182999Smav /* Input monitor */ 5207182999Smav /* Find mixer associated with input, but supplying signal 5208182999Smav for output associations. Hope it will be input monitor. */ 5209182999Smav HDA_BOOTVERBOSE( 5210182999Smav device_printf(devinfo->codec->sc->dev, 5211182999Smav "Tracing input monitor\n"); 5212182999Smav ); 5213182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5214182999Smav w = hdac_widget_get(devinfo, j); 5215182999Smav if (w == NULL || w->enable == 0) 5216182999Smav continue; 5217182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5218182999Smav continue; 5219182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5220182999Smav continue; 5221182999Smav HDA_BOOTVERBOSE( 5222182999Smav device_printf(devinfo->codec->sc->dev, 5223182999Smav " Tracing nid %d to out\n", 5224182999Smav j); 5225182999Smav ); 5226182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5227182999Smav HDA_BOOTVERBOSE( 5228182999Smav device_printf(devinfo->codec->sc->dev, 5229182999Smav " nid %d is input monitor\n", 5230182999Smav w->nid); 5231182999Smav ); 5232182999Smav w->pflags |= HDA_ADC_MONITOR; 5233182999Smav w->ossdev = SOUND_MIXER_IMIX; 5234162922Sariff } 5235162922Sariff } 5236182999Smav 5237182999Smav /* Beeper */ 5238182999Smav HDA_BOOTVERBOSE( 5239182999Smav device_printf(devinfo->codec->sc->dev, 5240182999Smav "Tracing beeper\n"); 5241182999Smav ); 5242182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5243182999Smav w = hdac_widget_get(devinfo, j); 5244182999Smav if (w == NULL || w->enable == 0) 5245182999Smav continue; 5246182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5247182999Smav continue; 5248183097Smav HDA_BOOTHVERBOSE( 5249182999Smav device_printf(devinfo->codec->sc->dev, 5250182999Smav " Tracing nid %d to out\n", 5251182999Smav j); 5252182999Smav ); 5253183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5254183097Smav HDA_BOOTVERBOSE( 5255183097Smav device_printf(devinfo->codec->sc->dev, 5256183097Smav " nid %d traced to out\n", 5257183097Smav j); 5258183097Smav ); 5259183097Smav } 5260182999Smav w->bindas = -2; 5261182999Smav } 5262162922Sariff} 5263162922Sariff 5264182999Smav/* 5265182999Smav * Bind assotiations to PCM channels 5266182999Smav */ 5267182999Smavstatic void 5268182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5269162922Sariff{ 5270182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5271182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5272182999Smav int j, cnt = 0, free; 5273162922Sariff 5274182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5275182999Smav if (as[j].enable) 5276182999Smav cnt++; 5277182999Smav } 5278182999Smav if (sc->num_chans == 0) { 5279182999Smav sc->chans = (struct hdac_chan *)malloc( 5280182999Smav sizeof(struct hdac_chan) * cnt, 5281182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5282182999Smav if (sc->chans == NULL) { 5283190519Smav device_printf(sc->dev, 5284182999Smav "Channels memory allocation failed!\n"); 5285182999Smav return; 5286182999Smav } 5287182999Smav } else { 5288182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5289183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5290182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5291182999Smav if (sc->chans == NULL) { 5292182999Smav sc->num_chans = 0; 5293190519Smav device_printf(sc->dev, 5294182999Smav "Channels memory allocation failed!\n"); 5295182999Smav return; 5296182999Smav } 5297190519Smav /* Fixup relative pointers after realloc */ 5298190519Smav for (j = 0; j < sc->num_chans; j++) 5299190519Smav sc->chans[j].caps.fmtlist = sc->chans[j].fmtlist; 5300182999Smav } 5301182999Smav free = sc->num_chans; 5302182999Smav sc->num_chans += cnt; 5303162922Sariff 5304182999Smav for (j = free; j < free + cnt; j++) { 5305190519Smav sc->chans[j].devinfo = devinfo; 5306190519Smav sc->chans[j].as = -1; 5307182999Smav } 5308162922Sariff 5309182999Smav /* Assign associations in order of their numbers, */ 5310182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5311182999Smav if (as[j].enable == 0) 5312182999Smav continue; 5313182999Smav 5314182999Smav as[j].chan = free; 5315190519Smav sc->chans[free].as = j; 5316190519Smav sc->chans[free].dir = 5317185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5318190519Smav hdac_pcmchannel_setup(&sc->chans[free]); 5319182999Smav free++; 5320182999Smav } 5321182999Smav} 5322162922Sariff 5323182999Smavstatic void 5324182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5325182999Smav{ 5326182999Smav struct hdac_widget *w; 5327182999Smav int i; 5328182999Smav 5329182999Smav /* Disable power and volume widgets. */ 5330182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5331182999Smav w = hdac_widget_get(devinfo, i); 5332182999Smav if (w == NULL || w->enable == 0) 5333182999Smav continue; 5334182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5335182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5336182999Smav w->enable = 0; 5337183097Smav HDA_BOOTHVERBOSE( 5338182999Smav device_printf(devinfo->codec->sc->dev, 5339182999Smav " Disabling nid %d due to it's" 5340182999Smav " non-audio type.\n", 5341182999Smav w->nid); 5342182999Smav ); 5343162922Sariff } 5344182999Smav } 5345182999Smav} 5346182999Smav 5347182999Smavstatic void 5348182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5349182999Smav{ 5350182999Smav struct hdac_widget *w, *cw; 5351182999Smav struct hdac_audio_ctl *ctl; 5352182999Smav int done, found, i, j, k; 5353182999Smav 5354182999Smav /* Disable useless pins. */ 5355182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5356182999Smav w = hdac_widget_get(devinfo, i); 5357182999Smav if (w == NULL || w->enable == 0) 5358182999Smav continue; 5359184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5360184991Smav if ((w->wclass.pin.config & 5361184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5362184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5363184991Smav w->enable = 0; 5364184991Smav HDA_BOOTHVERBOSE( 5365184991Smav device_printf(devinfo->codec->sc->dev, 5366184991Smav " Disabling pin nid %d due" 5367184991Smav " to None connectivity.\n", 5368184991Smav w->nid); 5369184991Smav ); 5370184991Smav } else if ((w->wclass.pin.config & 5371184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5372184991Smav w->enable = 0; 5373184991Smav HDA_BOOTHVERBOSE( 5374184991Smav device_printf(devinfo->codec->sc->dev, 5375184991Smav " Disabling unassociated" 5376184991Smav " pin nid %d.\n", 5377184991Smav w->nid); 5378184991Smav ); 5379184991Smav } 5380182999Smav } 5381182999Smav } 5382182999Smav do { 5383182999Smav done = 1; 5384182999Smav /* Disable and mute controls for disabled widgets. */ 5385162922Sariff i = 0; 5386162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5387182999Smav if (ctl->enable == 0) 5388162922Sariff continue; 5389182999Smav if (ctl->widget->enable == 0 || 5390182999Smav (ctl->childwidget != NULL && 5391182999Smav ctl->childwidget->enable == 0)) { 5392182999Smav ctl->forcemute = 1; 5393182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5394182999Smav ctl->left = 0; 5395182999Smav ctl->right = 0; 5396182999Smav ctl->enable = 0; 5397182999Smav if (ctl->ndir == HDA_CTL_IN) 5398182999Smav ctl->widget->connsenable[ctl->index] = 0; 5399182999Smav done = 0; 5400183097Smav HDA_BOOTHVERBOSE( 5401182999Smav device_printf(devinfo->codec->sc->dev, 5402182999Smav " Disabling ctl %d nid %d cnid %d due" 5403182999Smav " to disabled widget.\n", i, 5404182999Smav ctl->widget->nid, 5405182999Smav (ctl->childwidget != NULL)? 5406182999Smav ctl->childwidget->nid:-1); 5407182999Smav ); 5408182999Smav } 5409182999Smav } 5410182999Smav /* Disable useless widgets. */ 5411182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5412182999Smav w = hdac_widget_get(devinfo, i); 5413182999Smav if (w == NULL || w->enable == 0) 5414182999Smav continue; 5415182999Smav /* Disable inputs with disabled child widgets. */ 5416182999Smav for (j = 0; j < w->nconns; j++) { 5417182999Smav if (w->connsenable[j]) { 5418182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5419182999Smav if (cw == NULL || cw->enable == 0) { 5420182999Smav w->connsenable[j] = 0; 5421183097Smav HDA_BOOTHVERBOSE( 5422182999Smav device_printf(devinfo->codec->sc->dev, 5423182999Smav " Disabling nid %d connection %d due" 5424182999Smav " to disabled child widget.\n", 5425182999Smav i, j); 5426182999Smav ); 5427163057Sariff } 5428163057Sariff } 5429162922Sariff } 5430182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5431182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5432162922Sariff continue; 5433182999Smav /* Disable mixers and selectors without inputs. */ 5434182999Smav found = 0; 5435182999Smav for (j = 0; j < w->nconns; j++) { 5436182999Smav if (w->connsenable[j]) { 5437182999Smav found = 1; 5438162922Sariff break; 5439162922Sariff } 5440182999Smav } 5441182999Smav if (found == 0) { 5442182999Smav w->enable = 0; 5443182999Smav done = 0; 5444183097Smav HDA_BOOTHVERBOSE( 5445182999Smav device_printf(devinfo->codec->sc->dev, 5446182999Smav " Disabling nid %d due to all it's" 5447182999Smav " inputs disabled.\n", w->nid); 5448182999Smav ); 5449182999Smav } 5450182999Smav /* Disable nodes without consumers. */ 5451182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5452182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5453182999Smav continue; 5454182999Smav found = 0; 5455182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5456182999Smav cw = hdac_widget_get(devinfo, k); 5457182999Smav if (cw == NULL || cw->enable == 0) 5458182999Smav continue; 5459182999Smav for (j = 0; j < cw->nconns; j++) { 5460182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5461182999Smav found = 1; 5462182999Smav break; 5463182999Smav } 5464162922Sariff } 5465162922Sariff } 5466182999Smav if (found == 0) { 5467182999Smav w->enable = 0; 5468182999Smav done = 0; 5469183097Smav HDA_BOOTHVERBOSE( 5470182999Smav device_printf(devinfo->codec->sc->dev, 5471182999Smav " Disabling nid %d due to all it's" 5472182999Smav " consumers disabled.\n", w->nid); 5473182999Smav ); 5474182999Smav } 5475162922Sariff } 5476182999Smav } while (done == 0); 5477182999Smav 5478182999Smav} 5479182999Smav 5480182999Smavstatic void 5481182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5482182999Smav{ 5483182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5484182999Smav struct hdac_widget *w, *cw; 5485182999Smav struct hdac_audio_ctl *ctl; 5486182999Smav int i, j, k; 5487182999Smav 5488182999Smav /* Disable unassosiated widgets. */ 5489182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5490182999Smav w = hdac_widget_get(devinfo, i); 5491182999Smav if (w == NULL || w->enable == 0) 5492182999Smav continue; 5493182999Smav if (w->bindas == -1) { 5494182999Smav w->enable = 0; 5495183097Smav HDA_BOOTHVERBOSE( 5496182999Smav device_printf(devinfo->codec->sc->dev, 5497182999Smav " Disabling unassociated nid %d.\n", 5498182999Smav w->nid); 5499182999Smav ); 5500182999Smav } 5501182999Smav } 5502182999Smav /* Disable input connections on input pin and 5503182999Smav * output on output. */ 5504182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5505182999Smav w = hdac_widget_get(devinfo, i); 5506182999Smav if (w == NULL || w->enable == 0) 5507182999Smav continue; 5508182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5509182999Smav continue; 5510182999Smav if (w->bindas < 0) 5511182999Smav continue; 5512182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5513182999Smav for (j = 0; j < w->nconns; j++) { 5514182999Smav if (w->connsenable[j] == 0) 5515182999Smav continue; 5516182999Smav w->connsenable[j] = 0; 5517183097Smav HDA_BOOTHVERBOSE( 5518182999Smav device_printf(devinfo->codec->sc->dev, 5519182999Smav " Disabling connection to input pin " 5520182999Smav "nid %d conn %d.\n", 5521182999Smav i, j); 5522182999Smav ); 5523162922Sariff } 5524182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5525182999Smav HDA_CTL_IN, -1, 1); 5526182999Smav if (ctl && ctl->enable) { 5527182999Smav ctl->forcemute = 1; 5528182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5529182999Smav ctl->left = 0; 5530182999Smav ctl->right = 0; 5531182999Smav ctl->enable = 0; 5532182999Smav } 5533182999Smav } else { 5534182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5535182999Smav HDA_CTL_OUT, -1, 1); 5536182999Smav if (ctl && ctl->enable) { 5537182999Smav ctl->forcemute = 1; 5538182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5539182999Smav ctl->left = 0; 5540182999Smav ctl->right = 0; 5541182999Smav ctl->enable = 0; 5542182999Smav } 5543182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5544182999Smav cw = hdac_widget_get(devinfo, k); 5545182999Smav if (cw == NULL || cw->enable == 0) 5546182999Smav continue; 5547182999Smav for (j = 0; j < cw->nconns; j++) { 5548182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5549182999Smav cw->connsenable[j] = 0; 5550183097Smav HDA_BOOTHVERBOSE( 5551182999Smav device_printf(devinfo->codec->sc->dev, 5552182999Smav " Disabling connection from output pin " 5553182999Smav "nid %d conn %d cnid %d.\n", 5554182999Smav k, j, i); 5555182999Smav ); 5556182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5557182999Smav cw->nconns > 1) 5558182999Smav continue; 5559182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5560182999Smav HDA_CTL_IN, j, 1); 5561182999Smav if (ctl && ctl->enable) { 5562182999Smav ctl->forcemute = 1; 5563182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5564182999Smav ctl->left = 0; 5565182999Smav ctl->right = 0; 5566182999Smav ctl->enable = 0; 5567182999Smav } 5568182999Smav } 5569182999Smav } 5570182999Smav } 5571162922Sariff } 5572162922Sariff } 5573162922Sariff} 5574162922Sariff 5575182999Smavstatic void 5576182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5577162922Sariff{ 5578182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5579182999Smav struct hdac_widget *w; 5580182999Smav int i, j; 5581182999Smav 5582182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5583182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5584182999Smav w = hdac_widget_get(devinfo, i); 5585182999Smav if (w == NULL || w->enable == 0) 5586182999Smav continue; 5587182999Smav if (w->nconns <= 1) 5588182999Smav continue; 5589182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5590182999Smav continue; 5591182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5592182999Smav continue; 5593182999Smav for (j = 0; j < w->nconns; j++) { 5594182999Smav if (w->connsenable[j] == 0) 5595182999Smav continue; 5596182999Smav if (w->selconn < 0 || w->selconn == j) 5597182999Smav continue; 5598182999Smav w->connsenable[j] = 0; 5599183097Smav HDA_BOOTHVERBOSE( 5600182999Smav device_printf(devinfo->codec->sc->dev, 5601182999Smav " Disabling unselected connection " 5602182999Smav "nid %d conn %d.\n", 5603182999Smav i, j); 5604182999Smav ); 5605182999Smav } 5606182999Smav } 5607182999Smav} 5608182999Smav 5609182999Smavstatic void 5610182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5611182999Smav{ 5612162922Sariff struct hdac_widget *w, *cw; 5613162922Sariff struct hdac_audio_ctl *ctl; 5614182999Smav int i, j; 5615162922Sariff 5616187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5617182999Smav /* ... using selectors */ 5618182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5619182999Smav w = hdac_widget_get(devinfo, i); 5620182999Smav if (w == NULL || w->enable == 0) 5621182999Smav continue; 5622182999Smav if (w->nconns <= 1) 5623182999Smav continue; 5624182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5625182999Smav continue; 5626182999Smav if (w->bindas == -2) 5627182999Smav continue; 5628182999Smav for (j = 0; j < w->nconns; j++) { 5629182999Smav if (w->connsenable[j] == 0) 5630182999Smav continue; 5631182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5632182999Smav if (cw == NULL || w->enable == 0) 5633182999Smav continue; 5634187052Smav if (cw->bindas == -2) 5635182999Smav continue; 5636187052Smav if (w->bindas == cw->bindas && 5637187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5638187052Smav continue; 5639182999Smav w->connsenable[j] = 0; 5640183097Smav HDA_BOOTHVERBOSE( 5641182999Smav device_printf(devinfo->codec->sc->dev, 5642182999Smav " Disabling crossassociatement connection " 5643182999Smav "nid %d conn %d cnid %d.\n", 5644182999Smav i, j, cw->nid); 5645182999Smav ); 5646182999Smav } 5647182999Smav } 5648182999Smav /* ... using controls */ 5649182999Smav i = 0; 5650182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5651182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5652182999Smav continue; 5653182999Smav if (ctl->widget->bindas == -2 || 5654182999Smav ctl->childwidget->bindas == -2) 5655182999Smav continue; 5656187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5657187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5658182999Smav ctl->forcemute = 1; 5659182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5660182999Smav ctl->left = 0; 5661182999Smav ctl->right = 0; 5662182999Smav ctl->enable = 0; 5663182999Smav if (ctl->ndir == HDA_CTL_IN) 5664182999Smav ctl->widget->connsenable[ctl->index] = 0; 5665183097Smav HDA_BOOTHVERBOSE( 5666182999Smav device_printf(devinfo->codec->sc->dev, 5667182999Smav " Disabling crossassociatement connection " 5668182999Smav "ctl %d nid %d cnid %d.\n", i, 5669182999Smav ctl->widget->nid, 5670182999Smav ctl->childwidget->nid); 5671182999Smav ); 5672182999Smav } 5673182999Smav } 5674182999Smav 5675182999Smav} 5676182999Smav 5677182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5678182999Smav 5679182999Smav/* 5680182999Smav * Find controls to control amplification for source. 5681182999Smav */ 5682182999Smavstatic int 5683182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5684182999Smav int ossdev, int ctlable, int depth, int need) 5685182999Smav{ 5686182999Smav struct hdac_widget *w, *wc; 5687182999Smav struct hdac_audio_ctl *ctl; 5688182999Smav int i, j, conns = 0, rneed; 5689182999Smav 5690162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5691182999Smav return (need); 5692162922Sariff 5693162922Sariff w = hdac_widget_get(devinfo, nid); 5694162922Sariff if (w == NULL || w->enable == 0) 5695182999Smav return (need); 5696182999Smav 5697182999Smav /* Count number of active inputs. */ 5698182999Smav if (depth > 0) { 5699182999Smav for (j = 0; j < w->nconns; j++) { 5700182999Smav if (w->connsenable[j]) 5701182999Smav conns++; 5702162922Sariff } 5703162922Sariff } 5704182999Smav 5705182999Smav /* If this is not a first step - use input mixer. 5706182999Smav Pins have common input ctl so care must be taken. */ 5707182999Smav if (depth > 0 && ctlable && (conns == 1 || 5708182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5709182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5710182999Smav index, 1); 5711182999Smav if (ctl) { 5712182999Smav if (HDA_CTL_GIVE(ctl) & need) 5713182999Smav ctl->ossmask |= (1 << ossdev); 5714182999Smav else 5715182999Smav ctl->possmask |= (1 << ossdev); 5716182999Smav need &= ~HDA_CTL_GIVE(ctl); 5717182999Smav } 5718182999Smav } 5719182999Smav 5720182999Smav /* If widget has own ossdev - not traverse it. 5721182999Smav It will be traversed on it's own. */ 5722182999Smav if (w->ossdev >= 0 && depth > 0) 5723182999Smav return (need); 5724182999Smav 5725182999Smav /* We must not traverse pin */ 5726182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5727182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5728182999Smav depth > 0) 5729182999Smav return (need); 5730182999Smav 5731182999Smav /* record that this widget exports such signal, */ 5732182999Smav w->ossmask |= (1 << ossdev); 5733182999Smav 5734182999Smav /* If signals mixed, we can't assign controls farther. 5735182999Smav * Ignore this on depth zero. Caller must knows why. 5736182999Smav * Ignore this for static selectors if this input selected. 5737182999Smav */ 5738182999Smav if (conns > 1) 5739182999Smav ctlable = 0; 5740182999Smav 5741182999Smav if (ctlable) { 5742182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5743182999Smav if (ctl) { 5744182999Smav if (HDA_CTL_GIVE(ctl) & need) 5745182999Smav ctl->ossmask |= (1 << ossdev); 5746182999Smav else 5747182999Smav ctl->possmask |= (1 << ossdev); 5748182999Smav need &= ~HDA_CTL_GIVE(ctl); 5749182999Smav } 5750182999Smav } 5751182999Smav 5752182999Smav rneed = 0; 5753182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5754182999Smav wc = hdac_widget_get(devinfo, i); 5755182999Smav if (wc == NULL || wc->enable == 0) 5756162922Sariff continue; 5757182999Smav for (j = 0; j < wc->nconns; j++) { 5758182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5759182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5760182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5761182999Smav } 5762162922Sariff } 5763162922Sariff } 5764182999Smav rneed &= need; 5765182999Smav 5766182999Smav return (rneed); 5767162922Sariff} 5768162922Sariff 5769182999Smav/* 5770182999Smav * Find controls to control amplification for destination. 5771182999Smav */ 5772182999Smavstatic void 5773182999Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, 5774182999Smav int ossdev, int depth, int need) 5775162922Sariff{ 5776182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5777182999Smav struct hdac_widget *w, *wc; 5778182999Smav struct hdac_audio_ctl *ctl; 5779182999Smav int i, j, consumers; 5780182999Smav 5781162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5782182999Smav return; 5783162922Sariff 5784162922Sariff w = hdac_widget_get(devinfo, nid); 5785162922Sariff if (w == NULL || w->enable == 0) 5786182999Smav return; 5787182999Smav 5788182999Smav if (depth > 0) { 5789182999Smav /* If this node produce output for several consumers, 5790182999Smav we can't touch it. */ 5791182999Smav consumers = 0; 5792182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5793182999Smav wc = hdac_widget_get(devinfo, i); 5794182999Smav if (wc == NULL || wc->enable == 0) 5795182999Smav continue; 5796182999Smav for (j = 0; j < wc->nconns; j++) { 5797182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5798182999Smav consumers++; 5799182999Smav } 5800182999Smav } 5801182999Smav /* The only exception is if real HP redirection is configured 5802182999Smav and this is a duplication point. 5803182999Smav XXX: Actually exception is not completely correct. 5804182999Smav XXX: Duplication point check is not perfect. */ 5805182999Smav if ((consumers == 2 && (w->bindas < 0 || 5806182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5807182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5808182999Smav consumers > 2) 5809182999Smav return; 5810182999Smav 5811182999Smav /* Else use it's output mixer. */ 5812182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5813182999Smav HDA_CTL_OUT, -1, 1); 5814182999Smav if (ctl) { 5815182999Smav if (HDA_CTL_GIVE(ctl) & need) 5816182999Smav ctl->ossmask |= (1 << ossdev); 5817182999Smav else 5818182999Smav ctl->possmask |= (1 << ossdev); 5819182999Smav need &= ~HDA_CTL_GIVE(ctl); 5820182999Smav } 5821182999Smav } 5822182999Smav 5823182999Smav /* We must not traverse pin */ 5824182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5825182999Smav depth > 0) 5826182999Smav return; 5827182999Smav 5828162922Sariff for (i = 0; i < w->nconns; i++) { 5829182999Smav int tneed = need; 5830182999Smav if (w->connsenable[i] == 0) 5831162922Sariff continue; 5832182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5833182999Smav HDA_CTL_IN, i, 1); 5834182999Smav if (ctl) { 5835182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 5836182999Smav ctl->ossmask |= (1 << ossdev); 5837182999Smav else 5838182999Smav ctl->possmask |= (1 << ossdev); 5839182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 5840162922Sariff } 5841182999Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev, 5842182999Smav depth + 1, tneed); 5843162922Sariff } 5844162922Sariff} 5845162922Sariff 5846182999Smav/* 5847182999Smav * Assign OSS names to sound sources 5848182999Smav */ 5849182999Smavstatic void 5850182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 5851162922Sariff{ 5852182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5853182999Smav struct hdac_widget *w; 5854182999Smav int i, j; 5855182999Smav int type = -1, use, used = 0; 5856182999Smav static const int types[7][13] = { 5857182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5858182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 5859182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 5860182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 5861182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 5862182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 5863182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 5864182999Smav -1 }, /* digital */ 5865182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5866182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 5867182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 5868182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 5869182999Smav -1 } /* others */ 5870182999Smav }; 5871162922Sariff 5872182999Smav /* Surely known names */ 5873162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5874162922Sariff w = hdac_widget_get(devinfo, i); 5875162922Sariff if (w == NULL || w->enable == 0) 5876162922Sariff continue; 5877182999Smav if (w->bindas == -1) 5878182999Smav continue; 5879182999Smav use = -1; 5880182999Smav switch (w->type) { 5881182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5882182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5883182999Smav break; 5884182999Smav type = -1; 5885182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5886182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 5887182999Smav type = 0; 5888182999Smav break; 5889182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5890182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 5891182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 5892182999Smav break; 5893182999Smav type = 1; 5894182999Smav break; 5895182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 5896182999Smav type = 3; 5897182999Smav break; 5898182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5899182999Smav type = 4; 5900182999Smav break; 5901182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 5902182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 5903182999Smav type = 5; 5904182999Smav break; 5905182999Smav } 5906182999Smav if (type == -1) 5907182999Smav break; 5908182999Smav j = 0; 5909182999Smav while (types[type][j] >= 0 && 5910182999Smav (used & (1 << types[type][j])) != 0) { 5911182999Smav j++; 5912182999Smav } 5913182999Smav if (types[type][j] >= 0) 5914182999Smav use = types[type][j]; 5915182999Smav break; 5916182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5917182999Smav use = SOUND_MIXER_PCM; 5918182999Smav break; 5919182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 5920182999Smav use = SOUND_MIXER_SPEAKER; 5921182999Smav break; 5922182999Smav default: 5923182999Smav break; 5924182999Smav } 5925182999Smav if (use >= 0) { 5926182999Smav w->ossdev = use; 5927182999Smav used |= (1 << use); 5928182999Smav } 5929182999Smav } 5930182999Smav /* Semi-known names */ 5931182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5932182999Smav w = hdac_widget_get(devinfo, i); 5933182999Smav if (w == NULL || w->enable == 0) 5934182999Smav continue; 5935182999Smav if (w->ossdev >= 0) 5936182999Smav continue; 5937182999Smav if (w->bindas == -1) 5938182999Smav continue; 5939162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5940162922Sariff continue; 5941182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5942162922Sariff continue; 5943182999Smav type = -1; 5944182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5945182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 5946182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5947182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 5948182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 5949182999Smav type = 0; 5950182999Smav break; 5951182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5952182999Smav type = 2; 5953182999Smav break; 5954182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 5955182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 5956182999Smav type = 5; 5957182999Smav break; 5958182999Smav } 5959182999Smav if (type == -1) 5960182999Smav break; 5961182999Smav j = 0; 5962182999Smav while (types[type][j] >= 0 && 5963182999Smav (used & (1 << types[type][j])) != 0) { 5964182999Smav j++; 5965182999Smav } 5966182999Smav if (types[type][j] >= 0) { 5967182999Smav w->ossdev = types[type][j]; 5968182999Smav used |= (1 << types[type][j]); 5969182999Smav } 5970182999Smav } 5971182999Smav /* Others */ 5972182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5973182999Smav w = hdac_widget_get(devinfo, i); 5974182999Smav if (w == NULL || w->enable == 0) 5975162922Sariff continue; 5976182999Smav if (w->ossdev >= 0) 5977182999Smav continue; 5978182999Smav if (w->bindas == -1) 5979182999Smav continue; 5980182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5981182999Smav continue; 5982182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5983182999Smav continue; 5984182999Smav j = 0; 5985182999Smav while (types[6][j] >= 0 && 5986182999Smav (used & (1 << types[6][j])) != 0) { 5987182999Smav j++; 5988162922Sariff } 5989182999Smav if (types[6][j] >= 0) { 5990182999Smav w->ossdev = types[6][j]; 5991182999Smav used |= (1 << types[6][j]); 5992182999Smav } 5993162922Sariff } 5994162922Sariff} 5995162922Sariff 5996162922Sariffstatic void 5997162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5998162922Sariff{ 5999182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6000182999Smav int j, res; 6001162922Sariff 6002182999Smav /* Trace all associations in order of their numbers, */ 6003182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 6004182999Smav if (as[j].enable == 0) 6005182999Smav continue; 6006163057Sariff HDA_BOOTVERBOSE( 6007162922Sariff device_printf(devinfo->codec->sc->dev, 6008182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6009162922Sariff ); 6010182999Smav if (as[j].dir == HDA_CTL_OUT) { 6011182999Smavretry: 6012182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6013182999Smav if (res == 0 && as[j].hpredir >= 0 && 6014182999Smav as[j].fakeredir == 0) { 6015182999Smav /* If codec can't do analog HP redirection 6016182999Smav try to make it using one more DAC. */ 6017182999Smav as[j].fakeredir = 1; 6018182999Smav goto retry; 6019182999Smav } 6020182999Smav } else { 6021182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6022182999Smav } 6023182999Smav if (res) { 6024182999Smav HDA_BOOTVERBOSE( 6025182999Smav device_printf(devinfo->codec->sc->dev, 6026188510Smav "Association %d (%d) trace succeeded\n", 6027182999Smav j, as[j].index); 6028182999Smav ); 6029182999Smav } else { 6030182999Smav HDA_BOOTVERBOSE( 6031182999Smav device_printf(devinfo->codec->sc->dev, 6032182999Smav "Association %d (%d) trace failed\n", 6033182999Smav j, as[j].index); 6034182999Smav ); 6035182999Smav as[j].enable = 0; 6036182999Smav } 6037162922Sariff } 6038162922Sariff 6039182999Smav /* Trace mixer and beeper pseudo associations. */ 6040182999Smav hdac_audio_trace_as_extra(devinfo); 6041182999Smav} 6042162922Sariff 6043182999Smavstatic void 6044182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6045182999Smav{ 6046182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6047182999Smav struct hdac_audio_ctl *ctl; 6048182999Smav struct hdac_widget *w; 6049182999Smav int i; 6050162922Sariff 6051182999Smav /* Assign mixers to the tree. */ 6052162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6053162922Sariff w = hdac_widget_get(devinfo, i); 6054162922Sariff if (w == NULL || w->enable == 0) 6055162922Sariff continue; 6056182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6057182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6058182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6059182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6060182999Smav if (w->ossdev < 0) 6061182999Smav continue; 6062182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6063182999Smav w->ossdev, 1, 0, 1); 6064182999Smav } else if ((w->pflags & HDA_ADC_MONITOR) != 0) { 6065182999Smav if (w->ossdev < 0) 6066182999Smav continue; 6067182999Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6068182999Smav w->ossdev, 1, 0, 1)) { 6069182999Smav /* If we are unable to control input monitor 6070182999Smav as source - try to control it as destination. */ 6071182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6072182999Smav w->ossdev, 0, 1); 6073162922Sariff } 6074182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6075182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6076182999Smav SOUND_MIXER_RECLEV, 0, 1); 6077182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6078182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6079182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6080182999Smav SOUND_MIXER_VOLUME, 0, 1); 6081162922Sariff } 6082162922Sariff } 6083182999Smav /* Treat unrequired as possible. */ 6084182999Smav i = 0; 6085182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6086182999Smav if (ctl->ossmask == 0) 6087182999Smav ctl->ossmask = ctl->possmask; 6088182999Smav } 6089182999Smav} 6090162922Sariff 6091182999Smavstatic void 6092182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6093182999Smav{ 6094182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6095182999Smav struct hdac_widget *w; 6096182999Smav uint32_t pincap; 6097182999Smav int i; 6098182999Smav 6099182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6100182999Smav w = &devinfo->widget[i]; 6101182999Smav if (w == NULL) 6102162922Sariff continue; 6103182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6104162922Sariff continue; 6105182999Smav 6106182999Smav pincap = w->wclass.pin.cap; 6107182999Smav 6108182999Smav /* Disable everything. */ 6109182999Smav w->wclass.pin.ctrl &= ~( 6110182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6111182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6112182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6113182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6114182999Smav 6115182999Smav if (w->enable == 0 || 6116182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6117182999Smav /* Pin is unused so left it disabled. */ 6118182999Smav continue; 6119182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6120182999Smav /* Input pin, configure for input. */ 6121182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6122182999Smav w->wclass.pin.ctrl |= 6123182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6124182999Smav 6125182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6126182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6127182999Smav w->wclass.pin.ctrl |= 6128182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6129182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6130182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6131182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6132182999Smav w->wclass.pin.ctrl |= 6133182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6134182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6135182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6136182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6137182999Smav w->wclass.pin.ctrl |= 6138182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6139182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6140182999Smav } else { 6141182999Smav /* Output pin, configure for output. */ 6142182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6143182999Smav w->wclass.pin.ctrl |= 6144182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6145182999Smav 6146182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6147182999Smav (w->wclass.pin.config & 6148182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6149182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6150182999Smav w->wclass.pin.ctrl |= 6151182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6152182999Smav 6153182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6154182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6155182999Smav w->wclass.pin.ctrl |= 6156182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6157182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6158182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6159182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6160182999Smav w->wclass.pin.ctrl |= 6161182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6162182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6163182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6164182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6165182999Smav w->wclass.pin.ctrl |= 6166182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6167182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6168182999Smav } 6169162922Sariff } 6170162922Sariff} 6171162922Sariff 6172162922Sariffstatic void 6173187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6174187154Smav{ 6175187154Smav struct hdac_audio_ctl *ctl; 6176187154Smav int i, z; 6177187154Smav 6178187154Smav i = 0; 6179187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6180187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6181187154Smav /* Mute disabled and mixer controllable controls. 6182187154Smav * Last will be initialized by mixer_init(). 6183187154Smav * This expected to reduce click on startup. */ 6184187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6185187154Smav continue; 6186187154Smav } 6187187154Smav /* Init fixed controls to 0dB amplification. */ 6188187154Smav z = ctl->offset; 6189187154Smav if (z > ctl->step) 6190187154Smav z = ctl->step; 6191187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6192187154Smav } 6193187154Smav} 6194187154Smav 6195187154Smavstatic void 6196182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6197162922Sariff{ 6198162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6199162922Sariff struct hdac_widget *w; 6200164750Sariff nid_t cad; 6201182999Smav uint32_t gdata, gmask, gdir; 6202182999Smav int commitgpio, numgpio; 6203164750Sariff int i; 6204162922Sariff 6205162922Sariff cad = devinfo->codec->cad; 6206162922Sariff 6207182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6208182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6209182999Smav 0x7e7, 0), cad); 6210169277Sariff 6211187154Smav /* Commit controls. */ 6212187154Smav hdac_audio_ctl_commit(devinfo); 6213187154Smav 6214187154Smav /* Commit selectors, pins and EAPD. */ 6215187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6216187154Smav w = &devinfo->widget[i]; 6217187154Smav if (w == NULL) 6218187154Smav continue; 6219187154Smav if (w->selconn == -1) 6220187154Smav w->selconn = 0; 6221187154Smav if (w->nconns > 0) 6222187154Smav hdac_widget_connection_select(w, w->selconn); 6223187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6224187154Smav hdac_command(sc, 6225187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6226187154Smav w->wclass.pin.ctrl), cad); 6227187154Smav } 6228187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6229187154Smav uint32_t val; 6230187154Smav 6231187154Smav val = w->param.eapdbtl; 6232187154Smav if (devinfo->function.audio.quirks & 6233187154Smav HDA_QUIRK_EAPDINV) 6234187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6235187154Smav hdac_command(sc, 6236187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6237187154Smav val), cad); 6238187154Smav } 6239187154Smav } 6240187154Smav 6241187154Smav /* Commit GPIOs. */ 6242182999Smav gdata = 0; 6243182999Smav gmask = 0; 6244182999Smav gdir = 0; 6245182999Smav commitgpio = 0; 6246182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6247182999Smav devinfo->function.audio.gpio); 6248166796Sariff 6249182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6250182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6251182999Smav else { 6252182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6253182999Smav if (!(devinfo->function.audio.quirks & 6254182999Smav (1 << i))) 6255182999Smav continue; 6256182999Smav if (commitgpio == 0) { 6257182999Smav commitgpio = 1; 6258182999Smav HDA_BOOTVERBOSE( 6259182999Smav gdata = hdac_command(sc, 6260182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6261182999Smav devinfo->nid), cad); 6262182999Smav gmask = hdac_command(sc, 6263182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6264182999Smav devinfo->nid), cad); 6265182999Smav gdir = hdac_command(sc, 6266182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6267182999Smav devinfo->nid), cad); 6268182999Smav device_printf(sc->dev, 6269182999Smav "GPIO init: data=0x%08x " 6270182999Smav "mask=0x%08x dir=0x%08x\n", 6271182999Smav gdata, gmask, gdir); 6272182999Smav gdata = 0; 6273182999Smav gmask = 0; 6274182999Smav gdir = 0; 6275182999Smav ); 6276165039Sariff } 6277182999Smav gdata |= 1 << i; 6278182999Smav gmask |= 1 << i; 6279182999Smav gdir |= 1 << i; 6280165039Sariff } 6281182999Smav } 6282165039Sariff 6283182999Smav if (commitgpio != 0) { 6284182999Smav HDA_BOOTVERBOSE( 6285182999Smav device_printf(sc->dev, 6286182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6287182999Smav "dir=0x%08x\n", 6288182999Smav gdata, gmask, gdir); 6289182999Smav ); 6290182999Smav hdac_command(sc, 6291182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6292182999Smav gmask), cad); 6293182999Smav hdac_command(sc, 6294182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6295182999Smav gdir), cad); 6296182999Smav hdac_command(sc, 6297182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6298182999Smav gdata), cad); 6299162922Sariff } 6300162922Sariff} 6301162922Sariff 6302162922Sariffstatic void 6303182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6304182999Smav{ 6305182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6306182999Smav nid_t cad = devinfo->codec->cad; 6307182999Smav int i; 6308182999Smav 6309182999Smav hdac_command(sc, 6310182999Smav HDA_CMD_SET_POWER_STATE(cad, 6311182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6312182999Smav cad); 6313182999Smav DELAY(100); 6314182999Smav 6315182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6316182999Smav hdac_command(sc, 6317182999Smav HDA_CMD_SET_POWER_STATE(cad, 6318182999Smav i, HDA_CMD_POWER_STATE_D0), 6319182999Smav cad); 6320182999Smav } 6321182999Smav DELAY(1000); 6322182999Smav} 6323182999Smav 6324162922Sariffstatic int 6325182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6326162922Sariff{ 6327182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6328182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6329162922Sariff struct hdac_widget *w; 6330182999Smav uint32_t cap, fmtcap, pcmcap; 6331182999Smav int i, j, ret, max; 6332162922Sariff 6333162922Sariff ch->caps = hdac_caps; 6334162922Sariff ch->caps.fmtlist = ch->fmtlist; 6335162922Sariff ch->bit16 = 1; 6336162922Sariff ch->bit32 = 0; 6337162922Sariff ch->pcmrates[0] = 48000; 6338162922Sariff ch->pcmrates[1] = 0; 6339162922Sariff 6340162922Sariff ret = 0; 6341162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6342162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6343162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 6344162922Sariff 6345182999Smav for (i = 0; i < 16 && ret < max; i++) { 6346182999Smav /* Check as is correct */ 6347182999Smav if (ch->as < 0) 6348182999Smav break; 6349182999Smav /* Cound only present DACs */ 6350182999Smav if (as[ch->as].dacs[i] <= 0) 6351162922Sariff continue; 6352182999Smav /* Ignore duplicates */ 6353182999Smav for (j = 0; j < ret; j++) { 6354182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6355182999Smav break; 6356182999Smav } 6357182999Smav if (j < ret) 6358162922Sariff continue; 6359182999Smav 6360182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6361182999Smav if (w == NULL || w->enable == 0) 6362182999Smav continue; 6363182999Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6364182999Smav continue; 6365162922Sariff cap = w->param.supp_stream_formats; 6366182999Smav /*if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 6367162922Sariff }*/ 6368182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6369182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6370162922Sariff continue; 6371182999Smav /* Many codec does not declare AC3 support on SPDIF. 6372182999Smav I don't beleave that they doesn't support it! */ 6373182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6374182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6375164614Sariff if (ret == 0) { 6376182999Smav fmtcap = cap; 6377164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6378164614Sariff } else { 6379182999Smav fmtcap &= cap; 6380164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6381164614Sariff } 6382182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6383162922Sariff } 6384162922Sariff ch->io[ret] = -1; 6385162922Sariff 6386162922Sariff ch->supp_stream_formats = fmtcap; 6387162922Sariff ch->supp_pcm_size_rate = pcmcap; 6388162922Sariff 6389162922Sariff /* 6390162922Sariff * 8bit = 0 6391162922Sariff * 16bit = 1 6392162922Sariff * 20bit = 2 6393162922Sariff * 24bit = 3 6394162922Sariff * 32bit = 4 6395162922Sariff */ 6396162922Sariff if (ret > 0) { 6397162922Sariff i = 0; 6398182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6399182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6400182999Smav ch->bit16 = 1; 6401182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6402182999Smav ch->bit16 = 0; 6403182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6404182999Smav ch->bit32 = 4; 6405182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6406182999Smav ch->bit32 = 3; 6407182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6408182999Smav ch->bit32 = 2; 6409182999Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 6410182999Smav ch->fmtlist[i++] = AFMT_S16_LE; 6411182999Smav ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 6412182999Smav if (ch->bit32 > 0) { 6413182999Smav if (!(devinfo->function.audio.quirks & 6414182999Smav HDA_QUIRK_FORCESTEREO)) 6415182999Smav ch->fmtlist[i++] = AFMT_S32_LE; 6416182999Smav ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 6417182999Smav } 6418162922Sariff } 6419182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6420182999Smav ch->fmtlist[i++] = AFMT_AC3; 6421182999Smav } 6422162922Sariff ch->fmtlist[i] = 0; 6423162922Sariff i = 0; 6424182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6425162922Sariff ch->pcmrates[i++] = 8000; 6426182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6427162922Sariff ch->pcmrates[i++] = 11025; 6428182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6429162922Sariff ch->pcmrates[i++] = 16000; 6430182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6431162922Sariff ch->pcmrates[i++] = 22050; 6432182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6433162922Sariff ch->pcmrates[i++] = 32000; 6434182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6435162922Sariff ch->pcmrates[i++] = 44100; 6436182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6437162922Sariff ch->pcmrates[i++] = 48000; 6438182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6439162922Sariff ch->pcmrates[i++] = 88200; 6440182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6441162922Sariff ch->pcmrates[i++] = 96000; 6442182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6443162922Sariff ch->pcmrates[i++] = 176400; 6444182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6445162922Sariff ch->pcmrates[i++] = 192000; 6446182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6447162922Sariff ch->pcmrates[i] = 0; 6448162922Sariff if (i > 0) { 6449162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6450162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6451162922Sariff } 6452162922Sariff } 6453162922Sariff 6454162922Sariff return (ret); 6455162922Sariff} 6456162922Sariff 6457162922Sariffstatic void 6458185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6459185225Smav{ 6460185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6461185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6462185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6463185225Smav 6464185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6465185225Smav if (as[i].enable == 0) 6466185225Smav continue; 6467185225Smav if (as[i].dir == HDA_CTL_IN) { 6468185225Smav if (as[i].digital) 6469185225Smav drdev++; 6470185225Smav else 6471185225Smav ardev++; 6472185225Smav } else { 6473185225Smav if (as[i].digital) 6474185225Smav dpdev++; 6475185225Smav else 6476185225Smav apdev++; 6477185225Smav } 6478185225Smav } 6479185225Smav devinfo->function.audio.num_devs = 6480185225Smav max(ardev, apdev) + max(drdev, dpdev); 6481185225Smav devinfo->function.audio.devs = 6482185225Smav (struct hdac_pcm_devinfo *)malloc( 6483185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6484185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6485185225Smav if (devinfo->function.audio.devs == NULL) { 6486185225Smav device_printf(sc->dev, 6487185225Smav "Unable to allocate memory for devices\n"); 6488185225Smav return; 6489185225Smav } 6490185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6491185225Smav devinfo->function.audio.devs[i].index = i; 6492185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6493185225Smav devinfo->function.audio.devs[i].play = -1; 6494185225Smav devinfo->function.audio.devs[i].rec = -1; 6495185225Smav devinfo->function.audio.devs[i].digital = 2; 6496185225Smav } 6497185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6498185225Smav if (as[i].enable == 0) 6499185225Smav continue; 6500185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6501185225Smav if (devinfo->function.audio.devs[j].digital != 2 && 6502185225Smav devinfo->function.audio.devs[j].digital != 6503185225Smav as[i].digital) 6504185225Smav continue; 6505185225Smav if (as[i].dir == HDA_CTL_IN) { 6506185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6507185225Smav continue; 6508185225Smav devinfo->function.audio.devs[j].rec 6509185225Smav = as[i].chan; 6510185225Smav } else { 6511185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6512185225Smav continue; 6513185225Smav devinfo->function.audio.devs[j].play 6514185225Smav = as[i].chan; 6515185225Smav } 6516185225Smav sc->chans[as[i].chan].pdevinfo = 6517185225Smav &devinfo->function.audio.devs[j]; 6518185225Smav devinfo->function.audio.devs[j].digital = 6519185225Smav as[i].digital; 6520185225Smav break; 6521185225Smav } 6522185225Smav } 6523185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6524185225Smav struct hdac_pcm_devinfo *pdevinfo = 6525185225Smav &devinfo->function.audio.devs[i]; 6526185225Smav pdevinfo->dev = 6527185225Smav device_add_child(sc->dev, "pcm", -1); 6528185225Smav device_set_ivars(pdevinfo->dev, 6529185225Smav (void *)pdevinfo); 6530185225Smav } 6531185225Smav} 6532185225Smav 6533185225Smavstatic void 6534182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6535162922Sariff{ 6536182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6537162922Sariff struct hdac_audio_ctl *ctl; 6538162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6539182999Smav char buf[64]; 6540182999Smav int i, j, printed; 6541162922Sariff 6542162922Sariff if (flag == 0) { 6543182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6544162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6545182999Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN | 6546182999Smav SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6547162922Sariff } 6548162922Sariff 6549182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6550182999Smav if ((flag & (1 << j)) == 0) 6551162922Sariff continue; 6552182999Smav i = 0; 6553182999Smav printed = 0; 6554182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6555182999Smav if (ctl->enable == 0 || 6556182999Smav ctl->widget->enable == 0) 6557182999Smav continue; 6558182999Smav if (!((pdevinfo->play >= 0 && 6559182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6560182999Smav (pdevinfo->rec >= 0 && 6561182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6562182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6563182999Smav continue; 6564182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6565182999Smav continue; 6566182999Smav 6567182999Smav if (printed == 0) { 6568182999Smav device_printf(pdevinfo->dev, "\n"); 6569182999Smav if (banner != NULL) { 6570182999Smav device_printf(pdevinfo->dev, "%s", banner); 6571182999Smav } else { 6572182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6573182999Smav } 6574182999Smav printf(" (OSS: %s)\n", 6575182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6576182999Smav buf, sizeof(buf))); 6577182999Smav device_printf(pdevinfo->dev, " |\n"); 6578182999Smav printed = 1; 6579162922Sariff } 6580182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6581182999Smav ctl->widget->nid, 6582182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6583182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6584182999Smav printf(" %2d): ", ctl->index); 6585182999Smav else 6586182999Smav printf("): "); 6587182999Smav if (ctl->step > 0) { 6588182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6589182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6590182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6591182999Smav ctl->step + 1, 6592182999Smav ctl->mute?" + mute":""); 6593182999Smav } else 6594182999Smav printf("%s\n", ctl->mute?"mute":""); 6595162922Sariff } 6596162922Sariff } 6597162922Sariff} 6598162922Sariff 6599162922Sariffstatic void 6600182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6601162922Sariff{ 6602162922Sariff uint32_t cap; 6603162922Sariff 6604162922Sariff cap = fcap; 6605162922Sariff if (cap != 0) { 6606182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6607183097Smav device_printf(dev, " "); 6608162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6609162922Sariff printf(" AC3"); 6610162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6611162922Sariff printf(" FLOAT32"); 6612162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6613162922Sariff printf(" PCM"); 6614162922Sariff printf("\n"); 6615162922Sariff } 6616162922Sariff cap = pcmcap; 6617162922Sariff if (cap != 0) { 6618182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6619183097Smav device_printf(dev, " "); 6620162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6621162922Sariff printf(" 8"); 6622162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6623162922Sariff printf(" 16"); 6624162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6625162922Sariff printf(" 20"); 6626162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6627162922Sariff printf(" 24"); 6628162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6629162922Sariff printf(" 32"); 6630183097Smav printf(" bits,"); 6631162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6632162922Sariff printf(" 8"); 6633162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6634162922Sariff printf(" 11"); 6635162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6636162922Sariff printf(" 16"); 6637162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6638162922Sariff printf(" 22"); 6639162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6640162922Sariff printf(" 32"); 6641162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6642162922Sariff printf(" 44"); 6643162922Sariff printf(" 48"); 6644162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6645162922Sariff printf(" 88"); 6646162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6647162922Sariff printf(" 96"); 6648162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6649162922Sariff printf(" 176"); 6650162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6651162922Sariff printf(" 192"); 6652183097Smav printf(" KHz\n"); 6653162922Sariff } 6654162922Sariff} 6655162922Sariff 6656162922Sariffstatic void 6657162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6658162922Sariff{ 6659183097Smav uint32_t pincap; 6660162922Sariff 6661162922Sariff pincap = w->wclass.pin.cap; 6662162922Sariff 6663162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6664162922Sariff device_printf(sc->dev, " "); 6665162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6666162922Sariff printf(" ISC"); 6667162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6668162922Sariff printf(" TRQD"); 6669162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6670162922Sariff printf(" PDC"); 6671162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6672162922Sariff printf(" HP"); 6673162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6674162922Sariff printf(" OUT"); 6675162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6676162922Sariff printf(" IN"); 6677162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6678162922Sariff printf(" BAL"); 6679165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6680165069Sariff printf(" VREF["); 6681165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6682165069Sariff printf(" 50"); 6683165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6684165069Sariff printf(" 80"); 6685165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6686165069Sariff printf(" 100"); 6687165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6688165069Sariff printf(" GROUND"); 6689165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6690165069Sariff printf(" HIZ"); 6691165069Sariff printf(" ]"); 6692165069Sariff } 6693162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6694162922Sariff printf(" EAPD"); 6695162922Sariff printf("\n"); 6696162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6697162922Sariff w->wclass.pin.config); 6698162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6699162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6700162922Sariff printf(" HP"); 6701162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6702162922Sariff printf(" IN"); 6703162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6704162922Sariff printf(" OUT"); 6705182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6706182999Smav printf(" VREFs"); 6707162922Sariff printf("\n"); 6708162922Sariff} 6709162922Sariff 6710162922Sariffstatic void 6711182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6712182999Smav{ 6713182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6714182999Smav 6715183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6716182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6717182999Smav w->nid, conf, 6718182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6719182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6720182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6721182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6722182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6723182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6724182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6725182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6726182999Smav (w->enable == 0)?" [DISABLED]":""); 6727182999Smav} 6728182999Smav 6729182999Smavstatic void 6730182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6731182999Smav{ 6732182999Smav struct hdac_widget *w; 6733182999Smav int i; 6734182999Smav 6735182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6736182999Smav w = hdac_widget_get(devinfo, i); 6737182999Smav if (w == NULL) 6738182999Smav continue; 6739182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6740182999Smav continue; 6741182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6742182999Smav } 6743182999Smav} 6744182999Smav 6745182999Smavstatic void 6746162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6747162922Sariff{ 6748163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6749162922Sariff device_printf(sc->dev, " " 6750162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6751162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6752162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6753162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6754162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6755162922Sariff} 6756162922Sariff 6757162922Sariffstatic void 6758162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6759162922Sariff{ 6760162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6761182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6762162922Sariff struct hdac_widget *w, *cw; 6763182999Smav char buf[64]; 6764162922Sariff int i, j; 6765162922Sariff 6766162922Sariff device_printf(sc->dev, "\n"); 6767162922Sariff device_printf(sc->dev, "Default Parameter\n"); 6768162922Sariff device_printf(sc->dev, "-----------------\n"); 6769182999Smav hdac_dump_audio_formats(sc->dev, 6770162922Sariff devinfo->function.audio.supp_stream_formats, 6771162922Sariff devinfo->function.audio.supp_pcm_size_rate); 6772162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 6773162922Sariff devinfo->function.audio.inamp_cap); 6774162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 6775162922Sariff devinfo->function.audio.outamp_cap); 6776162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6777162922Sariff w = hdac_widget_get(devinfo, i); 6778162922Sariff if (w == NULL) { 6779162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 6780162922Sariff continue; 6781162922Sariff } 6782162922Sariff device_printf(sc->dev, "\n"); 6783183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 6784162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 6785183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 6786183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 6787162922Sariff w->param.widget_cap); 6788183097Smav if (w->param.widget_cap & 0x0ee1) { 6789183097Smav device_printf(sc->dev, " "); 6790183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 6791183097Smav printf(" LRSWAP"); 6792183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 6793183097Smav printf(" PWR"); 6794183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6795183097Smav printf(" DIGITAL"); 6796183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 6797183097Smav printf(" UNSOL"); 6798183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 6799183097Smav printf(" PROC"); 6800183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 6801183097Smav printf(" STRIPE"); 6802183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6803183097Smav printf(" STEREO"); 6804183097Smav printf("\n"); 6805183097Smav } 6806183097Smav if (w->bindas != -1) { 6807183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 6808183097Smav w->bindas, w->bindseqmask); 6809183097Smav } 6810183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 6811183097Smav device_printf(sc->dev, " OSS: %s", 6812183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 6813183097Smav if (w->ossdev >= 0) 6814183097Smav printf(" (%s)", ossname[w->ossdev]); 6815183097Smav printf("\n"); 6816183097Smav } 6817162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6818162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6819182999Smav hdac_dump_audio_formats(sc->dev, 6820162922Sariff w->param.supp_stream_formats, 6821162922Sariff w->param.supp_pcm_size_rate); 6822162922Sariff } else if (w->type == 6823162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6824162922Sariff hdac_dump_pin(sc, w); 6825162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 6826162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 6827162922Sariff w->param.eapdbtl); 6828163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 6829163057Sariff w->param.outamp_cap != 0) 6830162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 6831163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 6832163057Sariff w->param.inamp_cap != 0) 6833162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 6834183097Smav if (w->nconns > 0) { 6835183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 6836182999Smav device_printf(sc->dev, " |\n"); 6837183097Smav } 6838162922Sariff for (j = 0; j < w->nconns; j++) { 6839162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 6840182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 6841182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 6842162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 6843162922Sariff if (cw == NULL) 6844162922Sariff printf(" [UNKNOWN]"); 6845162922Sariff else if (cw->enable == 0) 6846162922Sariff printf(" [DISABLED]"); 6847162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 6848162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 6849162922Sariff printf(" (selected)"); 6850162922Sariff printf("\n"); 6851162922Sariff } 6852162922Sariff } 6853162922Sariff 6854162922Sariff} 6855162922Sariff 6856182999Smavstatic void 6857182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 6858163057Sariff{ 6859182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6860163057Sariff struct hdac_widget *w, *cw; 6861182999Smav char buf[64]; 6862182999Smav int i, printed = 0; 6863163057Sariff 6864163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 6865182999Smav return; 6866163057Sariff 6867163057Sariff w = hdac_widget_get(devinfo, nid); 6868182999Smav if (w == NULL || w->enable == 0) 6869182999Smav return; 6870163057Sariff 6871182999Smav if (depth == 0) 6872182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 6873182999Smav else 6874182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 6875182999Smav printf("nid=%d [%s]", w->nid, w->name); 6876163057Sariff 6877182999Smav if (depth > 0) { 6878182999Smav if (w->ossmask == 0) { 6879182999Smav printf("\n"); 6880182999Smav return; 6881163057Sariff } 6882182999Smav printf(" [src: %s]", 6883182999Smav hdac_audio_ctl_ossmixer_mask2allname( 6884182999Smav w->ossmask, buf, sizeof(buf))); 6885182999Smav if (w->ossdev >= 0) { 6886182999Smav printf("\n"); 6887182999Smav return; 6888182999Smav } 6889163057Sariff } 6890182999Smav printf("\n"); 6891182999Smav 6892182999Smav for (i = 0; i < w->nconns; i++) { 6893182999Smav if (w->connsenable[i] == 0) 6894182999Smav continue; 6895182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 6896182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 6897182999Smav continue; 6898182999Smav if (printed == 0) { 6899182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 6900182999Smav printed = 1; 6901182999Smav } 6902182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 6903182999Smav } 6904163057Sariff 6905163057Sariff} 6906163057Sariff 6907162922Sariffstatic void 6908182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 6909162922Sariff{ 6910182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6911182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6912163057Sariff struct hdac_widget *w; 6913163057Sariff int i, printed = 0; 6914163057Sariff 6915182999Smav if (pdevinfo->play < 0) 6916182999Smav return; 6917182999Smav 6918163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6919163057Sariff w = hdac_widget_get(devinfo, i); 6920163057Sariff if (w == NULL || w->enable == 0) 6921163057Sariff continue; 6922182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6923163057Sariff continue; 6924182999Smav if (w->bindas != sc->chans[pdevinfo->play].as) 6925182999Smav continue; 6926163057Sariff if (printed == 0) { 6927163057Sariff printed = 1; 6928182999Smav device_printf(pdevinfo->dev, "\n"); 6929182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6930163057Sariff } 6931182999Smav device_printf(pdevinfo->dev, "\n"); 6932182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6933163057Sariff } 6934162922Sariff} 6935162922Sariff 6936162922Sariffstatic void 6937182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 6938162922Sariff{ 6939182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6940162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6941182999Smav struct hdac_widget *w; 6942182999Smav int i; 6943162922Sariff int printed = 0; 6944162922Sariff 6945182999Smav if (pdevinfo->rec < 0) 6946182999Smav return; 6947182999Smav 6948162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6949162922Sariff w = hdac_widget_get(devinfo, i); 6950162922Sariff if (w == NULL || w->enable == 0) 6951162922Sariff continue; 6952182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 6953162922Sariff continue; 6954182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 6955182999Smav continue; 6956162922Sariff if (printed == 0) { 6957162922Sariff printed = 1; 6958182999Smav device_printf(pdevinfo->dev, "\n"); 6959182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6960162922Sariff } 6961182999Smav device_printf(pdevinfo->dev, "\n"); 6962182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6963182999Smav } 6964182999Smav} 6965182999Smav 6966182999Smavstatic void 6967182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 6968182999Smav{ 6969182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6970182999Smav struct hdac_widget *w; 6971182999Smav int i; 6972182999Smav int printed = 0; 6973182999Smav 6974182999Smav if (pdevinfo->index != 0) 6975182999Smav return; 6976182999Smav 6977182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6978182999Smav w = hdac_widget_get(devinfo, i); 6979182999Smav if (w == NULL || w->enable == 0) 6980182999Smav continue; 6981182999Smav if ((w->pflags & HDA_ADC_MONITOR) == 0) 6982182999Smav continue; 6983182999Smav if (printed == 0) { 6984182999Smav printed = 1; 6985182999Smav device_printf(pdevinfo->dev, "\n"); 6986182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 6987162922Sariff } 6988182999Smav device_printf(pdevinfo->dev, "\n"); 6989182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6990162922Sariff } 6991162922Sariff} 6992162922Sariff 6993162922Sariffstatic void 6994182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 6995162922Sariff{ 6996182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 6997162922Sariff nid_t *nids; 6998182999Smav int i; 6999162922Sariff 7000182999Smav if (pdevinfo->play >= 0) { 7001182999Smav i = pdevinfo->play; 7002182999Smav device_printf(pdevinfo->dev, "\n"); 7003182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7004182999Smav device_printf(pdevinfo->dev, "\n"); 7005182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7006182999Smav sc->chans[i].supp_pcm_size_rate); 7007182999Smav device_printf(pdevinfo->dev, " DAC:"); 7008182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7009162922Sariff printf(" %d", *nids); 7010162922Sariff printf("\n"); 7011162922Sariff } 7012182999Smav if (pdevinfo->rec >= 0) { 7013182999Smav i = pdevinfo->rec; 7014182999Smav device_printf(pdevinfo->dev, "\n"); 7015182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7016182999Smav device_printf(pdevinfo->dev, "\n"); 7017182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7018182999Smav sc->chans[i].supp_pcm_size_rate); 7019182999Smav device_printf(pdevinfo->dev, " ADC:"); 7020182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7021162922Sariff printf(" %d", *nids); 7022162922Sariff printf("\n"); 7023162922Sariff } 7024162922Sariff} 7025162922Sariff 7026162922Sariffstatic void 7027163057Sariffhdac_release_resources(struct hdac_softc *sc) 7028163057Sariff{ 7029182999Smav int i, j; 7030163057Sariff 7031163057Sariff if (sc == NULL) 7032163057Sariff return; 7033163057Sariff 7034163057Sariff hdac_lock(sc); 7035169277Sariff sc->polling = 0; 7036169277Sariff sc->poll_ival = 0; 7037170721Sariff callout_stop(&sc->poll_hda); 7038169277Sariff callout_stop(&sc->poll_hdac); 7039169277Sariff callout_stop(&sc->poll_jack); 7040182999Smav hdac_reset(sc, 0); 7041163057Sariff hdac_unlock(sc); 7042171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7043170721Sariff callout_drain(&sc->poll_hda); 7044169277Sariff callout_drain(&sc->poll_hdac); 7045169277Sariff callout_drain(&sc->poll_jack); 7046163057Sariff 7047169277Sariff hdac_irq_free(sc); 7048169277Sariff 7049182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7050182999Smav if (sc->codecs[i] == NULL) 7051163057Sariff continue; 7052182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7053182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7054182999Smav if (sc->codecs[i]->fgs[j].node_type == 7055182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7056182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7057182999Smav M_HDAC); 7058182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7059182999Smav M_HDAC); 7060182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7061182999Smav M_HDAC); 7062182999Smav } 7063182999Smav } 7064182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7065182999Smav free(sc->codecs[i], M_HDAC); 7066163057Sariff sc->codecs[i] = NULL; 7067163057Sariff } 7068163057Sariff 7069169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7070169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7071169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7072182999Smav for (i = 0; i < sc->num_chans; i++) { 7073182999Smav if (sc->chans[i].blkcnt > 0) 7074182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7075182999Smav } 7076182999Smav free(sc->chans, M_HDAC); 7077167702Sariff if (sc->chan_dmat != NULL) { 7078167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7079167702Sariff sc->chan_dmat = NULL; 7080167702Sariff } 7081163057Sariff hdac_mem_free(sc); 7082169277Sariff snd_mtxfree(sc->lock); 7083163057Sariff} 7084163057Sariff 7085163057Sariff/* This function surely going to make its way into upper level someday. */ 7086163057Sariffstatic void 7087163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7088163057Sariff{ 7089163057Sariff const char *res = NULL; 7090163057Sariff int i = 0, j, k, len, inv; 7091163057Sariff 7092163057Sariff if (on != NULL) 7093163057Sariff *on = 0; 7094163057Sariff if (off != NULL) 7095163057Sariff *off = 0; 7096163057Sariff if (sc == NULL) 7097163057Sariff return; 7098163057Sariff if (resource_string_value(device_get_name(sc->dev), 7099163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7100163057Sariff return; 7101163057Sariff if (!(res != NULL && strlen(res) > 0)) 7102163057Sariff return; 7103163057Sariff HDA_BOOTVERBOSE( 7104182999Smav device_printf(sc->dev, "HDA Config:"); 7105163057Sariff ); 7106163057Sariff for (;;) { 7107163057Sariff while (res[i] != '\0' && 7108163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7109163057Sariff i++; 7110163057Sariff if (res[i] == '\0') { 7111163057Sariff HDA_BOOTVERBOSE( 7112163057Sariff printf("\n"); 7113163057Sariff ); 7114163057Sariff return; 7115163057Sariff } 7116163057Sariff j = i; 7117163057Sariff while (res[j] != '\0' && 7118163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7119163057Sariff j++; 7120163057Sariff len = j - i; 7121163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7122163057Sariff inv = 2; 7123163057Sariff else 7124163057Sariff inv = 0; 7125163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7126163057Sariff if (strncmp(res + i + inv, 7127163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7128163057Sariff continue; 7129163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7130187944Smav continue; 7131163057Sariff HDA_BOOTVERBOSE( 7132163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7133163057Sariff hdac_quirks_tab[k].key); 7134163057Sariff ); 7135163057Sariff if (inv == 0 && on != NULL) 7136163057Sariff *on |= hdac_quirks_tab[k].value; 7137163057Sariff else if (inv != 0 && off != NULL) 7138163057Sariff *off |= hdac_quirks_tab[k].value; 7139163057Sariff break; 7140163057Sariff } 7141163057Sariff i = j; 7142163057Sariff } 7143163057Sariff} 7144163057Sariff 7145164614Sariff#ifdef SND_DYNSYSCTL 7146164614Sariffstatic int 7147164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7148164614Sariff{ 7149164614Sariff struct hdac_softc *sc; 7150164614Sariff device_t dev; 7151164614Sariff uint32_t ctl; 7152164614Sariff int err, val; 7153164614Sariff 7154164614Sariff dev = oidp->oid_arg1; 7155182999Smav sc = device_get_softc(dev); 7156182999Smav if (sc == NULL) 7157164614Sariff return (EINVAL); 7158164614Sariff hdac_lock(sc); 7159164614Sariff val = sc->polling; 7160164614Sariff hdac_unlock(sc); 7161170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7162164614Sariff 7163169277Sariff if (err != 0 || req->newptr == NULL) 7164164614Sariff return (err); 7165164614Sariff if (val < 0 || val > 1) 7166164614Sariff return (EINVAL); 7167164614Sariff 7168164614Sariff hdac_lock(sc); 7169164614Sariff if (val != sc->polling) { 7170182999Smav if (val == 0) { 7171182999Smav callout_stop(&sc->poll_hda); 7172164614Sariff callout_stop(&sc->poll_hdac); 7173169277Sariff hdac_unlock(sc); 7174182999Smav callout_drain(&sc->poll_hda); 7175169277Sariff callout_drain(&sc->poll_hdac); 7176169277Sariff hdac_lock(sc); 7177164614Sariff sc->polling = 0; 7178182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7179182999Smav ctl |= HDAC_INTCTL_GIE; 7180182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7181164614Sariff } else { 7182182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7183182999Smav ctl &= ~HDAC_INTCTL_GIE; 7184182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7185171141Sariff hdac_unlock(sc); 7186171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7187171141Sariff hdac_lock(sc); 7188164614Sariff sc->polling = 1; 7189182999Smav hdac_poll_reinit(sc); 7190182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7191164614Sariff } 7192164614Sariff } 7193164614Sariff hdac_unlock(sc); 7194164614Sariff 7195164614Sariff return (err); 7196164614Sariff} 7197169277Sariff 7198169277Sariffstatic int 7199169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7200169277Sariff{ 7201169277Sariff struct hdac_softc *sc; 7202169277Sariff device_t dev; 7203169277Sariff int err, val; 7204169277Sariff 7205169277Sariff dev = oidp->oid_arg1; 7206182999Smav sc = device_get_softc(dev); 7207182999Smav if (sc == NULL) 7208169277Sariff return (EINVAL); 7209169277Sariff hdac_lock(sc); 7210169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7211169277Sariff hdac_unlock(sc); 7212170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7213169277Sariff 7214169277Sariff if (err != 0 || req->newptr == NULL) 7215169277Sariff return (err); 7216169277Sariff 7217169277Sariff if (val < 1) 7218169277Sariff val = 1; 7219169277Sariff if (val > 5000) 7220169277Sariff val = 5000; 7221169277Sariff val = ((uint64_t)val * hz) / 1000; 7222169277Sariff if (val < 1) 7223169277Sariff val = 1; 7224169277Sariff if (val > (hz * 5)) 7225169277Sariff val = hz * 5; 7226169277Sariff 7227169277Sariff hdac_lock(sc); 7228169277Sariff sc->poll_ival = val; 7229169277Sariff hdac_unlock(sc); 7230169277Sariff 7231169277Sariff return (err); 7232169277Sariff} 7233169277Sariff 7234169277Sariffstatic int 7235171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7236169277Sariff{ 7237169277Sariff struct hdac_softc *sc; 7238182999Smav struct hdac_codec *codec; 7239169277Sariff struct hdac_devinfo *devinfo; 7240169277Sariff struct hdac_widget *w; 7241169277Sariff device_t dev; 7242182999Smav uint32_t res, pincap, delay; 7243182999Smav int codec_index, fg_index; 7244169277Sariff int i, err, val; 7245169277Sariff nid_t cad; 7246169277Sariff 7247169277Sariff dev = oidp->oid_arg1; 7248182999Smav sc = device_get_softc(dev); 7249182999Smav if (sc == NULL) 7250169277Sariff return (EINVAL); 7251169277Sariff val = 0; 7252170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7253169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7254169277Sariff return (err); 7255182999Smav 7256182999Smav /* XXX: Temporary. For debugging. */ 7257182999Smav if (val == 100) { 7258182999Smav hdac_suspend(dev); 7259182999Smav return (0); 7260182999Smav } else if (val == 101) { 7261182999Smav hdac_resume(dev); 7262182999Smav return (0); 7263182999Smav } 7264182999Smav 7265169277Sariff hdac_lock(sc); 7266182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7267182999Smav codec = sc->codecs[codec_index]; 7268182999Smav if (codec == NULL) 7269169277Sariff continue; 7270182999Smav cad = codec->cad; 7271182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7272182999Smav devinfo = &codec->fgs[fg_index]; 7273182999Smav if (devinfo->node_type != 7274182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7275182999Smav continue; 7276182999Smav 7277182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7278182999Smav codec_index, devinfo->nid); 7279182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7280182999Smav w = hdac_widget_get(devinfo, i); 7281182999Smav if (w == NULL || w->type != 7282182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7283182999Smav continue; 7284182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7285182999Smav pincap = w->wclass.pin.cap; 7286182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7287182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7288182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7289182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7290182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7291182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7292182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7293182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7294182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7295182999Smav delay = 0; 7296182999Smav hdac_command(sc, 7297182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7298182999Smav do { 7299182999Smav res = hdac_command(sc, 7300182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7301182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7302182999Smav break; 7303182999Smav DELAY(10); 7304182999Smav } while (++delay < 10000); 7305182999Smav } else { 7306182999Smav delay = 0; 7307182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7308182999Smav w->nid), cad); 7309182999Smav } 7310182999Smav printf(" Sense: 0x%08x", res); 7311182999Smav if (delay > 0) 7312182999Smav printf(" delay %dus", delay * 10); 7313182999Smav } 7314182999Smav printf("\n"); 7315182999Smav } 7316182999Smav device_printf(dev, 7317182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7318182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7319182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7320182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7321182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7322182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7323182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7324182999Smav device_printf(dev, " GPI:"); 7325171141Sariff res = hdac_command(sc, 7326182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7327182999Smav printf(" data=0x%08x", res); 7328182999Smav res = hdac_command(sc, 7329182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7330182999Smav cad); 7331182999Smav printf(" wake=0x%08x", res); 7332182999Smav res = hdac_command(sc, 7333182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7334182999Smav cad); 7335182999Smav printf(" unsol=0x%08x", res); 7336182999Smav res = hdac_command(sc, 7337182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7338182999Smav printf(" sticky=0x%08x\n", res); 7339182999Smav } 7340182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7341182999Smav device_printf(dev, " GPO:"); 7342182999Smav res = hdac_command(sc, 7343182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7344182999Smav printf(" data=0x%08x\n", res); 7345182999Smav } 7346182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7347182999Smav device_printf(dev, "GPIO:"); 7348182999Smav res = hdac_command(sc, 7349182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7350182999Smav printf(" data=0x%08x", res); 7351182999Smav res = hdac_command(sc, 7352182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7353182999Smav printf(" enable=0x%08x", res); 7354182999Smav res = hdac_command(sc, 7355182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7356182999Smav printf(" direction=0x%08x\n", res); 7357182999Smav res = hdac_command(sc, 7358182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7359182999Smav device_printf(dev, " wake=0x%08x", res); 7360182999Smav res = hdac_command(sc, 7361182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7362182999Smav cad); 7363182999Smav printf(" unsol=0x%08x", res); 7364182999Smav res = hdac_command(sc, 7365182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7366182999Smav printf(" sticky=0x%08x\n", res); 7367182999Smav } 7368171141Sariff } 7369169277Sariff } 7370169277Sariff hdac_unlock(sc); 7371169277Sariff return (0); 7372169277Sariff} 7373164614Sariff#endif 7374164614Sariff 7375163057Sariffstatic void 7376162922Sariffhdac_attach2(void *arg) 7377162922Sariff{ 7378182999Smav struct hdac_codec *codec; 7379162922Sariff struct hdac_softc *sc; 7380162922Sariff struct hdac_audio_ctl *ctl; 7381163057Sariff uint32_t quirks_on, quirks_off; 7382182999Smav int codec_index, fg_index; 7383185225Smav int i, dmaalloc = 0; 7384182999Smav struct hdac_devinfo *devinfo; 7385162922Sariff 7386162922Sariff sc = (struct hdac_softc *)arg; 7387162922Sariff 7388163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7389162922Sariff 7390183097Smav HDA_BOOTHVERBOSE( 7391182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7392163057Sariff quirks_on, quirks_off); 7393163057Sariff ); 7394163057Sariff 7395162922Sariff hdac_lock(sc); 7396162922Sariff 7397162922Sariff /* Remove ourselves from the config hooks */ 7398162922Sariff if (sc->intrhook.ich_func != NULL) { 7399162922Sariff config_intrhook_disestablish(&sc->intrhook); 7400162922Sariff sc->intrhook.ich_func = NULL; 7401162922Sariff } 7402162922Sariff 7403162922Sariff /* Start the corb and rirb engines */ 7404183097Smav HDA_BOOTHVERBOSE( 7405182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7406162922Sariff ); 7407162922Sariff hdac_corb_start(sc); 7408183097Smav HDA_BOOTHVERBOSE( 7409182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7410162922Sariff ); 7411162922Sariff hdac_rirb_start(sc); 7412162922Sariff 7413183097Smav HDA_BOOTHVERBOSE( 7414162922Sariff device_printf(sc->dev, 7415182999Smav "Enabling controller interrupt...\n"); 7416162922Sariff ); 7417182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7418182999Smav HDAC_GCTL_UNSOL); 7419182999Smav if (sc->polling == 0) { 7420164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7421164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7422182999Smav } else { 7423182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7424182999Smav } 7425162922Sariff DELAY(1000); 7426162922Sariff 7427183097Smav HDA_BOOTHVERBOSE( 7428172811Sariff device_printf(sc->dev, 7429182999Smav "Scanning HDA codecs ...\n"); 7430162922Sariff ); 7431182999Smav hdac_scan_codecs(sc); 7432182999Smav 7433182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7434182999Smav codec = sc->codecs[codec_index]; 7435182999Smav if (codec == NULL) 7436182999Smav continue; 7437182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7438182999Smav devinfo = &codec->fgs[fg_index]; 7439183019Smav HDA_BOOTVERBOSE( 7440183019Smav device_printf(sc->dev, "\n"); 7441183097Smav device_printf(sc->dev, 7442183097Smav "Processing %s FG cad=%d nid=%d...\n", 7443183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7444183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7445183097Smav "unknown", 7446183097Smav devinfo->codec->cad, devinfo->nid); 7447183019Smav ); 7448182999Smav if (devinfo->node_type != 7449182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7450183097Smav HDA_BOOTHVERBOSE( 7451182999Smav device_printf(sc->dev, 7452183097Smav "Powering down...\n"); 7453182999Smav ); 7454182999Smav hdac_command(sc, 7455182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7456182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7457182999Smav codec->cad); 7458182999Smav continue; 7459182999Smav } 7460162922Sariff 7461183097Smav HDA_BOOTHVERBOSE( 7462183097Smav device_printf(sc->dev, "Powering up...\n"); 7463182999Smav ); 7464182999Smav hdac_powerup(devinfo); 7465183097Smav HDA_BOOTHVERBOSE( 7466182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7467182999Smav ); 7468182999Smav hdac_audio_parse(devinfo); 7469183097Smav HDA_BOOTHVERBOSE( 7470182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7471182999Smav ); 7472182999Smav hdac_audio_ctl_parse(devinfo); 7473183097Smav HDA_BOOTHVERBOSE( 7474182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7475182999Smav ); 7476182999Smav hdac_vendor_patch_parse(devinfo); 7477182999Smav devinfo->function.audio.quirks |= quirks_on; 7478182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7479162922Sariff 7480183097Smav HDA_BOOTHVERBOSE( 7481182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7482182999Smav ); 7483182999Smav hdac_audio_disable_nonaudio(devinfo); 7484183097Smav HDA_BOOTHVERBOSE( 7485182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7486182999Smav ); 7487182999Smav hdac_audio_disable_useless(devinfo); 7488182999Smav HDA_BOOTVERBOSE( 7489182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7490182999Smav hdac_dump_pin_configs(devinfo); 7491183097Smav ); 7492183097Smav HDA_BOOTHVERBOSE( 7493182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7494182999Smav ); 7495182999Smav hdac_audio_as_parse(devinfo); 7496183097Smav HDA_BOOTHVERBOSE( 7497182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7498182999Smav ); 7499182999Smav hdac_audio_build_tree(devinfo); 7500183097Smav HDA_BOOTHVERBOSE( 7501182999Smav device_printf(sc->dev, "Disabling unassociated " 7502182999Smav "widgets...\n"); 7503182999Smav ); 7504182999Smav hdac_audio_disable_unas(devinfo); 7505183097Smav HDA_BOOTHVERBOSE( 7506182999Smav device_printf(sc->dev, "Disabling nonselected " 7507182999Smav "inputs...\n"); 7508182999Smav ); 7509182999Smav hdac_audio_disable_notselected(devinfo); 7510183097Smav HDA_BOOTHVERBOSE( 7511182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7512182999Smav ); 7513182999Smav hdac_audio_disable_useless(devinfo); 7514183097Smav HDA_BOOTHVERBOSE( 7515182999Smav device_printf(sc->dev, "Disabling " 7516182999Smav "crossassociatement connections...\n"); 7517182999Smav ); 7518182999Smav hdac_audio_disable_crossas(devinfo); 7519183097Smav HDA_BOOTHVERBOSE( 7520182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7521182999Smav ); 7522182999Smav hdac_audio_disable_useless(devinfo); 7523183097Smav HDA_BOOTHVERBOSE( 7524182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7525182999Smav ); 7526182999Smav hdac_audio_bind_as(devinfo); 7527183097Smav HDA_BOOTHVERBOSE( 7528182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7529182999Smav ); 7530182999Smav hdac_audio_assign_names(devinfo); 7531183097Smav HDA_BOOTHVERBOSE( 7532182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7533182999Smav ); 7534182999Smav hdac_audio_assign_mixers(devinfo); 7535183097Smav HDA_BOOTHVERBOSE( 7536182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7537182999Smav ); 7538182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7539183097Smav HDA_BOOTHVERBOSE( 7540182999Smav device_printf(sc->dev, "AFG commit...\n"); 7541182999Smav ); 7542182999Smav hdac_audio_commit(devinfo); 7543183097Smav HDA_BOOTHVERBOSE( 7544182999Smav device_printf(sc->dev, "HP switch init...\n"); 7545182999Smav ); 7546182999Smav hdac_hp_switch_init(devinfo); 7547182999Smav 7548182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7549182999Smav dmaalloc == 0) { 7550182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7551182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7552182999Smav HDA_BOOTVERBOSE( 7553182999Smav device_printf(sc->dev, "Failed to " 7554182999Smav "allocate DMA pos buffer " 7555182999Smav "(non-fatal)\n"); 7556182999Smav ); 7557182999Smav } else 7558182999Smav dmaalloc = 1; 7559182999Smav } 7560182999Smav 7561185225Smav HDA_BOOTHVERBOSE( 7562185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7563185225Smav ); 7564185225Smav hdac_create_pcms(devinfo); 7565182999Smav 7566182999Smav HDA_BOOTVERBOSE( 7567182999Smav if (devinfo->function.audio.quirks != 0) { 7568183097Smav device_printf(sc->dev, "FG config/quirks:"); 7569182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7570182999Smav if ((devinfo->function.audio.quirks & 7571182999Smav hdac_quirks_tab[i].value) == 7572182999Smav hdac_quirks_tab[i].value) 7573182999Smav printf(" %s", hdac_quirks_tab[i].key); 7574182999Smav } 7575182999Smav printf("\n"); 7576182999Smav } 7577182999Smav 7578182999Smav device_printf(sc->dev, "\n"); 7579182999Smav device_printf(sc->dev, "+-------------------+\n"); 7580182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7581182999Smav device_printf(sc->dev, "+-------------------+\n"); 7582182999Smav hdac_dump_nodes(devinfo); 7583183097Smav ); 7584182999Smav 7585183097Smav HDA_BOOTHVERBOSE( 7586182999Smav device_printf(sc->dev, "\n"); 7587182999Smav device_printf(sc->dev, "+------------------------+\n"); 7588182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7589182999Smav device_printf(sc->dev, "+------------------------+\n"); 7590182999Smav device_printf(sc->dev, "\n"); 7591182999Smav i = 0; 7592182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7593182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7594182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7595182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7596182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7597182999Smav ctl->index); 7598182999Smav if (ctl->childwidget != NULL) 7599182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7600182999Smav else 7601182999Smav printf(" "); 7602182999Smav printf(" ossmask=0x%08x\n", 7603182999Smav ctl->ossmask); 7604182999Smav device_printf(sc->dev, 7605182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7606182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7607182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7608182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7609182999Smav } 7610182999Smav ); 7611182999Smav } 7612162922Sariff } 7613182999Smav hdac_unlock(sc); 7614162922Sariff 7615163057Sariff HDA_BOOTVERBOSE( 7616182999Smav device_printf(sc->dev, "\n"); 7617162922Sariff ); 7618182999Smav 7619182999Smav bus_generic_attach(sc->dev); 7620182999Smav 7621182999Smav#ifdef SND_DYNSYSCTL 7622182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7623182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7624182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7625182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7626182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7627182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7628182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7629182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7630182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7631182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7632182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7633182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7634182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7635182999Smav#endif 7636182999Smav} 7637182999Smav 7638182999Smav/**************************************************************************** 7639182999Smav * int hdac_suspend(device_t) 7640182999Smav * 7641182999Smav * Suspend and power down HDA bus and codecs. 7642182999Smav ****************************************************************************/ 7643182999Smavstatic int 7644182999Smavhdac_suspend(device_t dev) 7645182999Smav{ 7646182999Smav struct hdac_softc *sc; 7647182999Smav struct hdac_codec *codec; 7648182999Smav struct hdac_devinfo *devinfo; 7649182999Smav int codec_index, fg_index, i; 7650182999Smav 7651183097Smav HDA_BOOTHVERBOSE( 7652182999Smav device_printf(dev, "Suspend...\n"); 7653162922Sariff ); 7654182999Smav 7655182999Smav sc = device_get_softc(dev); 7656182999Smav hdac_lock(sc); 7657182999Smav 7658183097Smav HDA_BOOTHVERBOSE( 7659182999Smav device_printf(dev, "Stop streams...\n"); 7660162922Sariff ); 7661182999Smav for (i = 0; i < sc->num_chans; i++) { 7662182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7663182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7664182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7665182999Smav } 7666182999Smav } 7667162922Sariff 7668182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7669182999Smav codec = sc->codecs[codec_index]; 7670182999Smav if (codec == NULL) 7671162922Sariff continue; 7672182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7673182999Smav devinfo = &codec->fgs[fg_index]; 7674183097Smav HDA_BOOTHVERBOSE( 7675182999Smav device_printf(dev, 7676182999Smav "Power down FG" 7677182999Smav " cad=%d nid=%d to the D3 state...\n", 7678182999Smav codec->cad, devinfo->nid); 7679182999Smav ); 7680182999Smav hdac_command(sc, 7681182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7682182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7683182999Smav codec->cad); 7684162922Sariff } 7685162922Sariff } 7686162922Sariff 7687183097Smav HDA_BOOTHVERBOSE( 7688182999Smav device_printf(dev, "Reset controller...\n"); 7689162922Sariff ); 7690182999Smav callout_stop(&sc->poll_hda); 7691182999Smav callout_stop(&sc->poll_hdac); 7692182999Smav callout_stop(&sc->poll_jack); 7693182999Smav hdac_reset(sc, 0); 7694182999Smav hdac_unlock(sc); 7695182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7696182999Smav callout_drain(&sc->poll_hda); 7697182999Smav callout_drain(&sc->poll_hdac); 7698182999Smav callout_drain(&sc->poll_jack); 7699162922Sariff 7700183097Smav HDA_BOOTHVERBOSE( 7701182999Smav device_printf(dev, "Suspend done\n"); 7702162922Sariff ); 7703182999Smav 7704182999Smav return (0); 7705182999Smav} 7706182999Smav 7707182999Smav/**************************************************************************** 7708182999Smav * int hdac_resume(device_t) 7709182999Smav * 7710182999Smav * Powerup and restore HDA bus and codecs state. 7711182999Smav ****************************************************************************/ 7712182999Smavstatic int 7713182999Smavhdac_resume(device_t dev) 7714182999Smav{ 7715182999Smav struct hdac_softc *sc; 7716182999Smav struct hdac_codec *codec; 7717182999Smav struct hdac_devinfo *devinfo; 7718182999Smav int codec_index, fg_index, i; 7719182999Smav 7720183097Smav HDA_BOOTHVERBOSE( 7721182999Smav device_printf(dev, "Resume...\n"); 7722162922Sariff ); 7723162922Sariff 7724182999Smav sc = device_get_softc(dev); 7725182999Smav hdac_lock(sc); 7726182999Smav 7727182999Smav /* Quiesce everything */ 7728183097Smav HDA_BOOTHVERBOSE( 7729182999Smav device_printf(dev, "Reset controller...\n"); 7730162922Sariff ); 7731182999Smav hdac_reset(sc, 1); 7732182999Smav 7733182999Smav /* Initialize the CORB and RIRB */ 7734182999Smav hdac_corb_init(sc); 7735182999Smav hdac_rirb_init(sc); 7736182999Smav 7737182999Smav /* Start the corb and rirb engines */ 7738183097Smav HDA_BOOTHVERBOSE( 7739182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7740162922Sariff ); 7741182999Smav hdac_corb_start(sc); 7742183097Smav HDA_BOOTHVERBOSE( 7743182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7744162922Sariff ); 7745182999Smav hdac_rirb_start(sc); 7746163057Sariff 7747183097Smav HDA_BOOTHVERBOSE( 7748182999Smav device_printf(dev, 7749182999Smav "Enabling controller interrupt...\n"); 7750162922Sariff ); 7751182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7752182999Smav HDAC_GCTL_UNSOL); 7753182999Smav if (sc->polling == 0) { 7754182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7755182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7756182999Smav } else { 7757182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7758182999Smav } 7759182999Smav DELAY(1000); 7760162922Sariff 7761182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7762182999Smav codec = sc->codecs[codec_index]; 7763182999Smav if (codec == NULL) 7764182999Smav continue; 7765182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7766182999Smav devinfo = &codec->fgs[fg_index]; 7767182999Smav if (devinfo->node_type != 7768182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7769183097Smav HDA_BOOTHVERBOSE( 7770182999Smav device_printf(dev, 7771182999Smav "Power down unsupported non-audio FG" 7772182999Smav " cad=%d nid=%d to the D3 state...\n", 7773182999Smav codec->cad, devinfo->nid); 7774182999Smav ); 7775182999Smav hdac_command(sc, 7776182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7777182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7778182999Smav codec->cad); 7779182999Smav continue; 7780182999Smav } 7781162922Sariff 7782183097Smav HDA_BOOTHVERBOSE( 7783182999Smav device_printf(dev, 7784182999Smav "Power up audio FG cad=%d nid=%d...\n", 7785182999Smav devinfo->codec->cad, devinfo->nid); 7786182999Smav ); 7787182999Smav hdac_powerup(devinfo); 7788183097Smav HDA_BOOTHVERBOSE( 7789182999Smav device_printf(dev, "AFG commit...\n"); 7790182999Smav ); 7791182999Smav hdac_audio_commit(devinfo); 7792183097Smav HDA_BOOTHVERBOSE( 7793182999Smav device_printf(dev, "HP switch init...\n"); 7794182999Smav ); 7795182999Smav hdac_hp_switch_init(devinfo); 7796182999Smav 7797182999Smav hdac_unlock(sc); 7798182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7799182999Smav struct hdac_pcm_devinfo *pdevinfo = 7800182999Smav &devinfo->function.audio.devs[i]; 7801183097Smav HDA_BOOTHVERBOSE( 7802182999Smav device_printf(pdevinfo->dev, 7803182999Smav "OSS mixer reinitialization...\n"); 7804182999Smav ); 7805182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 7806182999Smav device_printf(pdevinfo->dev, 7807182999Smav "unable to reinitialize the mixer\n"); 7808182999Smav } 7809182999Smav hdac_lock(sc); 7810182999Smav } 7811169277Sariff } 7812169277Sariff 7813183097Smav HDA_BOOTHVERBOSE( 7814182999Smav device_printf(dev, "Start streams...\n"); 7815163057Sariff ); 7816182999Smav for (i = 0; i < sc->num_chans; i++) { 7817182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 7818182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 7819182999Smav hdac_channel_start(sc, &sc->chans[i]); 7820182999Smav } 7821182999Smav } 7822162922Sariff 7823182999Smav hdac_unlock(sc); 7824182999Smav 7825183097Smav HDA_BOOTHVERBOSE( 7826182999Smav device_printf(dev, "Resume done\n"); 7827162922Sariff ); 7828164614Sariff 7829182999Smav return (0); 7830162922Sariff} 7831162922Sariff/**************************************************************************** 7832162922Sariff * int hdac_detach(device_t) 7833162922Sariff * 7834162922Sariff * Detach and free up resources utilized by the hdac device. 7835162922Sariff ****************************************************************************/ 7836162922Sariffstatic int 7837162922Sariffhdac_detach(device_t dev) 7838162922Sariff{ 7839182999Smav struct hdac_softc *sc; 7840185177Smav device_t *devlist; 7841185177Smav int i, devcount, error; 7842162922Sariff 7843185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 7844185177Smav return (error); 7845185177Smav for (i = 0; i < devcount; i++) { 7846185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 7847185178Smav free(devlist, M_TEMP); 7848185178Smav return (error); 7849185178Smav } 7850185177Smav } 7851185177Smav free(devlist, M_TEMP); 7852185177Smav 7853182999Smav sc = device_get_softc(dev); 7854163057Sariff hdac_release_resources(sc); 7855162922Sariff 7856162922Sariff return (0); 7857162922Sariff} 7858162922Sariff 7859184095Smavstatic int 7860184095Smavhdac_print_child(device_t dev, device_t child) 7861184095Smav{ 7862184095Smav struct hdac_pcm_devinfo *pdevinfo = 7863184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 7864184095Smav int retval; 7865184095Smav 7866184095Smav retval = bus_print_child_header(dev, child); 7867184095Smav retval += printf(" at cad %d nid %d", 7868184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 7869184095Smav retval += bus_print_child_footer(dev, child); 7870184095Smav 7871184095Smav return (retval); 7872184095Smav} 7873184095Smav 7874162922Sariffstatic device_method_t hdac_methods[] = { 7875162922Sariff /* device interface */ 7876162922Sariff DEVMETHOD(device_probe, hdac_probe), 7877162922Sariff DEVMETHOD(device_attach, hdac_attach), 7878162922Sariff DEVMETHOD(device_detach, hdac_detach), 7879182999Smav DEVMETHOD(device_suspend, hdac_suspend), 7880182999Smav DEVMETHOD(device_resume, hdac_resume), 7881184095Smav /* Bus interface */ 7882184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 7883162922Sariff { 0, 0 } 7884162922Sariff}; 7885162922Sariff 7886162922Sariffstatic driver_t hdac_driver = { 7887182999Smav "hdac", 7888162922Sariff hdac_methods, 7889182999Smav sizeof(struct hdac_softc), 7890162922Sariff}; 7891162922Sariff 7892182999Smavstatic devclass_t hdac_devclass; 7893182999Smav 7894182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 7895162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 7896162922SariffMODULE_VERSION(snd_hda, 1); 7897182999Smav 7898182999Smavstatic int 7899182999Smavhdac_pcm_probe(device_t dev) 7900182999Smav{ 7901182999Smav struct hdac_pcm_devinfo *pdevinfo = 7902182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7903182999Smav char buf[128]; 7904182999Smav 7905185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 7906182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 7907185225Smav pdevinfo->index, 7908185225Smav pdevinfo->digital?"Digital":"Analog"); 7909182999Smav device_set_desc_copy(dev, buf); 7910182999Smav return (0); 7911182999Smav} 7912182999Smav 7913182999Smavstatic int 7914182999Smavhdac_pcm_attach(device_t dev) 7915182999Smav{ 7916182999Smav struct hdac_pcm_devinfo *pdevinfo = 7917182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7918182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7919182999Smav char status[SND_STATUSLEN]; 7920182999Smav int i; 7921182999Smav 7922182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 7923182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 7924182999Smav 7925182999Smav HDA_BOOTVERBOSE( 7926182999Smav device_printf(dev, "+--------------------------------------+\n"); 7927182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 7928182999Smav device_printf(dev, "+--------------------------------------+\n"); 7929182999Smav hdac_dump_pcmchannels(pdevinfo); 7930182999Smav device_printf(dev, "\n"); 7931189876Smav device_printf(dev, "+-------------------------------+\n"); 7932189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 7933189876Smav device_printf(dev, "+-------------------------------+\n"); 7934182999Smav hdac_dump_dac(pdevinfo); 7935182999Smav hdac_dump_adc(pdevinfo); 7936182999Smav hdac_dump_mix(pdevinfo); 7937182999Smav device_printf(dev, "\n"); 7938182999Smav device_printf(dev, "+-------------------------+\n"); 7939182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 7940182999Smav device_printf(dev, "+-------------------------+\n"); 7941182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 7942182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 7943182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 7944182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 7945182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 7946182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 7947182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 7948182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 7949182999Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 7950182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 7951182999Smav device_printf(dev, "\n"); 7952182999Smav ); 7953182999Smav 7954182999Smav if (resource_int_value(device_get_name(dev), 7955182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 7956182999Smav i &= HDA_BLK_ALIGN; 7957182999Smav if (i < HDA_BLK_MIN) 7958182999Smav i = HDA_BLK_MIN; 7959182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 7960182999Smav i = 0; 7961182999Smav while (pdevinfo->chan_blkcnt >> i) 7962182999Smav i++; 7963182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 7964182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 7965182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 7966182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 7967182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 7968182999Smav } else 7969182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 7970182999Smav 7971182999Smav /* 7972182999Smav * We don't register interrupt handler with snd_setup_intr 7973182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 7974182999Smav */ 7975182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 7976182999Smav 7977183097Smav HDA_BOOTHVERBOSE( 7978182999Smav device_printf(dev, "OSS mixer initialization...\n"); 7979182999Smav ); 7980182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 7981182999Smav device_printf(dev, "Can't register mixer\n"); 7982182999Smav 7983183097Smav HDA_BOOTHVERBOSE( 7984182999Smav device_printf(dev, "Registering PCM channels...\n"); 7985182999Smav ); 7986182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 7987182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 7988182999Smav device_printf(dev, "Can't register PCM\n"); 7989182999Smav 7990182999Smav pdevinfo->registered++; 7991182999Smav 7992182999Smav if (pdevinfo->play >= 0) 7993182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 7994182999Smav if (pdevinfo->rec >= 0) 7995182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 7996182999Smav 7997184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 7998184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 7999184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 8000182999Smav pcm_setstatus(dev, status); 8001182999Smav 8002182999Smav return (0); 8003182999Smav} 8004182999Smav 8005182999Smavstatic int 8006182999Smavhdac_pcm_detach(device_t dev) 8007182999Smav{ 8008182999Smav struct hdac_pcm_devinfo *pdevinfo = 8009182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8010182999Smav int err; 8011182999Smav 8012182999Smav if (pdevinfo->registered > 0) { 8013182999Smav err = pcm_unregister(dev); 8014182999Smav if (err != 0) 8015182999Smav return (err); 8016182999Smav } 8017182999Smav 8018182999Smav return (0); 8019182999Smav} 8020182999Smav 8021182999Smavstatic device_method_t hdac_pcm_methods[] = { 8022182999Smav /* device interface */ 8023182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8024182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8025182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8026182999Smav { 0, 0 } 8027182999Smav}; 8028182999Smav 8029182999Smavstatic driver_t hdac_pcm_driver = { 8030182999Smav "pcm", 8031182999Smav hdac_pcm_methods, 8032182999Smav PCM_SOFTC_SIZE, 8033182999Smav}; 8034182999Smav 8035182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8036182999Smav 8037