hdac.c revision 208934
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 * 3) Widget parser - the real magic of why this driver works on so 42162922Sariff * many hardwares with minimal vendor specific quirk. The original 43162922Sariff * parser was written using Ruby and can be found at 44162922Sariff * http://people.freebsd.org/~ariff/HDA/parser.rb . This crude 45162922Sariff * ruby parser take the verbose dmesg dump as its input. Refer to 46162922Sariff * http://www.microsoft.com/whdc/device/audio/default.mspx for various 47164614Sariff * interesting documents, especially UAA (Universal Audio Architecture). 48162922Sariff * 4) Possible vendor specific support. 49162922Sariff * (snd_hda_intel, snd_hda_ati, etc..) 50162922Sariff * 51162922Sariff * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the 52162922Sariff * Compaq V3000 with Conexant HDA. 53162922Sariff * 54162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 55162922Sariff * * * 56162922Sariff * * This driver is a collaborative effort made by: * 57162922Sariff * * * 58162922Sariff * * Stephane E. Potvin <sepotvin@videotron.ca> * 59162922Sariff * * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * 60162922Sariff * * Wesley Morgan <morganw@chemikals.org> * 61162922Sariff * * Daniel Eischen <deischen@FreeBSD.org> * 62162922Sariff * * Maxime Guillaud <bsd-ports@mguillaud.net> * 63162922Sariff * * Ariff Abdullah <ariff@FreeBSD.org> * 64182999Smav * * Alexander Motin <mav@FreeBSD.org> * 65162922Sariff * * * 66162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 67162922Sariff * * * 68162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 69162922Sariff */ 70162922Sariff 71193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 72193640Sariff#include "opt_snd.h" 73193640Sariff#endif 74193640Sariff 75162922Sariff#include <dev/sound/pcm/sound.h> 76162922Sariff#include <dev/pci/pcireg.h> 77162922Sariff#include <dev/pci/pcivar.h> 78162922Sariff 79171141Sariff#include <sys/ctype.h> 80171141Sariff#include <sys/taskqueue.h> 81171141Sariff 82162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 83162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 84162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 85162922Sariff#include <dev/sound/pci/hda/hdac.h> 86162922Sariff 87162922Sariff#include "mixer_if.h" 88162922Sariff 89204351Smav#define HDA_DRV_TEST_REV "20100226_0142" 90162922Sariff 91162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 208934 2010-06-09 05:49:02Z mav $"); 92162922Sariff 93169277Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 94169277Sariff if (bootverbose != 0 || snd_verbose > 3) { \ 95169277Sariff stmt \ 96169277Sariff } \ 97193640Sariff} while (0) 98162922Sariff 99183097Smav#define HDA_BOOTHVERBOSE(stmt) do { \ 100183097Smav if (snd_verbose > 3) { \ 101183097Smav stmt \ 102183097Smav } \ 103193640Sariff} while (0) 104183097Smav 105162965Sariff#if 1 106162922Sariff#undef HDAC_INTR_EXTRA 107162922Sariff#define HDAC_INTR_EXTRA 1 108162922Sariff#endif 109162922Sariff 110162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 111162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 112163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 113163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 114162922Sariff 115162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 116163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 117163257Sariff (fl) == 0xffffffff || \ 118163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 119163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 120163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 121163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 122162965Sariff#define HDA_MATCH_ALL 0xffffffff 123162965Sariff#define HDAC_INVALID 0xffffffff 124162965Sariff 125169277Sariff/* Default controller / jack sense poll: 250ms */ 126169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 127169277Sariff 128171141Sariff/* 129171141Sariff * Make room for possible 4096 playback/record channels, in 100 years to come. 130171141Sariff */ 131171141Sariff#define HDAC_TRIGGER_NONE 0x00000000 132171141Sariff#define HDAC_TRIGGER_PLAY 0x00000fff 133171141Sariff#define HDAC_TRIGGER_REC 0x00fff000 134171141Sariff#define HDAC_TRIGGER_UNSOL 0x80000000 135171141Sariff 136162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 137162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 138162922Sariff 139162922Sariff/* Controller models */ 140162922Sariff 141162922Sariff/* Intel */ 142162922Sariff#define INTEL_VENDORID 0x8086 143162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 144171330Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 145162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 146163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 147171330Sariff#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e) 148197017Smav#define HDA_INTEL_82801JI HDA_MODEL_CONSTRUCT(INTEL, 0x3a3e) 149197017Smav#define HDA_INTEL_82801JD HDA_MODEL_CONSTRUCT(INTEL, 0x3a6e) 150187020Smav#define HDA_INTEL_PCH HDA_MODEL_CONSTRUCT(INTEL, 0x3b56) 151184207Smav#define HDA_INTEL_SCH HDA_MODEL_CONSTRUCT(INTEL, 0x811b) 152162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 153162922Sariff 154162922Sariff/* Nvidia */ 155162922Sariff#define NVIDIA_VENDORID 0x10de 156162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 157162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 158173817Sariff#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 159173817Sariff#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 160173817Sariff#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 161173817Sariff#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 162173817Sariff#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c) 163173817Sariff#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d) 164186511Smav#define HDA_NVIDIA_MCP78_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0774) 165186511Smav#define HDA_NVIDIA_MCP78_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0775) 166186511Smav#define HDA_NVIDIA_MCP78_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0776) 167186511Smav#define HDA_NVIDIA_MCP78_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0777) 168186511Smav#define HDA_NVIDIA_MCP73_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fc) 169186511Smav#define HDA_NVIDIA_MCP73_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fd) 170186511Smav#define HDA_NVIDIA_MCP79_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac0) 171186511Smav#define HDA_NVIDIA_MCP79_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac1) 172186511Smav#define HDA_NVIDIA_MCP79_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac2) 173186511Smav#define HDA_NVIDIA_MCP79_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac3) 174197018Smav#define HDA_NVIDIA_MCP89_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d94) 175197018Smav#define HDA_NVIDIA_MCP89_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d95) 176197018Smav#define HDA_NVIDIA_MCP89_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d96) 177197018Smav#define HDA_NVIDIA_MCP89_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d97) 178162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 179162922Sariff 180162922Sariff/* ATI */ 181162922Sariff#define ATI_VENDORID 0x1002 182162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 183163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 184187020Smav#define HDA_ATI_RS600 HDA_MODEL_CONSTRUCT(ATI, 0x793b) 185187020Smav#define HDA_ATI_RS690 HDA_MODEL_CONSTRUCT(ATI, 0x7919) 186187020Smav#define HDA_ATI_RS780 HDA_MODEL_CONSTRUCT(ATI, 0x960f) 187187020Smav#define HDA_ATI_R600 HDA_MODEL_CONSTRUCT(ATI, 0xaa00) 188187020Smav#define HDA_ATI_RV630 HDA_MODEL_CONSTRUCT(ATI, 0xaa08) 189187020Smav#define HDA_ATI_RV610 HDA_MODEL_CONSTRUCT(ATI, 0xaa10) 190187020Smav#define HDA_ATI_RV670 HDA_MODEL_CONSTRUCT(ATI, 0xaa18) 191187020Smav#define HDA_ATI_RV635 HDA_MODEL_CONSTRUCT(ATI, 0xaa20) 192187020Smav#define HDA_ATI_RV620 HDA_MODEL_CONSTRUCT(ATI, 0xaa28) 193187020Smav#define HDA_ATI_RV770 HDA_MODEL_CONSTRUCT(ATI, 0xaa30) 194187020Smav#define HDA_ATI_RV730 HDA_MODEL_CONSTRUCT(ATI, 0xaa38) 195187020Smav#define HDA_ATI_RV710 HDA_MODEL_CONSTRUCT(ATI, 0xaa40) 196187020Smav#define HDA_ATI_RV740 HDA_MODEL_CONSTRUCT(ATI, 0xaa48) 197162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 198162922Sariff 199163136Sariff/* VIA */ 200163136Sariff#define VIA_VENDORID 0x1106 201163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 202163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 203163136Sariff 204163136Sariff/* SiS */ 205163136Sariff#define SIS_VENDORID 0x1039 206163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 207163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 208163136Sariff 209186301Smav/* ULI */ 210186301Smav#define ULI_VENDORID 0x10b9 211186301Smav#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461) 212186301Smav#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff) 213186301Smav 214162922Sariff/* OEM/subvendors */ 215162922Sariff 216165466Sariff/* Intel */ 217165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 218165466Sariff 219162922Sariff/* HP/Compaq */ 220162922Sariff#define HP_VENDORID 0x103c 221162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 222162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 223162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 224165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 225166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 226169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 227169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 228174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 229172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 230162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 231165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 232165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 233162922Sariff 234162922Sariff/* Dell */ 235162922Sariff#define DELL_VENDORID 0x1028 236180532Sdelphij#define DELL_D630_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01f9) 237162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 238184483Smav#define DELL_V1400_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0227) 239178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 240162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 241169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 242169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 243162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 244162922Sariff 245162922Sariff/* Clevo */ 246162922Sariff#define CLEVO_VENDORID 0x1558 247162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 248162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 249162922Sariff 250162922Sariff/* Acer */ 251162922Sariff#define ACER_VENDORID 0x1025 252165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 253173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 254174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 255182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 256169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 257182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 258189879Smav#define ACER_T5320_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011f) 259162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 260162922Sariff 261162965Sariff/* Asus */ 262162965Sariff#define ASUS_VENDORID 0x1043 263178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 264163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 265178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 266165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 267178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 268178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 269167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 270169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 271178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 272190630Smav#define ASUS_P5PL2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x817f) 273178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 274178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 275170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 276178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 277169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 278171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 279162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 280162922Sariff 281163257Sariff/* IBM / Lenovo */ 282163257Sariff#define IBM_VENDORID 0x1014 283163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 284163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 285162965Sariff 286164614Sariff/* Lenovo */ 287164657Sariff#define LENOVO_VENDORID 0x17aa 288164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 289182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 290172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 291164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 292163257Sariff 293164657Sariff/* Samsung */ 294164657Sariff#define SAMSUNG_VENDORID 0x144d 295164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 296164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 297164614Sariff 298164750Sariff/* Medion ? */ 299164750Sariff#define MEDION_VENDORID 0x161f 300164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 301164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 302164750Sariff 303173817Sariff/* Apple Computer Inc. */ 304173817Sariff#define APPLE_VENDORID 0x106b 305173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 306173817Sariff 307182999Smav/* Sony */ 308182999Smav#define SONY_VENDORID 0x104d 309182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 310182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 311182999Smav 312164828Sariff/* 313164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 314164828Sariff * instead of their own, which is beyond my comprehension 315164828Sariff * (see HDA_CODEC_STAC9221 below). 316164828Sariff */ 317164828Sariff#define APPLE_INTEL_MAC 0x76808384 318199846Smav#define APPLE_MACBOOKPRO55 0xcb7910de 319164828Sariff 320165281Sariff/* LG Electronics */ 321165281Sariff#define LG_VENDORID 0x1854 322165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 323165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 324165281Sariff 325165351Sariff/* Fujitsu Siemens */ 326165351Sariff#define FS_VENDORID 0x1734 327165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 328172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 329165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 330165351Sariff 331172811Sariff/* Fujitsu Limited */ 332172811Sariff#define FL_VENDORID 0x10cf 333172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 334182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 335172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 336172811Sariff 337165770Sariff/* Toshiba */ 338165770Sariff#define TOSHIBA_VENDORID 0x1179 339165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 340173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 341165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 342165770Sariff 343165992Sariff/* Micro-Star International (MSI) */ 344165992Sariff#define MSI_VENDORID 0x1462 345165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 346172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 347165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 348165992Sariff 349172811Sariff/* Giga-Byte Technology */ 350172811Sariff#define GB_VENDORID 0x1458 351172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 352172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 353172811Sariff 354169277Sariff/* Uniwill ? */ 355169277Sariff#define UNIWILL_VENDORID 0x1584 356169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 357170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 358169277Sariff 359169277Sariff 360162922Sariff/* Misc constants.. */ 361182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 362162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 363162922Sariff#define HDA_AMP_MUTE_NONE (0) 364162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 365162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 366162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 367162922Sariff 368162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 369162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 370162922Sariff 371182999Smav#define HDA_ADC_MONITOR (1 << 0) 372162922Sariff 373182999Smav#define HDA_CTL_OUT 1 374182999Smav#define HDA_CTL_IN 2 375169277Sariff 376169277Sariff#define HDA_GPIO_MAX 8 377169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 378163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 379163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 380163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 381169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 382169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 383169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 384169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 385169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 386169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 387162922Sariff 388169277Sariff/* 9 - 25 = anything else */ 389169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 390169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 391169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 392169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 393169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 394182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 395169277Sariff 396169277Sariff/* 26 - 31 = vrefs */ 397169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 398169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 399169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 400169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 401169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 402169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 403169277Sariff 404169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 405169277Sariff HDA_QUIRK_IVREF100) 406169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 407169277Sariff HDA_QUIRK_OVREF100) 408169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 409169277Sariff 410171141Sariff#if __FreeBSD_version < 600000 411171141Sariff#define taskqueue_drain(...) 412171141Sariff#endif 413171141Sariff 414163057Sariffstatic const struct { 415163057Sariff char *key; 416163057Sariff uint32_t value; 417163057Sariff} hdac_quirks_tab[] = { 418163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 419163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 420163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 421169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 422169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 423169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 424169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 425169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 426165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 427163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 428163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 429163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 430163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 431169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 432182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 433169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 434169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 435169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 436169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 437169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 438169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 439169277Sariff { "ivref", HDA_QUIRK_IVREF }, 440169277Sariff { "ovref", HDA_QUIRK_OVREF }, 441165069Sariff { "vref", HDA_QUIRK_VREF }, 442163057Sariff}; 443163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 444163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 445163057Sariff 446162922Sariff#define HDA_BDL_MIN 2 447162922Sariff#define HDA_BDL_MAX 256 448162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 449162922Sariff 450169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 451167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 452167648Sariff 453162922Sariff#define HDA_BUFSZ_MIN 4096 454162922Sariff#define HDA_BUFSZ_MAX 65536 455162922Sariff#define HDA_BUFSZ_DEFAULT 16384 456162922Sariff 457162922Sariff#define HDA_PARSE_MAXDEPTH 10 458162922Sariff 459169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 460162922Sariff 461165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 462162922Sariff 463182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 464182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 465182999Smav "White", "Other"}; 466162922Sariff 467182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 468182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 469182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 470182999Smav 471182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 472182999Smav 473162922Sariff/* Default */ 474162922Sariffstatic uint32_t hdac_fmt[] = { 475193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 476162922Sariff 0 477162922Sariff}; 478162922Sariff 479162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 480162922Sariff 481189086Smav#define HDAC_NO_MSI 1 482194861Smav#define HDAC_NO_64BIT 2 483189086Smav 484162922Sariffstatic const struct { 485162922Sariff uint32_t model; 486162922Sariff char *desc; 487189086Smav char flags; 488162922Sariff} hdac_devices[] = { 489189086Smav { HDA_INTEL_82801F, "Intel 82801F", 0 }, 490189086Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, 491189086Smav { HDA_INTEL_82801G, "Intel 82801G", 0 }, 492189086Smav { HDA_INTEL_82801H, "Intel 82801H", 0 }, 493189086Smav { HDA_INTEL_82801I, "Intel 82801I", 0 }, 494197017Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0 }, 495197017Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0 }, 496189086Smav { HDA_INTEL_PCH, "Intel PCH", 0 }, 497189086Smav { HDA_INTEL_SCH, "Intel SCH", 0 }, 498189086Smav { HDA_NVIDIA_MCP51, "NVidia MCP51", HDAC_NO_MSI }, 499195690Smav { HDA_NVIDIA_MCP55, "NVidia MCP55", HDAC_NO_MSI }, 500189086Smav { HDA_NVIDIA_MCP61_1, "NVidia MCP61", 0 }, 501189086Smav { HDA_NVIDIA_MCP61_2, "NVidia MCP61", 0 }, 502189086Smav { HDA_NVIDIA_MCP65_1, "NVidia MCP65", 0 }, 503189086Smav { HDA_NVIDIA_MCP65_2, "NVidia MCP65", 0 }, 504189086Smav { HDA_NVIDIA_MCP67_1, "NVidia MCP67", 0 }, 505189086Smav { HDA_NVIDIA_MCP67_2, "NVidia MCP67", 0 }, 506189086Smav { HDA_NVIDIA_MCP73_1, "NVidia MCP73", 0 }, 507189086Smav { HDA_NVIDIA_MCP73_2, "NVidia MCP73", 0 }, 508194861Smav { HDA_NVIDIA_MCP78_1, "NVidia MCP78", HDAC_NO_64BIT }, 509194861Smav { HDA_NVIDIA_MCP78_2, "NVidia MCP78", HDAC_NO_64BIT }, 510194861Smav { HDA_NVIDIA_MCP78_3, "NVidia MCP78", HDAC_NO_64BIT }, 511194861Smav { HDA_NVIDIA_MCP78_4, "NVidia MCP78", HDAC_NO_64BIT }, 512189086Smav { HDA_NVIDIA_MCP79_1, "NVidia MCP79", 0 }, 513189086Smav { HDA_NVIDIA_MCP79_2, "NVidia MCP79", 0 }, 514189086Smav { HDA_NVIDIA_MCP79_3, "NVidia MCP79", 0 }, 515189086Smav { HDA_NVIDIA_MCP79_4, "NVidia MCP79", 0 }, 516197018Smav { HDA_NVIDIA_MCP89_1, "NVidia MCP89", 0 }, 517197018Smav { HDA_NVIDIA_MCP89_2, "NVidia MCP89", 0 }, 518197018Smav { HDA_NVIDIA_MCP89_3, "NVidia MCP89", 0 }, 519197018Smav { HDA_NVIDIA_MCP89_4, "NVidia MCP89", 0 }, 520189086Smav { HDA_ATI_SB450, "ATI SB450", 0 }, 521189086Smav { HDA_ATI_SB600, "ATI SB600", 0 }, 522189086Smav { HDA_ATI_RS600, "ATI RS600", 0 }, 523189086Smav { HDA_ATI_RS690, "ATI RS690", 0 }, 524189086Smav { HDA_ATI_RS780, "ATI RS780", 0 }, 525189086Smav { HDA_ATI_R600, "ATI R600", 0 }, 526189086Smav { HDA_ATI_RV610, "ATI RV610", 0 }, 527189086Smav { HDA_ATI_RV620, "ATI RV620", 0 }, 528189086Smav { HDA_ATI_RV630, "ATI RV630", 0 }, 529189086Smav { HDA_ATI_RV635, "ATI RV635", 0 }, 530189086Smav { HDA_ATI_RV710, "ATI RV710", 0 }, 531189086Smav { HDA_ATI_RV730, "ATI RV730", 0 }, 532189086Smav { HDA_ATI_RV740, "ATI RV740", 0 }, 533189086Smav { HDA_ATI_RV770, "ATI RV770", 0 }, 534189086Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0 }, 535189086Smav { HDA_SIS_966, "SiS 966", 0 }, 536189086Smav { HDA_ULI_M5461, "ULI M5461", 0 }, 537162922Sariff /* Unknown */ 538162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 539162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 540162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 541163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 542163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 543186301Smav { HDA_ULI_ALL, "ULI (Unknown)" }, 544162922Sariff}; 545162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 546162922Sariff 547162922Sariffstatic const struct { 548169277Sariff uint16_t vendor; 549169277Sariff uint8_t reg; 550169277Sariff uint8_t mask; 551169277Sariff uint8_t enable; 552169277Sariff} hdac_pcie_snoop[] = { 553169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 554169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 555169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 556169277Sariff}; 557169277Sariff#define HDAC_PCIESNOOP_LEN \ 558169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 559169277Sariff 560169277Sariffstatic const struct { 561162922Sariff uint32_t rate; 562162922Sariff int valid; 563162922Sariff uint16_t base; 564162922Sariff uint16_t mul; 565162922Sariff uint16_t div; 566162922Sariff} hda_rate_tab[] = { 567162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 568162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 569162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 570162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 571162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 572162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 573162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 574162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 575162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 576162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 577162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 578162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 579162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 580162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 581162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 582162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 583162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 584162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 585162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 586162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 587162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 588162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 589162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 590162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 591162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 592162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 593162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 594162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 595162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 596162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 597162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 598162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 599162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 600162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 601162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 602162922Sariff}; 603162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 604162922Sariff 605162922Sariff/* All codecs you can eat... */ 606162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 607162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 608162922Sariff 609199846Smav/* Cirrus Logic */ 610199846Smav#define CIRRUSLOGIC_VENDORID 0x1013 611199846Smav#define HDA_CODEC_CS4206 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4206) 612199846Smav#define HDA_CODEC_CS4207 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4207) 613200375Smav#define HDA_CODEC_CSXXXX HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0xffff) 614199846Smav 615162922Sariff/* Realtek */ 616162922Sariff#define REALTEK_VENDORID 0x10ec 617162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 618169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 619183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 620171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 621183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 622205413Smav#define HDA_CODEC_ALC270 HDA_CODEC_CONSTRUCT(REALTEK, 0x0270) 623183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 624205413Smav#define HDA_CODEC_ALC273 HDA_CODEC_CONSTRUCT(REALTEK, 0x0273) 625205413Smav#define HDA_CODEC_ALC275 HDA_CODEC_CONSTRUCT(REALTEK, 0x0275) 626170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 627183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 628183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 629205413Smav#define HDA_CODEC_ALC665 HDA_CODEC_CONSTRUCT(REALTEK, 0x0665) 630162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 631169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 632162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 633163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 634163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 635169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 636197640Smav#define HDA_CODEC_ALC887 HDA_CODEC_CONSTRUCT(REALTEK, 0x0887) 637165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 638182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 639205413Smav#define HDA_CODEC_ALC892 HDA_CODEC_CONSTRUCT(REALTEK, 0x0892) 640162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 641162922Sariff 642169277Sariff/* Analog Devices */ 643169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 644186403Smav#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) 645186403Smav#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) 646186403Smav#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) 647186403Smav#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) 648186403Smav#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) 649186403Smav#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) 650169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 651169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 652174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 653169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 654186403Smav#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) 655169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 656170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 657186403Smav#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) 658186403Smav#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) 659169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 660162922Sariff 661162922Sariff/* CMedia */ 662162922Sariff#define CMEDIA_VENDORID 0x434d 663162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 664162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 665162922Sariff 666162922Sariff/* Sigmatel */ 667162922Sariff#define SIGMATEL_VENDORID 0x8384 668182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 669182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 670182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 671182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 672182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 673182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 674182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 675182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 676183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 677183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 678183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 679183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 680183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 681183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 682183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 683182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 684183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 685183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 686183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 687183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 688183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 689183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 690183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 691183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 692200375Smav#define HDA_CODEC_CXD9872RDK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7661) 693182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 694200375Smav#define HDA_CODEC_CXD9872AKD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7664) 695162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 696182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 697183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 698162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 699162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 700183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 701183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 702183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 703183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 704183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 705183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 706183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 707183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 708183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 709162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 710162922Sariff 711183894Smav/* IDT */ 712183894Smav#define IDT_VENDORID 0x111d 713183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 714183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 715183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 716183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 717183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 718183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 719183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 720183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 721183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 722183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 723183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 724183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 725183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 726183894Smav 727182999Smav/* Silicon Image */ 728182999Smav#define SII_VENDORID 0x1095 729187020Smav#define HDA_CODEC_SII1390 HDA_CODEC_CONSTRUCT(SII, 0x1390) 730186146Smav#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) 731182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 732182999Smav 733182999Smav/* Lucent/Agere */ 734182999Smav#define AGERE_VENDORID 0x11c1 735182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 736182999Smav 737186430Smav/* Conexant */ 738162922Sariff#define CONEXANT_VENDORID 0x14f1 739186430Smav#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 740186430Smav#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 741186430Smav#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) 742200375Smav#define HDA_CODEC_CX20582 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5066) 743205413Smav#define HDA_CODEC_CX20583 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5067) 744208934Smav#define HDA_CODEC_CX20585 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5069) 745162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 746162922Sariff 747169277Sariff/* VIA */ 748169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 749169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 750169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 751169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 752169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 753169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 754169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 755169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 756169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 757169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 758169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 759169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 760186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 761186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 762186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 763186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 764186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 765186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 766186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 767186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 768187020Smav#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) 769187020Smav#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) 770187020Smav#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) 771187020Smav#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) 772187020Smav#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) 773187020Smav#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) 774187020Smav#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) 775187020Smav#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) 776187020Smav#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) 777187020Smav#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) 778187020Smav#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) 779187020Smav#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) 780187020Smav#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) 781187020Smav#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) 782187020Smav#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) 783187020Smav#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) 784199258Smav#define HDA_CODEC_VT1716S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0433) 785199258Smav#define HDA_CODEC_VT1716S_1 HDA_CODEC_CONSTRUCT(VIA, 0xa721) 786199258Smav#define HDA_CODEC_VT1718S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0428) 787199258Smav#define HDA_CODEC_VT1718S_1 HDA_CODEC_CONSTRUCT(VIA, 0x4428) 788199258Smav#define HDA_CODEC_VT1812 HDA_CODEC_CONSTRUCT(VIA, 0x0448) 789199258Smav#define HDA_CODEC_VT1818S HDA_CODEC_CONSTRUCT(VIA, 0x0440) 790199258Smav#define HDA_CODEC_VT1828S HDA_CODEC_CONSTRUCT(VIA, 0x4441) 791199258Smav#define HDA_CODEC_VT2002P_0 HDA_CODEC_CONSTRUCT(VIA, 0x0438) 792199258Smav#define HDA_CODEC_VT2002P_1 HDA_CODEC_CONSTRUCT(VIA, 0x4438) 793199258Smav#define HDA_CODEC_VT2020 HDA_CODEC_CONSTRUCT(VIA, 0x0441) 794169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 795162922Sariff 796182999Smav/* ATI */ 797186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 798186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 799186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 800186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 801182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 802169277Sariff 803182999Smav/* NVIDIA */ 804187020Smav#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) 805187445Smav#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) 806187020Smav#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) 807208934Smav#define HDA_CODEC_NVIDIAGT220 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000a) 808208934Smav#define HDA_CODEC_NVIDIAGT21X HDA_CODEC_CONSTRUCT(NVIDIA, 0x000b) 809208934Smav#define HDA_CODEC_NVIDIAMCP89 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000c) 810208934Smav#define HDA_CODEC_NVIDIAGT240 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000d) 811187020Smav#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) 812187445Smav#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) 813182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 814182999Smav 815183894Smav/* INTEL */ 816187020Smav#define HDA_CODEC_INTELG45_1 HDA_CODEC_CONSTRUCT(INTEL, 0x2801) 817187020Smav#define HDA_CODEC_INTELG45_2 HDA_CODEC_CONSTRUCT(INTEL, 0x2802) 818187020Smav#define HDA_CODEC_INTELG45_3 HDA_CODEC_CONSTRUCT(INTEL, 0x2803) 819205413Smav#define HDA_CODEC_INTELG45_4 HDA_CODEC_CONSTRUCT(INTEL, 0x2804) 820205413Smav#define HDA_CODEC_INTELG45_5 HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) 821199258Smav#define HDA_CODEC_INTELQ57 HDA_CODEC_CONSTRUCT(INTEL, 0x0054) 822183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 823183894Smav 824162922Sariff/* Codecs */ 825162922Sariffstatic const struct { 826162922Sariff uint32_t id; 827162922Sariff char *name; 828162922Sariff} hdac_codecs[] = { 829199846Smav { HDA_CODEC_CS4206, "Cirrus Logic CS4206" }, 830199846Smav { HDA_CODEC_CS4207, "Cirrus Logic CS4207" }, 831162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 832169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 833183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 834171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 835183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 836205413Smav { HDA_CODEC_ALC270, "Realtek ALC270" }, 837183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 838205413Smav { HDA_CODEC_ALC273, "Realtek ALC273" }, 839205413Smav { HDA_CODEC_ALC275, "Realtek ALC275" }, 840170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 841183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 842183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 843205413Smav { HDA_CODEC_ALC665, "Realtek ALC665" }, 844162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 845169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 846162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 847162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 848163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 849169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 850197640Smav { HDA_CODEC_ALC887, "Realtek ALC887" }, 851165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 852182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 853205413Smav { HDA_CODEC_ALC892, "Realtek ALC892" }, 854186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 855186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 856186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 857186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 858186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 859169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 860169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 861174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 862186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 863186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 864169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 865186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 866186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 867170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 868186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 869162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 870200375Smav { HDA_CODEC_CXD9872RDK, "Sigmatel CXD9872RD/K" }, 871200375Smav { HDA_CODEC_CXD9872AKD, "Sigmatel CXD9872AKD" }, 872183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 873183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 874183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 875183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 876183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 877183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 878183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 879183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 880162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 881183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 882162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 883162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 884183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 885183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 886183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 887183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 888183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 889183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 890182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 891182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 892183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 893183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 894183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 895166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 896183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 897183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 898183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 899183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 900183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 901183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 902183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 903183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 904183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 905183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 906183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 907183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 908183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 909183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 910183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 911183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 912183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 913183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 914183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 915183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 916183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 917183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 918183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 919183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 920183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 921183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 922183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 923186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 924186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 925186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 926200375Smav { HDA_CODEC_CX20582, "Conexant CX20582 (Pebble)" }, 927205413Smav { HDA_CODEC_CX20583, "Conexant CX20583 (Pebble HSF)" }, 928208934Smav { HDA_CODEC_CX20585, "Conexant CX20585" }, 929169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 930169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 931169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 932169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 933169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 934169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 935169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 936169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 937169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 938169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 939169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 940169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 941186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 942186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 943186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 944186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 945186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 946186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 947186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 948186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 949187020Smav { HDA_CODEC_VT1708S_0, "VIA VT1708S_0" }, 950187020Smav { HDA_CODEC_VT1708S_1, "VIA VT1708S_1" }, 951187020Smav { HDA_CODEC_VT1708S_2, "VIA VT1708S_2" }, 952187020Smav { HDA_CODEC_VT1708S_3, "VIA VT1708S_3" }, 953187020Smav { HDA_CODEC_VT1708S_4, "VIA VT1708S_4" }, 954187020Smav { HDA_CODEC_VT1708S_5, "VIA VT1708S_5" }, 955187020Smav { HDA_CODEC_VT1708S_6, "VIA VT1708S_6" }, 956187020Smav { HDA_CODEC_VT1708S_7, "VIA VT1708S_7" }, 957187020Smav { HDA_CODEC_VT1702_0, "VIA VT1702_0" }, 958187020Smav { HDA_CODEC_VT1702_1, "VIA VT1702_1" }, 959187020Smav { HDA_CODEC_VT1702_2, "VIA VT1702_2" }, 960187020Smav { HDA_CODEC_VT1702_3, "VIA VT1702_3" }, 961187020Smav { HDA_CODEC_VT1702_4, "VIA VT1702_4" }, 962187020Smav { HDA_CODEC_VT1702_5, "VIA VT1702_5" }, 963187020Smav { HDA_CODEC_VT1702_6, "VIA VT1702_6" }, 964187020Smav { HDA_CODEC_VT1702_7, "VIA VT1702_7" }, 965199258Smav { HDA_CODEC_VT1716S_0, "VIA VT1716S_0" }, 966199258Smav { HDA_CODEC_VT1716S_1, "VIA VT1716S_1" }, 967199258Smav { HDA_CODEC_VT1718S_0, "VIA VT1718S_0" }, 968199258Smav { HDA_CODEC_VT1718S_1, "VIA VT1718S_1" }, 969199258Smav { HDA_CODEC_VT1812, "VIA VT1812" }, 970199258Smav { HDA_CODEC_VT1818S, "VIA VT1818S" }, 971199258Smav { HDA_CODEC_VT1828S, "VIA VT1828S" }, 972199258Smav { HDA_CODEC_VT2002P_0, "VIA VT2002P_0" }, 973199258Smav { HDA_CODEC_VT2002P_1, "VIA VT2002P_1" }, 974199258Smav { HDA_CODEC_VT2020, "VIA VT2020" }, 975186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 976186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 977186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 978186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 979187020Smav { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, 980187445Smav { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, 981187020Smav { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, 982187445Smav { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, 983187020Smav { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, 984208934Smav { HDA_CODEC_NVIDIAGT220, "NVidia GT220 HDMI" }, 985208934Smav { HDA_CODEC_NVIDIAGT21X, "NVidia GT21x HDMI" }, 986208934Smav { HDA_CODEC_NVIDIAMCP89, "NVidia MCP89 HDMI" }, 987208934Smav { HDA_CODEC_NVIDIAGT240, "NVidia GT240 HDMI" }, 988187020Smav { HDA_CODEC_INTELG45_1, "Intel G45 HDMI" }, 989187020Smav { HDA_CODEC_INTELG45_2, "Intel G45 HDMI" }, 990187020Smav { HDA_CODEC_INTELG45_3, "Intel G45 HDMI" }, 991187020Smav { HDA_CODEC_INTELG45_4, "Intel G45 HDMI" }, 992205413Smav { HDA_CODEC_INTELG45_5, "Intel G45 HDMI" }, 993199258Smav { HDA_CODEC_INTELQ57, "Intel Q57 HDMI" }, 994187020Smav { HDA_CODEC_SII1390, "Silicon Image SiI1390 HDMI" }, 995186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 996162922Sariff /* Unknown codec */ 997162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 998169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 999200375Smav { HDA_CODEC_CSXXXX, "Cirrus Logic (Unknown)" }, 1000162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 1001162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 1002182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 1003182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 1004162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 1005169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 1006182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 1007182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 1008183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 1009183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 1010162922Sariff}; 1011162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 1012162922Sariff 1013162922Sariff 1014162922Sariff/**************************************************************************** 1015162922Sariff * Function prototypes 1016162922Sariff ****************************************************************************/ 1017162922Sariffstatic void hdac_intr_handler(void *); 1018182999Smavstatic int hdac_reset(struct hdac_softc *, int); 1019162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 1020162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 1021162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 1022162922Sariff struct hdac_dma *, bus_size_t); 1023169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 1024162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 1025162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 1026162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 1027162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 1028162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 1029162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 1030162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 1031162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 1032182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 1033182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 1034182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 1035182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 1036162922Sariff 1037162922Sariffstatic void hdac_attach2(void *); 1038162922Sariff 1039162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 1040162922Sariff uint32_t, int); 1041162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 1042162922Sariff struct hdac_command_list *, int); 1043162922Sariff 1044162922Sariffstatic int hdac_probe(device_t); 1045162922Sariffstatic int hdac_attach(device_t); 1046162922Sariffstatic int hdac_detach(device_t); 1047182999Smavstatic int hdac_suspend(device_t); 1048182999Smavstatic int hdac_resume(device_t); 1049162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 1050162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 1051162922Sariff uint32_t, int, int); 1052162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 1053182999Smav nid_t, int, int, int); 1054162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 1055162922Sariff nid_t, nid_t, int, int, int, int, int, int); 1056162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 1057162922Sariff 1058164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 1059164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 1060164614Sariff 1061182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 1062182999Smav 1063162922Sariff#define hdac_command(a1, a2, a3) \ 1064162922Sariff hdac_command_sendone_internal(a1, a2, a3) 1065162922Sariff 1066182999Smav#define hdac_codec_id(c) \ 1067182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 1068182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 1069182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 1070162922Sariff 1071162922Sariffstatic char * 1072182999Smavhdac_codec_name(struct hdac_codec *codec) 1073162922Sariff{ 1074162922Sariff uint32_t id; 1075162922Sariff int i; 1076162922Sariff 1077182999Smav id = hdac_codec_id(codec); 1078162922Sariff 1079162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 1080163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 1081162922Sariff return (hdac_codecs[i].name); 1082162922Sariff } 1083162922Sariff 1084162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 1085162922Sariff} 1086162922Sariff 1087162922Sariffstatic char * 1088162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 1089162922Sariff{ 1090162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 1091162922Sariff int i, first = 1; 1092162922Sariff 1093162922Sariff bzero(buf, len); 1094162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 1095162922Sariff if (mask & (1 << i)) { 1096162922Sariff if (first == 0) 1097162922Sariff strlcat(buf, ", ", len); 1098162922Sariff strlcat(buf, ossname[i], len); 1099162922Sariff first = 0; 1100162922Sariff } 1101162922Sariff } 1102182999Smav return (buf); 1103162922Sariff} 1104162922Sariff 1105162922Sariffstatic struct hdac_audio_ctl * 1106162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 1107162922Sariff{ 1108162922Sariff if (devinfo == NULL || 1109162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 1110162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 1111162922Sariff devinfo->function.audio.ctlcnt < 1 || 1112162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 1113162922Sariff return (NULL); 1114162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 1115162922Sariff} 1116162922Sariff 1117162922Sariffstatic struct hdac_audio_ctl * 1118182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 1119162922Sariff int index, int cnt) 1120162922Sariff{ 1121182999Smav struct hdac_audio_ctl *ctl; 1122182999Smav int i, found = 0; 1123162922Sariff 1124162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 1125162922Sariff return (NULL); 1126162922Sariff 1127162922Sariff i = 0; 1128162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 1129182999Smav if (ctl->enable == 0) 1130162922Sariff continue; 1131182999Smav if (ctl->widget->nid != nid) 1132162922Sariff continue; 1133182999Smav if (dir && ctl->ndir != dir) 1134182999Smav continue; 1135182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 1136182999Smav ctl->dir == ctl->ndir && ctl->index != index) 1137182999Smav continue; 1138162922Sariff found++; 1139182999Smav if (found == cnt || cnt <= 0) 1140162922Sariff return (ctl); 1141162922Sariff } 1142162922Sariff 1143182999Smav return (NULL); 1144162922Sariff} 1145162922Sariff 1146182999Smav/* 1147182999Smav * Jack detection (Speaker/HP redirection) event handler. 1148182999Smav */ 1149162922Sariffstatic void 1150162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 1151162922Sariff{ 1152182999Smav struct hdac_audio_as *as; 1153162922Sariff struct hdac_softc *sc; 1154162922Sariff struct hdac_widget *w; 1155162922Sariff struct hdac_audio_ctl *ctl; 1156182999Smav uint32_t val, res; 1157182999Smav int i, j; 1158162922Sariff nid_t cad; 1159162922Sariff 1160162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1161162922Sariff devinfo->codec->sc == NULL) 1162162922Sariff return; 1163162922Sariff 1164162922Sariff sc = devinfo->codec->sc; 1165162922Sariff cad = devinfo->codec->cad; 1166182999Smav as = devinfo->function.audio.as; 1167182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1168182999Smav if (as[i].hpredir < 0) 1169182999Smav continue; 1170182999Smav 1171182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1172182999Smav if (w == NULL || w->enable == 0 || w->type != 1173182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1174182999Smav continue; 1175162922Sariff 1176171141Sariff res = hdac_command(sc, 1177182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1178171141Sariff 1179182999Smav HDA_BOOTVERBOSE( 1180182999Smav device_printf(sc->dev, 1181182999Smav "Pin sense: nid=%d res=0x%08x\n", 1182182999Smav as[i].pins[15], res); 1183182999Smav ); 1184171141Sariff 1185182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1186182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1187182999Smav res ^= 1; 1188162922Sariff 1189182999Smav /* (Un)Mute headphone pin. */ 1190162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1191182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1192182999Smav if (ctl != NULL && ctl->mute) { 1193182999Smav /* If pin has muter - use it. */ 1194182999Smav val = (res != 0) ? 0 : 1; 1195182999Smav if (val != ctl->forcemute) { 1196182999Smav ctl->forcemute = val; 1197162922Sariff hdac_audio_ctl_amp_set(ctl, 1198182999Smav HDA_AMP_MUTE_DEFAULT, 1199182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1200162922Sariff } 1201182999Smav } else { 1202182999Smav /* If there is no muter - disable pin output. */ 1203182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1204163057Sariff if (w != NULL && w->type == 1205163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1206182999Smav if (res != 0) 1207169277Sariff val = w->wclass.pin.ctrl | 1208162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1209162922Sariff else 1210169277Sariff val = w->wclass.pin.ctrl & 1211162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1212169277Sariff if (val != w->wclass.pin.ctrl) { 1213169277Sariff w->wclass.pin.ctrl = val; 1214169277Sariff hdac_command(sc, 1215169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1216169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1217169277Sariff } 1218162922Sariff } 1219182999Smav } 1220182999Smav /* (Un)Mute other pins. */ 1221182999Smav for (j = 0; j < 15; j++) { 1222182999Smav if (as[i].pins[j] <= 0) 1223182999Smav continue; 1224182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1225182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1226182999Smav if (ctl != NULL && ctl->mute) { 1227182999Smav /* If pin has muter - use it. */ 1228182999Smav val = (res != 0) ? 1 : 0; 1229182999Smav if (val == ctl->forcemute) 1230169277Sariff continue; 1231182999Smav ctl->forcemute = val; 1232182999Smav hdac_audio_ctl_amp_set(ctl, 1233182999Smav HDA_AMP_MUTE_DEFAULT, 1234182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1235182999Smav continue; 1236162922Sariff } 1237182999Smav /* If there is no muter - disable pin output. */ 1238182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1239163057Sariff if (w != NULL && w->type == 1240163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1241182999Smav if (res != 0) 1242182999Smav val = w->wclass.pin.ctrl & 1243182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1244182999Smav else 1245182999Smav val = w->wclass.pin.ctrl | 1246182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1247169277Sariff if (val != w->wclass.pin.ctrl) { 1248169277Sariff w->wclass.pin.ctrl = val; 1249169277Sariff hdac_command(sc, 1250169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1251169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1252169277Sariff } 1253162922Sariff } 1254162922Sariff } 1255182999Smav } 1256182999Smav} 1257182999Smav 1258182999Smav/* 1259182999Smav * Callback for poll based jack detection. 1260182999Smav */ 1261182999Smavstatic void 1262182999Smavhdac_jack_poll_callback(void *arg) 1263182999Smav{ 1264182999Smav struct hdac_devinfo *devinfo = arg; 1265182999Smav struct hdac_softc *sc; 1266182999Smav 1267182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1268182999Smav devinfo->codec->sc == NULL) 1269182999Smav return; 1270182999Smav sc = devinfo->codec->sc; 1271182999Smav hdac_lock(sc); 1272182999Smav if (sc->poll_ival == 0) { 1273182999Smav hdac_unlock(sc); 1274182999Smav return; 1275182999Smav } 1276182999Smav hdac_hp_switch_handler(devinfo); 1277182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1278182999Smav hdac_jack_poll_callback, devinfo); 1279182999Smav hdac_unlock(sc); 1280182999Smav} 1281182999Smav 1282182999Smav/* 1283182999Smav * Jack detection initializer. 1284182999Smav */ 1285182999Smavstatic void 1286182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1287182999Smav{ 1288182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1289182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1290182999Smav struct hdac_widget *w; 1291182999Smav uint32_t id; 1292182999Smav int i, enable = 0, poll = 0; 1293182999Smav nid_t cad; 1294182999Smav 1295182999Smav id = hdac_codec_id(devinfo->codec); 1296182999Smav cad = devinfo->codec->cad; 1297182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1298182999Smav if (as[i].hpredir < 0) 1299182999Smav continue; 1300182999Smav 1301182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1302182999Smav if (w == NULL || w->enable == 0 || w->type != 1303182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1304182999Smav continue; 1305182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1306182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1307182999Smav device_printf(sc->dev, 1308182999Smav "No jack detection support at pin %d\n", 1309182999Smav as[i].pins[15]); 1310182999Smav continue; 1311182999Smav } 1312182999Smav enable = 1; 1313182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1314169277Sariff hdac_command(sc, 1315182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1316182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1317182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1318182999Smav } else 1319182999Smav poll = 1; 1320182999Smav HDA_BOOTVERBOSE( 1321169277Sariff device_printf(sc->dev, 1322182999Smav "Enabling headphone/speaker " 1323182999Smav "audio routing switching:\n"); 1324182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1325182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1326182999Smav ); 1327182999Smav } 1328182999Smav if (enable) { 1329182999Smav hdac_hp_switch_handler(devinfo); 1330182999Smav if (poll) { 1331182999Smav callout_reset(&sc->poll_jack, 1, 1332182999Smav hdac_jack_poll_callback, devinfo); 1333169277Sariff } 1334162922Sariff } 1335162922Sariff} 1336162922Sariff 1337182999Smav/* 1338182999Smav * Unsolicited messages handler. 1339182999Smav */ 1340162922Sariffstatic void 1341162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1342162922Sariff{ 1343162922Sariff struct hdac_softc *sc; 1344162922Sariff struct hdac_devinfo *devinfo = NULL; 1345182999Smav int i; 1346162922Sariff 1347162922Sariff if (codec == NULL || codec->sc == NULL) 1348162922Sariff return; 1349162922Sariff 1350162922Sariff sc = codec->sc; 1351162922Sariff 1352163057Sariff HDA_BOOTVERBOSE( 1353182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1354162922Sariff ); 1355162922Sariff 1356182999Smav for (i = 0; i < codec->num_fgs; i++) { 1357182999Smav if (codec->fgs[i].node_type == 1358182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1359182999Smav devinfo = &codec->fgs[i]; 1360162965Sariff break; 1361182999Smav } 1362162922Sariff } 1363162965Sariff 1364162922Sariff if (devinfo == NULL) 1365162922Sariff return; 1366162922Sariff 1367162922Sariff switch (tag) { 1368162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1369162922Sariff hdac_hp_switch_handler(devinfo); 1370162922Sariff break; 1371162922Sariff default: 1372182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1373162922Sariff break; 1374162922Sariff } 1375162922Sariff} 1376162922Sariff 1377164614Sariffstatic int 1378162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1379162922Sariff{ 1380162922Sariff /* XXX to be removed */ 1381162922Sariff#ifdef HDAC_INTR_EXTRA 1382162922Sariff uint32_t res; 1383162922Sariff#endif 1384162922Sariff 1385171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1386164614Sariff return (0); 1387162922Sariff 1388162922Sariff /* XXX to be removed */ 1389162922Sariff#ifdef HDAC_INTR_EXTRA 1390162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1391162922Sariff#endif 1392162922Sariff 1393162922Sariff /* XXX to be removed */ 1394162922Sariff#ifdef HDAC_INTR_EXTRA 1395163057Sariff HDA_BOOTVERBOSE( 1396163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1397182999Smav device_printf(ch->pdevinfo->dev, 1398163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1399163057Sariff "%08x\n", 1400163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1401163057Sariff ); 1402162922Sariff#endif 1403162922Sariff 1404162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1405163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1406162922Sariff 1407162922Sariff /* XXX to be removed */ 1408162922Sariff#ifdef HDAC_INTR_EXTRA 1409162922Sariff if (res & HDAC_SDSTS_BCIS) { 1410162922Sariff#endif 1411164614Sariff return (1); 1412162922Sariff /* XXX to be removed */ 1413162922Sariff#ifdef HDAC_INTR_EXTRA 1414162922Sariff } 1415162922Sariff#endif 1416164614Sariff 1417164614Sariff return (0); 1418162922Sariff} 1419162922Sariff 1420162922Sariff/**************************************************************************** 1421162922Sariff * void hdac_intr_handler(void *) 1422162922Sariff * 1423162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1424162922Sariff ****************************************************************************/ 1425162922Sariffstatic void 1426162922Sariffhdac_intr_handler(void *context) 1427162922Sariff{ 1428162922Sariff struct hdac_softc *sc; 1429162922Sariff uint32_t intsts; 1430162922Sariff uint8_t rirbsts; 1431164614Sariff struct hdac_rirb *rirb_base; 1432171141Sariff uint32_t trigger; 1433182999Smav int i; 1434162922Sariff 1435162922Sariff sc = (struct hdac_softc *)context; 1436162922Sariff 1437162922Sariff hdac_lock(sc); 1438164614Sariff if (sc->polling != 0) { 1439164614Sariff hdac_unlock(sc); 1440164614Sariff return; 1441164614Sariff } 1442171141Sariff 1443162922Sariff /* Do we have anything to do? */ 1444162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1445163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1446162922Sariff hdac_unlock(sc); 1447162922Sariff return; 1448162922Sariff } 1449162922Sariff 1450171141Sariff trigger = 0; 1451171141Sariff 1452162922Sariff /* Was this a controller interrupt? */ 1453163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1454162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1455162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1456162922Sariff /* Get as many responses that we can */ 1457163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1458164614Sariff HDAC_WRITE_1(&sc->mem, 1459164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1460171141Sariff if (hdac_rirb_flush(sc) != 0) 1461171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1462162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1463162922Sariff } 1464162922Sariff /* XXX to be removed */ 1465162922Sariff /* Clear interrupt and exit */ 1466162922Sariff#ifdef HDAC_INTR_EXTRA 1467162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1468162922Sariff#endif 1469162922Sariff } 1470164614Sariff 1471163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1472182999Smav for (i = 0; i < sc->num_chans; i++) { 1473182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1474182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1475182999Smav trigger |= (1 << i); 1476182999Smav } 1477162922Sariff /* XXX to be removed */ 1478162922Sariff#ifdef HDAC_INTR_EXTRA 1479164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1480164614Sariff HDAC_INTSTS_SIS_MASK); 1481162922Sariff#endif 1482162922Sariff } 1483162922Sariff 1484164614Sariff hdac_unlock(sc); 1485162922Sariff 1486182999Smav for (i = 0; i < sc->num_chans; i++) { 1487182999Smav if (trigger & (1 << i)) 1488182999Smav chn_intr(sc->chans[i].c); 1489182999Smav } 1490171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1491171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1492162922Sariff} 1493162922Sariff 1494162922Sariff/**************************************************************************** 1495182999Smav * int hdac_reset(hdac_softc *, int) 1496162922Sariff * 1497162922Sariff * Reset the hdac to a quiescent and known state. 1498162922Sariff ****************************************************************************/ 1499162922Sariffstatic int 1500182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1501162922Sariff{ 1502162922Sariff uint32_t gctl; 1503162922Sariff int count, i; 1504162922Sariff 1505162922Sariff /* 1506162922Sariff * Stop all Streams DMA engine 1507162922Sariff */ 1508162922Sariff for (i = 0; i < sc->num_iss; i++) 1509162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1510162922Sariff for (i = 0; i < sc->num_oss; i++) 1511162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1512162922Sariff for (i = 0; i < sc->num_bss; i++) 1513162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1514162922Sariff 1515162922Sariff /* 1516169277Sariff * Stop Control DMA engines. 1517162922Sariff */ 1518162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1519162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1520162922Sariff 1521162922Sariff /* 1522169277Sariff * Reset DMA position buffer. 1523169277Sariff */ 1524169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1525169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1526169277Sariff 1527169277Sariff /* 1528162922Sariff * Reset the controller. The reset must remain asserted for 1529162922Sariff * a minimum of 100us. 1530162922Sariff */ 1531162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1532162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1533162922Sariff count = 10000; 1534162922Sariff do { 1535162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1536162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1537162922Sariff break; 1538162922Sariff DELAY(10); 1539162922Sariff } while (--count); 1540162922Sariff if (gctl & HDAC_GCTL_CRST) { 1541162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1542162922Sariff return (ENXIO); 1543162922Sariff } 1544182999Smav 1545182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1546182999Smav if (!wakeup) 1547182999Smav return (0); 1548182999Smav 1549162922Sariff DELAY(100); 1550162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1551162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1552162922Sariff count = 10000; 1553162922Sariff do { 1554162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1555163057Sariff if (gctl & HDAC_GCTL_CRST) 1556162922Sariff break; 1557162922Sariff DELAY(10); 1558162922Sariff } while (--count); 1559162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1560162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1561162922Sariff return (ENXIO); 1562162922Sariff } 1563162922Sariff 1564162922Sariff /* 1565162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1566162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1567162922Sariff * computer. Let's use twice as much as necessary to make sure that 1568162922Sariff * it's reset properly. 1569162922Sariff */ 1570162922Sariff DELAY(1000); 1571162922Sariff 1572162922Sariff return (0); 1573162922Sariff} 1574162922Sariff 1575162922Sariff 1576162922Sariff/**************************************************************************** 1577162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1578162922Sariff * 1579162922Sariff * Retreive the general capabilities of the hdac; 1580162922Sariff * Number of Input Streams 1581162922Sariff * Number of Output Streams 1582162922Sariff * Number of bidirectional Streams 1583162922Sariff * 64bit ready 1584162922Sariff * CORB and RIRB sizes 1585162922Sariff ****************************************************************************/ 1586162922Sariffstatic int 1587162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1588162922Sariff{ 1589162922Sariff uint16_t gcap; 1590162922Sariff uint8_t corbsize, rirbsize; 1591162922Sariff 1592162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1593162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1594162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1595162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1596196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 1597163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1598162922Sariff 1599162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1600162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1601162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1602162922Sariff sc->corb_size = 256; 1603162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1604162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1605162922Sariff sc->corb_size = 16; 1606162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1607162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1608162922Sariff sc->corb_size = 2; 1609162922Sariff else { 1610162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1611162922Sariff __func__, corbsize); 1612162922Sariff return (ENXIO); 1613162922Sariff } 1614162922Sariff 1615162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1616162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1617162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1618162922Sariff sc->rirb_size = 256; 1619162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1620162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1621162922Sariff sc->rirb_size = 16; 1622162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1623162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1624162922Sariff sc->rirb_size = 2; 1625162922Sariff else { 1626162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1627162922Sariff __func__, rirbsize); 1628162922Sariff return (ENXIO); 1629162922Sariff } 1630162922Sariff 1631196762Smav HDA_BOOTVERBOSE( 1632196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 1633196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 1634196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 1635196762Smav sc->support_64bit ? ", 64bit" : "", 1636196762Smav sc->corb_size, sc->rirb_size); 1637182999Smav ); 1638182999Smav 1639162922Sariff return (0); 1640162922Sariff} 1641162922Sariff 1642162922Sariff 1643162922Sariff/**************************************************************************** 1644162922Sariff * void hdac_dma_cb 1645162922Sariff * 1646162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1647162922Sariff * established. We just record the physical address of the mapping into 1648162922Sariff * the struct hdac_dma passed in. 1649162922Sariff ****************************************************************************/ 1650162922Sariffstatic void 1651162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1652162922Sariff{ 1653162922Sariff struct hdac_dma *dma; 1654162922Sariff 1655162922Sariff if (error == 0) { 1656162922Sariff dma = (struct hdac_dma *)callback_arg; 1657162922Sariff dma->dma_paddr = segs[0].ds_addr; 1658162922Sariff } 1659162922Sariff} 1660162922Sariff 1661162922Sariff 1662162922Sariff/**************************************************************************** 1663162922Sariff * int hdac_dma_alloc 1664162922Sariff * 1665162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1666162922Sariff * It must be freed by a corresponding hdac_dma_free. 1667162922Sariff ****************************************************************************/ 1668162922Sariffstatic int 1669162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1670162922Sariff{ 1671169277Sariff bus_size_t roundsz; 1672162922Sariff int result; 1673162922Sariff 1674169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1675162922Sariff bzero(dma, sizeof(*dma)); 1676162922Sariff 1677162922Sariff /* 1678162922Sariff * Create a DMA tag 1679162922Sariff */ 1680194861Smav result = bus_dma_tag_create( 1681194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1682162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1683162922Sariff 0, /* boundary */ 1684194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1685194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1686162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1687162922Sariff NULL, /* filtfunc */ 1688162922Sariff NULL, /* fistfuncarg */ 1689169277Sariff roundsz, /* maxsize */ 1690162922Sariff 1, /* nsegments */ 1691169277Sariff roundsz, /* maxsegsz */ 1692162922Sariff 0, /* flags */ 1693162922Sariff NULL, /* lockfunc */ 1694162922Sariff NULL, /* lockfuncarg */ 1695162922Sariff &dma->dma_tag); /* dmat */ 1696162922Sariff if (result != 0) { 1697162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1698162922Sariff __func__, result); 1699167773Sariff goto hdac_dma_alloc_fail; 1700162922Sariff } 1701162922Sariff 1702162922Sariff /* 1703162922Sariff * Allocate DMA memory 1704162922Sariff */ 1705162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1706169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1707171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1708171330Sariff &dma->dma_map); 1709162922Sariff if (result != 0) { 1710162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1711162922Sariff __func__, result); 1712167773Sariff goto hdac_dma_alloc_fail; 1713162922Sariff } 1714162922Sariff 1715169277Sariff dma->dma_size = roundsz; 1716169277Sariff 1717162922Sariff /* 1718162922Sariff * Map the memory 1719162922Sariff */ 1720162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1721169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1722162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1723167773Sariff if (result == 0) 1724167773Sariff result = ENOMEM; 1725162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1726162922Sariff __func__, result); 1727167773Sariff goto hdac_dma_alloc_fail; 1728162922Sariff } 1729162922Sariff 1730183097Smav HDA_BOOTHVERBOSE( 1731169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1732169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1733169277Sariff ); 1734169277Sariff 1735162922Sariff return (0); 1736169277Sariff 1737167773Sariffhdac_dma_alloc_fail: 1738169277Sariff hdac_dma_free(sc, dma); 1739167773Sariff 1740162922Sariff return (result); 1741162922Sariff} 1742162922Sariff 1743162922Sariff 1744162922Sariff/**************************************************************************** 1745169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1746162922Sariff * 1747162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1748162922Sariff * hdac_dma_alloc function. 1749162922Sariff ****************************************************************************/ 1750162922Sariffstatic void 1751169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1752162922Sariff{ 1753167773Sariff if (dma->dma_map != NULL) { 1754169277Sariff#if 0 1755162922Sariff /* Flush caches */ 1756162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1757162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1758169277Sariff#endif 1759162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1760167773Sariff } 1761167773Sariff if (dma->dma_vaddr != NULL) { 1762162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1763167773Sariff dma->dma_vaddr = NULL; 1764167773Sariff } 1765167773Sariff dma->dma_map = NULL; 1766167773Sariff if (dma->dma_tag != NULL) { 1767162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1768167773Sariff dma->dma_tag = NULL; 1769162922Sariff } 1770167773Sariff dma->dma_size = 0; 1771162922Sariff} 1772162922Sariff 1773162922Sariff/**************************************************************************** 1774162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1775162922Sariff * 1776162922Sariff * Allocate all the bus resources necessary to speak with the physical 1777162922Sariff * controller. 1778162922Sariff ****************************************************************************/ 1779162922Sariffstatic int 1780162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1781162922Sariff{ 1782162922Sariff struct hdac_mem *mem; 1783162922Sariff 1784162922Sariff mem = &sc->mem; 1785162922Sariff mem->mem_rid = PCIR_BAR(0); 1786162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1787162922Sariff &mem->mem_rid, RF_ACTIVE); 1788162922Sariff if (mem->mem_res == NULL) { 1789162922Sariff device_printf(sc->dev, 1790162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1791162922Sariff return (ENOMEM); 1792162922Sariff } 1793162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1794162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1795162922Sariff 1796162922Sariff return (0); 1797162922Sariff} 1798162922Sariff 1799162922Sariff/**************************************************************************** 1800162922Sariff * void hdac_mem_free(struct hdac_softc *) 1801162922Sariff * 1802162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1803162922Sariff ****************************************************************************/ 1804162922Sariffstatic void 1805162922Sariffhdac_mem_free(struct hdac_softc *sc) 1806162922Sariff{ 1807162922Sariff struct hdac_mem *mem; 1808162922Sariff 1809162922Sariff mem = &sc->mem; 1810162922Sariff if (mem->mem_res != NULL) 1811162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1812162922Sariff mem->mem_res); 1813164614Sariff mem->mem_res = NULL; 1814162922Sariff} 1815162922Sariff 1816162922Sariff/**************************************************************************** 1817162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1818162922Sariff * 1819162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1820162922Sariff ****************************************************************************/ 1821162922Sariffstatic int 1822162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1823162922Sariff{ 1824162922Sariff struct hdac_irq *irq; 1825162922Sariff int result; 1826162922Sariff 1827162922Sariff irq = &sc->irq; 1828162922Sariff irq->irq_rid = 0x0; 1829171330Sariff 1830171330Sariff if ((sc->flags & HDAC_F_MSI) && 1831171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1832171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1833171330Sariff irq->irq_rid = 0x1; 1834171330Sariff else 1835171330Sariff sc->flags &= ~HDAC_F_MSI; 1836171330Sariff 1837162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1838162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1839162922Sariff if (irq->irq_res == NULL) { 1840162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1841162922Sariff __func__); 1842167773Sariff goto hdac_irq_alloc_fail; 1843162922Sariff } 1844182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1845182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1846162922Sariff if (result != 0) { 1847162922Sariff device_printf(sc->dev, 1848162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1849162922Sariff __func__, result); 1850167773Sariff goto hdac_irq_alloc_fail; 1851162922Sariff } 1852162922Sariff 1853162922Sariff return (0); 1854162922Sariff 1855167773Sariffhdac_irq_alloc_fail: 1856164614Sariff hdac_irq_free(sc); 1857164614Sariff 1858162922Sariff return (ENXIO); 1859162922Sariff} 1860162922Sariff 1861162922Sariff/**************************************************************************** 1862162922Sariff * void hdac_irq_free(struct hdac_softc *) 1863162922Sariff * 1864162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1865162922Sariff ****************************************************************************/ 1866162922Sariffstatic void 1867162922Sariffhdac_irq_free(struct hdac_softc *sc) 1868162922Sariff{ 1869162922Sariff struct hdac_irq *irq; 1870162922Sariff 1871162922Sariff irq = &sc->irq; 1872164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1873162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1874162922Sariff if (irq->irq_res != NULL) 1875162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1876162922Sariff irq->irq_res); 1877188656Smav if (irq->irq_rid == 0x1) 1878171330Sariff pci_release_msi(sc->dev); 1879164614Sariff irq->irq_handle = NULL; 1880164614Sariff irq->irq_res = NULL; 1881171330Sariff irq->irq_rid = 0x0; 1882162922Sariff} 1883162922Sariff 1884162922Sariff/**************************************************************************** 1885162922Sariff * void hdac_corb_init(struct hdac_softc *) 1886162922Sariff * 1887162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1888162922Sariff * The CORB engine must not be running when this function is called. 1889162922Sariff ****************************************************************************/ 1890162922Sariffstatic void 1891162922Sariffhdac_corb_init(struct hdac_softc *sc) 1892162922Sariff{ 1893162922Sariff uint8_t corbsize; 1894162922Sariff uint64_t corbpaddr; 1895162922Sariff 1896162922Sariff /* Setup the CORB size. */ 1897162922Sariff switch (sc->corb_size) { 1898162922Sariff case 256: 1899162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1900162922Sariff break; 1901162922Sariff case 16: 1902162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1903162922Sariff break; 1904162922Sariff case 2: 1905162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1906162922Sariff break; 1907162922Sariff default: 1908162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1909162922Sariff } 1910162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1911162922Sariff 1912162922Sariff /* Setup the CORB Address in the hdac */ 1913162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1914162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1915162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1916162922Sariff 1917162922Sariff /* Set the WP and RP */ 1918162922Sariff sc->corb_wp = 0; 1919162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1920162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1921162922Sariff /* 1922162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1923162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1924162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1925162922Sariff * manually reset the bit to zero before continuing. 1926162922Sariff */ 1927162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1928162922Sariff 1929162922Sariff /* Enable CORB error reporting */ 1930162922Sariff#if 0 1931162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1932162922Sariff#endif 1933162922Sariff} 1934162922Sariff 1935162922Sariff/**************************************************************************** 1936162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1937162922Sariff * 1938162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1939162922Sariff * The RIRB engine must not be running when this function is called. 1940162922Sariff ****************************************************************************/ 1941162922Sariffstatic void 1942162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1943162922Sariff{ 1944162922Sariff uint8_t rirbsize; 1945162922Sariff uint64_t rirbpaddr; 1946162922Sariff 1947162922Sariff /* Setup the RIRB size. */ 1948162922Sariff switch (sc->rirb_size) { 1949162922Sariff case 256: 1950162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1951162922Sariff break; 1952162922Sariff case 16: 1953162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1954162922Sariff break; 1955162922Sariff case 2: 1956162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1957162922Sariff break; 1958162922Sariff default: 1959162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1960162922Sariff } 1961162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1962162922Sariff 1963162922Sariff /* Setup the RIRB Address in the hdac */ 1964162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1965162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1966162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1967162922Sariff 1968162922Sariff /* Setup the WP and RP */ 1969162922Sariff sc->rirb_rp = 0; 1970162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1971162922Sariff 1972182999Smav /* Setup the interrupt threshold */ 1973182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1974162922Sariff 1975182999Smav /* Enable Overrun and response received reporting */ 1976162922Sariff#if 0 1977182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1978182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1979162922Sariff#else 1980182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1981162922Sariff#endif 1982162922Sariff 1983169277Sariff#if 0 1984162922Sariff /* 1985162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1986162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1987162922Sariff * should be sufficient to do this only once as the rirb is purely 1988162922Sariff * read-only from now on. 1989162922Sariff */ 1990162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1991162922Sariff BUS_DMASYNC_PREREAD); 1992169277Sariff#endif 1993162922Sariff} 1994162922Sariff 1995162922Sariff/**************************************************************************** 1996162922Sariff * void hdac_corb_start(hdac_softc *) 1997162922Sariff * 1998162922Sariff * Startup the corb DMA engine 1999162922Sariff ****************************************************************************/ 2000162922Sariffstatic void 2001162922Sariffhdac_corb_start(struct hdac_softc *sc) 2002162922Sariff{ 2003162922Sariff uint32_t corbctl; 2004162922Sariff 2005162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 2006162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 2007162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 2008162922Sariff} 2009162922Sariff 2010162922Sariff/**************************************************************************** 2011162922Sariff * void hdac_rirb_start(hdac_softc *) 2012162922Sariff * 2013162922Sariff * Startup the rirb DMA engine 2014162922Sariff ****************************************************************************/ 2015162922Sariffstatic void 2016162922Sariffhdac_rirb_start(struct hdac_softc *sc) 2017162922Sariff{ 2018162922Sariff uint32_t rirbctl; 2019162922Sariff 2020162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 2021162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 2022162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 2023162922Sariff} 2024162922Sariff 2025162922Sariff 2026162922Sariff/**************************************************************************** 2027172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 2028162922Sariff * 2029172811Sariff * Scan the bus for available codecs, starting with num. 2030162922Sariff ****************************************************************************/ 2031162922Sariffstatic void 2032182999Smavhdac_scan_codecs(struct hdac_softc *sc) 2033162922Sariff{ 2034162922Sariff struct hdac_codec *codec; 2035162922Sariff int i; 2036162922Sariff uint16_t statests; 2037162922Sariff 2038162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 2039182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 2040162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 2041162922Sariff /* We have found a codec. */ 2042162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 2043162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 2044162922Sariff if (codec == NULL) { 2045162922Sariff device_printf(sc->dev, 2046162922Sariff "Unable to allocate memory for codec\n"); 2047162922Sariff continue; 2048162922Sariff } 2049164614Sariff codec->commands = NULL; 2050164614Sariff codec->responses_received = 0; 2051162922Sariff codec->verbs_sent = 0; 2052162922Sariff codec->sc = sc; 2053162922Sariff codec->cad = i; 2054162922Sariff sc->codecs[i] = codec; 2055182999Smav hdac_probe_codec(codec); 2056162922Sariff } 2057162922Sariff } 2058162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 2059163057Sariff /* bus_generic_attach(sc->dev); */ 2060162922Sariff} 2061162922Sariff 2062162922Sariff/**************************************************************************** 2063162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 2064162922Sariff * 2065162922Sariff * Probe a the given codec_id for available function groups. 2066162922Sariff ****************************************************************************/ 2067182999Smavstatic void 2068162922Sariffhdac_probe_codec(struct hdac_codec *codec) 2069162922Sariff{ 2070162922Sariff struct hdac_softc *sc = codec->sc; 2071162922Sariff uint32_t vendorid, revisionid, subnode; 2072162922Sariff int startnode; 2073162922Sariff int endnode; 2074162922Sariff int i; 2075162922Sariff nid_t cad = codec->cad; 2076162922Sariff 2077163057Sariff HDA_BOOTVERBOSE( 2078184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 2079162922Sariff ); 2080162922Sariff vendorid = hdac_command(sc, 2081162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 2082162922Sariff cad); 2083162922Sariff revisionid = hdac_command(sc, 2084162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 2085162922Sariff cad); 2086182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 2087182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 2088182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 2089182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 2090182999Smav 2091182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 2092182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 2093182999Smav " Probing aborted.\n", cad); 2094182999Smav return; 2095182999Smav } 2096182999Smav 2097184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 2098182999Smav cad, hdac_codec_name(codec)); 2099182999Smav HDA_BOOTVERBOSE( 2100184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 2101182999Smav hdac_codec_id(codec)); 2102182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 2103182999Smav codec->vendor_id); 2104182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 2105182999Smav codec->device_id); 2106182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 2107182999Smav codec->revision_id); 2108182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 2109182999Smav codec->stepping_id); 2110182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2111182999Smav sc->pci_subvendor); 2112182999Smav ); 2113162922Sariff subnode = hdac_command(sc, 2114162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 2115162922Sariff cad); 2116162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 2117162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 2118162922Sariff 2119183097Smav HDA_BOOTHVERBOSE( 2120182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 2121163057Sariff startnode, endnode); 2122162922Sariff ); 2123182999Smav 2124182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 2125182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 2126182999Smav if (codec->fgs == NULL) { 2127183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 2128182999Smav __func__); 2129182999Smav return; 2130162922Sariff } 2131162922Sariff 2132182999Smav for (i = startnode; i < endnode; i++) 2133182999Smav hdac_probe_function(codec, i); 2134182999Smav return; 2135162922Sariff} 2136162922Sariff 2137182999Smav/* 2138182999Smav * Probe codec function and add it to the list. 2139182999Smav */ 2140182999Smavstatic void 2141162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 2142162922Sariff{ 2143162922Sariff struct hdac_softc *sc = codec->sc; 2144182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 2145162922Sariff uint32_t fctgrptype; 2146182999Smav uint32_t res; 2147162922Sariff nid_t cad = codec->cad; 2148162922Sariff 2149162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 2150162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 2151162922Sariff 2152162922Sariff devinfo->nid = nid; 2153162965Sariff devinfo->node_type = fctgrptype; 2154162922Sariff devinfo->codec = codec; 2155162922Sariff 2156182999Smav res = hdac_command(sc, 2157182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2158162922Sariff 2159182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2160182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2161182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2162162922Sariff 2163182999Smav HDA_BOOTVERBOSE( 2164182999Smav device_printf(sc->dev, 2165182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2166182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2167182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2168182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2169182999Smav devinfo->nodecnt); 2170182999Smav ); 2171182999Smav 2172182999Smav if (devinfo->nodecnt > 0) 2173182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2174182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2175182999Smav M_NOWAIT | M_ZERO); 2176182999Smav else 2177182999Smav devinfo->widget = NULL; 2178182999Smav 2179182999Smav if (devinfo->widget == NULL) { 2180182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2181182999Smav devinfo->endnode = devinfo->startnode; 2182182999Smav devinfo->nodecnt = 0; 2183182999Smav return; 2184182999Smav } 2185182999Smav 2186182999Smav codec->num_fgs++; 2187162922Sariff} 2188162922Sariff 2189162922Sariffstatic void 2190162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2191162922Sariff{ 2192162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2193162922Sariff uint32_t res; 2194169277Sariff int i, j, max, ents, entnum; 2195162922Sariff nid_t cad = w->devinfo->codec->cad; 2196162922Sariff nid_t nid = w->nid; 2197169277Sariff nid_t cnid, addcnid, prevcnid; 2198162922Sariff 2199169277Sariff w->nconns = 0; 2200169277Sariff 2201162922Sariff res = hdac_command(sc, 2202162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2203162922Sariff 2204169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2205162922Sariff 2206169277Sariff if (ents < 1) 2207162922Sariff return; 2208162922Sariff 2209162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2210162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2211169277Sariff prevcnid = 0; 2212162922Sariff 2213169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2214169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2215169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2216169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2217169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2218169277Sariff 2219169277Sariff for (i = 0; i < ents; i += entnum) { 2220162922Sariff res = hdac_command(sc, 2221162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2222162922Sariff for (j = 0; j < entnum; j++) { 2223169277Sariff cnid = CONN_CNID(res, entnum, j); 2224169277Sariff if (cnid == 0) { 2225169277Sariff if (w->nconns < ents) 2226169277Sariff device_printf(sc->dev, 2227169277Sariff "%s: nid=%d WARNING: zero cnid " 2228169277Sariff "entnum=%d j=%d index=%d " 2229169277Sariff "entries=%d found=%d res=0x%08x\n", 2230169277Sariff __func__, nid, entnum, j, i, 2231169277Sariff ents, w->nconns, res); 2232169277Sariff else 2233169277Sariff goto getconns_out; 2234169277Sariff } 2235169277Sariff if (cnid < w->devinfo->startnode || 2236169277Sariff cnid >= w->devinfo->endnode) { 2237169277Sariff HDA_BOOTVERBOSE( 2238169277Sariff device_printf(sc->dev, 2239182999Smav "GHOST: nid=%d j=%d " 2240169277Sariff "entnum=%d index=%d res=0x%08x\n", 2241182999Smav nid, j, entnum, i, res); 2242169277Sariff ); 2243169277Sariff } 2244169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2245169277Sariff addcnid = cnid; 2246169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2247162922Sariff device_printf(sc->dev, 2248169277Sariff "%s: WARNING: Invalid child range " 2249169277Sariff "nid=%d index=%d j=%d entnum=%d " 2250169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2251169277Sariff __func__, nid, i, j, entnum, prevcnid, 2252169277Sariff cnid, res); 2253169277Sariff addcnid = cnid; 2254169277Sariff } else 2255169277Sariff addcnid = prevcnid + 1; 2256169277Sariff while (addcnid <= cnid) { 2257169277Sariff if (w->nconns > max) { 2258169277Sariff device_printf(sc->dev, 2259182999Smav "Adding %d (nid=%d): " 2260169277Sariff "Max connection reached! max=%d\n", 2261182999Smav addcnid, nid, max + 1); 2262169277Sariff goto getconns_out; 2263169277Sariff } 2264182999Smav w->connsenable[w->nconns] = 1; 2265169277Sariff w->conns[w->nconns++] = addcnid++; 2266162922Sariff } 2267169277Sariff prevcnid = cnid; 2268162922Sariff } 2269162922Sariff } 2270162922Sariff 2271169277Sariffgetconns_out: 2272169277Sariff return; 2273162922Sariff} 2274162922Sariff 2275162922Sariffstatic uint32_t 2276182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2277182999Smav{ 2278182999Smav char buf[256]; 2279182999Smav char *key, *value, *rest, *bad; 2280182999Smav int ival, i; 2281182999Smav 2282182999Smav strlcpy(buf, str, sizeof(buf)); 2283182999Smav rest = buf; 2284182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2285182999Smav value = strsep(&rest, " \t"); 2286182999Smav if (value == NULL) 2287182999Smav break; 2288182999Smav ival = strtol(value, &bad, 10); 2289182999Smav if (strcmp(key, "seq") == 0) { 2290182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2291182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2292182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2293182999Smav } else if (strcmp(key, "as") == 0) { 2294182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2295182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2296182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2297182999Smav } else if (strcmp(key, "misc") == 0) { 2298182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2299182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2300182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2301182999Smav } else if (strcmp(key, "color") == 0) { 2302182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2303182999Smav if (bad[0] == 0) { 2304182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2305182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2306182999Smav }; 2307182999Smav for (i = 0; i < 16; i++) { 2308182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2309182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2310182999Smav break; 2311182999Smav } 2312182999Smav } 2313182999Smav } else if (strcmp(key, "ctype") == 0) { 2314182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2315182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2316182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2317182999Smav } else if (strcmp(key, "device") == 0) { 2318182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2319182999Smav if (bad[0] == 0) { 2320182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2321182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2322182999Smav continue; 2323182999Smav }; 2324182999Smav for (i = 0; i < 16; i++) { 2325182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2326182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2327182999Smav break; 2328182999Smav } 2329182999Smav } 2330182999Smav } else if (strcmp(key, "loc") == 0) { 2331182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2332182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2333182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2334182999Smav } else if (strcmp(key, "conn") == 0) { 2335182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2336182999Smav if (bad[0] == 0) { 2337182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2338182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2339182999Smav continue; 2340182999Smav }; 2341182999Smav for (i = 0; i < 4; i++) { 2342182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2343182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2344182999Smav break; 2345182999Smav } 2346182999Smav } 2347182999Smav } 2348182999Smav } 2349182999Smav return (config); 2350182999Smav} 2351182999Smav 2352182999Smavstatic uint32_t 2353162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2354162922Sariff{ 2355162922Sariff struct hdac_softc *sc; 2356166965Sariff uint32_t config, orig, id; 2357162922Sariff nid_t cad, nid; 2358182999Smav char buf[32]; 2359182999Smav const char *res = NULL, *patch = NULL; 2360162922Sariff 2361162922Sariff sc = w->devinfo->codec->sc; 2362162922Sariff cad = w->devinfo->codec->cad; 2363162922Sariff nid = w->nid; 2364182999Smav id = hdac_codec_id(w->devinfo->codec); 2365162922Sariff 2366162922Sariff config = hdac_command(sc, 2367162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2368162922Sariff cad); 2369166965Sariff orig = config; 2370166965Sariff 2371182999Smav HDA_BOOTVERBOSE( 2372182999Smav hdac_dump_pin_config(w, orig); 2373182999Smav ); 2374182999Smav 2375182999Smav /* XXX: Old patches require complete review. 2376182999Smav * Now they may create more problem then solve due to 2377182999Smav * incorrect associations. 2378162965Sariff */ 2379165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2380165281Sariff switch (nid) { 2381165281Sariff case 26: 2382165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2383165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2384165281Sariff break; 2385165281Sariff case 27: 2386165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2387165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2388165281Sariff break; 2389167610Sariff default: 2390167610Sariff break; 2391165281Sariff } 2392165281Sariff } else if (id == HDA_CODEC_ALC880 && 2393162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2394162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2395162922Sariff /* 2396162965Sariff * Super broken BIOS 2397162922Sariff */ 2398162922Sariff switch (nid) { 2399162922Sariff case 24: /* MIC1 */ 2400162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2401162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2402162922Sariff break; 2403162922Sariff case 25: /* XXX MIC2 */ 2404162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2405162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2406162922Sariff break; 2407162922Sariff case 26: /* LINE1 */ 2408162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2409162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2410162922Sariff break; 2411162922Sariff case 27: /* XXX LINE2 */ 2412162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2413162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2414162922Sariff break; 2415162922Sariff case 28: /* CD */ 2416162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2417162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2418162922Sariff break; 2419162922Sariff } 2420166965Sariff } else if (id == HDA_CODEC_ALC883 && 2421172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2422172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2423166965Sariff switch (nid) { 2424166965Sariff case 25: 2425166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2426166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2427166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2428166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2429166965Sariff break; 2430169277Sariff case 28: 2431169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2432169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2433169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2434169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2435169277Sariff break; 2436166965Sariff } 2437186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2438166965Sariff HP_V3000_SUBVENDOR) { 2439166965Sariff switch (nid) { 2440166965Sariff case 18: 2441166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2442166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2443166965Sariff break; 2444166965Sariff case 20: 2445166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2446166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2447166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2448166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2449166965Sariff break; 2450167454Sariff case 21: 2451167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2452167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2453167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2454167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2455167454Sariff break; 2456166965Sariff } 2457186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2458169277Sariff HP_DV5000_SUBVENDOR) { 2459169277Sariff switch (nid) { 2460169277Sariff case 20: 2461169277Sariff case 21: 2462169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2463169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2464169277Sariff break; 2465169277Sariff } 2466169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2467169277Sariff ASUS_W6F_SUBVENDOR) { 2468169277Sariff switch (nid) { 2469169277Sariff case 11: 2470169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2471169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2472169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2473169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2474169277Sariff break; 2475178324Sariff case 12: 2476178324Sariff case 14: 2477178324Sariff case 16: 2478178324Sariff case 31: 2479178324Sariff case 32: 2480178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2481178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2482178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2483178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2484178324Sariff break; 2485169277Sariff case 15: 2486169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2487169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2488169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2489169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2490169277Sariff break; 2491169277Sariff } 2492169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2493169277Sariff UNIWILL_9075_SUBVENDOR) { 2494169277Sariff switch (nid) { 2495169277Sariff case 15: 2496169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2497169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2498169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2499169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2500169277Sariff break; 2501169277Sariff } 2502182999Smav } 2503182999Smav 2504182999Smav /* New patches */ 2505182999Smav if (id == HDA_CODEC_AD1986A && 2506171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2507190630Smav sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR || 2508190630Smav sc->pci_subvendor == ASUS_P5PL2_SUBVENDOR)) { 2509169277Sariff switch (nid) { 2510190630Smav case 26: /* Headphones with redirection */ 2511190630Smav patch = "as=1 seq=15"; 2512190630Smav break; 2513190630Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 2514182999Smav patch = "device=Line-in as=8 seq=1"; 2515169277Sariff break; 2516190630Smav case 29: /* Can't use this as input, as the only available mic 2517190630Smav * preamplifier is busy by front panel mic (nid 31). 2518190630Smav * If you want to use this rear connector as mic input, 2519190630Smav * you have to disable the front panel one. */ 2520190630Smav patch = "as=0"; 2521169277Sariff break; 2522182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2523182999Smav patch = "as=8 seq=3"; 2524169277Sariff break; 2525182999Smav case 32: 2526182999Smav patch = "as=8 seq=4"; 2527182999Smav break; 2528182999Smav case 34: 2529182999Smav patch = "as=8 seq=5"; 2530182999Smav break; 2531182999Smav case 36: 2532182999Smav patch = "as=8 seq=6"; 2533182999Smav break; 2534169277Sariff } 2535182999Smav } else if (id == HDA_CODEC_ALC260 && 2536182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2537182999Smav switch (nid) { 2538182999Smav case 16: 2539182999Smav patch = "seq=15 device=Headphones"; 2540182999Smav break; 2541182999Smav } 2542189879Smav } else if (id == HDA_CODEC_ALC268) { 2543189879Smav if (sc->pci_subvendor == ACER_T5320_SUBVENDOR) { 2544174578Sariff switch (nid) { 2545189879Smav case 20: /* Headphones Jack */ 2546189879Smav patch = "as=1 seq=15"; 2547174578Sariff break; 2548174578Sariff } 2549189879Smav } 2550162922Sariff } 2551162922Sariff 2552182999Smav if (patch != NULL) 2553182999Smav config = hdac_widget_pin_patch(config, patch); 2554182999Smav 2555182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2556182999Smav if (resource_string_value(device_get_name(sc->dev), 2557182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2558182999Smav if (strncmp(res, "0x", 2) == 0) { 2559182999Smav config = strtol(res + 2, NULL, 16); 2560182999Smav } else { 2561182999Smav config = hdac_widget_pin_patch(config, res); 2562182999Smav } 2563182999Smav } 2564182999Smav 2565166965Sariff HDA_BOOTVERBOSE( 2566166965Sariff if (config != orig) 2567166965Sariff device_printf(sc->dev, 2568182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2569166965Sariff nid, orig, config); 2570166965Sariff ); 2571166965Sariff 2572162922Sariff return (config); 2573162922Sariff} 2574162922Sariff 2575166965Sariffstatic uint32_t 2576166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2577166965Sariff{ 2578166965Sariff struct hdac_softc *sc; 2579166965Sariff uint32_t caps, orig, id; 2580166965Sariff nid_t cad, nid; 2581166965Sariff 2582166965Sariff sc = w->devinfo->codec->sc; 2583166965Sariff cad = w->devinfo->codec->cad; 2584166965Sariff nid = w->nid; 2585182999Smav id = hdac_codec_id(w->devinfo->codec); 2586166965Sariff 2587166965Sariff caps = hdac_command(sc, 2588166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2589166965Sariff orig = caps; 2590166965Sariff 2591166965Sariff HDA_BOOTVERBOSE( 2592166965Sariff if (caps != orig) 2593166965Sariff device_printf(sc->dev, 2594182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2595166965Sariff nid, orig, caps); 2596166965Sariff ); 2597166965Sariff 2598166965Sariff return (caps); 2599166965Sariff} 2600166965Sariff 2601162922Sariffstatic void 2602162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2603162922Sariff{ 2604162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2605162922Sariff uint32_t config, pincap; 2606186912Smav const char *devstr; 2607162922Sariff nid_t cad = w->devinfo->codec->cad; 2608162922Sariff nid_t nid = w->nid; 2609186912Smav int conn, color; 2610162922Sariff 2611162922Sariff config = hdac_widget_pin_getconfig(w); 2612162922Sariff w->wclass.pin.config = config; 2613162922Sariff 2614166965Sariff pincap = hdac_widget_pin_getcaps(w); 2615162922Sariff w->wclass.pin.cap = pincap; 2616162922Sariff 2617162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2618182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2619162922Sariff 2620162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2621162922Sariff w->param.eapdbtl = hdac_command(sc, 2622162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2623162922Sariff w->param.eapdbtl &= 0x7; 2624162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2625162922Sariff } else 2626162965Sariff w->param.eapdbtl = HDAC_INVALID; 2627162922Sariff 2628182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2629182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2630162922Sariff 2631186912Smav conn = (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2632186912Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT; 2633186912Smav color = (config & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> 2634186912Smav HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT; 2635162922Sariff 2636162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2637162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2638162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2639186912Smav if (conn == 0 && color != 0 && color != 15) { 2640186912Smav strlcat(w->name, HDA_COLORS[color], sizeof(w->name)); 2641186912Smav strlcat(w->name, " ", sizeof(w->name)); 2642186912Smav } 2643186912Smav strlcat(w->name, HDA_CONNS[conn], sizeof(w->name)); 2644162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2645162922Sariff} 2646162922Sariff 2647182999Smavstatic uint32_t 2648182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2649182999Smav{ 2650182999Smav struct hdac_softc *sc; 2651182999Smav uint32_t caps, orig, id; 2652182999Smav nid_t cad, nid, beeper = -1; 2653182999Smav 2654182999Smav sc = w->devinfo->codec->sc; 2655182999Smav cad = w->devinfo->codec->cad; 2656182999Smav nid = w->nid; 2657182999Smav id = hdac_codec_id(w->devinfo->codec); 2658182999Smav 2659182999Smav caps = hdac_command(sc, 2660182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2661182999Smav cad); 2662182999Smav orig = caps; 2663182999Smav 2664182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2665182999Smav alone. Also most of BIOSes does not declare beeper pin. 2666182999Smav Change beeper pin node type to beeper to help parser. */ 2667182999Smav *waspin = 0; 2668182999Smav switch (id) { 2669187721Smav case HDA_CODEC_AD1882: 2670187721Smav case HDA_CODEC_AD1883: 2671187721Smav case HDA_CODEC_AD1984: 2672187721Smav case HDA_CODEC_AD1984A: 2673187721Smav case HDA_CODEC_AD1984B: 2674187721Smav case HDA_CODEC_AD1987: 2675182999Smav case HDA_CODEC_AD1988: 2676182999Smav case HDA_CODEC_AD1988B: 2677187721Smav case HDA_CODEC_AD1989B: 2678182999Smav beeper = 26; 2679182999Smav break; 2680182999Smav case HDA_CODEC_ALC260: 2681182999Smav beeper = 23; 2682182999Smav break; 2683182999Smav case HDA_CODEC_ALC262: 2684182999Smav case HDA_CODEC_ALC268: 2685182999Smav case HDA_CODEC_ALC880: 2686182999Smav case HDA_CODEC_ALC882: 2687182999Smav case HDA_CODEC_ALC883: 2688182999Smav case HDA_CODEC_ALC885: 2689182999Smav case HDA_CODEC_ALC888: 2690182999Smav case HDA_CODEC_ALC889: 2691182999Smav beeper = 29; 2692182999Smav break; 2693182999Smav } 2694182999Smav if (nid == beeper) { 2695182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2696182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2697182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2698182999Smav *waspin = 1; 2699182999Smav } 2700182999Smav 2701182999Smav HDA_BOOTVERBOSE( 2702182999Smav if (caps != orig) { 2703182999Smav device_printf(sc->dev, 2704182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2705182999Smav nid, orig, caps); 2706182999Smav } 2707182999Smav ); 2708182999Smav 2709182999Smav return (caps); 2710182999Smav} 2711182999Smav 2712162922Sariffstatic void 2713162922Sariffhdac_widget_parse(struct hdac_widget *w) 2714162922Sariff{ 2715162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2716162922Sariff uint32_t wcap, cap; 2717162922Sariff char *typestr; 2718162922Sariff nid_t cad = w->devinfo->codec->cad; 2719162922Sariff nid_t nid = w->nid; 2720162922Sariff 2721182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2722182999Smav 2723162922Sariff w->param.widget_cap = wcap; 2724162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2725162922Sariff 2726162922Sariff switch (w->type) { 2727162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2728162922Sariff typestr = "audio output"; 2729162922Sariff break; 2730162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2731162922Sariff typestr = "audio input"; 2732162922Sariff break; 2733162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2734162922Sariff typestr = "audio mixer"; 2735162922Sariff break; 2736162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2737162922Sariff typestr = "audio selector"; 2738162922Sariff break; 2739162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2740162922Sariff typestr = "pin"; 2741162922Sariff break; 2742162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2743162922Sariff typestr = "power widget"; 2744162922Sariff break; 2745162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2746162922Sariff typestr = "volume widget"; 2747162922Sariff break; 2748162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2749162922Sariff typestr = "beep widget"; 2750162922Sariff break; 2751162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2752162922Sariff typestr = "vendor widget"; 2753162922Sariff break; 2754162922Sariff default: 2755162922Sariff typestr = "unknown type"; 2756162922Sariff break; 2757162922Sariff } 2758162922Sariff 2759162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2760162922Sariff 2761162922Sariff hdac_widget_connection_parse(w); 2762162922Sariff 2763162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2764162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2765162922Sariff w->param.outamp_cap = 2766162922Sariff hdac_command(sc, 2767162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2768162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2769162922Sariff else 2770162922Sariff w->param.outamp_cap = 2771162922Sariff w->devinfo->function.audio.outamp_cap; 2772162922Sariff } else 2773162922Sariff w->param.outamp_cap = 0; 2774162922Sariff 2775162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2776162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2777162922Sariff w->param.inamp_cap = 2778162922Sariff hdac_command(sc, 2779162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2780162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2781162922Sariff else 2782162922Sariff w->param.inamp_cap = 2783162922Sariff w->devinfo->function.audio.inamp_cap; 2784162922Sariff } else 2785162922Sariff w->param.inamp_cap = 0; 2786162922Sariff 2787162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2788162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2789162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2790162922Sariff cap = hdac_command(sc, 2791162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2792162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2793162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2794162922Sariff w->devinfo->function.audio.supp_stream_formats; 2795162922Sariff cap = hdac_command(sc, 2796162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2797162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2798162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2799162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2800162922Sariff } else { 2801162922Sariff w->param.supp_stream_formats = 2802162922Sariff w->devinfo->function.audio.supp_stream_formats; 2803162922Sariff w->param.supp_pcm_size_rate = 2804162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2805162922Sariff } 2806162922Sariff } else { 2807162922Sariff w->param.supp_stream_formats = 0; 2808162922Sariff w->param.supp_pcm_size_rate = 0; 2809162922Sariff } 2810162922Sariff 2811162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2812162922Sariff hdac_widget_pin_parse(w); 2813162922Sariff} 2814162922Sariff 2815162922Sariffstatic struct hdac_widget * 2816162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2817162922Sariff{ 2818162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2819162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2820162922Sariff return (NULL); 2821162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2822162922Sariff} 2823162922Sariff 2824164614Sariffstatic __inline int 2825164614Sariffhda_poll_channel(struct hdac_chan *ch) 2826164614Sariff{ 2827164614Sariff uint32_t sz, delta; 2828164614Sariff volatile uint32_t ptr; 2829164614Sariff 2830171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2831164614Sariff return (0); 2832164614Sariff 2833164614Sariff sz = ch->blksz * ch->blkcnt; 2834169277Sariff if (ch->dmapos != NULL) 2835169277Sariff ptr = *(ch->dmapos); 2836169277Sariff else 2837169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2838169277Sariff ch->off + HDAC_SDLPIB); 2839164614Sariff ch->ptr = ptr; 2840164614Sariff ptr %= sz; 2841164614Sariff ptr &= ~(ch->blksz - 1); 2842164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2843164614Sariff 2844164614Sariff if (delta < ch->blksz) 2845164614Sariff return (0); 2846164614Sariff 2847164614Sariff ch->prevptr = ptr; 2848164614Sariff 2849164614Sariff return (1); 2850164614Sariff} 2851164614Sariff 2852162922Sariffstatic void 2853164614Sariffhda_poll_callback(void *arg) 2854164614Sariff{ 2855164614Sariff struct hdac_softc *sc = arg; 2856171141Sariff uint32_t trigger; 2857182999Smav int i, active = 0; 2858164614Sariff 2859164614Sariff if (sc == NULL) 2860164614Sariff return; 2861164614Sariff 2862164614Sariff hdac_lock(sc); 2863182999Smav if (sc->polling == 0) { 2864164614Sariff hdac_unlock(sc); 2865164614Sariff return; 2866164614Sariff } 2867164614Sariff 2868171141Sariff trigger = 0; 2869182999Smav for (i = 0; i < sc->num_chans; i++) { 2870182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2871182999Smav continue; 2872182999Smav active = 1; 2873182999Smav if (hda_poll_channel(&sc->chans[i])) 2874182999Smav trigger |= (1 << i); 2875182999Smav } 2876164614Sariff 2877164614Sariff /* XXX */ 2878182999Smav if (active) 2879182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2880182999Smav hda_poll_callback, sc); 2881164614Sariff 2882164614Sariff hdac_unlock(sc); 2883164614Sariff 2884182999Smav for (i = 0; i < sc->num_chans; i++) { 2885182999Smav if (trigger & (1 << i)) 2886182999Smav chn_intr(sc->chans[i].c); 2887182999Smav } 2888164614Sariff} 2889164614Sariff 2890164614Sariffstatic int 2891164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2892164614Sariff{ 2893164614Sariff struct hdac_rirb *rirb_base, *rirb; 2894164614Sariff struct hdac_codec *codec; 2895164614Sariff struct hdac_command_list *commands; 2896164614Sariff nid_t cad; 2897164614Sariff uint32_t resp; 2898164614Sariff uint8_t rirbwp; 2899171141Sariff int ret; 2900164614Sariff 2901164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2902164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2903169277Sariff#if 0 2904164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2905164614Sariff BUS_DMASYNC_POSTREAD); 2906169277Sariff#endif 2907164614Sariff 2908171141Sariff ret = 0; 2909171141Sariff 2910164614Sariff while (sc->rirb_rp != rirbwp) { 2911164614Sariff sc->rirb_rp++; 2912164614Sariff sc->rirb_rp %= sc->rirb_size; 2913164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2914164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2915164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2916164614Sariff sc->codecs[cad] == NULL) 2917164614Sariff continue; 2918164614Sariff resp = rirb->response; 2919164614Sariff codec = sc->codecs[cad]; 2920164614Sariff commands = codec->commands; 2921164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2922164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2923164614Sariff ((resp >> 26) & 0xffff); 2924164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2925164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2926164614Sariff codec->responses_received < commands->num_commands) 2927164614Sariff commands->responses[codec->responses_received++] = 2928164614Sariff resp; 2929164614Sariff ret++; 2930164614Sariff } 2931164614Sariff 2932164614Sariff return (ret); 2933164614Sariff} 2934164614Sariff 2935164614Sariffstatic int 2936164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2937164614Sariff{ 2938164614Sariff nid_t cad; 2939164614Sariff uint32_t tag; 2940164614Sariff int ret = 0; 2941164614Sariff 2942164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2943164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2944164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2945164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2946164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2947164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2948164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2949164614Sariff ret++; 2950164614Sariff } 2951164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2952164614Sariff } 2953164614Sariff 2954164614Sariff return (ret); 2955164614Sariff} 2956164614Sariff 2957164614Sariffstatic void 2958164614Sariffhdac_poll_callback(void *arg) 2959164614Sariff{ 2960164614Sariff struct hdac_softc *sc = arg; 2961164614Sariff if (sc == NULL) 2962164614Sariff return; 2963166796Sariff 2964164614Sariff hdac_lock(sc); 2965169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2966164614Sariff hdac_unlock(sc); 2967164614Sariff return; 2968164614Sariff } 2969171141Sariff if (hdac_rirb_flush(sc) != 0) 2970171141Sariff hdac_unsolq_flush(sc); 2971169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2972164614Sariff hdac_unlock(sc); 2973164614Sariff} 2974164614Sariff 2975164614Sariffstatic void 2976182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2977182999Smav{ 2978182999Smav int i, pollticks, min = 1000000; 2979182999Smav struct hdac_chan *ch; 2980182999Smav 2981182999Smav for (i = 0; i < sc->num_chans; i++) { 2982182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2983182999Smav continue; 2984182999Smav ch = &sc->chans[i]; 2985182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2986193640Sariff ((uint64_t)sndbuf_getalign(ch->b) * sndbuf_getspd(ch->b)); 2987182999Smav pollticks >>= 1; 2988182999Smav if (pollticks > hz) 2989182999Smav pollticks = hz; 2990182999Smav if (pollticks < 1) { 2991182999Smav HDA_BOOTVERBOSE( 2992182999Smav device_printf(sc->dev, 2993182999Smav "%s: pollticks=%d < 1 !\n", 2994182999Smav __func__, pollticks); 2995182999Smav ); 2996182999Smav pollticks = 1; 2997182999Smav } 2998182999Smav if (min > pollticks) 2999182999Smav min = pollticks; 3000182999Smav } 3001182999Smav HDA_BOOTVERBOSE( 3002182999Smav device_printf(sc->dev, 3003182999Smav "%s: pollticks %d -> %d\n", 3004182999Smav __func__, sc->poll_ticks, min); 3005182999Smav ); 3006182999Smav sc->poll_ticks = min; 3007182999Smav if (min == 1000000) 3008182999Smav callout_stop(&sc->poll_hda); 3009182999Smav else 3010182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 3011182999Smav} 3012182999Smav 3013182999Smavstatic void 3014162922Sariffhdac_stream_stop(struct hdac_chan *ch) 3015162922Sariff{ 3016162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3017162922Sariff uint32_t ctl; 3018162922Sariff 3019162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3020162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3021162922Sariff HDAC_SDCTL_RUN); 3022162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3023162922Sariff 3024171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 3025164614Sariff 3026182999Smav if (sc->polling != 0) 3027182999Smav hdac_poll_reinit(sc); 3028164614Sariff 3029182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3030182999Smav ctl &= ~(1 << (ch->off >> 5)); 3031182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3032162922Sariff} 3033162922Sariff 3034162922Sariffstatic void 3035162922Sariffhdac_stream_start(struct hdac_chan *ch) 3036162922Sariff{ 3037162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3038162922Sariff uint32_t ctl; 3039162922Sariff 3040182999Smav ch->flags |= HDAC_CHN_RUNNING; 3041162922Sariff 3042182999Smav if (sc->polling != 0) 3043182999Smav hdac_poll_reinit(sc); 3044182999Smav 3045182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3046182999Smav ctl |= 1 << (ch->off >> 5); 3047182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3048182999Smav 3049182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3050182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3051182999Smav HDAC_SDCTL_RUN; 3052162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3053162922Sariff} 3054162922Sariff 3055162922Sariffstatic void 3056162922Sariffhdac_stream_reset(struct hdac_chan *ch) 3057162922Sariff{ 3058162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3059162922Sariff int timeout = 1000; 3060162922Sariff int to = timeout; 3061162922Sariff uint32_t ctl; 3062162922Sariff 3063162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3064162922Sariff ctl |= HDAC_SDCTL_SRST; 3065162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3066162922Sariff do { 3067162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3068162922Sariff if (ctl & HDAC_SDCTL_SRST) 3069162922Sariff break; 3070162922Sariff DELAY(10); 3071162922Sariff } while (--to); 3072162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 3073162922Sariff device_printf(sc->dev, "timeout in reset\n"); 3074162922Sariff } 3075162922Sariff ctl &= ~HDAC_SDCTL_SRST; 3076162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3077162922Sariff to = timeout; 3078162922Sariff do { 3079162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3080162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 3081162922Sariff break; 3082162922Sariff DELAY(10); 3083162922Sariff } while (--to); 3084163057Sariff if (ctl & HDAC_SDCTL_SRST) 3085162922Sariff device_printf(sc->dev, "can't reset!\n"); 3086162922Sariff} 3087162922Sariff 3088162922Sariffstatic void 3089162922Sariffhdac_stream_setid(struct hdac_chan *ch) 3090162922Sariff{ 3091162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3092162922Sariff uint32_t ctl; 3093162922Sariff 3094162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 3095162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 3096162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 3097162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 3098162922Sariff} 3099162922Sariff 3100162922Sariffstatic void 3101162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 3102162922Sariff{ 3103162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3104164614Sariff struct hdac_bdle *bdle; 3105162922Sariff uint64_t addr; 3106164614Sariff uint32_t blksz, blkcnt; 3107162922Sariff int i; 3108162922Sariff 3109162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 3110164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 3111162922Sariff 3112182999Smav blksz = ch->blksz; 3113182999Smav blkcnt = ch->blkcnt; 3114164614Sariff 3115164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 3116162922Sariff bdle->addrl = (uint32_t)addr; 3117162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 3118164614Sariff bdle->len = blksz; 3119182999Smav bdle->ioc = 1; 3120164614Sariff addr += blksz; 3121162922Sariff } 3122162922Sariff 3123164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 3124164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 3125162922Sariff addr = ch->bdl_dma.dma_paddr; 3126162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 3127162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 3128169277Sariff if (ch->dmapos != NULL && 3129169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 3130169277Sariff addr = sc->pos_dma.dma_paddr; 3131169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 3132169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 3133169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 3134169277Sariff } 3135162922Sariff} 3136162922Sariff 3137162922Sariffstatic int 3138162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 3139162922Sariff{ 3140162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3141162922Sariff int rc; 3142162922Sariff 3143162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 3144162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 3145162922Sariff if (rc) { 3146162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 3147162922Sariff return (rc); 3148162922Sariff } 3149162922Sariff 3150162922Sariff return (0); 3151162922Sariff} 3152162922Sariff 3153162922Sariffstatic void 3154162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 3155162922Sariff int index, int lmute, int rmute, 3156162922Sariff int left, int right, int dir) 3157162922Sariff{ 3158162922Sariff uint16_t v = 0; 3159162922Sariff 3160162922Sariff if (sc == NULL) 3161162922Sariff return; 3162162922Sariff 3163162922Sariff if (left != right || lmute != rmute) { 3164162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 3165162922Sariff (lmute << 7) | left; 3166162922Sariff hdac_command(sc, 3167164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3168162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 3169162922Sariff (rmute << 7) | right; 3170162922Sariff } else 3171162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 3172162922Sariff (lmute << 7) | left; 3173162922Sariff 3174162922Sariff hdac_command(sc, 3175162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3176162922Sariff} 3177162922Sariff 3178162922Sariffstatic void 3179162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3180162922Sariff int left, int right) 3181162922Sariff{ 3182162922Sariff struct hdac_softc *sc; 3183162922Sariff nid_t nid, cad; 3184162922Sariff int lmute, rmute; 3185162922Sariff 3186162922Sariff sc = ctl->widget->devinfo->codec->sc; 3187162922Sariff cad = ctl->widget->devinfo->codec->cad; 3188162922Sariff nid = ctl->widget->nid; 3189162922Sariff 3190182999Smav /* Save new values if valid. */ 3191182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3192182999Smav ctl->muted = mute; 3193182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3194182999Smav ctl->left = left; 3195182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3196182999Smav ctl->right = right; 3197182999Smav /* Prepare effective values */ 3198182999Smav if (ctl->forcemute) { 3199182999Smav lmute = 1; 3200182999Smav rmute = 1; 3201182999Smav left = 0; 3202182999Smav right = 0; 3203182999Smav } else { 3204162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3205162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3206182999Smav left = ctl->left; 3207182999Smav right = ctl->right; 3208162922Sariff } 3209182999Smav /* Apply effective values */ 3210162922Sariff if (ctl->dir & HDA_CTL_OUT) 3211162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3212162922Sariff lmute, rmute, left, right, 0); 3213162922Sariff if (ctl->dir & HDA_CTL_IN) 3214182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3215162922Sariff lmute, rmute, left, right, 1); 3216162922Sariff} 3217162922Sariff 3218162922Sariffstatic void 3219162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3220162922Sariff{ 3221162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3222162922Sariff return; 3223162922Sariff hdac_command(w->devinfo->codec->sc, 3224162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3225162922Sariff w->nid, index), w->devinfo->codec->cad); 3226162922Sariff w->selconn = index; 3227162922Sariff} 3228162922Sariff 3229162922Sariff 3230162922Sariff/**************************************************************************** 3231162922Sariff * uint32_t hdac_command_sendone_internal 3232162922Sariff * 3233162922Sariff * Wrapper function that sends only one command to a given codec 3234162922Sariff ****************************************************************************/ 3235162922Sariffstatic uint32_t 3236162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3237162922Sariff{ 3238162922Sariff struct hdac_command_list cl; 3239162965Sariff uint32_t response = HDAC_INVALID; 3240162922Sariff 3241163057Sariff if (!hdac_lockowned(sc)) 3242162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3243162922Sariff cl.num_commands = 1; 3244162922Sariff cl.verbs = &verb; 3245162922Sariff cl.responses = &response; 3246162922Sariff 3247162922Sariff hdac_command_send_internal(sc, &cl, cad); 3248162922Sariff 3249162922Sariff return (response); 3250162922Sariff} 3251162922Sariff 3252162922Sariff/**************************************************************************** 3253162922Sariff * hdac_command_send_internal 3254162922Sariff * 3255162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3256162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3257162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3258162922Sariff * if any. 3259162922Sariff ****************************************************************************/ 3260162922Sariffstatic void 3261162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3262162922Sariff struct hdac_command_list *commands, nid_t cad) 3263162922Sariff{ 3264162922Sariff struct hdac_codec *codec; 3265162922Sariff int corbrp; 3266162922Sariff uint32_t *corb; 3267162922Sariff int timeout; 3268162922Sariff int retry = 10; 3269164614Sariff struct hdac_rirb *rirb_base; 3270162922Sariff 3271164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3272164614Sariff commands->num_commands < 1) 3273162922Sariff return; 3274162922Sariff 3275162922Sariff codec = sc->codecs[cad]; 3276162922Sariff codec->commands = commands; 3277162922Sariff codec->responses_received = 0; 3278162922Sariff codec->verbs_sent = 0; 3279162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3280162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3281162922Sariff 3282162922Sariff do { 3283162922Sariff if (codec->verbs_sent != commands->num_commands) { 3284162922Sariff /* Queue as many verbs as possible */ 3285162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3286169277Sariff#if 0 3287162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3288162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3289169277Sariff#endif 3290162922Sariff while (codec->verbs_sent != commands->num_commands && 3291162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3292162922Sariff sc->corb_wp++; 3293162922Sariff sc->corb_wp %= sc->corb_size; 3294162922Sariff corb[sc->corb_wp] = 3295162922Sariff commands->verbs[codec->verbs_sent++]; 3296162922Sariff } 3297162922Sariff 3298162922Sariff /* Send the verbs to the codecs */ 3299169277Sariff#if 0 3300162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3301162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3302169277Sariff#endif 3303162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3304162922Sariff } 3305162922Sariff 3306162922Sariff timeout = 1000; 3307164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3308162922Sariff DELAY(10); 3309162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3310164614Sariff codec->responses_received != commands->num_commands) && --retry); 3311162922Sariff 3312162922Sariff if (retry == 0) 3313162922Sariff device_printf(sc->dev, 3314164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3315164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3316164614Sariff codec->responses_received); 3317162922Sariff 3318164614Sariff codec->commands = NULL; 3319164614Sariff codec->responses_received = 0; 3320162922Sariff codec->verbs_sent = 0; 3321162922Sariff 3322164614Sariff hdac_unsolq_flush(sc); 3323162922Sariff} 3324162922Sariff 3325162922Sariff 3326162922Sariff/**************************************************************************** 3327162922Sariff * Device Methods 3328162922Sariff ****************************************************************************/ 3329162922Sariff 3330162922Sariff/**************************************************************************** 3331162922Sariff * int hdac_probe(device_t) 3332162922Sariff * 3333162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3334162922Sariff * match using the subclass of the device. 3335162922Sariff ****************************************************************************/ 3336162922Sariffstatic int 3337162922Sariffhdac_probe(device_t dev) 3338162922Sariff{ 3339162922Sariff int i, result; 3340163257Sariff uint32_t model; 3341163257Sariff uint16_t class, subclass; 3342162922Sariff char desc[64]; 3343162922Sariff 3344162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3345162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3346162922Sariff class = pci_get_class(dev); 3347162922Sariff subclass = pci_get_subclass(dev); 3348162922Sariff 3349162922Sariff bzero(desc, sizeof(desc)); 3350162922Sariff result = ENXIO; 3351162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3352162922Sariff if (hdac_devices[i].model == model) { 3353162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3354162922Sariff result = BUS_PROBE_DEFAULT; 3355162922Sariff break; 3356162922Sariff } 3357163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3358162922Sariff class == PCIC_MULTIMEDIA && 3359162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3360162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3361162922Sariff result = BUS_PROBE_GENERIC; 3362162922Sariff break; 3363162922Sariff } 3364162922Sariff } 3365162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3366162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3367162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3368162922Sariff result = BUS_PROBE_GENERIC; 3369162922Sariff } 3370162922Sariff if (result != ENXIO) { 3371162922Sariff strlcat(desc, " High Definition Audio Controller", 3372162922Sariff sizeof(desc)); 3373162922Sariff device_set_desc_copy(dev, desc); 3374162922Sariff } 3375162922Sariff 3376162922Sariff return (result); 3377162922Sariff} 3378162922Sariff 3379162922Sariffstatic void * 3380162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3381162922Sariff struct pcm_channel *c, int dir) 3382162922Sariff{ 3383182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3384182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3385162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3386162922Sariff struct hdac_chan *ch; 3387182999Smav int i, ord = 0, chid; 3388162922Sariff 3389162922Sariff hdac_lock(sc); 3390182999Smav 3391182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3392182999Smav ch = &sc->chans[chid]; 3393182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3394182999Smav if (ch->dir == sc->chans[i].dir) 3395182999Smav ord++; 3396182999Smav } 3397162922Sariff if (dir == PCMDIR_PLAY) { 3398182999Smav ch->off = (sc->num_iss + ord) << 5; 3399162922Sariff } else { 3400182999Smav ch->off = ord << 5; 3401162922Sariff } 3402182999Smav 3403162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3404162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3405162922Sariff ch->pcmrates[0] = 48000; 3406162922Sariff ch->pcmrates[1] = 0; 3407162922Sariff } 3408169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3409169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3410169277Sariff (sc->streamcnt * 8)); 3411169277Sariff else 3412169277Sariff ch->dmapos = NULL; 3413169277Sariff ch->sid = ++sc->streamcnt; 3414169277Sariff ch->dir = dir; 3415162922Sariff ch->b = b; 3416162922Sariff ch->c = c; 3417182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3418182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3419162922Sariff hdac_unlock(sc); 3420162922Sariff 3421162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3422162922Sariff ch->blkcnt = 0; 3423162922Sariff return (NULL); 3424162922Sariff } 3425162922Sariff 3426169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3427171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3428182999Smav pdevinfo->chan_size) != 0) 3429162922Sariff return (NULL); 3430162922Sariff 3431162922Sariff return (ch); 3432162922Sariff} 3433162922Sariff 3434162922Sariffstatic int 3435162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3436162922Sariff{ 3437162922Sariff struct hdac_chan *ch = data; 3438162922Sariff int i; 3439162922Sariff 3440162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3441162922Sariff if (format == ch->caps.fmtlist[i]) { 3442162922Sariff ch->fmt = format; 3443162922Sariff return (0); 3444162922Sariff } 3445162922Sariff } 3446162922Sariff 3447162922Sariff return (EINVAL); 3448162922Sariff} 3449162922Sariff 3450193640Sariffstatic uint32_t 3451162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3452162922Sariff{ 3453162922Sariff struct hdac_chan *ch = data; 3454164614Sariff uint32_t spd = 0, threshold; 3455162922Sariff int i; 3456162922Sariff 3457162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3458162922Sariff spd = ch->pcmrates[i]; 3459164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3460164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3461164614Sariff if (speed < threshold) 3462162922Sariff break; 3463162922Sariff } 3464162922Sariff 3465164614Sariff if (spd == 0) /* impossible */ 3466162922Sariff ch->spd = 48000; 3467162922Sariff else 3468162922Sariff ch->spd = spd; 3469162922Sariff 3470162922Sariff return (ch->spd); 3471162922Sariff} 3472162922Sariff 3473162922Sariffstatic void 3474162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3475162922Sariff{ 3476162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3477182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3478173817Sariff struct hdac_widget *w; 3479182999Smav int i, chn, totalchn, c; 3480162922Sariff nid_t cad = ch->devinfo->codec->cad; 3481182999Smav uint16_t fmt, dfmt; 3482202127Smav uint16_t chmap[2][5] = {{ 0x0010, 0x0001, 0x0201, 0x0231, 0x0231 }, /* 5.1 */ 3483202127Smav { 0x0010, 0x0001, 0x2001, 0x2031, 0x2431 }};/* 7.1 */ 3484202127Smav int map = -1; 3485162922Sariff 3486202127Smav totalchn = AFMT_CHANNEL(ch->fmt); 3487183097Smav HDA_BOOTHVERBOSE( 3488182999Smav device_printf(ch->pdevinfo->dev, 3489182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3490182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3491182999Smav ch->fmt, ch->spd); 3492182999Smav ); 3493162922Sariff fmt = 0; 3494162922Sariff if (ch->fmt & AFMT_S16_LE) 3495162922Sariff fmt |= ch->bit16 << 4; 3496162922Sariff else if (ch->fmt & AFMT_S32_LE) 3497162922Sariff fmt |= ch->bit32 << 4; 3498162922Sariff else 3499162922Sariff fmt |= 1 << 4; 3500162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3501162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3502162922Sariff fmt |= hda_rate_tab[i].base; 3503162922Sariff fmt |= hda_rate_tab[i].mul; 3504162922Sariff fmt |= hda_rate_tab[i].div; 3505162922Sariff break; 3506162922Sariff } 3507162922Sariff } 3508202127Smav fmt |= (totalchn - 1); 3509162922Sariff 3510202127Smav /* Set channel mapping for known speaker setups. */ 3511202127Smav if (as->pinset == 0x0007 || as->pinset == 0x0013) /* Standard 5.1 */ 3512202127Smav map = 0; 3513202127Smav else if (as->pinset == 0x0017) /* Standard 7.1 */ 3514202127Smav map = 1; 3515162922Sariff 3516162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3517182999Smav 3518182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3519182999Smav if (ch->fmt & AFMT_AC3) 3520182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3521162922Sariff 3522173817Sariff chn = 0; 3523162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3524173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3525173817Sariff if (w == NULL) 3526173817Sariff continue; 3527182999Smav 3528202127Smav /* If HP redirection is enabled, but failed to use same 3529202127Smav DAC, make last DAC to duplicate first one. */ 3530204351Smav if (as->fakeredir && i == (as->pincnt - 1)) { 3531202127Smav c = (ch->sid << 4); 3532202127Smav } else { 3533202127Smav if (map >= 0) /* Map known speaker setups. */ 3534202127Smav chn = (((chmap[map][totalchn / 2] >> i * 4) & 3535202127Smav 0xf) - 1) * 2; 3536202127Smav if (chn < 0 || chn >= totalchn) { 3537202127Smav c = 0; 3538202127Smav } else { 3539202127Smav c = (ch->sid << 4) | chn; 3540202127Smav } 3541202127Smav } 3542183097Smav HDA_BOOTHVERBOSE( 3543182999Smav device_printf(ch->pdevinfo->dev, 3544182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3545202127Smav "fmt=0x%04x, dfmt=0x%04x, chan=0x%04x\n", 3546162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3547202127Smav ch->io[i], fmt, dfmt, c); 3548162922Sariff ); 3549162922Sariff hdac_command(sc, 3550162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3551182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3552174025Sariff hdac_command(sc, 3553182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3554174025Sariff cad); 3555182999Smav } 3556182999Smav hdac_command(sc, 3557182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3558197611Smav#if 0 3559197611Smav hdac_command(sc, 3560197611Smav HDA_CMD_SET_CONV_CHAN_COUNT(cad, ch->io[i], 1), cad); 3561197611Smav hdac_command(sc, 3562197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x00), cad); 3563197611Smav hdac_command(sc, 3564197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x11), cad); 3565197611Smav#endif 3566202127Smav chn += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 3567162922Sariff } 3568162922Sariff} 3569162922Sariff 3570202156Smav/* 3571202156Smav * Greatest Common Divisor. 3572202156Smav */ 3573202156Smavstatic unsigned 3574202156Smavgcd(unsigned a, unsigned b) 3575202156Smav{ 3576202156Smav u_int c; 3577202156Smav 3578202156Smav while (b != 0) { 3579202156Smav c = a; 3580202156Smav a = b; 3581202156Smav b = (c % b); 3582202156Smav } 3583202156Smav return (a); 3584202156Smav} 3585202156Smav 3586202156Smav/* 3587202156Smav * Least Common Multiple. 3588202156Smav */ 3589202156Smavstatic unsigned 3590202156Smavlcm(unsigned a, unsigned b) 3591202156Smav{ 3592202156Smav 3593202156Smav return ((a * b) / gcd(a, b)); 3594202156Smav} 3595202156Smav 3596162922Sariffstatic int 3597167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3598167648Sariff uint32_t blksz, uint32_t blkcnt) 3599162922Sariff{ 3600162922Sariff struct hdac_chan *ch = data; 3601164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3602162922Sariff 3603202156Smav blksz -= blksz % lcm(HDAC_DMA_ALIGNMENT, sndbuf_getalign(ch->b)); 3604162922Sariff 3605167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3606167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3607167648Sariff if (blksz < HDA_BLK_MIN) 3608167648Sariff blksz = HDA_BLK_MIN; 3609167648Sariff if (blkcnt > HDA_BDL_MAX) 3610167648Sariff blkcnt = HDA_BDL_MAX; 3611167648Sariff if (blkcnt < HDA_BDL_MIN) 3612167648Sariff blkcnt = HDA_BDL_MIN; 3613164614Sariff 3614167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3615167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3616167648Sariff blkcnt >>= 1; 3617167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3618167648Sariff blksz >>= 1; 3619167648Sariff else 3620167648Sariff break; 3621167648Sariff } 3622167648Sariff 3623164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3624167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3625167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3626164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3627167648Sariff __func__, blksz, blkcnt); 3628164614Sariff 3629164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3630167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3631164614Sariff 3632193640Sariff return (0); 3633167648Sariff} 3634167648Sariff 3635193640Sariffstatic uint32_t 3636167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3637167648Sariff{ 3638167648Sariff struct hdac_chan *ch = data; 3639167648Sariff 3640182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3641167648Sariff 3642162922Sariff return (ch->blksz); 3643162922Sariff} 3644162922Sariff 3645162922Sariffstatic void 3646162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3647162922Sariff{ 3648162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3649182999Smav struct hdac_widget *w; 3650162922Sariff nid_t cad = devinfo->codec->cad; 3651162922Sariff int i; 3652162922Sariff 3653162922Sariff hdac_stream_stop(ch); 3654162922Sariff 3655162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3656182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3657182999Smav if (w == NULL) 3658182999Smav continue; 3659182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3660182999Smav hdac_command(sc, 3661182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3662182999Smav cad); 3663182999Smav } 3664162922Sariff hdac_command(sc, 3665162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3666162922Sariff 0), cad); 3667162922Sariff } 3668162922Sariff} 3669162922Sariff 3670162922Sariffstatic void 3671162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3672162922Sariff{ 3673162922Sariff ch->ptr = 0; 3674162922Sariff ch->prevptr = 0; 3675162922Sariff hdac_stream_stop(ch); 3676162922Sariff hdac_stream_reset(ch); 3677162922Sariff hdac_bdl_setup(ch); 3678162922Sariff hdac_stream_setid(ch); 3679162922Sariff hdac_stream_setup(ch); 3680162922Sariff hdac_stream_start(ch); 3681162922Sariff} 3682162922Sariff 3683162922Sariffstatic int 3684162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3685162922Sariff{ 3686162922Sariff struct hdac_chan *ch = data; 3687162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3688162922Sariff 3689170521Sariff if (!PCMTRIG_COMMON(go)) 3690170521Sariff return (0); 3691170521Sariff 3692162922Sariff hdac_lock(sc); 3693162922Sariff switch (go) { 3694162922Sariff case PCMTRIG_START: 3695162922Sariff hdac_channel_start(sc, ch); 3696162922Sariff break; 3697162922Sariff case PCMTRIG_STOP: 3698162922Sariff case PCMTRIG_ABORT: 3699162922Sariff hdac_channel_stop(sc, ch); 3700162922Sariff break; 3701167610Sariff default: 3702167610Sariff break; 3703162922Sariff } 3704162922Sariff hdac_unlock(sc); 3705162922Sariff 3706162922Sariff return (0); 3707162922Sariff} 3708162922Sariff 3709193640Sariffstatic uint32_t 3710162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3711162922Sariff{ 3712162922Sariff struct hdac_chan *ch = data; 3713162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3714162922Sariff uint32_t ptr; 3715162922Sariff 3716162922Sariff hdac_lock(sc); 3717164614Sariff if (sc->polling != 0) 3718164614Sariff ptr = ch->ptr; 3719169277Sariff else if (ch->dmapos != NULL) 3720169277Sariff ptr = *(ch->dmapos); 3721164614Sariff else 3722164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3723162922Sariff hdac_unlock(sc); 3724162922Sariff 3725164614Sariff /* 3726164614Sariff * Round to available space and force 128 bytes aligment. 3727164614Sariff */ 3728164614Sariff ptr %= ch->blksz * ch->blkcnt; 3729167648Sariff ptr &= HDA_BLK_ALIGN; 3730162922Sariff 3731162922Sariff return (ptr); 3732162922Sariff} 3733162922Sariff 3734162922Sariffstatic struct pcmchan_caps * 3735162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3736162922Sariff{ 3737162922Sariff return (&((struct hdac_chan *)data)->caps); 3738162922Sariff} 3739162922Sariff 3740162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3741162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3742162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3743162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3744162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3745167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3746162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3747162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3748162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3749193640Sariff KOBJMETHOD_END 3750162922Sariff}; 3751162922SariffCHANNEL_DECLARE(hdac_channel); 3752162922Sariff 3753162922Sariffstatic int 3754162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3755162922Sariff{ 3756182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3757182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3758162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3759162922Sariff struct hdac_widget *w, *cw; 3760162922Sariff struct hdac_audio_ctl *ctl; 3761162922Sariff uint32_t mask, recmask, id; 3762162922Sariff int i, j, softpcmvol; 3763162922Sariff 3764162922Sariff hdac_lock(sc); 3765162922Sariff 3766182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3767182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3768182999Smav pdevinfo->left[i] = 100; 3769182999Smav pdevinfo->right[i] = 100; 3770182999Smav } 3771182999Smav 3772162922Sariff mask = 0; 3773162922Sariff recmask = 0; 3774182999Smav id = hdac_codec_id(devinfo->codec); 3775162922Sariff 3776182999Smav /* Declate EAPD as ogain control. */ 3777182999Smav if (pdevinfo->play >= 0) { 3778182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3779182999Smav w = hdac_widget_get(devinfo, i); 3780182999Smav if (w == NULL || w->enable == 0) 3781182999Smav continue; 3782182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3783182999Smav w->param.eapdbtl == HDAC_INVALID || 3784182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3785182999Smav continue; 3786182999Smav mask |= SOUND_MASK_OGAIN; 3787162922Sariff break; 3788162922Sariff } 3789162922Sariff } 3790162922Sariff 3791182999Smav /* Declare volume controls assigned to this association. */ 3792162922Sariff i = 0; 3793162922Sariff ctl = NULL; 3794162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3795182999Smav if (ctl->enable == 0) 3796162922Sariff continue; 3797182999Smav if ((pdevinfo->play >= 0 && 3798182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3799182999Smav (pdevinfo->rec >= 0 && 3800182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3801182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3802182999Smav mask |= ctl->ossmask; 3803162922Sariff } 3804162922Sariff 3805182999Smav /* Declare record sources available to this association. */ 3806182999Smav if (pdevinfo->rec >= 0) { 3807182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3808182999Smav for (i = 0; ch->io[i] != -1; i++) { 3809182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3810182999Smav if (w == NULL || w->enable == 0) 3811182999Smav continue; 3812182999Smav for (j = 0; j < w->nconns; j++) { 3813182999Smav if (w->connsenable[j] == 0) 3814162922Sariff continue; 3815182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3816182999Smav if (cw == NULL || cw->enable == 0) 3817165992Sariff continue; 3818182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3819182999Smav cw->bindas != -2) 3820165992Sariff continue; 3821182999Smav recmask |= cw->ossmask; 3822165992Sariff } 3823182999Smav } 3824182999Smav } 3825182999Smav 3826185230Smav /* Declare soft PCM volume if needed. */ 3827193640Sariff if (pdevinfo->play >= 0) { 3828182999Smav ctl = NULL; 3829182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3830182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3831182999Smav softpcmvol = 1; 3832182999Smav mask |= SOUND_MASK_PCM; 3833162922Sariff } else { 3834182999Smav softpcmvol = 0; 3835182999Smav i = 0; 3836182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3837182999Smav if (ctl->enable == 0) 3838162922Sariff continue; 3839182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3840182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3841162922Sariff continue; 3842182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3843182999Smav continue; 3844182999Smav if (ctl->step > 0) 3845182999Smav break; 3846162922Sariff } 3847162922Sariff } 3848182999Smav 3849182999Smav if (softpcmvol == 1 || ctl == NULL) { 3850182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3851182999Smav HDA_BOOTVERBOSE( 3852182999Smav device_printf(pdevinfo->dev, 3853182999Smav "%s Soft PCM volume\n", 3854182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3855182999Smav ); 3856182999Smav } 3857185230Smav } 3858182999Smav 3859185230Smav /* Declare master volume if needed. */ 3860185230Smav if (pdevinfo->play >= 0) { 3861185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3862185230Smav SOUND_MASK_PCM) { 3863182999Smav mask |= SOUND_MASK_VOLUME; 3864182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3865182999Smav SOUND_MASK_PCM); 3866182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3867182999Smav SOUND_MIXER_NONE); 3868182999Smav HDA_BOOTVERBOSE( 3869182999Smav device_printf(pdevinfo->dev, 3870182999Smav "Forcing master volume with PCM\n"); 3871182999Smav ); 3872182999Smav } 3873162922Sariff } 3874162922Sariff 3875169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3876169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3877162922Sariff 3878162922Sariff mix_setrecdevs(m, recmask); 3879162922Sariff mix_setdevs(m, mask); 3880162922Sariff 3881162922Sariff hdac_unlock(sc); 3882162922Sariff 3883162922Sariff return (0); 3884162922Sariff} 3885162922Sariff 3886162922Sariffstatic int 3887162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3888162922Sariff unsigned left, unsigned right) 3889162922Sariff{ 3890182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3891182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3892162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3893162922Sariff struct hdac_widget *w; 3894162922Sariff struct hdac_audio_ctl *ctl; 3895182999Smav uint32_t mute; 3896182999Smav int lvol, rvol; 3897182999Smav int i, j; 3898162922Sariff 3899162922Sariff hdac_lock(sc); 3900182999Smav /* Save new values. */ 3901182999Smav pdevinfo->left[dev] = left; 3902182999Smav pdevinfo->right[dev] = right; 3903182999Smav 3904182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3905162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3906163257Sariff uint32_t orig; 3907182999Smav w = NULL; 3908182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3909182999Smav w = hdac_widget_get(devinfo, i); 3910182999Smav if (w == NULL || w->enable == 0) 3911182999Smav continue; 3912182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3913182999Smav w->param.eapdbtl == HDAC_INVALID) 3914182999Smav continue; 3915182999Smav break; 3916162922Sariff } 3917182999Smav if (i >= devinfo->endnode) { 3918162922Sariff hdac_unlock(sc); 3919162922Sariff return (-1); 3920162922Sariff } 3921163257Sariff orig = w->param.eapdbtl; 3922163432Sariff if (left == 0) 3923162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3924162922Sariff else 3925162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3926163257Sariff if (orig != w->param.eapdbtl) { 3927163432Sariff uint32_t val; 3928163432Sariff 3929163432Sariff val = w->param.eapdbtl; 3930163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3931163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3932163257Sariff hdac_command(sc, 3933163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3934163432Sariff w->nid, val), devinfo->codec->cad); 3935163257Sariff } 3936162922Sariff hdac_unlock(sc); 3937162922Sariff return (left | (left << 8)); 3938162922Sariff } 3939162922Sariff 3940182999Smav /* Recalculate all controls related to this OSS device. */ 3941162922Sariff i = 0; 3942162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3943182999Smav if (ctl->enable == 0 || 3944162922Sariff !(ctl->ossmask & (1 << dev))) 3945162922Sariff continue; 3946182999Smav if (!((pdevinfo->play >= 0 && 3947182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3948182999Smav (pdevinfo->rec >= 0 && 3949182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3950182999Smav ctl->widget->bindas == -2)) 3951182999Smav continue; 3952182999Smav 3953182999Smav lvol = 100; 3954182999Smav rvol = 100; 3955182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3956182999Smav if (ctl->ossmask & (1 << j)) { 3957182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3958182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3959162922Sariff } 3960162922Sariff } 3961202789Smav mute = (lvol == 0) ? HDA_AMP_MUTE_LEFT : 0; 3962202789Smav mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3963182999Smav lvol = (lvol * ctl->step + 50) / 100; 3964182999Smav rvol = (rvol * ctl->step + 50) / 100; 3965162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3966162922Sariff } 3967162922Sariff hdac_unlock(sc); 3968162922Sariff 3969162922Sariff return (left | (right << 8)); 3970162922Sariff} 3971162922Sariff 3972182999Smav/* 3973182999Smav * Commutate specified record source. 3974182999Smav */ 3975182999Smavstatic uint32_t 3976182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3977162922Sariff{ 3978182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3979162922Sariff struct hdac_widget *w, *cw; 3980182999Smav struct hdac_audio_ctl *ctl; 3981182999Smav char buf[64]; 3982182999Smav int i, muted; 3983182999Smav uint32_t res = 0; 3984162922Sariff 3985182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3986182999Smav return (0); 3987182999Smav 3988182999Smav w = hdac_widget_get(devinfo, nid); 3989182999Smav if (w == NULL || w->enable == 0) 3990182999Smav return (0); 3991182999Smav 3992182999Smav for (i = 0; i < w->nconns; i++) { 3993182999Smav if (w->connsenable[i] == 0) 3994182999Smav continue; 3995182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3996182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3997182999Smav continue; 3998182999Smav /* Call recursively to trace signal to it's source if needed. */ 3999182999Smav if ((src & cw->ossmask) != 0) { 4000182999Smav if (cw->ossdev < 0) { 4001182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 4002182999Smav w->conns[i], depth + 1); 4003182999Smav } else { 4004182999Smav res |= cw->ossmask; 4005182999Smav } 4006182999Smav } 4007182999Smav /* We have two special cases: mixers and others (selectors). */ 4008182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 4009182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 4010182999Smav w->nid, HDA_CTL_IN, i, 1); 4011182999Smav if (ctl == NULL) 4012182999Smav continue; 4013182999Smav /* If we have input control on this node mute them 4014182999Smav * according to requested sources. */ 4015182999Smav muted = (src & cw->ossmask) ? 0 : 1; 4016182999Smav if (muted != ctl->forcemute) { 4017182999Smav ctl->forcemute = muted; 4018182999Smav hdac_audio_ctl_amp_set(ctl, 4019182999Smav HDA_AMP_MUTE_DEFAULT, 4020182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 4021182999Smav } 4022183097Smav HDA_BOOTHVERBOSE( 4023182999Smav device_printf(pdevinfo->dev, 4024182999Smav "Recsel (%s): nid %d source %d %s\n", 4025182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4026182999Smav src, buf, sizeof(buf)), 4027182999Smav nid, i, muted?"mute":"unmute"); 4028182999Smav ); 4029182999Smav } else { 4030182999Smav if (w->nconns == 1) 4031182999Smav break; 4032182999Smav if ((src & cw->ossmask) == 0) 4033182999Smav continue; 4034182999Smav /* If we found requested source - select it and exit. */ 4035182999Smav hdac_widget_connection_select(w, i); 4036183097Smav HDA_BOOTHVERBOSE( 4037182999Smav device_printf(pdevinfo->dev, 4038182999Smav "Recsel (%s): nid %d source %d select\n", 4039182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4040182999Smav src, buf, sizeof(buf)), 4041182999Smav nid, i); 4042182999Smav ); 4043162922Sariff break; 4044162922Sariff } 4045162922Sariff } 4046182999Smav return (res); 4047182999Smav} 4048162922Sariff 4049182999Smavstatic uint32_t 4050182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 4051182999Smav{ 4052182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 4053182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 4054182999Smav struct hdac_widget *w; 4055182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4056182999Smav struct hdac_chan *ch; 4057182999Smav int i; 4058182999Smav uint32_t ret = 0xffffffff; 4059182999Smav 4060162922Sariff hdac_lock(sc); 4061162922Sariff 4062182999Smav /* Commutate requested recsrc for each ADC. */ 4063182999Smav ch = &sc->chans[pdevinfo->rec]; 4064182999Smav for (i = 0; ch->io[i] != -1; i++) { 4065182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 4066162965Sariff if (w == NULL || w->enable == 0) 4067162922Sariff continue; 4068182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 4069162922Sariff } 4070162922Sariff 4071162922Sariff hdac_unlock(sc); 4072162922Sariff 4073182999Smav return ((ret == 0xffffffff)? 0 : ret); 4074162922Sariff} 4075162922Sariff 4076162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 4077162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 4078162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 4079162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 4080193640Sariff KOBJMETHOD_END 4081162922Sariff}; 4082162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 4083162922Sariff 4084171141Sariffstatic void 4085171141Sariffhdac_unsolq_task(void *context, int pending) 4086171141Sariff{ 4087171141Sariff struct hdac_softc *sc; 4088171141Sariff 4089171141Sariff sc = (struct hdac_softc *)context; 4090171141Sariff 4091171141Sariff hdac_lock(sc); 4092171141Sariff hdac_unsolq_flush(sc); 4093171141Sariff hdac_unlock(sc); 4094171141Sariff} 4095171141Sariff 4096162922Sariff/**************************************************************************** 4097162922Sariff * int hdac_attach(device_t) 4098162922Sariff * 4099162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 4100162922Sariff * when this function is called. Setup everything that doesn't require 4101162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 4102162922Sariff ****************************************************************************/ 4103162922Sariffstatic int 4104162922Sariffhdac_attach(device_t dev) 4105162922Sariff{ 4106162922Sariff struct hdac_softc *sc; 4107162922Sariff int result; 4108189086Smav int i, devid = -1; 4109189086Smav uint32_t model; 4110189086Smav uint16_t class, subclass; 4111169277Sariff uint16_t vendor; 4112169277Sariff uint8_t v; 4113162922Sariff 4114184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 4115182999Smav 4116189086Smav model = (uint32_t)pci_get_device(dev) << 16; 4117189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 4118189086Smav class = pci_get_class(dev); 4119189086Smav subclass = pci_get_subclass(dev); 4120189086Smav 4121189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 4122189086Smav if (hdac_devices[i].model == model) { 4123189086Smav devid = i; 4124189086Smav break; 4125189086Smav } 4126189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 4127189086Smav class == PCIC_MULTIMEDIA && 4128189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 4129189086Smav devid = i; 4130189086Smav break; 4131189086Smav } 4132189086Smav } 4133189086Smav 4134182999Smav sc = device_get_softc(dev); 4135163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 4136162922Sariff sc->dev = dev; 4137163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 4138163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 4139169277Sariff vendor = pci_get_vendor(dev); 4140162922Sariff 4141165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 4142165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 4143165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 4144165281Sariff } 4145165281Sariff 4146164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 4147164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 4148169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 4149164614Sariff 4150171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 4151171141Sariff 4152182999Smav sc->poll_ticks = 1000000; 4153169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 4154169277Sariff if (resource_int_value(device_get_name(dev), 4155169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 4156164614Sariff sc->polling = 1; 4157164614Sariff else 4158164614Sariff sc->polling = 0; 4159164614Sariff 4160162922Sariff sc->hdabus = NULL; 4161162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 4162162922Sariff sc->codecs[i] = NULL; 4163162922Sariff 4164162922Sariff pci_enable_busmaster(dev); 4165162922Sariff 4166169277Sariff if (vendor == INTEL_VENDORID) { 4167169277Sariff /* TCSEL -> TC0 */ 4168169277Sariff v = pci_read_config(dev, 0x44, 1); 4169169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 4170183097Smav HDA_BOOTHVERBOSE( 4171169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 4172169277Sariff pci_read_config(dev, 0x44, 1)); 4173169277Sariff ); 4174169277Sariff } 4175169277Sariff 4176189127Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_MSI)) 4177188656Smav sc->flags &= ~HDAC_F_MSI; 4178188656Smav else 4179171330Sariff sc->flags |= HDAC_F_MSI; 4180189086Smav if (resource_int_value(device_get_name(dev), 4181189086Smav device_get_unit(dev), "msi", &i) == 0) { 4182189086Smav if (i == 0) 4183189086Smav sc->flags &= ~HDAC_F_MSI; 4184189086Smav else 4185189086Smav sc->flags |= HDAC_F_MSI; 4186189086Smav } 4187171330Sariff 4188169277Sariff#if defined(__i386__) || defined(__amd64__) 4189171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4190169277Sariff 4191169277Sariff if (resource_int_value(device_get_name(dev), 4192169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 4193169277Sariff#else 4194171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4195169277Sariff#endif 4196169277Sariff /* 4197169277Sariff * Try to enable PCIe snoop to avoid messing around with 4198169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 4199169277Sariff * config is pretty much vendor specific, there are no 4200169277Sariff * general solutions on how to enable it, forcing us (even 4201169277Sariff * Microsoft) to enable uncacheable or write combined DMA 4202169277Sariff * by default. 4203169277Sariff * 4204169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 4205169277Sariff */ 4206169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 4207169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 4208169277Sariff continue; 4209171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4210169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4211169277Sariff break; 4212169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4213169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4214169277Sariff hdac_pcie_snoop[i].enable) 4215169277Sariff break; 4216169277Sariff v &= hdac_pcie_snoop[i].mask; 4217169277Sariff v |= hdac_pcie_snoop[i].enable; 4218169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4219169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4220169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4221169277Sariff hdac_pcie_snoop[i].enable) { 4222169277Sariff HDA_BOOTVERBOSE( 4223169277Sariff device_printf(dev, 4224169277Sariff "WARNING: Failed to enable PCIe " 4225169277Sariff "snoop!\n"); 4226169277Sariff ); 4227169277Sariff#if defined(__i386__) || defined(__amd64__) 4228171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4229169277Sariff#endif 4230169277Sariff } 4231169277Sariff break; 4232169277Sariff } 4233169277Sariff#if defined(__i386__) || defined(__amd64__) 4234169277Sariff } 4235169277Sariff#endif 4236169277Sariff 4237183097Smav HDA_BOOTHVERBOSE( 4238169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4239171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4240171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4241169277Sariff ); 4242169277Sariff 4243162922Sariff /* Allocate resources */ 4244162922Sariff result = hdac_mem_alloc(sc); 4245162922Sariff if (result != 0) 4246163057Sariff goto hdac_attach_fail; 4247162922Sariff result = hdac_irq_alloc(sc); 4248162922Sariff if (result != 0) 4249163057Sariff goto hdac_attach_fail; 4250162922Sariff 4251162922Sariff /* Get Capabilities */ 4252162922Sariff result = hdac_get_capabilities(sc); 4253162922Sariff if (result != 0) 4254163057Sariff goto hdac_attach_fail; 4255162922Sariff 4256194861Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_64BIT)) 4257194861Smav sc->support_64bit = 0; 4258194861Smav 4259162922Sariff /* Allocate CORB and RIRB dma memory */ 4260162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4261162922Sariff sc->corb_size * sizeof(uint32_t)); 4262162922Sariff if (result != 0) 4263163057Sariff goto hdac_attach_fail; 4264162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4265162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4266162922Sariff if (result != 0) 4267163057Sariff goto hdac_attach_fail; 4268162922Sariff 4269194861Smav result = bus_dma_tag_create( 4270194861Smav bus_get_dma_tag(sc->dev), /* parent */ 4271194861Smav HDAC_DMA_ALIGNMENT, /* alignment */ 4272194861Smav 0, /* boundary */ 4273194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 4274194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 4275194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 4276194861Smav NULL, /* filtfunc */ 4277194861Smav NULL, /* fistfuncarg */ 4278194861Smav HDA_BUFSZ_MAX, /* maxsize */ 4279194861Smav 1, /* nsegments */ 4280194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 4281194861Smav 0, /* flags */ 4282194861Smav NULL, /* lockfunc */ 4283194861Smav NULL, /* lockfuncarg */ 4284194861Smav &sc->chan_dmat); /* dmat */ 4285194861Smav if (result != 0) { 4286194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 4287194861Smav __func__, result); 4288194861Smav goto hdac_attach_fail; 4289194861Smav } 4290194861Smav 4291162922Sariff /* Quiesce everything */ 4292183097Smav HDA_BOOTHVERBOSE( 4293182999Smav device_printf(dev, "Reset controller...\n"); 4294182999Smav ); 4295182999Smav hdac_reset(sc, 1); 4296162922Sariff 4297162922Sariff /* Initialize the CORB and RIRB */ 4298162922Sariff hdac_corb_init(sc); 4299162922Sariff hdac_rirb_init(sc); 4300162922Sariff 4301162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4302162922Sariff sc->intrhook.ich_func = hdac_attach2; 4303162922Sariff sc->intrhook.ich_arg = (void *)sc; 4304162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4305162922Sariff sc->intrhook.ich_func = NULL; 4306162922Sariff hdac_attach2((void *)sc); 4307162922Sariff } 4308162922Sariff 4309163057Sariff return (0); 4310162922Sariff 4311163057Sariffhdac_attach_fail: 4312162922Sariff hdac_irq_free(sc); 4313169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4314169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4315162922Sariff hdac_mem_free(sc); 4316162922Sariff snd_mtxfree(sc->lock); 4317163057Sariff free(sc, M_DEVBUF); 4318162922Sariff 4319163057Sariff return (ENXIO); 4320162922Sariff} 4321162922Sariff 4322162922Sariffstatic void 4323162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4324162922Sariff{ 4325182999Smav struct hdac_codec *codec = devinfo->codec; 4326182999Smav struct hdac_softc *sc = codec->sc; 4327162922Sariff struct hdac_widget *w; 4328162922Sariff uint32_t res; 4329162922Sariff int i; 4330162922Sariff nid_t cad, nid; 4331162922Sariff 4332162922Sariff cad = devinfo->codec->cad; 4333162922Sariff nid = devinfo->nid; 4334162922Sariff 4335162922Sariff res = hdac_command(sc, 4336169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4337169277Sariff devinfo->function.audio.gpio = res; 4338169277Sariff 4339163057Sariff HDA_BOOTVERBOSE( 4340183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4341183097Smav "NumGPIO=%d NumGPO=%d " 4342169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4343183097Smav devinfo->function.audio.gpio, 4344169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4345169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4346169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4347169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4348169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4349162922Sariff ); 4350162922Sariff 4351162922Sariff res = hdac_command(sc, 4352162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4353162922Sariff cad); 4354162922Sariff devinfo->function.audio.supp_stream_formats = res; 4355162922Sariff 4356162922Sariff res = hdac_command(sc, 4357162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4358162922Sariff cad); 4359162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4360162922Sariff 4361162922Sariff res = hdac_command(sc, 4362162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4363162922Sariff cad); 4364162922Sariff devinfo->function.audio.outamp_cap = res; 4365162922Sariff 4366162922Sariff res = hdac_command(sc, 4367162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4368162922Sariff cad); 4369162922Sariff devinfo->function.audio.inamp_cap = res; 4370162922Sariff 4371162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4372162922Sariff w = hdac_widget_get(devinfo, i); 4373162922Sariff if (w == NULL) 4374162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4375162922Sariff else { 4376162922Sariff w->devinfo = devinfo; 4377162922Sariff w->nid = i; 4378162922Sariff w->enable = 1; 4379162922Sariff w->selconn = -1; 4380162922Sariff w->pflags = 0; 4381182999Smav w->ossdev = -1; 4382182999Smav w->bindas = -1; 4383162965Sariff w->param.eapdbtl = HDAC_INVALID; 4384162922Sariff hdac_widget_parse(w); 4385162922Sariff } 4386162922Sariff } 4387162922Sariff} 4388162922Sariff 4389162922Sariffstatic void 4390162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4391162922Sariff{ 4392162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4393162922Sariff struct hdac_audio_ctl *ctls; 4394162922Sariff struct hdac_widget *w, *cw; 4395162922Sariff int i, j, cnt, max, ocap, icap; 4396163057Sariff int mute, offset, step, size; 4397162922Sariff 4398162922Sariff /* XXX This is redundant */ 4399162922Sariff max = 0; 4400162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4401162922Sariff w = hdac_widget_get(devinfo, i); 4402162922Sariff if (w == NULL || w->enable == 0) 4403162922Sariff continue; 4404162922Sariff if (w->param.outamp_cap != 0) 4405162922Sariff max++; 4406162922Sariff if (w->param.inamp_cap != 0) { 4407162922Sariff switch (w->type) { 4408162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4409162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4410162922Sariff for (j = 0; j < w->nconns; j++) { 4411162922Sariff cw = hdac_widget_get(devinfo, 4412162922Sariff w->conns[j]); 4413162922Sariff if (cw == NULL || cw->enable == 0) 4414162922Sariff continue; 4415162922Sariff max++; 4416162922Sariff } 4417162922Sariff break; 4418162922Sariff default: 4419162922Sariff max++; 4420162922Sariff break; 4421162922Sariff } 4422162922Sariff } 4423162922Sariff } 4424162922Sariff 4425162922Sariff devinfo->function.audio.ctlcnt = max; 4426162922Sariff 4427162922Sariff if (max < 1) 4428162922Sariff return; 4429162922Sariff 4430162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4431162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4432162922Sariff 4433162922Sariff if (ctls == NULL) { 4434162922Sariff /* Blekh! */ 4435162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4436162922Sariff devinfo->function.audio.ctlcnt = 0; 4437162922Sariff return; 4438162922Sariff } 4439162922Sariff 4440162922Sariff cnt = 0; 4441162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4442162922Sariff if (cnt >= max) { 4443162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4444162922Sariff __func__); 4445162922Sariff break; 4446162922Sariff } 4447162922Sariff w = hdac_widget_get(devinfo, i); 4448162922Sariff if (w == NULL || w->enable == 0) 4449162922Sariff continue; 4450162922Sariff ocap = w->param.outamp_cap; 4451162922Sariff icap = w->param.inamp_cap; 4452162922Sariff if (ocap != 0) { 4453163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4454163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4455163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4456163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4457163057Sariff /*if (offset > step) { 4458163057Sariff HDA_BOOTVERBOSE( 4459163057Sariff device_printf(sc->dev, 4460182999Smav "BUGGY outamp: nid=%d " 4461163057Sariff "[offset=%d > step=%d]\n", 4462163057Sariff w->nid, offset, step); 4463163057Sariff ); 4464163057Sariff offset = step; 4465163057Sariff }*/ 4466162922Sariff ctls[cnt].enable = 1; 4467162922Sariff ctls[cnt].widget = w; 4468163057Sariff ctls[cnt].mute = mute; 4469163057Sariff ctls[cnt].step = step; 4470163057Sariff ctls[cnt].size = size; 4471163057Sariff ctls[cnt].offset = offset; 4472163057Sariff ctls[cnt].left = offset; 4473163057Sariff ctls[cnt].right = offset; 4474182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4475182999Smav w->waspin) 4476182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4477182999Smav else 4478182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4479162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4480162922Sariff } 4481162922Sariff 4482162922Sariff if (icap != 0) { 4483163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4484163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4485163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4486163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4487163057Sariff /*if (offset > step) { 4488163057Sariff HDA_BOOTVERBOSE( 4489163057Sariff device_printf(sc->dev, 4490182999Smav "BUGGY inamp: nid=%d " 4491163057Sariff "[offset=%d > step=%d]\n", 4492163057Sariff w->nid, offset, step); 4493163057Sariff ); 4494163057Sariff offset = step; 4495163057Sariff }*/ 4496162922Sariff switch (w->type) { 4497162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4498162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4499162922Sariff for (j = 0; j < w->nconns; j++) { 4500162922Sariff if (cnt >= max) { 4501162922Sariff device_printf(sc->dev, 4502162922Sariff "%s: Ctl overflow!\n", 4503162922Sariff __func__); 4504162922Sariff break; 4505162922Sariff } 4506162922Sariff cw = hdac_widget_get(devinfo, 4507162922Sariff w->conns[j]); 4508162922Sariff if (cw == NULL || cw->enable == 0) 4509162922Sariff continue; 4510162922Sariff ctls[cnt].enable = 1; 4511162922Sariff ctls[cnt].widget = w; 4512162922Sariff ctls[cnt].childwidget = cw; 4513162922Sariff ctls[cnt].index = j; 4514163057Sariff ctls[cnt].mute = mute; 4515163057Sariff ctls[cnt].step = step; 4516163057Sariff ctls[cnt].size = size; 4517163057Sariff ctls[cnt].offset = offset; 4518163057Sariff ctls[cnt].left = offset; 4519163057Sariff ctls[cnt].right = offset; 4520182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4521162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4522162922Sariff } 4523162922Sariff break; 4524162922Sariff default: 4525162922Sariff if (cnt >= max) { 4526162922Sariff device_printf(sc->dev, 4527162922Sariff "%s: Ctl overflow!\n", 4528162922Sariff __func__); 4529162922Sariff break; 4530162922Sariff } 4531162922Sariff ctls[cnt].enable = 1; 4532162922Sariff ctls[cnt].widget = w; 4533163057Sariff ctls[cnt].mute = mute; 4534163057Sariff ctls[cnt].step = step; 4535163057Sariff ctls[cnt].size = size; 4536163057Sariff ctls[cnt].offset = offset; 4537163057Sariff ctls[cnt].left = offset; 4538163057Sariff ctls[cnt].right = offset; 4539182999Smav if (w->type == 4540182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4541182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4542182999Smav else 4543182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4544162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4545162922Sariff break; 4546162922Sariff } 4547162922Sariff } 4548162922Sariff } 4549162922Sariff 4550162922Sariff devinfo->function.audio.ctl = ctls; 4551162922Sariff} 4552162922Sariff 4553182999Smavstatic void 4554182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4555182999Smav{ 4556182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4557182999Smav struct hdac_audio_as *as; 4558182999Smav struct hdac_widget *w; 4559182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4560182999Smav 4561184991Smav /* Count present associations */ 4562182999Smav max = 0; 4563184991Smav for (j = 1; j < 16; j++) { 4564182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4565182999Smav w = hdac_widget_get(devinfo, i); 4566182999Smav if (w == NULL || w->enable == 0) 4567182999Smav continue; 4568182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4569182999Smav continue; 4570182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4571182999Smav != j) 4572182999Smav continue; 4573182999Smav max++; 4574182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4575182999Smav break; 4576182999Smav } 4577182999Smav } 4578182999Smav 4579182999Smav devinfo->function.audio.ascnt = max; 4580182999Smav 4581182999Smav if (max < 1) 4582182999Smav return; 4583182999Smav 4584182999Smav as = (struct hdac_audio_as *)malloc( 4585182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4586182999Smav 4587182999Smav if (as == NULL) { 4588182999Smav /* Blekh! */ 4589182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4590182999Smav devinfo->function.audio.ascnt = 0; 4591182999Smav return; 4592182999Smav } 4593182999Smav 4594182999Smav for (i = 0; i < max; i++) { 4595182999Smav as[i].hpredir = -1; 4596182999Smav as[i].chan = -1; 4597197611Smav as[i].digital = 0; 4598182999Smav } 4599182999Smav 4600182999Smav /* Scan associations skipping as=0. */ 4601182999Smav cnt = 0; 4602182999Smav for (j = 1; j < 16; j++) { 4603182999Smav first = 16; 4604182999Smav hpredir = 0; 4605182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4606182999Smav w = hdac_widget_get(devinfo, i); 4607182999Smav if (w == NULL || w->enable == 0) 4608182999Smav continue; 4609182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4610182999Smav continue; 4611182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4612182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4613182999Smav if (assoc != j) { 4614182999Smav continue; 4615182999Smav } 4616182999Smav KASSERT(cnt < max, 4617182999Smav ("%s: Associations owerflow (%d of %d)", 4618182999Smav __func__, cnt, max)); 4619182999Smav type = w->wclass.pin.config & 4620182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4621182999Smav /* Get pin direction. */ 4622182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4623182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4624182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4625182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4626182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4627182999Smav dir = HDA_CTL_OUT; 4628182999Smav else 4629182999Smav dir = HDA_CTL_IN; 4630182999Smav /* If this is a first pin - create new association. */ 4631182999Smav if (as[cnt].pincnt == 0) { 4632182999Smav as[cnt].enable = 1; 4633182999Smav as[cnt].index = j; 4634182999Smav as[cnt].dir = dir; 4635182999Smav } 4636182999Smav if (seq < first) 4637182999Smav first = seq; 4638182999Smav /* Check association correctness. */ 4639182999Smav if (as[cnt].pins[seq] != 0) { 4640182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4641182999Smav "in association %d! Disabling association.\n", 4642182999Smav __func__, seq, w->nid, j); 4643182999Smav as[cnt].enable = 0; 4644182999Smav } 4645182999Smav if (dir != as[cnt].dir) { 4646182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4647182999Smav "direction for association %d! Disabling " 4648182999Smav "association.\n", 4649182999Smav __func__, w->nid, j); 4650182999Smav as[cnt].enable = 0; 4651182999Smav } 4652197611Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 4653197611Smav if (HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap)) 4654197611Smav as[cnt].digital = 3; 4655197611Smav else if (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap)) 4656197611Smav as[cnt].digital = 2; 4657197611Smav else 4658197611Smav as[cnt].digital = 1; 4659197611Smav } 4660182999Smav /* Headphones with seq=15 may mean redirection. */ 4661182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4662182999Smav seq == 15) 4663182999Smav hpredir = 1; 4664182999Smav as[cnt].pins[seq] = w->nid; 4665182999Smav as[cnt].pincnt++; 4666182999Smav /* Association 15 is a multiple unassociated pins. */ 4667182999Smav if (j == 15) 4668182999Smav cnt++; 4669182999Smav } 4670182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4671182999Smav if (hpredir && as[cnt].pincnt > 1) 4672182999Smav as[cnt].hpredir = first; 4673182999Smav cnt++; 4674182999Smav } 4675182999Smav } 4676182999Smav HDA_BOOTVERBOSE( 4677182999Smav device_printf(sc->dev, 4678183097Smav "%d associations found:\n", max); 4679182999Smav for (i = 0; i < max; i++) { 4680182999Smav device_printf(sc->dev, 4681182999Smav "Association %d (%d) %s%s:\n", 4682182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4683182999Smav as[i].enable?"":" (disabled)"); 4684182999Smav for (j = 0; j < 16; j++) { 4685182999Smav if (as[i].pins[j] == 0) 4686182999Smav continue; 4687182999Smav device_printf(sc->dev, 4688183097Smav " Pin nid=%d seq=%d\n", 4689182999Smav as[i].pins[j], j); 4690182999Smav } 4691182999Smav } 4692182999Smav ); 4693182999Smav 4694182999Smav devinfo->function.audio.as = as; 4695182999Smav} 4696182999Smav 4697162965Sariffstatic const struct { 4698162965Sariff uint32_t model; 4699162965Sariff uint32_t id; 4700162965Sariff uint32_t set, unset; 4701162965Sariff} hdac_quirks[] = { 4702163057Sariff /* 4703163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4704163057Sariff * on few codecs (especially ALC880) seems broken or 4705163057Sariff * perhaps unsupported. 4706163057Sariff */ 4707163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4708169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4709162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4710165039Sariff HDA_QUIRK_GPIO0, 0 }, 4711178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4712178155Sariff HDA_QUIRK_GPIO0, 0 }, 4713162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4714165039Sariff HDA_QUIRK_GPIO0, 0 }, 4715165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4716165281Sariff HDA_QUIRK_GPIO0, 0 }, 4717167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4718167623Sariff HDA_QUIRK_GPIO0, 0 }, 4719169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4720169277Sariff HDA_QUIRK_GPIO0, 0 }, 4721163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4722163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4723178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4724163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4725169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4726169277Sariff HDA_QUIRK_OVREF, 0 }, 4727169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4728169277Sariff HDA_QUIRK_OVREF, 0 }, 4729169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4730169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4731165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4732165281Sariff HDA_QUIRK_GPIO1, 0 }, 4733164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4734182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4735164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4736164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4737173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4738173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4739165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4740165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4741199846Smav { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, 4742199846Smav HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 }, 4743183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4744180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4745184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4746184483Smav HDA_QUIRK_GPIO2, 0 }, 4747183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4748178155Sariff HDA_QUIRK_GPIO0, 0 }, 4749169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4750169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4751170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4752170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4753186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4754182999Smav 0, HDA_QUIRK_FORCESTEREO } 4755162965Sariff}; 4756162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4757162965Sariff 4758162922Sariffstatic void 4759162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4760162922Sariff{ 4761162922Sariff struct hdac_widget *w; 4762162965Sariff uint32_t id, subvendor; 4763162922Sariff int i; 4764162922Sariff 4765182999Smav id = hdac_codec_id(devinfo->codec); 4766163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4767163057Sariff 4768162922Sariff /* 4769163057Sariff * Quirks 4770162922Sariff */ 4771163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4772163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4773163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4774163057Sariff continue; 4775163057Sariff if (hdac_quirks[i].set != 0) 4776163057Sariff devinfo->function.audio.quirks |= 4777163057Sariff hdac_quirks[i].set; 4778163057Sariff if (hdac_quirks[i].unset != 0) 4779163057Sariff devinfo->function.audio.quirks &= 4780163057Sariff ~(hdac_quirks[i].unset); 4781163057Sariff } 4782163057Sariff 4783162922Sariff switch (id) { 4784187196Smav case HDA_CODEC_AD1983: 4785187196Smav /* 4786187202Smav * This codec has several possible usages, but none 4787187202Smav * fit the parser best. Help parser to choose better. 4788187196Smav */ 4789187196Smav /* Disable direct unmixed playback to get pcm volume. */ 4790187196Smav w = hdac_widget_get(devinfo, 5); 4791187196Smav if (w != NULL) 4792187196Smav w->connsenable[0] = 0; 4793187196Smav w = hdac_widget_get(devinfo, 6); 4794187196Smav if (w != NULL) 4795187196Smav w->connsenable[0] = 0; 4796187196Smav w = hdac_widget_get(devinfo, 11); 4797187196Smav if (w != NULL) 4798187196Smav w->connsenable[0] = 0; 4799187196Smav /* Disable mic and line selectors. */ 4800187196Smav w = hdac_widget_get(devinfo, 12); 4801187196Smav if (w != NULL) 4802187196Smav w->connsenable[1] = 0; 4803187196Smav w = hdac_widget_get(devinfo, 13); 4804187196Smav if (w != NULL) 4805187196Smav w->connsenable[1] = 0; 4806187196Smav /* Disable recording from mono playback mix. */ 4807187196Smav w = hdac_widget_get(devinfo, 20); 4808187196Smav if (w != NULL) 4809187196Smav w->connsenable[3] = 0; 4810187196Smav break; 4811162922Sariff case HDA_CODEC_AD1986A: 4812186503Smav /* 4813186503Smav * This codec has overcomplicated input mixing. 4814186503Smav * Make some cleaning there. 4815186503Smav */ 4816186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4817186503Smav w = hdac_widget_get(devinfo, 43); 4818186503Smav if (w != NULL) 4819186503Smav w->enable = 0; 4820186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4821186503Smav w = hdac_widget_get(devinfo, 39); 4822186503Smav if (w != NULL) 4823186503Smav w->enable = 0; 4824186503Smav w = hdac_widget_get(devinfo, 40); 4825186503Smav if (w != NULL) 4826186503Smav w->enable = 0; 4827186503Smav w = hdac_widget_get(devinfo, 41); 4828186503Smav if (w != NULL) 4829186503Smav w->enable = 0; 4830186503Smav w = hdac_widget_get(devinfo, 42); 4831186503Smav if (w != NULL) 4832186503Smav w->enable = 0; 4833186503Smav /* Disable duplicate mixer node connector. */ 4834186503Smav w = hdac_widget_get(devinfo, 15); 4835186503Smav if (w != NULL) 4836186503Smav w->connsenable[3] = 0; 4837190630Smav /* There is only one mic preamplifier, use it effectively. */ 4838190630Smav w = hdac_widget_get(devinfo, 31); 4839190630Smav if (w != NULL) { 4840190630Smav if ((w->wclass.pin.config & 4841190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4842190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4843190630Smav w = hdac_widget_get(devinfo, 16); 4844190630Smav if (w != NULL) 4845190630Smav w->connsenable[2] = 0; 4846190630Smav } else { 4847190630Smav w = hdac_widget_get(devinfo, 15); 4848190630Smav if (w != NULL) 4849190630Smav w->connsenable[0] = 0; 4850190630Smav } 4851190630Smav } 4852190630Smav w = hdac_widget_get(devinfo, 32); 4853190630Smav if (w != NULL) { 4854190630Smav if ((w->wclass.pin.config & 4855190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4856190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4857190630Smav w = hdac_widget_get(devinfo, 16); 4858190630Smav if (w != NULL) 4859190630Smav w->connsenable[0] = 0; 4860190630Smav } else { 4861190630Smav w = hdac_widget_get(devinfo, 15); 4862190630Smav if (w != NULL) 4863190630Smav w->connsenable[1] = 0; 4864190630Smav } 4865190630Smav } 4866186503Smav 4867182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4868178155Sariff /* 4869178155Sariff * This is just plain ridiculous.. There 4870178155Sariff * are several A8 series that share the same 4871178155Sariff * pci id but works differently (EAPD). 4872178155Sariff */ 4873178155Sariff w = hdac_widget_get(devinfo, 26); 4874178155Sariff if (w != NULL && w->type == 4875178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4876178155Sariff (w->wclass.pin.config & 4877178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4878178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4879178155Sariff devinfo->function.audio.quirks &= 4880178155Sariff ~HDA_QUIRK_EAPDINV; 4881169277Sariff } 4882162922Sariff break; 4883184230Smav case HDA_CODEC_AD1981HD: 4884184230Smav /* 4885184230Smav * This codec has very unusual design with several 4886184254Smav * points inappropriate for the present parser. 4887184230Smav */ 4888184230Smav /* Disable recording from mono playback mix. */ 4889184230Smav w = hdac_widget_get(devinfo, 21); 4890184230Smav if (w != NULL) 4891184230Smav w->connsenable[3] = 0; 4892184230Smav /* Disable rear to front mic mixer, use separately. */ 4893184230Smav w = hdac_widget_get(devinfo, 31); 4894184230Smav if (w != NULL) 4895184230Smav w->enable = 0; 4896202789Smav /* Disable direct playback, use mixer. */ 4897202789Smav w = hdac_widget_get(devinfo, 5); 4898184230Smav if (w != NULL) 4899202789Smav w->connsenable[0] = 0; 4900202789Smav w = hdac_widget_get(devinfo, 6); 4901202789Smav if (w != NULL) 4902202789Smav w->connsenable[0] = 0; 4903202789Smav w = hdac_widget_get(devinfo, 9); 4904202789Smav if (w != NULL) 4905202789Smav w->connsenable[0] = 0; 4906202789Smav w = hdac_widget_get(devinfo, 24); 4907202789Smav if (w != NULL) 4908202789Smav w->connsenable[0] = 0; 4909184230Smav break; 4910182999Smav } 4911182999Smav} 4912182999Smav 4913182999Smav/* 4914182999Smav * Trace path from DAC to pin. 4915182999Smav */ 4916182999Smavstatic nid_t 4917182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4918182999Smav int dupseq, int min, int only, int depth) 4919182999Smav{ 4920182999Smav struct hdac_widget *w; 4921182999Smav int i, im = -1; 4922182999Smav nid_t m = 0, ret; 4923182999Smav 4924182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4925182999Smav return (0); 4926182999Smav w = hdac_widget_get(devinfo, nid); 4927182999Smav if (w == NULL || w->enable == 0) 4928182999Smav return (0); 4929183097Smav HDA_BOOTHVERBOSE( 4930182999Smav if (!only) { 4931182999Smav device_printf(devinfo->codec->sc->dev, 4932182999Smav " %*stracing via nid %d\n", 4933182999Smav depth + 1, "", w->nid); 4934169277Sariff } 4935182999Smav ); 4936182999Smav /* Use only unused widgets */ 4937182999Smav if (w->bindas >= 0 && w->bindas != as) { 4938183097Smav HDA_BOOTHVERBOSE( 4939182999Smav if (!only) { 4940182999Smav device_printf(devinfo->codec->sc->dev, 4941182999Smav " %*snid %d busy by association %d\n", 4942182999Smav depth + 1, "", w->nid, w->bindas); 4943182999Smav } 4944182999Smav ); 4945182999Smav return (0); 4946182999Smav } 4947182999Smav if (dupseq < 0) { 4948182999Smav if (w->bindseqmask != 0) { 4949183097Smav HDA_BOOTHVERBOSE( 4950182999Smav if (!only) { 4951182999Smav device_printf(devinfo->codec->sc->dev, 4952182999Smav " %*snid %d busy by seqmask %x\n", 4953182999Smav depth + 1, "", w->nid, w->bindseqmask); 4954182999Smav } 4955182999Smav ); 4956182999Smav return (0); 4957169277Sariff } 4958182999Smav } else { 4959182999Smav /* If this is headphones - allow duplicate first pin. */ 4960182999Smav if (w->bindseqmask != 0 && 4961182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4962183097Smav HDA_BOOTHVERBOSE( 4963182999Smav device_printf(devinfo->codec->sc->dev, 4964182999Smav " %*snid %d busy by seqmask %x\n", 4965182999Smav depth + 1, "", w->nid, w->bindseqmask); 4966182999Smav ); 4967182999Smav return (0); 4968169277Sariff } 4969182999Smav } 4970182999Smav 4971182999Smav switch (w->type) { 4972182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4973182999Smav /* Do not traverse input. AD1988 has digital monitor 4974182999Smav for which we are not ready. */ 4975169277Sariff break; 4976182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4977182999Smav /* If we are tracing HP take only dac of first pin. */ 4978182999Smav if ((only == 0 || only == w->nid) && 4979182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4980182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4981182999Smav m = w->nid; 4982178155Sariff break; 4983182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4984182999Smav if (depth > 0) 4985169277Sariff break; 4986182999Smav /* Fall */ 4987182999Smav default: 4988182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4989182999Smav for (i = 0; i < w->nconns; i++) { 4990182999Smav if (w->connsenable[i] == 0) 4991162922Sariff continue; 4992182999Smav if (w->selconn != -1 && w->selconn != i) 4993162922Sariff continue; 4994182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4995182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4996182999Smav if (m == 0 || ret < m) { 4997182999Smav m = ret; 4998182999Smav im = i; 4999182999Smav } 5000182999Smav if (only || dupseq >= 0) 5001182999Smav break; 5002182999Smav } 5003162922Sariff } 5004182999Smav if (m && only && ((w->nconns > 1 && 5005182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5006182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 5007182999Smav w->selconn = im; 5008162922Sariff break; 5009182999Smav } 5010182999Smav if (m && only) { 5011182999Smav w->bindas = as; 5012182999Smav w->bindseqmask |= (1 << seq); 5013182999Smav } 5014183097Smav HDA_BOOTHVERBOSE( 5015182999Smav if (!only) { 5016182999Smav device_printf(devinfo->codec->sc->dev, 5017182999Smav " %*snid %d returned %d\n", 5018182999Smav depth + 1, "", w->nid, m); 5019182999Smav } 5020182999Smav ); 5021182999Smav return (m); 5022182999Smav} 5023162922Sariff 5024182999Smav/* 5025182999Smav * Trace path from widget to ADC. 5026182999Smav */ 5027182999Smavstatic nid_t 5028182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 5029182999Smav int only, int depth) 5030182999Smav{ 5031182999Smav struct hdac_widget *w, *wc; 5032182999Smav int i, j; 5033182999Smav nid_t res = 0; 5034182999Smav 5035182999Smav if (depth > HDA_PARSE_MAXDEPTH) 5036182999Smav return (0); 5037182999Smav w = hdac_widget_get(devinfo, nid); 5038182999Smav if (w == NULL || w->enable == 0) 5039182999Smav return (0); 5040183097Smav HDA_BOOTHVERBOSE( 5041182999Smav device_printf(devinfo->codec->sc->dev, 5042182999Smav " %*stracing via nid %d\n", 5043182999Smav depth + 1, "", w->nid); 5044182999Smav ); 5045182999Smav /* Use only unused widgets */ 5046182999Smav if (w->bindas >= 0 && w->bindas != as) { 5047183097Smav HDA_BOOTHVERBOSE( 5048182999Smav device_printf(devinfo->codec->sc->dev, 5049182999Smav " %*snid %d busy by association %d\n", 5050182999Smav depth + 1, "", w->nid, w->bindas); 5051182999Smav ); 5052182999Smav return (0); 5053182999Smav } 5054182999Smav 5055182999Smav switch (w->type) { 5056182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5057182999Smav /* If we are tracing HP take only dac of first pin. */ 5058182999Smav if (only == w->nid) 5059182999Smav res = 1; 5060162922Sariff break; 5061182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5062182999Smav if (depth > 0) 5063182999Smav break; 5064182999Smav /* Fall */ 5065182999Smav default: 5066182999Smav /* Try to find reachable ADCs with specified nid. */ 5067182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5068182999Smav wc = hdac_widget_get(devinfo, j); 5069182999Smav if (wc == NULL || wc->enable == 0) 5070182999Smav continue; 5071182999Smav for (i = 0; i < wc->nconns; i++) { 5072182999Smav if (wc->connsenable[i] == 0) 5073182999Smav continue; 5074182999Smav if (wc->conns[i] != nid) 5075182999Smav continue; 5076182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 5077182999Smav j, only, depth + 1) != 0) { 5078182999Smav res = 1; 5079182999Smav if (((wc->nconns > 1 && 5080182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5081182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 5082182999Smav wc->selconn == -1) 5083182999Smav wc->selconn = i; 5084182999Smav } 5085182999Smav } 5086169277Sariff } 5087169277Sariff break; 5088162922Sariff } 5089182999Smav if (res) { 5090182999Smav w->bindas = as; 5091182999Smav w->bindseqmask |= (1 << seq); 5092182999Smav } 5093183097Smav HDA_BOOTHVERBOSE( 5094182999Smav device_printf(devinfo->codec->sc->dev, 5095182999Smav " %*snid %d returned %d\n", 5096182999Smav depth + 1, "", w->nid, res); 5097182999Smav ); 5098182999Smav return (res); 5099162922Sariff} 5100162922Sariff 5101182999Smav/* 5102182999Smav * Erase trace path of the specified association. 5103182999Smav */ 5104182999Smavstatic void 5105182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 5106182999Smav{ 5107182999Smav struct hdac_widget *w; 5108182999Smav int i; 5109182999Smav 5110182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5111182999Smav w = hdac_widget_get(devinfo, i); 5112182999Smav if (w == NULL || w->enable == 0) 5113182999Smav continue; 5114182999Smav if (w->bindas == as) { 5115182999Smav if (seq >= 0) { 5116182999Smav w->bindseqmask &= ~(1 << seq); 5117182999Smav if (w->bindseqmask == 0) { 5118182999Smav w->bindas = -1; 5119182999Smav w->selconn = -1; 5120182999Smav } 5121182999Smav } else { 5122182999Smav w->bindas = -1; 5123182999Smav w->bindseqmask = 0; 5124182999Smav w->selconn = -1; 5125182999Smav } 5126182999Smav } 5127182999Smav } 5128182999Smav} 5129182999Smav 5130182999Smav/* 5131182999Smav * Trace association path from DAC to output 5132182999Smav */ 5133162922Sariffstatic int 5134182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 5135162922Sariff{ 5136182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5137182999Smav int i, hpredir; 5138182999Smav nid_t min, res; 5139162922Sariff 5140182999Smav /* Find next pin */ 5141185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 5142182999Smav ; 5143188510Smav /* Check if there is no any left. If so - we succeeded. */ 5144182999Smav if (i == 16) 5145182999Smav return (1); 5146182999Smav 5147182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 5148182999Smav min = 0; 5149182999Smav res = 0; 5150182999Smav do { 5151183097Smav HDA_BOOTHVERBOSE( 5152182999Smav device_printf(devinfo->codec->sc->dev, 5153182999Smav " Tracing pin %d with min nid %d", 5154182999Smav ases[as].pins[i], min); 5155182999Smav if (hpredir >= 0) 5156183097Smav printf(" and hpredir %d", hpredir); 5157183097Smav printf("\n"); 5158182999Smav ); 5159182999Smav /* Trace this pin taking min nid into account. */ 5160182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 5161182999Smav ases[as].pins[i], hpredir, min, 0, 0); 5162182999Smav if (res == 0) { 5163182999Smav /* If we failed - return to previous and redo it. */ 5164182999Smav HDA_BOOTVERBOSE( 5165182999Smav device_printf(devinfo->codec->sc->dev, 5166182999Smav " Unable to trace pin %d seq %d with min " 5167183097Smav "nid %d", 5168183097Smav ases[as].pins[i], i, min); 5169183097Smav if (hpredir >= 0) 5170183097Smav printf(" and hpredir %d", hpredir); 5171183097Smav printf("\n"); 5172182999Smav ); 5173182999Smav return (0); 5174162922Sariff } 5175182999Smav HDA_BOOTVERBOSE( 5176182999Smav device_printf(devinfo->codec->sc->dev, 5177183097Smav " Pin %d traced to DAC %d", 5178183097Smav ases[as].pins[i], res); 5179183097Smav if (hpredir >= 0) 5180183097Smav printf(" and hpredir %d", hpredir); 5181183097Smav if (ases[as].fakeredir) 5182183097Smav printf(" with fake redirection"); 5183183097Smav printf("\n"); 5184182999Smav ); 5185182999Smav /* Trace again to mark the path */ 5186182999Smav hdac_audio_trace_dac(devinfo, as, i, 5187182999Smav ases[as].pins[i], hpredir, min, res, 0); 5188182999Smav ases[as].dacs[i] = res; 5189188510Smav /* We succeeded, so call next. */ 5190182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 5191182999Smav return (1); 5192182999Smav /* If next failed, we should retry with next min */ 5193182999Smav hdac_audio_undo_trace(devinfo, as, i); 5194182999Smav ases[as].dacs[i] = 0; 5195182999Smav min = res + 1; 5196182999Smav } while (1); 5197162922Sariff} 5198162922Sariff 5199182999Smav/* 5200182999Smav * Trace association path from input to ADC 5201182999Smav */ 5202162922Sariffstatic int 5203182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 5204162922Sariff{ 5205182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5206162922Sariff struct hdac_widget *w; 5207182999Smav int i, j, k; 5208162922Sariff 5209182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5210182999Smav w = hdac_widget_get(devinfo, j); 5211182999Smav if (w == NULL || w->enable == 0) 5212182999Smav continue; 5213182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5214182999Smav continue; 5215182999Smav if (w->bindas >= 0 && w->bindas != as) 5216182999Smav continue; 5217182999Smav 5218182999Smav /* Find next pin */ 5219182999Smav for (i = 0; i < 16; i++) { 5220182999Smav if (ases[as].pins[i] == 0) 5221182999Smav continue; 5222182999Smav 5223183097Smav HDA_BOOTHVERBOSE( 5224182999Smav device_printf(devinfo->codec->sc->dev, 5225182999Smav " Tracing pin %d to ADC %d\n", 5226182999Smav ases[as].pins[i], j); 5227182999Smav ); 5228182999Smav /* Trace this pin taking goal into account. */ 5229182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 5230182999Smav ases[as].pins[i], j, 0) == 0) { 5231182999Smav /* If we failed - return to previous and redo it. */ 5232182999Smav HDA_BOOTVERBOSE( 5233182999Smav device_printf(devinfo->codec->sc->dev, 5234183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 5235182999Smav ases[as].pins[i], j); 5236182999Smav ); 5237182999Smav hdac_audio_undo_trace(devinfo, as, -1); 5238182999Smav for (k = 0; k < 16; k++) 5239182999Smav ases[as].dacs[k] = 0; 5240182999Smav break; 5241162922Sariff } 5242182999Smav HDA_BOOTVERBOSE( 5243182999Smav device_printf(devinfo->codec->sc->dev, 5244183097Smav " Pin %d traced to ADC %d\n", 5245183097Smav ases[as].pins[i], j); 5246182999Smav ); 5247182999Smav ases[as].dacs[i] = j; 5248162922Sariff } 5249182999Smav if (i == 16) 5250182999Smav return (1); 5251162922Sariff } 5252182999Smav return (0); 5253162922Sariff} 5254162922Sariff 5255182999Smav/* 5256182999Smav * Trace input monitor path from mixer to output association. 5257182999Smav */ 5258183097Smavstatic int 5259182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5260162922Sariff{ 5261182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5262182999Smav struct hdac_widget *w, *wc; 5263182999Smav int i, j; 5264182999Smav nid_t res = 0; 5265162922Sariff 5266162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5267162922Sariff return (0); 5268162922Sariff w = hdac_widget_get(devinfo, nid); 5269162922Sariff if (w == NULL || w->enable == 0) 5270162922Sariff return (0); 5271183097Smav HDA_BOOTHVERBOSE( 5272182999Smav device_printf(devinfo->codec->sc->dev, 5273182999Smav " %*stracing via nid %d\n", 5274182999Smav depth + 1, "", w->nid); 5275182999Smav ); 5276182999Smav /* Use only unused widgets */ 5277182999Smav if (depth > 0 && w->bindas != -1) { 5278182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5279183097Smav HDA_BOOTHVERBOSE( 5280182999Smav device_printf(devinfo->codec->sc->dev, 5281182999Smav " %*snid %d found output association %d\n", 5282182999Smav depth + 1, "", w->nid, w->bindas); 5283182999Smav ); 5284202789Smav if (w->bindas >= 0) 5285202789Smav w->pflags |= HDA_ADC_MONITOR; 5286182999Smav return (1); 5287182999Smav } else { 5288183097Smav HDA_BOOTHVERBOSE( 5289182999Smav device_printf(devinfo->codec->sc->dev, 5290182999Smav " %*snid %d busy by input association %d\n", 5291182999Smav depth + 1, "", w->nid, w->bindas); 5292182999Smav ); 5293182999Smav return (0); 5294182999Smav } 5295182999Smav } 5296182999Smav 5297162922Sariff switch (w->type) { 5298162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5299182999Smav /* Do not traverse input. AD1988 has digital monitor 5300182999Smav for which we are not ready. */ 5301162922Sariff break; 5302162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5303182999Smav if (depth > 0) 5304182999Smav break; 5305182999Smav /* Fall */ 5306182999Smav default: 5307182999Smav /* Try to find reachable ADCs with specified nid. */ 5308182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5309182999Smav wc = hdac_widget_get(devinfo, j); 5310182999Smav if (wc == NULL || wc->enable == 0) 5311182999Smav continue; 5312182999Smav for (i = 0; i < wc->nconns; i++) { 5313182999Smav if (wc->connsenable[i] == 0) 5314182999Smav continue; 5315182999Smav if (wc->conns[i] != nid) 5316182999Smav continue; 5317182999Smav if (hdac_audio_trace_to_out(devinfo, 5318182999Smav j, depth + 1) != 0) { 5319182999Smav res = 1; 5320182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5321182999Smav wc->selconn == -1) 5322182999Smav wc->selconn = i; 5323182999Smav } 5324182999Smav } 5325162922Sariff } 5326162922Sariff break; 5327182999Smav } 5328202789Smav if (res && w->bindas == -1) 5329182999Smav w->bindas = -2; 5330182999Smav 5331183097Smav HDA_BOOTHVERBOSE( 5332182999Smav device_printf(devinfo->codec->sc->dev, 5333182999Smav " %*snid %d returned %d\n", 5334182999Smav depth + 1, "", w->nid, res); 5335182999Smav ); 5336182999Smav return (res); 5337182999Smav} 5338182999Smav 5339182999Smav/* 5340182999Smav * Trace extra associations (beeper, monitor) 5341182999Smav */ 5342182999Smavstatic void 5343182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5344182999Smav{ 5345182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5346182999Smav struct hdac_widget *w; 5347182999Smav int j; 5348182999Smav 5349182999Smav /* Input monitor */ 5350182999Smav /* Find mixer associated with input, but supplying signal 5351182999Smav for output associations. Hope it will be input monitor. */ 5352182999Smav HDA_BOOTVERBOSE( 5353182999Smav device_printf(devinfo->codec->sc->dev, 5354182999Smav "Tracing input monitor\n"); 5355182999Smav ); 5356182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5357182999Smav w = hdac_widget_get(devinfo, j); 5358182999Smav if (w == NULL || w->enable == 0) 5359182999Smav continue; 5360182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5361182999Smav continue; 5362182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5363182999Smav continue; 5364182999Smav HDA_BOOTVERBOSE( 5365182999Smav device_printf(devinfo->codec->sc->dev, 5366182999Smav " Tracing nid %d to out\n", 5367182999Smav j); 5368182999Smav ); 5369182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5370182999Smav HDA_BOOTVERBOSE( 5371182999Smav device_printf(devinfo->codec->sc->dev, 5372182999Smav " nid %d is input monitor\n", 5373182999Smav w->nid); 5374182999Smav ); 5375182999Smav w->ossdev = SOUND_MIXER_IMIX; 5376162922Sariff } 5377162922Sariff } 5378182999Smav 5379202789Smav /* Other inputs monitor */ 5380202789Smav /* Find input pins supplying signal for output associations. 5381202789Smav Hope it will be input monitoring. */ 5382202789Smav HDA_BOOTVERBOSE( 5383202789Smav device_printf(devinfo->codec->sc->dev, 5384202789Smav "Tracing other input monitors\n"); 5385202789Smav ); 5386202789Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5387202789Smav w = hdac_widget_get(devinfo, j); 5388202789Smav if (w == NULL || w->enable == 0) 5389202789Smav continue; 5390202789Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5391202789Smav continue; 5392202789Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5393202789Smav continue; 5394202789Smav HDA_BOOTVERBOSE( 5395202789Smav device_printf(devinfo->codec->sc->dev, 5396202789Smav " Tracing nid %d to out\n", 5397202789Smav j); 5398202789Smav ); 5399202789Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5400202789Smav HDA_BOOTVERBOSE( 5401202789Smav device_printf(devinfo->codec->sc->dev, 5402202789Smav " nid %d is input monitor\n", 5403202789Smav w->nid); 5404202789Smav ); 5405202789Smav } 5406202789Smav } 5407202789Smav 5408182999Smav /* Beeper */ 5409182999Smav HDA_BOOTVERBOSE( 5410182999Smav device_printf(devinfo->codec->sc->dev, 5411182999Smav "Tracing beeper\n"); 5412182999Smav ); 5413182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5414182999Smav w = hdac_widget_get(devinfo, j); 5415182999Smav if (w == NULL || w->enable == 0) 5416182999Smav continue; 5417182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5418182999Smav continue; 5419183097Smav HDA_BOOTHVERBOSE( 5420182999Smav device_printf(devinfo->codec->sc->dev, 5421182999Smav " Tracing nid %d to out\n", 5422182999Smav j); 5423182999Smav ); 5424183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5425183097Smav HDA_BOOTVERBOSE( 5426183097Smav device_printf(devinfo->codec->sc->dev, 5427183097Smav " nid %d traced to out\n", 5428183097Smav j); 5429183097Smav ); 5430183097Smav } 5431182999Smav w->bindas = -2; 5432182999Smav } 5433162922Sariff} 5434162922Sariff 5435182999Smav/* 5436182999Smav * Bind assotiations to PCM channels 5437182999Smav */ 5438182999Smavstatic void 5439182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5440162922Sariff{ 5441182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5442182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5443182999Smav int j, cnt = 0, free; 5444162922Sariff 5445182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5446182999Smav if (as[j].enable) 5447182999Smav cnt++; 5448182999Smav } 5449182999Smav if (sc->num_chans == 0) { 5450182999Smav sc->chans = (struct hdac_chan *)malloc( 5451182999Smav sizeof(struct hdac_chan) * cnt, 5452182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5453182999Smav if (sc->chans == NULL) { 5454190519Smav device_printf(sc->dev, 5455182999Smav "Channels memory allocation failed!\n"); 5456182999Smav return; 5457182999Smav } 5458182999Smav } else { 5459182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5460183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5461182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5462182999Smav if (sc->chans == NULL) { 5463182999Smav sc->num_chans = 0; 5464190519Smav device_printf(sc->dev, 5465182999Smav "Channels memory allocation failed!\n"); 5466182999Smav return; 5467182999Smav } 5468190519Smav /* Fixup relative pointers after realloc */ 5469190519Smav for (j = 0; j < sc->num_chans; j++) 5470190519Smav sc->chans[j].caps.fmtlist = sc->chans[j].fmtlist; 5471182999Smav } 5472182999Smav free = sc->num_chans; 5473182999Smav sc->num_chans += cnt; 5474162922Sariff 5475182999Smav for (j = free; j < free + cnt; j++) { 5476190519Smav sc->chans[j].devinfo = devinfo; 5477190519Smav sc->chans[j].as = -1; 5478182999Smav } 5479162922Sariff 5480182999Smav /* Assign associations in order of their numbers, */ 5481182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5482182999Smav if (as[j].enable == 0) 5483182999Smav continue; 5484182999Smav 5485182999Smav as[j].chan = free; 5486190519Smav sc->chans[free].as = j; 5487190519Smav sc->chans[free].dir = 5488185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5489190519Smav hdac_pcmchannel_setup(&sc->chans[free]); 5490182999Smav free++; 5491182999Smav } 5492182999Smav} 5493162922Sariff 5494182999Smavstatic void 5495182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5496182999Smav{ 5497182999Smav struct hdac_widget *w; 5498182999Smav int i; 5499182999Smav 5500182999Smav /* Disable power and volume widgets. */ 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_POWER_WIDGET || 5506182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5507182999Smav w->enable = 0; 5508183097Smav HDA_BOOTHVERBOSE( 5509182999Smav device_printf(devinfo->codec->sc->dev, 5510182999Smav " Disabling nid %d due to it's" 5511182999Smav " non-audio type.\n", 5512182999Smav w->nid); 5513182999Smav ); 5514162922Sariff } 5515182999Smav } 5516182999Smav} 5517182999Smav 5518182999Smavstatic void 5519182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5520182999Smav{ 5521182999Smav struct hdac_widget *w, *cw; 5522182999Smav struct hdac_audio_ctl *ctl; 5523182999Smav int done, found, i, j, k; 5524182999Smav 5525182999Smav /* Disable useless pins. */ 5526182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5527182999Smav w = hdac_widget_get(devinfo, i); 5528182999Smav if (w == NULL || w->enable == 0) 5529182999Smav continue; 5530184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5531184991Smav if ((w->wclass.pin.config & 5532184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5533184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5534184991Smav w->enable = 0; 5535184991Smav HDA_BOOTHVERBOSE( 5536184991Smav device_printf(devinfo->codec->sc->dev, 5537184991Smav " Disabling pin nid %d due" 5538184991Smav " to None connectivity.\n", 5539184991Smav w->nid); 5540184991Smav ); 5541184991Smav } else if ((w->wclass.pin.config & 5542184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5543184991Smav w->enable = 0; 5544184991Smav HDA_BOOTHVERBOSE( 5545184991Smav device_printf(devinfo->codec->sc->dev, 5546184991Smav " Disabling unassociated" 5547184991Smav " pin nid %d.\n", 5548184991Smav w->nid); 5549184991Smav ); 5550184991Smav } 5551182999Smav } 5552182999Smav } 5553182999Smav do { 5554182999Smav done = 1; 5555182999Smav /* Disable and mute controls for disabled widgets. */ 5556162922Sariff i = 0; 5557162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5558182999Smav if (ctl->enable == 0) 5559162922Sariff continue; 5560182999Smav if (ctl->widget->enable == 0 || 5561182999Smav (ctl->childwidget != NULL && 5562182999Smav ctl->childwidget->enable == 0)) { 5563182999Smav ctl->forcemute = 1; 5564182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5565182999Smav ctl->left = 0; 5566182999Smav ctl->right = 0; 5567182999Smav ctl->enable = 0; 5568182999Smav if (ctl->ndir == HDA_CTL_IN) 5569182999Smav ctl->widget->connsenable[ctl->index] = 0; 5570182999Smav done = 0; 5571183097Smav HDA_BOOTHVERBOSE( 5572182999Smav device_printf(devinfo->codec->sc->dev, 5573182999Smav " Disabling ctl %d nid %d cnid %d due" 5574182999Smav " to disabled widget.\n", i, 5575182999Smav ctl->widget->nid, 5576182999Smav (ctl->childwidget != NULL)? 5577182999Smav ctl->childwidget->nid:-1); 5578182999Smav ); 5579182999Smav } 5580182999Smav } 5581182999Smav /* Disable useless widgets. */ 5582182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5583182999Smav w = hdac_widget_get(devinfo, i); 5584182999Smav if (w == NULL || w->enable == 0) 5585182999Smav continue; 5586182999Smav /* Disable inputs with disabled child widgets. */ 5587182999Smav for (j = 0; j < w->nconns; j++) { 5588182999Smav if (w->connsenable[j]) { 5589182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5590182999Smav if (cw == NULL || cw->enable == 0) { 5591182999Smav w->connsenable[j] = 0; 5592183097Smav HDA_BOOTHVERBOSE( 5593182999Smav device_printf(devinfo->codec->sc->dev, 5594182999Smav " Disabling nid %d connection %d due" 5595182999Smav " to disabled child widget.\n", 5596182999Smav i, j); 5597182999Smav ); 5598163057Sariff } 5599163057Sariff } 5600162922Sariff } 5601182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5602182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5603162922Sariff continue; 5604182999Smav /* Disable mixers and selectors without inputs. */ 5605182999Smav found = 0; 5606182999Smav for (j = 0; j < w->nconns; j++) { 5607182999Smav if (w->connsenable[j]) { 5608182999Smav found = 1; 5609162922Sariff break; 5610162922Sariff } 5611182999Smav } 5612182999Smav if (found == 0) { 5613182999Smav w->enable = 0; 5614182999Smav done = 0; 5615183097Smav HDA_BOOTHVERBOSE( 5616182999Smav device_printf(devinfo->codec->sc->dev, 5617182999Smav " Disabling nid %d due to all it's" 5618182999Smav " inputs disabled.\n", w->nid); 5619182999Smav ); 5620182999Smav } 5621182999Smav /* Disable nodes without consumers. */ 5622182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5623182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5624182999Smav continue; 5625182999Smav found = 0; 5626182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5627182999Smav cw = hdac_widget_get(devinfo, k); 5628182999Smav if (cw == NULL || cw->enable == 0) 5629182999Smav continue; 5630182999Smav for (j = 0; j < cw->nconns; j++) { 5631182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5632182999Smav found = 1; 5633182999Smav break; 5634182999Smav } 5635162922Sariff } 5636162922Sariff } 5637182999Smav if (found == 0) { 5638182999Smav w->enable = 0; 5639182999Smav done = 0; 5640183097Smav HDA_BOOTHVERBOSE( 5641182999Smav device_printf(devinfo->codec->sc->dev, 5642182999Smav " Disabling nid %d due to all it's" 5643182999Smav " consumers disabled.\n", w->nid); 5644182999Smav ); 5645182999Smav } 5646162922Sariff } 5647182999Smav } while (done == 0); 5648182999Smav 5649182999Smav} 5650182999Smav 5651182999Smavstatic void 5652182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5653182999Smav{ 5654182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5655182999Smav struct hdac_widget *w, *cw; 5656182999Smav struct hdac_audio_ctl *ctl; 5657182999Smav int i, j, k; 5658182999Smav 5659182999Smav /* Disable unassosiated widgets. */ 5660182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5661182999Smav w = hdac_widget_get(devinfo, i); 5662182999Smav if (w == NULL || w->enable == 0) 5663182999Smav continue; 5664182999Smav if (w->bindas == -1) { 5665182999Smav w->enable = 0; 5666183097Smav HDA_BOOTHVERBOSE( 5667182999Smav device_printf(devinfo->codec->sc->dev, 5668182999Smav " Disabling unassociated nid %d.\n", 5669182999Smav w->nid); 5670182999Smav ); 5671182999Smav } 5672182999Smav } 5673182999Smav /* Disable input connections on input pin and 5674182999Smav * output on output. */ 5675182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5676182999Smav w = hdac_widget_get(devinfo, i); 5677182999Smav if (w == NULL || w->enable == 0) 5678182999Smav continue; 5679182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5680182999Smav continue; 5681182999Smav if (w->bindas < 0) 5682182999Smav continue; 5683182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5684182999Smav for (j = 0; j < w->nconns; j++) { 5685182999Smav if (w->connsenable[j] == 0) 5686182999Smav continue; 5687182999Smav w->connsenable[j] = 0; 5688183097Smav HDA_BOOTHVERBOSE( 5689182999Smav device_printf(devinfo->codec->sc->dev, 5690182999Smav " Disabling connection to input pin " 5691182999Smav "nid %d conn %d.\n", 5692182999Smav i, j); 5693182999Smav ); 5694162922Sariff } 5695182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5696182999Smav HDA_CTL_IN, -1, 1); 5697182999Smav if (ctl && ctl->enable) { 5698182999Smav ctl->forcemute = 1; 5699182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5700182999Smav ctl->left = 0; 5701182999Smav ctl->right = 0; 5702182999Smav ctl->enable = 0; 5703182999Smav } 5704182999Smav } else { 5705182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5706182999Smav HDA_CTL_OUT, -1, 1); 5707182999Smav if (ctl && ctl->enable) { 5708182999Smav ctl->forcemute = 1; 5709182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5710182999Smav ctl->left = 0; 5711182999Smav ctl->right = 0; 5712182999Smav ctl->enable = 0; 5713182999Smav } 5714182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5715182999Smav cw = hdac_widget_get(devinfo, k); 5716182999Smav if (cw == NULL || cw->enable == 0) 5717182999Smav continue; 5718182999Smav for (j = 0; j < cw->nconns; j++) { 5719182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5720182999Smav cw->connsenable[j] = 0; 5721183097Smav HDA_BOOTHVERBOSE( 5722182999Smav device_printf(devinfo->codec->sc->dev, 5723182999Smav " Disabling connection from output pin " 5724182999Smav "nid %d conn %d cnid %d.\n", 5725182999Smav k, j, i); 5726182999Smav ); 5727182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5728182999Smav cw->nconns > 1) 5729182999Smav continue; 5730182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5731182999Smav HDA_CTL_IN, j, 1); 5732182999Smav if (ctl && ctl->enable) { 5733182999Smav ctl->forcemute = 1; 5734182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5735182999Smav ctl->left = 0; 5736182999Smav ctl->right = 0; 5737182999Smav ctl->enable = 0; 5738182999Smav } 5739182999Smav } 5740182999Smav } 5741182999Smav } 5742162922Sariff } 5743162922Sariff } 5744162922Sariff} 5745162922Sariff 5746182999Smavstatic void 5747182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5748162922Sariff{ 5749182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5750182999Smav struct hdac_widget *w; 5751182999Smav int i, j; 5752182999Smav 5753182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5754182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5755182999Smav w = hdac_widget_get(devinfo, i); 5756182999Smav if (w == NULL || w->enable == 0) 5757182999Smav continue; 5758182999Smav if (w->nconns <= 1) 5759182999Smav continue; 5760182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5761182999Smav continue; 5762182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5763182999Smav continue; 5764182999Smav for (j = 0; j < w->nconns; j++) { 5765182999Smav if (w->connsenable[j] == 0) 5766182999Smav continue; 5767182999Smav if (w->selconn < 0 || w->selconn == j) 5768182999Smav continue; 5769182999Smav w->connsenable[j] = 0; 5770183097Smav HDA_BOOTHVERBOSE( 5771182999Smav device_printf(devinfo->codec->sc->dev, 5772182999Smav " Disabling unselected connection " 5773182999Smav "nid %d conn %d.\n", 5774182999Smav i, j); 5775182999Smav ); 5776182999Smav } 5777182999Smav } 5778182999Smav} 5779182999Smav 5780182999Smavstatic void 5781182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5782182999Smav{ 5783202789Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5784162922Sariff struct hdac_widget *w, *cw; 5785162922Sariff struct hdac_audio_ctl *ctl; 5786182999Smav int i, j; 5787162922Sariff 5788187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5789182999Smav /* ... using selectors */ 5790182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5791182999Smav w = hdac_widget_get(devinfo, i); 5792182999Smav if (w == NULL || w->enable == 0) 5793182999Smav continue; 5794182999Smav if (w->nconns <= 1) 5795182999Smav continue; 5796182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5797182999Smav continue; 5798182999Smav if (w->bindas == -2) 5799182999Smav continue; 5800182999Smav for (j = 0; j < w->nconns; j++) { 5801182999Smav if (w->connsenable[j] == 0) 5802182999Smav continue; 5803182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5804182999Smav if (cw == NULL || w->enable == 0) 5805182999Smav continue; 5806202789Smav if (cw->bindas == -2 || 5807202789Smav ((w->pflags & HDA_ADC_MONITOR) && 5808202789Smav cw->bindas >= 0 && 5809202789Smav ases[cw->bindas].dir == HDA_CTL_IN)) 5810182999Smav continue; 5811187052Smav if (w->bindas == cw->bindas && 5812187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5813187052Smav continue; 5814182999Smav w->connsenable[j] = 0; 5815183097Smav HDA_BOOTHVERBOSE( 5816182999Smav device_printf(devinfo->codec->sc->dev, 5817182999Smav " Disabling crossassociatement connection " 5818182999Smav "nid %d conn %d cnid %d.\n", 5819182999Smav i, j, cw->nid); 5820182999Smav ); 5821182999Smav } 5822182999Smav } 5823182999Smav /* ... using controls */ 5824182999Smav i = 0; 5825182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5826182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5827182999Smav continue; 5828202789Smav if (ctl->widget->bindas == -2) 5829182999Smav continue; 5830202789Smav if (ctl->childwidget->bindas == -2 || 5831202789Smav ((ctl->widget->pflags & HDA_ADC_MONITOR) && 5832202789Smav ctl->childwidget->bindas >= 0 && 5833202789Smav ases[ctl->childwidget->bindas].dir == HDA_CTL_IN)) 5834202789Smav continue; 5835187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5836187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5837182999Smav ctl->forcemute = 1; 5838182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5839182999Smav ctl->left = 0; 5840182999Smav ctl->right = 0; 5841182999Smav ctl->enable = 0; 5842182999Smav if (ctl->ndir == HDA_CTL_IN) 5843182999Smav ctl->widget->connsenable[ctl->index] = 0; 5844183097Smav HDA_BOOTHVERBOSE( 5845182999Smav device_printf(devinfo->codec->sc->dev, 5846182999Smav " Disabling crossassociatement connection " 5847182999Smav "ctl %d nid %d cnid %d.\n", i, 5848182999Smav ctl->widget->nid, 5849182999Smav ctl->childwidget->nid); 5850182999Smav ); 5851182999Smav } 5852182999Smav } 5853182999Smav 5854182999Smav} 5855182999Smav 5856182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5857182999Smav 5858182999Smav/* 5859182999Smav * Find controls to control amplification for source. 5860182999Smav */ 5861182999Smavstatic int 5862182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5863182999Smav int ossdev, int ctlable, int depth, int need) 5864182999Smav{ 5865182999Smav struct hdac_widget *w, *wc; 5866182999Smav struct hdac_audio_ctl *ctl; 5867182999Smav int i, j, conns = 0, rneed; 5868182999Smav 5869162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5870182999Smav return (need); 5871162922Sariff 5872162922Sariff w = hdac_widget_get(devinfo, nid); 5873162922Sariff if (w == NULL || w->enable == 0) 5874182999Smav return (need); 5875182999Smav 5876182999Smav /* Count number of active inputs. */ 5877182999Smav if (depth > 0) { 5878182999Smav for (j = 0; j < w->nconns; j++) { 5879182999Smav if (w->connsenable[j]) 5880182999Smav conns++; 5881162922Sariff } 5882162922Sariff } 5883182999Smav 5884182999Smav /* If this is not a first step - use input mixer. 5885182999Smav Pins have common input ctl so care must be taken. */ 5886182999Smav if (depth > 0 && ctlable && (conns == 1 || 5887182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5888182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5889182999Smav index, 1); 5890182999Smav if (ctl) { 5891182999Smav if (HDA_CTL_GIVE(ctl) & need) 5892182999Smav ctl->ossmask |= (1 << ossdev); 5893182999Smav else 5894182999Smav ctl->possmask |= (1 << ossdev); 5895182999Smav need &= ~HDA_CTL_GIVE(ctl); 5896182999Smav } 5897182999Smav } 5898182999Smav 5899182999Smav /* If widget has own ossdev - not traverse it. 5900182999Smav It will be traversed on it's own. */ 5901182999Smav if (w->ossdev >= 0 && depth > 0) 5902182999Smav return (need); 5903182999Smav 5904182999Smav /* We must not traverse pin */ 5905182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5906182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5907182999Smav depth > 0) 5908182999Smav return (need); 5909182999Smav 5910182999Smav /* record that this widget exports such signal, */ 5911182999Smav w->ossmask |= (1 << ossdev); 5912182999Smav 5913182999Smav /* If signals mixed, we can't assign controls farther. 5914182999Smav * Ignore this on depth zero. Caller must knows why. 5915182999Smav * Ignore this for static selectors if this input selected. 5916182999Smav */ 5917182999Smav if (conns > 1) 5918182999Smav ctlable = 0; 5919182999Smav 5920182999Smav if (ctlable) { 5921182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5922182999Smav if (ctl) { 5923182999Smav if (HDA_CTL_GIVE(ctl) & need) 5924182999Smav ctl->ossmask |= (1 << ossdev); 5925182999Smav else 5926182999Smav ctl->possmask |= (1 << ossdev); 5927182999Smav need &= ~HDA_CTL_GIVE(ctl); 5928182999Smav } 5929182999Smav } 5930182999Smav 5931182999Smav rneed = 0; 5932182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5933182999Smav wc = hdac_widget_get(devinfo, i); 5934182999Smav if (wc == NULL || wc->enable == 0) 5935162922Sariff continue; 5936182999Smav for (j = 0; j < wc->nconns; j++) { 5937182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5938182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5939182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5940182999Smav } 5941162922Sariff } 5942162922Sariff } 5943182999Smav rneed &= need; 5944182999Smav 5945182999Smav return (rneed); 5946162922Sariff} 5947162922Sariff 5948182999Smav/* 5949182999Smav * Find controls to control amplification for destination. 5950182999Smav */ 5951182999Smavstatic void 5952202789Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5953182999Smav int ossdev, int depth, int need) 5954162922Sariff{ 5955182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5956182999Smav struct hdac_widget *w, *wc; 5957182999Smav struct hdac_audio_ctl *ctl; 5958182999Smav int i, j, consumers; 5959182999Smav 5960162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5961182999Smav return; 5962162922Sariff 5963162922Sariff w = hdac_widget_get(devinfo, nid); 5964162922Sariff if (w == NULL || w->enable == 0) 5965182999Smav return; 5966182999Smav 5967182999Smav if (depth > 0) { 5968182999Smav /* If this node produce output for several consumers, 5969182999Smav we can't touch it. */ 5970182999Smav consumers = 0; 5971182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5972182999Smav wc = hdac_widget_get(devinfo, i); 5973182999Smav if (wc == NULL || wc->enable == 0) 5974182999Smav continue; 5975182999Smav for (j = 0; j < wc->nconns; j++) { 5976182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5977182999Smav consumers++; 5978182999Smav } 5979182999Smav } 5980182999Smav /* The only exception is if real HP redirection is configured 5981182999Smav and this is a duplication point. 5982182999Smav XXX: Actually exception is not completely correct. 5983182999Smav XXX: Duplication point check is not perfect. */ 5984182999Smav if ((consumers == 2 && (w->bindas < 0 || 5985182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5986182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5987182999Smav consumers > 2) 5988182999Smav return; 5989182999Smav 5990182999Smav /* Else use it's output mixer. */ 5991182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5992182999Smav HDA_CTL_OUT, -1, 1); 5993182999Smav if (ctl) { 5994182999Smav if (HDA_CTL_GIVE(ctl) & need) 5995182999Smav ctl->ossmask |= (1 << ossdev); 5996182999Smav else 5997182999Smav ctl->possmask |= (1 << ossdev); 5998182999Smav need &= ~HDA_CTL_GIVE(ctl); 5999182999Smav } 6000182999Smav } 6001182999Smav 6002182999Smav /* We must not traverse pin */ 6003182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6004182999Smav depth > 0) 6005182999Smav return; 6006182999Smav 6007162922Sariff for (i = 0; i < w->nconns; i++) { 6008182999Smav int tneed = need; 6009182999Smav if (w->connsenable[i] == 0) 6010162922Sariff continue; 6011202789Smav if (index >= 0 && i != index) 6012202789Smav continue; 6013182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 6014182999Smav HDA_CTL_IN, i, 1); 6015182999Smav if (ctl) { 6016182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 6017182999Smav ctl->ossmask |= (1 << ossdev); 6018182999Smav else 6019182999Smav ctl->possmask |= (1 << ossdev); 6020182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 6021162922Sariff } 6022202789Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev, 6023182999Smav depth + 1, tneed); 6024162922Sariff } 6025162922Sariff} 6026162922Sariff 6027182999Smav/* 6028182999Smav * Assign OSS names to sound sources 6029182999Smav */ 6030182999Smavstatic void 6031182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 6032162922Sariff{ 6033182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6034182999Smav struct hdac_widget *w; 6035182999Smav int i, j; 6036182999Smav int type = -1, use, used = 0; 6037182999Smav static const int types[7][13] = { 6038182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6039182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 6040182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 6041182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 6042182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 6043182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 6044182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 6045182999Smav -1 }, /* digital */ 6046182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6047182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 6048182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 6049182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 6050182999Smav -1 } /* others */ 6051182999Smav }; 6052162922Sariff 6053182999Smav /* Surely known names */ 6054162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6055162922Sariff w = hdac_widget_get(devinfo, i); 6056162922Sariff if (w == NULL || w->enable == 0) 6057162922Sariff continue; 6058182999Smav if (w->bindas == -1) 6059182999Smav continue; 6060182999Smav use = -1; 6061182999Smav switch (w->type) { 6062182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 6063182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6064182999Smav break; 6065182999Smav type = -1; 6066182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6067182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 6068182999Smav type = 0; 6069182999Smav break; 6070182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6071182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 6072182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 6073182999Smav break; 6074182999Smav type = 1; 6075182999Smav break; 6076182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 6077182999Smav type = 3; 6078182999Smav break; 6079182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6080182999Smav type = 4; 6081182999Smav break; 6082182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 6083182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 6084182999Smav type = 5; 6085182999Smav break; 6086182999Smav } 6087182999Smav if (type == -1) 6088182999Smav break; 6089182999Smav j = 0; 6090182999Smav while (types[type][j] >= 0 && 6091182999Smav (used & (1 << types[type][j])) != 0) { 6092182999Smav j++; 6093182999Smav } 6094182999Smav if (types[type][j] >= 0) 6095182999Smav use = types[type][j]; 6096182999Smav break; 6097182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 6098182999Smav use = SOUND_MIXER_PCM; 6099182999Smav break; 6100182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 6101182999Smav use = SOUND_MIXER_SPEAKER; 6102182999Smav break; 6103182999Smav default: 6104182999Smav break; 6105182999Smav } 6106182999Smav if (use >= 0) { 6107182999Smav w->ossdev = use; 6108182999Smav used |= (1 << use); 6109182999Smav } 6110182999Smav } 6111182999Smav /* Semi-known names */ 6112182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6113182999Smav w = hdac_widget_get(devinfo, i); 6114182999Smav if (w == NULL || w->enable == 0) 6115182999Smav continue; 6116182999Smav if (w->ossdev >= 0) 6117182999Smav continue; 6118182999Smav if (w->bindas == -1) 6119182999Smav continue; 6120162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6121162922Sariff continue; 6122182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6123162922Sariff continue; 6124182999Smav type = -1; 6125182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6126182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 6127182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6128182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 6129182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 6130182999Smav type = 0; 6131182999Smav break; 6132182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6133182999Smav type = 2; 6134182999Smav break; 6135182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 6136182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 6137182999Smav type = 5; 6138182999Smav break; 6139182999Smav } 6140182999Smav if (type == -1) 6141182999Smav break; 6142182999Smav j = 0; 6143182999Smav while (types[type][j] >= 0 && 6144182999Smav (used & (1 << types[type][j])) != 0) { 6145182999Smav j++; 6146182999Smav } 6147182999Smav if (types[type][j] >= 0) { 6148182999Smav w->ossdev = types[type][j]; 6149182999Smav used |= (1 << types[type][j]); 6150182999Smav } 6151182999Smav } 6152182999Smav /* Others */ 6153182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6154182999Smav w = hdac_widget_get(devinfo, i); 6155182999Smav if (w == NULL || w->enable == 0) 6156162922Sariff continue; 6157182999Smav if (w->ossdev >= 0) 6158182999Smav continue; 6159182999Smav if (w->bindas == -1) 6160182999Smav continue; 6161182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6162182999Smav continue; 6163182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6164182999Smav continue; 6165182999Smav j = 0; 6166182999Smav while (types[6][j] >= 0 && 6167182999Smav (used & (1 << types[6][j])) != 0) { 6168182999Smav j++; 6169162922Sariff } 6170182999Smav if (types[6][j] >= 0) { 6171182999Smav w->ossdev = types[6][j]; 6172182999Smav used |= (1 << types[6][j]); 6173182999Smav } 6174162922Sariff } 6175162922Sariff} 6176162922Sariff 6177162922Sariffstatic void 6178162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 6179162922Sariff{ 6180182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6181182999Smav int j, res; 6182162922Sariff 6183182999Smav /* Trace all associations in order of their numbers, */ 6184182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 6185182999Smav if (as[j].enable == 0) 6186182999Smav continue; 6187163057Sariff HDA_BOOTVERBOSE( 6188162922Sariff device_printf(devinfo->codec->sc->dev, 6189182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6190162922Sariff ); 6191182999Smav if (as[j].dir == HDA_CTL_OUT) { 6192182999Smavretry: 6193182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6194182999Smav if (res == 0 && as[j].hpredir >= 0 && 6195182999Smav as[j].fakeredir == 0) { 6196182999Smav /* If codec can't do analog HP redirection 6197182999Smav try to make it using one more DAC. */ 6198182999Smav as[j].fakeredir = 1; 6199182999Smav goto retry; 6200182999Smav } 6201182999Smav } else { 6202182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6203182999Smav } 6204182999Smav if (res) { 6205182999Smav HDA_BOOTVERBOSE( 6206182999Smav device_printf(devinfo->codec->sc->dev, 6207188510Smav "Association %d (%d) trace succeeded\n", 6208182999Smav j, as[j].index); 6209182999Smav ); 6210182999Smav } else { 6211182999Smav HDA_BOOTVERBOSE( 6212182999Smav device_printf(devinfo->codec->sc->dev, 6213182999Smav "Association %d (%d) trace failed\n", 6214182999Smav j, as[j].index); 6215182999Smav ); 6216182999Smav as[j].enable = 0; 6217182999Smav } 6218162922Sariff } 6219162922Sariff 6220182999Smav /* Trace mixer and beeper pseudo associations. */ 6221182999Smav hdac_audio_trace_as_extra(devinfo); 6222182999Smav} 6223162922Sariff 6224182999Smavstatic void 6225182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6226182999Smav{ 6227182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6228182999Smav struct hdac_audio_ctl *ctl; 6229202789Smav struct hdac_widget *w, *cw; 6230202789Smav int i, j; 6231162922Sariff 6232182999Smav /* Assign mixers to the tree. */ 6233162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6234162922Sariff w = hdac_widget_get(devinfo, i); 6235162922Sariff if (w == NULL || w->enable == 0) 6236162922Sariff continue; 6237182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6238182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6239182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6240182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6241182999Smav if (w->ossdev < 0) 6242182999Smav continue; 6243182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6244182999Smav w->ossdev, 1, 0, 1); 6245182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6246202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6247182999Smav SOUND_MIXER_RECLEV, 0, 1); 6248182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6249182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6250202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6251182999Smav SOUND_MIXER_VOLUME, 0, 1); 6252162922Sariff } 6253202796Smav if (w->ossdev == SOUND_MIXER_IMIX) { 6254202796Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6255202796Smav w->ossdev, 1, 0, 1)) { 6256202796Smav /* If we are unable to control input monitor 6257202796Smav as source - try to control it as destination. */ 6258202796Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6259202796Smav w->ossdev, 0, 1); 6260202796Smav } 6261202796Smav } 6262202789Smav if (w->pflags & HDA_ADC_MONITOR) { 6263202789Smav for (j = 0; j < w->nconns; j++) { 6264202789Smav if (!w->connsenable[j]) 6265202789Smav continue; 6266202789Smav cw = hdac_widget_get(devinfo, w->conns[j]); 6267202789Smav if (cw == NULL || cw->enable == 0) 6268202789Smav continue; 6269202789Smav if (cw->bindas == -1) 6270202789Smav continue; 6271202789Smav if (cw->bindas >= 0 && 6272202789Smav as[cw->bindas].dir != HDA_CTL_IN) 6273202789Smav continue; 6274202789Smav hdac_audio_ctl_dest_amp(devinfo, 6275202796Smav w->nid, j, SOUND_MIXER_IGAIN, 0, 1); 6276202789Smav } 6277202789Smav } 6278162922Sariff } 6279182999Smav /* Treat unrequired as possible. */ 6280182999Smav i = 0; 6281182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6282182999Smav if (ctl->ossmask == 0) 6283182999Smav ctl->ossmask = ctl->possmask; 6284182999Smav } 6285182999Smav} 6286162922Sariff 6287182999Smavstatic void 6288182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6289182999Smav{ 6290182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6291182999Smav struct hdac_widget *w; 6292182999Smav uint32_t pincap; 6293182999Smav int i; 6294182999Smav 6295182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6296182999Smav w = &devinfo->widget[i]; 6297182999Smav if (w == NULL) 6298162922Sariff continue; 6299182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6300162922Sariff continue; 6301182999Smav 6302182999Smav pincap = w->wclass.pin.cap; 6303182999Smav 6304182999Smav /* Disable everything. */ 6305182999Smav w->wclass.pin.ctrl &= ~( 6306182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6307182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6308182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6309182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6310182999Smav 6311182999Smav if (w->enable == 0 || 6312182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6313182999Smav /* Pin is unused so left it disabled. */ 6314182999Smav continue; 6315182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6316182999Smav /* Input pin, configure for input. */ 6317182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6318182999Smav w->wclass.pin.ctrl |= 6319182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6320182999Smav 6321182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6322182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6323182999Smav w->wclass.pin.ctrl |= 6324182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6325182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6326182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6327182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6328182999Smav w->wclass.pin.ctrl |= 6329182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6330182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6331182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6332182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6333182999Smav w->wclass.pin.ctrl |= 6334182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6335182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6336182999Smav } else { 6337182999Smav /* Output pin, configure for output. */ 6338182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6339182999Smav w->wclass.pin.ctrl |= 6340182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6341182999Smav 6342182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6343182999Smav (w->wclass.pin.config & 6344182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6345182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6346182999Smav w->wclass.pin.ctrl |= 6347182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6348182999Smav 6349182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6350182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6351182999Smav w->wclass.pin.ctrl |= 6352182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6353182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6354182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6355182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6356182999Smav w->wclass.pin.ctrl |= 6357182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6358182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6359182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6360182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6361182999Smav w->wclass.pin.ctrl |= 6362182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6363182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6364182999Smav } 6365162922Sariff } 6366162922Sariff} 6367162922Sariff 6368162922Sariffstatic void 6369187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6370187154Smav{ 6371187154Smav struct hdac_audio_ctl *ctl; 6372187154Smav int i, z; 6373187154Smav 6374187154Smav i = 0; 6375187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6376187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6377187154Smav /* Mute disabled and mixer controllable controls. 6378187154Smav * Last will be initialized by mixer_init(). 6379187154Smav * This expected to reduce click on startup. */ 6380187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6381187154Smav continue; 6382187154Smav } 6383187154Smav /* Init fixed controls to 0dB amplification. */ 6384187154Smav z = ctl->offset; 6385187154Smav if (z > ctl->step) 6386187154Smav z = ctl->step; 6387187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6388187154Smav } 6389187154Smav} 6390187154Smav 6391187154Smavstatic void 6392182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6393162922Sariff{ 6394162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6395162922Sariff struct hdac_widget *w; 6396164750Sariff nid_t cad; 6397182999Smav uint32_t gdata, gmask, gdir; 6398182999Smav int commitgpio, numgpio; 6399164750Sariff int i; 6400162922Sariff 6401162922Sariff cad = devinfo->codec->cad; 6402162922Sariff 6403182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6404182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6405182999Smav 0x7e7, 0), cad); 6406169277Sariff 6407187154Smav /* Commit controls. */ 6408187154Smav hdac_audio_ctl_commit(devinfo); 6409187154Smav 6410187154Smav /* Commit selectors, pins and EAPD. */ 6411187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6412187154Smav w = &devinfo->widget[i]; 6413187154Smav if (w == NULL) 6414187154Smav continue; 6415187154Smav if (w->selconn == -1) 6416187154Smav w->selconn = 0; 6417187154Smav if (w->nconns > 0) 6418187154Smav hdac_widget_connection_select(w, w->selconn); 6419187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6420187154Smav hdac_command(sc, 6421187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6422187154Smav w->wclass.pin.ctrl), cad); 6423187154Smav } 6424187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6425187154Smav uint32_t val; 6426187154Smav 6427187154Smav val = w->param.eapdbtl; 6428187154Smav if (devinfo->function.audio.quirks & 6429187154Smav HDA_QUIRK_EAPDINV) 6430187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6431187154Smav hdac_command(sc, 6432187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6433187154Smav val), cad); 6434187154Smav } 6435187154Smav } 6436187154Smav 6437187154Smav /* Commit GPIOs. */ 6438182999Smav gdata = 0; 6439182999Smav gmask = 0; 6440182999Smav gdir = 0; 6441182999Smav commitgpio = 0; 6442182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6443182999Smav devinfo->function.audio.gpio); 6444166796Sariff 6445182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6446182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6447182999Smav else { 6448182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6449182999Smav if (!(devinfo->function.audio.quirks & 6450182999Smav (1 << i))) 6451182999Smav continue; 6452182999Smav if (commitgpio == 0) { 6453182999Smav commitgpio = 1; 6454182999Smav HDA_BOOTVERBOSE( 6455182999Smav gdata = hdac_command(sc, 6456182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6457182999Smav devinfo->nid), cad); 6458182999Smav gmask = hdac_command(sc, 6459182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6460182999Smav devinfo->nid), cad); 6461182999Smav gdir = hdac_command(sc, 6462182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6463182999Smav devinfo->nid), cad); 6464182999Smav device_printf(sc->dev, 6465182999Smav "GPIO init: data=0x%08x " 6466182999Smav "mask=0x%08x dir=0x%08x\n", 6467182999Smav gdata, gmask, gdir); 6468182999Smav gdata = 0; 6469182999Smav gmask = 0; 6470182999Smav gdir = 0; 6471182999Smav ); 6472165039Sariff } 6473182999Smav gdata |= 1 << i; 6474182999Smav gmask |= 1 << i; 6475182999Smav gdir |= 1 << i; 6476165039Sariff } 6477182999Smav } 6478165039Sariff 6479182999Smav if (commitgpio != 0) { 6480182999Smav HDA_BOOTVERBOSE( 6481182999Smav device_printf(sc->dev, 6482182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6483182999Smav "dir=0x%08x\n", 6484182999Smav gdata, gmask, gdir); 6485182999Smav ); 6486182999Smav hdac_command(sc, 6487182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6488182999Smav gmask), cad); 6489182999Smav hdac_command(sc, 6490182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6491182999Smav gdir), cad); 6492182999Smav hdac_command(sc, 6493182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6494182999Smav gdata), cad); 6495162922Sariff } 6496162922Sariff} 6497162922Sariff 6498162922Sariffstatic void 6499182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6500182999Smav{ 6501182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6502182999Smav nid_t cad = devinfo->codec->cad; 6503182999Smav int i; 6504182999Smav 6505182999Smav hdac_command(sc, 6506182999Smav HDA_CMD_SET_POWER_STATE(cad, 6507182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6508182999Smav cad); 6509182999Smav DELAY(100); 6510182999Smav 6511182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6512182999Smav hdac_command(sc, 6513182999Smav HDA_CMD_SET_POWER_STATE(cad, 6514182999Smav i, HDA_CMD_POWER_STATE_D0), 6515182999Smav cad); 6516182999Smav } 6517182999Smav DELAY(1000); 6518182999Smav} 6519182999Smav 6520162922Sariffstatic int 6521182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6522162922Sariff{ 6523182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6524182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6525162922Sariff struct hdac_widget *w; 6526182999Smav uint32_t cap, fmtcap, pcmcap; 6527202127Smav int i, j, ret, channels, onlystereo; 6528202127Smav uint16_t pinset; 6529162922Sariff 6530162922Sariff ch->caps = hdac_caps; 6531162922Sariff ch->caps.fmtlist = ch->fmtlist; 6532162922Sariff ch->bit16 = 1; 6533162922Sariff ch->bit32 = 0; 6534162922Sariff ch->pcmrates[0] = 48000; 6535162922Sariff ch->pcmrates[1] = 0; 6536162922Sariff 6537162922Sariff ret = 0; 6538202127Smav channels = 0; 6539202127Smav onlystereo = 1; 6540202127Smav pinset = 0; 6541162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6542162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6543162922Sariff 6544202127Smav for (i = 0; i < 16; i++) { 6545182999Smav /* Check as is correct */ 6546182999Smav if (ch->as < 0) 6547182999Smav break; 6548182999Smav /* Cound only present DACs */ 6549182999Smav if (as[ch->as].dacs[i] <= 0) 6550162922Sariff continue; 6551182999Smav /* Ignore duplicates */ 6552182999Smav for (j = 0; j < ret; j++) { 6553182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6554182999Smav break; 6555182999Smav } 6556182999Smav if (j < ret) 6557162922Sariff continue; 6558182999Smav 6559182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6560182999Smav if (w == NULL || w->enable == 0) 6561182999Smav continue; 6562162922Sariff cap = w->param.supp_stream_formats; 6563182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6564182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6565162922Sariff continue; 6566202127Smav /* Many CODECs does not declare AC3 support on SPDIF. 6567182999Smav I don't beleave that they doesn't support it! */ 6568182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6569182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6570164614Sariff if (ret == 0) { 6571182999Smav fmtcap = cap; 6572164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6573164614Sariff } else { 6574182999Smav fmtcap &= cap; 6575164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6576164614Sariff } 6577182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6578202127Smav /* Do not count redirection pin/dac channels. */ 6579202127Smav if (i == 15 && as[ch->as].hpredir >= 0) 6580202127Smav continue; 6581202127Smav channels += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 6582202127Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) != 1) 6583202127Smav onlystereo = 0; 6584202127Smav pinset |= (1 << i); 6585162922Sariff } 6586162922Sariff ch->io[ret] = -1; 6587162922Sariff 6588202127Smav if (as[ch->as].fakeredir) 6589202127Smav ret--; 6590202127Smav /* Standard speaks only about stereo pins and playback, ... */ 6591202127Smav if ((!onlystereo) || as[ch->as].dir != HDA_CTL_OUT) 6592202127Smav pinset = 0; 6593202127Smav /* ..., but there it gives us info about speakers layout. */ 6594202127Smav as[ch->as].pinset = pinset; 6595202127Smav 6596162922Sariff ch->supp_stream_formats = fmtcap; 6597162922Sariff ch->supp_pcm_size_rate = pcmcap; 6598162922Sariff 6599162922Sariff /* 6600162922Sariff * 8bit = 0 6601162922Sariff * 16bit = 1 6602162922Sariff * 20bit = 2 6603162922Sariff * 24bit = 3 6604162922Sariff * 32bit = 4 6605162922Sariff */ 6606162922Sariff if (ret > 0) { 6607162922Sariff i = 0; 6608182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6609182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6610182999Smav ch->bit16 = 1; 6611182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6612182999Smav ch->bit16 = 0; 6613182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6614182999Smav ch->bit32 = 4; 6615182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6616182999Smav ch->bit32 = 3; 6617182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6618182999Smav ch->bit32 = 2; 6619202127Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) { 6620202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 1, 0); 6621202127Smav if (ch->bit32) 6622202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 1, 0); 6623182999Smav } 6624202127Smav if (channels >= 2) { 6625202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 2, 0); 6626202127Smav if (ch->bit32) 6627202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 2, 0); 6628202127Smav } 6629202127Smav if (channels == 4 || /* Any 4-channel */ 6630202127Smav pinset == 0x0007 || /* 5.1 */ 6631202127Smav pinset == 0x0013 || /* 5.1 */ 6632202127Smav pinset == 0x0017) { /* 7.1 */ 6633202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 4, 0); 6634202127Smav if (ch->bit32) 6635202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 0); 6636202127Smav } 6637202127Smav if (channels == 6 || /* Any 6-channel */ 6638202127Smav pinset == 0x0017) { /* 7.1 */ 6639202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 1); 6640202127Smav if (ch->bit32) 6641202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 1); 6642202127Smav } 6643202127Smav if (channels == 8) { /* Any 8-channel */ 6644202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 8, 1); 6645202127Smav if (ch->bit32) 6646202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 8, 1); 6647202127Smav } 6648162922Sariff } 6649182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6650193640Sariff ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 2, 0); 6651182999Smav } 6652162922Sariff ch->fmtlist[i] = 0; 6653162922Sariff i = 0; 6654182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6655162922Sariff ch->pcmrates[i++] = 8000; 6656182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6657162922Sariff ch->pcmrates[i++] = 11025; 6658182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6659162922Sariff ch->pcmrates[i++] = 16000; 6660182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6661162922Sariff ch->pcmrates[i++] = 22050; 6662182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6663162922Sariff ch->pcmrates[i++] = 32000; 6664182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6665162922Sariff ch->pcmrates[i++] = 44100; 6666182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6667162922Sariff ch->pcmrates[i++] = 48000; 6668182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6669162922Sariff ch->pcmrates[i++] = 88200; 6670182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6671162922Sariff ch->pcmrates[i++] = 96000; 6672182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6673162922Sariff ch->pcmrates[i++] = 176400; 6674182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6675162922Sariff ch->pcmrates[i++] = 192000; 6676182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6677162922Sariff ch->pcmrates[i] = 0; 6678162922Sariff if (i > 0) { 6679162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6680162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6681162922Sariff } 6682162922Sariff } 6683162922Sariff 6684162922Sariff return (ret); 6685162922Sariff} 6686162922Sariff 6687162922Sariffstatic void 6688185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6689185225Smav{ 6690185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6691185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6692185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6693185225Smav 6694185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6695185225Smav if (as[i].enable == 0) 6696185225Smav continue; 6697185225Smav if (as[i].dir == HDA_CTL_IN) { 6698185225Smav if (as[i].digital) 6699185225Smav drdev++; 6700185225Smav else 6701185225Smav ardev++; 6702185225Smav } else { 6703185225Smav if (as[i].digital) 6704185225Smav dpdev++; 6705185225Smav else 6706185225Smav apdev++; 6707185225Smav } 6708185225Smav } 6709185225Smav devinfo->function.audio.num_devs = 6710185225Smav max(ardev, apdev) + max(drdev, dpdev); 6711185225Smav devinfo->function.audio.devs = 6712185225Smav (struct hdac_pcm_devinfo *)malloc( 6713185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6714185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6715185225Smav if (devinfo->function.audio.devs == NULL) { 6716185225Smav device_printf(sc->dev, 6717185225Smav "Unable to allocate memory for devices\n"); 6718185225Smav return; 6719185225Smav } 6720185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6721185225Smav devinfo->function.audio.devs[i].index = i; 6722185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6723185225Smav devinfo->function.audio.devs[i].play = -1; 6724185225Smav devinfo->function.audio.devs[i].rec = -1; 6725197611Smav devinfo->function.audio.devs[i].digital = 255; 6726185225Smav } 6727185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6728185225Smav if (as[i].enable == 0) 6729185225Smav continue; 6730185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6731197611Smav if (devinfo->function.audio.devs[j].digital != 255 && 6732197640Smav (!devinfo->function.audio.devs[j].digital) != 6733197611Smav (!as[i].digital)) 6734185225Smav continue; 6735185225Smav if (as[i].dir == HDA_CTL_IN) { 6736185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6737185225Smav continue; 6738185225Smav devinfo->function.audio.devs[j].rec 6739185225Smav = as[i].chan; 6740185225Smav } else { 6741185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6742185225Smav continue; 6743185225Smav devinfo->function.audio.devs[j].play 6744185225Smav = as[i].chan; 6745185225Smav } 6746185225Smav sc->chans[as[i].chan].pdevinfo = 6747185225Smav &devinfo->function.audio.devs[j]; 6748185225Smav devinfo->function.audio.devs[j].digital = 6749185225Smav as[i].digital; 6750185225Smav break; 6751185225Smav } 6752185225Smav } 6753185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6754185225Smav struct hdac_pcm_devinfo *pdevinfo = 6755185225Smav &devinfo->function.audio.devs[i]; 6756185225Smav pdevinfo->dev = 6757185225Smav device_add_child(sc->dev, "pcm", -1); 6758185225Smav device_set_ivars(pdevinfo->dev, 6759185225Smav (void *)pdevinfo); 6760185225Smav } 6761185225Smav} 6762185225Smav 6763185225Smavstatic void 6764182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6765162922Sariff{ 6766182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6767162922Sariff struct hdac_audio_ctl *ctl; 6768162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6769182999Smav char buf[64]; 6770182999Smav int i, j, printed; 6771162922Sariff 6772162922Sariff if (flag == 0) { 6773182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6774162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6775202796Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IGAIN | 6776202796Smav SOUND_MASK_OGAIN | SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6777162922Sariff } 6778162922Sariff 6779182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6780182999Smav if ((flag & (1 << j)) == 0) 6781162922Sariff continue; 6782182999Smav i = 0; 6783182999Smav printed = 0; 6784182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6785182999Smav if (ctl->enable == 0 || 6786182999Smav ctl->widget->enable == 0) 6787182999Smav continue; 6788182999Smav if (!((pdevinfo->play >= 0 && 6789182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6790182999Smav (pdevinfo->rec >= 0 && 6791182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6792182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6793182999Smav continue; 6794182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6795182999Smav continue; 6796182999Smav 6797182999Smav if (printed == 0) { 6798182999Smav device_printf(pdevinfo->dev, "\n"); 6799182999Smav if (banner != NULL) { 6800182999Smav device_printf(pdevinfo->dev, "%s", banner); 6801182999Smav } else { 6802182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6803182999Smav } 6804182999Smav printf(" (OSS: %s)\n", 6805182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6806182999Smav buf, sizeof(buf))); 6807182999Smav device_printf(pdevinfo->dev, " |\n"); 6808182999Smav printed = 1; 6809162922Sariff } 6810182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6811182999Smav ctl->widget->nid, 6812182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6813182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6814182999Smav printf(" %2d): ", ctl->index); 6815182999Smav else 6816182999Smav printf("): "); 6817182999Smav if (ctl->step > 0) { 6818182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6819182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6820182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6821182999Smav ctl->step + 1, 6822182999Smav ctl->mute?" + mute":""); 6823182999Smav } else 6824182999Smav printf("%s\n", ctl->mute?"mute":""); 6825162922Sariff } 6826162922Sariff } 6827162922Sariff} 6828162922Sariff 6829162922Sariffstatic void 6830182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6831162922Sariff{ 6832162922Sariff uint32_t cap; 6833162922Sariff 6834162922Sariff cap = fcap; 6835162922Sariff if (cap != 0) { 6836182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6837183097Smav device_printf(dev, " "); 6838162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6839162922Sariff printf(" AC3"); 6840162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6841162922Sariff printf(" FLOAT32"); 6842162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6843162922Sariff printf(" PCM"); 6844162922Sariff printf("\n"); 6845162922Sariff } 6846162922Sariff cap = pcmcap; 6847162922Sariff if (cap != 0) { 6848182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6849183097Smav device_printf(dev, " "); 6850162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6851162922Sariff printf(" 8"); 6852162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6853162922Sariff printf(" 16"); 6854162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6855162922Sariff printf(" 20"); 6856162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6857162922Sariff printf(" 24"); 6858162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6859162922Sariff printf(" 32"); 6860183097Smav printf(" bits,"); 6861162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6862162922Sariff printf(" 8"); 6863162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6864162922Sariff printf(" 11"); 6865162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6866162922Sariff printf(" 16"); 6867162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6868162922Sariff printf(" 22"); 6869162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6870162922Sariff printf(" 32"); 6871162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6872162922Sariff printf(" 44"); 6873162922Sariff printf(" 48"); 6874162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6875162922Sariff printf(" 88"); 6876162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6877162922Sariff printf(" 96"); 6878162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6879162922Sariff printf(" 176"); 6880162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6881162922Sariff printf(" 192"); 6882183097Smav printf(" KHz\n"); 6883162922Sariff } 6884162922Sariff} 6885162922Sariff 6886162922Sariffstatic void 6887162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6888162922Sariff{ 6889183097Smav uint32_t pincap; 6890162922Sariff 6891162922Sariff pincap = w->wclass.pin.cap; 6892162922Sariff 6893162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6894162922Sariff device_printf(sc->dev, " "); 6895162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6896162922Sariff printf(" ISC"); 6897162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6898162922Sariff printf(" TRQD"); 6899162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6900162922Sariff printf(" PDC"); 6901162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6902162922Sariff printf(" HP"); 6903162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6904162922Sariff printf(" OUT"); 6905162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6906162922Sariff printf(" IN"); 6907162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6908162922Sariff printf(" BAL"); 6909197611Smav if (HDA_PARAM_PIN_CAP_HDMI(pincap)) 6910197611Smav printf(" HDMI"); 6911165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6912165069Sariff printf(" VREF["); 6913165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6914165069Sariff printf(" 50"); 6915165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6916165069Sariff printf(" 80"); 6917165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6918165069Sariff printf(" 100"); 6919165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6920165069Sariff printf(" GROUND"); 6921165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6922165069Sariff printf(" HIZ"); 6923165069Sariff printf(" ]"); 6924165069Sariff } 6925162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6926162922Sariff printf(" EAPD"); 6927197611Smav if (HDA_PARAM_PIN_CAP_DP(pincap)) 6928197611Smav printf(" DP"); 6929197611Smav if (HDA_PARAM_PIN_CAP_HBR(pincap)) 6930197611Smav printf(" HBR"); 6931162922Sariff printf("\n"); 6932162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6933162922Sariff w->wclass.pin.config); 6934162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6935162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6936162922Sariff printf(" HP"); 6937162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6938162922Sariff printf(" IN"); 6939162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6940162922Sariff printf(" OUT"); 6941182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6942182999Smav printf(" VREFs"); 6943162922Sariff printf("\n"); 6944162922Sariff} 6945162922Sariff 6946162922Sariffstatic void 6947182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6948182999Smav{ 6949182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6950182999Smav 6951183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6952182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6953182999Smav w->nid, conf, 6954182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6955182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6956182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6957182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6958182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6959182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6960182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6961182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6962182999Smav (w->enable == 0)?" [DISABLED]":""); 6963182999Smav} 6964182999Smav 6965182999Smavstatic void 6966182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6967182999Smav{ 6968182999Smav struct hdac_widget *w; 6969182999Smav int i; 6970182999Smav 6971182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6972182999Smav w = hdac_widget_get(devinfo, i); 6973182999Smav if (w == NULL) 6974182999Smav continue; 6975182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6976182999Smav continue; 6977182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6978182999Smav } 6979182999Smav} 6980182999Smav 6981182999Smavstatic void 6982162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6983162922Sariff{ 6984163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6985162922Sariff device_printf(sc->dev, " " 6986162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6987162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6988162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6989162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6990162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6991162922Sariff} 6992162922Sariff 6993162922Sariffstatic void 6994162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6995162922Sariff{ 6996162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6997182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6998162922Sariff struct hdac_widget *w, *cw; 6999182999Smav char buf[64]; 7000162922Sariff int i, j; 7001162922Sariff 7002162922Sariff device_printf(sc->dev, "\n"); 7003162922Sariff device_printf(sc->dev, "Default Parameter\n"); 7004162922Sariff device_printf(sc->dev, "-----------------\n"); 7005182999Smav hdac_dump_audio_formats(sc->dev, 7006162922Sariff devinfo->function.audio.supp_stream_formats, 7007162922Sariff devinfo->function.audio.supp_pcm_size_rate); 7008162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 7009162922Sariff devinfo->function.audio.inamp_cap); 7010162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 7011162922Sariff devinfo->function.audio.outamp_cap); 7012162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7013162922Sariff w = hdac_widget_get(devinfo, i); 7014162922Sariff if (w == NULL) { 7015162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 7016162922Sariff continue; 7017162922Sariff } 7018162922Sariff device_printf(sc->dev, "\n"); 7019183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 7020162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 7021183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 7022183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 7023162922Sariff w->param.widget_cap); 7024183097Smav if (w->param.widget_cap & 0x0ee1) { 7025183097Smav device_printf(sc->dev, " "); 7026183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 7027183097Smav printf(" LRSWAP"); 7028183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 7029183097Smav printf(" PWR"); 7030183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 7031183097Smav printf(" DIGITAL"); 7032183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 7033183097Smav printf(" UNSOL"); 7034183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 7035183097Smav printf(" PROC"); 7036183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 7037183097Smav printf(" STRIPE"); 7038197611Smav j = HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap); 7039197611Smav if (j == 1) 7040183097Smav printf(" STEREO"); 7041197611Smav else if (j > 1) 7042197611Smav printf(" %dCH", j + 1); 7043183097Smav printf("\n"); 7044183097Smav } 7045183097Smav if (w->bindas != -1) { 7046183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 7047183097Smav w->bindas, w->bindseqmask); 7048183097Smav } 7049183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 7050183097Smav device_printf(sc->dev, " OSS: %s", 7051183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 7052183097Smav if (w->ossdev >= 0) 7053183097Smav printf(" (%s)", ossname[w->ossdev]); 7054183097Smav printf("\n"); 7055183097Smav } 7056162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 7057162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 7058182999Smav hdac_dump_audio_formats(sc->dev, 7059162922Sariff w->param.supp_stream_formats, 7060162922Sariff w->param.supp_pcm_size_rate); 7061162922Sariff } else if (w->type == 7062162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7063162922Sariff hdac_dump_pin(sc, w); 7064162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 7065162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 7066162922Sariff w->param.eapdbtl); 7067163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 7068163057Sariff w->param.outamp_cap != 0) 7069162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 7070163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 7071163057Sariff w->param.inamp_cap != 0) 7072162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 7073183097Smav if (w->nconns > 0) { 7074183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 7075182999Smav device_printf(sc->dev, " |\n"); 7076183097Smav } 7077162922Sariff for (j = 0; j < w->nconns; j++) { 7078162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 7079182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 7080182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 7081162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 7082162922Sariff if (cw == NULL) 7083162922Sariff printf(" [UNKNOWN]"); 7084162922Sariff else if (cw->enable == 0) 7085162922Sariff printf(" [DISABLED]"); 7086162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 7087162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 7088162922Sariff printf(" (selected)"); 7089162922Sariff printf("\n"); 7090162922Sariff } 7091162922Sariff } 7092162922Sariff 7093162922Sariff} 7094162922Sariff 7095182999Smavstatic void 7096182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 7097163057Sariff{ 7098182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7099163057Sariff struct hdac_widget *w, *cw; 7100182999Smav char buf[64]; 7101182999Smav int i, printed = 0; 7102163057Sariff 7103163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 7104182999Smav return; 7105163057Sariff 7106163057Sariff w = hdac_widget_get(devinfo, nid); 7107182999Smav if (w == NULL || w->enable == 0) 7108182999Smav return; 7109163057Sariff 7110182999Smav if (depth == 0) 7111182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 7112182999Smav else 7113182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 7114182999Smav printf("nid=%d [%s]", w->nid, w->name); 7115163057Sariff 7116182999Smav if (depth > 0) { 7117182999Smav if (w->ossmask == 0) { 7118182999Smav printf("\n"); 7119182999Smav return; 7120163057Sariff } 7121182999Smav printf(" [src: %s]", 7122182999Smav hdac_audio_ctl_ossmixer_mask2allname( 7123182999Smav w->ossmask, buf, sizeof(buf))); 7124182999Smav if (w->ossdev >= 0) { 7125182999Smav printf("\n"); 7126182999Smav return; 7127182999Smav } 7128163057Sariff } 7129182999Smav printf("\n"); 7130182999Smav 7131182999Smav for (i = 0; i < w->nconns; i++) { 7132182999Smav if (w->connsenable[i] == 0) 7133182999Smav continue; 7134182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 7135182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 7136182999Smav continue; 7137182999Smav if (printed == 0) { 7138182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 7139182999Smav printed = 1; 7140182999Smav } 7141182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 7142182999Smav } 7143163057Sariff 7144163057Sariff} 7145163057Sariff 7146162922Sariffstatic void 7147182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 7148162922Sariff{ 7149182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7150182999Smav struct hdac_softc *sc = devinfo->codec->sc; 7151202736Smav struct hdac_audio_as *as; 7152163057Sariff struct hdac_widget *w; 7153163057Sariff int i, printed = 0; 7154163057Sariff 7155182999Smav if (pdevinfo->play < 0) 7156182999Smav return; 7157182999Smav 7158202736Smav as = &devinfo->function.audio.as[sc->chans[pdevinfo->play].as]; 7159202736Smav for (i = 0; i < 16; i++) { 7160202736Smav if (as->pins[i] <= 0) 7161202736Smav continue; 7162202736Smav w = hdac_widget_get(devinfo, as->pins[i]); 7163163057Sariff if (w == NULL || w->enable == 0) 7164163057Sariff continue; 7165163057Sariff if (printed == 0) { 7166163057Sariff printed = 1; 7167182999Smav device_printf(pdevinfo->dev, "\n"); 7168182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7169163057Sariff } 7170182999Smav device_printf(pdevinfo->dev, "\n"); 7171202736Smav hdac_dump_dst_nid(pdevinfo, as->pins[i], 0); 7172163057Sariff } 7173162922Sariff} 7174162922Sariff 7175162922Sariffstatic void 7176182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 7177162922Sariff{ 7178182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7179162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 7180182999Smav struct hdac_widget *w; 7181182999Smav int i; 7182162922Sariff int printed = 0; 7183162922Sariff 7184182999Smav if (pdevinfo->rec < 0) 7185182999Smav return; 7186182999Smav 7187162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7188162922Sariff w = hdac_widget_get(devinfo, i); 7189162922Sariff if (w == NULL || w->enable == 0) 7190162922Sariff continue; 7191182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 7192162922Sariff continue; 7193182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 7194182999Smav continue; 7195162922Sariff if (printed == 0) { 7196162922Sariff printed = 1; 7197182999Smav device_printf(pdevinfo->dev, "\n"); 7198182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7199162922Sariff } 7200182999Smav device_printf(pdevinfo->dev, "\n"); 7201182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7202182999Smav } 7203182999Smav} 7204182999Smav 7205182999Smavstatic void 7206182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 7207182999Smav{ 7208182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7209182999Smav struct hdac_widget *w; 7210182999Smav int i; 7211182999Smav int printed = 0; 7212182999Smav 7213182999Smav if (pdevinfo->index != 0) 7214182999Smav return; 7215182999Smav 7216182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7217182999Smav w = hdac_widget_get(devinfo, i); 7218182999Smav if (w == NULL || w->enable == 0) 7219182999Smav continue; 7220202789Smav if (w->ossdev != SOUND_MIXER_IMIX) 7221182999Smav continue; 7222182999Smav if (printed == 0) { 7223182999Smav printed = 1; 7224182999Smav device_printf(pdevinfo->dev, "\n"); 7225182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 7226162922Sariff } 7227182999Smav device_printf(pdevinfo->dev, "\n"); 7228182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7229162922Sariff } 7230162922Sariff} 7231162922Sariff 7232162922Sariffstatic void 7233182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 7234162922Sariff{ 7235182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7236162922Sariff nid_t *nids; 7237182999Smav int i; 7238162922Sariff 7239182999Smav if (pdevinfo->play >= 0) { 7240182999Smav i = pdevinfo->play; 7241182999Smav device_printf(pdevinfo->dev, "\n"); 7242182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7243182999Smav device_printf(pdevinfo->dev, "\n"); 7244182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7245182999Smav sc->chans[i].supp_pcm_size_rate); 7246182999Smav device_printf(pdevinfo->dev, " DAC:"); 7247182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7248162922Sariff printf(" %d", *nids); 7249162922Sariff printf("\n"); 7250162922Sariff } 7251182999Smav if (pdevinfo->rec >= 0) { 7252182999Smav i = pdevinfo->rec; 7253182999Smav device_printf(pdevinfo->dev, "\n"); 7254182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7255182999Smav device_printf(pdevinfo->dev, "\n"); 7256182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7257182999Smav sc->chans[i].supp_pcm_size_rate); 7258182999Smav device_printf(pdevinfo->dev, " ADC:"); 7259182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7260162922Sariff printf(" %d", *nids); 7261162922Sariff printf("\n"); 7262162922Sariff } 7263162922Sariff} 7264162922Sariff 7265162922Sariffstatic void 7266163057Sariffhdac_release_resources(struct hdac_softc *sc) 7267163057Sariff{ 7268182999Smav int i, j; 7269163057Sariff 7270163057Sariff if (sc == NULL) 7271163057Sariff return; 7272163057Sariff 7273163057Sariff hdac_lock(sc); 7274169277Sariff sc->polling = 0; 7275169277Sariff sc->poll_ival = 0; 7276170721Sariff callout_stop(&sc->poll_hda); 7277169277Sariff callout_stop(&sc->poll_hdac); 7278169277Sariff callout_stop(&sc->poll_jack); 7279182999Smav hdac_reset(sc, 0); 7280163057Sariff hdac_unlock(sc); 7281171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7282170721Sariff callout_drain(&sc->poll_hda); 7283169277Sariff callout_drain(&sc->poll_hdac); 7284169277Sariff callout_drain(&sc->poll_jack); 7285163057Sariff 7286169277Sariff hdac_irq_free(sc); 7287169277Sariff 7288182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7289182999Smav if (sc->codecs[i] == NULL) 7290163057Sariff continue; 7291182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7292182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7293182999Smav if (sc->codecs[i]->fgs[j].node_type == 7294182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7295182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7296182999Smav M_HDAC); 7297182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7298182999Smav M_HDAC); 7299182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7300182999Smav M_HDAC); 7301182999Smav } 7302182999Smav } 7303182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7304182999Smav free(sc->codecs[i], M_HDAC); 7305163057Sariff sc->codecs[i] = NULL; 7306163057Sariff } 7307163057Sariff 7308169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7309169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7310169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7311182999Smav for (i = 0; i < sc->num_chans; i++) { 7312182999Smav if (sc->chans[i].blkcnt > 0) 7313182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7314182999Smav } 7315182999Smav free(sc->chans, M_HDAC); 7316167702Sariff if (sc->chan_dmat != NULL) { 7317167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7318167702Sariff sc->chan_dmat = NULL; 7319167702Sariff } 7320163057Sariff hdac_mem_free(sc); 7321169277Sariff snd_mtxfree(sc->lock); 7322163057Sariff} 7323163057Sariff 7324163057Sariff/* This function surely going to make its way into upper level someday. */ 7325163057Sariffstatic void 7326163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7327163057Sariff{ 7328163057Sariff const char *res = NULL; 7329163057Sariff int i = 0, j, k, len, inv; 7330163057Sariff 7331163057Sariff if (on != NULL) 7332163057Sariff *on = 0; 7333163057Sariff if (off != NULL) 7334163057Sariff *off = 0; 7335163057Sariff if (sc == NULL) 7336163057Sariff return; 7337163057Sariff if (resource_string_value(device_get_name(sc->dev), 7338163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7339163057Sariff return; 7340163057Sariff if (!(res != NULL && strlen(res) > 0)) 7341163057Sariff return; 7342163057Sariff HDA_BOOTVERBOSE( 7343182999Smav device_printf(sc->dev, "HDA Config:"); 7344163057Sariff ); 7345163057Sariff for (;;) { 7346163057Sariff while (res[i] != '\0' && 7347163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7348163057Sariff i++; 7349163057Sariff if (res[i] == '\0') { 7350163057Sariff HDA_BOOTVERBOSE( 7351163057Sariff printf("\n"); 7352163057Sariff ); 7353163057Sariff return; 7354163057Sariff } 7355163057Sariff j = i; 7356163057Sariff while (res[j] != '\0' && 7357163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7358163057Sariff j++; 7359163057Sariff len = j - i; 7360163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7361163057Sariff inv = 2; 7362163057Sariff else 7363163057Sariff inv = 0; 7364163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7365163057Sariff if (strncmp(res + i + inv, 7366163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7367163057Sariff continue; 7368163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7369187944Smav continue; 7370163057Sariff HDA_BOOTVERBOSE( 7371163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7372163057Sariff hdac_quirks_tab[k].key); 7373163057Sariff ); 7374163057Sariff if (inv == 0 && on != NULL) 7375163057Sariff *on |= hdac_quirks_tab[k].value; 7376163057Sariff else if (inv != 0 && off != NULL) 7377163057Sariff *off |= hdac_quirks_tab[k].value; 7378163057Sariff break; 7379163057Sariff } 7380163057Sariff i = j; 7381163057Sariff } 7382163057Sariff} 7383163057Sariff 7384164614Sariffstatic int 7385164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7386164614Sariff{ 7387164614Sariff struct hdac_softc *sc; 7388164614Sariff device_t dev; 7389164614Sariff uint32_t ctl; 7390164614Sariff int err, val; 7391164614Sariff 7392164614Sariff dev = oidp->oid_arg1; 7393182999Smav sc = device_get_softc(dev); 7394182999Smav if (sc == NULL) 7395164614Sariff return (EINVAL); 7396164614Sariff hdac_lock(sc); 7397164614Sariff val = sc->polling; 7398164614Sariff hdac_unlock(sc); 7399170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7400164614Sariff 7401169277Sariff if (err != 0 || req->newptr == NULL) 7402164614Sariff return (err); 7403164614Sariff if (val < 0 || val > 1) 7404164614Sariff return (EINVAL); 7405164614Sariff 7406164614Sariff hdac_lock(sc); 7407164614Sariff if (val != sc->polling) { 7408182999Smav if (val == 0) { 7409182999Smav callout_stop(&sc->poll_hda); 7410164614Sariff callout_stop(&sc->poll_hdac); 7411169277Sariff hdac_unlock(sc); 7412182999Smav callout_drain(&sc->poll_hda); 7413169277Sariff callout_drain(&sc->poll_hdac); 7414169277Sariff hdac_lock(sc); 7415164614Sariff sc->polling = 0; 7416182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7417182999Smav ctl |= HDAC_INTCTL_GIE; 7418182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7419164614Sariff } else { 7420182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7421182999Smav ctl &= ~HDAC_INTCTL_GIE; 7422182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7423171141Sariff hdac_unlock(sc); 7424171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7425171141Sariff hdac_lock(sc); 7426164614Sariff sc->polling = 1; 7427182999Smav hdac_poll_reinit(sc); 7428182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7429164614Sariff } 7430164614Sariff } 7431164614Sariff hdac_unlock(sc); 7432164614Sariff 7433164614Sariff return (err); 7434164614Sariff} 7435169277Sariff 7436169277Sariffstatic int 7437169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7438169277Sariff{ 7439169277Sariff struct hdac_softc *sc; 7440169277Sariff device_t dev; 7441169277Sariff int err, val; 7442169277Sariff 7443169277Sariff dev = oidp->oid_arg1; 7444182999Smav sc = device_get_softc(dev); 7445182999Smav if (sc == NULL) 7446169277Sariff return (EINVAL); 7447169277Sariff hdac_lock(sc); 7448169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7449169277Sariff hdac_unlock(sc); 7450170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7451169277Sariff 7452169277Sariff if (err != 0 || req->newptr == NULL) 7453169277Sariff return (err); 7454169277Sariff 7455169277Sariff if (val < 1) 7456169277Sariff val = 1; 7457169277Sariff if (val > 5000) 7458169277Sariff val = 5000; 7459169277Sariff val = ((uint64_t)val * hz) / 1000; 7460169277Sariff if (val < 1) 7461169277Sariff val = 1; 7462169277Sariff if (val > (hz * 5)) 7463169277Sariff val = hz * 5; 7464169277Sariff 7465169277Sariff hdac_lock(sc); 7466169277Sariff sc->poll_ival = val; 7467169277Sariff hdac_unlock(sc); 7468169277Sariff 7469169277Sariff return (err); 7470169277Sariff} 7471169277Sariff 7472169277Sariffstatic int 7473171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7474169277Sariff{ 7475169277Sariff struct hdac_softc *sc; 7476182999Smav struct hdac_codec *codec; 7477169277Sariff struct hdac_devinfo *devinfo; 7478169277Sariff struct hdac_widget *w; 7479169277Sariff device_t dev; 7480182999Smav uint32_t res, pincap, delay; 7481182999Smav int codec_index, fg_index; 7482169277Sariff int i, err, val; 7483169277Sariff nid_t cad; 7484169277Sariff 7485169277Sariff dev = oidp->oid_arg1; 7486182999Smav sc = device_get_softc(dev); 7487182999Smav if (sc == NULL) 7488169277Sariff return (EINVAL); 7489169277Sariff val = 0; 7490170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7491169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7492169277Sariff return (err); 7493182999Smav 7494182999Smav /* XXX: Temporary. For debugging. */ 7495182999Smav if (val == 100) { 7496182999Smav hdac_suspend(dev); 7497182999Smav return (0); 7498182999Smav } else if (val == 101) { 7499182999Smav hdac_resume(dev); 7500182999Smav return (0); 7501182999Smav } 7502182999Smav 7503169277Sariff hdac_lock(sc); 7504182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7505182999Smav codec = sc->codecs[codec_index]; 7506182999Smav if (codec == NULL) 7507169277Sariff continue; 7508182999Smav cad = codec->cad; 7509182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7510182999Smav devinfo = &codec->fgs[fg_index]; 7511182999Smav if (devinfo->node_type != 7512182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7513182999Smav continue; 7514182999Smav 7515182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7516182999Smav codec_index, devinfo->nid); 7517182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7518182999Smav w = hdac_widget_get(devinfo, i); 7519182999Smav if (w == NULL || w->type != 7520182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7521182999Smav continue; 7522182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7523182999Smav pincap = w->wclass.pin.cap; 7524182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7525182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7526182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7527182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7528182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7529182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7530182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7531182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7532182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7533182999Smav delay = 0; 7534182999Smav hdac_command(sc, 7535182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7536182999Smav do { 7537182999Smav res = hdac_command(sc, 7538182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7539182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7540182999Smav break; 7541182999Smav DELAY(10); 7542182999Smav } while (++delay < 10000); 7543182999Smav } else { 7544182999Smav delay = 0; 7545182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7546182999Smav w->nid), cad); 7547182999Smav } 7548182999Smav printf(" Sense: 0x%08x", res); 7549182999Smav if (delay > 0) 7550182999Smav printf(" delay %dus", delay * 10); 7551182999Smav } 7552182999Smav printf("\n"); 7553182999Smav } 7554182999Smav device_printf(dev, 7555182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7556182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7557182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7558182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7559182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7560182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7561182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7562182999Smav device_printf(dev, " GPI:"); 7563171141Sariff res = hdac_command(sc, 7564182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7565182999Smav printf(" data=0x%08x", res); 7566182999Smav res = hdac_command(sc, 7567182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7568182999Smav cad); 7569182999Smav printf(" wake=0x%08x", res); 7570182999Smav res = hdac_command(sc, 7571182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7572182999Smav cad); 7573182999Smav printf(" unsol=0x%08x", res); 7574182999Smav res = hdac_command(sc, 7575182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7576182999Smav printf(" sticky=0x%08x\n", res); 7577182999Smav } 7578182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7579182999Smav device_printf(dev, " GPO:"); 7580182999Smav res = hdac_command(sc, 7581182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7582182999Smav printf(" data=0x%08x\n", res); 7583182999Smav } 7584182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7585182999Smav device_printf(dev, "GPIO:"); 7586182999Smav res = hdac_command(sc, 7587182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7588182999Smav printf(" data=0x%08x", res); 7589182999Smav res = hdac_command(sc, 7590182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7591182999Smav printf(" enable=0x%08x", res); 7592182999Smav res = hdac_command(sc, 7593182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7594182999Smav printf(" direction=0x%08x\n", res); 7595182999Smav res = hdac_command(sc, 7596182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7597182999Smav device_printf(dev, " wake=0x%08x", res); 7598182999Smav res = hdac_command(sc, 7599182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7600182999Smav cad); 7601182999Smav printf(" unsol=0x%08x", res); 7602182999Smav res = hdac_command(sc, 7603182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7604182999Smav printf(" sticky=0x%08x\n", res); 7605182999Smav } 7606171141Sariff } 7607169277Sariff } 7608169277Sariff hdac_unlock(sc); 7609169277Sariff return (0); 7610169277Sariff} 7611164614Sariff 7612163057Sariffstatic void 7613162922Sariffhdac_attach2(void *arg) 7614162922Sariff{ 7615182999Smav struct hdac_codec *codec; 7616162922Sariff struct hdac_softc *sc; 7617162922Sariff struct hdac_audio_ctl *ctl; 7618163057Sariff uint32_t quirks_on, quirks_off; 7619182999Smav int codec_index, fg_index; 7620185225Smav int i, dmaalloc = 0; 7621182999Smav struct hdac_devinfo *devinfo; 7622162922Sariff 7623162922Sariff sc = (struct hdac_softc *)arg; 7624162922Sariff 7625163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7626162922Sariff 7627183097Smav HDA_BOOTHVERBOSE( 7628182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7629163057Sariff quirks_on, quirks_off); 7630163057Sariff ); 7631163057Sariff 7632162922Sariff hdac_lock(sc); 7633162922Sariff 7634162922Sariff /* Remove ourselves from the config hooks */ 7635162922Sariff if (sc->intrhook.ich_func != NULL) { 7636162922Sariff config_intrhook_disestablish(&sc->intrhook); 7637162922Sariff sc->intrhook.ich_func = NULL; 7638162922Sariff } 7639162922Sariff 7640162922Sariff /* Start the corb and rirb engines */ 7641183097Smav HDA_BOOTHVERBOSE( 7642182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7643162922Sariff ); 7644162922Sariff hdac_corb_start(sc); 7645183097Smav HDA_BOOTHVERBOSE( 7646182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7647162922Sariff ); 7648162922Sariff hdac_rirb_start(sc); 7649162922Sariff 7650183097Smav HDA_BOOTHVERBOSE( 7651162922Sariff device_printf(sc->dev, 7652182999Smav "Enabling controller interrupt...\n"); 7653162922Sariff ); 7654182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7655182999Smav HDAC_GCTL_UNSOL); 7656182999Smav if (sc->polling == 0) { 7657164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7658164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7659182999Smav } else { 7660182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7661182999Smav } 7662162922Sariff DELAY(1000); 7663162922Sariff 7664183097Smav HDA_BOOTHVERBOSE( 7665172811Sariff device_printf(sc->dev, 7666182999Smav "Scanning HDA codecs ...\n"); 7667162922Sariff ); 7668182999Smav hdac_scan_codecs(sc); 7669182999Smav 7670182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7671182999Smav codec = sc->codecs[codec_index]; 7672182999Smav if (codec == NULL) 7673182999Smav continue; 7674182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7675182999Smav devinfo = &codec->fgs[fg_index]; 7676183019Smav HDA_BOOTVERBOSE( 7677183019Smav device_printf(sc->dev, "\n"); 7678183097Smav device_printf(sc->dev, 7679183097Smav "Processing %s FG cad=%d nid=%d...\n", 7680183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7681183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7682183097Smav "unknown", 7683183097Smav devinfo->codec->cad, devinfo->nid); 7684183019Smav ); 7685182999Smav if (devinfo->node_type != 7686182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7687183097Smav HDA_BOOTHVERBOSE( 7688182999Smav device_printf(sc->dev, 7689183097Smav "Powering down...\n"); 7690182999Smav ); 7691182999Smav hdac_command(sc, 7692182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7693182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7694182999Smav codec->cad); 7695182999Smav continue; 7696182999Smav } 7697162922Sariff 7698183097Smav HDA_BOOTHVERBOSE( 7699183097Smav device_printf(sc->dev, "Powering up...\n"); 7700182999Smav ); 7701182999Smav hdac_powerup(devinfo); 7702183097Smav HDA_BOOTHVERBOSE( 7703182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7704182999Smav ); 7705182999Smav hdac_audio_parse(devinfo); 7706183097Smav HDA_BOOTHVERBOSE( 7707182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7708182999Smav ); 7709182999Smav hdac_audio_ctl_parse(devinfo); 7710183097Smav HDA_BOOTHVERBOSE( 7711182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7712182999Smav ); 7713182999Smav hdac_vendor_patch_parse(devinfo); 7714182999Smav devinfo->function.audio.quirks |= quirks_on; 7715182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7716162922Sariff 7717183097Smav HDA_BOOTHVERBOSE( 7718182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7719182999Smav ); 7720182999Smav hdac_audio_disable_nonaudio(devinfo); 7721183097Smav HDA_BOOTHVERBOSE( 7722182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7723182999Smav ); 7724182999Smav hdac_audio_disable_useless(devinfo); 7725182999Smav HDA_BOOTVERBOSE( 7726182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7727182999Smav hdac_dump_pin_configs(devinfo); 7728183097Smav ); 7729183097Smav HDA_BOOTHVERBOSE( 7730182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7731182999Smav ); 7732182999Smav hdac_audio_as_parse(devinfo); 7733183097Smav HDA_BOOTHVERBOSE( 7734182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7735182999Smav ); 7736182999Smav hdac_audio_build_tree(devinfo); 7737183097Smav HDA_BOOTHVERBOSE( 7738182999Smav device_printf(sc->dev, "Disabling unassociated " 7739182999Smav "widgets...\n"); 7740182999Smav ); 7741182999Smav hdac_audio_disable_unas(devinfo); 7742183097Smav HDA_BOOTHVERBOSE( 7743182999Smav device_printf(sc->dev, "Disabling nonselected " 7744182999Smav "inputs...\n"); 7745182999Smav ); 7746182999Smav hdac_audio_disable_notselected(devinfo); 7747183097Smav HDA_BOOTHVERBOSE( 7748182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7749182999Smav ); 7750182999Smav hdac_audio_disable_useless(devinfo); 7751183097Smav HDA_BOOTHVERBOSE( 7752182999Smav device_printf(sc->dev, "Disabling " 7753182999Smav "crossassociatement connections...\n"); 7754182999Smav ); 7755182999Smav hdac_audio_disable_crossas(devinfo); 7756183097Smav HDA_BOOTHVERBOSE( 7757182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7758182999Smav ); 7759182999Smav hdac_audio_disable_useless(devinfo); 7760183097Smav HDA_BOOTHVERBOSE( 7761182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7762182999Smav ); 7763182999Smav hdac_audio_bind_as(devinfo); 7764183097Smav HDA_BOOTHVERBOSE( 7765182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7766182999Smav ); 7767182999Smav hdac_audio_assign_names(devinfo); 7768183097Smav HDA_BOOTHVERBOSE( 7769182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7770182999Smav ); 7771182999Smav hdac_audio_assign_mixers(devinfo); 7772183097Smav HDA_BOOTHVERBOSE( 7773182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7774182999Smav ); 7775182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7776183097Smav HDA_BOOTHVERBOSE( 7777182999Smav device_printf(sc->dev, "AFG commit...\n"); 7778182999Smav ); 7779182999Smav hdac_audio_commit(devinfo); 7780183097Smav HDA_BOOTHVERBOSE( 7781182999Smav device_printf(sc->dev, "HP switch init...\n"); 7782182999Smav ); 7783182999Smav hdac_hp_switch_init(devinfo); 7784182999Smav 7785182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7786182999Smav dmaalloc == 0) { 7787182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7788182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7789182999Smav HDA_BOOTVERBOSE( 7790182999Smav device_printf(sc->dev, "Failed to " 7791182999Smav "allocate DMA pos buffer " 7792182999Smav "(non-fatal)\n"); 7793182999Smav ); 7794182999Smav } else 7795182999Smav dmaalloc = 1; 7796182999Smav } 7797182999Smav 7798185225Smav HDA_BOOTHVERBOSE( 7799185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7800185225Smav ); 7801185225Smav hdac_create_pcms(devinfo); 7802182999Smav 7803182999Smav HDA_BOOTVERBOSE( 7804182999Smav if (devinfo->function.audio.quirks != 0) { 7805183097Smav device_printf(sc->dev, "FG config/quirks:"); 7806182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7807182999Smav if ((devinfo->function.audio.quirks & 7808182999Smav hdac_quirks_tab[i].value) == 7809182999Smav hdac_quirks_tab[i].value) 7810182999Smav printf(" %s", hdac_quirks_tab[i].key); 7811182999Smav } 7812182999Smav printf("\n"); 7813182999Smav } 7814182999Smav 7815182999Smav device_printf(sc->dev, "\n"); 7816182999Smav device_printf(sc->dev, "+-------------------+\n"); 7817182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7818182999Smav device_printf(sc->dev, "+-------------------+\n"); 7819182999Smav hdac_dump_nodes(devinfo); 7820183097Smav ); 7821182999Smav 7822183097Smav HDA_BOOTHVERBOSE( 7823182999Smav device_printf(sc->dev, "\n"); 7824182999Smav device_printf(sc->dev, "+------------------------+\n"); 7825182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7826182999Smav device_printf(sc->dev, "+------------------------+\n"); 7827182999Smav device_printf(sc->dev, "\n"); 7828182999Smav i = 0; 7829182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7830182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7831182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7832182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7833182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7834182999Smav ctl->index); 7835182999Smav if (ctl->childwidget != NULL) 7836182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7837182999Smav else 7838182999Smav printf(" "); 7839182999Smav printf(" ossmask=0x%08x\n", 7840182999Smav ctl->ossmask); 7841182999Smav device_printf(sc->dev, 7842182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7843182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7844182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7845182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7846182999Smav } 7847182999Smav ); 7848182999Smav } 7849162922Sariff } 7850182999Smav hdac_unlock(sc); 7851162922Sariff 7852163057Sariff HDA_BOOTVERBOSE( 7853182999Smav device_printf(sc->dev, "\n"); 7854162922Sariff ); 7855182999Smav 7856182999Smav bus_generic_attach(sc->dev); 7857182999Smav 7858182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7859182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7860182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7861182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7862182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7863182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7864182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7865182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7866182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7867182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7868182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7869182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7870182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7871182999Smav} 7872182999Smav 7873182999Smav/**************************************************************************** 7874182999Smav * int hdac_suspend(device_t) 7875182999Smav * 7876182999Smav * Suspend and power down HDA bus and codecs. 7877182999Smav ****************************************************************************/ 7878182999Smavstatic int 7879182999Smavhdac_suspend(device_t dev) 7880182999Smav{ 7881182999Smav struct hdac_softc *sc; 7882182999Smav struct hdac_codec *codec; 7883182999Smav struct hdac_devinfo *devinfo; 7884182999Smav int codec_index, fg_index, i; 7885182999Smav 7886183097Smav HDA_BOOTHVERBOSE( 7887182999Smav device_printf(dev, "Suspend...\n"); 7888162922Sariff ); 7889182999Smav 7890182999Smav sc = device_get_softc(dev); 7891182999Smav hdac_lock(sc); 7892182999Smav 7893183097Smav HDA_BOOTHVERBOSE( 7894182999Smav device_printf(dev, "Stop streams...\n"); 7895162922Sariff ); 7896182999Smav for (i = 0; i < sc->num_chans; i++) { 7897182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7898182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7899182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7900182999Smav } 7901182999Smav } 7902162922Sariff 7903182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7904182999Smav codec = sc->codecs[codec_index]; 7905182999Smav if (codec == NULL) 7906162922Sariff continue; 7907182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7908182999Smav devinfo = &codec->fgs[fg_index]; 7909183097Smav HDA_BOOTHVERBOSE( 7910182999Smav device_printf(dev, 7911182999Smav "Power down FG" 7912182999Smav " cad=%d nid=%d to the D3 state...\n", 7913182999Smav codec->cad, devinfo->nid); 7914182999Smav ); 7915182999Smav hdac_command(sc, 7916182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7917182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7918182999Smav codec->cad); 7919162922Sariff } 7920162922Sariff } 7921162922Sariff 7922183097Smav HDA_BOOTHVERBOSE( 7923182999Smav device_printf(dev, "Reset controller...\n"); 7924162922Sariff ); 7925182999Smav callout_stop(&sc->poll_hda); 7926182999Smav callout_stop(&sc->poll_hdac); 7927182999Smav callout_stop(&sc->poll_jack); 7928182999Smav hdac_reset(sc, 0); 7929182999Smav hdac_unlock(sc); 7930182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7931182999Smav callout_drain(&sc->poll_hda); 7932182999Smav callout_drain(&sc->poll_hdac); 7933182999Smav callout_drain(&sc->poll_jack); 7934162922Sariff 7935183097Smav HDA_BOOTHVERBOSE( 7936182999Smav device_printf(dev, "Suspend done\n"); 7937162922Sariff ); 7938182999Smav 7939182999Smav return (0); 7940182999Smav} 7941182999Smav 7942182999Smav/**************************************************************************** 7943182999Smav * int hdac_resume(device_t) 7944182999Smav * 7945182999Smav * Powerup and restore HDA bus and codecs state. 7946182999Smav ****************************************************************************/ 7947182999Smavstatic int 7948182999Smavhdac_resume(device_t dev) 7949182999Smav{ 7950182999Smav struct hdac_softc *sc; 7951182999Smav struct hdac_codec *codec; 7952182999Smav struct hdac_devinfo *devinfo; 7953182999Smav int codec_index, fg_index, i; 7954182999Smav 7955183097Smav HDA_BOOTHVERBOSE( 7956182999Smav device_printf(dev, "Resume...\n"); 7957162922Sariff ); 7958162922Sariff 7959182999Smav sc = device_get_softc(dev); 7960182999Smav hdac_lock(sc); 7961182999Smav 7962182999Smav /* Quiesce everything */ 7963183097Smav HDA_BOOTHVERBOSE( 7964182999Smav device_printf(dev, "Reset controller...\n"); 7965162922Sariff ); 7966182999Smav hdac_reset(sc, 1); 7967182999Smav 7968182999Smav /* Initialize the CORB and RIRB */ 7969182999Smav hdac_corb_init(sc); 7970182999Smav hdac_rirb_init(sc); 7971182999Smav 7972182999Smav /* Start the corb and rirb engines */ 7973183097Smav HDA_BOOTHVERBOSE( 7974182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7975162922Sariff ); 7976182999Smav hdac_corb_start(sc); 7977183097Smav HDA_BOOTHVERBOSE( 7978182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7979162922Sariff ); 7980182999Smav hdac_rirb_start(sc); 7981163057Sariff 7982183097Smav HDA_BOOTHVERBOSE( 7983182999Smav device_printf(dev, 7984182999Smav "Enabling controller interrupt...\n"); 7985162922Sariff ); 7986182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7987182999Smav HDAC_GCTL_UNSOL); 7988182999Smav if (sc->polling == 0) { 7989182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7990182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7991182999Smav } else { 7992182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7993182999Smav } 7994182999Smav DELAY(1000); 7995162922Sariff 7996182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7997182999Smav codec = sc->codecs[codec_index]; 7998182999Smav if (codec == NULL) 7999182999Smav continue; 8000182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 8001182999Smav devinfo = &codec->fgs[fg_index]; 8002182999Smav if (devinfo->node_type != 8003182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 8004183097Smav HDA_BOOTHVERBOSE( 8005182999Smav device_printf(dev, 8006182999Smav "Power down unsupported non-audio FG" 8007182999Smav " cad=%d nid=%d to the D3 state...\n", 8008182999Smav codec->cad, devinfo->nid); 8009182999Smav ); 8010182999Smav hdac_command(sc, 8011182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 8012182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 8013182999Smav codec->cad); 8014182999Smav continue; 8015182999Smav } 8016162922Sariff 8017183097Smav HDA_BOOTHVERBOSE( 8018182999Smav device_printf(dev, 8019182999Smav "Power up audio FG cad=%d nid=%d...\n", 8020182999Smav devinfo->codec->cad, devinfo->nid); 8021182999Smav ); 8022182999Smav hdac_powerup(devinfo); 8023183097Smav HDA_BOOTHVERBOSE( 8024182999Smav device_printf(dev, "AFG commit...\n"); 8025182999Smav ); 8026182999Smav hdac_audio_commit(devinfo); 8027183097Smav HDA_BOOTHVERBOSE( 8028182999Smav device_printf(dev, "HP switch init...\n"); 8029182999Smav ); 8030182999Smav hdac_hp_switch_init(devinfo); 8031182999Smav 8032182999Smav hdac_unlock(sc); 8033182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 8034182999Smav struct hdac_pcm_devinfo *pdevinfo = 8035182999Smav &devinfo->function.audio.devs[i]; 8036183097Smav HDA_BOOTHVERBOSE( 8037182999Smav device_printf(pdevinfo->dev, 8038182999Smav "OSS mixer reinitialization...\n"); 8039182999Smav ); 8040182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 8041182999Smav device_printf(pdevinfo->dev, 8042182999Smav "unable to reinitialize the mixer\n"); 8043182999Smav } 8044182999Smav hdac_lock(sc); 8045182999Smav } 8046169277Sariff } 8047169277Sariff 8048183097Smav HDA_BOOTHVERBOSE( 8049182999Smav device_printf(dev, "Start streams...\n"); 8050163057Sariff ); 8051182999Smav for (i = 0; i < sc->num_chans; i++) { 8052182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 8053182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 8054182999Smav hdac_channel_start(sc, &sc->chans[i]); 8055182999Smav } 8056182999Smav } 8057162922Sariff 8058182999Smav hdac_unlock(sc); 8059182999Smav 8060183097Smav HDA_BOOTHVERBOSE( 8061182999Smav device_printf(dev, "Resume done\n"); 8062162922Sariff ); 8063164614Sariff 8064182999Smav return (0); 8065162922Sariff} 8066162922Sariff/**************************************************************************** 8067162922Sariff * int hdac_detach(device_t) 8068162922Sariff * 8069162922Sariff * Detach and free up resources utilized by the hdac device. 8070162922Sariff ****************************************************************************/ 8071162922Sariffstatic int 8072162922Sariffhdac_detach(device_t dev) 8073162922Sariff{ 8074182999Smav struct hdac_softc *sc; 8075185177Smav device_t *devlist; 8076185177Smav int i, devcount, error; 8077162922Sariff 8078185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 8079185177Smav return (error); 8080185177Smav for (i = 0; i < devcount; i++) { 8081185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 8082185178Smav free(devlist, M_TEMP); 8083185178Smav return (error); 8084185178Smav } 8085185177Smav } 8086185177Smav free(devlist, M_TEMP); 8087185177Smav 8088182999Smav sc = device_get_softc(dev); 8089163057Sariff hdac_release_resources(sc); 8090162922Sariff 8091162922Sariff return (0); 8092162922Sariff} 8093162922Sariff 8094184095Smavstatic int 8095184095Smavhdac_print_child(device_t dev, device_t child) 8096184095Smav{ 8097184095Smav struct hdac_pcm_devinfo *pdevinfo = 8098184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 8099184095Smav int retval; 8100184095Smav 8101184095Smav retval = bus_print_child_header(dev, child); 8102184095Smav retval += printf(" at cad %d nid %d", 8103184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 8104184095Smav retval += bus_print_child_footer(dev, child); 8105184095Smav 8106184095Smav return (retval); 8107184095Smav} 8108184095Smav 8109162922Sariffstatic device_method_t hdac_methods[] = { 8110162922Sariff /* device interface */ 8111162922Sariff DEVMETHOD(device_probe, hdac_probe), 8112162922Sariff DEVMETHOD(device_attach, hdac_attach), 8113162922Sariff DEVMETHOD(device_detach, hdac_detach), 8114182999Smav DEVMETHOD(device_suspend, hdac_suspend), 8115182999Smav DEVMETHOD(device_resume, hdac_resume), 8116184095Smav /* Bus interface */ 8117184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 8118162922Sariff { 0, 0 } 8119162922Sariff}; 8120162922Sariff 8121162922Sariffstatic driver_t hdac_driver = { 8122182999Smav "hdac", 8123162922Sariff hdac_methods, 8124182999Smav sizeof(struct hdac_softc), 8125162922Sariff}; 8126162922Sariff 8127182999Smavstatic devclass_t hdac_devclass; 8128182999Smav 8129182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 8130162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 8131162922SariffMODULE_VERSION(snd_hda, 1); 8132182999Smav 8133182999Smavstatic int 8134182999Smavhdac_pcm_probe(device_t dev) 8135182999Smav{ 8136182999Smav struct hdac_pcm_devinfo *pdevinfo = 8137182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8138182999Smav char buf[128]; 8139182999Smav 8140185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 8141182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 8142185225Smav pdevinfo->index, 8143197611Smav (pdevinfo->digital == 3)?"DisplayPort": 8144197611Smav ((pdevinfo->digital == 2)?"HDMI": 8145197611Smav ((pdevinfo->digital)?"Digital":"Analog"))); 8146182999Smav device_set_desc_copy(dev, buf); 8147182999Smav return (0); 8148182999Smav} 8149182999Smav 8150182999Smavstatic int 8151182999Smavhdac_pcm_attach(device_t dev) 8152182999Smav{ 8153182999Smav struct hdac_pcm_devinfo *pdevinfo = 8154182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8155182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 8156182999Smav char status[SND_STATUSLEN]; 8157182999Smav int i; 8158182999Smav 8159182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 8160182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 8161182999Smav 8162182999Smav HDA_BOOTVERBOSE( 8163182999Smav device_printf(dev, "+--------------------------------------+\n"); 8164182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 8165182999Smav device_printf(dev, "+--------------------------------------+\n"); 8166182999Smav hdac_dump_pcmchannels(pdevinfo); 8167182999Smav device_printf(dev, "\n"); 8168189876Smav device_printf(dev, "+-------------------------------+\n"); 8169189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 8170189876Smav device_printf(dev, "+-------------------------------+\n"); 8171182999Smav hdac_dump_dac(pdevinfo); 8172182999Smav hdac_dump_adc(pdevinfo); 8173182999Smav hdac_dump_mix(pdevinfo); 8174182999Smav device_printf(dev, "\n"); 8175182999Smav device_printf(dev, "+-------------------------+\n"); 8176182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 8177182999Smav device_printf(dev, "+-------------------------+\n"); 8178182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 8179182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 8180182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 8181182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 8182182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 8183182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 8184182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 8185182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 8186202796Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 8187202796Smav hdac_dump_ctls(pdevinfo, "Input Monitoring Level", SOUND_MASK_IGAIN); 8188182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 8189182999Smav device_printf(dev, "\n"); 8190182999Smav ); 8191182999Smav 8192182999Smav if (resource_int_value(device_get_name(dev), 8193182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 8194182999Smav i &= HDA_BLK_ALIGN; 8195182999Smav if (i < HDA_BLK_MIN) 8196182999Smav i = HDA_BLK_MIN; 8197182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 8198182999Smav i = 0; 8199182999Smav while (pdevinfo->chan_blkcnt >> i) 8200182999Smav i++; 8201182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 8202182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 8203182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 8204182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 8205182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 8206182999Smav } else 8207182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 8208182999Smav 8209182999Smav /* 8210182999Smav * We don't register interrupt handler with snd_setup_intr 8211182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 8212182999Smav */ 8213182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 8214182999Smav 8215183097Smav HDA_BOOTHVERBOSE( 8216182999Smav device_printf(dev, "OSS mixer initialization...\n"); 8217182999Smav ); 8218182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 8219182999Smav device_printf(dev, "Can't register mixer\n"); 8220182999Smav 8221183097Smav HDA_BOOTHVERBOSE( 8222182999Smav device_printf(dev, "Registering PCM channels...\n"); 8223182999Smav ); 8224182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 8225182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 8226182999Smav device_printf(dev, "Can't register PCM\n"); 8227182999Smav 8228182999Smav pdevinfo->registered++; 8229182999Smav 8230182999Smav if (pdevinfo->play >= 0) 8231182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 8232182999Smav if (pdevinfo->rec >= 0) 8233182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 8234182999Smav 8235184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 8236184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 8237184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 8238182999Smav pcm_setstatus(dev, status); 8239182999Smav 8240182999Smav return (0); 8241182999Smav} 8242182999Smav 8243182999Smavstatic int 8244182999Smavhdac_pcm_detach(device_t dev) 8245182999Smav{ 8246182999Smav struct hdac_pcm_devinfo *pdevinfo = 8247182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8248182999Smav int err; 8249182999Smav 8250182999Smav if (pdevinfo->registered > 0) { 8251182999Smav err = pcm_unregister(dev); 8252182999Smav if (err != 0) 8253182999Smav return (err); 8254182999Smav } 8255182999Smav 8256182999Smav return (0); 8257182999Smav} 8258182999Smav 8259182999Smavstatic device_method_t hdac_pcm_methods[] = { 8260182999Smav /* device interface */ 8261182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8262182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8263182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8264182999Smav { 0, 0 } 8265182999Smav}; 8266182999Smav 8267182999Smavstatic driver_t hdac_pcm_driver = { 8268182999Smav "pcm", 8269182999Smav hdac_pcm_methods, 8270182999Smav PCM_SOFTC_SIZE, 8271182999Smav}; 8272182999Smav 8273182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8274182999Smav 8275