hdac.c revision 189879
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 86189879Smav#define HDA_DRV_TEST_REV "20090316_0130" 87162922Sariff 88162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 189879 2009-03-16 15:50:29Z 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) { 5283182999Smav device_printf(devinfo->codec->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; 5293182999Smav device_printf(devinfo->codec->sc->dev, 5294182999Smav "Channels memory allocation failed!\n"); 5295182999Smav return; 5296182999Smav } 5297182999Smav } 5298182999Smav free = sc->num_chans; 5299182999Smav sc->num_chans += cnt; 5300162922Sariff 5301182999Smav for (j = free; j < free + cnt; j++) { 5302182999Smav devinfo->codec->sc->chans[j].devinfo = devinfo; 5303182999Smav devinfo->codec->sc->chans[j].as = -1; 5304182999Smav } 5305162922Sariff 5306182999Smav /* Assign associations in order of their numbers, */ 5307182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5308182999Smav if (as[j].enable == 0) 5309182999Smav continue; 5310182999Smav 5311182999Smav as[j].chan = free; 5312182999Smav devinfo->codec->sc->chans[free].as = j; 5313185225Smav devinfo->codec->sc->chans[free].dir = 5314185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5315182999Smav hdac_pcmchannel_setup(&devinfo->codec->sc->chans[free]); 5316182999Smav free++; 5317182999Smav } 5318182999Smav} 5319162922Sariff 5320182999Smavstatic void 5321182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5322182999Smav{ 5323182999Smav struct hdac_widget *w; 5324182999Smav int i; 5325182999Smav 5326182999Smav /* Disable power and volume widgets. */ 5327182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5328182999Smav w = hdac_widget_get(devinfo, i); 5329182999Smav if (w == NULL || w->enable == 0) 5330182999Smav continue; 5331182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5332182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5333182999Smav w->enable = 0; 5334183097Smav HDA_BOOTHVERBOSE( 5335182999Smav device_printf(devinfo->codec->sc->dev, 5336182999Smav " Disabling nid %d due to it's" 5337182999Smav " non-audio type.\n", 5338182999Smav w->nid); 5339182999Smav ); 5340162922Sariff } 5341182999Smav } 5342182999Smav} 5343182999Smav 5344182999Smavstatic void 5345182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5346182999Smav{ 5347182999Smav struct hdac_widget *w, *cw; 5348182999Smav struct hdac_audio_ctl *ctl; 5349182999Smav int done, found, i, j, k; 5350182999Smav 5351182999Smav /* Disable useless pins. */ 5352182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5353182999Smav w = hdac_widget_get(devinfo, i); 5354182999Smav if (w == NULL || w->enable == 0) 5355182999Smav continue; 5356184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5357184991Smav if ((w->wclass.pin.config & 5358184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5359184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5360184991Smav w->enable = 0; 5361184991Smav HDA_BOOTHVERBOSE( 5362184991Smav device_printf(devinfo->codec->sc->dev, 5363184991Smav " Disabling pin nid %d due" 5364184991Smav " to None connectivity.\n", 5365184991Smav w->nid); 5366184991Smav ); 5367184991Smav } else if ((w->wclass.pin.config & 5368184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5369184991Smav w->enable = 0; 5370184991Smav HDA_BOOTHVERBOSE( 5371184991Smav device_printf(devinfo->codec->sc->dev, 5372184991Smav " Disabling unassociated" 5373184991Smav " pin nid %d.\n", 5374184991Smav w->nid); 5375184991Smav ); 5376184991Smav } 5377182999Smav } 5378182999Smav } 5379182999Smav do { 5380182999Smav done = 1; 5381182999Smav /* Disable and mute controls for disabled widgets. */ 5382162922Sariff i = 0; 5383162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5384182999Smav if (ctl->enable == 0) 5385162922Sariff continue; 5386182999Smav if (ctl->widget->enable == 0 || 5387182999Smav (ctl->childwidget != NULL && 5388182999Smav ctl->childwidget->enable == 0)) { 5389182999Smav ctl->forcemute = 1; 5390182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5391182999Smav ctl->left = 0; 5392182999Smav ctl->right = 0; 5393182999Smav ctl->enable = 0; 5394182999Smav if (ctl->ndir == HDA_CTL_IN) 5395182999Smav ctl->widget->connsenable[ctl->index] = 0; 5396182999Smav done = 0; 5397183097Smav HDA_BOOTHVERBOSE( 5398182999Smav device_printf(devinfo->codec->sc->dev, 5399182999Smav " Disabling ctl %d nid %d cnid %d due" 5400182999Smav " to disabled widget.\n", i, 5401182999Smav ctl->widget->nid, 5402182999Smav (ctl->childwidget != NULL)? 5403182999Smav ctl->childwidget->nid:-1); 5404182999Smav ); 5405182999Smav } 5406182999Smav } 5407182999Smav /* Disable useless widgets. */ 5408182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5409182999Smav w = hdac_widget_get(devinfo, i); 5410182999Smav if (w == NULL || w->enable == 0) 5411182999Smav continue; 5412182999Smav /* Disable inputs with disabled child widgets. */ 5413182999Smav for (j = 0; j < w->nconns; j++) { 5414182999Smav if (w->connsenable[j]) { 5415182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5416182999Smav if (cw == NULL || cw->enable == 0) { 5417182999Smav w->connsenable[j] = 0; 5418183097Smav HDA_BOOTHVERBOSE( 5419182999Smav device_printf(devinfo->codec->sc->dev, 5420182999Smav " Disabling nid %d connection %d due" 5421182999Smav " to disabled child widget.\n", 5422182999Smav i, j); 5423182999Smav ); 5424163057Sariff } 5425163057Sariff } 5426162922Sariff } 5427182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5428182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5429162922Sariff continue; 5430182999Smav /* Disable mixers and selectors without inputs. */ 5431182999Smav found = 0; 5432182999Smav for (j = 0; j < w->nconns; j++) { 5433182999Smav if (w->connsenable[j]) { 5434182999Smav found = 1; 5435162922Sariff break; 5436162922Sariff } 5437182999Smav } 5438182999Smav if (found == 0) { 5439182999Smav w->enable = 0; 5440182999Smav done = 0; 5441183097Smav HDA_BOOTHVERBOSE( 5442182999Smav device_printf(devinfo->codec->sc->dev, 5443182999Smav " Disabling nid %d due to all it's" 5444182999Smav " inputs disabled.\n", w->nid); 5445182999Smav ); 5446182999Smav } 5447182999Smav /* Disable nodes without consumers. */ 5448182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5449182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5450182999Smav continue; 5451182999Smav found = 0; 5452182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5453182999Smav cw = hdac_widget_get(devinfo, k); 5454182999Smav if (cw == NULL || cw->enable == 0) 5455182999Smav continue; 5456182999Smav for (j = 0; j < cw->nconns; j++) { 5457182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5458182999Smav found = 1; 5459182999Smav break; 5460182999Smav } 5461162922Sariff } 5462162922Sariff } 5463182999Smav if (found == 0) { 5464182999Smav w->enable = 0; 5465182999Smav done = 0; 5466183097Smav HDA_BOOTHVERBOSE( 5467182999Smav device_printf(devinfo->codec->sc->dev, 5468182999Smav " Disabling nid %d due to all it's" 5469182999Smav " consumers disabled.\n", w->nid); 5470182999Smav ); 5471182999Smav } 5472162922Sariff } 5473182999Smav } while (done == 0); 5474182999Smav 5475182999Smav} 5476182999Smav 5477182999Smavstatic void 5478182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5479182999Smav{ 5480182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5481182999Smav struct hdac_widget *w, *cw; 5482182999Smav struct hdac_audio_ctl *ctl; 5483182999Smav int i, j, k; 5484182999Smav 5485182999Smav /* Disable unassosiated widgets. */ 5486182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5487182999Smav w = hdac_widget_get(devinfo, i); 5488182999Smav if (w == NULL || w->enable == 0) 5489182999Smav continue; 5490182999Smav if (w->bindas == -1) { 5491182999Smav w->enable = 0; 5492183097Smav HDA_BOOTHVERBOSE( 5493182999Smav device_printf(devinfo->codec->sc->dev, 5494182999Smav " Disabling unassociated nid %d.\n", 5495182999Smav w->nid); 5496182999Smav ); 5497182999Smav } 5498182999Smav } 5499182999Smav /* Disable input connections on input pin and 5500182999Smav * output on output. */ 5501182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5502182999Smav w = hdac_widget_get(devinfo, i); 5503182999Smav if (w == NULL || w->enable == 0) 5504182999Smav continue; 5505182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5506182999Smav continue; 5507182999Smav if (w->bindas < 0) 5508182999Smav continue; 5509182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5510182999Smav for (j = 0; j < w->nconns; j++) { 5511182999Smav if (w->connsenable[j] == 0) 5512182999Smav continue; 5513182999Smav w->connsenable[j] = 0; 5514183097Smav HDA_BOOTHVERBOSE( 5515182999Smav device_printf(devinfo->codec->sc->dev, 5516182999Smav " Disabling connection to input pin " 5517182999Smav "nid %d conn %d.\n", 5518182999Smav i, j); 5519182999Smav ); 5520162922Sariff } 5521182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5522182999Smav HDA_CTL_IN, -1, 1); 5523182999Smav if (ctl && ctl->enable) { 5524182999Smav ctl->forcemute = 1; 5525182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5526182999Smav ctl->left = 0; 5527182999Smav ctl->right = 0; 5528182999Smav ctl->enable = 0; 5529182999Smav } 5530182999Smav } else { 5531182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5532182999Smav HDA_CTL_OUT, -1, 1); 5533182999Smav if (ctl && ctl->enable) { 5534182999Smav ctl->forcemute = 1; 5535182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5536182999Smav ctl->left = 0; 5537182999Smav ctl->right = 0; 5538182999Smav ctl->enable = 0; 5539182999Smav } 5540182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5541182999Smav cw = hdac_widget_get(devinfo, k); 5542182999Smav if (cw == NULL || cw->enable == 0) 5543182999Smav continue; 5544182999Smav for (j = 0; j < cw->nconns; j++) { 5545182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5546182999Smav cw->connsenable[j] = 0; 5547183097Smav HDA_BOOTHVERBOSE( 5548182999Smav device_printf(devinfo->codec->sc->dev, 5549182999Smav " Disabling connection from output pin " 5550182999Smav "nid %d conn %d cnid %d.\n", 5551182999Smav k, j, i); 5552182999Smav ); 5553182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5554182999Smav cw->nconns > 1) 5555182999Smav continue; 5556182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5557182999Smav HDA_CTL_IN, j, 1); 5558182999Smav if (ctl && ctl->enable) { 5559182999Smav ctl->forcemute = 1; 5560182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5561182999Smav ctl->left = 0; 5562182999Smav ctl->right = 0; 5563182999Smav ctl->enable = 0; 5564182999Smav } 5565182999Smav } 5566182999Smav } 5567182999Smav } 5568162922Sariff } 5569162922Sariff } 5570162922Sariff} 5571162922Sariff 5572182999Smavstatic void 5573182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5574162922Sariff{ 5575182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5576182999Smav struct hdac_widget *w; 5577182999Smav int i, j; 5578182999Smav 5579182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5580182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5581182999Smav w = hdac_widget_get(devinfo, i); 5582182999Smav if (w == NULL || w->enable == 0) 5583182999Smav continue; 5584182999Smav if (w->nconns <= 1) 5585182999Smav continue; 5586182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5587182999Smav continue; 5588182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5589182999Smav continue; 5590182999Smav for (j = 0; j < w->nconns; j++) { 5591182999Smav if (w->connsenable[j] == 0) 5592182999Smav continue; 5593182999Smav if (w->selconn < 0 || w->selconn == j) 5594182999Smav continue; 5595182999Smav w->connsenable[j] = 0; 5596183097Smav HDA_BOOTHVERBOSE( 5597182999Smav device_printf(devinfo->codec->sc->dev, 5598182999Smav " Disabling unselected connection " 5599182999Smav "nid %d conn %d.\n", 5600182999Smav i, j); 5601182999Smav ); 5602182999Smav } 5603182999Smav } 5604182999Smav} 5605182999Smav 5606182999Smavstatic void 5607182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5608182999Smav{ 5609162922Sariff struct hdac_widget *w, *cw; 5610162922Sariff struct hdac_audio_ctl *ctl; 5611182999Smav int i, j; 5612162922Sariff 5613187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5614182999Smav /* ... using selectors */ 5615182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5616182999Smav w = hdac_widget_get(devinfo, i); 5617182999Smav if (w == NULL || w->enable == 0) 5618182999Smav continue; 5619182999Smav if (w->nconns <= 1) 5620182999Smav continue; 5621182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5622182999Smav continue; 5623182999Smav if (w->bindas == -2) 5624182999Smav continue; 5625182999Smav for (j = 0; j < w->nconns; j++) { 5626182999Smav if (w->connsenable[j] == 0) 5627182999Smav continue; 5628182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5629182999Smav if (cw == NULL || w->enable == 0) 5630182999Smav continue; 5631187052Smav if (cw->bindas == -2) 5632182999Smav continue; 5633187052Smav if (w->bindas == cw->bindas && 5634187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5635187052Smav continue; 5636182999Smav w->connsenable[j] = 0; 5637183097Smav HDA_BOOTHVERBOSE( 5638182999Smav device_printf(devinfo->codec->sc->dev, 5639182999Smav " Disabling crossassociatement connection " 5640182999Smav "nid %d conn %d cnid %d.\n", 5641182999Smav i, j, cw->nid); 5642182999Smav ); 5643182999Smav } 5644182999Smav } 5645182999Smav /* ... using controls */ 5646182999Smav i = 0; 5647182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5648182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5649182999Smav continue; 5650182999Smav if (ctl->widget->bindas == -2 || 5651182999Smav ctl->childwidget->bindas == -2) 5652182999Smav continue; 5653187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5654187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5655182999Smav ctl->forcemute = 1; 5656182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5657182999Smav ctl->left = 0; 5658182999Smav ctl->right = 0; 5659182999Smav ctl->enable = 0; 5660182999Smav if (ctl->ndir == HDA_CTL_IN) 5661182999Smav ctl->widget->connsenable[ctl->index] = 0; 5662183097Smav HDA_BOOTHVERBOSE( 5663182999Smav device_printf(devinfo->codec->sc->dev, 5664182999Smav " Disabling crossassociatement connection " 5665182999Smav "ctl %d nid %d cnid %d.\n", i, 5666182999Smav ctl->widget->nid, 5667182999Smav ctl->childwidget->nid); 5668182999Smav ); 5669182999Smav } 5670182999Smav } 5671182999Smav 5672182999Smav} 5673182999Smav 5674182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5675182999Smav 5676182999Smav/* 5677182999Smav * Find controls to control amplification for source. 5678182999Smav */ 5679182999Smavstatic int 5680182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5681182999Smav int ossdev, int ctlable, int depth, int need) 5682182999Smav{ 5683182999Smav struct hdac_widget *w, *wc; 5684182999Smav struct hdac_audio_ctl *ctl; 5685182999Smav int i, j, conns = 0, rneed; 5686182999Smav 5687162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5688182999Smav return (need); 5689162922Sariff 5690162922Sariff w = hdac_widget_get(devinfo, nid); 5691162922Sariff if (w == NULL || w->enable == 0) 5692182999Smav return (need); 5693182999Smav 5694182999Smav /* Count number of active inputs. */ 5695182999Smav if (depth > 0) { 5696182999Smav for (j = 0; j < w->nconns; j++) { 5697182999Smav if (w->connsenable[j]) 5698182999Smav conns++; 5699162922Sariff } 5700162922Sariff } 5701182999Smav 5702182999Smav /* If this is not a first step - use input mixer. 5703182999Smav Pins have common input ctl so care must be taken. */ 5704182999Smav if (depth > 0 && ctlable && (conns == 1 || 5705182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5706182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5707182999Smav index, 1); 5708182999Smav if (ctl) { 5709182999Smav if (HDA_CTL_GIVE(ctl) & need) 5710182999Smav ctl->ossmask |= (1 << ossdev); 5711182999Smav else 5712182999Smav ctl->possmask |= (1 << ossdev); 5713182999Smav need &= ~HDA_CTL_GIVE(ctl); 5714182999Smav } 5715182999Smav } 5716182999Smav 5717182999Smav /* If widget has own ossdev - not traverse it. 5718182999Smav It will be traversed on it's own. */ 5719182999Smav if (w->ossdev >= 0 && depth > 0) 5720182999Smav return (need); 5721182999Smav 5722182999Smav /* We must not traverse pin */ 5723182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5724182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5725182999Smav depth > 0) 5726182999Smav return (need); 5727182999Smav 5728182999Smav /* record that this widget exports such signal, */ 5729182999Smav w->ossmask |= (1 << ossdev); 5730182999Smav 5731182999Smav /* If signals mixed, we can't assign controls farther. 5732182999Smav * Ignore this on depth zero. Caller must knows why. 5733182999Smav * Ignore this for static selectors if this input selected. 5734182999Smav */ 5735182999Smav if (conns > 1) 5736182999Smav ctlable = 0; 5737182999Smav 5738182999Smav if (ctlable) { 5739182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5740182999Smav if (ctl) { 5741182999Smav if (HDA_CTL_GIVE(ctl) & need) 5742182999Smav ctl->ossmask |= (1 << ossdev); 5743182999Smav else 5744182999Smav ctl->possmask |= (1 << ossdev); 5745182999Smav need &= ~HDA_CTL_GIVE(ctl); 5746182999Smav } 5747182999Smav } 5748182999Smav 5749182999Smav rneed = 0; 5750182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5751182999Smav wc = hdac_widget_get(devinfo, i); 5752182999Smav if (wc == NULL || wc->enable == 0) 5753162922Sariff continue; 5754182999Smav for (j = 0; j < wc->nconns; j++) { 5755182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5756182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5757182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5758182999Smav } 5759162922Sariff } 5760162922Sariff } 5761182999Smav rneed &= need; 5762182999Smav 5763182999Smav return (rneed); 5764162922Sariff} 5765162922Sariff 5766182999Smav/* 5767182999Smav * Find controls to control amplification for destination. 5768182999Smav */ 5769182999Smavstatic void 5770182999Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, 5771182999Smav int ossdev, int depth, int need) 5772162922Sariff{ 5773182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5774182999Smav struct hdac_widget *w, *wc; 5775182999Smav struct hdac_audio_ctl *ctl; 5776182999Smav int i, j, consumers; 5777182999Smav 5778162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5779182999Smav return; 5780162922Sariff 5781162922Sariff w = hdac_widget_get(devinfo, nid); 5782162922Sariff if (w == NULL || w->enable == 0) 5783182999Smav return; 5784182999Smav 5785182999Smav if (depth > 0) { 5786182999Smav /* If this node produce output for several consumers, 5787182999Smav we can't touch it. */ 5788182999Smav consumers = 0; 5789182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5790182999Smav wc = hdac_widget_get(devinfo, i); 5791182999Smav if (wc == NULL || wc->enable == 0) 5792182999Smav continue; 5793182999Smav for (j = 0; j < wc->nconns; j++) { 5794182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5795182999Smav consumers++; 5796182999Smav } 5797182999Smav } 5798182999Smav /* The only exception is if real HP redirection is configured 5799182999Smav and this is a duplication point. 5800182999Smav XXX: Actually exception is not completely correct. 5801182999Smav XXX: Duplication point check is not perfect. */ 5802182999Smav if ((consumers == 2 && (w->bindas < 0 || 5803182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5804182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5805182999Smav consumers > 2) 5806182999Smav return; 5807182999Smav 5808182999Smav /* Else use it's output mixer. */ 5809182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5810182999Smav HDA_CTL_OUT, -1, 1); 5811182999Smav if (ctl) { 5812182999Smav if (HDA_CTL_GIVE(ctl) & need) 5813182999Smav ctl->ossmask |= (1 << ossdev); 5814182999Smav else 5815182999Smav ctl->possmask |= (1 << ossdev); 5816182999Smav need &= ~HDA_CTL_GIVE(ctl); 5817182999Smav } 5818182999Smav } 5819182999Smav 5820182999Smav /* We must not traverse pin */ 5821182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5822182999Smav depth > 0) 5823182999Smav return; 5824182999Smav 5825162922Sariff for (i = 0; i < w->nconns; i++) { 5826182999Smav int tneed = need; 5827182999Smav if (w->connsenable[i] == 0) 5828162922Sariff continue; 5829182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5830182999Smav HDA_CTL_IN, i, 1); 5831182999Smav if (ctl) { 5832182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 5833182999Smav ctl->ossmask |= (1 << ossdev); 5834182999Smav else 5835182999Smav ctl->possmask |= (1 << ossdev); 5836182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 5837162922Sariff } 5838182999Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev, 5839182999Smav depth + 1, tneed); 5840162922Sariff } 5841162922Sariff} 5842162922Sariff 5843182999Smav/* 5844182999Smav * Assign OSS names to sound sources 5845182999Smav */ 5846182999Smavstatic void 5847182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 5848162922Sariff{ 5849182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5850182999Smav struct hdac_widget *w; 5851182999Smav int i, j; 5852182999Smav int type = -1, use, used = 0; 5853182999Smav static const int types[7][13] = { 5854182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5855182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 5856182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 5857182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 5858182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 5859182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 5860182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 5861182999Smav -1 }, /* digital */ 5862182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5863182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 5864182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 5865182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 5866182999Smav -1 } /* others */ 5867182999Smav }; 5868162922Sariff 5869182999Smav /* Surely known names */ 5870162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5871162922Sariff w = hdac_widget_get(devinfo, i); 5872162922Sariff if (w == NULL || w->enable == 0) 5873162922Sariff continue; 5874182999Smav if (w->bindas == -1) 5875182999Smav continue; 5876182999Smav use = -1; 5877182999Smav switch (w->type) { 5878182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5879182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5880182999Smav break; 5881182999Smav type = -1; 5882182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5883182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 5884182999Smav type = 0; 5885182999Smav break; 5886182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5887182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 5888182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 5889182999Smav break; 5890182999Smav type = 1; 5891182999Smav break; 5892182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 5893182999Smav type = 3; 5894182999Smav break; 5895182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5896182999Smav type = 4; 5897182999Smav break; 5898182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 5899182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 5900182999Smav type = 5; 5901182999Smav break; 5902182999Smav } 5903182999Smav if (type == -1) 5904182999Smav break; 5905182999Smav j = 0; 5906182999Smav while (types[type][j] >= 0 && 5907182999Smav (used & (1 << types[type][j])) != 0) { 5908182999Smav j++; 5909182999Smav } 5910182999Smav if (types[type][j] >= 0) 5911182999Smav use = types[type][j]; 5912182999Smav break; 5913182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5914182999Smav use = SOUND_MIXER_PCM; 5915182999Smav break; 5916182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 5917182999Smav use = SOUND_MIXER_SPEAKER; 5918182999Smav break; 5919182999Smav default: 5920182999Smav break; 5921182999Smav } 5922182999Smav if (use >= 0) { 5923182999Smav w->ossdev = use; 5924182999Smav used |= (1 << use); 5925182999Smav } 5926182999Smav } 5927182999Smav /* Semi-known names */ 5928182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5929182999Smav w = hdac_widget_get(devinfo, i); 5930182999Smav if (w == NULL || w->enable == 0) 5931182999Smav continue; 5932182999Smav if (w->ossdev >= 0) 5933182999Smav continue; 5934182999Smav if (w->bindas == -1) 5935182999Smav continue; 5936162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5937162922Sariff continue; 5938182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5939162922Sariff continue; 5940182999Smav type = -1; 5941182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5942182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 5943182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5944182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 5945182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 5946182999Smav type = 0; 5947182999Smav break; 5948182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5949182999Smav type = 2; 5950182999Smav break; 5951182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 5952182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 5953182999Smav type = 5; 5954182999Smav break; 5955182999Smav } 5956182999Smav if (type == -1) 5957182999Smav break; 5958182999Smav j = 0; 5959182999Smav while (types[type][j] >= 0 && 5960182999Smav (used & (1 << types[type][j])) != 0) { 5961182999Smav j++; 5962182999Smav } 5963182999Smav if (types[type][j] >= 0) { 5964182999Smav w->ossdev = types[type][j]; 5965182999Smav used |= (1 << types[type][j]); 5966182999Smav } 5967182999Smav } 5968182999Smav /* Others */ 5969182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5970182999Smav w = hdac_widget_get(devinfo, i); 5971182999Smav if (w == NULL || w->enable == 0) 5972162922Sariff continue; 5973182999Smav if (w->ossdev >= 0) 5974182999Smav continue; 5975182999Smav if (w->bindas == -1) 5976182999Smav continue; 5977182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5978182999Smav continue; 5979182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5980182999Smav continue; 5981182999Smav j = 0; 5982182999Smav while (types[6][j] >= 0 && 5983182999Smav (used & (1 << types[6][j])) != 0) { 5984182999Smav j++; 5985162922Sariff } 5986182999Smav if (types[6][j] >= 0) { 5987182999Smav w->ossdev = types[6][j]; 5988182999Smav used |= (1 << types[6][j]); 5989182999Smav } 5990162922Sariff } 5991162922Sariff} 5992162922Sariff 5993162922Sariffstatic void 5994162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5995162922Sariff{ 5996182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5997182999Smav int j, res; 5998162922Sariff 5999182999Smav /* Trace all associations in order of their numbers, */ 6000182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 6001182999Smav if (as[j].enable == 0) 6002182999Smav continue; 6003163057Sariff HDA_BOOTVERBOSE( 6004162922Sariff device_printf(devinfo->codec->sc->dev, 6005182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6006162922Sariff ); 6007182999Smav if (as[j].dir == HDA_CTL_OUT) { 6008182999Smavretry: 6009182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6010182999Smav if (res == 0 && as[j].hpredir >= 0 && 6011182999Smav as[j].fakeredir == 0) { 6012182999Smav /* If codec can't do analog HP redirection 6013182999Smav try to make it using one more DAC. */ 6014182999Smav as[j].fakeredir = 1; 6015182999Smav goto retry; 6016182999Smav } 6017182999Smav } else { 6018182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6019182999Smav } 6020182999Smav if (res) { 6021182999Smav HDA_BOOTVERBOSE( 6022182999Smav device_printf(devinfo->codec->sc->dev, 6023188510Smav "Association %d (%d) trace succeeded\n", 6024182999Smav j, as[j].index); 6025182999Smav ); 6026182999Smav } else { 6027182999Smav HDA_BOOTVERBOSE( 6028182999Smav device_printf(devinfo->codec->sc->dev, 6029182999Smav "Association %d (%d) trace failed\n", 6030182999Smav j, as[j].index); 6031182999Smav ); 6032182999Smav as[j].enable = 0; 6033182999Smav } 6034162922Sariff } 6035162922Sariff 6036182999Smav /* Trace mixer and beeper pseudo associations. */ 6037182999Smav hdac_audio_trace_as_extra(devinfo); 6038182999Smav} 6039162922Sariff 6040182999Smavstatic void 6041182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6042182999Smav{ 6043182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6044182999Smav struct hdac_audio_ctl *ctl; 6045182999Smav struct hdac_widget *w; 6046182999Smav int i; 6047162922Sariff 6048182999Smav /* Assign mixers to the tree. */ 6049162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6050162922Sariff w = hdac_widget_get(devinfo, i); 6051162922Sariff if (w == NULL || w->enable == 0) 6052162922Sariff continue; 6053182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6054182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6055182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6056182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6057182999Smav if (w->ossdev < 0) 6058182999Smav continue; 6059182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6060182999Smav w->ossdev, 1, 0, 1); 6061182999Smav } else if ((w->pflags & HDA_ADC_MONITOR) != 0) { 6062182999Smav if (w->ossdev < 0) 6063182999Smav continue; 6064182999Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6065182999Smav w->ossdev, 1, 0, 1)) { 6066182999Smav /* If we are unable to control input monitor 6067182999Smav as source - try to control it as destination. */ 6068182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6069182999Smav w->ossdev, 0, 1); 6070162922Sariff } 6071182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6072182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6073182999Smav SOUND_MIXER_RECLEV, 0, 1); 6074182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6075182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6076182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 6077182999Smav SOUND_MIXER_VOLUME, 0, 1); 6078162922Sariff } 6079162922Sariff } 6080182999Smav /* Treat unrequired as possible. */ 6081182999Smav i = 0; 6082182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6083182999Smav if (ctl->ossmask == 0) 6084182999Smav ctl->ossmask = ctl->possmask; 6085182999Smav } 6086182999Smav} 6087162922Sariff 6088182999Smavstatic void 6089182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6090182999Smav{ 6091182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6092182999Smav struct hdac_widget *w; 6093182999Smav uint32_t pincap; 6094182999Smav int i; 6095182999Smav 6096182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6097182999Smav w = &devinfo->widget[i]; 6098182999Smav if (w == NULL) 6099162922Sariff continue; 6100182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6101162922Sariff continue; 6102182999Smav 6103182999Smav pincap = w->wclass.pin.cap; 6104182999Smav 6105182999Smav /* Disable everything. */ 6106182999Smav w->wclass.pin.ctrl &= ~( 6107182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6108182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6109182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6110182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6111182999Smav 6112182999Smav if (w->enable == 0 || 6113182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6114182999Smav /* Pin is unused so left it disabled. */ 6115182999Smav continue; 6116182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6117182999Smav /* Input pin, configure for input. */ 6118182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6119182999Smav w->wclass.pin.ctrl |= 6120182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6121182999Smav 6122182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6123182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6124182999Smav w->wclass.pin.ctrl |= 6125182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6126182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6127182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6128182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6129182999Smav w->wclass.pin.ctrl |= 6130182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6131182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6132182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6133182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6134182999Smav w->wclass.pin.ctrl |= 6135182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6136182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6137182999Smav } else { 6138182999Smav /* Output pin, configure for output. */ 6139182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6140182999Smav w->wclass.pin.ctrl |= 6141182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6142182999Smav 6143182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6144182999Smav (w->wclass.pin.config & 6145182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6146182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6147182999Smav w->wclass.pin.ctrl |= 6148182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6149182999Smav 6150182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6151182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6152182999Smav w->wclass.pin.ctrl |= 6153182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6154182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6155182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6156182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6157182999Smav w->wclass.pin.ctrl |= 6158182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6159182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6160182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6161182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6162182999Smav w->wclass.pin.ctrl |= 6163182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6164182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6165182999Smav } 6166162922Sariff } 6167162922Sariff} 6168162922Sariff 6169162922Sariffstatic void 6170187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6171187154Smav{ 6172187154Smav struct hdac_audio_ctl *ctl; 6173187154Smav int i, z; 6174187154Smav 6175187154Smav i = 0; 6176187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6177187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6178187154Smav /* Mute disabled and mixer controllable controls. 6179187154Smav * Last will be initialized by mixer_init(). 6180187154Smav * This expected to reduce click on startup. */ 6181187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6182187154Smav continue; 6183187154Smav } 6184187154Smav /* Init fixed controls to 0dB amplification. */ 6185187154Smav z = ctl->offset; 6186187154Smav if (z > ctl->step) 6187187154Smav z = ctl->step; 6188187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6189187154Smav } 6190187154Smav} 6191187154Smav 6192187154Smavstatic void 6193182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6194162922Sariff{ 6195162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6196162922Sariff struct hdac_widget *w; 6197164750Sariff nid_t cad; 6198182999Smav uint32_t gdata, gmask, gdir; 6199182999Smav int commitgpio, numgpio; 6200164750Sariff int i; 6201162922Sariff 6202162922Sariff cad = devinfo->codec->cad; 6203162922Sariff 6204182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6205182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6206182999Smav 0x7e7, 0), cad); 6207169277Sariff 6208187154Smav /* Commit controls. */ 6209187154Smav hdac_audio_ctl_commit(devinfo); 6210187154Smav 6211187154Smav /* Commit selectors, pins and EAPD. */ 6212187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6213187154Smav w = &devinfo->widget[i]; 6214187154Smav if (w == NULL) 6215187154Smav continue; 6216187154Smav if (w->selconn == -1) 6217187154Smav w->selconn = 0; 6218187154Smav if (w->nconns > 0) 6219187154Smav hdac_widget_connection_select(w, w->selconn); 6220187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6221187154Smav hdac_command(sc, 6222187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6223187154Smav w->wclass.pin.ctrl), cad); 6224187154Smav } 6225187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6226187154Smav uint32_t val; 6227187154Smav 6228187154Smav val = w->param.eapdbtl; 6229187154Smav if (devinfo->function.audio.quirks & 6230187154Smav HDA_QUIRK_EAPDINV) 6231187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6232187154Smav hdac_command(sc, 6233187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6234187154Smav val), cad); 6235187154Smav } 6236187154Smav } 6237187154Smav 6238187154Smav /* Commit GPIOs. */ 6239182999Smav gdata = 0; 6240182999Smav gmask = 0; 6241182999Smav gdir = 0; 6242182999Smav commitgpio = 0; 6243182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6244182999Smav devinfo->function.audio.gpio); 6245166796Sariff 6246182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6247182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6248182999Smav else { 6249182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6250182999Smav if (!(devinfo->function.audio.quirks & 6251182999Smav (1 << i))) 6252182999Smav continue; 6253182999Smav if (commitgpio == 0) { 6254182999Smav commitgpio = 1; 6255182999Smav HDA_BOOTVERBOSE( 6256182999Smav gdata = hdac_command(sc, 6257182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6258182999Smav devinfo->nid), cad); 6259182999Smav gmask = hdac_command(sc, 6260182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6261182999Smav devinfo->nid), cad); 6262182999Smav gdir = hdac_command(sc, 6263182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6264182999Smav devinfo->nid), cad); 6265182999Smav device_printf(sc->dev, 6266182999Smav "GPIO init: data=0x%08x " 6267182999Smav "mask=0x%08x dir=0x%08x\n", 6268182999Smav gdata, gmask, gdir); 6269182999Smav gdata = 0; 6270182999Smav gmask = 0; 6271182999Smav gdir = 0; 6272182999Smav ); 6273165039Sariff } 6274182999Smav gdata |= 1 << i; 6275182999Smav gmask |= 1 << i; 6276182999Smav gdir |= 1 << i; 6277165039Sariff } 6278182999Smav } 6279165039Sariff 6280182999Smav if (commitgpio != 0) { 6281182999Smav HDA_BOOTVERBOSE( 6282182999Smav device_printf(sc->dev, 6283182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6284182999Smav "dir=0x%08x\n", 6285182999Smav gdata, gmask, gdir); 6286182999Smav ); 6287182999Smav hdac_command(sc, 6288182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6289182999Smav gmask), cad); 6290182999Smav hdac_command(sc, 6291182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6292182999Smav gdir), cad); 6293182999Smav hdac_command(sc, 6294182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6295182999Smav gdata), cad); 6296162922Sariff } 6297162922Sariff} 6298162922Sariff 6299162922Sariffstatic void 6300182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6301182999Smav{ 6302182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6303182999Smav nid_t cad = devinfo->codec->cad; 6304182999Smav int i; 6305182999Smav 6306182999Smav hdac_command(sc, 6307182999Smav HDA_CMD_SET_POWER_STATE(cad, 6308182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6309182999Smav cad); 6310182999Smav DELAY(100); 6311182999Smav 6312182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6313182999Smav hdac_command(sc, 6314182999Smav HDA_CMD_SET_POWER_STATE(cad, 6315182999Smav i, HDA_CMD_POWER_STATE_D0), 6316182999Smav cad); 6317182999Smav } 6318182999Smav DELAY(1000); 6319182999Smav} 6320182999Smav 6321162922Sariffstatic int 6322182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6323162922Sariff{ 6324182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6325182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6326162922Sariff struct hdac_widget *w; 6327182999Smav uint32_t cap, fmtcap, pcmcap; 6328182999Smav int i, j, ret, max; 6329162922Sariff 6330162922Sariff ch->caps = hdac_caps; 6331162922Sariff ch->caps.fmtlist = ch->fmtlist; 6332162922Sariff ch->bit16 = 1; 6333162922Sariff ch->bit32 = 0; 6334162922Sariff ch->pcmrates[0] = 48000; 6335162922Sariff ch->pcmrates[1] = 0; 6336162922Sariff 6337162922Sariff ret = 0; 6338162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6339162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6340162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 6341162922Sariff 6342182999Smav for (i = 0; i < 16 && ret < max; i++) { 6343182999Smav /* Check as is correct */ 6344182999Smav if (ch->as < 0) 6345182999Smav break; 6346182999Smav /* Cound only present DACs */ 6347182999Smav if (as[ch->as].dacs[i] <= 0) 6348162922Sariff continue; 6349182999Smav /* Ignore duplicates */ 6350182999Smav for (j = 0; j < ret; j++) { 6351182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6352182999Smav break; 6353182999Smav } 6354182999Smav if (j < ret) 6355162922Sariff continue; 6356182999Smav 6357182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6358182999Smav if (w == NULL || w->enable == 0) 6359182999Smav continue; 6360182999Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6361182999Smav continue; 6362162922Sariff cap = w->param.supp_stream_formats; 6363182999Smav /*if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 6364162922Sariff }*/ 6365182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6366182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6367162922Sariff continue; 6368182999Smav /* Many codec does not declare AC3 support on SPDIF. 6369182999Smav I don't beleave that they doesn't support it! */ 6370182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6371182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6372164614Sariff if (ret == 0) { 6373182999Smav fmtcap = cap; 6374164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6375164614Sariff } else { 6376182999Smav fmtcap &= cap; 6377164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6378164614Sariff } 6379182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6380162922Sariff } 6381162922Sariff ch->io[ret] = -1; 6382162922Sariff 6383162922Sariff ch->supp_stream_formats = fmtcap; 6384162922Sariff ch->supp_pcm_size_rate = pcmcap; 6385162922Sariff 6386162922Sariff /* 6387162922Sariff * 8bit = 0 6388162922Sariff * 16bit = 1 6389162922Sariff * 20bit = 2 6390162922Sariff * 24bit = 3 6391162922Sariff * 32bit = 4 6392162922Sariff */ 6393162922Sariff if (ret > 0) { 6394162922Sariff i = 0; 6395182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6396182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6397182999Smav ch->bit16 = 1; 6398182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6399182999Smav ch->bit16 = 0; 6400182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6401182999Smav ch->bit32 = 4; 6402182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6403182999Smav ch->bit32 = 3; 6404182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6405182999Smav ch->bit32 = 2; 6406182999Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 6407182999Smav ch->fmtlist[i++] = AFMT_S16_LE; 6408182999Smav ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 6409182999Smav if (ch->bit32 > 0) { 6410182999Smav if (!(devinfo->function.audio.quirks & 6411182999Smav HDA_QUIRK_FORCESTEREO)) 6412182999Smav ch->fmtlist[i++] = AFMT_S32_LE; 6413182999Smav ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 6414182999Smav } 6415162922Sariff } 6416182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6417182999Smav ch->fmtlist[i++] = AFMT_AC3; 6418182999Smav } 6419162922Sariff ch->fmtlist[i] = 0; 6420162922Sariff i = 0; 6421182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6422162922Sariff ch->pcmrates[i++] = 8000; 6423182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6424162922Sariff ch->pcmrates[i++] = 11025; 6425182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6426162922Sariff ch->pcmrates[i++] = 16000; 6427182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6428162922Sariff ch->pcmrates[i++] = 22050; 6429182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6430162922Sariff ch->pcmrates[i++] = 32000; 6431182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6432162922Sariff ch->pcmrates[i++] = 44100; 6433182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6434162922Sariff ch->pcmrates[i++] = 48000; 6435182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6436162922Sariff ch->pcmrates[i++] = 88200; 6437182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6438162922Sariff ch->pcmrates[i++] = 96000; 6439182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6440162922Sariff ch->pcmrates[i++] = 176400; 6441182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6442162922Sariff ch->pcmrates[i++] = 192000; 6443182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6444162922Sariff ch->pcmrates[i] = 0; 6445162922Sariff if (i > 0) { 6446162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6447162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6448162922Sariff } 6449162922Sariff } 6450162922Sariff 6451162922Sariff return (ret); 6452162922Sariff} 6453162922Sariff 6454162922Sariffstatic void 6455185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6456185225Smav{ 6457185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6458185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6459185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6460185225Smav 6461185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6462185225Smav if (as[i].enable == 0) 6463185225Smav continue; 6464185225Smav if (as[i].dir == HDA_CTL_IN) { 6465185225Smav if (as[i].digital) 6466185225Smav drdev++; 6467185225Smav else 6468185225Smav ardev++; 6469185225Smav } else { 6470185225Smav if (as[i].digital) 6471185225Smav dpdev++; 6472185225Smav else 6473185225Smav apdev++; 6474185225Smav } 6475185225Smav } 6476185225Smav devinfo->function.audio.num_devs = 6477185225Smav max(ardev, apdev) + max(drdev, dpdev); 6478185225Smav devinfo->function.audio.devs = 6479185225Smav (struct hdac_pcm_devinfo *)malloc( 6480185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6481185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6482185225Smav if (devinfo->function.audio.devs == NULL) { 6483185225Smav device_printf(sc->dev, 6484185225Smav "Unable to allocate memory for devices\n"); 6485185225Smav return; 6486185225Smav } 6487185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6488185225Smav devinfo->function.audio.devs[i].index = i; 6489185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6490185225Smav devinfo->function.audio.devs[i].play = -1; 6491185225Smav devinfo->function.audio.devs[i].rec = -1; 6492185225Smav devinfo->function.audio.devs[i].digital = 2; 6493185225Smav } 6494185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6495185225Smav if (as[i].enable == 0) 6496185225Smav continue; 6497185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6498185225Smav if (devinfo->function.audio.devs[j].digital != 2 && 6499185225Smav devinfo->function.audio.devs[j].digital != 6500185225Smav as[i].digital) 6501185225Smav continue; 6502185225Smav if (as[i].dir == HDA_CTL_IN) { 6503185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6504185225Smav continue; 6505185225Smav devinfo->function.audio.devs[j].rec 6506185225Smav = as[i].chan; 6507185225Smav } else { 6508185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6509185225Smav continue; 6510185225Smav devinfo->function.audio.devs[j].play 6511185225Smav = as[i].chan; 6512185225Smav } 6513185225Smav sc->chans[as[i].chan].pdevinfo = 6514185225Smav &devinfo->function.audio.devs[j]; 6515185225Smav devinfo->function.audio.devs[j].digital = 6516185225Smav as[i].digital; 6517185225Smav break; 6518185225Smav } 6519185225Smav } 6520185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6521185225Smav struct hdac_pcm_devinfo *pdevinfo = 6522185225Smav &devinfo->function.audio.devs[i]; 6523185225Smav pdevinfo->dev = 6524185225Smav device_add_child(sc->dev, "pcm", -1); 6525185225Smav device_set_ivars(pdevinfo->dev, 6526185225Smav (void *)pdevinfo); 6527185225Smav } 6528185225Smav} 6529185225Smav 6530185225Smavstatic void 6531182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6532162922Sariff{ 6533182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6534162922Sariff struct hdac_audio_ctl *ctl; 6535162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6536182999Smav char buf[64]; 6537182999Smav int i, j, printed; 6538162922Sariff 6539162922Sariff if (flag == 0) { 6540182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6541162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6542182999Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN | 6543182999Smav SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6544162922Sariff } 6545162922Sariff 6546182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6547182999Smav if ((flag & (1 << j)) == 0) 6548162922Sariff continue; 6549182999Smav i = 0; 6550182999Smav printed = 0; 6551182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6552182999Smav if (ctl->enable == 0 || 6553182999Smav ctl->widget->enable == 0) 6554182999Smav continue; 6555182999Smav if (!((pdevinfo->play >= 0 && 6556182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6557182999Smav (pdevinfo->rec >= 0 && 6558182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6559182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6560182999Smav continue; 6561182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6562182999Smav continue; 6563182999Smav 6564182999Smav if (printed == 0) { 6565182999Smav device_printf(pdevinfo->dev, "\n"); 6566182999Smav if (banner != NULL) { 6567182999Smav device_printf(pdevinfo->dev, "%s", banner); 6568182999Smav } else { 6569182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6570182999Smav } 6571182999Smav printf(" (OSS: %s)\n", 6572182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6573182999Smav buf, sizeof(buf))); 6574182999Smav device_printf(pdevinfo->dev, " |\n"); 6575182999Smav printed = 1; 6576162922Sariff } 6577182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6578182999Smav ctl->widget->nid, 6579182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6580182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6581182999Smav printf(" %2d): ", ctl->index); 6582182999Smav else 6583182999Smav printf("): "); 6584182999Smav if (ctl->step > 0) { 6585182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6586182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6587182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6588182999Smav ctl->step + 1, 6589182999Smav ctl->mute?" + mute":""); 6590182999Smav } else 6591182999Smav printf("%s\n", ctl->mute?"mute":""); 6592162922Sariff } 6593162922Sariff } 6594162922Sariff} 6595162922Sariff 6596162922Sariffstatic void 6597182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6598162922Sariff{ 6599162922Sariff uint32_t cap; 6600162922Sariff 6601162922Sariff cap = fcap; 6602162922Sariff if (cap != 0) { 6603182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6604183097Smav device_printf(dev, " "); 6605162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6606162922Sariff printf(" AC3"); 6607162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6608162922Sariff printf(" FLOAT32"); 6609162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6610162922Sariff printf(" PCM"); 6611162922Sariff printf("\n"); 6612162922Sariff } 6613162922Sariff cap = pcmcap; 6614162922Sariff if (cap != 0) { 6615182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6616183097Smav device_printf(dev, " "); 6617162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6618162922Sariff printf(" 8"); 6619162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6620162922Sariff printf(" 16"); 6621162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6622162922Sariff printf(" 20"); 6623162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6624162922Sariff printf(" 24"); 6625162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6626162922Sariff printf(" 32"); 6627183097Smav printf(" bits,"); 6628162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6629162922Sariff printf(" 8"); 6630162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6631162922Sariff printf(" 11"); 6632162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6633162922Sariff printf(" 16"); 6634162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6635162922Sariff printf(" 22"); 6636162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6637162922Sariff printf(" 32"); 6638162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6639162922Sariff printf(" 44"); 6640162922Sariff printf(" 48"); 6641162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6642162922Sariff printf(" 88"); 6643162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6644162922Sariff printf(" 96"); 6645162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6646162922Sariff printf(" 176"); 6647162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6648162922Sariff printf(" 192"); 6649183097Smav printf(" KHz\n"); 6650162922Sariff } 6651162922Sariff} 6652162922Sariff 6653162922Sariffstatic void 6654162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6655162922Sariff{ 6656183097Smav uint32_t pincap; 6657162922Sariff 6658162922Sariff pincap = w->wclass.pin.cap; 6659162922Sariff 6660162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6661162922Sariff device_printf(sc->dev, " "); 6662162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6663162922Sariff printf(" ISC"); 6664162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6665162922Sariff printf(" TRQD"); 6666162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6667162922Sariff printf(" PDC"); 6668162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6669162922Sariff printf(" HP"); 6670162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6671162922Sariff printf(" OUT"); 6672162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6673162922Sariff printf(" IN"); 6674162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6675162922Sariff printf(" BAL"); 6676165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6677165069Sariff printf(" VREF["); 6678165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6679165069Sariff printf(" 50"); 6680165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6681165069Sariff printf(" 80"); 6682165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6683165069Sariff printf(" 100"); 6684165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6685165069Sariff printf(" GROUND"); 6686165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6687165069Sariff printf(" HIZ"); 6688165069Sariff printf(" ]"); 6689165069Sariff } 6690162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6691162922Sariff printf(" EAPD"); 6692162922Sariff printf("\n"); 6693162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6694162922Sariff w->wclass.pin.config); 6695162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6696162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6697162922Sariff printf(" HP"); 6698162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6699162922Sariff printf(" IN"); 6700162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6701162922Sariff printf(" OUT"); 6702182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6703182999Smav printf(" VREFs"); 6704162922Sariff printf("\n"); 6705162922Sariff} 6706162922Sariff 6707162922Sariffstatic void 6708182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6709182999Smav{ 6710182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6711182999Smav 6712183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6713182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6714182999Smav w->nid, conf, 6715182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6716182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6717182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6718182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6719182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6720182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6721182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6722182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6723182999Smav (w->enable == 0)?" [DISABLED]":""); 6724182999Smav} 6725182999Smav 6726182999Smavstatic void 6727182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6728182999Smav{ 6729182999Smav struct hdac_widget *w; 6730182999Smav int i; 6731182999Smav 6732182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6733182999Smav w = hdac_widget_get(devinfo, i); 6734182999Smav if (w == NULL) 6735182999Smav continue; 6736182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6737182999Smav continue; 6738182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6739182999Smav } 6740182999Smav} 6741182999Smav 6742182999Smavstatic void 6743162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6744162922Sariff{ 6745163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6746162922Sariff device_printf(sc->dev, " " 6747162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6748162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6749162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6750162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6751162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6752162922Sariff} 6753162922Sariff 6754162922Sariffstatic void 6755162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6756162922Sariff{ 6757162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6758182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6759162922Sariff struct hdac_widget *w, *cw; 6760182999Smav char buf[64]; 6761162922Sariff int i, j; 6762162922Sariff 6763162922Sariff device_printf(sc->dev, "\n"); 6764162922Sariff device_printf(sc->dev, "Default Parameter\n"); 6765162922Sariff device_printf(sc->dev, "-----------------\n"); 6766182999Smav hdac_dump_audio_formats(sc->dev, 6767162922Sariff devinfo->function.audio.supp_stream_formats, 6768162922Sariff devinfo->function.audio.supp_pcm_size_rate); 6769162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 6770162922Sariff devinfo->function.audio.inamp_cap); 6771162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 6772162922Sariff devinfo->function.audio.outamp_cap); 6773162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6774162922Sariff w = hdac_widget_get(devinfo, i); 6775162922Sariff if (w == NULL) { 6776162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 6777162922Sariff continue; 6778162922Sariff } 6779162922Sariff device_printf(sc->dev, "\n"); 6780183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 6781162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 6782183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 6783183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 6784162922Sariff w->param.widget_cap); 6785183097Smav if (w->param.widget_cap & 0x0ee1) { 6786183097Smav device_printf(sc->dev, " "); 6787183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 6788183097Smav printf(" LRSWAP"); 6789183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 6790183097Smav printf(" PWR"); 6791183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6792183097Smav printf(" DIGITAL"); 6793183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 6794183097Smav printf(" UNSOL"); 6795183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 6796183097Smav printf(" PROC"); 6797183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 6798183097Smav printf(" STRIPE"); 6799183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6800183097Smav printf(" STEREO"); 6801183097Smav printf("\n"); 6802183097Smav } 6803183097Smav if (w->bindas != -1) { 6804183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 6805183097Smav w->bindas, w->bindseqmask); 6806183097Smav } 6807183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 6808183097Smav device_printf(sc->dev, " OSS: %s", 6809183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 6810183097Smav if (w->ossdev >= 0) 6811183097Smav printf(" (%s)", ossname[w->ossdev]); 6812183097Smav printf("\n"); 6813183097Smav } 6814162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6815162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6816182999Smav hdac_dump_audio_formats(sc->dev, 6817162922Sariff w->param.supp_stream_formats, 6818162922Sariff w->param.supp_pcm_size_rate); 6819162922Sariff } else if (w->type == 6820162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6821162922Sariff hdac_dump_pin(sc, w); 6822162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 6823162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 6824162922Sariff w->param.eapdbtl); 6825163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 6826163057Sariff w->param.outamp_cap != 0) 6827162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 6828163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 6829163057Sariff w->param.inamp_cap != 0) 6830162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 6831183097Smav if (w->nconns > 0) { 6832183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 6833182999Smav device_printf(sc->dev, " |\n"); 6834183097Smav } 6835162922Sariff for (j = 0; j < w->nconns; j++) { 6836162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 6837182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 6838182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 6839162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 6840162922Sariff if (cw == NULL) 6841162922Sariff printf(" [UNKNOWN]"); 6842162922Sariff else if (cw->enable == 0) 6843162922Sariff printf(" [DISABLED]"); 6844162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 6845162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 6846162922Sariff printf(" (selected)"); 6847162922Sariff printf("\n"); 6848162922Sariff } 6849162922Sariff } 6850162922Sariff 6851162922Sariff} 6852162922Sariff 6853182999Smavstatic void 6854182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 6855163057Sariff{ 6856182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6857163057Sariff struct hdac_widget *w, *cw; 6858182999Smav char buf[64]; 6859182999Smav int i, printed = 0; 6860163057Sariff 6861163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 6862182999Smav return; 6863163057Sariff 6864163057Sariff w = hdac_widget_get(devinfo, nid); 6865182999Smav if (w == NULL || w->enable == 0) 6866182999Smav return; 6867163057Sariff 6868182999Smav if (depth == 0) 6869182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 6870182999Smav else 6871182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 6872182999Smav printf("nid=%d [%s]", w->nid, w->name); 6873163057Sariff 6874182999Smav if (depth > 0) { 6875182999Smav if (w->ossmask == 0) { 6876182999Smav printf("\n"); 6877182999Smav return; 6878163057Sariff } 6879182999Smav printf(" [src: %s]", 6880182999Smav hdac_audio_ctl_ossmixer_mask2allname( 6881182999Smav w->ossmask, buf, sizeof(buf))); 6882182999Smav if (w->ossdev >= 0) { 6883182999Smav printf("\n"); 6884182999Smav return; 6885182999Smav } 6886163057Sariff } 6887182999Smav printf("\n"); 6888182999Smav 6889182999Smav for (i = 0; i < w->nconns; i++) { 6890182999Smav if (w->connsenable[i] == 0) 6891182999Smav continue; 6892182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 6893182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 6894182999Smav continue; 6895182999Smav if (printed == 0) { 6896182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 6897182999Smav printed = 1; 6898182999Smav } 6899182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 6900182999Smav } 6901163057Sariff 6902163057Sariff} 6903163057Sariff 6904162922Sariffstatic void 6905182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 6906162922Sariff{ 6907182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6908182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6909163057Sariff struct hdac_widget *w; 6910163057Sariff int i, printed = 0; 6911163057Sariff 6912182999Smav if (pdevinfo->play < 0) 6913182999Smav return; 6914182999Smav 6915163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6916163057Sariff w = hdac_widget_get(devinfo, i); 6917163057Sariff if (w == NULL || w->enable == 0) 6918163057Sariff continue; 6919182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6920163057Sariff continue; 6921182999Smav if (w->bindas != sc->chans[pdevinfo->play].as) 6922182999Smav continue; 6923163057Sariff if (printed == 0) { 6924163057Sariff printed = 1; 6925182999Smav device_printf(pdevinfo->dev, "\n"); 6926182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6927163057Sariff } 6928182999Smav device_printf(pdevinfo->dev, "\n"); 6929182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6930163057Sariff } 6931162922Sariff} 6932162922Sariff 6933162922Sariffstatic void 6934182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 6935162922Sariff{ 6936182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6937162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6938182999Smav struct hdac_widget *w; 6939182999Smav int i; 6940162922Sariff int printed = 0; 6941162922Sariff 6942182999Smav if (pdevinfo->rec < 0) 6943182999Smav return; 6944182999Smav 6945162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6946162922Sariff w = hdac_widget_get(devinfo, i); 6947162922Sariff if (w == NULL || w->enable == 0) 6948162922Sariff continue; 6949182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 6950162922Sariff continue; 6951182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 6952182999Smav continue; 6953162922Sariff if (printed == 0) { 6954162922Sariff printed = 1; 6955182999Smav device_printf(pdevinfo->dev, "\n"); 6956182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6957162922Sariff } 6958182999Smav device_printf(pdevinfo->dev, "\n"); 6959182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6960182999Smav } 6961182999Smav} 6962182999Smav 6963182999Smavstatic void 6964182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 6965182999Smav{ 6966182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6967182999Smav struct hdac_widget *w; 6968182999Smav int i; 6969182999Smav int printed = 0; 6970182999Smav 6971182999Smav if (pdevinfo->index != 0) 6972182999Smav return; 6973182999Smav 6974182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6975182999Smav w = hdac_widget_get(devinfo, i); 6976182999Smav if (w == NULL || w->enable == 0) 6977182999Smav continue; 6978182999Smav if ((w->pflags & HDA_ADC_MONITOR) == 0) 6979182999Smav continue; 6980182999Smav if (printed == 0) { 6981182999Smav printed = 1; 6982182999Smav device_printf(pdevinfo->dev, "\n"); 6983182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 6984162922Sariff } 6985182999Smav device_printf(pdevinfo->dev, "\n"); 6986182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6987162922Sariff } 6988162922Sariff} 6989162922Sariff 6990162922Sariffstatic void 6991182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 6992162922Sariff{ 6993182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 6994162922Sariff nid_t *nids; 6995182999Smav int i; 6996162922Sariff 6997182999Smav if (pdevinfo->play >= 0) { 6998182999Smav i = pdevinfo->play; 6999182999Smav device_printf(pdevinfo->dev, "\n"); 7000182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7001182999Smav device_printf(pdevinfo->dev, "\n"); 7002182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7003182999Smav sc->chans[i].supp_pcm_size_rate); 7004182999Smav device_printf(pdevinfo->dev, " DAC:"); 7005182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7006162922Sariff printf(" %d", *nids); 7007162922Sariff printf("\n"); 7008162922Sariff } 7009182999Smav if (pdevinfo->rec >= 0) { 7010182999Smav i = pdevinfo->rec; 7011182999Smav device_printf(pdevinfo->dev, "\n"); 7012182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7013182999Smav device_printf(pdevinfo->dev, "\n"); 7014182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7015182999Smav sc->chans[i].supp_pcm_size_rate); 7016182999Smav device_printf(pdevinfo->dev, " ADC:"); 7017182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7018162922Sariff printf(" %d", *nids); 7019162922Sariff printf("\n"); 7020162922Sariff } 7021162922Sariff} 7022162922Sariff 7023162922Sariffstatic void 7024163057Sariffhdac_release_resources(struct hdac_softc *sc) 7025163057Sariff{ 7026182999Smav int i, j; 7027163057Sariff 7028163057Sariff if (sc == NULL) 7029163057Sariff return; 7030163057Sariff 7031163057Sariff hdac_lock(sc); 7032169277Sariff sc->polling = 0; 7033169277Sariff sc->poll_ival = 0; 7034170721Sariff callout_stop(&sc->poll_hda); 7035169277Sariff callout_stop(&sc->poll_hdac); 7036169277Sariff callout_stop(&sc->poll_jack); 7037182999Smav hdac_reset(sc, 0); 7038163057Sariff hdac_unlock(sc); 7039171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7040170721Sariff callout_drain(&sc->poll_hda); 7041169277Sariff callout_drain(&sc->poll_hdac); 7042169277Sariff callout_drain(&sc->poll_jack); 7043163057Sariff 7044169277Sariff hdac_irq_free(sc); 7045169277Sariff 7046182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7047182999Smav if (sc->codecs[i] == NULL) 7048163057Sariff continue; 7049182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7050182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7051182999Smav if (sc->codecs[i]->fgs[j].node_type == 7052182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7053182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7054182999Smav M_HDAC); 7055182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7056182999Smav M_HDAC); 7057182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7058182999Smav M_HDAC); 7059182999Smav } 7060182999Smav } 7061182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7062182999Smav free(sc->codecs[i], M_HDAC); 7063163057Sariff sc->codecs[i] = NULL; 7064163057Sariff } 7065163057Sariff 7066169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7067169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7068169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7069182999Smav for (i = 0; i < sc->num_chans; i++) { 7070182999Smav if (sc->chans[i].blkcnt > 0) 7071182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7072182999Smav } 7073182999Smav free(sc->chans, M_HDAC); 7074167702Sariff if (sc->chan_dmat != NULL) { 7075167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7076167702Sariff sc->chan_dmat = NULL; 7077167702Sariff } 7078163057Sariff hdac_mem_free(sc); 7079169277Sariff snd_mtxfree(sc->lock); 7080163057Sariff} 7081163057Sariff 7082163057Sariff/* This function surely going to make its way into upper level someday. */ 7083163057Sariffstatic void 7084163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7085163057Sariff{ 7086163057Sariff const char *res = NULL; 7087163057Sariff int i = 0, j, k, len, inv; 7088163057Sariff 7089163057Sariff if (on != NULL) 7090163057Sariff *on = 0; 7091163057Sariff if (off != NULL) 7092163057Sariff *off = 0; 7093163057Sariff if (sc == NULL) 7094163057Sariff return; 7095163057Sariff if (resource_string_value(device_get_name(sc->dev), 7096163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7097163057Sariff return; 7098163057Sariff if (!(res != NULL && strlen(res) > 0)) 7099163057Sariff return; 7100163057Sariff HDA_BOOTVERBOSE( 7101182999Smav device_printf(sc->dev, "HDA Config:"); 7102163057Sariff ); 7103163057Sariff for (;;) { 7104163057Sariff while (res[i] != '\0' && 7105163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7106163057Sariff i++; 7107163057Sariff if (res[i] == '\0') { 7108163057Sariff HDA_BOOTVERBOSE( 7109163057Sariff printf("\n"); 7110163057Sariff ); 7111163057Sariff return; 7112163057Sariff } 7113163057Sariff j = i; 7114163057Sariff while (res[j] != '\0' && 7115163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7116163057Sariff j++; 7117163057Sariff len = j - i; 7118163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7119163057Sariff inv = 2; 7120163057Sariff else 7121163057Sariff inv = 0; 7122163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7123163057Sariff if (strncmp(res + i + inv, 7124163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7125163057Sariff continue; 7126163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7127187944Smav continue; 7128163057Sariff HDA_BOOTVERBOSE( 7129163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7130163057Sariff hdac_quirks_tab[k].key); 7131163057Sariff ); 7132163057Sariff if (inv == 0 && on != NULL) 7133163057Sariff *on |= hdac_quirks_tab[k].value; 7134163057Sariff else if (inv != 0 && off != NULL) 7135163057Sariff *off |= hdac_quirks_tab[k].value; 7136163057Sariff break; 7137163057Sariff } 7138163057Sariff i = j; 7139163057Sariff } 7140163057Sariff} 7141163057Sariff 7142164614Sariff#ifdef SND_DYNSYSCTL 7143164614Sariffstatic int 7144164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7145164614Sariff{ 7146164614Sariff struct hdac_softc *sc; 7147164614Sariff device_t dev; 7148164614Sariff uint32_t ctl; 7149164614Sariff int err, val; 7150164614Sariff 7151164614Sariff dev = oidp->oid_arg1; 7152182999Smav sc = device_get_softc(dev); 7153182999Smav if (sc == NULL) 7154164614Sariff return (EINVAL); 7155164614Sariff hdac_lock(sc); 7156164614Sariff val = sc->polling; 7157164614Sariff hdac_unlock(sc); 7158170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7159164614Sariff 7160169277Sariff if (err != 0 || req->newptr == NULL) 7161164614Sariff return (err); 7162164614Sariff if (val < 0 || val > 1) 7163164614Sariff return (EINVAL); 7164164614Sariff 7165164614Sariff hdac_lock(sc); 7166164614Sariff if (val != sc->polling) { 7167182999Smav if (val == 0) { 7168182999Smav callout_stop(&sc->poll_hda); 7169164614Sariff callout_stop(&sc->poll_hdac); 7170169277Sariff hdac_unlock(sc); 7171182999Smav callout_drain(&sc->poll_hda); 7172169277Sariff callout_drain(&sc->poll_hdac); 7173169277Sariff hdac_lock(sc); 7174164614Sariff sc->polling = 0; 7175182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7176182999Smav ctl |= HDAC_INTCTL_GIE; 7177182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7178164614Sariff } else { 7179182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7180182999Smav ctl &= ~HDAC_INTCTL_GIE; 7181182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7182171141Sariff hdac_unlock(sc); 7183171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7184171141Sariff hdac_lock(sc); 7185164614Sariff sc->polling = 1; 7186182999Smav hdac_poll_reinit(sc); 7187182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7188164614Sariff } 7189164614Sariff } 7190164614Sariff hdac_unlock(sc); 7191164614Sariff 7192164614Sariff return (err); 7193164614Sariff} 7194169277Sariff 7195169277Sariffstatic int 7196169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7197169277Sariff{ 7198169277Sariff struct hdac_softc *sc; 7199169277Sariff device_t dev; 7200169277Sariff int err, val; 7201169277Sariff 7202169277Sariff dev = oidp->oid_arg1; 7203182999Smav sc = device_get_softc(dev); 7204182999Smav if (sc == NULL) 7205169277Sariff return (EINVAL); 7206169277Sariff hdac_lock(sc); 7207169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7208169277Sariff hdac_unlock(sc); 7209170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7210169277Sariff 7211169277Sariff if (err != 0 || req->newptr == NULL) 7212169277Sariff return (err); 7213169277Sariff 7214169277Sariff if (val < 1) 7215169277Sariff val = 1; 7216169277Sariff if (val > 5000) 7217169277Sariff val = 5000; 7218169277Sariff val = ((uint64_t)val * hz) / 1000; 7219169277Sariff if (val < 1) 7220169277Sariff val = 1; 7221169277Sariff if (val > (hz * 5)) 7222169277Sariff val = hz * 5; 7223169277Sariff 7224169277Sariff hdac_lock(sc); 7225169277Sariff sc->poll_ival = val; 7226169277Sariff hdac_unlock(sc); 7227169277Sariff 7228169277Sariff return (err); 7229169277Sariff} 7230169277Sariff 7231169277Sariffstatic int 7232171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7233169277Sariff{ 7234169277Sariff struct hdac_softc *sc; 7235182999Smav struct hdac_codec *codec; 7236169277Sariff struct hdac_devinfo *devinfo; 7237169277Sariff struct hdac_widget *w; 7238169277Sariff device_t dev; 7239182999Smav uint32_t res, pincap, delay; 7240182999Smav int codec_index, fg_index; 7241169277Sariff int i, err, val; 7242169277Sariff nid_t cad; 7243169277Sariff 7244169277Sariff dev = oidp->oid_arg1; 7245182999Smav sc = device_get_softc(dev); 7246182999Smav if (sc == NULL) 7247169277Sariff return (EINVAL); 7248169277Sariff val = 0; 7249170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7250169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7251169277Sariff return (err); 7252182999Smav 7253182999Smav /* XXX: Temporary. For debugging. */ 7254182999Smav if (val == 100) { 7255182999Smav hdac_suspend(dev); 7256182999Smav return (0); 7257182999Smav } else if (val == 101) { 7258182999Smav hdac_resume(dev); 7259182999Smav return (0); 7260182999Smav } 7261182999Smav 7262169277Sariff hdac_lock(sc); 7263182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7264182999Smav codec = sc->codecs[codec_index]; 7265182999Smav if (codec == NULL) 7266169277Sariff continue; 7267182999Smav cad = codec->cad; 7268182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7269182999Smav devinfo = &codec->fgs[fg_index]; 7270182999Smav if (devinfo->node_type != 7271182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7272182999Smav continue; 7273182999Smav 7274182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7275182999Smav codec_index, devinfo->nid); 7276182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7277182999Smav w = hdac_widget_get(devinfo, i); 7278182999Smav if (w == NULL || w->type != 7279182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7280182999Smav continue; 7281182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7282182999Smav pincap = w->wclass.pin.cap; 7283182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7284182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7285182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7286182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7287182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7288182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7289182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7290182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7291182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7292182999Smav delay = 0; 7293182999Smav hdac_command(sc, 7294182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7295182999Smav do { 7296182999Smav res = hdac_command(sc, 7297182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7298182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7299182999Smav break; 7300182999Smav DELAY(10); 7301182999Smav } while (++delay < 10000); 7302182999Smav } else { 7303182999Smav delay = 0; 7304182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7305182999Smav w->nid), cad); 7306182999Smav } 7307182999Smav printf(" Sense: 0x%08x", res); 7308182999Smav if (delay > 0) 7309182999Smav printf(" delay %dus", delay * 10); 7310182999Smav } 7311182999Smav printf("\n"); 7312182999Smav } 7313182999Smav device_printf(dev, 7314182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7315182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7316182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7317182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7318182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7319182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7320182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7321182999Smav device_printf(dev, " GPI:"); 7322171141Sariff res = hdac_command(sc, 7323182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7324182999Smav printf(" data=0x%08x", res); 7325182999Smav res = hdac_command(sc, 7326182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7327182999Smav cad); 7328182999Smav printf(" wake=0x%08x", res); 7329182999Smav res = hdac_command(sc, 7330182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7331182999Smav cad); 7332182999Smav printf(" unsol=0x%08x", res); 7333182999Smav res = hdac_command(sc, 7334182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7335182999Smav printf(" sticky=0x%08x\n", res); 7336182999Smav } 7337182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7338182999Smav device_printf(dev, " GPO:"); 7339182999Smav res = hdac_command(sc, 7340182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7341182999Smav printf(" data=0x%08x\n", res); 7342182999Smav } 7343182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7344182999Smav device_printf(dev, "GPIO:"); 7345182999Smav res = hdac_command(sc, 7346182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7347182999Smav printf(" data=0x%08x", res); 7348182999Smav res = hdac_command(sc, 7349182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7350182999Smav printf(" enable=0x%08x", res); 7351182999Smav res = hdac_command(sc, 7352182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7353182999Smav printf(" direction=0x%08x\n", res); 7354182999Smav res = hdac_command(sc, 7355182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7356182999Smav device_printf(dev, " wake=0x%08x", res); 7357182999Smav res = hdac_command(sc, 7358182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7359182999Smav cad); 7360182999Smav printf(" unsol=0x%08x", res); 7361182999Smav res = hdac_command(sc, 7362182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7363182999Smav printf(" sticky=0x%08x\n", res); 7364182999Smav } 7365171141Sariff } 7366169277Sariff } 7367169277Sariff hdac_unlock(sc); 7368169277Sariff return (0); 7369169277Sariff} 7370164614Sariff#endif 7371164614Sariff 7372163057Sariffstatic void 7373162922Sariffhdac_attach2(void *arg) 7374162922Sariff{ 7375182999Smav struct hdac_codec *codec; 7376162922Sariff struct hdac_softc *sc; 7377162922Sariff struct hdac_audio_ctl *ctl; 7378163057Sariff uint32_t quirks_on, quirks_off; 7379182999Smav int codec_index, fg_index; 7380185225Smav int i, dmaalloc = 0; 7381182999Smav struct hdac_devinfo *devinfo; 7382162922Sariff 7383162922Sariff sc = (struct hdac_softc *)arg; 7384162922Sariff 7385163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7386162922Sariff 7387183097Smav HDA_BOOTHVERBOSE( 7388182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7389163057Sariff quirks_on, quirks_off); 7390163057Sariff ); 7391163057Sariff 7392162922Sariff hdac_lock(sc); 7393162922Sariff 7394162922Sariff /* Remove ourselves from the config hooks */ 7395162922Sariff if (sc->intrhook.ich_func != NULL) { 7396162922Sariff config_intrhook_disestablish(&sc->intrhook); 7397162922Sariff sc->intrhook.ich_func = NULL; 7398162922Sariff } 7399162922Sariff 7400162922Sariff /* Start the corb and rirb engines */ 7401183097Smav HDA_BOOTHVERBOSE( 7402182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7403162922Sariff ); 7404162922Sariff hdac_corb_start(sc); 7405183097Smav HDA_BOOTHVERBOSE( 7406182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7407162922Sariff ); 7408162922Sariff hdac_rirb_start(sc); 7409162922Sariff 7410183097Smav HDA_BOOTHVERBOSE( 7411162922Sariff device_printf(sc->dev, 7412182999Smav "Enabling controller interrupt...\n"); 7413162922Sariff ); 7414182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7415182999Smav HDAC_GCTL_UNSOL); 7416182999Smav if (sc->polling == 0) { 7417164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7418164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7419182999Smav } else { 7420182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7421182999Smav } 7422162922Sariff DELAY(1000); 7423162922Sariff 7424183097Smav HDA_BOOTHVERBOSE( 7425172811Sariff device_printf(sc->dev, 7426182999Smav "Scanning HDA codecs ...\n"); 7427162922Sariff ); 7428182999Smav hdac_scan_codecs(sc); 7429182999Smav 7430182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7431182999Smav codec = sc->codecs[codec_index]; 7432182999Smav if (codec == NULL) 7433182999Smav continue; 7434182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7435182999Smav devinfo = &codec->fgs[fg_index]; 7436183019Smav HDA_BOOTVERBOSE( 7437183019Smav device_printf(sc->dev, "\n"); 7438183097Smav device_printf(sc->dev, 7439183097Smav "Processing %s FG cad=%d nid=%d...\n", 7440183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7441183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7442183097Smav "unknown", 7443183097Smav devinfo->codec->cad, devinfo->nid); 7444183019Smav ); 7445182999Smav if (devinfo->node_type != 7446182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7447183097Smav HDA_BOOTHVERBOSE( 7448182999Smav device_printf(sc->dev, 7449183097Smav "Powering down...\n"); 7450182999Smav ); 7451182999Smav hdac_command(sc, 7452182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7453182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7454182999Smav codec->cad); 7455182999Smav continue; 7456182999Smav } 7457162922Sariff 7458183097Smav HDA_BOOTHVERBOSE( 7459183097Smav device_printf(sc->dev, "Powering up...\n"); 7460182999Smav ); 7461182999Smav hdac_powerup(devinfo); 7462183097Smav HDA_BOOTHVERBOSE( 7463182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7464182999Smav ); 7465182999Smav hdac_audio_parse(devinfo); 7466183097Smav HDA_BOOTHVERBOSE( 7467182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7468182999Smav ); 7469182999Smav hdac_audio_ctl_parse(devinfo); 7470183097Smav HDA_BOOTHVERBOSE( 7471182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7472182999Smav ); 7473182999Smav hdac_vendor_patch_parse(devinfo); 7474182999Smav devinfo->function.audio.quirks |= quirks_on; 7475182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7476162922Sariff 7477183097Smav HDA_BOOTHVERBOSE( 7478182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7479182999Smav ); 7480182999Smav hdac_audio_disable_nonaudio(devinfo); 7481183097Smav HDA_BOOTHVERBOSE( 7482182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7483182999Smav ); 7484182999Smav hdac_audio_disable_useless(devinfo); 7485182999Smav HDA_BOOTVERBOSE( 7486182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7487182999Smav hdac_dump_pin_configs(devinfo); 7488183097Smav ); 7489183097Smav HDA_BOOTHVERBOSE( 7490182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7491182999Smav ); 7492182999Smav hdac_audio_as_parse(devinfo); 7493183097Smav HDA_BOOTHVERBOSE( 7494182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7495182999Smav ); 7496182999Smav hdac_audio_build_tree(devinfo); 7497183097Smav HDA_BOOTHVERBOSE( 7498182999Smav device_printf(sc->dev, "Disabling unassociated " 7499182999Smav "widgets...\n"); 7500182999Smav ); 7501182999Smav hdac_audio_disable_unas(devinfo); 7502183097Smav HDA_BOOTHVERBOSE( 7503182999Smav device_printf(sc->dev, "Disabling nonselected " 7504182999Smav "inputs...\n"); 7505182999Smav ); 7506182999Smav hdac_audio_disable_notselected(devinfo); 7507183097Smav HDA_BOOTHVERBOSE( 7508182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7509182999Smav ); 7510182999Smav hdac_audio_disable_useless(devinfo); 7511183097Smav HDA_BOOTHVERBOSE( 7512182999Smav device_printf(sc->dev, "Disabling " 7513182999Smav "crossassociatement connections...\n"); 7514182999Smav ); 7515182999Smav hdac_audio_disable_crossas(devinfo); 7516183097Smav HDA_BOOTHVERBOSE( 7517182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7518182999Smav ); 7519182999Smav hdac_audio_disable_useless(devinfo); 7520183097Smav HDA_BOOTHVERBOSE( 7521182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7522182999Smav ); 7523182999Smav hdac_audio_bind_as(devinfo); 7524183097Smav HDA_BOOTHVERBOSE( 7525182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7526182999Smav ); 7527182999Smav hdac_audio_assign_names(devinfo); 7528183097Smav HDA_BOOTHVERBOSE( 7529182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7530182999Smav ); 7531182999Smav hdac_audio_assign_mixers(devinfo); 7532183097Smav HDA_BOOTHVERBOSE( 7533182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7534182999Smav ); 7535182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7536183097Smav HDA_BOOTHVERBOSE( 7537182999Smav device_printf(sc->dev, "AFG commit...\n"); 7538182999Smav ); 7539182999Smav hdac_audio_commit(devinfo); 7540183097Smav HDA_BOOTHVERBOSE( 7541182999Smav device_printf(sc->dev, "HP switch init...\n"); 7542182999Smav ); 7543182999Smav hdac_hp_switch_init(devinfo); 7544182999Smav 7545182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7546182999Smav dmaalloc == 0) { 7547182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7548182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7549182999Smav HDA_BOOTVERBOSE( 7550182999Smav device_printf(sc->dev, "Failed to " 7551182999Smav "allocate DMA pos buffer " 7552182999Smav "(non-fatal)\n"); 7553182999Smav ); 7554182999Smav } else 7555182999Smav dmaalloc = 1; 7556182999Smav } 7557182999Smav 7558185225Smav HDA_BOOTHVERBOSE( 7559185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7560185225Smav ); 7561185225Smav hdac_create_pcms(devinfo); 7562182999Smav 7563182999Smav HDA_BOOTVERBOSE( 7564182999Smav if (devinfo->function.audio.quirks != 0) { 7565183097Smav device_printf(sc->dev, "FG config/quirks:"); 7566182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7567182999Smav if ((devinfo->function.audio.quirks & 7568182999Smav hdac_quirks_tab[i].value) == 7569182999Smav hdac_quirks_tab[i].value) 7570182999Smav printf(" %s", hdac_quirks_tab[i].key); 7571182999Smav } 7572182999Smav printf("\n"); 7573182999Smav } 7574182999Smav 7575182999Smav device_printf(sc->dev, "\n"); 7576182999Smav device_printf(sc->dev, "+-------------------+\n"); 7577182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7578182999Smav device_printf(sc->dev, "+-------------------+\n"); 7579182999Smav hdac_dump_nodes(devinfo); 7580183097Smav ); 7581182999Smav 7582183097Smav HDA_BOOTHVERBOSE( 7583182999Smav device_printf(sc->dev, "\n"); 7584182999Smav device_printf(sc->dev, "+------------------------+\n"); 7585182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7586182999Smav device_printf(sc->dev, "+------------------------+\n"); 7587182999Smav device_printf(sc->dev, "\n"); 7588182999Smav i = 0; 7589182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7590182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7591182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7592182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7593182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7594182999Smav ctl->index); 7595182999Smav if (ctl->childwidget != NULL) 7596182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7597182999Smav else 7598182999Smav printf(" "); 7599182999Smav printf(" ossmask=0x%08x\n", 7600182999Smav ctl->ossmask); 7601182999Smav device_printf(sc->dev, 7602182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7603182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7604182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7605182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7606182999Smav } 7607182999Smav ); 7608182999Smav } 7609162922Sariff } 7610182999Smav hdac_unlock(sc); 7611162922Sariff 7612163057Sariff HDA_BOOTVERBOSE( 7613182999Smav device_printf(sc->dev, "\n"); 7614162922Sariff ); 7615182999Smav 7616182999Smav bus_generic_attach(sc->dev); 7617182999Smav 7618182999Smav#ifdef SND_DYNSYSCTL 7619182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7620182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7621182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7622182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7623182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7624182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7625182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7626182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7627182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7628182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7629182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7630182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7631182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7632182999Smav#endif 7633182999Smav} 7634182999Smav 7635182999Smav/**************************************************************************** 7636182999Smav * int hdac_suspend(device_t) 7637182999Smav * 7638182999Smav * Suspend and power down HDA bus and codecs. 7639182999Smav ****************************************************************************/ 7640182999Smavstatic int 7641182999Smavhdac_suspend(device_t dev) 7642182999Smav{ 7643182999Smav struct hdac_softc *sc; 7644182999Smav struct hdac_codec *codec; 7645182999Smav struct hdac_devinfo *devinfo; 7646182999Smav int codec_index, fg_index, i; 7647182999Smav 7648183097Smav HDA_BOOTHVERBOSE( 7649182999Smav device_printf(dev, "Suspend...\n"); 7650162922Sariff ); 7651182999Smav 7652182999Smav sc = device_get_softc(dev); 7653182999Smav hdac_lock(sc); 7654182999Smav 7655183097Smav HDA_BOOTHVERBOSE( 7656182999Smav device_printf(dev, "Stop streams...\n"); 7657162922Sariff ); 7658182999Smav for (i = 0; i < sc->num_chans; i++) { 7659182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7660182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7661182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7662182999Smav } 7663182999Smav } 7664162922Sariff 7665182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7666182999Smav codec = sc->codecs[codec_index]; 7667182999Smav if (codec == NULL) 7668162922Sariff continue; 7669182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7670182999Smav devinfo = &codec->fgs[fg_index]; 7671183097Smav HDA_BOOTHVERBOSE( 7672182999Smav device_printf(dev, 7673182999Smav "Power down FG" 7674182999Smav " cad=%d nid=%d to the D3 state...\n", 7675182999Smav codec->cad, devinfo->nid); 7676182999Smav ); 7677182999Smav hdac_command(sc, 7678182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7679182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7680182999Smav codec->cad); 7681162922Sariff } 7682162922Sariff } 7683162922Sariff 7684183097Smav HDA_BOOTHVERBOSE( 7685182999Smav device_printf(dev, "Reset controller...\n"); 7686162922Sariff ); 7687182999Smav callout_stop(&sc->poll_hda); 7688182999Smav callout_stop(&sc->poll_hdac); 7689182999Smav callout_stop(&sc->poll_jack); 7690182999Smav hdac_reset(sc, 0); 7691182999Smav hdac_unlock(sc); 7692182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7693182999Smav callout_drain(&sc->poll_hda); 7694182999Smav callout_drain(&sc->poll_hdac); 7695182999Smav callout_drain(&sc->poll_jack); 7696162922Sariff 7697183097Smav HDA_BOOTHVERBOSE( 7698182999Smav device_printf(dev, "Suspend done\n"); 7699162922Sariff ); 7700182999Smav 7701182999Smav return (0); 7702182999Smav} 7703182999Smav 7704182999Smav/**************************************************************************** 7705182999Smav * int hdac_resume(device_t) 7706182999Smav * 7707182999Smav * Powerup and restore HDA bus and codecs state. 7708182999Smav ****************************************************************************/ 7709182999Smavstatic int 7710182999Smavhdac_resume(device_t dev) 7711182999Smav{ 7712182999Smav struct hdac_softc *sc; 7713182999Smav struct hdac_codec *codec; 7714182999Smav struct hdac_devinfo *devinfo; 7715182999Smav int codec_index, fg_index, i; 7716182999Smav 7717183097Smav HDA_BOOTHVERBOSE( 7718182999Smav device_printf(dev, "Resume...\n"); 7719162922Sariff ); 7720162922Sariff 7721182999Smav sc = device_get_softc(dev); 7722182999Smav hdac_lock(sc); 7723182999Smav 7724182999Smav /* Quiesce everything */ 7725183097Smav HDA_BOOTHVERBOSE( 7726182999Smav device_printf(dev, "Reset controller...\n"); 7727162922Sariff ); 7728182999Smav hdac_reset(sc, 1); 7729182999Smav 7730182999Smav /* Initialize the CORB and RIRB */ 7731182999Smav hdac_corb_init(sc); 7732182999Smav hdac_rirb_init(sc); 7733182999Smav 7734182999Smav /* Start the corb and rirb engines */ 7735183097Smav HDA_BOOTHVERBOSE( 7736182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7737162922Sariff ); 7738182999Smav hdac_corb_start(sc); 7739183097Smav HDA_BOOTHVERBOSE( 7740182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7741162922Sariff ); 7742182999Smav hdac_rirb_start(sc); 7743163057Sariff 7744183097Smav HDA_BOOTHVERBOSE( 7745182999Smav device_printf(dev, 7746182999Smav "Enabling controller interrupt...\n"); 7747162922Sariff ); 7748182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7749182999Smav HDAC_GCTL_UNSOL); 7750182999Smav if (sc->polling == 0) { 7751182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7752182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7753182999Smav } else { 7754182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7755182999Smav } 7756182999Smav DELAY(1000); 7757162922Sariff 7758182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7759182999Smav codec = sc->codecs[codec_index]; 7760182999Smav if (codec == NULL) 7761182999Smav continue; 7762182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7763182999Smav devinfo = &codec->fgs[fg_index]; 7764182999Smav if (devinfo->node_type != 7765182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7766183097Smav HDA_BOOTHVERBOSE( 7767182999Smav device_printf(dev, 7768182999Smav "Power down unsupported non-audio FG" 7769182999Smav " cad=%d nid=%d to the D3 state...\n", 7770182999Smav codec->cad, devinfo->nid); 7771182999Smav ); 7772182999Smav hdac_command(sc, 7773182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7774182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7775182999Smav codec->cad); 7776182999Smav continue; 7777182999Smav } 7778162922Sariff 7779183097Smav HDA_BOOTHVERBOSE( 7780182999Smav device_printf(dev, 7781182999Smav "Power up audio FG cad=%d nid=%d...\n", 7782182999Smav devinfo->codec->cad, devinfo->nid); 7783182999Smav ); 7784182999Smav hdac_powerup(devinfo); 7785183097Smav HDA_BOOTHVERBOSE( 7786182999Smav device_printf(dev, "AFG commit...\n"); 7787182999Smav ); 7788182999Smav hdac_audio_commit(devinfo); 7789183097Smav HDA_BOOTHVERBOSE( 7790182999Smav device_printf(dev, "HP switch init...\n"); 7791182999Smav ); 7792182999Smav hdac_hp_switch_init(devinfo); 7793182999Smav 7794182999Smav hdac_unlock(sc); 7795182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7796182999Smav struct hdac_pcm_devinfo *pdevinfo = 7797182999Smav &devinfo->function.audio.devs[i]; 7798183097Smav HDA_BOOTHVERBOSE( 7799182999Smav device_printf(pdevinfo->dev, 7800182999Smav "OSS mixer reinitialization...\n"); 7801182999Smav ); 7802182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 7803182999Smav device_printf(pdevinfo->dev, 7804182999Smav "unable to reinitialize the mixer\n"); 7805182999Smav } 7806182999Smav hdac_lock(sc); 7807182999Smav } 7808169277Sariff } 7809169277Sariff 7810183097Smav HDA_BOOTHVERBOSE( 7811182999Smav device_printf(dev, "Start streams...\n"); 7812163057Sariff ); 7813182999Smav for (i = 0; i < sc->num_chans; i++) { 7814182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 7815182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 7816182999Smav hdac_channel_start(sc, &sc->chans[i]); 7817182999Smav } 7818182999Smav } 7819162922Sariff 7820182999Smav hdac_unlock(sc); 7821182999Smav 7822183097Smav HDA_BOOTHVERBOSE( 7823182999Smav device_printf(dev, "Resume done\n"); 7824162922Sariff ); 7825164614Sariff 7826182999Smav return (0); 7827162922Sariff} 7828162922Sariff/**************************************************************************** 7829162922Sariff * int hdac_detach(device_t) 7830162922Sariff * 7831162922Sariff * Detach and free up resources utilized by the hdac device. 7832162922Sariff ****************************************************************************/ 7833162922Sariffstatic int 7834162922Sariffhdac_detach(device_t dev) 7835162922Sariff{ 7836182999Smav struct hdac_softc *sc; 7837185177Smav device_t *devlist; 7838185177Smav int i, devcount, error; 7839162922Sariff 7840185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 7841185177Smav return (error); 7842185177Smav for (i = 0; i < devcount; i++) { 7843185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 7844185178Smav free(devlist, M_TEMP); 7845185178Smav return (error); 7846185178Smav } 7847185177Smav } 7848185177Smav free(devlist, M_TEMP); 7849185177Smav 7850182999Smav sc = device_get_softc(dev); 7851163057Sariff hdac_release_resources(sc); 7852162922Sariff 7853162922Sariff return (0); 7854162922Sariff} 7855162922Sariff 7856184095Smavstatic int 7857184095Smavhdac_print_child(device_t dev, device_t child) 7858184095Smav{ 7859184095Smav struct hdac_pcm_devinfo *pdevinfo = 7860184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 7861184095Smav int retval; 7862184095Smav 7863184095Smav retval = bus_print_child_header(dev, child); 7864184095Smav retval += printf(" at cad %d nid %d", 7865184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 7866184095Smav retval += bus_print_child_footer(dev, child); 7867184095Smav 7868184095Smav return (retval); 7869184095Smav} 7870184095Smav 7871162922Sariffstatic device_method_t hdac_methods[] = { 7872162922Sariff /* device interface */ 7873162922Sariff DEVMETHOD(device_probe, hdac_probe), 7874162922Sariff DEVMETHOD(device_attach, hdac_attach), 7875162922Sariff DEVMETHOD(device_detach, hdac_detach), 7876182999Smav DEVMETHOD(device_suspend, hdac_suspend), 7877182999Smav DEVMETHOD(device_resume, hdac_resume), 7878184095Smav /* Bus interface */ 7879184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 7880162922Sariff { 0, 0 } 7881162922Sariff}; 7882162922Sariff 7883162922Sariffstatic driver_t hdac_driver = { 7884182999Smav "hdac", 7885162922Sariff hdac_methods, 7886182999Smav sizeof(struct hdac_softc), 7887162922Sariff}; 7888162922Sariff 7889182999Smavstatic devclass_t hdac_devclass; 7890182999Smav 7891182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 7892162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 7893162922SariffMODULE_VERSION(snd_hda, 1); 7894182999Smav 7895182999Smavstatic int 7896182999Smavhdac_pcm_probe(device_t dev) 7897182999Smav{ 7898182999Smav struct hdac_pcm_devinfo *pdevinfo = 7899182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7900182999Smav char buf[128]; 7901182999Smav 7902185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 7903182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 7904185225Smav pdevinfo->index, 7905185225Smav pdevinfo->digital?"Digital":"Analog"); 7906182999Smav device_set_desc_copy(dev, buf); 7907182999Smav return (0); 7908182999Smav} 7909182999Smav 7910182999Smavstatic int 7911182999Smavhdac_pcm_attach(device_t dev) 7912182999Smav{ 7913182999Smav struct hdac_pcm_devinfo *pdevinfo = 7914182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7915182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7916182999Smav char status[SND_STATUSLEN]; 7917182999Smav int i; 7918182999Smav 7919182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 7920182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 7921182999Smav 7922182999Smav HDA_BOOTVERBOSE( 7923182999Smav device_printf(dev, "+--------------------------------------+\n"); 7924182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 7925182999Smav device_printf(dev, "+--------------------------------------+\n"); 7926182999Smav hdac_dump_pcmchannels(pdevinfo); 7927182999Smav device_printf(dev, "\n"); 7928189876Smav device_printf(dev, "+-------------------------------+\n"); 7929189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 7930189876Smav device_printf(dev, "+-------------------------------+\n"); 7931182999Smav hdac_dump_dac(pdevinfo); 7932182999Smav hdac_dump_adc(pdevinfo); 7933182999Smav hdac_dump_mix(pdevinfo); 7934182999Smav device_printf(dev, "\n"); 7935182999Smav device_printf(dev, "+-------------------------+\n"); 7936182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 7937182999Smav device_printf(dev, "+-------------------------+\n"); 7938182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 7939182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 7940182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 7941182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 7942182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 7943182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 7944182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 7945182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 7946182999Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 7947182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 7948182999Smav device_printf(dev, "\n"); 7949182999Smav ); 7950182999Smav 7951182999Smav if (resource_int_value(device_get_name(dev), 7952182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 7953182999Smav i &= HDA_BLK_ALIGN; 7954182999Smav if (i < HDA_BLK_MIN) 7955182999Smav i = HDA_BLK_MIN; 7956182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 7957182999Smav i = 0; 7958182999Smav while (pdevinfo->chan_blkcnt >> i) 7959182999Smav i++; 7960182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 7961182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 7962182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 7963182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 7964182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 7965182999Smav } else 7966182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 7967182999Smav 7968182999Smav /* 7969182999Smav * We don't register interrupt handler with snd_setup_intr 7970182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 7971182999Smav */ 7972182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 7973182999Smav 7974183097Smav HDA_BOOTHVERBOSE( 7975182999Smav device_printf(dev, "OSS mixer initialization...\n"); 7976182999Smav ); 7977182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 7978182999Smav device_printf(dev, "Can't register mixer\n"); 7979182999Smav 7980183097Smav HDA_BOOTHVERBOSE( 7981182999Smav device_printf(dev, "Registering PCM channels...\n"); 7982182999Smav ); 7983182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 7984182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 7985182999Smav device_printf(dev, "Can't register PCM\n"); 7986182999Smav 7987182999Smav pdevinfo->registered++; 7988182999Smav 7989182999Smav if (pdevinfo->play >= 0) 7990182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 7991182999Smav if (pdevinfo->rec >= 0) 7992182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 7993182999Smav 7994184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 7995184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 7996184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 7997182999Smav pcm_setstatus(dev, status); 7998182999Smav 7999182999Smav return (0); 8000182999Smav} 8001182999Smav 8002182999Smavstatic int 8003182999Smavhdac_pcm_detach(device_t dev) 8004182999Smav{ 8005182999Smav struct hdac_pcm_devinfo *pdevinfo = 8006182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8007182999Smav int err; 8008182999Smav 8009182999Smav if (pdevinfo->registered > 0) { 8010182999Smav err = pcm_unregister(dev); 8011182999Smav if (err != 0) 8012182999Smav return (err); 8013182999Smav } 8014182999Smav 8015182999Smav return (0); 8016182999Smav} 8017182999Smav 8018182999Smavstatic device_method_t hdac_pcm_methods[] = { 8019182999Smav /* device interface */ 8020182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8021182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8022182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8023182999Smav { 0, 0 } 8024182999Smav}; 8025182999Smav 8026182999Smavstatic driver_t hdac_pcm_driver = { 8027182999Smav "pcm", 8028182999Smav hdac_pcm_methods, 8029182999Smav PCM_SOFTC_SIZE, 8030182999Smav}; 8031182999Smav 8032182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8033182999Smav 8034