hdac.c revision 222298
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 222298 2011-05-26 06:43:10Z 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 143211910Sjfv#define HDA_INTEL_CPT HDA_MODEL_CONSTRUCT(INTEL, 0x1c20) 144218149Sjfv#define HDA_INTEL_PATSBURG HDA_MODEL_CONSTRUCT(INTEL, 0x1d20) 145221789Sjfv#define HDA_INTEL_PPT1 HDA_MODEL_CONSTRUCT(INTEL, 0x1e20) 146162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 147171330Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 148162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 149163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 150171330Sariff#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e) 151197017Smav#define HDA_INTEL_82801JI HDA_MODEL_CONSTRUCT(INTEL, 0x3a3e) 152197017Smav#define HDA_INTEL_82801JD HDA_MODEL_CONSTRUCT(INTEL, 0x3a6e) 153187020Smav#define HDA_INTEL_PCH HDA_MODEL_CONSTRUCT(INTEL, 0x3b56) 154218149Sjfv#define HDA_INTEL_PCH2 HDA_MODEL_CONSTRUCT(INTEL, 0x3b57) 155184207Smav#define HDA_INTEL_SCH HDA_MODEL_CONSTRUCT(INTEL, 0x811b) 156162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 157162922Sariff 158162922Sariff/* Nvidia */ 159162922Sariff#define NVIDIA_VENDORID 0x10de 160162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 161162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 162173817Sariff#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 163173817Sariff#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 164173817Sariff#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 165173817Sariff#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 166173817Sariff#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c) 167173817Sariff#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d) 168186511Smav#define HDA_NVIDIA_MCP78_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0774) 169186511Smav#define HDA_NVIDIA_MCP78_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0775) 170186511Smav#define HDA_NVIDIA_MCP78_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0776) 171186511Smav#define HDA_NVIDIA_MCP78_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0777) 172186511Smav#define HDA_NVIDIA_MCP73_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fc) 173186511Smav#define HDA_NVIDIA_MCP73_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fd) 174186511Smav#define HDA_NVIDIA_MCP79_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac0) 175186511Smav#define HDA_NVIDIA_MCP79_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac1) 176186511Smav#define HDA_NVIDIA_MCP79_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac2) 177186511Smav#define HDA_NVIDIA_MCP79_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac3) 178197018Smav#define HDA_NVIDIA_MCP89_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d94) 179197018Smav#define HDA_NVIDIA_MCP89_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d95) 180197018Smav#define HDA_NVIDIA_MCP89_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d96) 181197018Smav#define HDA_NVIDIA_MCP89_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d97) 182162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 183162922Sariff 184162922Sariff/* ATI */ 185162922Sariff#define ATI_VENDORID 0x1002 186162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 187163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 188187020Smav#define HDA_ATI_RS600 HDA_MODEL_CONSTRUCT(ATI, 0x793b) 189187020Smav#define HDA_ATI_RS690 HDA_MODEL_CONSTRUCT(ATI, 0x7919) 190187020Smav#define HDA_ATI_RS780 HDA_MODEL_CONSTRUCT(ATI, 0x960f) 191187020Smav#define HDA_ATI_R600 HDA_MODEL_CONSTRUCT(ATI, 0xaa00) 192187020Smav#define HDA_ATI_RV630 HDA_MODEL_CONSTRUCT(ATI, 0xaa08) 193187020Smav#define HDA_ATI_RV610 HDA_MODEL_CONSTRUCT(ATI, 0xaa10) 194187020Smav#define HDA_ATI_RV670 HDA_MODEL_CONSTRUCT(ATI, 0xaa18) 195187020Smav#define HDA_ATI_RV635 HDA_MODEL_CONSTRUCT(ATI, 0xaa20) 196187020Smav#define HDA_ATI_RV620 HDA_MODEL_CONSTRUCT(ATI, 0xaa28) 197187020Smav#define HDA_ATI_RV770 HDA_MODEL_CONSTRUCT(ATI, 0xaa30) 198187020Smav#define HDA_ATI_RV730 HDA_MODEL_CONSTRUCT(ATI, 0xaa38) 199187020Smav#define HDA_ATI_RV710 HDA_MODEL_CONSTRUCT(ATI, 0xaa40) 200187020Smav#define HDA_ATI_RV740 HDA_MODEL_CONSTRUCT(ATI, 0xaa48) 201162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 202162922Sariff 203216766Syongari/* RDC */ 204216766Syongari#define RDC_VENDORID 0x17f3 205216766Syongari#define HDA_RDC_M3010 HDA_MODEL_CONSTRUCT(RDC, 0x3010) 206216766Syongari 207163136Sariff/* VIA */ 208163136Sariff#define VIA_VENDORID 0x1106 209163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 210163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 211163136Sariff 212163136Sariff/* SiS */ 213163136Sariff#define SIS_VENDORID 0x1039 214163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 215163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 216163136Sariff 217186301Smav/* ULI */ 218186301Smav#define ULI_VENDORID 0x10b9 219186301Smav#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461) 220186301Smav#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff) 221186301Smav 222162922Sariff/* OEM/subvendors */ 223162922Sariff 224165466Sariff/* Intel */ 225165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 226165466Sariff 227162922Sariff/* HP/Compaq */ 228162922Sariff#define HP_VENDORID 0x103c 229162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 230162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 231162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 232165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 233166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 234169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 235169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 236174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 237172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 238162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 239165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 240165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 241162922Sariff 242162922Sariff/* Dell */ 243162922Sariff#define DELL_VENDORID 0x1028 244180532Sdelphij#define DELL_D630_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01f9) 245162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 246184483Smav#define DELL_V1400_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0227) 247178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 248162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 249169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 250169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 251162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 252162922Sariff 253162922Sariff/* Clevo */ 254162922Sariff#define CLEVO_VENDORID 0x1558 255162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 256162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 257162922Sariff 258162922Sariff/* Acer */ 259162922Sariff#define ACER_VENDORID 0x1025 260165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 261173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 262174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 263182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 264169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 265182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 266189879Smav#define ACER_T5320_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011f) 267162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 268162922Sariff 269162965Sariff/* Asus */ 270162965Sariff#define ASUS_VENDORID 0x1043 271178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 272163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 273178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 274165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 275178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 276178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 277167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 278169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 279178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 280190630Smav#define ASUS_P5PL2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x817f) 281178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 282178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 283170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 284178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 285169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 286171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 287162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 288162922Sariff 289163257Sariff/* IBM / Lenovo */ 290163257Sariff#define IBM_VENDORID 0x1014 291163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 292163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 293162965Sariff 294164614Sariff/* Lenovo */ 295164657Sariff#define LENOVO_VENDORID 0x17aa 296164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 297182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 298172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 299164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 300163257Sariff 301164657Sariff/* Samsung */ 302164657Sariff#define SAMSUNG_VENDORID 0x144d 303164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 304164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 305164614Sariff 306164750Sariff/* Medion ? */ 307164750Sariff#define MEDION_VENDORID 0x161f 308164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 309164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 310164750Sariff 311173817Sariff/* Apple Computer Inc. */ 312173817Sariff#define APPLE_VENDORID 0x106b 313173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 314173817Sariff 315182999Smav/* Sony */ 316182999Smav#define SONY_VENDORID 0x104d 317182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 318182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 319182999Smav 320164828Sariff/* 321164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 322164828Sariff * instead of their own, which is beyond my comprehension 323164828Sariff * (see HDA_CODEC_STAC9221 below). 324164828Sariff */ 325164828Sariff#define APPLE_INTEL_MAC 0x76808384 326199846Smav#define APPLE_MACBOOKPRO55 0xcb7910de 327164828Sariff 328165281Sariff/* LG Electronics */ 329165281Sariff#define LG_VENDORID 0x1854 330165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 331165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 332165281Sariff 333165351Sariff/* Fujitsu Siemens */ 334165351Sariff#define FS_VENDORID 0x1734 335165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 336172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 337165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 338165351Sariff 339172811Sariff/* Fujitsu Limited */ 340172811Sariff#define FL_VENDORID 0x10cf 341172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 342182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 343172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 344172811Sariff 345165770Sariff/* Toshiba */ 346165770Sariff#define TOSHIBA_VENDORID 0x1179 347165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 348173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 349165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 350165770Sariff 351165992Sariff/* Micro-Star International (MSI) */ 352165992Sariff#define MSI_VENDORID 0x1462 353165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 354172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 355165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 356165992Sariff 357172811Sariff/* Giga-Byte Technology */ 358172811Sariff#define GB_VENDORID 0x1458 359172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 360172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 361172811Sariff 362169277Sariff/* Uniwill ? */ 363169277Sariff#define UNIWILL_VENDORID 0x1584 364169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 365170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 366169277Sariff 367169277Sariff 368162922Sariff/* Misc constants.. */ 369182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 370162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 371162922Sariff#define HDA_AMP_MUTE_NONE (0) 372162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 373162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 374162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 375162922Sariff 376162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 377162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 378162922Sariff 379182999Smav#define HDA_ADC_MONITOR (1 << 0) 380162922Sariff 381182999Smav#define HDA_CTL_OUT 1 382182999Smav#define HDA_CTL_IN 2 383169277Sariff 384169277Sariff#define HDA_GPIO_MAX 8 385169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 386163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 387163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 388163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 389169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 390169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 391169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 392169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 393169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 394169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 395162922Sariff 396169277Sariff/* 9 - 25 = anything else */ 397169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 398169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 399169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 400169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 401169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 402182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 403169277Sariff 404169277Sariff/* 26 - 31 = vrefs */ 405169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 406169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 407169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 408169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 409169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 410169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 411169277Sariff 412169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 413169277Sariff HDA_QUIRK_IVREF100) 414169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 415169277Sariff HDA_QUIRK_OVREF100) 416169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 417169277Sariff 418171141Sariff#if __FreeBSD_version < 600000 419171141Sariff#define taskqueue_drain(...) 420171141Sariff#endif 421171141Sariff 422163057Sariffstatic const struct { 423163057Sariff char *key; 424163057Sariff uint32_t value; 425163057Sariff} hdac_quirks_tab[] = { 426163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 427163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 428163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 429169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 430169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 431169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 432169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 433169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 434165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 435163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 436163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 437163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 438163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 439169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 440182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 441169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 442169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 443169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 444169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 445169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 446169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 447169277Sariff { "ivref", HDA_QUIRK_IVREF }, 448169277Sariff { "ovref", HDA_QUIRK_OVREF }, 449165069Sariff { "vref", HDA_QUIRK_VREF }, 450163057Sariff}; 451163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 452163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 453163057Sariff 454162922Sariff#define HDA_BDL_MIN 2 455162922Sariff#define HDA_BDL_MAX 256 456162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 457162922Sariff 458169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 459167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 460167648Sariff 461162922Sariff#define HDA_BUFSZ_MIN 4096 462162922Sariff#define HDA_BUFSZ_MAX 65536 463162922Sariff#define HDA_BUFSZ_DEFAULT 16384 464162922Sariff 465162922Sariff#define HDA_PARSE_MAXDEPTH 10 466162922Sariff 467169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 468162922Sariff 469165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 470162922Sariff 471182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 472182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 473182999Smav "White", "Other"}; 474162922Sariff 475182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 476182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 477182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 478182999Smav 479182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 480182999Smav 481162922Sariff/* Default */ 482162922Sariffstatic uint32_t hdac_fmt[] = { 483193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 484162922Sariff 0 485162922Sariff}; 486162922Sariff 487162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 488162922Sariff 489189086Smav#define HDAC_NO_MSI 1 490194861Smav#define HDAC_NO_64BIT 2 491189086Smav 492162922Sariffstatic const struct { 493162922Sariff uint32_t model; 494162922Sariff char *desc; 495189086Smav char flags; 496162922Sariff} hdac_devices[] = { 497211910Sjfv { HDA_INTEL_CPT, "Intel Cougar Point", 0 }, 498218149Sjfv { HDA_INTEL_PATSBURG,"Intel Patsburg", 0 }, 499221794Sjfv { HDA_INTEL_PPT1, "Intel Panther Point", 0 }, 500189086Smav { HDA_INTEL_82801F, "Intel 82801F", 0 }, 501189086Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, 502189086Smav { HDA_INTEL_82801G, "Intel 82801G", 0 }, 503189086Smav { HDA_INTEL_82801H, "Intel 82801H", 0 }, 504189086Smav { HDA_INTEL_82801I, "Intel 82801I", 0 }, 505197017Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0 }, 506197017Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0 }, 507218149Sjfv { HDA_INTEL_PCH, "Intel 5 Series/3400 Series", 0 }, 508218149Sjfv { HDA_INTEL_PCH2, "Intel 5 Series/3400 Series", 0 }, 509189086Smav { HDA_INTEL_SCH, "Intel SCH", 0 }, 510189086Smav { HDA_NVIDIA_MCP51, "NVidia MCP51", HDAC_NO_MSI }, 511195690Smav { HDA_NVIDIA_MCP55, "NVidia MCP55", HDAC_NO_MSI }, 512189086Smav { HDA_NVIDIA_MCP61_1, "NVidia MCP61", 0 }, 513189086Smav { HDA_NVIDIA_MCP61_2, "NVidia MCP61", 0 }, 514189086Smav { HDA_NVIDIA_MCP65_1, "NVidia MCP65", 0 }, 515189086Smav { HDA_NVIDIA_MCP65_2, "NVidia MCP65", 0 }, 516189086Smav { HDA_NVIDIA_MCP67_1, "NVidia MCP67", 0 }, 517189086Smav { HDA_NVIDIA_MCP67_2, "NVidia MCP67", 0 }, 518189086Smav { HDA_NVIDIA_MCP73_1, "NVidia MCP73", 0 }, 519189086Smav { HDA_NVIDIA_MCP73_2, "NVidia MCP73", 0 }, 520194861Smav { HDA_NVIDIA_MCP78_1, "NVidia MCP78", HDAC_NO_64BIT }, 521194861Smav { HDA_NVIDIA_MCP78_2, "NVidia MCP78", HDAC_NO_64BIT }, 522194861Smav { HDA_NVIDIA_MCP78_3, "NVidia MCP78", HDAC_NO_64BIT }, 523194861Smav { HDA_NVIDIA_MCP78_4, "NVidia MCP78", HDAC_NO_64BIT }, 524189086Smav { HDA_NVIDIA_MCP79_1, "NVidia MCP79", 0 }, 525189086Smav { HDA_NVIDIA_MCP79_2, "NVidia MCP79", 0 }, 526189086Smav { HDA_NVIDIA_MCP79_3, "NVidia MCP79", 0 }, 527189086Smav { HDA_NVIDIA_MCP79_4, "NVidia MCP79", 0 }, 528197018Smav { HDA_NVIDIA_MCP89_1, "NVidia MCP89", 0 }, 529197018Smav { HDA_NVIDIA_MCP89_2, "NVidia MCP89", 0 }, 530197018Smav { HDA_NVIDIA_MCP89_3, "NVidia MCP89", 0 }, 531197018Smav { HDA_NVIDIA_MCP89_4, "NVidia MCP89", 0 }, 532189086Smav { HDA_ATI_SB450, "ATI SB450", 0 }, 533189086Smav { HDA_ATI_SB600, "ATI SB600", 0 }, 534189086Smav { HDA_ATI_RS600, "ATI RS600", 0 }, 535189086Smav { HDA_ATI_RS690, "ATI RS690", 0 }, 536189086Smav { HDA_ATI_RS780, "ATI RS780", 0 }, 537189086Smav { HDA_ATI_R600, "ATI R600", 0 }, 538189086Smav { HDA_ATI_RV610, "ATI RV610", 0 }, 539189086Smav { HDA_ATI_RV620, "ATI RV620", 0 }, 540189086Smav { HDA_ATI_RV630, "ATI RV630", 0 }, 541189086Smav { HDA_ATI_RV635, "ATI RV635", 0 }, 542189086Smav { HDA_ATI_RV710, "ATI RV710", 0 }, 543189086Smav { HDA_ATI_RV730, "ATI RV730", 0 }, 544189086Smav { HDA_ATI_RV740, "ATI RV740", 0 }, 545189086Smav { HDA_ATI_RV770, "ATI RV770", 0 }, 546216766Syongari { HDA_RDC_M3010, "RDC M3010", 0 }, 547189086Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0 }, 548189086Smav { HDA_SIS_966, "SiS 966", 0 }, 549189086Smav { HDA_ULI_M5461, "ULI M5461", 0 }, 550162922Sariff /* Unknown */ 551162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 552162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 553162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 554163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 555163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 556186301Smav { HDA_ULI_ALL, "ULI (Unknown)" }, 557162922Sariff}; 558162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 559162922Sariff 560162922Sariffstatic const struct { 561169277Sariff uint16_t vendor; 562169277Sariff uint8_t reg; 563169277Sariff uint8_t mask; 564169277Sariff uint8_t enable; 565169277Sariff} hdac_pcie_snoop[] = { 566169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 567169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 568169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 569169277Sariff}; 570169277Sariff#define HDAC_PCIESNOOP_LEN \ 571169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 572169277Sariff 573169277Sariffstatic const struct { 574162922Sariff uint32_t rate; 575162922Sariff int valid; 576162922Sariff uint16_t base; 577162922Sariff uint16_t mul; 578162922Sariff uint16_t div; 579162922Sariff} hda_rate_tab[] = { 580162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 581162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 582162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 583162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 584162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 585162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 586162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 587162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 588162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 589162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 590162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 591162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 592162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 593162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 594162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 595162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 596162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 597162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 598162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 599162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 600162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 601162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 602162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 603162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 604162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 605162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 606162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 607162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 608162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 609162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 610162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 611162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 612162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 613162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 614162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 615162922Sariff}; 616162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 617162922Sariff 618162922Sariff/* All codecs you can eat... */ 619162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 620162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 621162922Sariff 622199846Smav/* Cirrus Logic */ 623199846Smav#define CIRRUSLOGIC_VENDORID 0x1013 624199846Smav#define HDA_CODEC_CS4206 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4206) 625199846Smav#define HDA_CODEC_CS4207 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4207) 626200375Smav#define HDA_CODEC_CSXXXX HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0xffff) 627199846Smav 628162922Sariff/* Realtek */ 629162922Sariff#define REALTEK_VENDORID 0x10ec 630162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 631169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 632183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 633171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 634183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 635205413Smav#define HDA_CODEC_ALC270 HDA_CODEC_CONSTRUCT(REALTEK, 0x0270) 636183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 637205413Smav#define HDA_CODEC_ALC273 HDA_CODEC_CONSTRUCT(REALTEK, 0x0273) 638205413Smav#define HDA_CODEC_ALC275 HDA_CODEC_CONSTRUCT(REALTEK, 0x0275) 639170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 640183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 641183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 642205413Smav#define HDA_CODEC_ALC665 HDA_CODEC_CONSTRUCT(REALTEK, 0x0665) 643162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 644169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 645162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 646163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 647163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 648169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 649197640Smav#define HDA_CODEC_ALC887 HDA_CODEC_CONSTRUCT(REALTEK, 0x0887) 650165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 651182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 652205413Smav#define HDA_CODEC_ALC892 HDA_CODEC_CONSTRUCT(REALTEK, 0x0892) 653162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 654162922Sariff 655169277Sariff/* Analog Devices */ 656169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 657186403Smav#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) 658186403Smav#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) 659186403Smav#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) 660186403Smav#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) 661186403Smav#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) 662186403Smav#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) 663169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 664169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 665174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 666169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 667186403Smav#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) 668169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 669170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 670186403Smav#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) 671186403Smav#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) 672169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 673162922Sariff 674162922Sariff/* CMedia */ 675162922Sariff#define CMEDIA_VENDORID 0x434d 676162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 677162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 678162922Sariff 679162922Sariff/* Sigmatel */ 680162922Sariff#define SIGMATEL_VENDORID 0x8384 681182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 682182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 683182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 684182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 685182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 686182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 687182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 688182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 689183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 690183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 691183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 692183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 693183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 694183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 695183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 696182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 697183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 698183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 699183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 700183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 701183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 702183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 703183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 704183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 705200375Smav#define HDA_CODEC_CXD9872RDK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7661) 706182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 707200375Smav#define HDA_CODEC_CXD9872AKD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7664) 708162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 709182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 710183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 711162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 712162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 713183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 714183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 715183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 716183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 717183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 718183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 719183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 720183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 721183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 722162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 723162922Sariff 724183894Smav/* IDT */ 725183894Smav#define IDT_VENDORID 0x111d 726183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 727183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 728183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 729183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 730183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 731183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 732183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 733183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 734183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 735183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 736183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 737183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 738183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 739183894Smav 740182999Smav/* Silicon Image */ 741182999Smav#define SII_VENDORID 0x1095 742187020Smav#define HDA_CODEC_SII1390 HDA_CODEC_CONSTRUCT(SII, 0x1390) 743186146Smav#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) 744182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 745182999Smav 746182999Smav/* Lucent/Agere */ 747182999Smav#define AGERE_VENDORID 0x11c1 748182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 749182999Smav 750186430Smav/* Conexant */ 751162922Sariff#define CONEXANT_VENDORID 0x14f1 752186430Smav#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 753186430Smav#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 754186430Smav#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) 755200375Smav#define HDA_CODEC_CX20582 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5066) 756205413Smav#define HDA_CODEC_CX20583 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5067) 757208934Smav#define HDA_CODEC_CX20585 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5069) 758162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 759162922Sariff 760169277Sariff/* VIA */ 761169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 762169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 763169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 764169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 765169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 766169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 767169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 768169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 769169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 770169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 771169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 772169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 773186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 774186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 775186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 776186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 777186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 778186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 779186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 780186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 781187020Smav#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) 782187020Smav#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) 783187020Smav#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) 784187020Smav#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) 785187020Smav#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) 786187020Smav#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) 787187020Smav#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) 788187020Smav#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) 789187020Smav#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) 790187020Smav#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) 791187020Smav#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) 792187020Smav#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) 793187020Smav#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) 794187020Smav#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) 795187020Smav#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) 796187020Smav#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) 797199258Smav#define HDA_CODEC_VT1716S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0433) 798199258Smav#define HDA_CODEC_VT1716S_1 HDA_CODEC_CONSTRUCT(VIA, 0xa721) 799199258Smav#define HDA_CODEC_VT1718S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0428) 800199258Smav#define HDA_CODEC_VT1718S_1 HDA_CODEC_CONSTRUCT(VIA, 0x4428) 801199258Smav#define HDA_CODEC_VT1812 HDA_CODEC_CONSTRUCT(VIA, 0x0448) 802199258Smav#define HDA_CODEC_VT1818S HDA_CODEC_CONSTRUCT(VIA, 0x0440) 803199258Smav#define HDA_CODEC_VT1828S HDA_CODEC_CONSTRUCT(VIA, 0x4441) 804199258Smav#define HDA_CODEC_VT2002P_0 HDA_CODEC_CONSTRUCT(VIA, 0x0438) 805199258Smav#define HDA_CODEC_VT2002P_1 HDA_CODEC_CONSTRUCT(VIA, 0x4438) 806199258Smav#define HDA_CODEC_VT2020 HDA_CODEC_CONSTRUCT(VIA, 0x0441) 807169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 808162922Sariff 809182999Smav/* ATI */ 810186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 811186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 812186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 813186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 814182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 815169277Sariff 816182999Smav/* NVIDIA */ 817187020Smav#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) 818187445Smav#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) 819187020Smav#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) 820208934Smav#define HDA_CODEC_NVIDIAGT220 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000a) 821208934Smav#define HDA_CODEC_NVIDIAGT21X HDA_CODEC_CONSTRUCT(NVIDIA, 0x000b) 822208934Smav#define HDA_CODEC_NVIDIAMCP89 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000c) 823208934Smav#define HDA_CODEC_NVIDIAGT240 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000d) 824187020Smav#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) 825187445Smav#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) 826182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 827182999Smav 828183894Smav/* INTEL */ 829222298Smav#define HDA_CODEC_INTELIP HDA_CODEC_CONSTRUCT(INTEL, 0x0054) 830222298Smav#define HDA_CODEC_INTELBL HDA_CODEC_CONSTRUCT(INTEL, 0x2801) 831222298Smav#define HDA_CODEC_INTELCA HDA_CODEC_CONSTRUCT(INTEL, 0x2802) 832222298Smav#define HDA_CODEC_INTELEL HDA_CODEC_CONSTRUCT(INTEL, 0x2803) 833222298Smav#define HDA_CODEC_INTELIP2 HDA_CODEC_CONSTRUCT(INTEL, 0x2804) 834222298Smav#define HDA_CODEC_INTELCPT HDA_CODEC_CONSTRUCT(INTEL, 0x2805) 835222298Smav#define HDA_CODEC_INTELCL HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) 836183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 837183894Smav 838162922Sariff/* Codecs */ 839162922Sariffstatic const struct { 840162922Sariff uint32_t id; 841162922Sariff char *name; 842162922Sariff} hdac_codecs[] = { 843199846Smav { HDA_CODEC_CS4206, "Cirrus Logic CS4206" }, 844199846Smav { HDA_CODEC_CS4207, "Cirrus Logic CS4207" }, 845162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 846169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 847183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 848171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 849183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 850205413Smav { HDA_CODEC_ALC270, "Realtek ALC270" }, 851183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 852205413Smav { HDA_CODEC_ALC273, "Realtek ALC273" }, 853205413Smav { HDA_CODEC_ALC275, "Realtek ALC275" }, 854170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 855183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 856183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 857205413Smav { HDA_CODEC_ALC665, "Realtek ALC665" }, 858162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 859169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 860162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 861162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 862163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 863169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 864197640Smav { HDA_CODEC_ALC887, "Realtek ALC887" }, 865165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 866182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 867205413Smav { HDA_CODEC_ALC892, "Realtek ALC892" }, 868186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 869186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 870186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 871186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 872186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 873169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 874169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 875174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 876186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 877186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 878169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 879186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 880186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 881170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 882186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 883162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 884200375Smav { HDA_CODEC_CXD9872RDK, "Sigmatel CXD9872RD/K" }, 885200375Smav { HDA_CODEC_CXD9872AKD, "Sigmatel CXD9872AKD" }, 886183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 887183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 888183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 889183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 890183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 891183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 892183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 893183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 894162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 895183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 896162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 897162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 898183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 899183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 900183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 901183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 902183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 903183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 904182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 905182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 906183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 907183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 908183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 909166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 910183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 911183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 912183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 913183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 914183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 915183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 916183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 917183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 918183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 919183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 920183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 921183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 922183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 923183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 924183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 925183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 926183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 927183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 928183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 929183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 930183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 931183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 932183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 933183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 934183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 935183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 936183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 937186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 938186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 939186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 940200375Smav { HDA_CODEC_CX20582, "Conexant CX20582 (Pebble)" }, 941205413Smav { HDA_CODEC_CX20583, "Conexant CX20583 (Pebble HSF)" }, 942208934Smav { HDA_CODEC_CX20585, "Conexant CX20585" }, 943169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 944169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 945169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 946169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 947169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 948169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 949169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 950169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 951169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 952169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 953169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 954169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 955186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 956186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 957186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 958186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 959186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 960186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 961186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 962186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 963187020Smav { HDA_CODEC_VT1708S_0, "VIA VT1708S_0" }, 964187020Smav { HDA_CODEC_VT1708S_1, "VIA VT1708S_1" }, 965187020Smav { HDA_CODEC_VT1708S_2, "VIA VT1708S_2" }, 966187020Smav { HDA_CODEC_VT1708S_3, "VIA VT1708S_3" }, 967187020Smav { HDA_CODEC_VT1708S_4, "VIA VT1708S_4" }, 968187020Smav { HDA_CODEC_VT1708S_5, "VIA VT1708S_5" }, 969187020Smav { HDA_CODEC_VT1708S_6, "VIA VT1708S_6" }, 970187020Smav { HDA_CODEC_VT1708S_7, "VIA VT1708S_7" }, 971187020Smav { HDA_CODEC_VT1702_0, "VIA VT1702_0" }, 972187020Smav { HDA_CODEC_VT1702_1, "VIA VT1702_1" }, 973187020Smav { HDA_CODEC_VT1702_2, "VIA VT1702_2" }, 974187020Smav { HDA_CODEC_VT1702_3, "VIA VT1702_3" }, 975187020Smav { HDA_CODEC_VT1702_4, "VIA VT1702_4" }, 976187020Smav { HDA_CODEC_VT1702_5, "VIA VT1702_5" }, 977187020Smav { HDA_CODEC_VT1702_6, "VIA VT1702_6" }, 978187020Smav { HDA_CODEC_VT1702_7, "VIA VT1702_7" }, 979199258Smav { HDA_CODEC_VT1716S_0, "VIA VT1716S_0" }, 980199258Smav { HDA_CODEC_VT1716S_1, "VIA VT1716S_1" }, 981199258Smav { HDA_CODEC_VT1718S_0, "VIA VT1718S_0" }, 982199258Smav { HDA_CODEC_VT1718S_1, "VIA VT1718S_1" }, 983199258Smav { HDA_CODEC_VT1812, "VIA VT1812" }, 984199258Smav { HDA_CODEC_VT1818S, "VIA VT1818S" }, 985199258Smav { HDA_CODEC_VT1828S, "VIA VT1828S" }, 986199258Smav { HDA_CODEC_VT2002P_0, "VIA VT2002P_0" }, 987199258Smav { HDA_CODEC_VT2002P_1, "VIA VT2002P_1" }, 988199258Smav { HDA_CODEC_VT2020, "VIA VT2020" }, 989186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 990186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 991186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 992186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 993187020Smav { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, 994187445Smav { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, 995187020Smav { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, 996187445Smav { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, 997187020Smav { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, 998208934Smav { HDA_CODEC_NVIDIAGT220, "NVidia GT220 HDMI" }, 999208934Smav { HDA_CODEC_NVIDIAGT21X, "NVidia GT21x HDMI" }, 1000208934Smav { HDA_CODEC_NVIDIAMCP89, "NVidia MCP89 HDMI" }, 1001208934Smav { HDA_CODEC_NVIDIAGT240, "NVidia GT240 HDMI" }, 1002222298Smav { HDA_CODEC_INTELIP, "Intel Ibex Peak HDMI" }, 1003222298Smav { HDA_CODEC_INTELBL, "Intel Bearlake HDMI" }, 1004222298Smav { HDA_CODEC_INTELCA, "Intel Cantiga HDMI" }, 1005222298Smav { HDA_CODEC_INTELEL, "Intel Eaglelake HDMI" }, 1006222298Smav { HDA_CODEC_INTELIP2, "Intel Ibex Peak HDMI" }, 1007222298Smav { HDA_CODEC_INTELCPT, "Intel Cougar Point HDMI" }, 1008222298Smav { HDA_CODEC_INTELCL, "Intel Crestline HDMI" }, 1009187020Smav { HDA_CODEC_SII1390, "Silicon Image SiI1390 HDMI" }, 1010186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 1011162922Sariff /* Unknown codec */ 1012162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 1013169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 1014200375Smav { HDA_CODEC_CSXXXX, "Cirrus Logic (Unknown)" }, 1015162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 1016162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 1017182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 1018182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 1019162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 1020169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 1021182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 1022182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 1023183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 1024183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 1025162922Sariff}; 1026162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 1027162922Sariff 1028162922Sariff 1029162922Sariff/**************************************************************************** 1030162922Sariff * Function prototypes 1031162922Sariff ****************************************************************************/ 1032162922Sariffstatic void hdac_intr_handler(void *); 1033182999Smavstatic int hdac_reset(struct hdac_softc *, int); 1034162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 1035162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 1036162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 1037162922Sariff struct hdac_dma *, bus_size_t); 1038169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 1039162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 1040162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 1041162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 1042162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 1043162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 1044162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 1045162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 1046162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 1047182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 1048182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 1049182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 1050182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 1051162922Sariff 1052162922Sariffstatic void hdac_attach2(void *); 1053162922Sariff 1054162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 1055162922Sariff uint32_t, int); 1056162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 1057162922Sariff struct hdac_command_list *, int); 1058162922Sariff 1059162922Sariffstatic int hdac_probe(device_t); 1060162922Sariffstatic int hdac_attach(device_t); 1061162922Sariffstatic int hdac_detach(device_t); 1062182999Smavstatic int hdac_suspend(device_t); 1063182999Smavstatic int hdac_resume(device_t); 1064162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 1065162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 1066162922Sariff uint32_t, int, int); 1067162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 1068182999Smav nid_t, int, int, int); 1069162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 1070162922Sariff nid_t, nid_t, int, int, int, int, int, int); 1071162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 1072162922Sariff 1073164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 1074164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 1075164614Sariff 1076182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 1077182999Smav 1078162922Sariff#define hdac_command(a1, a2, a3) \ 1079162922Sariff hdac_command_sendone_internal(a1, a2, a3) 1080162922Sariff 1081182999Smav#define hdac_codec_id(c) \ 1082182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 1083182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 1084182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 1085162922Sariff 1086162922Sariffstatic char * 1087182999Smavhdac_codec_name(struct hdac_codec *codec) 1088162922Sariff{ 1089162922Sariff uint32_t id; 1090162922Sariff int i; 1091162922Sariff 1092182999Smav id = hdac_codec_id(codec); 1093162922Sariff 1094162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 1095163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 1096162922Sariff return (hdac_codecs[i].name); 1097162922Sariff } 1098162922Sariff 1099162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 1100162922Sariff} 1101162922Sariff 1102162922Sariffstatic char * 1103162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 1104162922Sariff{ 1105162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 1106162922Sariff int i, first = 1; 1107162922Sariff 1108162922Sariff bzero(buf, len); 1109162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 1110162922Sariff if (mask & (1 << i)) { 1111162922Sariff if (first == 0) 1112162922Sariff strlcat(buf, ", ", len); 1113162922Sariff strlcat(buf, ossname[i], len); 1114162922Sariff first = 0; 1115162922Sariff } 1116162922Sariff } 1117182999Smav return (buf); 1118162922Sariff} 1119162922Sariff 1120162922Sariffstatic struct hdac_audio_ctl * 1121162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 1122162922Sariff{ 1123162922Sariff if (devinfo == NULL || 1124162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 1125162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 1126162922Sariff devinfo->function.audio.ctlcnt < 1 || 1127162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 1128162922Sariff return (NULL); 1129162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 1130162922Sariff} 1131162922Sariff 1132162922Sariffstatic struct hdac_audio_ctl * 1133182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 1134162922Sariff int index, int cnt) 1135162922Sariff{ 1136182999Smav struct hdac_audio_ctl *ctl; 1137182999Smav int i, found = 0; 1138162922Sariff 1139162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 1140162922Sariff return (NULL); 1141162922Sariff 1142162922Sariff i = 0; 1143162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 1144182999Smav if (ctl->enable == 0) 1145162922Sariff continue; 1146182999Smav if (ctl->widget->nid != nid) 1147162922Sariff continue; 1148182999Smav if (dir && ctl->ndir != dir) 1149182999Smav continue; 1150182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 1151182999Smav ctl->dir == ctl->ndir && ctl->index != index) 1152182999Smav continue; 1153162922Sariff found++; 1154182999Smav if (found == cnt || cnt <= 0) 1155162922Sariff return (ctl); 1156162922Sariff } 1157162922Sariff 1158182999Smav return (NULL); 1159162922Sariff} 1160162922Sariff 1161182999Smav/* 1162182999Smav * Jack detection (Speaker/HP redirection) event handler. 1163182999Smav */ 1164162922Sariffstatic void 1165162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 1166162922Sariff{ 1167182999Smav struct hdac_audio_as *as; 1168162922Sariff struct hdac_softc *sc; 1169162922Sariff struct hdac_widget *w; 1170162922Sariff struct hdac_audio_ctl *ctl; 1171182999Smav uint32_t val, res; 1172182999Smav int i, j; 1173162922Sariff nid_t cad; 1174162922Sariff 1175162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1176162922Sariff devinfo->codec->sc == NULL) 1177162922Sariff return; 1178162922Sariff 1179162922Sariff sc = devinfo->codec->sc; 1180162922Sariff cad = devinfo->codec->cad; 1181182999Smav as = devinfo->function.audio.as; 1182182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1183182999Smav if (as[i].hpredir < 0) 1184182999Smav continue; 1185182999Smav 1186182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1187182999Smav if (w == NULL || w->enable == 0 || w->type != 1188182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1189182999Smav continue; 1190162922Sariff 1191171141Sariff res = hdac_command(sc, 1192182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1193171141Sariff 1194182999Smav HDA_BOOTVERBOSE( 1195182999Smav device_printf(sc->dev, 1196182999Smav "Pin sense: nid=%d res=0x%08x\n", 1197182999Smav as[i].pins[15], res); 1198182999Smav ); 1199171141Sariff 1200182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1201182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1202182999Smav res ^= 1; 1203162922Sariff 1204182999Smav /* (Un)Mute headphone pin. */ 1205162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1206182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1207182999Smav if (ctl != NULL && ctl->mute) { 1208182999Smav /* If pin has muter - use it. */ 1209182999Smav val = (res != 0) ? 0 : 1; 1210182999Smav if (val != ctl->forcemute) { 1211182999Smav ctl->forcemute = val; 1212162922Sariff hdac_audio_ctl_amp_set(ctl, 1213182999Smav HDA_AMP_MUTE_DEFAULT, 1214182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1215162922Sariff } 1216182999Smav } else { 1217182999Smav /* If there is no muter - disable pin output. */ 1218182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1219163057Sariff if (w != NULL && w->type == 1220163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1221182999Smav if (res != 0) 1222169277Sariff val = w->wclass.pin.ctrl | 1223162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1224162922Sariff else 1225169277Sariff val = w->wclass.pin.ctrl & 1226162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1227169277Sariff if (val != w->wclass.pin.ctrl) { 1228169277Sariff w->wclass.pin.ctrl = val; 1229169277Sariff hdac_command(sc, 1230169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1231169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1232169277Sariff } 1233162922Sariff } 1234182999Smav } 1235182999Smav /* (Un)Mute other pins. */ 1236182999Smav for (j = 0; j < 15; j++) { 1237182999Smav if (as[i].pins[j] <= 0) 1238182999Smav continue; 1239182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1240182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1241182999Smav if (ctl != NULL && ctl->mute) { 1242182999Smav /* If pin has muter - use it. */ 1243182999Smav val = (res != 0) ? 1 : 0; 1244182999Smav if (val == ctl->forcemute) 1245169277Sariff continue; 1246182999Smav ctl->forcemute = val; 1247182999Smav hdac_audio_ctl_amp_set(ctl, 1248182999Smav HDA_AMP_MUTE_DEFAULT, 1249182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1250182999Smav continue; 1251162922Sariff } 1252182999Smav /* If there is no muter - disable pin output. */ 1253182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1254163057Sariff if (w != NULL && w->type == 1255163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1256182999Smav if (res != 0) 1257182999Smav val = w->wclass.pin.ctrl & 1258182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1259182999Smav else 1260182999Smav val = w->wclass.pin.ctrl | 1261182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1262169277Sariff if (val != w->wclass.pin.ctrl) { 1263169277Sariff w->wclass.pin.ctrl = val; 1264169277Sariff hdac_command(sc, 1265169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1266169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1267169277Sariff } 1268162922Sariff } 1269162922Sariff } 1270182999Smav } 1271182999Smav} 1272182999Smav 1273182999Smav/* 1274182999Smav * Callback for poll based jack detection. 1275182999Smav */ 1276182999Smavstatic void 1277182999Smavhdac_jack_poll_callback(void *arg) 1278182999Smav{ 1279182999Smav struct hdac_devinfo *devinfo = arg; 1280182999Smav struct hdac_softc *sc; 1281182999Smav 1282182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1283182999Smav devinfo->codec->sc == NULL) 1284182999Smav return; 1285182999Smav sc = devinfo->codec->sc; 1286182999Smav hdac_lock(sc); 1287182999Smav if (sc->poll_ival == 0) { 1288182999Smav hdac_unlock(sc); 1289182999Smav return; 1290182999Smav } 1291182999Smav hdac_hp_switch_handler(devinfo); 1292182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1293182999Smav hdac_jack_poll_callback, devinfo); 1294182999Smav hdac_unlock(sc); 1295182999Smav} 1296182999Smav 1297182999Smav/* 1298182999Smav * Jack detection initializer. 1299182999Smav */ 1300182999Smavstatic void 1301182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1302182999Smav{ 1303182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1304182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1305182999Smav struct hdac_widget *w; 1306182999Smav uint32_t id; 1307182999Smav int i, enable = 0, poll = 0; 1308182999Smav nid_t cad; 1309182999Smav 1310182999Smav id = hdac_codec_id(devinfo->codec); 1311182999Smav cad = devinfo->codec->cad; 1312182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1313182999Smav if (as[i].hpredir < 0) 1314182999Smav continue; 1315182999Smav 1316182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1317182999Smav if (w == NULL || w->enable == 0 || w->type != 1318182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1319182999Smav continue; 1320182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1321182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1322182999Smav device_printf(sc->dev, 1323182999Smav "No jack detection support at pin %d\n", 1324182999Smav as[i].pins[15]); 1325182999Smav continue; 1326182999Smav } 1327182999Smav enable = 1; 1328182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1329169277Sariff hdac_command(sc, 1330182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1331182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1332182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1333182999Smav } else 1334182999Smav poll = 1; 1335182999Smav HDA_BOOTVERBOSE( 1336169277Sariff device_printf(sc->dev, 1337182999Smav "Enabling headphone/speaker " 1338182999Smav "audio routing switching:\n"); 1339182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1340182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1341182999Smav ); 1342182999Smav } 1343182999Smav if (enable) { 1344182999Smav hdac_hp_switch_handler(devinfo); 1345182999Smav if (poll) { 1346182999Smav callout_reset(&sc->poll_jack, 1, 1347182999Smav hdac_jack_poll_callback, devinfo); 1348169277Sariff } 1349162922Sariff } 1350162922Sariff} 1351162922Sariff 1352182999Smav/* 1353182999Smav * Unsolicited messages handler. 1354182999Smav */ 1355162922Sariffstatic void 1356162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1357162922Sariff{ 1358162922Sariff struct hdac_softc *sc; 1359162922Sariff struct hdac_devinfo *devinfo = NULL; 1360182999Smav int i; 1361162922Sariff 1362162922Sariff if (codec == NULL || codec->sc == NULL) 1363162922Sariff return; 1364162922Sariff 1365162922Sariff sc = codec->sc; 1366162922Sariff 1367163057Sariff HDA_BOOTVERBOSE( 1368182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1369162922Sariff ); 1370162922Sariff 1371182999Smav for (i = 0; i < codec->num_fgs; i++) { 1372182999Smav if (codec->fgs[i].node_type == 1373182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1374182999Smav devinfo = &codec->fgs[i]; 1375162965Sariff break; 1376182999Smav } 1377162922Sariff } 1378162965Sariff 1379162922Sariff if (devinfo == NULL) 1380162922Sariff return; 1381162922Sariff 1382162922Sariff switch (tag) { 1383162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1384162922Sariff hdac_hp_switch_handler(devinfo); 1385162922Sariff break; 1386162922Sariff default: 1387182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1388162922Sariff break; 1389162922Sariff } 1390162922Sariff} 1391162922Sariff 1392164614Sariffstatic int 1393162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1394162922Sariff{ 1395162922Sariff /* XXX to be removed */ 1396162922Sariff#ifdef HDAC_INTR_EXTRA 1397162922Sariff uint32_t res; 1398162922Sariff#endif 1399162922Sariff 1400171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1401164614Sariff return (0); 1402162922Sariff 1403162922Sariff /* XXX to be removed */ 1404162922Sariff#ifdef HDAC_INTR_EXTRA 1405162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1406162922Sariff#endif 1407162922Sariff 1408162922Sariff /* XXX to be removed */ 1409162922Sariff#ifdef HDAC_INTR_EXTRA 1410163057Sariff HDA_BOOTVERBOSE( 1411163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1412182999Smav device_printf(ch->pdevinfo->dev, 1413163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1414163057Sariff "%08x\n", 1415163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1416163057Sariff ); 1417162922Sariff#endif 1418162922Sariff 1419162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1420163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1421162922Sariff 1422162922Sariff /* XXX to be removed */ 1423162922Sariff#ifdef HDAC_INTR_EXTRA 1424162922Sariff if (res & HDAC_SDSTS_BCIS) { 1425162922Sariff#endif 1426164614Sariff return (1); 1427162922Sariff /* XXX to be removed */ 1428162922Sariff#ifdef HDAC_INTR_EXTRA 1429162922Sariff } 1430162922Sariff#endif 1431164614Sariff 1432164614Sariff return (0); 1433162922Sariff} 1434162922Sariff 1435162922Sariff/**************************************************************************** 1436162922Sariff * void hdac_intr_handler(void *) 1437162922Sariff * 1438162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1439162922Sariff ****************************************************************************/ 1440162922Sariffstatic void 1441162922Sariffhdac_intr_handler(void *context) 1442162922Sariff{ 1443162922Sariff struct hdac_softc *sc; 1444162922Sariff uint32_t intsts; 1445162922Sariff uint8_t rirbsts; 1446164614Sariff struct hdac_rirb *rirb_base; 1447171141Sariff uint32_t trigger; 1448182999Smav int i; 1449162922Sariff 1450162922Sariff sc = (struct hdac_softc *)context; 1451162922Sariff 1452162922Sariff hdac_lock(sc); 1453164614Sariff if (sc->polling != 0) { 1454164614Sariff hdac_unlock(sc); 1455164614Sariff return; 1456164614Sariff } 1457171141Sariff 1458162922Sariff /* Do we have anything to do? */ 1459162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1460163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1461162922Sariff hdac_unlock(sc); 1462162922Sariff return; 1463162922Sariff } 1464162922Sariff 1465171141Sariff trigger = 0; 1466171141Sariff 1467162922Sariff /* Was this a controller interrupt? */ 1468163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1469162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1470162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1471162922Sariff /* Get as many responses that we can */ 1472163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1473164614Sariff HDAC_WRITE_1(&sc->mem, 1474164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1475171141Sariff if (hdac_rirb_flush(sc) != 0) 1476171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1477162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1478162922Sariff } 1479162922Sariff /* XXX to be removed */ 1480162922Sariff /* Clear interrupt and exit */ 1481162922Sariff#ifdef HDAC_INTR_EXTRA 1482162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1483162922Sariff#endif 1484162922Sariff } 1485164614Sariff 1486163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1487182999Smav for (i = 0; i < sc->num_chans; i++) { 1488182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1489182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1490182999Smav trigger |= (1 << i); 1491182999Smav } 1492162922Sariff /* XXX to be removed */ 1493162922Sariff#ifdef HDAC_INTR_EXTRA 1494164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1495164614Sariff HDAC_INTSTS_SIS_MASK); 1496162922Sariff#endif 1497162922Sariff } 1498162922Sariff 1499164614Sariff hdac_unlock(sc); 1500162922Sariff 1501182999Smav for (i = 0; i < sc->num_chans; i++) { 1502182999Smav if (trigger & (1 << i)) 1503182999Smav chn_intr(sc->chans[i].c); 1504182999Smav } 1505171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1506171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1507162922Sariff} 1508162922Sariff 1509162922Sariff/**************************************************************************** 1510182999Smav * int hdac_reset(hdac_softc *, int) 1511162922Sariff * 1512162922Sariff * Reset the hdac to a quiescent and known state. 1513162922Sariff ****************************************************************************/ 1514162922Sariffstatic int 1515182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1516162922Sariff{ 1517162922Sariff uint32_t gctl; 1518162922Sariff int count, i; 1519162922Sariff 1520162922Sariff /* 1521162922Sariff * Stop all Streams DMA engine 1522162922Sariff */ 1523162922Sariff for (i = 0; i < sc->num_iss; i++) 1524162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1525162922Sariff for (i = 0; i < sc->num_oss; i++) 1526162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1527162922Sariff for (i = 0; i < sc->num_bss; i++) 1528162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1529162922Sariff 1530162922Sariff /* 1531169277Sariff * Stop Control DMA engines. 1532162922Sariff */ 1533162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1534162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1535162922Sariff 1536162922Sariff /* 1537169277Sariff * Reset DMA position buffer. 1538169277Sariff */ 1539169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1540169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1541169277Sariff 1542169277Sariff /* 1543162922Sariff * Reset the controller. The reset must remain asserted for 1544162922Sariff * a minimum of 100us. 1545162922Sariff */ 1546162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1547162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1548162922Sariff count = 10000; 1549162922Sariff do { 1550162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1551162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1552162922Sariff break; 1553162922Sariff DELAY(10); 1554162922Sariff } while (--count); 1555162922Sariff if (gctl & HDAC_GCTL_CRST) { 1556162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1557162922Sariff return (ENXIO); 1558162922Sariff } 1559182999Smav 1560182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1561182999Smav if (!wakeup) 1562182999Smav return (0); 1563182999Smav 1564162922Sariff DELAY(100); 1565162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1566162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1567162922Sariff count = 10000; 1568162922Sariff do { 1569162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1570163057Sariff if (gctl & HDAC_GCTL_CRST) 1571162922Sariff break; 1572162922Sariff DELAY(10); 1573162922Sariff } while (--count); 1574162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1575162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1576162922Sariff return (ENXIO); 1577162922Sariff } 1578162922Sariff 1579162922Sariff /* 1580162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1581162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1582162922Sariff * computer. Let's use twice as much as necessary to make sure that 1583162922Sariff * it's reset properly. 1584162922Sariff */ 1585162922Sariff DELAY(1000); 1586162922Sariff 1587162922Sariff return (0); 1588162922Sariff} 1589162922Sariff 1590162922Sariff 1591162922Sariff/**************************************************************************** 1592162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1593162922Sariff * 1594162922Sariff * Retreive the general capabilities of the hdac; 1595162922Sariff * Number of Input Streams 1596162922Sariff * Number of Output Streams 1597162922Sariff * Number of bidirectional Streams 1598162922Sariff * 64bit ready 1599162922Sariff * CORB and RIRB sizes 1600162922Sariff ****************************************************************************/ 1601162922Sariffstatic int 1602162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1603162922Sariff{ 1604162922Sariff uint16_t gcap; 1605162922Sariff uint8_t corbsize, rirbsize; 1606162922Sariff 1607162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1608162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1609162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1610162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1611196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 1612163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1613162922Sariff 1614162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1615162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1616162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1617162922Sariff sc->corb_size = 256; 1618162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1619162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1620162922Sariff sc->corb_size = 16; 1621162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1622162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1623162922Sariff sc->corb_size = 2; 1624162922Sariff else { 1625162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1626162922Sariff __func__, corbsize); 1627162922Sariff return (ENXIO); 1628162922Sariff } 1629162922Sariff 1630162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1631162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1632162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1633162922Sariff sc->rirb_size = 256; 1634162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1635162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1636162922Sariff sc->rirb_size = 16; 1637162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1638162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1639162922Sariff sc->rirb_size = 2; 1640162922Sariff else { 1641162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1642162922Sariff __func__, rirbsize); 1643162922Sariff return (ENXIO); 1644162922Sariff } 1645162922Sariff 1646196762Smav HDA_BOOTVERBOSE( 1647196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 1648196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 1649196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 1650196762Smav sc->support_64bit ? ", 64bit" : "", 1651196762Smav sc->corb_size, sc->rirb_size); 1652182999Smav ); 1653182999Smav 1654162922Sariff return (0); 1655162922Sariff} 1656162922Sariff 1657162922Sariff 1658162922Sariff/**************************************************************************** 1659162922Sariff * void hdac_dma_cb 1660162922Sariff * 1661162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1662162922Sariff * established. We just record the physical address of the mapping into 1663162922Sariff * the struct hdac_dma passed in. 1664162922Sariff ****************************************************************************/ 1665162922Sariffstatic void 1666162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1667162922Sariff{ 1668162922Sariff struct hdac_dma *dma; 1669162922Sariff 1670162922Sariff if (error == 0) { 1671162922Sariff dma = (struct hdac_dma *)callback_arg; 1672162922Sariff dma->dma_paddr = segs[0].ds_addr; 1673162922Sariff } 1674162922Sariff} 1675162922Sariff 1676162922Sariff 1677162922Sariff/**************************************************************************** 1678162922Sariff * int hdac_dma_alloc 1679162922Sariff * 1680162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1681162922Sariff * It must be freed by a corresponding hdac_dma_free. 1682162922Sariff ****************************************************************************/ 1683162922Sariffstatic int 1684162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1685162922Sariff{ 1686169277Sariff bus_size_t roundsz; 1687162922Sariff int result; 1688162922Sariff 1689169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1690162922Sariff bzero(dma, sizeof(*dma)); 1691162922Sariff 1692162922Sariff /* 1693162922Sariff * Create a DMA tag 1694162922Sariff */ 1695194861Smav result = bus_dma_tag_create( 1696194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1697162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1698162922Sariff 0, /* boundary */ 1699194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1700194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1701162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1702162922Sariff NULL, /* filtfunc */ 1703162922Sariff NULL, /* fistfuncarg */ 1704169277Sariff roundsz, /* maxsize */ 1705162922Sariff 1, /* nsegments */ 1706169277Sariff roundsz, /* maxsegsz */ 1707162922Sariff 0, /* flags */ 1708162922Sariff NULL, /* lockfunc */ 1709162922Sariff NULL, /* lockfuncarg */ 1710162922Sariff &dma->dma_tag); /* dmat */ 1711162922Sariff if (result != 0) { 1712162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1713162922Sariff __func__, result); 1714167773Sariff goto hdac_dma_alloc_fail; 1715162922Sariff } 1716162922Sariff 1717162922Sariff /* 1718162922Sariff * Allocate DMA memory 1719162922Sariff */ 1720162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1721169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1722171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1723171330Sariff &dma->dma_map); 1724162922Sariff if (result != 0) { 1725162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1726162922Sariff __func__, result); 1727167773Sariff goto hdac_dma_alloc_fail; 1728162922Sariff } 1729162922Sariff 1730169277Sariff dma->dma_size = roundsz; 1731169277Sariff 1732162922Sariff /* 1733162922Sariff * Map the memory 1734162922Sariff */ 1735162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1736169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1737162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1738167773Sariff if (result == 0) 1739167773Sariff result = ENOMEM; 1740162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1741162922Sariff __func__, result); 1742167773Sariff goto hdac_dma_alloc_fail; 1743162922Sariff } 1744162922Sariff 1745183097Smav HDA_BOOTHVERBOSE( 1746169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1747169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1748169277Sariff ); 1749169277Sariff 1750162922Sariff return (0); 1751169277Sariff 1752167773Sariffhdac_dma_alloc_fail: 1753169277Sariff hdac_dma_free(sc, dma); 1754167773Sariff 1755162922Sariff return (result); 1756162922Sariff} 1757162922Sariff 1758162922Sariff 1759162922Sariff/**************************************************************************** 1760169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1761162922Sariff * 1762162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1763162922Sariff * hdac_dma_alloc function. 1764162922Sariff ****************************************************************************/ 1765162922Sariffstatic void 1766169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1767162922Sariff{ 1768167773Sariff if (dma->dma_map != NULL) { 1769169277Sariff#if 0 1770162922Sariff /* Flush caches */ 1771162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1772162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1773169277Sariff#endif 1774162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1775167773Sariff } 1776167773Sariff if (dma->dma_vaddr != NULL) { 1777162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1778167773Sariff dma->dma_vaddr = NULL; 1779167773Sariff } 1780167773Sariff dma->dma_map = NULL; 1781167773Sariff if (dma->dma_tag != NULL) { 1782162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1783167773Sariff dma->dma_tag = NULL; 1784162922Sariff } 1785167773Sariff dma->dma_size = 0; 1786162922Sariff} 1787162922Sariff 1788162922Sariff/**************************************************************************** 1789162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1790162922Sariff * 1791162922Sariff * Allocate all the bus resources necessary to speak with the physical 1792162922Sariff * controller. 1793162922Sariff ****************************************************************************/ 1794162922Sariffstatic int 1795162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1796162922Sariff{ 1797162922Sariff struct hdac_mem *mem; 1798162922Sariff 1799162922Sariff mem = &sc->mem; 1800162922Sariff mem->mem_rid = PCIR_BAR(0); 1801162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1802162922Sariff &mem->mem_rid, RF_ACTIVE); 1803162922Sariff if (mem->mem_res == NULL) { 1804162922Sariff device_printf(sc->dev, 1805162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1806162922Sariff return (ENOMEM); 1807162922Sariff } 1808162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1809162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1810162922Sariff 1811162922Sariff return (0); 1812162922Sariff} 1813162922Sariff 1814162922Sariff/**************************************************************************** 1815162922Sariff * void hdac_mem_free(struct hdac_softc *) 1816162922Sariff * 1817162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1818162922Sariff ****************************************************************************/ 1819162922Sariffstatic void 1820162922Sariffhdac_mem_free(struct hdac_softc *sc) 1821162922Sariff{ 1822162922Sariff struct hdac_mem *mem; 1823162922Sariff 1824162922Sariff mem = &sc->mem; 1825162922Sariff if (mem->mem_res != NULL) 1826162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1827162922Sariff mem->mem_res); 1828164614Sariff mem->mem_res = NULL; 1829162922Sariff} 1830162922Sariff 1831162922Sariff/**************************************************************************** 1832162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1833162922Sariff * 1834162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1835162922Sariff ****************************************************************************/ 1836162922Sariffstatic int 1837162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1838162922Sariff{ 1839162922Sariff struct hdac_irq *irq; 1840162922Sariff int result; 1841162922Sariff 1842162922Sariff irq = &sc->irq; 1843162922Sariff irq->irq_rid = 0x0; 1844171330Sariff 1845171330Sariff if ((sc->flags & HDAC_F_MSI) && 1846171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1847171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1848171330Sariff irq->irq_rid = 0x1; 1849171330Sariff else 1850171330Sariff sc->flags &= ~HDAC_F_MSI; 1851171330Sariff 1852162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1853162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1854162922Sariff if (irq->irq_res == NULL) { 1855162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1856162922Sariff __func__); 1857167773Sariff goto hdac_irq_alloc_fail; 1858162922Sariff } 1859182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1860182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1861162922Sariff if (result != 0) { 1862162922Sariff device_printf(sc->dev, 1863162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1864162922Sariff __func__, result); 1865167773Sariff goto hdac_irq_alloc_fail; 1866162922Sariff } 1867162922Sariff 1868162922Sariff return (0); 1869162922Sariff 1870167773Sariffhdac_irq_alloc_fail: 1871164614Sariff hdac_irq_free(sc); 1872164614Sariff 1873162922Sariff return (ENXIO); 1874162922Sariff} 1875162922Sariff 1876162922Sariff/**************************************************************************** 1877162922Sariff * void hdac_irq_free(struct hdac_softc *) 1878162922Sariff * 1879162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1880162922Sariff ****************************************************************************/ 1881162922Sariffstatic void 1882162922Sariffhdac_irq_free(struct hdac_softc *sc) 1883162922Sariff{ 1884162922Sariff struct hdac_irq *irq; 1885162922Sariff 1886162922Sariff irq = &sc->irq; 1887164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1888162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1889162922Sariff if (irq->irq_res != NULL) 1890162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1891162922Sariff irq->irq_res); 1892188656Smav if (irq->irq_rid == 0x1) 1893171330Sariff pci_release_msi(sc->dev); 1894164614Sariff irq->irq_handle = NULL; 1895164614Sariff irq->irq_res = NULL; 1896171330Sariff irq->irq_rid = 0x0; 1897162922Sariff} 1898162922Sariff 1899162922Sariff/**************************************************************************** 1900162922Sariff * void hdac_corb_init(struct hdac_softc *) 1901162922Sariff * 1902162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1903162922Sariff * The CORB engine must not be running when this function is called. 1904162922Sariff ****************************************************************************/ 1905162922Sariffstatic void 1906162922Sariffhdac_corb_init(struct hdac_softc *sc) 1907162922Sariff{ 1908162922Sariff uint8_t corbsize; 1909162922Sariff uint64_t corbpaddr; 1910162922Sariff 1911162922Sariff /* Setup the CORB size. */ 1912162922Sariff switch (sc->corb_size) { 1913162922Sariff case 256: 1914162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1915162922Sariff break; 1916162922Sariff case 16: 1917162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1918162922Sariff break; 1919162922Sariff case 2: 1920162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1921162922Sariff break; 1922162922Sariff default: 1923162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1924162922Sariff } 1925162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1926162922Sariff 1927162922Sariff /* Setup the CORB Address in the hdac */ 1928162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1929162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1930162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1931162922Sariff 1932162922Sariff /* Set the WP and RP */ 1933162922Sariff sc->corb_wp = 0; 1934162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1935162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1936162922Sariff /* 1937162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1938162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1939162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1940162922Sariff * manually reset the bit to zero before continuing. 1941162922Sariff */ 1942162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1943162922Sariff 1944162922Sariff /* Enable CORB error reporting */ 1945162922Sariff#if 0 1946162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1947162922Sariff#endif 1948162922Sariff} 1949162922Sariff 1950162922Sariff/**************************************************************************** 1951162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1952162922Sariff * 1953162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1954162922Sariff * The RIRB engine must not be running when this function is called. 1955162922Sariff ****************************************************************************/ 1956162922Sariffstatic void 1957162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1958162922Sariff{ 1959162922Sariff uint8_t rirbsize; 1960162922Sariff uint64_t rirbpaddr; 1961162922Sariff 1962162922Sariff /* Setup the RIRB size. */ 1963162922Sariff switch (sc->rirb_size) { 1964162922Sariff case 256: 1965162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1966162922Sariff break; 1967162922Sariff case 16: 1968162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1969162922Sariff break; 1970162922Sariff case 2: 1971162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1972162922Sariff break; 1973162922Sariff default: 1974162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1975162922Sariff } 1976162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1977162922Sariff 1978162922Sariff /* Setup the RIRB Address in the hdac */ 1979162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1980162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1981162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1982162922Sariff 1983162922Sariff /* Setup the WP and RP */ 1984162922Sariff sc->rirb_rp = 0; 1985162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1986162922Sariff 1987182999Smav /* Setup the interrupt threshold */ 1988182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1989162922Sariff 1990182999Smav /* Enable Overrun and response received reporting */ 1991162922Sariff#if 0 1992182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1993182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1994162922Sariff#else 1995182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1996162922Sariff#endif 1997162922Sariff 1998169277Sariff#if 0 1999162922Sariff /* 2000162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 2001162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 2002162922Sariff * should be sufficient to do this only once as the rirb is purely 2003162922Sariff * read-only from now on. 2004162922Sariff */ 2005162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2006162922Sariff BUS_DMASYNC_PREREAD); 2007169277Sariff#endif 2008162922Sariff} 2009162922Sariff 2010162922Sariff/**************************************************************************** 2011162922Sariff * void hdac_corb_start(hdac_softc *) 2012162922Sariff * 2013162922Sariff * Startup the corb DMA engine 2014162922Sariff ****************************************************************************/ 2015162922Sariffstatic void 2016162922Sariffhdac_corb_start(struct hdac_softc *sc) 2017162922Sariff{ 2018162922Sariff uint32_t corbctl; 2019162922Sariff 2020162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 2021162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 2022162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 2023162922Sariff} 2024162922Sariff 2025162922Sariff/**************************************************************************** 2026162922Sariff * void hdac_rirb_start(hdac_softc *) 2027162922Sariff * 2028162922Sariff * Startup the rirb DMA engine 2029162922Sariff ****************************************************************************/ 2030162922Sariffstatic void 2031162922Sariffhdac_rirb_start(struct hdac_softc *sc) 2032162922Sariff{ 2033162922Sariff uint32_t rirbctl; 2034162922Sariff 2035162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 2036162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 2037162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 2038162922Sariff} 2039162922Sariff 2040162922Sariff 2041162922Sariff/**************************************************************************** 2042172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 2043162922Sariff * 2044172811Sariff * Scan the bus for available codecs, starting with num. 2045162922Sariff ****************************************************************************/ 2046162922Sariffstatic void 2047182999Smavhdac_scan_codecs(struct hdac_softc *sc) 2048162922Sariff{ 2049162922Sariff struct hdac_codec *codec; 2050162922Sariff int i; 2051162922Sariff uint16_t statests; 2052162922Sariff 2053162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 2054182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 2055162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 2056162922Sariff /* We have found a codec. */ 2057162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 2058162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 2059162922Sariff if (codec == NULL) { 2060162922Sariff device_printf(sc->dev, 2061162922Sariff "Unable to allocate memory for codec\n"); 2062162922Sariff continue; 2063162922Sariff } 2064164614Sariff codec->commands = NULL; 2065164614Sariff codec->responses_received = 0; 2066162922Sariff codec->verbs_sent = 0; 2067162922Sariff codec->sc = sc; 2068162922Sariff codec->cad = i; 2069162922Sariff sc->codecs[i] = codec; 2070182999Smav hdac_probe_codec(codec); 2071162922Sariff } 2072162922Sariff } 2073162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 2074163057Sariff /* bus_generic_attach(sc->dev); */ 2075162922Sariff} 2076162922Sariff 2077162922Sariff/**************************************************************************** 2078162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 2079162922Sariff * 2080162922Sariff * Probe a the given codec_id for available function groups. 2081162922Sariff ****************************************************************************/ 2082182999Smavstatic void 2083162922Sariffhdac_probe_codec(struct hdac_codec *codec) 2084162922Sariff{ 2085162922Sariff struct hdac_softc *sc = codec->sc; 2086162922Sariff uint32_t vendorid, revisionid, subnode; 2087162922Sariff int startnode; 2088162922Sariff int endnode; 2089162922Sariff int i; 2090162922Sariff nid_t cad = codec->cad; 2091162922Sariff 2092163057Sariff HDA_BOOTVERBOSE( 2093184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 2094162922Sariff ); 2095162922Sariff vendorid = hdac_command(sc, 2096162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 2097162922Sariff cad); 2098162922Sariff revisionid = hdac_command(sc, 2099162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 2100162922Sariff cad); 2101182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 2102182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 2103182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 2104182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 2105182999Smav 2106182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 2107182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 2108182999Smav " Probing aborted.\n", cad); 2109182999Smav return; 2110182999Smav } 2111182999Smav 2112184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 2113182999Smav cad, hdac_codec_name(codec)); 2114182999Smav HDA_BOOTVERBOSE( 2115184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 2116182999Smav hdac_codec_id(codec)); 2117182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 2118182999Smav codec->vendor_id); 2119182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 2120182999Smav codec->device_id); 2121182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 2122182999Smav codec->revision_id); 2123182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 2124182999Smav codec->stepping_id); 2125182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2126182999Smav sc->pci_subvendor); 2127182999Smav ); 2128162922Sariff subnode = hdac_command(sc, 2129162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 2130162922Sariff cad); 2131162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 2132162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 2133162922Sariff 2134183097Smav HDA_BOOTHVERBOSE( 2135182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 2136163057Sariff startnode, endnode); 2137162922Sariff ); 2138182999Smav 2139182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 2140182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 2141182999Smav if (codec->fgs == NULL) { 2142183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 2143182999Smav __func__); 2144182999Smav return; 2145162922Sariff } 2146162922Sariff 2147182999Smav for (i = startnode; i < endnode; i++) 2148182999Smav hdac_probe_function(codec, i); 2149182999Smav return; 2150162922Sariff} 2151162922Sariff 2152182999Smav/* 2153182999Smav * Probe codec function and add it to the list. 2154182999Smav */ 2155182999Smavstatic void 2156162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 2157162922Sariff{ 2158162922Sariff struct hdac_softc *sc = codec->sc; 2159182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 2160162922Sariff uint32_t fctgrptype; 2161182999Smav uint32_t res; 2162162922Sariff nid_t cad = codec->cad; 2163162922Sariff 2164162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 2165162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 2166162922Sariff 2167162922Sariff devinfo->nid = nid; 2168162965Sariff devinfo->node_type = fctgrptype; 2169162922Sariff devinfo->codec = codec; 2170162922Sariff 2171182999Smav res = hdac_command(sc, 2172182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2173162922Sariff 2174182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2175182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2176182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2177162922Sariff 2178182999Smav HDA_BOOTVERBOSE( 2179182999Smav device_printf(sc->dev, 2180182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2181182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2182182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2183182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2184182999Smav devinfo->nodecnt); 2185182999Smav ); 2186182999Smav 2187182999Smav if (devinfo->nodecnt > 0) 2188182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2189182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2190182999Smav M_NOWAIT | M_ZERO); 2191182999Smav else 2192182999Smav devinfo->widget = NULL; 2193182999Smav 2194182999Smav if (devinfo->widget == NULL) { 2195182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2196182999Smav devinfo->endnode = devinfo->startnode; 2197182999Smav devinfo->nodecnt = 0; 2198182999Smav return; 2199182999Smav } 2200182999Smav 2201182999Smav codec->num_fgs++; 2202162922Sariff} 2203162922Sariff 2204162922Sariffstatic void 2205162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2206162922Sariff{ 2207162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2208162922Sariff uint32_t res; 2209169277Sariff int i, j, max, ents, entnum; 2210162922Sariff nid_t cad = w->devinfo->codec->cad; 2211162922Sariff nid_t nid = w->nid; 2212169277Sariff nid_t cnid, addcnid, prevcnid; 2213162922Sariff 2214169277Sariff w->nconns = 0; 2215169277Sariff 2216162922Sariff res = hdac_command(sc, 2217162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2218162922Sariff 2219169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2220162922Sariff 2221169277Sariff if (ents < 1) 2222162922Sariff return; 2223162922Sariff 2224162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2225162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2226169277Sariff prevcnid = 0; 2227162922Sariff 2228169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2229169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2230169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2231169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2232169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2233169277Sariff 2234169277Sariff for (i = 0; i < ents; i += entnum) { 2235162922Sariff res = hdac_command(sc, 2236162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2237162922Sariff for (j = 0; j < entnum; j++) { 2238169277Sariff cnid = CONN_CNID(res, entnum, j); 2239169277Sariff if (cnid == 0) { 2240169277Sariff if (w->nconns < ents) 2241169277Sariff device_printf(sc->dev, 2242169277Sariff "%s: nid=%d WARNING: zero cnid " 2243169277Sariff "entnum=%d j=%d index=%d " 2244169277Sariff "entries=%d found=%d res=0x%08x\n", 2245169277Sariff __func__, nid, entnum, j, i, 2246169277Sariff ents, w->nconns, res); 2247169277Sariff else 2248169277Sariff goto getconns_out; 2249169277Sariff } 2250169277Sariff if (cnid < w->devinfo->startnode || 2251169277Sariff cnid >= w->devinfo->endnode) { 2252169277Sariff HDA_BOOTVERBOSE( 2253169277Sariff device_printf(sc->dev, 2254182999Smav "GHOST: nid=%d j=%d " 2255169277Sariff "entnum=%d index=%d res=0x%08x\n", 2256182999Smav nid, j, entnum, i, res); 2257169277Sariff ); 2258169277Sariff } 2259169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2260169277Sariff addcnid = cnid; 2261169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2262162922Sariff device_printf(sc->dev, 2263169277Sariff "%s: WARNING: Invalid child range " 2264169277Sariff "nid=%d index=%d j=%d entnum=%d " 2265169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2266169277Sariff __func__, nid, i, j, entnum, prevcnid, 2267169277Sariff cnid, res); 2268169277Sariff addcnid = cnid; 2269169277Sariff } else 2270169277Sariff addcnid = prevcnid + 1; 2271169277Sariff while (addcnid <= cnid) { 2272169277Sariff if (w->nconns > max) { 2273169277Sariff device_printf(sc->dev, 2274182999Smav "Adding %d (nid=%d): " 2275169277Sariff "Max connection reached! max=%d\n", 2276182999Smav addcnid, nid, max + 1); 2277169277Sariff goto getconns_out; 2278169277Sariff } 2279182999Smav w->connsenable[w->nconns] = 1; 2280169277Sariff w->conns[w->nconns++] = addcnid++; 2281162922Sariff } 2282169277Sariff prevcnid = cnid; 2283162922Sariff } 2284162922Sariff } 2285162922Sariff 2286169277Sariffgetconns_out: 2287169277Sariff return; 2288162922Sariff} 2289162922Sariff 2290162922Sariffstatic uint32_t 2291182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2292182999Smav{ 2293182999Smav char buf[256]; 2294182999Smav char *key, *value, *rest, *bad; 2295182999Smav int ival, i; 2296182999Smav 2297182999Smav strlcpy(buf, str, sizeof(buf)); 2298182999Smav rest = buf; 2299182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2300182999Smav value = strsep(&rest, " \t"); 2301182999Smav if (value == NULL) 2302182999Smav break; 2303182999Smav ival = strtol(value, &bad, 10); 2304182999Smav if (strcmp(key, "seq") == 0) { 2305182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2306182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2307182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2308182999Smav } else if (strcmp(key, "as") == 0) { 2309182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2310182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2311182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2312182999Smav } else if (strcmp(key, "misc") == 0) { 2313182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2314182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2315182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2316182999Smav } else if (strcmp(key, "color") == 0) { 2317182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2318182999Smav if (bad[0] == 0) { 2319182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2320182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2321182999Smav }; 2322182999Smav for (i = 0; i < 16; i++) { 2323182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2324182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2325182999Smav break; 2326182999Smav } 2327182999Smav } 2328182999Smav } else if (strcmp(key, "ctype") == 0) { 2329182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2330182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2331182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2332182999Smav } else if (strcmp(key, "device") == 0) { 2333182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2334182999Smav if (bad[0] == 0) { 2335182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2336182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2337182999Smav continue; 2338182999Smav }; 2339182999Smav for (i = 0; i < 16; i++) { 2340182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2341182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2342182999Smav break; 2343182999Smav } 2344182999Smav } 2345182999Smav } else if (strcmp(key, "loc") == 0) { 2346182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2347182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2348182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2349182999Smav } else if (strcmp(key, "conn") == 0) { 2350182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2351182999Smav if (bad[0] == 0) { 2352182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2353182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2354182999Smav continue; 2355182999Smav }; 2356182999Smav for (i = 0; i < 4; i++) { 2357182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2358182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2359182999Smav break; 2360182999Smav } 2361182999Smav } 2362182999Smav } 2363182999Smav } 2364182999Smav return (config); 2365182999Smav} 2366182999Smav 2367182999Smavstatic uint32_t 2368162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2369162922Sariff{ 2370162922Sariff struct hdac_softc *sc; 2371166965Sariff uint32_t config, orig, id; 2372162922Sariff nid_t cad, nid; 2373182999Smav char buf[32]; 2374182999Smav const char *res = NULL, *patch = NULL; 2375162922Sariff 2376162922Sariff sc = w->devinfo->codec->sc; 2377162922Sariff cad = w->devinfo->codec->cad; 2378162922Sariff nid = w->nid; 2379182999Smav id = hdac_codec_id(w->devinfo->codec); 2380162922Sariff 2381162922Sariff config = hdac_command(sc, 2382162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2383162922Sariff cad); 2384166965Sariff orig = config; 2385166965Sariff 2386182999Smav HDA_BOOTVERBOSE( 2387182999Smav hdac_dump_pin_config(w, orig); 2388182999Smav ); 2389182999Smav 2390182999Smav /* XXX: Old patches require complete review. 2391182999Smav * Now they may create more problem then solve due to 2392182999Smav * incorrect associations. 2393162965Sariff */ 2394165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2395165281Sariff switch (nid) { 2396165281Sariff case 26: 2397165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2398165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2399165281Sariff break; 2400165281Sariff case 27: 2401165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2402165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2403165281Sariff break; 2404167610Sariff default: 2405167610Sariff break; 2406165281Sariff } 2407165281Sariff } else if (id == HDA_CODEC_ALC880 && 2408162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2409162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2410162922Sariff /* 2411162965Sariff * Super broken BIOS 2412162922Sariff */ 2413162922Sariff switch (nid) { 2414162922Sariff case 24: /* MIC1 */ 2415162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2416162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2417162922Sariff break; 2418162922Sariff case 25: /* XXX MIC2 */ 2419162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2420162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2421162922Sariff break; 2422162922Sariff case 26: /* LINE1 */ 2423162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2424162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2425162922Sariff break; 2426162922Sariff case 27: /* XXX LINE2 */ 2427162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2428162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2429162922Sariff break; 2430162922Sariff case 28: /* CD */ 2431162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2432162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2433162922Sariff break; 2434162922Sariff } 2435166965Sariff } else if (id == HDA_CODEC_ALC883 && 2436172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2437172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2438166965Sariff switch (nid) { 2439166965Sariff case 25: 2440166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2441166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2442166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2443166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2444166965Sariff break; 2445169277Sariff case 28: 2446169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2447169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2448169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2449169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2450169277Sariff break; 2451166965Sariff } 2452186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2453166965Sariff HP_V3000_SUBVENDOR) { 2454166965Sariff switch (nid) { 2455166965Sariff case 18: 2456166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2457166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2458166965Sariff break; 2459166965Sariff case 20: 2460166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2461166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2462166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2463166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2464166965Sariff break; 2465167454Sariff case 21: 2466167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2467167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2468167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2469167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2470167454Sariff break; 2471166965Sariff } 2472186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2473169277Sariff HP_DV5000_SUBVENDOR) { 2474169277Sariff switch (nid) { 2475169277Sariff case 20: 2476169277Sariff case 21: 2477169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2478169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2479169277Sariff break; 2480169277Sariff } 2481169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2482169277Sariff ASUS_W6F_SUBVENDOR) { 2483169277Sariff switch (nid) { 2484169277Sariff case 11: 2485169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2486169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2487169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2488169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2489169277Sariff break; 2490178324Sariff case 12: 2491178324Sariff case 14: 2492178324Sariff case 16: 2493178324Sariff case 31: 2494178324Sariff case 32: 2495178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2496178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2497178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2498178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2499178324Sariff break; 2500169277Sariff case 15: 2501169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2502169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2503169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2504169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2505169277Sariff break; 2506169277Sariff } 2507169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2508169277Sariff UNIWILL_9075_SUBVENDOR) { 2509169277Sariff switch (nid) { 2510169277Sariff case 15: 2511169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2512169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2513169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2514169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2515169277Sariff break; 2516169277Sariff } 2517182999Smav } 2518182999Smav 2519182999Smav /* New patches */ 2520182999Smav if (id == HDA_CODEC_AD1986A && 2521171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2522190630Smav sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR || 2523190630Smav sc->pci_subvendor == ASUS_P5PL2_SUBVENDOR)) { 2524169277Sariff switch (nid) { 2525190630Smav case 26: /* Headphones with redirection */ 2526190630Smav patch = "as=1 seq=15"; 2527190630Smav break; 2528190630Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 2529182999Smav patch = "device=Line-in as=8 seq=1"; 2530169277Sariff break; 2531190630Smav case 29: /* Can't use this as input, as the only available mic 2532190630Smav * preamplifier is busy by front panel mic (nid 31). 2533190630Smav * If you want to use this rear connector as mic input, 2534190630Smav * you have to disable the front panel one. */ 2535190630Smav patch = "as=0"; 2536169277Sariff break; 2537182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2538182999Smav patch = "as=8 seq=3"; 2539169277Sariff break; 2540182999Smav case 32: 2541182999Smav patch = "as=8 seq=4"; 2542182999Smav break; 2543182999Smav case 34: 2544182999Smav patch = "as=8 seq=5"; 2545182999Smav break; 2546182999Smav case 36: 2547182999Smav patch = "as=8 seq=6"; 2548182999Smav break; 2549169277Sariff } 2550182999Smav } else if (id == HDA_CODEC_ALC260 && 2551182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2552182999Smav switch (nid) { 2553182999Smav case 16: 2554182999Smav patch = "seq=15 device=Headphones"; 2555182999Smav break; 2556182999Smav } 2557189879Smav } else if (id == HDA_CODEC_ALC268) { 2558189879Smav if (sc->pci_subvendor == ACER_T5320_SUBVENDOR) { 2559174578Sariff switch (nid) { 2560189879Smav case 20: /* Headphones Jack */ 2561189879Smav patch = "as=1 seq=15"; 2562174578Sariff break; 2563174578Sariff } 2564189879Smav } 2565162922Sariff } 2566162922Sariff 2567182999Smav if (patch != NULL) 2568182999Smav config = hdac_widget_pin_patch(config, patch); 2569182999Smav 2570182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2571182999Smav if (resource_string_value(device_get_name(sc->dev), 2572182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2573182999Smav if (strncmp(res, "0x", 2) == 0) { 2574182999Smav config = strtol(res + 2, NULL, 16); 2575182999Smav } else { 2576182999Smav config = hdac_widget_pin_patch(config, res); 2577182999Smav } 2578182999Smav } 2579182999Smav 2580166965Sariff HDA_BOOTVERBOSE( 2581166965Sariff if (config != orig) 2582166965Sariff device_printf(sc->dev, 2583182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2584166965Sariff nid, orig, config); 2585166965Sariff ); 2586166965Sariff 2587162922Sariff return (config); 2588162922Sariff} 2589162922Sariff 2590166965Sariffstatic uint32_t 2591166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2592166965Sariff{ 2593166965Sariff struct hdac_softc *sc; 2594166965Sariff uint32_t caps, orig, id; 2595166965Sariff nid_t cad, nid; 2596166965Sariff 2597166965Sariff sc = w->devinfo->codec->sc; 2598166965Sariff cad = w->devinfo->codec->cad; 2599166965Sariff nid = w->nid; 2600182999Smav id = hdac_codec_id(w->devinfo->codec); 2601166965Sariff 2602166965Sariff caps = hdac_command(sc, 2603166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2604166965Sariff orig = caps; 2605166965Sariff 2606166965Sariff HDA_BOOTVERBOSE( 2607166965Sariff if (caps != orig) 2608166965Sariff device_printf(sc->dev, 2609182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2610166965Sariff nid, orig, caps); 2611166965Sariff ); 2612166965Sariff 2613166965Sariff return (caps); 2614166965Sariff} 2615166965Sariff 2616162922Sariffstatic void 2617162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2618162922Sariff{ 2619162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2620162922Sariff uint32_t config, pincap; 2621186912Smav const char *devstr; 2622162922Sariff nid_t cad = w->devinfo->codec->cad; 2623162922Sariff nid_t nid = w->nid; 2624186912Smav int conn, color; 2625162922Sariff 2626162922Sariff config = hdac_widget_pin_getconfig(w); 2627162922Sariff w->wclass.pin.config = config; 2628162922Sariff 2629166965Sariff pincap = hdac_widget_pin_getcaps(w); 2630162922Sariff w->wclass.pin.cap = pincap; 2631162922Sariff 2632162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2633182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2634162922Sariff 2635162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2636162922Sariff w->param.eapdbtl = hdac_command(sc, 2637162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2638162922Sariff w->param.eapdbtl &= 0x7; 2639162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2640162922Sariff } else 2641162965Sariff w->param.eapdbtl = HDAC_INVALID; 2642162922Sariff 2643182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2644182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2645162922Sariff 2646186912Smav conn = (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2647186912Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT; 2648186912Smav color = (config & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> 2649186912Smav HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT; 2650162922Sariff 2651162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2652162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2653162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2654186912Smav if (conn == 0 && color != 0 && color != 15) { 2655186912Smav strlcat(w->name, HDA_COLORS[color], sizeof(w->name)); 2656186912Smav strlcat(w->name, " ", sizeof(w->name)); 2657186912Smav } 2658186912Smav strlcat(w->name, HDA_CONNS[conn], sizeof(w->name)); 2659162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2660162922Sariff} 2661162922Sariff 2662182999Smavstatic uint32_t 2663182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2664182999Smav{ 2665182999Smav struct hdac_softc *sc; 2666182999Smav uint32_t caps, orig, id; 2667182999Smav nid_t cad, nid, beeper = -1; 2668182999Smav 2669182999Smav sc = w->devinfo->codec->sc; 2670182999Smav cad = w->devinfo->codec->cad; 2671182999Smav nid = w->nid; 2672182999Smav id = hdac_codec_id(w->devinfo->codec); 2673182999Smav 2674182999Smav caps = hdac_command(sc, 2675182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2676182999Smav cad); 2677182999Smav orig = caps; 2678182999Smav 2679182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2680182999Smav alone. Also most of BIOSes does not declare beeper pin. 2681182999Smav Change beeper pin node type to beeper to help parser. */ 2682182999Smav *waspin = 0; 2683182999Smav switch (id) { 2684187721Smav case HDA_CODEC_AD1882: 2685187721Smav case HDA_CODEC_AD1883: 2686187721Smav case HDA_CODEC_AD1984: 2687187721Smav case HDA_CODEC_AD1984A: 2688187721Smav case HDA_CODEC_AD1984B: 2689187721Smav case HDA_CODEC_AD1987: 2690182999Smav case HDA_CODEC_AD1988: 2691182999Smav case HDA_CODEC_AD1988B: 2692187721Smav case HDA_CODEC_AD1989B: 2693182999Smav beeper = 26; 2694182999Smav break; 2695182999Smav case HDA_CODEC_ALC260: 2696182999Smav beeper = 23; 2697182999Smav break; 2698182999Smav case HDA_CODEC_ALC262: 2699182999Smav case HDA_CODEC_ALC268: 2700182999Smav case HDA_CODEC_ALC880: 2701182999Smav case HDA_CODEC_ALC882: 2702182999Smav case HDA_CODEC_ALC883: 2703182999Smav case HDA_CODEC_ALC885: 2704182999Smav case HDA_CODEC_ALC888: 2705182999Smav case HDA_CODEC_ALC889: 2706182999Smav beeper = 29; 2707182999Smav break; 2708182999Smav } 2709182999Smav if (nid == beeper) { 2710182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2711182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2712182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2713182999Smav *waspin = 1; 2714182999Smav } 2715182999Smav 2716182999Smav HDA_BOOTVERBOSE( 2717182999Smav if (caps != orig) { 2718182999Smav device_printf(sc->dev, 2719182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2720182999Smav nid, orig, caps); 2721182999Smav } 2722182999Smav ); 2723182999Smav 2724182999Smav return (caps); 2725182999Smav} 2726182999Smav 2727162922Sariffstatic void 2728162922Sariffhdac_widget_parse(struct hdac_widget *w) 2729162922Sariff{ 2730162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2731162922Sariff uint32_t wcap, cap; 2732162922Sariff char *typestr; 2733162922Sariff nid_t cad = w->devinfo->codec->cad; 2734162922Sariff nid_t nid = w->nid; 2735162922Sariff 2736182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2737182999Smav 2738162922Sariff w->param.widget_cap = wcap; 2739162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2740162922Sariff 2741162922Sariff switch (w->type) { 2742162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2743162922Sariff typestr = "audio output"; 2744162922Sariff break; 2745162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2746162922Sariff typestr = "audio input"; 2747162922Sariff break; 2748162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2749162922Sariff typestr = "audio mixer"; 2750162922Sariff break; 2751162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2752162922Sariff typestr = "audio selector"; 2753162922Sariff break; 2754162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2755162922Sariff typestr = "pin"; 2756162922Sariff break; 2757162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2758162922Sariff typestr = "power widget"; 2759162922Sariff break; 2760162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2761162922Sariff typestr = "volume widget"; 2762162922Sariff break; 2763162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2764162922Sariff typestr = "beep widget"; 2765162922Sariff break; 2766162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2767162922Sariff typestr = "vendor widget"; 2768162922Sariff break; 2769162922Sariff default: 2770162922Sariff typestr = "unknown type"; 2771162922Sariff break; 2772162922Sariff } 2773162922Sariff 2774162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2775162922Sariff 2776162922Sariff hdac_widget_connection_parse(w); 2777162922Sariff 2778162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2779162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2780162922Sariff w->param.outamp_cap = 2781162922Sariff hdac_command(sc, 2782162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2783162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2784162922Sariff else 2785162922Sariff w->param.outamp_cap = 2786162922Sariff w->devinfo->function.audio.outamp_cap; 2787162922Sariff } else 2788162922Sariff w->param.outamp_cap = 0; 2789162922Sariff 2790162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2791162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2792162922Sariff w->param.inamp_cap = 2793162922Sariff hdac_command(sc, 2794162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2795162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2796162922Sariff else 2797162922Sariff w->param.inamp_cap = 2798162922Sariff w->devinfo->function.audio.inamp_cap; 2799162922Sariff } else 2800162922Sariff w->param.inamp_cap = 0; 2801162922Sariff 2802162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2803162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2804162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2805162922Sariff cap = hdac_command(sc, 2806162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2807162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2808162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2809162922Sariff w->devinfo->function.audio.supp_stream_formats; 2810162922Sariff cap = hdac_command(sc, 2811162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2812162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2813162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2814162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2815162922Sariff } else { 2816162922Sariff w->param.supp_stream_formats = 2817162922Sariff w->devinfo->function.audio.supp_stream_formats; 2818162922Sariff w->param.supp_pcm_size_rate = 2819162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2820162922Sariff } 2821162922Sariff } else { 2822162922Sariff w->param.supp_stream_formats = 0; 2823162922Sariff w->param.supp_pcm_size_rate = 0; 2824162922Sariff } 2825162922Sariff 2826162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2827162922Sariff hdac_widget_pin_parse(w); 2828162922Sariff} 2829162922Sariff 2830162922Sariffstatic struct hdac_widget * 2831162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2832162922Sariff{ 2833162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2834162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2835162922Sariff return (NULL); 2836162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2837162922Sariff} 2838162922Sariff 2839164614Sariffstatic __inline int 2840164614Sariffhda_poll_channel(struct hdac_chan *ch) 2841164614Sariff{ 2842164614Sariff uint32_t sz, delta; 2843164614Sariff volatile uint32_t ptr; 2844164614Sariff 2845171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2846164614Sariff return (0); 2847164614Sariff 2848164614Sariff sz = ch->blksz * ch->blkcnt; 2849169277Sariff if (ch->dmapos != NULL) 2850169277Sariff ptr = *(ch->dmapos); 2851169277Sariff else 2852169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2853169277Sariff ch->off + HDAC_SDLPIB); 2854164614Sariff ch->ptr = ptr; 2855164614Sariff ptr %= sz; 2856164614Sariff ptr &= ~(ch->blksz - 1); 2857164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2858164614Sariff 2859164614Sariff if (delta < ch->blksz) 2860164614Sariff return (0); 2861164614Sariff 2862164614Sariff ch->prevptr = ptr; 2863164614Sariff 2864164614Sariff return (1); 2865164614Sariff} 2866164614Sariff 2867162922Sariffstatic void 2868164614Sariffhda_poll_callback(void *arg) 2869164614Sariff{ 2870164614Sariff struct hdac_softc *sc = arg; 2871171141Sariff uint32_t trigger; 2872182999Smav int i, active = 0; 2873164614Sariff 2874164614Sariff if (sc == NULL) 2875164614Sariff return; 2876164614Sariff 2877164614Sariff hdac_lock(sc); 2878182999Smav if (sc->polling == 0) { 2879164614Sariff hdac_unlock(sc); 2880164614Sariff return; 2881164614Sariff } 2882164614Sariff 2883171141Sariff trigger = 0; 2884182999Smav for (i = 0; i < sc->num_chans; i++) { 2885182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2886182999Smav continue; 2887182999Smav active = 1; 2888182999Smav if (hda_poll_channel(&sc->chans[i])) 2889182999Smav trigger |= (1 << i); 2890182999Smav } 2891164614Sariff 2892164614Sariff /* XXX */ 2893182999Smav if (active) 2894182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2895182999Smav hda_poll_callback, sc); 2896164614Sariff 2897164614Sariff hdac_unlock(sc); 2898164614Sariff 2899182999Smav for (i = 0; i < sc->num_chans; i++) { 2900182999Smav if (trigger & (1 << i)) 2901182999Smav chn_intr(sc->chans[i].c); 2902182999Smav } 2903164614Sariff} 2904164614Sariff 2905164614Sariffstatic int 2906164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2907164614Sariff{ 2908164614Sariff struct hdac_rirb *rirb_base, *rirb; 2909164614Sariff struct hdac_codec *codec; 2910164614Sariff struct hdac_command_list *commands; 2911164614Sariff nid_t cad; 2912164614Sariff uint32_t resp; 2913164614Sariff uint8_t rirbwp; 2914171141Sariff int ret; 2915164614Sariff 2916164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2917164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2918169277Sariff#if 0 2919164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2920164614Sariff BUS_DMASYNC_POSTREAD); 2921169277Sariff#endif 2922164614Sariff 2923171141Sariff ret = 0; 2924171141Sariff 2925164614Sariff while (sc->rirb_rp != rirbwp) { 2926164614Sariff sc->rirb_rp++; 2927164614Sariff sc->rirb_rp %= sc->rirb_size; 2928164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2929164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2930164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2931164614Sariff sc->codecs[cad] == NULL) 2932164614Sariff continue; 2933164614Sariff resp = rirb->response; 2934164614Sariff codec = sc->codecs[cad]; 2935164614Sariff commands = codec->commands; 2936164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2937164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2938164614Sariff ((resp >> 26) & 0xffff); 2939164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2940164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2941164614Sariff codec->responses_received < commands->num_commands) 2942164614Sariff commands->responses[codec->responses_received++] = 2943164614Sariff resp; 2944164614Sariff ret++; 2945164614Sariff } 2946164614Sariff 2947164614Sariff return (ret); 2948164614Sariff} 2949164614Sariff 2950164614Sariffstatic int 2951164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2952164614Sariff{ 2953164614Sariff nid_t cad; 2954164614Sariff uint32_t tag; 2955164614Sariff int ret = 0; 2956164614Sariff 2957164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2958164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2959164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2960164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2961164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2962164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2963164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2964164614Sariff ret++; 2965164614Sariff } 2966164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2967164614Sariff } 2968164614Sariff 2969164614Sariff return (ret); 2970164614Sariff} 2971164614Sariff 2972164614Sariffstatic void 2973164614Sariffhdac_poll_callback(void *arg) 2974164614Sariff{ 2975164614Sariff struct hdac_softc *sc = arg; 2976164614Sariff if (sc == NULL) 2977164614Sariff return; 2978166796Sariff 2979164614Sariff hdac_lock(sc); 2980169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2981164614Sariff hdac_unlock(sc); 2982164614Sariff return; 2983164614Sariff } 2984171141Sariff if (hdac_rirb_flush(sc) != 0) 2985171141Sariff hdac_unsolq_flush(sc); 2986169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2987164614Sariff hdac_unlock(sc); 2988164614Sariff} 2989164614Sariff 2990164614Sariffstatic void 2991182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2992182999Smav{ 2993182999Smav int i, pollticks, min = 1000000; 2994182999Smav struct hdac_chan *ch; 2995182999Smav 2996182999Smav for (i = 0; i < sc->num_chans; i++) { 2997182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2998182999Smav continue; 2999182999Smav ch = &sc->chans[i]; 3000182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 3001193640Sariff ((uint64_t)sndbuf_getalign(ch->b) * sndbuf_getspd(ch->b)); 3002182999Smav pollticks >>= 1; 3003182999Smav if (pollticks > hz) 3004182999Smav pollticks = hz; 3005182999Smav if (pollticks < 1) { 3006182999Smav HDA_BOOTVERBOSE( 3007182999Smav device_printf(sc->dev, 3008182999Smav "%s: pollticks=%d < 1 !\n", 3009182999Smav __func__, pollticks); 3010182999Smav ); 3011182999Smav pollticks = 1; 3012182999Smav } 3013182999Smav if (min > pollticks) 3014182999Smav min = pollticks; 3015182999Smav } 3016182999Smav HDA_BOOTVERBOSE( 3017182999Smav device_printf(sc->dev, 3018182999Smav "%s: pollticks %d -> %d\n", 3019182999Smav __func__, sc->poll_ticks, min); 3020182999Smav ); 3021182999Smav sc->poll_ticks = min; 3022182999Smav if (min == 1000000) 3023182999Smav callout_stop(&sc->poll_hda); 3024182999Smav else 3025182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 3026182999Smav} 3027182999Smav 3028182999Smavstatic void 3029162922Sariffhdac_stream_stop(struct hdac_chan *ch) 3030162922Sariff{ 3031162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3032162922Sariff uint32_t ctl; 3033162922Sariff 3034162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3035162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3036162922Sariff HDAC_SDCTL_RUN); 3037162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3038162922Sariff 3039171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 3040164614Sariff 3041182999Smav if (sc->polling != 0) 3042182999Smav hdac_poll_reinit(sc); 3043164614Sariff 3044182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3045182999Smav ctl &= ~(1 << (ch->off >> 5)); 3046182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3047162922Sariff} 3048162922Sariff 3049162922Sariffstatic void 3050162922Sariffhdac_stream_start(struct hdac_chan *ch) 3051162922Sariff{ 3052162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3053162922Sariff uint32_t ctl; 3054162922Sariff 3055182999Smav ch->flags |= HDAC_CHN_RUNNING; 3056162922Sariff 3057182999Smav if (sc->polling != 0) 3058182999Smav hdac_poll_reinit(sc); 3059182999Smav 3060182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3061182999Smav ctl |= 1 << (ch->off >> 5); 3062182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3063182999Smav 3064182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3065182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3066182999Smav HDAC_SDCTL_RUN; 3067162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3068162922Sariff} 3069162922Sariff 3070162922Sariffstatic void 3071162922Sariffhdac_stream_reset(struct hdac_chan *ch) 3072162922Sariff{ 3073162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3074162922Sariff int timeout = 1000; 3075162922Sariff int to = timeout; 3076162922Sariff uint32_t ctl; 3077162922Sariff 3078162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3079162922Sariff ctl |= HDAC_SDCTL_SRST; 3080162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3081162922Sariff do { 3082162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3083162922Sariff if (ctl & HDAC_SDCTL_SRST) 3084162922Sariff break; 3085162922Sariff DELAY(10); 3086162922Sariff } while (--to); 3087162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 3088162922Sariff device_printf(sc->dev, "timeout in reset\n"); 3089162922Sariff } 3090162922Sariff ctl &= ~HDAC_SDCTL_SRST; 3091162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3092162922Sariff to = timeout; 3093162922Sariff do { 3094162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3095162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 3096162922Sariff break; 3097162922Sariff DELAY(10); 3098162922Sariff } while (--to); 3099163057Sariff if (ctl & HDAC_SDCTL_SRST) 3100162922Sariff device_printf(sc->dev, "can't reset!\n"); 3101162922Sariff} 3102162922Sariff 3103162922Sariffstatic void 3104162922Sariffhdac_stream_setid(struct hdac_chan *ch) 3105162922Sariff{ 3106162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3107162922Sariff uint32_t ctl; 3108162922Sariff 3109162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 3110162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 3111162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 3112162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 3113162922Sariff} 3114162922Sariff 3115162922Sariffstatic void 3116162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 3117162922Sariff{ 3118162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3119164614Sariff struct hdac_bdle *bdle; 3120162922Sariff uint64_t addr; 3121164614Sariff uint32_t blksz, blkcnt; 3122162922Sariff int i; 3123162922Sariff 3124162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 3125164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 3126162922Sariff 3127182999Smav blksz = ch->blksz; 3128182999Smav blkcnt = ch->blkcnt; 3129164614Sariff 3130164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 3131162922Sariff bdle->addrl = (uint32_t)addr; 3132162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 3133164614Sariff bdle->len = blksz; 3134182999Smav bdle->ioc = 1; 3135164614Sariff addr += blksz; 3136162922Sariff } 3137162922Sariff 3138164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 3139164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 3140162922Sariff addr = ch->bdl_dma.dma_paddr; 3141162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 3142162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 3143169277Sariff if (ch->dmapos != NULL && 3144169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 3145169277Sariff addr = sc->pos_dma.dma_paddr; 3146169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 3147169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 3148169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 3149169277Sariff } 3150162922Sariff} 3151162922Sariff 3152162922Sariffstatic int 3153162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 3154162922Sariff{ 3155162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3156162922Sariff int rc; 3157162922Sariff 3158162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 3159162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 3160162922Sariff if (rc) { 3161162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 3162162922Sariff return (rc); 3163162922Sariff } 3164162922Sariff 3165162922Sariff return (0); 3166162922Sariff} 3167162922Sariff 3168162922Sariffstatic void 3169162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 3170162922Sariff int index, int lmute, int rmute, 3171162922Sariff int left, int right, int dir) 3172162922Sariff{ 3173162922Sariff uint16_t v = 0; 3174162922Sariff 3175162922Sariff if (sc == NULL) 3176162922Sariff return; 3177162922Sariff 3178162922Sariff if (left != right || lmute != rmute) { 3179162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 3180162922Sariff (lmute << 7) | left; 3181162922Sariff hdac_command(sc, 3182164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3183162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 3184162922Sariff (rmute << 7) | right; 3185162922Sariff } else 3186162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 3187162922Sariff (lmute << 7) | left; 3188162922Sariff 3189162922Sariff hdac_command(sc, 3190162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3191162922Sariff} 3192162922Sariff 3193162922Sariffstatic void 3194162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3195162922Sariff int left, int right) 3196162922Sariff{ 3197162922Sariff struct hdac_softc *sc; 3198162922Sariff nid_t nid, cad; 3199162922Sariff int lmute, rmute; 3200162922Sariff 3201162922Sariff sc = ctl->widget->devinfo->codec->sc; 3202162922Sariff cad = ctl->widget->devinfo->codec->cad; 3203162922Sariff nid = ctl->widget->nid; 3204162922Sariff 3205182999Smav /* Save new values if valid. */ 3206182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3207182999Smav ctl->muted = mute; 3208182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3209182999Smav ctl->left = left; 3210182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3211182999Smav ctl->right = right; 3212182999Smav /* Prepare effective values */ 3213182999Smav if (ctl->forcemute) { 3214182999Smav lmute = 1; 3215182999Smav rmute = 1; 3216182999Smav left = 0; 3217182999Smav right = 0; 3218182999Smav } else { 3219162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3220162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3221182999Smav left = ctl->left; 3222182999Smav right = ctl->right; 3223162922Sariff } 3224182999Smav /* Apply effective values */ 3225162922Sariff if (ctl->dir & HDA_CTL_OUT) 3226162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3227162922Sariff lmute, rmute, left, right, 0); 3228162922Sariff if (ctl->dir & HDA_CTL_IN) 3229182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3230162922Sariff lmute, rmute, left, right, 1); 3231162922Sariff} 3232162922Sariff 3233162922Sariffstatic void 3234162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3235162922Sariff{ 3236162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3237162922Sariff return; 3238162922Sariff hdac_command(w->devinfo->codec->sc, 3239162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3240162922Sariff w->nid, index), w->devinfo->codec->cad); 3241162922Sariff w->selconn = index; 3242162922Sariff} 3243162922Sariff 3244162922Sariff 3245162922Sariff/**************************************************************************** 3246162922Sariff * uint32_t hdac_command_sendone_internal 3247162922Sariff * 3248162922Sariff * Wrapper function that sends only one command to a given codec 3249162922Sariff ****************************************************************************/ 3250162922Sariffstatic uint32_t 3251162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3252162922Sariff{ 3253162922Sariff struct hdac_command_list cl; 3254162965Sariff uint32_t response = HDAC_INVALID; 3255162922Sariff 3256163057Sariff if (!hdac_lockowned(sc)) 3257162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3258162922Sariff cl.num_commands = 1; 3259162922Sariff cl.verbs = &verb; 3260162922Sariff cl.responses = &response; 3261162922Sariff 3262162922Sariff hdac_command_send_internal(sc, &cl, cad); 3263162922Sariff 3264162922Sariff return (response); 3265162922Sariff} 3266162922Sariff 3267162922Sariff/**************************************************************************** 3268162922Sariff * hdac_command_send_internal 3269162922Sariff * 3270162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3271162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3272162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3273162922Sariff * if any. 3274162922Sariff ****************************************************************************/ 3275162922Sariffstatic void 3276162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3277162922Sariff struct hdac_command_list *commands, nid_t cad) 3278162922Sariff{ 3279162922Sariff struct hdac_codec *codec; 3280162922Sariff int corbrp; 3281162922Sariff uint32_t *corb; 3282162922Sariff int timeout; 3283162922Sariff int retry = 10; 3284164614Sariff struct hdac_rirb *rirb_base; 3285162922Sariff 3286164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3287164614Sariff commands->num_commands < 1) 3288162922Sariff return; 3289162922Sariff 3290162922Sariff codec = sc->codecs[cad]; 3291162922Sariff codec->commands = commands; 3292162922Sariff codec->responses_received = 0; 3293162922Sariff codec->verbs_sent = 0; 3294162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3295162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3296162922Sariff 3297162922Sariff do { 3298162922Sariff if (codec->verbs_sent != commands->num_commands) { 3299162922Sariff /* Queue as many verbs as possible */ 3300162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3301169277Sariff#if 0 3302162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3303162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3304169277Sariff#endif 3305162922Sariff while (codec->verbs_sent != commands->num_commands && 3306162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3307162922Sariff sc->corb_wp++; 3308162922Sariff sc->corb_wp %= sc->corb_size; 3309162922Sariff corb[sc->corb_wp] = 3310162922Sariff commands->verbs[codec->verbs_sent++]; 3311162922Sariff } 3312162922Sariff 3313162922Sariff /* Send the verbs to the codecs */ 3314169277Sariff#if 0 3315162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3316162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3317169277Sariff#endif 3318162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3319162922Sariff } 3320162922Sariff 3321162922Sariff timeout = 1000; 3322164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3323162922Sariff DELAY(10); 3324162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3325164614Sariff codec->responses_received != commands->num_commands) && --retry); 3326162922Sariff 3327162922Sariff if (retry == 0) 3328162922Sariff device_printf(sc->dev, 3329164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3330164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3331164614Sariff codec->responses_received); 3332162922Sariff 3333164614Sariff codec->commands = NULL; 3334164614Sariff codec->responses_received = 0; 3335162922Sariff codec->verbs_sent = 0; 3336162922Sariff 3337164614Sariff hdac_unsolq_flush(sc); 3338162922Sariff} 3339162922Sariff 3340162922Sariff 3341162922Sariff/**************************************************************************** 3342162922Sariff * Device Methods 3343162922Sariff ****************************************************************************/ 3344162922Sariff 3345162922Sariff/**************************************************************************** 3346162922Sariff * int hdac_probe(device_t) 3347162922Sariff * 3348162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3349162922Sariff * match using the subclass of the device. 3350162922Sariff ****************************************************************************/ 3351162922Sariffstatic int 3352162922Sariffhdac_probe(device_t dev) 3353162922Sariff{ 3354162922Sariff int i, result; 3355163257Sariff uint32_t model; 3356163257Sariff uint16_t class, subclass; 3357162922Sariff char desc[64]; 3358162922Sariff 3359162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3360162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3361162922Sariff class = pci_get_class(dev); 3362162922Sariff subclass = pci_get_subclass(dev); 3363162922Sariff 3364162922Sariff bzero(desc, sizeof(desc)); 3365162922Sariff result = ENXIO; 3366162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3367162922Sariff if (hdac_devices[i].model == model) { 3368162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3369162922Sariff result = BUS_PROBE_DEFAULT; 3370162922Sariff break; 3371162922Sariff } 3372163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3373162922Sariff class == PCIC_MULTIMEDIA && 3374162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3375162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3376162922Sariff result = BUS_PROBE_GENERIC; 3377162922Sariff break; 3378162922Sariff } 3379162922Sariff } 3380162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3381162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3382162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3383162922Sariff result = BUS_PROBE_GENERIC; 3384162922Sariff } 3385162922Sariff if (result != ENXIO) { 3386162922Sariff strlcat(desc, " High Definition Audio Controller", 3387162922Sariff sizeof(desc)); 3388162922Sariff device_set_desc_copy(dev, desc); 3389162922Sariff } 3390162922Sariff 3391162922Sariff return (result); 3392162922Sariff} 3393162922Sariff 3394162922Sariffstatic void * 3395162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3396162922Sariff struct pcm_channel *c, int dir) 3397162922Sariff{ 3398182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3399182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3400162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3401162922Sariff struct hdac_chan *ch; 3402182999Smav int i, ord = 0, chid; 3403162922Sariff 3404162922Sariff hdac_lock(sc); 3405182999Smav 3406182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3407182999Smav ch = &sc->chans[chid]; 3408182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3409182999Smav if (ch->dir == sc->chans[i].dir) 3410182999Smav ord++; 3411182999Smav } 3412162922Sariff if (dir == PCMDIR_PLAY) { 3413182999Smav ch->off = (sc->num_iss + ord) << 5; 3414162922Sariff } else { 3415182999Smav ch->off = ord << 5; 3416162922Sariff } 3417182999Smav 3418162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3419162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3420162922Sariff ch->pcmrates[0] = 48000; 3421162922Sariff ch->pcmrates[1] = 0; 3422162922Sariff } 3423169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3424169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3425169277Sariff (sc->streamcnt * 8)); 3426169277Sariff else 3427169277Sariff ch->dmapos = NULL; 3428169277Sariff ch->sid = ++sc->streamcnt; 3429169277Sariff ch->dir = dir; 3430162922Sariff ch->b = b; 3431162922Sariff ch->c = c; 3432182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3433182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3434162922Sariff hdac_unlock(sc); 3435162922Sariff 3436162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3437162922Sariff ch->blkcnt = 0; 3438162922Sariff return (NULL); 3439162922Sariff } 3440162922Sariff 3441169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3442171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3443182999Smav pdevinfo->chan_size) != 0) 3444162922Sariff return (NULL); 3445162922Sariff 3446162922Sariff return (ch); 3447162922Sariff} 3448162922Sariff 3449162922Sariffstatic int 3450162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3451162922Sariff{ 3452162922Sariff struct hdac_chan *ch = data; 3453162922Sariff int i; 3454162922Sariff 3455162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3456162922Sariff if (format == ch->caps.fmtlist[i]) { 3457162922Sariff ch->fmt = format; 3458162922Sariff return (0); 3459162922Sariff } 3460162922Sariff } 3461162922Sariff 3462162922Sariff return (EINVAL); 3463162922Sariff} 3464162922Sariff 3465193640Sariffstatic uint32_t 3466162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3467162922Sariff{ 3468162922Sariff struct hdac_chan *ch = data; 3469164614Sariff uint32_t spd = 0, threshold; 3470162922Sariff int i; 3471162922Sariff 3472162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3473162922Sariff spd = ch->pcmrates[i]; 3474164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3475164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3476164614Sariff if (speed < threshold) 3477162922Sariff break; 3478162922Sariff } 3479162922Sariff 3480164614Sariff if (spd == 0) /* impossible */ 3481162922Sariff ch->spd = 48000; 3482162922Sariff else 3483162922Sariff ch->spd = spd; 3484162922Sariff 3485162922Sariff return (ch->spd); 3486162922Sariff} 3487162922Sariff 3488162922Sariffstatic void 3489162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3490162922Sariff{ 3491162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3492182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3493173817Sariff struct hdac_widget *w; 3494182999Smav int i, chn, totalchn, c; 3495162922Sariff nid_t cad = ch->devinfo->codec->cad; 3496182999Smav uint16_t fmt, dfmt; 3497202127Smav uint16_t chmap[2][5] = {{ 0x0010, 0x0001, 0x0201, 0x0231, 0x0231 }, /* 5.1 */ 3498202127Smav { 0x0010, 0x0001, 0x2001, 0x2031, 0x2431 }};/* 7.1 */ 3499202127Smav int map = -1; 3500162922Sariff 3501202127Smav totalchn = AFMT_CHANNEL(ch->fmt); 3502183097Smav HDA_BOOTHVERBOSE( 3503182999Smav device_printf(ch->pdevinfo->dev, 3504182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3505182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3506182999Smav ch->fmt, ch->spd); 3507182999Smav ); 3508162922Sariff fmt = 0; 3509162922Sariff if (ch->fmt & AFMT_S16_LE) 3510162922Sariff fmt |= ch->bit16 << 4; 3511162922Sariff else if (ch->fmt & AFMT_S32_LE) 3512162922Sariff fmt |= ch->bit32 << 4; 3513162922Sariff else 3514162922Sariff fmt |= 1 << 4; 3515162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3516162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3517162922Sariff fmt |= hda_rate_tab[i].base; 3518162922Sariff fmt |= hda_rate_tab[i].mul; 3519162922Sariff fmt |= hda_rate_tab[i].div; 3520162922Sariff break; 3521162922Sariff } 3522162922Sariff } 3523202127Smav fmt |= (totalchn - 1); 3524162922Sariff 3525202127Smav /* Set channel mapping for known speaker setups. */ 3526202127Smav if (as->pinset == 0x0007 || as->pinset == 0x0013) /* Standard 5.1 */ 3527202127Smav map = 0; 3528202127Smav else if (as->pinset == 0x0017) /* Standard 7.1 */ 3529202127Smav map = 1; 3530162922Sariff 3531162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3532182999Smav 3533182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3534182999Smav if (ch->fmt & AFMT_AC3) 3535182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3536162922Sariff 3537173817Sariff chn = 0; 3538162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3539173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3540173817Sariff if (w == NULL) 3541173817Sariff continue; 3542182999Smav 3543202127Smav /* If HP redirection is enabled, but failed to use same 3544202127Smav DAC, make last DAC to duplicate first one. */ 3545204351Smav if (as->fakeredir && i == (as->pincnt - 1)) { 3546202127Smav c = (ch->sid << 4); 3547202127Smav } else { 3548202127Smav if (map >= 0) /* Map known speaker setups. */ 3549202127Smav chn = (((chmap[map][totalchn / 2] >> i * 4) & 3550202127Smav 0xf) - 1) * 2; 3551202127Smav if (chn < 0 || chn >= totalchn) { 3552202127Smav c = 0; 3553202127Smav } else { 3554202127Smav c = (ch->sid << 4) | chn; 3555202127Smav } 3556202127Smav } 3557183097Smav HDA_BOOTHVERBOSE( 3558182999Smav device_printf(ch->pdevinfo->dev, 3559182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3560202127Smav "fmt=0x%04x, dfmt=0x%04x, chan=0x%04x\n", 3561162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3562202127Smav ch->io[i], fmt, dfmt, c); 3563162922Sariff ); 3564162922Sariff hdac_command(sc, 3565162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3566182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3567174025Sariff hdac_command(sc, 3568182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3569174025Sariff cad); 3570182999Smav } 3571182999Smav hdac_command(sc, 3572182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3573197611Smav#if 0 3574197611Smav hdac_command(sc, 3575197611Smav HDA_CMD_SET_CONV_CHAN_COUNT(cad, ch->io[i], 1), cad); 3576197611Smav hdac_command(sc, 3577197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x00), cad); 3578197611Smav hdac_command(sc, 3579197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x11), cad); 3580197611Smav#endif 3581202127Smav chn += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 3582162922Sariff } 3583162922Sariff} 3584162922Sariff 3585202156Smav/* 3586202156Smav * Greatest Common Divisor. 3587202156Smav */ 3588202156Smavstatic unsigned 3589202156Smavgcd(unsigned a, unsigned b) 3590202156Smav{ 3591202156Smav u_int c; 3592202156Smav 3593202156Smav while (b != 0) { 3594202156Smav c = a; 3595202156Smav a = b; 3596202156Smav b = (c % b); 3597202156Smav } 3598202156Smav return (a); 3599202156Smav} 3600202156Smav 3601202156Smav/* 3602202156Smav * Least Common Multiple. 3603202156Smav */ 3604202156Smavstatic unsigned 3605202156Smavlcm(unsigned a, unsigned b) 3606202156Smav{ 3607202156Smav 3608202156Smav return ((a * b) / gcd(a, b)); 3609202156Smav} 3610202156Smav 3611162922Sariffstatic int 3612167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3613167648Sariff uint32_t blksz, uint32_t blkcnt) 3614162922Sariff{ 3615162922Sariff struct hdac_chan *ch = data; 3616164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3617162922Sariff 3618202156Smav blksz -= blksz % lcm(HDAC_DMA_ALIGNMENT, sndbuf_getalign(ch->b)); 3619162922Sariff 3620167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3621167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3622167648Sariff if (blksz < HDA_BLK_MIN) 3623167648Sariff blksz = HDA_BLK_MIN; 3624167648Sariff if (blkcnt > HDA_BDL_MAX) 3625167648Sariff blkcnt = HDA_BDL_MAX; 3626167648Sariff if (blkcnt < HDA_BDL_MIN) 3627167648Sariff blkcnt = HDA_BDL_MIN; 3628164614Sariff 3629167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3630167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3631167648Sariff blkcnt >>= 1; 3632167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3633167648Sariff blksz >>= 1; 3634167648Sariff else 3635167648Sariff break; 3636167648Sariff } 3637167648Sariff 3638164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3639167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3640167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3641164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3642167648Sariff __func__, blksz, blkcnt); 3643164614Sariff 3644164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3645167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3646164614Sariff 3647193640Sariff return (0); 3648167648Sariff} 3649167648Sariff 3650193640Sariffstatic uint32_t 3651167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3652167648Sariff{ 3653167648Sariff struct hdac_chan *ch = data; 3654167648Sariff 3655182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3656167648Sariff 3657162922Sariff return (ch->blksz); 3658162922Sariff} 3659162922Sariff 3660162922Sariffstatic void 3661162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3662162922Sariff{ 3663162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3664182999Smav struct hdac_widget *w; 3665162922Sariff nid_t cad = devinfo->codec->cad; 3666162922Sariff int i; 3667162922Sariff 3668162922Sariff hdac_stream_stop(ch); 3669162922Sariff 3670162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3671182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3672182999Smav if (w == NULL) 3673182999Smav continue; 3674182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3675182999Smav hdac_command(sc, 3676182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3677182999Smav cad); 3678182999Smav } 3679162922Sariff hdac_command(sc, 3680162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3681162922Sariff 0), cad); 3682162922Sariff } 3683162922Sariff} 3684162922Sariff 3685162922Sariffstatic void 3686162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3687162922Sariff{ 3688162922Sariff ch->ptr = 0; 3689162922Sariff ch->prevptr = 0; 3690162922Sariff hdac_stream_stop(ch); 3691162922Sariff hdac_stream_reset(ch); 3692162922Sariff hdac_bdl_setup(ch); 3693162922Sariff hdac_stream_setid(ch); 3694162922Sariff hdac_stream_setup(ch); 3695162922Sariff hdac_stream_start(ch); 3696162922Sariff} 3697162922Sariff 3698162922Sariffstatic int 3699162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3700162922Sariff{ 3701162922Sariff struct hdac_chan *ch = data; 3702162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3703162922Sariff 3704170521Sariff if (!PCMTRIG_COMMON(go)) 3705170521Sariff return (0); 3706170521Sariff 3707162922Sariff hdac_lock(sc); 3708162922Sariff switch (go) { 3709162922Sariff case PCMTRIG_START: 3710162922Sariff hdac_channel_start(sc, ch); 3711162922Sariff break; 3712162922Sariff case PCMTRIG_STOP: 3713162922Sariff case PCMTRIG_ABORT: 3714162922Sariff hdac_channel_stop(sc, ch); 3715162922Sariff break; 3716167610Sariff default: 3717167610Sariff break; 3718162922Sariff } 3719162922Sariff hdac_unlock(sc); 3720162922Sariff 3721162922Sariff return (0); 3722162922Sariff} 3723162922Sariff 3724193640Sariffstatic uint32_t 3725162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3726162922Sariff{ 3727162922Sariff struct hdac_chan *ch = data; 3728162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3729162922Sariff uint32_t ptr; 3730162922Sariff 3731162922Sariff hdac_lock(sc); 3732164614Sariff if (sc->polling != 0) 3733164614Sariff ptr = ch->ptr; 3734169277Sariff else if (ch->dmapos != NULL) 3735169277Sariff ptr = *(ch->dmapos); 3736164614Sariff else 3737164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3738162922Sariff hdac_unlock(sc); 3739162922Sariff 3740164614Sariff /* 3741164614Sariff * Round to available space and force 128 bytes aligment. 3742164614Sariff */ 3743164614Sariff ptr %= ch->blksz * ch->blkcnt; 3744167648Sariff ptr &= HDA_BLK_ALIGN; 3745162922Sariff 3746162922Sariff return (ptr); 3747162922Sariff} 3748162922Sariff 3749162922Sariffstatic struct pcmchan_caps * 3750162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3751162922Sariff{ 3752162922Sariff return (&((struct hdac_chan *)data)->caps); 3753162922Sariff} 3754162922Sariff 3755162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3756162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3757162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3758162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3759162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3760167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3761162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3762162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3763162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3764193640Sariff KOBJMETHOD_END 3765162922Sariff}; 3766162922SariffCHANNEL_DECLARE(hdac_channel); 3767162922Sariff 3768162922Sariffstatic int 3769162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3770162922Sariff{ 3771182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3772182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3773162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3774162922Sariff struct hdac_widget *w, *cw; 3775162922Sariff struct hdac_audio_ctl *ctl; 3776162922Sariff uint32_t mask, recmask, id; 3777162922Sariff int i, j, softpcmvol; 3778162922Sariff 3779162922Sariff hdac_lock(sc); 3780162922Sariff 3781182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3782182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3783182999Smav pdevinfo->left[i] = 100; 3784182999Smav pdevinfo->right[i] = 100; 3785182999Smav } 3786182999Smav 3787162922Sariff mask = 0; 3788162922Sariff recmask = 0; 3789182999Smav id = hdac_codec_id(devinfo->codec); 3790162922Sariff 3791182999Smav /* Declate EAPD as ogain control. */ 3792182999Smav if (pdevinfo->play >= 0) { 3793182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3794182999Smav w = hdac_widget_get(devinfo, i); 3795182999Smav if (w == NULL || w->enable == 0) 3796182999Smav continue; 3797182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3798182999Smav w->param.eapdbtl == HDAC_INVALID || 3799182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3800182999Smav continue; 3801182999Smav mask |= SOUND_MASK_OGAIN; 3802162922Sariff break; 3803162922Sariff } 3804162922Sariff } 3805162922Sariff 3806182999Smav /* Declare volume controls assigned to this association. */ 3807162922Sariff i = 0; 3808162922Sariff ctl = NULL; 3809162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3810182999Smav if (ctl->enable == 0) 3811162922Sariff continue; 3812182999Smav if ((pdevinfo->play >= 0 && 3813182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3814182999Smav (pdevinfo->rec >= 0 && 3815182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3816182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3817182999Smav mask |= ctl->ossmask; 3818162922Sariff } 3819162922Sariff 3820182999Smav /* Declare record sources available to this association. */ 3821182999Smav if (pdevinfo->rec >= 0) { 3822182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3823182999Smav for (i = 0; ch->io[i] != -1; i++) { 3824182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3825182999Smav if (w == NULL || w->enable == 0) 3826182999Smav continue; 3827182999Smav for (j = 0; j < w->nconns; j++) { 3828182999Smav if (w->connsenable[j] == 0) 3829162922Sariff continue; 3830182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3831182999Smav if (cw == NULL || cw->enable == 0) 3832165992Sariff continue; 3833182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3834182999Smav cw->bindas != -2) 3835165992Sariff continue; 3836182999Smav recmask |= cw->ossmask; 3837165992Sariff } 3838182999Smav } 3839182999Smav } 3840182999Smav 3841185230Smav /* Declare soft PCM volume if needed. */ 3842193640Sariff if (pdevinfo->play >= 0) { 3843182999Smav ctl = NULL; 3844182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3845182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3846182999Smav softpcmvol = 1; 3847182999Smav mask |= SOUND_MASK_PCM; 3848162922Sariff } else { 3849182999Smav softpcmvol = 0; 3850182999Smav i = 0; 3851182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3852182999Smav if (ctl->enable == 0) 3853162922Sariff continue; 3854182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3855182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3856162922Sariff continue; 3857182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3858182999Smav continue; 3859182999Smav if (ctl->step > 0) 3860182999Smav break; 3861162922Sariff } 3862162922Sariff } 3863182999Smav 3864182999Smav if (softpcmvol == 1 || ctl == NULL) { 3865182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3866182999Smav HDA_BOOTVERBOSE( 3867182999Smav device_printf(pdevinfo->dev, 3868182999Smav "%s Soft PCM volume\n", 3869182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3870182999Smav ); 3871182999Smav } 3872185230Smav } 3873182999Smav 3874185230Smav /* Declare master volume if needed. */ 3875185230Smav if (pdevinfo->play >= 0) { 3876185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3877185230Smav SOUND_MASK_PCM) { 3878182999Smav mask |= SOUND_MASK_VOLUME; 3879182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3880182999Smav SOUND_MASK_PCM); 3881182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3882182999Smav SOUND_MIXER_NONE); 3883182999Smav HDA_BOOTVERBOSE( 3884182999Smav device_printf(pdevinfo->dev, 3885182999Smav "Forcing master volume with PCM\n"); 3886182999Smav ); 3887182999Smav } 3888162922Sariff } 3889162922Sariff 3890169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3891169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3892162922Sariff 3893162922Sariff mix_setrecdevs(m, recmask); 3894162922Sariff mix_setdevs(m, mask); 3895162922Sariff 3896162922Sariff hdac_unlock(sc); 3897162922Sariff 3898162922Sariff return (0); 3899162922Sariff} 3900162922Sariff 3901162922Sariffstatic int 3902162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3903162922Sariff unsigned left, unsigned right) 3904162922Sariff{ 3905182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3906182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3907162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3908162922Sariff struct hdac_widget *w; 3909162922Sariff struct hdac_audio_ctl *ctl; 3910182999Smav uint32_t mute; 3911182999Smav int lvol, rvol; 3912182999Smav int i, j; 3913162922Sariff 3914162922Sariff hdac_lock(sc); 3915182999Smav /* Save new values. */ 3916182999Smav pdevinfo->left[dev] = left; 3917182999Smav pdevinfo->right[dev] = right; 3918182999Smav 3919182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3920162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3921163257Sariff uint32_t orig; 3922182999Smav w = NULL; 3923182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3924182999Smav w = hdac_widget_get(devinfo, i); 3925182999Smav if (w == NULL || w->enable == 0) 3926182999Smav continue; 3927182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3928182999Smav w->param.eapdbtl == HDAC_INVALID) 3929182999Smav continue; 3930182999Smav break; 3931162922Sariff } 3932182999Smav if (i >= devinfo->endnode) { 3933162922Sariff hdac_unlock(sc); 3934162922Sariff return (-1); 3935162922Sariff } 3936163257Sariff orig = w->param.eapdbtl; 3937163432Sariff if (left == 0) 3938162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3939162922Sariff else 3940162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3941163257Sariff if (orig != w->param.eapdbtl) { 3942163432Sariff uint32_t val; 3943163432Sariff 3944163432Sariff val = w->param.eapdbtl; 3945163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3946163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3947163257Sariff hdac_command(sc, 3948163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3949163432Sariff w->nid, val), devinfo->codec->cad); 3950163257Sariff } 3951162922Sariff hdac_unlock(sc); 3952162922Sariff return (left | (left << 8)); 3953162922Sariff } 3954162922Sariff 3955182999Smav /* Recalculate all controls related to this OSS device. */ 3956162922Sariff i = 0; 3957162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3958182999Smav if (ctl->enable == 0 || 3959162922Sariff !(ctl->ossmask & (1 << dev))) 3960162922Sariff continue; 3961182999Smav if (!((pdevinfo->play >= 0 && 3962182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3963182999Smav (pdevinfo->rec >= 0 && 3964182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3965182999Smav ctl->widget->bindas == -2)) 3966182999Smav continue; 3967182999Smav 3968182999Smav lvol = 100; 3969182999Smav rvol = 100; 3970182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3971182999Smav if (ctl->ossmask & (1 << j)) { 3972182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3973182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3974162922Sariff } 3975162922Sariff } 3976202789Smav mute = (lvol == 0) ? HDA_AMP_MUTE_LEFT : 0; 3977202789Smav mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3978182999Smav lvol = (lvol * ctl->step + 50) / 100; 3979182999Smav rvol = (rvol * ctl->step + 50) / 100; 3980162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3981162922Sariff } 3982162922Sariff hdac_unlock(sc); 3983162922Sariff 3984162922Sariff return (left | (right << 8)); 3985162922Sariff} 3986162922Sariff 3987182999Smav/* 3988182999Smav * Commutate specified record source. 3989182999Smav */ 3990182999Smavstatic uint32_t 3991182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3992162922Sariff{ 3993182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3994162922Sariff struct hdac_widget *w, *cw; 3995182999Smav struct hdac_audio_ctl *ctl; 3996182999Smav char buf[64]; 3997182999Smav int i, muted; 3998182999Smav uint32_t res = 0; 3999162922Sariff 4000182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4001182999Smav return (0); 4002182999Smav 4003182999Smav w = hdac_widget_get(devinfo, nid); 4004182999Smav if (w == NULL || w->enable == 0) 4005182999Smav return (0); 4006182999Smav 4007182999Smav for (i = 0; i < w->nconns; i++) { 4008182999Smav if (w->connsenable[i] == 0) 4009182999Smav continue; 4010182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 4011182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 4012182999Smav continue; 4013182999Smav /* Call recursively to trace signal to it's source if needed. */ 4014182999Smav if ((src & cw->ossmask) != 0) { 4015182999Smav if (cw->ossdev < 0) { 4016182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 4017182999Smav w->conns[i], depth + 1); 4018182999Smav } else { 4019182999Smav res |= cw->ossmask; 4020182999Smav } 4021182999Smav } 4022182999Smav /* We have two special cases: mixers and others (selectors). */ 4023182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 4024182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 4025182999Smav w->nid, HDA_CTL_IN, i, 1); 4026182999Smav if (ctl == NULL) 4027182999Smav continue; 4028182999Smav /* If we have input control on this node mute them 4029182999Smav * according to requested sources. */ 4030182999Smav muted = (src & cw->ossmask) ? 0 : 1; 4031182999Smav if (muted != ctl->forcemute) { 4032182999Smav ctl->forcemute = muted; 4033182999Smav hdac_audio_ctl_amp_set(ctl, 4034182999Smav HDA_AMP_MUTE_DEFAULT, 4035182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 4036182999Smav } 4037183097Smav HDA_BOOTHVERBOSE( 4038182999Smav device_printf(pdevinfo->dev, 4039182999Smav "Recsel (%s): nid %d source %d %s\n", 4040182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4041182999Smav src, buf, sizeof(buf)), 4042182999Smav nid, i, muted?"mute":"unmute"); 4043182999Smav ); 4044182999Smav } else { 4045182999Smav if (w->nconns == 1) 4046182999Smav break; 4047182999Smav if ((src & cw->ossmask) == 0) 4048182999Smav continue; 4049182999Smav /* If we found requested source - select it and exit. */ 4050182999Smav hdac_widget_connection_select(w, i); 4051183097Smav HDA_BOOTHVERBOSE( 4052182999Smav device_printf(pdevinfo->dev, 4053182999Smav "Recsel (%s): nid %d source %d select\n", 4054182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4055182999Smav src, buf, sizeof(buf)), 4056182999Smav nid, i); 4057182999Smav ); 4058162922Sariff break; 4059162922Sariff } 4060162922Sariff } 4061182999Smav return (res); 4062182999Smav} 4063162922Sariff 4064182999Smavstatic uint32_t 4065182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 4066182999Smav{ 4067182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 4068182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 4069182999Smav struct hdac_widget *w; 4070182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4071182999Smav struct hdac_chan *ch; 4072182999Smav int i; 4073182999Smav uint32_t ret = 0xffffffff; 4074182999Smav 4075162922Sariff hdac_lock(sc); 4076162922Sariff 4077182999Smav /* Commutate requested recsrc for each ADC. */ 4078182999Smav ch = &sc->chans[pdevinfo->rec]; 4079182999Smav for (i = 0; ch->io[i] != -1; i++) { 4080182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 4081162965Sariff if (w == NULL || w->enable == 0) 4082162922Sariff continue; 4083182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 4084162922Sariff } 4085162922Sariff 4086162922Sariff hdac_unlock(sc); 4087162922Sariff 4088182999Smav return ((ret == 0xffffffff)? 0 : ret); 4089162922Sariff} 4090162922Sariff 4091162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 4092162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 4093162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 4094162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 4095193640Sariff KOBJMETHOD_END 4096162922Sariff}; 4097162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 4098162922Sariff 4099171141Sariffstatic void 4100171141Sariffhdac_unsolq_task(void *context, int pending) 4101171141Sariff{ 4102171141Sariff struct hdac_softc *sc; 4103171141Sariff 4104171141Sariff sc = (struct hdac_softc *)context; 4105171141Sariff 4106171141Sariff hdac_lock(sc); 4107171141Sariff hdac_unsolq_flush(sc); 4108171141Sariff hdac_unlock(sc); 4109171141Sariff} 4110171141Sariff 4111162922Sariff/**************************************************************************** 4112162922Sariff * int hdac_attach(device_t) 4113162922Sariff * 4114162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 4115162922Sariff * when this function is called. Setup everything that doesn't require 4116162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 4117162922Sariff ****************************************************************************/ 4118162922Sariffstatic int 4119162922Sariffhdac_attach(device_t dev) 4120162922Sariff{ 4121162922Sariff struct hdac_softc *sc; 4122162922Sariff int result; 4123189086Smav int i, devid = -1; 4124189086Smav uint32_t model; 4125189086Smav uint16_t class, subclass; 4126169277Sariff uint16_t vendor; 4127169277Sariff uint8_t v; 4128162922Sariff 4129184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 4130182999Smav 4131189086Smav model = (uint32_t)pci_get_device(dev) << 16; 4132189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 4133189086Smav class = pci_get_class(dev); 4134189086Smav subclass = pci_get_subclass(dev); 4135189086Smav 4136189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 4137189086Smav if (hdac_devices[i].model == model) { 4138189086Smav devid = i; 4139189086Smav break; 4140189086Smav } 4141189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 4142189086Smav class == PCIC_MULTIMEDIA && 4143189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 4144189086Smav devid = i; 4145189086Smav break; 4146189086Smav } 4147189086Smav } 4148189086Smav 4149182999Smav sc = device_get_softc(dev); 4150163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 4151162922Sariff sc->dev = dev; 4152163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 4153163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 4154169277Sariff vendor = pci_get_vendor(dev); 4155162922Sariff 4156165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 4157165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 4158165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 4159165281Sariff } 4160165281Sariff 4161164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 4162164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 4163169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 4164164614Sariff 4165171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 4166171141Sariff 4167182999Smav sc->poll_ticks = 1000000; 4168169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 4169169277Sariff if (resource_int_value(device_get_name(dev), 4170169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 4171164614Sariff sc->polling = 1; 4172164614Sariff else 4173164614Sariff sc->polling = 0; 4174164614Sariff 4175162922Sariff sc->hdabus = NULL; 4176162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 4177162922Sariff sc->codecs[i] = NULL; 4178162922Sariff 4179162922Sariff pci_enable_busmaster(dev); 4180162922Sariff 4181169277Sariff if (vendor == INTEL_VENDORID) { 4182169277Sariff /* TCSEL -> TC0 */ 4183169277Sariff v = pci_read_config(dev, 0x44, 1); 4184169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 4185183097Smav HDA_BOOTHVERBOSE( 4186169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 4187169277Sariff pci_read_config(dev, 0x44, 1)); 4188169277Sariff ); 4189169277Sariff } 4190169277Sariff 4191189127Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_MSI)) 4192188656Smav sc->flags &= ~HDAC_F_MSI; 4193188656Smav else 4194171330Sariff sc->flags |= HDAC_F_MSI; 4195189086Smav if (resource_int_value(device_get_name(dev), 4196189086Smav device_get_unit(dev), "msi", &i) == 0) { 4197189086Smav if (i == 0) 4198189086Smav sc->flags &= ~HDAC_F_MSI; 4199189086Smav else 4200189086Smav sc->flags |= HDAC_F_MSI; 4201189086Smav } 4202171330Sariff 4203169277Sariff#if defined(__i386__) || defined(__amd64__) 4204171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4205169277Sariff 4206169277Sariff if (resource_int_value(device_get_name(dev), 4207169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 4208169277Sariff#else 4209171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4210169277Sariff#endif 4211169277Sariff /* 4212169277Sariff * Try to enable PCIe snoop to avoid messing around with 4213169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 4214169277Sariff * config is pretty much vendor specific, there are no 4215169277Sariff * general solutions on how to enable it, forcing us (even 4216169277Sariff * Microsoft) to enable uncacheable or write combined DMA 4217169277Sariff * by default. 4218169277Sariff * 4219169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 4220169277Sariff */ 4221169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 4222169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 4223169277Sariff continue; 4224171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4225169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4226169277Sariff break; 4227169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4228169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4229169277Sariff hdac_pcie_snoop[i].enable) 4230169277Sariff break; 4231169277Sariff v &= hdac_pcie_snoop[i].mask; 4232169277Sariff v |= hdac_pcie_snoop[i].enable; 4233169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4234169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4235169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4236169277Sariff hdac_pcie_snoop[i].enable) { 4237169277Sariff HDA_BOOTVERBOSE( 4238169277Sariff device_printf(dev, 4239169277Sariff "WARNING: Failed to enable PCIe " 4240169277Sariff "snoop!\n"); 4241169277Sariff ); 4242169277Sariff#if defined(__i386__) || defined(__amd64__) 4243171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4244169277Sariff#endif 4245169277Sariff } 4246169277Sariff break; 4247169277Sariff } 4248169277Sariff#if defined(__i386__) || defined(__amd64__) 4249169277Sariff } 4250169277Sariff#endif 4251169277Sariff 4252183097Smav HDA_BOOTHVERBOSE( 4253169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4254171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4255171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4256169277Sariff ); 4257169277Sariff 4258162922Sariff /* Allocate resources */ 4259162922Sariff result = hdac_mem_alloc(sc); 4260162922Sariff if (result != 0) 4261163057Sariff goto hdac_attach_fail; 4262162922Sariff result = hdac_irq_alloc(sc); 4263162922Sariff if (result != 0) 4264163057Sariff goto hdac_attach_fail; 4265162922Sariff 4266162922Sariff /* Get Capabilities */ 4267162922Sariff result = hdac_get_capabilities(sc); 4268162922Sariff if (result != 0) 4269163057Sariff goto hdac_attach_fail; 4270162922Sariff 4271194861Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_64BIT)) 4272194861Smav sc->support_64bit = 0; 4273194861Smav 4274162922Sariff /* Allocate CORB and RIRB dma memory */ 4275162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4276162922Sariff sc->corb_size * sizeof(uint32_t)); 4277162922Sariff if (result != 0) 4278163057Sariff goto hdac_attach_fail; 4279162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4280162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4281162922Sariff if (result != 0) 4282163057Sariff goto hdac_attach_fail; 4283162922Sariff 4284194861Smav result = bus_dma_tag_create( 4285194861Smav bus_get_dma_tag(sc->dev), /* parent */ 4286194861Smav HDAC_DMA_ALIGNMENT, /* alignment */ 4287194861Smav 0, /* boundary */ 4288194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 4289194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 4290194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 4291194861Smav NULL, /* filtfunc */ 4292194861Smav NULL, /* fistfuncarg */ 4293194861Smav HDA_BUFSZ_MAX, /* maxsize */ 4294194861Smav 1, /* nsegments */ 4295194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 4296194861Smav 0, /* flags */ 4297194861Smav NULL, /* lockfunc */ 4298194861Smav NULL, /* lockfuncarg */ 4299194861Smav &sc->chan_dmat); /* dmat */ 4300194861Smav if (result != 0) { 4301194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 4302194861Smav __func__, result); 4303194861Smav goto hdac_attach_fail; 4304194861Smav } 4305194861Smav 4306162922Sariff /* Quiesce everything */ 4307183097Smav HDA_BOOTHVERBOSE( 4308182999Smav device_printf(dev, "Reset controller...\n"); 4309182999Smav ); 4310182999Smav hdac_reset(sc, 1); 4311162922Sariff 4312162922Sariff /* Initialize the CORB and RIRB */ 4313162922Sariff hdac_corb_init(sc); 4314162922Sariff hdac_rirb_init(sc); 4315162922Sariff 4316162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4317162922Sariff sc->intrhook.ich_func = hdac_attach2; 4318162922Sariff sc->intrhook.ich_arg = (void *)sc; 4319162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4320162922Sariff sc->intrhook.ich_func = NULL; 4321162922Sariff hdac_attach2((void *)sc); 4322162922Sariff } 4323162922Sariff 4324163057Sariff return (0); 4325162922Sariff 4326163057Sariffhdac_attach_fail: 4327162922Sariff hdac_irq_free(sc); 4328169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4329169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4330162922Sariff hdac_mem_free(sc); 4331162922Sariff snd_mtxfree(sc->lock); 4332162922Sariff 4333163057Sariff return (ENXIO); 4334162922Sariff} 4335162922Sariff 4336162922Sariffstatic void 4337162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4338162922Sariff{ 4339182999Smav struct hdac_codec *codec = devinfo->codec; 4340182999Smav struct hdac_softc *sc = codec->sc; 4341162922Sariff struct hdac_widget *w; 4342162922Sariff uint32_t res; 4343162922Sariff int i; 4344162922Sariff nid_t cad, nid; 4345162922Sariff 4346162922Sariff cad = devinfo->codec->cad; 4347162922Sariff nid = devinfo->nid; 4348162922Sariff 4349162922Sariff res = hdac_command(sc, 4350169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4351169277Sariff devinfo->function.audio.gpio = res; 4352169277Sariff 4353163057Sariff HDA_BOOTVERBOSE( 4354183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4355183097Smav "NumGPIO=%d NumGPO=%d " 4356169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4357183097Smav devinfo->function.audio.gpio, 4358169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4359169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4360169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4361169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4362169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4363162922Sariff ); 4364162922Sariff 4365162922Sariff res = hdac_command(sc, 4366162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4367162922Sariff cad); 4368162922Sariff devinfo->function.audio.supp_stream_formats = res; 4369162922Sariff 4370162922Sariff res = hdac_command(sc, 4371162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4372162922Sariff cad); 4373162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4374162922Sariff 4375162922Sariff res = hdac_command(sc, 4376162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4377162922Sariff cad); 4378162922Sariff devinfo->function.audio.outamp_cap = res; 4379162922Sariff 4380162922Sariff res = hdac_command(sc, 4381162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4382162922Sariff cad); 4383162922Sariff devinfo->function.audio.inamp_cap = res; 4384162922Sariff 4385162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4386162922Sariff w = hdac_widget_get(devinfo, i); 4387162922Sariff if (w == NULL) 4388162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4389162922Sariff else { 4390162922Sariff w->devinfo = devinfo; 4391162922Sariff w->nid = i; 4392162922Sariff w->enable = 1; 4393162922Sariff w->selconn = -1; 4394162922Sariff w->pflags = 0; 4395182999Smav w->ossdev = -1; 4396182999Smav w->bindas = -1; 4397162965Sariff w->param.eapdbtl = HDAC_INVALID; 4398162922Sariff hdac_widget_parse(w); 4399162922Sariff } 4400162922Sariff } 4401162922Sariff} 4402162922Sariff 4403162922Sariffstatic void 4404162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4405162922Sariff{ 4406162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4407162922Sariff struct hdac_audio_ctl *ctls; 4408162922Sariff struct hdac_widget *w, *cw; 4409162922Sariff int i, j, cnt, max, ocap, icap; 4410163057Sariff int mute, offset, step, size; 4411162922Sariff 4412162922Sariff /* XXX This is redundant */ 4413162922Sariff max = 0; 4414162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4415162922Sariff w = hdac_widget_get(devinfo, i); 4416162922Sariff if (w == NULL || w->enable == 0) 4417162922Sariff continue; 4418162922Sariff if (w->param.outamp_cap != 0) 4419162922Sariff max++; 4420162922Sariff if (w->param.inamp_cap != 0) { 4421162922Sariff switch (w->type) { 4422162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4423162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4424162922Sariff for (j = 0; j < w->nconns; j++) { 4425162922Sariff cw = hdac_widget_get(devinfo, 4426162922Sariff w->conns[j]); 4427162922Sariff if (cw == NULL || cw->enable == 0) 4428162922Sariff continue; 4429162922Sariff max++; 4430162922Sariff } 4431162922Sariff break; 4432162922Sariff default: 4433162922Sariff max++; 4434162922Sariff break; 4435162922Sariff } 4436162922Sariff } 4437162922Sariff } 4438162922Sariff 4439162922Sariff devinfo->function.audio.ctlcnt = max; 4440162922Sariff 4441162922Sariff if (max < 1) 4442162922Sariff return; 4443162922Sariff 4444162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4445162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4446162922Sariff 4447162922Sariff if (ctls == NULL) { 4448162922Sariff /* Blekh! */ 4449162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4450162922Sariff devinfo->function.audio.ctlcnt = 0; 4451162922Sariff return; 4452162922Sariff } 4453162922Sariff 4454162922Sariff cnt = 0; 4455162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4456162922Sariff if (cnt >= max) { 4457162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4458162922Sariff __func__); 4459162922Sariff break; 4460162922Sariff } 4461162922Sariff w = hdac_widget_get(devinfo, i); 4462162922Sariff if (w == NULL || w->enable == 0) 4463162922Sariff continue; 4464162922Sariff ocap = w->param.outamp_cap; 4465162922Sariff icap = w->param.inamp_cap; 4466162922Sariff if (ocap != 0) { 4467163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4468163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4469163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4470163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4471163057Sariff /*if (offset > step) { 4472163057Sariff HDA_BOOTVERBOSE( 4473163057Sariff device_printf(sc->dev, 4474182999Smav "BUGGY outamp: nid=%d " 4475163057Sariff "[offset=%d > step=%d]\n", 4476163057Sariff w->nid, offset, step); 4477163057Sariff ); 4478163057Sariff offset = step; 4479163057Sariff }*/ 4480162922Sariff ctls[cnt].enable = 1; 4481162922Sariff ctls[cnt].widget = w; 4482163057Sariff ctls[cnt].mute = mute; 4483163057Sariff ctls[cnt].step = step; 4484163057Sariff ctls[cnt].size = size; 4485163057Sariff ctls[cnt].offset = offset; 4486163057Sariff ctls[cnt].left = offset; 4487163057Sariff ctls[cnt].right = offset; 4488182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4489182999Smav w->waspin) 4490182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4491182999Smav else 4492182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4493162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4494162922Sariff } 4495162922Sariff 4496162922Sariff if (icap != 0) { 4497163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4498163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4499163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4500163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4501163057Sariff /*if (offset > step) { 4502163057Sariff HDA_BOOTVERBOSE( 4503163057Sariff device_printf(sc->dev, 4504182999Smav "BUGGY inamp: nid=%d " 4505163057Sariff "[offset=%d > step=%d]\n", 4506163057Sariff w->nid, offset, step); 4507163057Sariff ); 4508163057Sariff offset = step; 4509163057Sariff }*/ 4510162922Sariff switch (w->type) { 4511162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4512162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4513162922Sariff for (j = 0; j < w->nconns; j++) { 4514162922Sariff if (cnt >= max) { 4515162922Sariff device_printf(sc->dev, 4516162922Sariff "%s: Ctl overflow!\n", 4517162922Sariff __func__); 4518162922Sariff break; 4519162922Sariff } 4520162922Sariff cw = hdac_widget_get(devinfo, 4521162922Sariff w->conns[j]); 4522162922Sariff if (cw == NULL || cw->enable == 0) 4523162922Sariff continue; 4524162922Sariff ctls[cnt].enable = 1; 4525162922Sariff ctls[cnt].widget = w; 4526162922Sariff ctls[cnt].childwidget = cw; 4527162922Sariff ctls[cnt].index = j; 4528163057Sariff ctls[cnt].mute = mute; 4529163057Sariff ctls[cnt].step = step; 4530163057Sariff ctls[cnt].size = size; 4531163057Sariff ctls[cnt].offset = offset; 4532163057Sariff ctls[cnt].left = offset; 4533163057Sariff ctls[cnt].right = offset; 4534182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4535162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4536162922Sariff } 4537162922Sariff break; 4538162922Sariff default: 4539162922Sariff if (cnt >= max) { 4540162922Sariff device_printf(sc->dev, 4541162922Sariff "%s: Ctl overflow!\n", 4542162922Sariff __func__); 4543162922Sariff break; 4544162922Sariff } 4545162922Sariff ctls[cnt].enable = 1; 4546162922Sariff ctls[cnt].widget = w; 4547163057Sariff ctls[cnt].mute = mute; 4548163057Sariff ctls[cnt].step = step; 4549163057Sariff ctls[cnt].size = size; 4550163057Sariff ctls[cnt].offset = offset; 4551163057Sariff ctls[cnt].left = offset; 4552163057Sariff ctls[cnt].right = offset; 4553182999Smav if (w->type == 4554182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4555182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4556182999Smav else 4557182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4558162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4559162922Sariff break; 4560162922Sariff } 4561162922Sariff } 4562162922Sariff } 4563162922Sariff 4564162922Sariff devinfo->function.audio.ctl = ctls; 4565162922Sariff} 4566162922Sariff 4567182999Smavstatic void 4568182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4569182999Smav{ 4570182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4571182999Smav struct hdac_audio_as *as; 4572182999Smav struct hdac_widget *w; 4573182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4574182999Smav 4575184991Smav /* Count present associations */ 4576182999Smav max = 0; 4577184991Smav for (j = 1; j < 16; j++) { 4578182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4579182999Smav w = hdac_widget_get(devinfo, i); 4580182999Smav if (w == NULL || w->enable == 0) 4581182999Smav continue; 4582182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4583182999Smav continue; 4584182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4585182999Smav != j) 4586182999Smav continue; 4587182999Smav max++; 4588182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4589182999Smav break; 4590182999Smav } 4591182999Smav } 4592182999Smav 4593182999Smav devinfo->function.audio.ascnt = max; 4594182999Smav 4595182999Smav if (max < 1) 4596182999Smav return; 4597182999Smav 4598182999Smav as = (struct hdac_audio_as *)malloc( 4599182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4600182999Smav 4601182999Smav if (as == NULL) { 4602182999Smav /* Blekh! */ 4603182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4604182999Smav devinfo->function.audio.ascnt = 0; 4605182999Smav return; 4606182999Smav } 4607182999Smav 4608182999Smav for (i = 0; i < max; i++) { 4609182999Smav as[i].hpredir = -1; 4610182999Smav as[i].chan = -1; 4611197611Smav as[i].digital = 0; 4612182999Smav } 4613182999Smav 4614182999Smav /* Scan associations skipping as=0. */ 4615182999Smav cnt = 0; 4616182999Smav for (j = 1; j < 16; j++) { 4617182999Smav first = 16; 4618182999Smav hpredir = 0; 4619182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4620182999Smav w = hdac_widget_get(devinfo, i); 4621182999Smav if (w == NULL || w->enable == 0) 4622182999Smav continue; 4623182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4624182999Smav continue; 4625182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4626182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4627182999Smav if (assoc != j) { 4628182999Smav continue; 4629182999Smav } 4630182999Smav KASSERT(cnt < max, 4631182999Smav ("%s: Associations owerflow (%d of %d)", 4632182999Smav __func__, cnt, max)); 4633182999Smav type = w->wclass.pin.config & 4634182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4635182999Smav /* Get pin direction. */ 4636182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4637182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4638182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4639182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4640182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4641182999Smav dir = HDA_CTL_OUT; 4642182999Smav else 4643182999Smav dir = HDA_CTL_IN; 4644182999Smav /* If this is a first pin - create new association. */ 4645182999Smav if (as[cnt].pincnt == 0) { 4646182999Smav as[cnt].enable = 1; 4647182999Smav as[cnt].index = j; 4648182999Smav as[cnt].dir = dir; 4649182999Smav } 4650182999Smav if (seq < first) 4651182999Smav first = seq; 4652182999Smav /* Check association correctness. */ 4653182999Smav if (as[cnt].pins[seq] != 0) { 4654182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4655182999Smav "in association %d! Disabling association.\n", 4656182999Smav __func__, seq, w->nid, j); 4657182999Smav as[cnt].enable = 0; 4658182999Smav } 4659182999Smav if (dir != as[cnt].dir) { 4660182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4661182999Smav "direction for association %d! Disabling " 4662182999Smav "association.\n", 4663182999Smav __func__, w->nid, j); 4664182999Smav as[cnt].enable = 0; 4665182999Smav } 4666197611Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 4667197611Smav if (HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap)) 4668197611Smav as[cnt].digital = 3; 4669197611Smav else if (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap)) 4670197611Smav as[cnt].digital = 2; 4671197611Smav else 4672197611Smav as[cnt].digital = 1; 4673197611Smav } 4674182999Smav /* Headphones with seq=15 may mean redirection. */ 4675182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4676182999Smav seq == 15) 4677182999Smav hpredir = 1; 4678182999Smav as[cnt].pins[seq] = w->nid; 4679182999Smav as[cnt].pincnt++; 4680182999Smav /* Association 15 is a multiple unassociated pins. */ 4681182999Smav if (j == 15) 4682182999Smav cnt++; 4683182999Smav } 4684182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4685182999Smav if (hpredir && as[cnt].pincnt > 1) 4686182999Smav as[cnt].hpredir = first; 4687182999Smav cnt++; 4688182999Smav } 4689182999Smav } 4690182999Smav HDA_BOOTVERBOSE( 4691182999Smav device_printf(sc->dev, 4692183097Smav "%d associations found:\n", max); 4693182999Smav for (i = 0; i < max; i++) { 4694182999Smav device_printf(sc->dev, 4695182999Smav "Association %d (%d) %s%s:\n", 4696182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4697182999Smav as[i].enable?"":" (disabled)"); 4698182999Smav for (j = 0; j < 16; j++) { 4699182999Smav if (as[i].pins[j] == 0) 4700182999Smav continue; 4701182999Smav device_printf(sc->dev, 4702183097Smav " Pin nid=%d seq=%d\n", 4703182999Smav as[i].pins[j], j); 4704182999Smav } 4705182999Smav } 4706182999Smav ); 4707182999Smav 4708182999Smav devinfo->function.audio.as = as; 4709182999Smav} 4710182999Smav 4711162965Sariffstatic const struct { 4712162965Sariff uint32_t model; 4713162965Sariff uint32_t id; 4714162965Sariff uint32_t set, unset; 4715162965Sariff} hdac_quirks[] = { 4716163057Sariff /* 4717163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4718163057Sariff * on few codecs (especially ALC880) seems broken or 4719163057Sariff * perhaps unsupported. 4720163057Sariff */ 4721163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4722169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4723162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4724165039Sariff HDA_QUIRK_GPIO0, 0 }, 4725178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4726178155Sariff HDA_QUIRK_GPIO0, 0 }, 4727162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4728165039Sariff HDA_QUIRK_GPIO0, 0 }, 4729165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4730165281Sariff HDA_QUIRK_GPIO0, 0 }, 4731167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4732167623Sariff HDA_QUIRK_GPIO0, 0 }, 4733169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4734169277Sariff HDA_QUIRK_GPIO0, 0 }, 4735163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4736163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4737178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4738163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4739169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4740169277Sariff HDA_QUIRK_OVREF, 0 }, 4741169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4742169277Sariff HDA_QUIRK_OVREF, 0 }, 4743169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4744169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4745165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4746165281Sariff HDA_QUIRK_GPIO1, 0 }, 4747164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4748182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4749164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4750164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4751173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4752173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4753165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4754165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4755199846Smav { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, 4756199846Smav HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 }, 4757183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4758180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4759184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4760184483Smav HDA_QUIRK_GPIO2, 0 }, 4761183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4762178155Sariff HDA_QUIRK_GPIO0, 0 }, 4763169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4764169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4765170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4766170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4767186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4768182999Smav 0, HDA_QUIRK_FORCESTEREO } 4769162965Sariff}; 4770162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4771162965Sariff 4772162922Sariffstatic void 4773162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4774162922Sariff{ 4775162922Sariff struct hdac_widget *w; 4776162965Sariff uint32_t id, subvendor; 4777162922Sariff int i; 4778162922Sariff 4779182999Smav id = hdac_codec_id(devinfo->codec); 4780163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4781163057Sariff 4782162922Sariff /* 4783163057Sariff * Quirks 4784162922Sariff */ 4785163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4786163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4787163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4788163057Sariff continue; 4789163057Sariff if (hdac_quirks[i].set != 0) 4790163057Sariff devinfo->function.audio.quirks |= 4791163057Sariff hdac_quirks[i].set; 4792163057Sariff if (hdac_quirks[i].unset != 0) 4793163057Sariff devinfo->function.audio.quirks &= 4794163057Sariff ~(hdac_quirks[i].unset); 4795163057Sariff } 4796163057Sariff 4797162922Sariff switch (id) { 4798187196Smav case HDA_CODEC_AD1983: 4799187196Smav /* 4800187202Smav * This codec has several possible usages, but none 4801187202Smav * fit the parser best. Help parser to choose better. 4802187196Smav */ 4803187196Smav /* Disable direct unmixed playback to get pcm volume. */ 4804187196Smav w = hdac_widget_get(devinfo, 5); 4805187196Smav if (w != NULL) 4806187196Smav w->connsenable[0] = 0; 4807187196Smav w = hdac_widget_get(devinfo, 6); 4808187196Smav if (w != NULL) 4809187196Smav w->connsenable[0] = 0; 4810187196Smav w = hdac_widget_get(devinfo, 11); 4811187196Smav if (w != NULL) 4812187196Smav w->connsenable[0] = 0; 4813187196Smav /* Disable mic and line selectors. */ 4814187196Smav w = hdac_widget_get(devinfo, 12); 4815187196Smav if (w != NULL) 4816187196Smav w->connsenable[1] = 0; 4817187196Smav w = hdac_widget_get(devinfo, 13); 4818187196Smav if (w != NULL) 4819187196Smav w->connsenable[1] = 0; 4820187196Smav /* Disable recording from mono playback mix. */ 4821187196Smav w = hdac_widget_get(devinfo, 20); 4822187196Smav if (w != NULL) 4823187196Smav w->connsenable[3] = 0; 4824187196Smav break; 4825162922Sariff case HDA_CODEC_AD1986A: 4826186503Smav /* 4827186503Smav * This codec has overcomplicated input mixing. 4828186503Smav * Make some cleaning there. 4829186503Smav */ 4830186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4831186503Smav w = hdac_widget_get(devinfo, 43); 4832186503Smav if (w != NULL) 4833186503Smav w->enable = 0; 4834186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4835186503Smav w = hdac_widget_get(devinfo, 39); 4836186503Smav if (w != NULL) 4837186503Smav w->enable = 0; 4838186503Smav w = hdac_widget_get(devinfo, 40); 4839186503Smav if (w != NULL) 4840186503Smav w->enable = 0; 4841186503Smav w = hdac_widget_get(devinfo, 41); 4842186503Smav if (w != NULL) 4843186503Smav w->enable = 0; 4844186503Smav w = hdac_widget_get(devinfo, 42); 4845186503Smav if (w != NULL) 4846186503Smav w->enable = 0; 4847186503Smav /* Disable duplicate mixer node connector. */ 4848186503Smav w = hdac_widget_get(devinfo, 15); 4849186503Smav if (w != NULL) 4850186503Smav w->connsenable[3] = 0; 4851190630Smav /* There is only one mic preamplifier, use it effectively. */ 4852190630Smav w = hdac_widget_get(devinfo, 31); 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[2] = 0; 4860190630Smav } else { 4861190630Smav w = hdac_widget_get(devinfo, 15); 4862190630Smav if (w != NULL) 4863190630Smav w->connsenable[0] = 0; 4864190630Smav } 4865190630Smav } 4866190630Smav w = hdac_widget_get(devinfo, 32); 4867190630Smav if (w != NULL) { 4868190630Smav if ((w->wclass.pin.config & 4869190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4870190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4871190630Smav w = hdac_widget_get(devinfo, 16); 4872190630Smav if (w != NULL) 4873190630Smav w->connsenable[0] = 0; 4874190630Smav } else { 4875190630Smav w = hdac_widget_get(devinfo, 15); 4876190630Smav if (w != NULL) 4877190630Smav w->connsenable[1] = 0; 4878190630Smav } 4879190630Smav } 4880186503Smav 4881182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4882178155Sariff /* 4883178155Sariff * This is just plain ridiculous.. There 4884178155Sariff * are several A8 series that share the same 4885178155Sariff * pci id but works differently (EAPD). 4886178155Sariff */ 4887178155Sariff w = hdac_widget_get(devinfo, 26); 4888178155Sariff if (w != NULL && w->type == 4889178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4890178155Sariff (w->wclass.pin.config & 4891178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4892178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4893178155Sariff devinfo->function.audio.quirks &= 4894178155Sariff ~HDA_QUIRK_EAPDINV; 4895169277Sariff } 4896162922Sariff break; 4897184230Smav case HDA_CODEC_AD1981HD: 4898184230Smav /* 4899184230Smav * This codec has very unusual design with several 4900184254Smav * points inappropriate for the present parser. 4901184230Smav */ 4902184230Smav /* Disable recording from mono playback mix. */ 4903184230Smav w = hdac_widget_get(devinfo, 21); 4904184230Smav if (w != NULL) 4905184230Smav w->connsenable[3] = 0; 4906184230Smav /* Disable rear to front mic mixer, use separately. */ 4907184230Smav w = hdac_widget_get(devinfo, 31); 4908184230Smav if (w != NULL) 4909184230Smav w->enable = 0; 4910202789Smav /* Disable direct playback, use mixer. */ 4911202789Smav w = hdac_widget_get(devinfo, 5); 4912184230Smav if (w != NULL) 4913202789Smav w->connsenable[0] = 0; 4914202789Smav w = hdac_widget_get(devinfo, 6); 4915202789Smav if (w != NULL) 4916202789Smav w->connsenable[0] = 0; 4917202789Smav w = hdac_widget_get(devinfo, 9); 4918202789Smav if (w != NULL) 4919202789Smav w->connsenable[0] = 0; 4920202789Smav w = hdac_widget_get(devinfo, 24); 4921202789Smav if (w != NULL) 4922202789Smav w->connsenable[0] = 0; 4923184230Smav break; 4924182999Smav } 4925182999Smav} 4926182999Smav 4927182999Smav/* 4928182999Smav * Trace path from DAC to pin. 4929182999Smav */ 4930182999Smavstatic nid_t 4931182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4932182999Smav int dupseq, int min, int only, int depth) 4933182999Smav{ 4934182999Smav struct hdac_widget *w; 4935182999Smav int i, im = -1; 4936182999Smav nid_t m = 0, ret; 4937182999Smav 4938182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4939182999Smav return (0); 4940182999Smav w = hdac_widget_get(devinfo, nid); 4941182999Smav if (w == NULL || w->enable == 0) 4942182999Smav return (0); 4943183097Smav HDA_BOOTHVERBOSE( 4944182999Smav if (!only) { 4945182999Smav device_printf(devinfo->codec->sc->dev, 4946182999Smav " %*stracing via nid %d\n", 4947182999Smav depth + 1, "", w->nid); 4948169277Sariff } 4949182999Smav ); 4950182999Smav /* Use only unused widgets */ 4951182999Smav if (w->bindas >= 0 && w->bindas != as) { 4952183097Smav HDA_BOOTHVERBOSE( 4953182999Smav if (!only) { 4954182999Smav device_printf(devinfo->codec->sc->dev, 4955182999Smav " %*snid %d busy by association %d\n", 4956182999Smav depth + 1, "", w->nid, w->bindas); 4957182999Smav } 4958182999Smav ); 4959182999Smav return (0); 4960182999Smav } 4961182999Smav if (dupseq < 0) { 4962182999Smav if (w->bindseqmask != 0) { 4963183097Smav HDA_BOOTHVERBOSE( 4964182999Smav if (!only) { 4965182999Smav device_printf(devinfo->codec->sc->dev, 4966182999Smav " %*snid %d busy by seqmask %x\n", 4967182999Smav depth + 1, "", w->nid, w->bindseqmask); 4968182999Smav } 4969182999Smav ); 4970182999Smav return (0); 4971169277Sariff } 4972182999Smav } else { 4973182999Smav /* If this is headphones - allow duplicate first pin. */ 4974182999Smav if (w->bindseqmask != 0 && 4975182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4976183097Smav HDA_BOOTHVERBOSE( 4977182999Smav device_printf(devinfo->codec->sc->dev, 4978182999Smav " %*snid %d busy by seqmask %x\n", 4979182999Smav depth + 1, "", w->nid, w->bindseqmask); 4980182999Smav ); 4981182999Smav return (0); 4982169277Sariff } 4983182999Smav } 4984182999Smav 4985182999Smav switch (w->type) { 4986182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4987182999Smav /* Do not traverse input. AD1988 has digital monitor 4988182999Smav for which we are not ready. */ 4989169277Sariff break; 4990182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4991182999Smav /* If we are tracing HP take only dac of first pin. */ 4992182999Smav if ((only == 0 || only == w->nid) && 4993182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4994182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4995182999Smav m = w->nid; 4996178155Sariff break; 4997182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4998182999Smav if (depth > 0) 4999169277Sariff break; 5000182999Smav /* Fall */ 5001182999Smav default: 5002182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 5003182999Smav for (i = 0; i < w->nconns; i++) { 5004182999Smav if (w->connsenable[i] == 0) 5005162922Sariff continue; 5006182999Smav if (w->selconn != -1 && w->selconn != i) 5007162922Sariff continue; 5008182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 5009182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 5010182999Smav if (m == 0 || ret < m) { 5011182999Smav m = ret; 5012182999Smav im = i; 5013182999Smav } 5014182999Smav if (only || dupseq >= 0) 5015182999Smav break; 5016182999Smav } 5017162922Sariff } 5018182999Smav if (m && only && ((w->nconns > 1 && 5019182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5020182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 5021182999Smav w->selconn = im; 5022162922Sariff break; 5023182999Smav } 5024182999Smav if (m && only) { 5025182999Smav w->bindas = as; 5026182999Smav w->bindseqmask |= (1 << seq); 5027182999Smav } 5028183097Smav HDA_BOOTHVERBOSE( 5029182999Smav if (!only) { 5030182999Smav device_printf(devinfo->codec->sc->dev, 5031182999Smav " %*snid %d returned %d\n", 5032182999Smav depth + 1, "", w->nid, m); 5033182999Smav } 5034182999Smav ); 5035182999Smav return (m); 5036182999Smav} 5037162922Sariff 5038182999Smav/* 5039182999Smav * Trace path from widget to ADC. 5040182999Smav */ 5041182999Smavstatic nid_t 5042182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 5043182999Smav int only, int depth) 5044182999Smav{ 5045182999Smav struct hdac_widget *w, *wc; 5046182999Smav int i, j; 5047182999Smav nid_t res = 0; 5048182999Smav 5049182999Smav if (depth > HDA_PARSE_MAXDEPTH) 5050182999Smav return (0); 5051182999Smav w = hdac_widget_get(devinfo, nid); 5052182999Smav if (w == NULL || w->enable == 0) 5053182999Smav return (0); 5054183097Smav HDA_BOOTHVERBOSE( 5055182999Smav device_printf(devinfo->codec->sc->dev, 5056182999Smav " %*stracing via nid %d\n", 5057182999Smav depth + 1, "", w->nid); 5058182999Smav ); 5059182999Smav /* Use only unused widgets */ 5060182999Smav if (w->bindas >= 0 && w->bindas != as) { 5061183097Smav HDA_BOOTHVERBOSE( 5062182999Smav device_printf(devinfo->codec->sc->dev, 5063182999Smav " %*snid %d busy by association %d\n", 5064182999Smav depth + 1, "", w->nid, w->bindas); 5065182999Smav ); 5066182999Smav return (0); 5067182999Smav } 5068182999Smav 5069182999Smav switch (w->type) { 5070182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5071182999Smav /* If we are tracing HP take only dac of first pin. */ 5072182999Smav if (only == w->nid) 5073182999Smav res = 1; 5074162922Sariff break; 5075182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5076182999Smav if (depth > 0) 5077182999Smav break; 5078182999Smav /* Fall */ 5079182999Smav default: 5080182999Smav /* Try to find reachable ADCs with specified nid. */ 5081182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5082182999Smav wc = hdac_widget_get(devinfo, j); 5083182999Smav if (wc == NULL || wc->enable == 0) 5084182999Smav continue; 5085182999Smav for (i = 0; i < wc->nconns; i++) { 5086182999Smav if (wc->connsenable[i] == 0) 5087182999Smav continue; 5088182999Smav if (wc->conns[i] != nid) 5089182999Smav continue; 5090182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 5091182999Smav j, only, depth + 1) != 0) { 5092182999Smav res = 1; 5093182999Smav if (((wc->nconns > 1 && 5094182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5095182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 5096182999Smav wc->selconn == -1) 5097182999Smav wc->selconn = i; 5098182999Smav } 5099182999Smav } 5100169277Sariff } 5101169277Sariff break; 5102162922Sariff } 5103182999Smav if (res) { 5104182999Smav w->bindas = as; 5105182999Smav w->bindseqmask |= (1 << seq); 5106182999Smav } 5107183097Smav HDA_BOOTHVERBOSE( 5108182999Smav device_printf(devinfo->codec->sc->dev, 5109182999Smav " %*snid %d returned %d\n", 5110182999Smav depth + 1, "", w->nid, res); 5111182999Smav ); 5112182999Smav return (res); 5113162922Sariff} 5114162922Sariff 5115182999Smav/* 5116182999Smav * Erase trace path of the specified association. 5117182999Smav */ 5118182999Smavstatic void 5119182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 5120182999Smav{ 5121182999Smav struct hdac_widget *w; 5122182999Smav int i; 5123182999Smav 5124182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5125182999Smav w = hdac_widget_get(devinfo, i); 5126182999Smav if (w == NULL || w->enable == 0) 5127182999Smav continue; 5128182999Smav if (w->bindas == as) { 5129182999Smav if (seq >= 0) { 5130182999Smav w->bindseqmask &= ~(1 << seq); 5131182999Smav if (w->bindseqmask == 0) { 5132182999Smav w->bindas = -1; 5133182999Smav w->selconn = -1; 5134182999Smav } 5135182999Smav } else { 5136182999Smav w->bindas = -1; 5137182999Smav w->bindseqmask = 0; 5138182999Smav w->selconn = -1; 5139182999Smav } 5140182999Smav } 5141182999Smav } 5142182999Smav} 5143182999Smav 5144182999Smav/* 5145182999Smav * Trace association path from DAC to output 5146182999Smav */ 5147162922Sariffstatic int 5148182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 5149162922Sariff{ 5150182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5151182999Smav int i, hpredir; 5152182999Smav nid_t min, res; 5153162922Sariff 5154182999Smav /* Find next pin */ 5155185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 5156182999Smav ; 5157188510Smav /* Check if there is no any left. If so - we succeeded. */ 5158182999Smav if (i == 16) 5159182999Smav return (1); 5160182999Smav 5161182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 5162182999Smav min = 0; 5163182999Smav res = 0; 5164182999Smav do { 5165183097Smav HDA_BOOTHVERBOSE( 5166182999Smav device_printf(devinfo->codec->sc->dev, 5167182999Smav " Tracing pin %d with min nid %d", 5168182999Smav ases[as].pins[i], min); 5169182999Smav if (hpredir >= 0) 5170183097Smav printf(" and hpredir %d", hpredir); 5171183097Smav printf("\n"); 5172182999Smav ); 5173182999Smav /* Trace this pin taking min nid into account. */ 5174182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 5175182999Smav ases[as].pins[i], hpredir, min, 0, 0); 5176182999Smav if (res == 0) { 5177182999Smav /* If we failed - return to previous and redo it. */ 5178182999Smav HDA_BOOTVERBOSE( 5179182999Smav device_printf(devinfo->codec->sc->dev, 5180182999Smav " Unable to trace pin %d seq %d with min " 5181183097Smav "nid %d", 5182183097Smav ases[as].pins[i], i, min); 5183183097Smav if (hpredir >= 0) 5184183097Smav printf(" and hpredir %d", hpredir); 5185183097Smav printf("\n"); 5186182999Smav ); 5187182999Smav return (0); 5188162922Sariff } 5189182999Smav HDA_BOOTVERBOSE( 5190182999Smav device_printf(devinfo->codec->sc->dev, 5191183097Smav " Pin %d traced to DAC %d", 5192183097Smav ases[as].pins[i], res); 5193183097Smav if (hpredir >= 0) 5194183097Smav printf(" and hpredir %d", hpredir); 5195183097Smav if (ases[as].fakeredir) 5196183097Smav printf(" with fake redirection"); 5197183097Smav printf("\n"); 5198182999Smav ); 5199182999Smav /* Trace again to mark the path */ 5200182999Smav hdac_audio_trace_dac(devinfo, as, i, 5201182999Smav ases[as].pins[i], hpredir, min, res, 0); 5202182999Smav ases[as].dacs[i] = res; 5203188510Smav /* We succeeded, so call next. */ 5204182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 5205182999Smav return (1); 5206182999Smav /* If next failed, we should retry with next min */ 5207182999Smav hdac_audio_undo_trace(devinfo, as, i); 5208182999Smav ases[as].dacs[i] = 0; 5209182999Smav min = res + 1; 5210182999Smav } while (1); 5211162922Sariff} 5212162922Sariff 5213182999Smav/* 5214182999Smav * Trace association path from input to ADC 5215182999Smav */ 5216162922Sariffstatic int 5217182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 5218162922Sariff{ 5219182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5220162922Sariff struct hdac_widget *w; 5221182999Smav int i, j, k; 5222162922Sariff 5223182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5224182999Smav w = hdac_widget_get(devinfo, j); 5225182999Smav if (w == NULL || w->enable == 0) 5226182999Smav continue; 5227182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5228182999Smav continue; 5229182999Smav if (w->bindas >= 0 && w->bindas != as) 5230182999Smav continue; 5231182999Smav 5232182999Smav /* Find next pin */ 5233182999Smav for (i = 0; i < 16; i++) { 5234182999Smav if (ases[as].pins[i] == 0) 5235182999Smav continue; 5236182999Smav 5237183097Smav HDA_BOOTHVERBOSE( 5238182999Smav device_printf(devinfo->codec->sc->dev, 5239182999Smav " Tracing pin %d to ADC %d\n", 5240182999Smav ases[as].pins[i], j); 5241182999Smav ); 5242182999Smav /* Trace this pin taking goal into account. */ 5243182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 5244182999Smav ases[as].pins[i], j, 0) == 0) { 5245182999Smav /* If we failed - return to previous and redo it. */ 5246182999Smav HDA_BOOTVERBOSE( 5247182999Smav device_printf(devinfo->codec->sc->dev, 5248183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 5249182999Smav ases[as].pins[i], j); 5250182999Smav ); 5251182999Smav hdac_audio_undo_trace(devinfo, as, -1); 5252182999Smav for (k = 0; k < 16; k++) 5253182999Smav ases[as].dacs[k] = 0; 5254182999Smav break; 5255162922Sariff } 5256182999Smav HDA_BOOTVERBOSE( 5257182999Smav device_printf(devinfo->codec->sc->dev, 5258183097Smav " Pin %d traced to ADC %d\n", 5259183097Smav ases[as].pins[i], j); 5260182999Smav ); 5261182999Smav ases[as].dacs[i] = j; 5262162922Sariff } 5263182999Smav if (i == 16) 5264182999Smav return (1); 5265162922Sariff } 5266182999Smav return (0); 5267162922Sariff} 5268162922Sariff 5269182999Smav/* 5270182999Smav * Trace input monitor path from mixer to output association. 5271182999Smav */ 5272183097Smavstatic int 5273182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5274162922Sariff{ 5275182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5276182999Smav struct hdac_widget *w, *wc; 5277182999Smav int i, j; 5278182999Smav nid_t res = 0; 5279162922Sariff 5280162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5281162922Sariff return (0); 5282162922Sariff w = hdac_widget_get(devinfo, nid); 5283162922Sariff if (w == NULL || w->enable == 0) 5284162922Sariff return (0); 5285183097Smav HDA_BOOTHVERBOSE( 5286182999Smav device_printf(devinfo->codec->sc->dev, 5287182999Smav " %*stracing via nid %d\n", 5288182999Smav depth + 1, "", w->nid); 5289182999Smav ); 5290182999Smav /* Use only unused widgets */ 5291182999Smav if (depth > 0 && w->bindas != -1) { 5292182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5293183097Smav HDA_BOOTHVERBOSE( 5294182999Smav device_printf(devinfo->codec->sc->dev, 5295182999Smav " %*snid %d found output association %d\n", 5296182999Smav depth + 1, "", w->nid, w->bindas); 5297182999Smav ); 5298202789Smav if (w->bindas >= 0) 5299202789Smav w->pflags |= HDA_ADC_MONITOR; 5300182999Smav return (1); 5301182999Smav } else { 5302183097Smav HDA_BOOTHVERBOSE( 5303182999Smav device_printf(devinfo->codec->sc->dev, 5304182999Smav " %*snid %d busy by input association %d\n", 5305182999Smav depth + 1, "", w->nid, w->bindas); 5306182999Smav ); 5307182999Smav return (0); 5308182999Smav } 5309182999Smav } 5310182999Smav 5311162922Sariff switch (w->type) { 5312162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5313182999Smav /* Do not traverse input. AD1988 has digital monitor 5314182999Smav for which we are not ready. */ 5315162922Sariff break; 5316162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5317182999Smav if (depth > 0) 5318182999Smav break; 5319182999Smav /* Fall */ 5320182999Smav default: 5321182999Smav /* Try to find reachable ADCs with specified nid. */ 5322182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5323182999Smav wc = hdac_widget_get(devinfo, j); 5324182999Smav if (wc == NULL || wc->enable == 0) 5325182999Smav continue; 5326182999Smav for (i = 0; i < wc->nconns; i++) { 5327182999Smav if (wc->connsenable[i] == 0) 5328182999Smav continue; 5329182999Smav if (wc->conns[i] != nid) 5330182999Smav continue; 5331182999Smav if (hdac_audio_trace_to_out(devinfo, 5332182999Smav j, depth + 1) != 0) { 5333182999Smav res = 1; 5334182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5335182999Smav wc->selconn == -1) 5336182999Smav wc->selconn = i; 5337182999Smav } 5338182999Smav } 5339162922Sariff } 5340162922Sariff break; 5341182999Smav } 5342202789Smav if (res && w->bindas == -1) 5343182999Smav w->bindas = -2; 5344182999Smav 5345183097Smav HDA_BOOTHVERBOSE( 5346182999Smav device_printf(devinfo->codec->sc->dev, 5347182999Smav " %*snid %d returned %d\n", 5348182999Smav depth + 1, "", w->nid, res); 5349182999Smav ); 5350182999Smav return (res); 5351182999Smav} 5352182999Smav 5353182999Smav/* 5354182999Smav * Trace extra associations (beeper, monitor) 5355182999Smav */ 5356182999Smavstatic void 5357182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5358182999Smav{ 5359182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5360182999Smav struct hdac_widget *w; 5361182999Smav int j; 5362182999Smav 5363182999Smav /* Input monitor */ 5364182999Smav /* Find mixer associated with input, but supplying signal 5365182999Smav for output associations. Hope it will be input monitor. */ 5366182999Smav HDA_BOOTVERBOSE( 5367182999Smav device_printf(devinfo->codec->sc->dev, 5368182999Smav "Tracing input monitor\n"); 5369182999Smav ); 5370182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5371182999Smav w = hdac_widget_get(devinfo, j); 5372182999Smav if (w == NULL || w->enable == 0) 5373182999Smav continue; 5374182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5375182999Smav continue; 5376182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5377182999Smav continue; 5378182999Smav HDA_BOOTVERBOSE( 5379182999Smav device_printf(devinfo->codec->sc->dev, 5380182999Smav " Tracing nid %d to out\n", 5381182999Smav j); 5382182999Smav ); 5383182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5384182999Smav HDA_BOOTVERBOSE( 5385182999Smav device_printf(devinfo->codec->sc->dev, 5386182999Smav " nid %d is input monitor\n", 5387182999Smav w->nid); 5388182999Smav ); 5389182999Smav w->ossdev = SOUND_MIXER_IMIX; 5390162922Sariff } 5391162922Sariff } 5392182999Smav 5393202789Smav /* Other inputs monitor */ 5394202789Smav /* Find input pins supplying signal for output associations. 5395202789Smav Hope it will be input monitoring. */ 5396202789Smav HDA_BOOTVERBOSE( 5397202789Smav device_printf(devinfo->codec->sc->dev, 5398202789Smav "Tracing other input monitors\n"); 5399202789Smav ); 5400202789Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5401202789Smav w = hdac_widget_get(devinfo, j); 5402202789Smav if (w == NULL || w->enable == 0) 5403202789Smav continue; 5404202789Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5405202789Smav continue; 5406202789Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5407202789Smav continue; 5408202789Smav HDA_BOOTVERBOSE( 5409202789Smav device_printf(devinfo->codec->sc->dev, 5410202789Smav " Tracing nid %d to out\n", 5411202789Smav j); 5412202789Smav ); 5413202789Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5414202789Smav HDA_BOOTVERBOSE( 5415202789Smav device_printf(devinfo->codec->sc->dev, 5416202789Smav " nid %d is input monitor\n", 5417202789Smav w->nid); 5418202789Smav ); 5419202789Smav } 5420202789Smav } 5421202789Smav 5422182999Smav /* Beeper */ 5423182999Smav HDA_BOOTVERBOSE( 5424182999Smav device_printf(devinfo->codec->sc->dev, 5425182999Smav "Tracing beeper\n"); 5426182999Smav ); 5427182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5428182999Smav w = hdac_widget_get(devinfo, j); 5429182999Smav if (w == NULL || w->enable == 0) 5430182999Smav continue; 5431182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5432182999Smav continue; 5433183097Smav HDA_BOOTHVERBOSE( 5434182999Smav device_printf(devinfo->codec->sc->dev, 5435182999Smav " Tracing nid %d to out\n", 5436182999Smav j); 5437182999Smav ); 5438183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5439183097Smav HDA_BOOTVERBOSE( 5440183097Smav device_printf(devinfo->codec->sc->dev, 5441183097Smav " nid %d traced to out\n", 5442183097Smav j); 5443183097Smav ); 5444183097Smav } 5445182999Smav w->bindas = -2; 5446182999Smav } 5447162922Sariff} 5448162922Sariff 5449182999Smav/* 5450182999Smav * Bind assotiations to PCM channels 5451182999Smav */ 5452182999Smavstatic void 5453182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5454162922Sariff{ 5455182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5456182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5457182999Smav int j, cnt = 0, free; 5458162922Sariff 5459182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5460182999Smav if (as[j].enable) 5461182999Smav cnt++; 5462182999Smav } 5463182999Smav if (sc->num_chans == 0) { 5464182999Smav sc->chans = (struct hdac_chan *)malloc( 5465182999Smav sizeof(struct hdac_chan) * cnt, 5466182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5467182999Smav if (sc->chans == NULL) { 5468190519Smav device_printf(sc->dev, 5469182999Smav "Channels memory allocation failed!\n"); 5470182999Smav return; 5471182999Smav } 5472182999Smav } else { 5473182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5474183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5475182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5476182999Smav if (sc->chans == NULL) { 5477182999Smav sc->num_chans = 0; 5478190519Smav device_printf(sc->dev, 5479182999Smav "Channels memory allocation failed!\n"); 5480182999Smav return; 5481182999Smav } 5482190519Smav /* Fixup relative pointers after realloc */ 5483190519Smav for (j = 0; j < sc->num_chans; j++) 5484190519Smav sc->chans[j].caps.fmtlist = sc->chans[j].fmtlist; 5485182999Smav } 5486182999Smav free = sc->num_chans; 5487182999Smav sc->num_chans += cnt; 5488162922Sariff 5489182999Smav for (j = free; j < free + cnt; j++) { 5490190519Smav sc->chans[j].devinfo = devinfo; 5491190519Smav sc->chans[j].as = -1; 5492182999Smav } 5493162922Sariff 5494182999Smav /* Assign associations in order of their numbers, */ 5495182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5496182999Smav if (as[j].enable == 0) 5497182999Smav continue; 5498182999Smav 5499182999Smav as[j].chan = free; 5500190519Smav sc->chans[free].as = j; 5501190519Smav sc->chans[free].dir = 5502185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5503190519Smav hdac_pcmchannel_setup(&sc->chans[free]); 5504182999Smav free++; 5505182999Smav } 5506182999Smav} 5507162922Sariff 5508182999Smavstatic void 5509182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5510182999Smav{ 5511182999Smav struct hdac_widget *w; 5512182999Smav int i; 5513182999Smav 5514182999Smav /* Disable power and volume widgets. */ 5515182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5516182999Smav w = hdac_widget_get(devinfo, i); 5517182999Smav if (w == NULL || w->enable == 0) 5518182999Smav continue; 5519182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5520182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5521182999Smav w->enable = 0; 5522183097Smav HDA_BOOTHVERBOSE( 5523182999Smav device_printf(devinfo->codec->sc->dev, 5524182999Smav " Disabling nid %d due to it's" 5525182999Smav " non-audio type.\n", 5526182999Smav w->nid); 5527182999Smav ); 5528162922Sariff } 5529182999Smav } 5530182999Smav} 5531182999Smav 5532182999Smavstatic void 5533182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5534182999Smav{ 5535182999Smav struct hdac_widget *w, *cw; 5536182999Smav struct hdac_audio_ctl *ctl; 5537182999Smav int done, found, i, j, k; 5538182999Smav 5539182999Smav /* Disable useless pins. */ 5540182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5541182999Smav w = hdac_widget_get(devinfo, i); 5542182999Smav if (w == NULL || w->enable == 0) 5543182999Smav continue; 5544184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5545184991Smav if ((w->wclass.pin.config & 5546184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5547184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5548184991Smav w->enable = 0; 5549184991Smav HDA_BOOTHVERBOSE( 5550184991Smav device_printf(devinfo->codec->sc->dev, 5551184991Smav " Disabling pin nid %d due" 5552184991Smav " to None connectivity.\n", 5553184991Smav w->nid); 5554184991Smav ); 5555184991Smav } else if ((w->wclass.pin.config & 5556184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5557184991Smav w->enable = 0; 5558184991Smav HDA_BOOTHVERBOSE( 5559184991Smav device_printf(devinfo->codec->sc->dev, 5560184991Smav " Disabling unassociated" 5561184991Smav " pin nid %d.\n", 5562184991Smav w->nid); 5563184991Smav ); 5564184991Smav } 5565182999Smav } 5566182999Smav } 5567182999Smav do { 5568182999Smav done = 1; 5569182999Smav /* Disable and mute controls for disabled widgets. */ 5570162922Sariff i = 0; 5571162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5572182999Smav if (ctl->enable == 0) 5573162922Sariff continue; 5574182999Smav if (ctl->widget->enable == 0 || 5575182999Smav (ctl->childwidget != NULL && 5576182999Smav ctl->childwidget->enable == 0)) { 5577182999Smav ctl->forcemute = 1; 5578182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5579182999Smav ctl->left = 0; 5580182999Smav ctl->right = 0; 5581182999Smav ctl->enable = 0; 5582182999Smav if (ctl->ndir == HDA_CTL_IN) 5583182999Smav ctl->widget->connsenable[ctl->index] = 0; 5584182999Smav done = 0; 5585183097Smav HDA_BOOTHVERBOSE( 5586182999Smav device_printf(devinfo->codec->sc->dev, 5587182999Smav " Disabling ctl %d nid %d cnid %d due" 5588182999Smav " to disabled widget.\n", i, 5589182999Smav ctl->widget->nid, 5590182999Smav (ctl->childwidget != NULL)? 5591182999Smav ctl->childwidget->nid:-1); 5592182999Smav ); 5593182999Smav } 5594182999Smav } 5595182999Smav /* Disable useless widgets. */ 5596182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5597182999Smav w = hdac_widget_get(devinfo, i); 5598182999Smav if (w == NULL || w->enable == 0) 5599182999Smav continue; 5600182999Smav /* Disable inputs with disabled child widgets. */ 5601182999Smav for (j = 0; j < w->nconns; j++) { 5602182999Smav if (w->connsenable[j]) { 5603182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5604182999Smav if (cw == NULL || cw->enable == 0) { 5605182999Smav w->connsenable[j] = 0; 5606183097Smav HDA_BOOTHVERBOSE( 5607182999Smav device_printf(devinfo->codec->sc->dev, 5608182999Smav " Disabling nid %d connection %d due" 5609182999Smav " to disabled child widget.\n", 5610182999Smav i, j); 5611182999Smav ); 5612163057Sariff } 5613163057Sariff } 5614162922Sariff } 5615182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5616182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5617162922Sariff continue; 5618182999Smav /* Disable mixers and selectors without inputs. */ 5619182999Smav found = 0; 5620182999Smav for (j = 0; j < w->nconns; j++) { 5621182999Smav if (w->connsenable[j]) { 5622182999Smav found = 1; 5623162922Sariff break; 5624162922Sariff } 5625182999Smav } 5626182999Smav if (found == 0) { 5627182999Smav w->enable = 0; 5628182999Smav done = 0; 5629183097Smav HDA_BOOTHVERBOSE( 5630182999Smav device_printf(devinfo->codec->sc->dev, 5631182999Smav " Disabling nid %d due to all it's" 5632182999Smav " inputs disabled.\n", w->nid); 5633182999Smav ); 5634182999Smav } 5635182999Smav /* Disable nodes without consumers. */ 5636182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5637182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5638182999Smav continue; 5639182999Smav found = 0; 5640182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5641182999Smav cw = hdac_widget_get(devinfo, k); 5642182999Smav if (cw == NULL || cw->enable == 0) 5643182999Smav continue; 5644182999Smav for (j = 0; j < cw->nconns; j++) { 5645182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5646182999Smav found = 1; 5647182999Smav break; 5648182999Smav } 5649162922Sariff } 5650162922Sariff } 5651182999Smav if (found == 0) { 5652182999Smav w->enable = 0; 5653182999Smav done = 0; 5654183097Smav HDA_BOOTHVERBOSE( 5655182999Smav device_printf(devinfo->codec->sc->dev, 5656182999Smav " Disabling nid %d due to all it's" 5657182999Smav " consumers disabled.\n", w->nid); 5658182999Smav ); 5659182999Smav } 5660162922Sariff } 5661182999Smav } while (done == 0); 5662182999Smav 5663182999Smav} 5664182999Smav 5665182999Smavstatic void 5666182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5667182999Smav{ 5668182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5669182999Smav struct hdac_widget *w, *cw; 5670182999Smav struct hdac_audio_ctl *ctl; 5671182999Smav int i, j, k; 5672182999Smav 5673182999Smav /* Disable unassosiated widgets. */ 5674182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5675182999Smav w = hdac_widget_get(devinfo, i); 5676182999Smav if (w == NULL || w->enable == 0) 5677182999Smav continue; 5678182999Smav if (w->bindas == -1) { 5679182999Smav w->enable = 0; 5680183097Smav HDA_BOOTHVERBOSE( 5681182999Smav device_printf(devinfo->codec->sc->dev, 5682182999Smav " Disabling unassociated nid %d.\n", 5683182999Smav w->nid); 5684182999Smav ); 5685182999Smav } 5686182999Smav } 5687182999Smav /* Disable input connections on input pin and 5688182999Smav * output on output. */ 5689182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5690182999Smav w = hdac_widget_get(devinfo, i); 5691182999Smav if (w == NULL || w->enable == 0) 5692182999Smav continue; 5693182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5694182999Smav continue; 5695182999Smav if (w->bindas < 0) 5696182999Smav continue; 5697182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5698182999Smav for (j = 0; j < w->nconns; j++) { 5699182999Smav if (w->connsenable[j] == 0) 5700182999Smav continue; 5701182999Smav w->connsenable[j] = 0; 5702183097Smav HDA_BOOTHVERBOSE( 5703182999Smav device_printf(devinfo->codec->sc->dev, 5704182999Smav " Disabling connection to input pin " 5705182999Smav "nid %d conn %d.\n", 5706182999Smav i, j); 5707182999Smav ); 5708162922Sariff } 5709182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5710182999Smav HDA_CTL_IN, -1, 1); 5711182999Smav if (ctl && ctl->enable) { 5712182999Smav ctl->forcemute = 1; 5713182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5714182999Smav ctl->left = 0; 5715182999Smav ctl->right = 0; 5716182999Smav ctl->enable = 0; 5717182999Smav } 5718182999Smav } else { 5719182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5720182999Smav HDA_CTL_OUT, -1, 1); 5721182999Smav if (ctl && ctl->enable) { 5722182999Smav ctl->forcemute = 1; 5723182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5724182999Smav ctl->left = 0; 5725182999Smav ctl->right = 0; 5726182999Smav ctl->enable = 0; 5727182999Smav } 5728182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5729182999Smav cw = hdac_widget_get(devinfo, k); 5730182999Smav if (cw == NULL || cw->enable == 0) 5731182999Smav continue; 5732182999Smav for (j = 0; j < cw->nconns; j++) { 5733182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5734182999Smav cw->connsenable[j] = 0; 5735183097Smav HDA_BOOTHVERBOSE( 5736182999Smav device_printf(devinfo->codec->sc->dev, 5737182999Smav " Disabling connection from output pin " 5738182999Smav "nid %d conn %d cnid %d.\n", 5739182999Smav k, j, i); 5740182999Smav ); 5741182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5742182999Smav cw->nconns > 1) 5743182999Smav continue; 5744182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5745182999Smav HDA_CTL_IN, j, 1); 5746182999Smav if (ctl && ctl->enable) { 5747182999Smav ctl->forcemute = 1; 5748182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5749182999Smav ctl->left = 0; 5750182999Smav ctl->right = 0; 5751182999Smav ctl->enable = 0; 5752182999Smav } 5753182999Smav } 5754182999Smav } 5755182999Smav } 5756162922Sariff } 5757162922Sariff } 5758162922Sariff} 5759162922Sariff 5760182999Smavstatic void 5761182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5762162922Sariff{ 5763182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5764182999Smav struct hdac_widget *w; 5765182999Smav int i, j; 5766182999Smav 5767182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5768182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5769182999Smav w = hdac_widget_get(devinfo, i); 5770182999Smav if (w == NULL || w->enable == 0) 5771182999Smav continue; 5772182999Smav if (w->nconns <= 1) 5773182999Smav continue; 5774182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5775182999Smav continue; 5776182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5777182999Smav continue; 5778182999Smav for (j = 0; j < w->nconns; j++) { 5779182999Smav if (w->connsenable[j] == 0) 5780182999Smav continue; 5781182999Smav if (w->selconn < 0 || w->selconn == j) 5782182999Smav continue; 5783182999Smav w->connsenable[j] = 0; 5784183097Smav HDA_BOOTHVERBOSE( 5785182999Smav device_printf(devinfo->codec->sc->dev, 5786182999Smav " Disabling unselected connection " 5787182999Smav "nid %d conn %d.\n", 5788182999Smav i, j); 5789182999Smav ); 5790182999Smav } 5791182999Smav } 5792182999Smav} 5793182999Smav 5794182999Smavstatic void 5795182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5796182999Smav{ 5797202789Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5798162922Sariff struct hdac_widget *w, *cw; 5799162922Sariff struct hdac_audio_ctl *ctl; 5800182999Smav int i, j; 5801162922Sariff 5802187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5803182999Smav /* ... using selectors */ 5804182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5805182999Smav w = hdac_widget_get(devinfo, i); 5806182999Smav if (w == NULL || w->enable == 0) 5807182999Smav continue; 5808182999Smav if (w->nconns <= 1) 5809182999Smav continue; 5810182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5811182999Smav continue; 5812182999Smav if (w->bindas == -2) 5813182999Smav continue; 5814182999Smav for (j = 0; j < w->nconns; j++) { 5815182999Smav if (w->connsenable[j] == 0) 5816182999Smav continue; 5817182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5818182999Smav if (cw == NULL || w->enable == 0) 5819182999Smav continue; 5820202789Smav if (cw->bindas == -2 || 5821202789Smav ((w->pflags & HDA_ADC_MONITOR) && 5822202789Smav cw->bindas >= 0 && 5823202789Smav ases[cw->bindas].dir == HDA_CTL_IN)) 5824182999Smav continue; 5825187052Smav if (w->bindas == cw->bindas && 5826187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5827187052Smav continue; 5828182999Smav w->connsenable[j] = 0; 5829183097Smav HDA_BOOTHVERBOSE( 5830182999Smav device_printf(devinfo->codec->sc->dev, 5831182999Smav " Disabling crossassociatement connection " 5832182999Smav "nid %d conn %d cnid %d.\n", 5833182999Smav i, j, cw->nid); 5834182999Smav ); 5835182999Smav } 5836182999Smav } 5837182999Smav /* ... using controls */ 5838182999Smav i = 0; 5839182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5840182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5841182999Smav continue; 5842202789Smav if (ctl->widget->bindas == -2) 5843182999Smav continue; 5844202789Smav if (ctl->childwidget->bindas == -2 || 5845202789Smav ((ctl->widget->pflags & HDA_ADC_MONITOR) && 5846202789Smav ctl->childwidget->bindas >= 0 && 5847202789Smav ases[ctl->childwidget->bindas].dir == HDA_CTL_IN)) 5848202789Smav continue; 5849187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5850187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5851182999Smav ctl->forcemute = 1; 5852182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5853182999Smav ctl->left = 0; 5854182999Smav ctl->right = 0; 5855182999Smav ctl->enable = 0; 5856182999Smav if (ctl->ndir == HDA_CTL_IN) 5857182999Smav ctl->widget->connsenable[ctl->index] = 0; 5858183097Smav HDA_BOOTHVERBOSE( 5859182999Smav device_printf(devinfo->codec->sc->dev, 5860182999Smav " Disabling crossassociatement connection " 5861182999Smav "ctl %d nid %d cnid %d.\n", i, 5862182999Smav ctl->widget->nid, 5863182999Smav ctl->childwidget->nid); 5864182999Smav ); 5865182999Smav } 5866182999Smav } 5867182999Smav 5868182999Smav} 5869182999Smav 5870182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5871182999Smav 5872182999Smav/* 5873182999Smav * Find controls to control amplification for source. 5874182999Smav */ 5875182999Smavstatic int 5876182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5877182999Smav int ossdev, int ctlable, int depth, int need) 5878182999Smav{ 5879182999Smav struct hdac_widget *w, *wc; 5880182999Smav struct hdac_audio_ctl *ctl; 5881182999Smav int i, j, conns = 0, rneed; 5882182999Smav 5883162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5884182999Smav return (need); 5885162922Sariff 5886162922Sariff w = hdac_widget_get(devinfo, nid); 5887162922Sariff if (w == NULL || w->enable == 0) 5888182999Smav return (need); 5889182999Smav 5890182999Smav /* Count number of active inputs. */ 5891182999Smav if (depth > 0) { 5892182999Smav for (j = 0; j < w->nconns; j++) { 5893182999Smav if (w->connsenable[j]) 5894182999Smav conns++; 5895162922Sariff } 5896162922Sariff } 5897182999Smav 5898182999Smav /* If this is not a first step - use input mixer. 5899182999Smav Pins have common input ctl so care must be taken. */ 5900182999Smav if (depth > 0 && ctlable && (conns == 1 || 5901182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5902182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5903182999Smav index, 1); 5904182999Smav if (ctl) { 5905182999Smav if (HDA_CTL_GIVE(ctl) & need) 5906182999Smav ctl->ossmask |= (1 << ossdev); 5907182999Smav else 5908182999Smav ctl->possmask |= (1 << ossdev); 5909182999Smav need &= ~HDA_CTL_GIVE(ctl); 5910182999Smav } 5911182999Smav } 5912182999Smav 5913182999Smav /* If widget has own ossdev - not traverse it. 5914182999Smav It will be traversed on it's own. */ 5915182999Smav if (w->ossdev >= 0 && depth > 0) 5916182999Smav return (need); 5917182999Smav 5918182999Smav /* We must not traverse pin */ 5919182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5920182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5921182999Smav depth > 0) 5922182999Smav return (need); 5923182999Smav 5924182999Smav /* record that this widget exports such signal, */ 5925182999Smav w->ossmask |= (1 << ossdev); 5926182999Smav 5927182999Smav /* If signals mixed, we can't assign controls farther. 5928182999Smav * Ignore this on depth zero. Caller must knows why. 5929182999Smav * Ignore this for static selectors if this input selected. 5930182999Smav */ 5931182999Smav if (conns > 1) 5932182999Smav ctlable = 0; 5933182999Smav 5934182999Smav if (ctlable) { 5935182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5936182999Smav if (ctl) { 5937182999Smav if (HDA_CTL_GIVE(ctl) & need) 5938182999Smav ctl->ossmask |= (1 << ossdev); 5939182999Smav else 5940182999Smav ctl->possmask |= (1 << ossdev); 5941182999Smav need &= ~HDA_CTL_GIVE(ctl); 5942182999Smav } 5943182999Smav } 5944182999Smav 5945182999Smav rneed = 0; 5946182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5947182999Smav wc = hdac_widget_get(devinfo, i); 5948182999Smav if (wc == NULL || wc->enable == 0) 5949162922Sariff continue; 5950182999Smav for (j = 0; j < wc->nconns; j++) { 5951182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5952182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5953182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5954182999Smav } 5955162922Sariff } 5956162922Sariff } 5957182999Smav rneed &= need; 5958182999Smav 5959182999Smav return (rneed); 5960162922Sariff} 5961162922Sariff 5962182999Smav/* 5963182999Smav * Find controls to control amplification for destination. 5964182999Smav */ 5965182999Smavstatic void 5966202789Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5967182999Smav int ossdev, int depth, int need) 5968162922Sariff{ 5969182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5970182999Smav struct hdac_widget *w, *wc; 5971182999Smav struct hdac_audio_ctl *ctl; 5972182999Smav int i, j, consumers; 5973182999Smav 5974162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5975182999Smav return; 5976162922Sariff 5977162922Sariff w = hdac_widget_get(devinfo, nid); 5978162922Sariff if (w == NULL || w->enable == 0) 5979182999Smav return; 5980182999Smav 5981182999Smav if (depth > 0) { 5982182999Smav /* If this node produce output for several consumers, 5983182999Smav we can't touch it. */ 5984182999Smav consumers = 0; 5985182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5986182999Smav wc = hdac_widget_get(devinfo, i); 5987182999Smav if (wc == NULL || wc->enable == 0) 5988182999Smav continue; 5989182999Smav for (j = 0; j < wc->nconns; j++) { 5990182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5991182999Smav consumers++; 5992182999Smav } 5993182999Smav } 5994182999Smav /* The only exception is if real HP redirection is configured 5995182999Smav and this is a duplication point. 5996182999Smav XXX: Actually exception is not completely correct. 5997182999Smav XXX: Duplication point check is not perfect. */ 5998182999Smav if ((consumers == 2 && (w->bindas < 0 || 5999182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 6000182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 6001182999Smav consumers > 2) 6002182999Smav return; 6003182999Smav 6004182999Smav /* Else use it's output mixer. */ 6005182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 6006182999Smav HDA_CTL_OUT, -1, 1); 6007182999Smav if (ctl) { 6008182999Smav if (HDA_CTL_GIVE(ctl) & need) 6009182999Smav ctl->ossmask |= (1 << ossdev); 6010182999Smav else 6011182999Smav ctl->possmask |= (1 << ossdev); 6012182999Smav need &= ~HDA_CTL_GIVE(ctl); 6013182999Smav } 6014182999Smav } 6015182999Smav 6016182999Smav /* We must not traverse pin */ 6017182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6018182999Smav depth > 0) 6019182999Smav return; 6020182999Smav 6021162922Sariff for (i = 0; i < w->nconns; i++) { 6022182999Smav int tneed = need; 6023182999Smav if (w->connsenable[i] == 0) 6024162922Sariff continue; 6025202789Smav if (index >= 0 && i != index) 6026202789Smav continue; 6027182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 6028182999Smav HDA_CTL_IN, i, 1); 6029182999Smav if (ctl) { 6030182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 6031182999Smav ctl->ossmask |= (1 << ossdev); 6032182999Smav else 6033182999Smav ctl->possmask |= (1 << ossdev); 6034182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 6035162922Sariff } 6036202789Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev, 6037182999Smav depth + 1, tneed); 6038162922Sariff } 6039162922Sariff} 6040162922Sariff 6041182999Smav/* 6042182999Smav * Assign OSS names to sound sources 6043182999Smav */ 6044182999Smavstatic void 6045182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 6046162922Sariff{ 6047182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6048182999Smav struct hdac_widget *w; 6049182999Smav int i, j; 6050182999Smav int type = -1, use, used = 0; 6051182999Smav static const int types[7][13] = { 6052182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6053182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 6054182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 6055182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 6056182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 6057182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 6058182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 6059182999Smav -1 }, /* digital */ 6060182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6061182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 6062182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 6063182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 6064182999Smav -1 } /* others */ 6065182999Smav }; 6066162922Sariff 6067182999Smav /* Surely known names */ 6068162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6069162922Sariff w = hdac_widget_get(devinfo, i); 6070162922Sariff if (w == NULL || w->enable == 0) 6071162922Sariff continue; 6072182999Smav if (w->bindas == -1) 6073182999Smav continue; 6074182999Smav use = -1; 6075182999Smav switch (w->type) { 6076182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 6077182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6078182999Smav break; 6079182999Smav type = -1; 6080182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6081182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 6082182999Smav type = 0; 6083182999Smav break; 6084182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6085182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 6086182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 6087182999Smav break; 6088182999Smav type = 1; 6089182999Smav break; 6090182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 6091182999Smav type = 3; 6092182999Smav break; 6093182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6094182999Smav type = 4; 6095182999Smav break; 6096182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 6097182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 6098182999Smav type = 5; 6099182999Smav break; 6100182999Smav } 6101182999Smav if (type == -1) 6102182999Smav break; 6103182999Smav j = 0; 6104182999Smav while (types[type][j] >= 0 && 6105182999Smav (used & (1 << types[type][j])) != 0) { 6106182999Smav j++; 6107182999Smav } 6108182999Smav if (types[type][j] >= 0) 6109182999Smav use = types[type][j]; 6110182999Smav break; 6111182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 6112182999Smav use = SOUND_MIXER_PCM; 6113182999Smav break; 6114182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 6115182999Smav use = SOUND_MIXER_SPEAKER; 6116182999Smav break; 6117182999Smav default: 6118182999Smav break; 6119182999Smav } 6120182999Smav if (use >= 0) { 6121182999Smav w->ossdev = use; 6122182999Smav used |= (1 << use); 6123182999Smav } 6124182999Smav } 6125182999Smav /* Semi-known names */ 6126182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6127182999Smav w = hdac_widget_get(devinfo, i); 6128182999Smav if (w == NULL || w->enable == 0) 6129182999Smav continue; 6130182999Smav if (w->ossdev >= 0) 6131182999Smav continue; 6132182999Smav if (w->bindas == -1) 6133182999Smav continue; 6134162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6135162922Sariff continue; 6136182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6137162922Sariff continue; 6138182999Smav type = -1; 6139182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6140182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 6141182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6142182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 6143182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 6144182999Smav type = 0; 6145182999Smav break; 6146182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6147182999Smav type = 2; 6148182999Smav break; 6149182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 6150182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 6151182999Smav type = 5; 6152182999Smav break; 6153182999Smav } 6154182999Smav if (type == -1) 6155182999Smav break; 6156182999Smav j = 0; 6157182999Smav while (types[type][j] >= 0 && 6158182999Smav (used & (1 << types[type][j])) != 0) { 6159182999Smav j++; 6160182999Smav } 6161182999Smav if (types[type][j] >= 0) { 6162182999Smav w->ossdev = types[type][j]; 6163182999Smav used |= (1 << types[type][j]); 6164182999Smav } 6165182999Smav } 6166182999Smav /* Others */ 6167182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6168182999Smav w = hdac_widget_get(devinfo, i); 6169182999Smav if (w == NULL || w->enable == 0) 6170162922Sariff continue; 6171182999Smav if (w->ossdev >= 0) 6172182999Smav continue; 6173182999Smav if (w->bindas == -1) 6174182999Smav continue; 6175182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6176182999Smav continue; 6177182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6178182999Smav continue; 6179182999Smav j = 0; 6180182999Smav while (types[6][j] >= 0 && 6181182999Smav (used & (1 << types[6][j])) != 0) { 6182182999Smav j++; 6183162922Sariff } 6184182999Smav if (types[6][j] >= 0) { 6185182999Smav w->ossdev = types[6][j]; 6186182999Smav used |= (1 << types[6][j]); 6187182999Smav } 6188162922Sariff } 6189162922Sariff} 6190162922Sariff 6191162922Sariffstatic void 6192162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 6193162922Sariff{ 6194182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6195182999Smav int j, res; 6196162922Sariff 6197182999Smav /* Trace all associations in order of their numbers, */ 6198182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 6199182999Smav if (as[j].enable == 0) 6200182999Smav continue; 6201163057Sariff HDA_BOOTVERBOSE( 6202162922Sariff device_printf(devinfo->codec->sc->dev, 6203182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6204162922Sariff ); 6205182999Smav if (as[j].dir == HDA_CTL_OUT) { 6206182999Smavretry: 6207182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6208182999Smav if (res == 0 && as[j].hpredir >= 0 && 6209182999Smav as[j].fakeredir == 0) { 6210182999Smav /* If codec can't do analog HP redirection 6211182999Smav try to make it using one more DAC. */ 6212182999Smav as[j].fakeredir = 1; 6213182999Smav goto retry; 6214182999Smav } 6215182999Smav } else { 6216182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6217182999Smav } 6218182999Smav if (res) { 6219182999Smav HDA_BOOTVERBOSE( 6220182999Smav device_printf(devinfo->codec->sc->dev, 6221188510Smav "Association %d (%d) trace succeeded\n", 6222182999Smav j, as[j].index); 6223182999Smav ); 6224182999Smav } else { 6225182999Smav HDA_BOOTVERBOSE( 6226182999Smav device_printf(devinfo->codec->sc->dev, 6227182999Smav "Association %d (%d) trace failed\n", 6228182999Smav j, as[j].index); 6229182999Smav ); 6230182999Smav as[j].enable = 0; 6231182999Smav } 6232162922Sariff } 6233162922Sariff 6234182999Smav /* Trace mixer and beeper pseudo associations. */ 6235182999Smav hdac_audio_trace_as_extra(devinfo); 6236182999Smav} 6237162922Sariff 6238182999Smavstatic void 6239182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6240182999Smav{ 6241182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6242182999Smav struct hdac_audio_ctl *ctl; 6243202789Smav struct hdac_widget *w, *cw; 6244202789Smav int i, j; 6245162922Sariff 6246182999Smav /* Assign mixers to the tree. */ 6247162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6248162922Sariff w = hdac_widget_get(devinfo, i); 6249162922Sariff if (w == NULL || w->enable == 0) 6250162922Sariff continue; 6251182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6252182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6253182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6254182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6255182999Smav if (w->ossdev < 0) 6256182999Smav continue; 6257182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6258182999Smav w->ossdev, 1, 0, 1); 6259182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6260202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6261182999Smav SOUND_MIXER_RECLEV, 0, 1); 6262182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6263182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6264202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6265182999Smav SOUND_MIXER_VOLUME, 0, 1); 6266162922Sariff } 6267202796Smav if (w->ossdev == SOUND_MIXER_IMIX) { 6268202796Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6269202796Smav w->ossdev, 1, 0, 1)) { 6270202796Smav /* If we are unable to control input monitor 6271202796Smav as source - try to control it as destination. */ 6272202796Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6273202796Smav w->ossdev, 0, 1); 6274202796Smav } 6275202796Smav } 6276202789Smav if (w->pflags & HDA_ADC_MONITOR) { 6277202789Smav for (j = 0; j < w->nconns; j++) { 6278202789Smav if (!w->connsenable[j]) 6279202789Smav continue; 6280202789Smav cw = hdac_widget_get(devinfo, w->conns[j]); 6281202789Smav if (cw == NULL || cw->enable == 0) 6282202789Smav continue; 6283202789Smav if (cw->bindas == -1) 6284202789Smav continue; 6285202789Smav if (cw->bindas >= 0 && 6286202789Smav as[cw->bindas].dir != HDA_CTL_IN) 6287202789Smav continue; 6288202789Smav hdac_audio_ctl_dest_amp(devinfo, 6289202796Smav w->nid, j, SOUND_MIXER_IGAIN, 0, 1); 6290202789Smav } 6291202789Smav } 6292162922Sariff } 6293182999Smav /* Treat unrequired as possible. */ 6294182999Smav i = 0; 6295182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6296182999Smav if (ctl->ossmask == 0) 6297182999Smav ctl->ossmask = ctl->possmask; 6298182999Smav } 6299182999Smav} 6300162922Sariff 6301182999Smavstatic void 6302182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6303182999Smav{ 6304182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6305182999Smav struct hdac_widget *w; 6306182999Smav uint32_t pincap; 6307182999Smav int i; 6308182999Smav 6309182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6310182999Smav w = &devinfo->widget[i]; 6311182999Smav if (w == NULL) 6312162922Sariff continue; 6313182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6314162922Sariff continue; 6315182999Smav 6316182999Smav pincap = w->wclass.pin.cap; 6317182999Smav 6318182999Smav /* Disable everything. */ 6319182999Smav w->wclass.pin.ctrl &= ~( 6320182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6321182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6322182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6323182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6324182999Smav 6325182999Smav if (w->enable == 0 || 6326182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6327182999Smav /* Pin is unused so left it disabled. */ 6328182999Smav continue; 6329182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6330182999Smav /* Input pin, configure for input. */ 6331182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6332182999Smav w->wclass.pin.ctrl |= 6333182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6334182999Smav 6335182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6336182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6337182999Smav w->wclass.pin.ctrl |= 6338182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6339182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6340182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6341182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6342182999Smav w->wclass.pin.ctrl |= 6343182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6344182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6345182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6346182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6347182999Smav w->wclass.pin.ctrl |= 6348182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6349182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6350182999Smav } else { 6351182999Smav /* Output pin, configure for output. */ 6352182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6353182999Smav w->wclass.pin.ctrl |= 6354182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6355182999Smav 6356182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6357182999Smav (w->wclass.pin.config & 6358182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6359182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6360182999Smav w->wclass.pin.ctrl |= 6361182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6362182999Smav 6363182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6364182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6365182999Smav w->wclass.pin.ctrl |= 6366182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6367182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6368182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6369182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6370182999Smav w->wclass.pin.ctrl |= 6371182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6372182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6373182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6374182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6375182999Smav w->wclass.pin.ctrl |= 6376182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6377182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6378182999Smav } 6379162922Sariff } 6380162922Sariff} 6381162922Sariff 6382162922Sariffstatic void 6383187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6384187154Smav{ 6385187154Smav struct hdac_audio_ctl *ctl; 6386187154Smav int i, z; 6387187154Smav 6388187154Smav i = 0; 6389187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6390187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6391187154Smav /* Mute disabled and mixer controllable controls. 6392187154Smav * Last will be initialized by mixer_init(). 6393187154Smav * This expected to reduce click on startup. */ 6394187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6395187154Smav continue; 6396187154Smav } 6397187154Smav /* Init fixed controls to 0dB amplification. */ 6398187154Smav z = ctl->offset; 6399187154Smav if (z > ctl->step) 6400187154Smav z = ctl->step; 6401187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6402187154Smav } 6403187154Smav} 6404187154Smav 6405187154Smavstatic void 6406182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6407162922Sariff{ 6408162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6409162922Sariff struct hdac_widget *w; 6410164750Sariff nid_t cad; 6411182999Smav uint32_t gdata, gmask, gdir; 6412182999Smav int commitgpio, numgpio; 6413164750Sariff int i; 6414162922Sariff 6415162922Sariff cad = devinfo->codec->cad; 6416162922Sariff 6417182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6418182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6419182999Smav 0x7e7, 0), cad); 6420169277Sariff 6421187154Smav /* Commit controls. */ 6422187154Smav hdac_audio_ctl_commit(devinfo); 6423187154Smav 6424187154Smav /* Commit selectors, pins and EAPD. */ 6425187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6426187154Smav w = &devinfo->widget[i]; 6427187154Smav if (w == NULL) 6428187154Smav continue; 6429187154Smav if (w->selconn == -1) 6430187154Smav w->selconn = 0; 6431187154Smav if (w->nconns > 0) 6432187154Smav hdac_widget_connection_select(w, w->selconn); 6433187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6434187154Smav hdac_command(sc, 6435187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6436187154Smav w->wclass.pin.ctrl), cad); 6437187154Smav } 6438187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6439187154Smav uint32_t val; 6440187154Smav 6441187154Smav val = w->param.eapdbtl; 6442187154Smav if (devinfo->function.audio.quirks & 6443187154Smav HDA_QUIRK_EAPDINV) 6444187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6445187154Smav hdac_command(sc, 6446187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6447187154Smav val), cad); 6448187154Smav } 6449187154Smav } 6450187154Smav 6451187154Smav /* Commit GPIOs. */ 6452182999Smav gdata = 0; 6453182999Smav gmask = 0; 6454182999Smav gdir = 0; 6455182999Smav commitgpio = 0; 6456182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6457182999Smav devinfo->function.audio.gpio); 6458166796Sariff 6459182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6460182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6461182999Smav else { 6462182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6463182999Smav if (!(devinfo->function.audio.quirks & 6464182999Smav (1 << i))) 6465182999Smav continue; 6466182999Smav if (commitgpio == 0) { 6467182999Smav commitgpio = 1; 6468182999Smav HDA_BOOTVERBOSE( 6469182999Smav gdata = hdac_command(sc, 6470182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6471182999Smav devinfo->nid), cad); 6472182999Smav gmask = hdac_command(sc, 6473182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6474182999Smav devinfo->nid), cad); 6475182999Smav gdir = hdac_command(sc, 6476182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6477182999Smav devinfo->nid), cad); 6478182999Smav device_printf(sc->dev, 6479182999Smav "GPIO init: data=0x%08x " 6480182999Smav "mask=0x%08x dir=0x%08x\n", 6481182999Smav gdata, gmask, gdir); 6482182999Smav gdata = 0; 6483182999Smav gmask = 0; 6484182999Smav gdir = 0; 6485182999Smav ); 6486165039Sariff } 6487182999Smav gdata |= 1 << i; 6488182999Smav gmask |= 1 << i; 6489182999Smav gdir |= 1 << i; 6490165039Sariff } 6491182999Smav } 6492165039Sariff 6493182999Smav if (commitgpio != 0) { 6494182999Smav HDA_BOOTVERBOSE( 6495182999Smav device_printf(sc->dev, 6496182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6497182999Smav "dir=0x%08x\n", 6498182999Smav gdata, gmask, gdir); 6499182999Smav ); 6500182999Smav hdac_command(sc, 6501182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6502182999Smav gmask), cad); 6503182999Smav hdac_command(sc, 6504182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6505182999Smav gdir), cad); 6506182999Smav hdac_command(sc, 6507182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6508182999Smav gdata), cad); 6509162922Sariff } 6510162922Sariff} 6511162922Sariff 6512162922Sariffstatic void 6513182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6514182999Smav{ 6515182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6516182999Smav nid_t cad = devinfo->codec->cad; 6517182999Smav int i; 6518182999Smav 6519182999Smav hdac_command(sc, 6520182999Smav HDA_CMD_SET_POWER_STATE(cad, 6521182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6522182999Smav cad); 6523182999Smav DELAY(100); 6524182999Smav 6525182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6526182999Smav hdac_command(sc, 6527182999Smav HDA_CMD_SET_POWER_STATE(cad, 6528182999Smav i, HDA_CMD_POWER_STATE_D0), 6529182999Smav cad); 6530182999Smav } 6531182999Smav DELAY(1000); 6532182999Smav} 6533182999Smav 6534162922Sariffstatic int 6535182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6536162922Sariff{ 6537182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6538182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6539162922Sariff struct hdac_widget *w; 6540182999Smav uint32_t cap, fmtcap, pcmcap; 6541202127Smav int i, j, ret, channels, onlystereo; 6542202127Smav uint16_t pinset; 6543162922Sariff 6544162922Sariff ch->caps = hdac_caps; 6545162922Sariff ch->caps.fmtlist = ch->fmtlist; 6546162922Sariff ch->bit16 = 1; 6547162922Sariff ch->bit32 = 0; 6548162922Sariff ch->pcmrates[0] = 48000; 6549162922Sariff ch->pcmrates[1] = 0; 6550162922Sariff 6551162922Sariff ret = 0; 6552202127Smav channels = 0; 6553202127Smav onlystereo = 1; 6554202127Smav pinset = 0; 6555162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6556162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6557162922Sariff 6558202127Smav for (i = 0; i < 16; i++) { 6559182999Smav /* Check as is correct */ 6560182999Smav if (ch->as < 0) 6561182999Smav break; 6562182999Smav /* Cound only present DACs */ 6563182999Smav if (as[ch->as].dacs[i] <= 0) 6564162922Sariff continue; 6565182999Smav /* Ignore duplicates */ 6566182999Smav for (j = 0; j < ret; j++) { 6567182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6568182999Smav break; 6569182999Smav } 6570182999Smav if (j < ret) 6571162922Sariff continue; 6572182999Smav 6573182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6574182999Smav if (w == NULL || w->enable == 0) 6575182999Smav continue; 6576162922Sariff cap = w->param.supp_stream_formats; 6577182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6578182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6579162922Sariff continue; 6580202127Smav /* Many CODECs does not declare AC3 support on SPDIF. 6581182999Smav I don't beleave that they doesn't support it! */ 6582182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6583182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6584164614Sariff if (ret == 0) { 6585182999Smav fmtcap = cap; 6586164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6587164614Sariff } else { 6588182999Smav fmtcap &= cap; 6589164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6590164614Sariff } 6591182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6592202127Smav /* Do not count redirection pin/dac channels. */ 6593202127Smav if (i == 15 && as[ch->as].hpredir >= 0) 6594202127Smav continue; 6595202127Smav channels += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 6596202127Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) != 1) 6597202127Smav onlystereo = 0; 6598202127Smav pinset |= (1 << i); 6599162922Sariff } 6600162922Sariff ch->io[ret] = -1; 6601162922Sariff 6602202127Smav if (as[ch->as].fakeredir) 6603202127Smav ret--; 6604202127Smav /* Standard speaks only about stereo pins and playback, ... */ 6605202127Smav if ((!onlystereo) || as[ch->as].dir != HDA_CTL_OUT) 6606202127Smav pinset = 0; 6607202127Smav /* ..., but there it gives us info about speakers layout. */ 6608202127Smav as[ch->as].pinset = pinset; 6609202127Smav 6610162922Sariff ch->supp_stream_formats = fmtcap; 6611162922Sariff ch->supp_pcm_size_rate = pcmcap; 6612162922Sariff 6613162922Sariff /* 6614162922Sariff * 8bit = 0 6615162922Sariff * 16bit = 1 6616162922Sariff * 20bit = 2 6617162922Sariff * 24bit = 3 6618162922Sariff * 32bit = 4 6619162922Sariff */ 6620162922Sariff if (ret > 0) { 6621162922Sariff i = 0; 6622182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6623182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6624182999Smav ch->bit16 = 1; 6625182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6626182999Smav ch->bit16 = 0; 6627182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6628182999Smav ch->bit32 = 4; 6629182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6630182999Smav ch->bit32 = 3; 6631182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6632182999Smav ch->bit32 = 2; 6633202127Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) { 6634202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 1, 0); 6635202127Smav if (ch->bit32) 6636202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 1, 0); 6637182999Smav } 6638202127Smav if (channels >= 2) { 6639202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 2, 0); 6640202127Smav if (ch->bit32) 6641202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 2, 0); 6642202127Smav } 6643202127Smav if (channels == 4 || /* Any 4-channel */ 6644202127Smav pinset == 0x0007 || /* 5.1 */ 6645202127Smav pinset == 0x0013 || /* 5.1 */ 6646202127Smav pinset == 0x0017) { /* 7.1 */ 6647202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 4, 0); 6648202127Smav if (ch->bit32) 6649202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 0); 6650202127Smav } 6651202127Smav if (channels == 6 || /* Any 6-channel */ 6652202127Smav pinset == 0x0017) { /* 7.1 */ 6653202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 1); 6654202127Smav if (ch->bit32) 6655202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 1); 6656202127Smav } 6657202127Smav if (channels == 8) { /* Any 8-channel */ 6658202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 8, 1); 6659202127Smav if (ch->bit32) 6660202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 8, 1); 6661202127Smav } 6662162922Sariff } 6663182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6664193640Sariff ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 2, 0); 6665182999Smav } 6666162922Sariff ch->fmtlist[i] = 0; 6667162922Sariff i = 0; 6668182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6669162922Sariff ch->pcmrates[i++] = 8000; 6670182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6671162922Sariff ch->pcmrates[i++] = 11025; 6672182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6673162922Sariff ch->pcmrates[i++] = 16000; 6674182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6675162922Sariff ch->pcmrates[i++] = 22050; 6676182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6677162922Sariff ch->pcmrates[i++] = 32000; 6678182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6679162922Sariff ch->pcmrates[i++] = 44100; 6680182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6681162922Sariff ch->pcmrates[i++] = 48000; 6682182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6683162922Sariff ch->pcmrates[i++] = 88200; 6684182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6685162922Sariff ch->pcmrates[i++] = 96000; 6686182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6687162922Sariff ch->pcmrates[i++] = 176400; 6688182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6689162922Sariff ch->pcmrates[i++] = 192000; 6690182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6691162922Sariff ch->pcmrates[i] = 0; 6692162922Sariff if (i > 0) { 6693162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6694162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6695162922Sariff } 6696162922Sariff } 6697162922Sariff 6698162922Sariff return (ret); 6699162922Sariff} 6700162922Sariff 6701162922Sariffstatic void 6702185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6703185225Smav{ 6704185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6705185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6706185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6707185225Smav 6708185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6709185225Smav if (as[i].enable == 0) 6710185225Smav continue; 6711185225Smav if (as[i].dir == HDA_CTL_IN) { 6712185225Smav if (as[i].digital) 6713185225Smav drdev++; 6714185225Smav else 6715185225Smav ardev++; 6716185225Smav } else { 6717185225Smav if (as[i].digital) 6718185225Smav dpdev++; 6719185225Smav else 6720185225Smav apdev++; 6721185225Smav } 6722185225Smav } 6723185225Smav devinfo->function.audio.num_devs = 6724185225Smav max(ardev, apdev) + max(drdev, dpdev); 6725185225Smav devinfo->function.audio.devs = 6726185225Smav (struct hdac_pcm_devinfo *)malloc( 6727185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6728185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6729185225Smav if (devinfo->function.audio.devs == NULL) { 6730185225Smav device_printf(sc->dev, 6731185225Smav "Unable to allocate memory for devices\n"); 6732185225Smav return; 6733185225Smav } 6734185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6735185225Smav devinfo->function.audio.devs[i].index = i; 6736185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6737185225Smav devinfo->function.audio.devs[i].play = -1; 6738185225Smav devinfo->function.audio.devs[i].rec = -1; 6739197611Smav devinfo->function.audio.devs[i].digital = 255; 6740185225Smav } 6741185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6742185225Smav if (as[i].enable == 0) 6743185225Smav continue; 6744185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6745197611Smav if (devinfo->function.audio.devs[j].digital != 255 && 6746197640Smav (!devinfo->function.audio.devs[j].digital) != 6747197611Smav (!as[i].digital)) 6748185225Smav continue; 6749185225Smav if (as[i].dir == HDA_CTL_IN) { 6750185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6751185225Smav continue; 6752185225Smav devinfo->function.audio.devs[j].rec 6753185225Smav = as[i].chan; 6754185225Smav } else { 6755185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6756185225Smav continue; 6757185225Smav devinfo->function.audio.devs[j].play 6758185225Smav = as[i].chan; 6759185225Smav } 6760185225Smav sc->chans[as[i].chan].pdevinfo = 6761185225Smav &devinfo->function.audio.devs[j]; 6762185225Smav devinfo->function.audio.devs[j].digital = 6763185225Smav as[i].digital; 6764185225Smav break; 6765185225Smav } 6766185225Smav } 6767185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6768185225Smav struct hdac_pcm_devinfo *pdevinfo = 6769185225Smav &devinfo->function.audio.devs[i]; 6770185225Smav pdevinfo->dev = 6771185225Smav device_add_child(sc->dev, "pcm", -1); 6772185225Smav device_set_ivars(pdevinfo->dev, 6773185225Smav (void *)pdevinfo); 6774185225Smav } 6775185225Smav} 6776185225Smav 6777185225Smavstatic void 6778182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6779162922Sariff{ 6780182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6781162922Sariff struct hdac_audio_ctl *ctl; 6782162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6783182999Smav char buf[64]; 6784182999Smav int i, j, printed; 6785162922Sariff 6786162922Sariff if (flag == 0) { 6787182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6788162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6789202796Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IGAIN | 6790202796Smav SOUND_MASK_OGAIN | SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6791162922Sariff } 6792162922Sariff 6793182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6794182999Smav if ((flag & (1 << j)) == 0) 6795162922Sariff continue; 6796182999Smav i = 0; 6797182999Smav printed = 0; 6798182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6799182999Smav if (ctl->enable == 0 || 6800182999Smav ctl->widget->enable == 0) 6801182999Smav continue; 6802182999Smav if (!((pdevinfo->play >= 0 && 6803182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6804182999Smav (pdevinfo->rec >= 0 && 6805182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6806182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6807182999Smav continue; 6808182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6809182999Smav continue; 6810182999Smav 6811182999Smav if (printed == 0) { 6812182999Smav device_printf(pdevinfo->dev, "\n"); 6813182999Smav if (banner != NULL) { 6814182999Smav device_printf(pdevinfo->dev, "%s", banner); 6815182999Smav } else { 6816182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6817182999Smav } 6818182999Smav printf(" (OSS: %s)\n", 6819182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6820182999Smav buf, sizeof(buf))); 6821182999Smav device_printf(pdevinfo->dev, " |\n"); 6822182999Smav printed = 1; 6823162922Sariff } 6824182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6825182999Smav ctl->widget->nid, 6826182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6827182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6828182999Smav printf(" %2d): ", ctl->index); 6829182999Smav else 6830182999Smav printf("): "); 6831182999Smav if (ctl->step > 0) { 6832182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6833182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6834182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6835182999Smav ctl->step + 1, 6836182999Smav ctl->mute?" + mute":""); 6837182999Smav } else 6838182999Smav printf("%s\n", ctl->mute?"mute":""); 6839162922Sariff } 6840162922Sariff } 6841162922Sariff} 6842162922Sariff 6843162922Sariffstatic void 6844182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6845162922Sariff{ 6846162922Sariff uint32_t cap; 6847162922Sariff 6848162922Sariff cap = fcap; 6849162922Sariff if (cap != 0) { 6850182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6851183097Smav device_printf(dev, " "); 6852162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6853162922Sariff printf(" AC3"); 6854162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6855162922Sariff printf(" FLOAT32"); 6856162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6857162922Sariff printf(" PCM"); 6858162922Sariff printf("\n"); 6859162922Sariff } 6860162922Sariff cap = pcmcap; 6861162922Sariff if (cap != 0) { 6862182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6863183097Smav device_printf(dev, " "); 6864162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6865162922Sariff printf(" 8"); 6866162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6867162922Sariff printf(" 16"); 6868162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6869162922Sariff printf(" 20"); 6870162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6871162922Sariff printf(" 24"); 6872162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6873162922Sariff printf(" 32"); 6874183097Smav printf(" bits,"); 6875162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6876162922Sariff printf(" 8"); 6877162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6878162922Sariff printf(" 11"); 6879162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6880162922Sariff printf(" 16"); 6881162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6882162922Sariff printf(" 22"); 6883162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6884162922Sariff printf(" 32"); 6885162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6886162922Sariff printf(" 44"); 6887162922Sariff printf(" 48"); 6888162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6889162922Sariff printf(" 88"); 6890162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6891162922Sariff printf(" 96"); 6892162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6893162922Sariff printf(" 176"); 6894162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6895162922Sariff printf(" 192"); 6896183097Smav printf(" KHz\n"); 6897162922Sariff } 6898162922Sariff} 6899162922Sariff 6900162922Sariffstatic void 6901162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6902162922Sariff{ 6903183097Smav uint32_t pincap; 6904162922Sariff 6905162922Sariff pincap = w->wclass.pin.cap; 6906162922Sariff 6907162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6908162922Sariff device_printf(sc->dev, " "); 6909162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6910162922Sariff printf(" ISC"); 6911162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6912162922Sariff printf(" TRQD"); 6913162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6914162922Sariff printf(" PDC"); 6915162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6916162922Sariff printf(" HP"); 6917162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6918162922Sariff printf(" OUT"); 6919162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6920162922Sariff printf(" IN"); 6921162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6922162922Sariff printf(" BAL"); 6923197611Smav if (HDA_PARAM_PIN_CAP_HDMI(pincap)) 6924197611Smav printf(" HDMI"); 6925165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6926165069Sariff printf(" VREF["); 6927165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6928165069Sariff printf(" 50"); 6929165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6930165069Sariff printf(" 80"); 6931165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6932165069Sariff printf(" 100"); 6933165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6934165069Sariff printf(" GROUND"); 6935165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6936165069Sariff printf(" HIZ"); 6937165069Sariff printf(" ]"); 6938165069Sariff } 6939162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6940162922Sariff printf(" EAPD"); 6941197611Smav if (HDA_PARAM_PIN_CAP_DP(pincap)) 6942197611Smav printf(" DP"); 6943197611Smav if (HDA_PARAM_PIN_CAP_HBR(pincap)) 6944197611Smav printf(" HBR"); 6945162922Sariff printf("\n"); 6946162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6947162922Sariff w->wclass.pin.config); 6948162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6949162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6950162922Sariff printf(" HP"); 6951162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6952162922Sariff printf(" IN"); 6953162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6954162922Sariff printf(" OUT"); 6955182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6956182999Smav printf(" VREFs"); 6957162922Sariff printf("\n"); 6958162922Sariff} 6959162922Sariff 6960162922Sariffstatic void 6961182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6962182999Smav{ 6963182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6964182999Smav 6965183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6966182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6967182999Smav w->nid, conf, 6968182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6969182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6970182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6971182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6972182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6973182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6974182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6975182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6976182999Smav (w->enable == 0)?" [DISABLED]":""); 6977182999Smav} 6978182999Smav 6979182999Smavstatic void 6980182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6981182999Smav{ 6982182999Smav struct hdac_widget *w; 6983182999Smav int i; 6984182999Smav 6985182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6986182999Smav w = hdac_widget_get(devinfo, i); 6987182999Smav if (w == NULL) 6988182999Smav continue; 6989182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6990182999Smav continue; 6991182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6992182999Smav } 6993182999Smav} 6994182999Smav 6995182999Smavstatic void 6996162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6997162922Sariff{ 6998163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6999162922Sariff device_printf(sc->dev, " " 7000162922Sariff "mute=%d step=%d size=%d offset=%d\n", 7001162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 7002162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 7003162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 7004162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 7005162922Sariff} 7006162922Sariff 7007162922Sariffstatic void 7008162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 7009162922Sariff{ 7010162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 7011182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 7012162922Sariff struct hdac_widget *w, *cw; 7013182999Smav char buf[64]; 7014162922Sariff int i, j; 7015162922Sariff 7016162922Sariff device_printf(sc->dev, "\n"); 7017162922Sariff device_printf(sc->dev, "Default Parameter\n"); 7018162922Sariff device_printf(sc->dev, "-----------------\n"); 7019182999Smav hdac_dump_audio_formats(sc->dev, 7020162922Sariff devinfo->function.audio.supp_stream_formats, 7021162922Sariff devinfo->function.audio.supp_pcm_size_rate); 7022162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 7023162922Sariff devinfo->function.audio.inamp_cap); 7024162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 7025162922Sariff devinfo->function.audio.outamp_cap); 7026162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7027162922Sariff w = hdac_widget_get(devinfo, i); 7028162922Sariff if (w == NULL) { 7029162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 7030162922Sariff continue; 7031162922Sariff } 7032162922Sariff device_printf(sc->dev, "\n"); 7033183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 7034162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 7035183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 7036183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 7037162922Sariff w->param.widget_cap); 7038183097Smav if (w->param.widget_cap & 0x0ee1) { 7039183097Smav device_printf(sc->dev, " "); 7040183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 7041183097Smav printf(" LRSWAP"); 7042183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 7043183097Smav printf(" PWR"); 7044183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 7045183097Smav printf(" DIGITAL"); 7046183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 7047183097Smav printf(" UNSOL"); 7048183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 7049183097Smav printf(" PROC"); 7050183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 7051183097Smav printf(" STRIPE"); 7052197611Smav j = HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap); 7053197611Smav if (j == 1) 7054183097Smav printf(" STEREO"); 7055197611Smav else if (j > 1) 7056197611Smav printf(" %dCH", j + 1); 7057183097Smav printf("\n"); 7058183097Smav } 7059183097Smav if (w->bindas != -1) { 7060183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 7061183097Smav w->bindas, w->bindseqmask); 7062183097Smav } 7063183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 7064183097Smav device_printf(sc->dev, " OSS: %s", 7065183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 7066183097Smav if (w->ossdev >= 0) 7067183097Smav printf(" (%s)", ossname[w->ossdev]); 7068183097Smav printf("\n"); 7069183097Smav } 7070162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 7071162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 7072182999Smav hdac_dump_audio_formats(sc->dev, 7073162922Sariff w->param.supp_stream_formats, 7074162922Sariff w->param.supp_pcm_size_rate); 7075162922Sariff } else if (w->type == 7076162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7077162922Sariff hdac_dump_pin(sc, w); 7078162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 7079162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 7080162922Sariff w->param.eapdbtl); 7081163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 7082163057Sariff w->param.outamp_cap != 0) 7083162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 7084163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 7085163057Sariff w->param.inamp_cap != 0) 7086162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 7087183097Smav if (w->nconns > 0) { 7088183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 7089182999Smav device_printf(sc->dev, " |\n"); 7090183097Smav } 7091162922Sariff for (j = 0; j < w->nconns; j++) { 7092162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 7093182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 7094182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 7095162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 7096162922Sariff if (cw == NULL) 7097162922Sariff printf(" [UNKNOWN]"); 7098162922Sariff else if (cw->enable == 0) 7099162922Sariff printf(" [DISABLED]"); 7100162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 7101162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 7102162922Sariff printf(" (selected)"); 7103162922Sariff printf("\n"); 7104162922Sariff } 7105162922Sariff } 7106162922Sariff 7107162922Sariff} 7108162922Sariff 7109182999Smavstatic void 7110182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 7111163057Sariff{ 7112182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7113163057Sariff struct hdac_widget *w, *cw; 7114182999Smav char buf[64]; 7115182999Smav int i, printed = 0; 7116163057Sariff 7117163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 7118182999Smav return; 7119163057Sariff 7120163057Sariff w = hdac_widget_get(devinfo, nid); 7121182999Smav if (w == NULL || w->enable == 0) 7122182999Smav return; 7123163057Sariff 7124182999Smav if (depth == 0) 7125182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 7126182999Smav else 7127182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 7128182999Smav printf("nid=%d [%s]", w->nid, w->name); 7129163057Sariff 7130182999Smav if (depth > 0) { 7131182999Smav if (w->ossmask == 0) { 7132182999Smav printf("\n"); 7133182999Smav return; 7134163057Sariff } 7135182999Smav printf(" [src: %s]", 7136182999Smav hdac_audio_ctl_ossmixer_mask2allname( 7137182999Smav w->ossmask, buf, sizeof(buf))); 7138182999Smav if (w->ossdev >= 0) { 7139182999Smav printf("\n"); 7140182999Smav return; 7141182999Smav } 7142163057Sariff } 7143182999Smav printf("\n"); 7144182999Smav 7145182999Smav for (i = 0; i < w->nconns; i++) { 7146182999Smav if (w->connsenable[i] == 0) 7147182999Smav continue; 7148182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 7149182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 7150182999Smav continue; 7151182999Smav if (printed == 0) { 7152182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 7153182999Smav printed = 1; 7154182999Smav } 7155182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 7156182999Smav } 7157163057Sariff 7158163057Sariff} 7159163057Sariff 7160162922Sariffstatic void 7161182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 7162162922Sariff{ 7163182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7164182999Smav struct hdac_softc *sc = devinfo->codec->sc; 7165202736Smav struct hdac_audio_as *as; 7166163057Sariff struct hdac_widget *w; 7167163057Sariff int i, printed = 0; 7168163057Sariff 7169182999Smav if (pdevinfo->play < 0) 7170182999Smav return; 7171182999Smav 7172202736Smav as = &devinfo->function.audio.as[sc->chans[pdevinfo->play].as]; 7173202736Smav for (i = 0; i < 16; i++) { 7174202736Smav if (as->pins[i] <= 0) 7175202736Smav continue; 7176202736Smav w = hdac_widget_get(devinfo, as->pins[i]); 7177163057Sariff if (w == NULL || w->enable == 0) 7178163057Sariff continue; 7179163057Sariff if (printed == 0) { 7180163057Sariff printed = 1; 7181182999Smav device_printf(pdevinfo->dev, "\n"); 7182182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7183163057Sariff } 7184182999Smav device_printf(pdevinfo->dev, "\n"); 7185202736Smav hdac_dump_dst_nid(pdevinfo, as->pins[i], 0); 7186163057Sariff } 7187162922Sariff} 7188162922Sariff 7189162922Sariffstatic void 7190182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 7191162922Sariff{ 7192182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7193162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 7194182999Smav struct hdac_widget *w; 7195182999Smav int i; 7196162922Sariff int printed = 0; 7197162922Sariff 7198182999Smav if (pdevinfo->rec < 0) 7199182999Smav return; 7200182999Smav 7201162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7202162922Sariff w = hdac_widget_get(devinfo, i); 7203162922Sariff if (w == NULL || w->enable == 0) 7204162922Sariff continue; 7205182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 7206162922Sariff continue; 7207182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 7208182999Smav continue; 7209162922Sariff if (printed == 0) { 7210162922Sariff printed = 1; 7211182999Smav device_printf(pdevinfo->dev, "\n"); 7212182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7213162922Sariff } 7214182999Smav device_printf(pdevinfo->dev, "\n"); 7215182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7216182999Smav } 7217182999Smav} 7218182999Smav 7219182999Smavstatic void 7220182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 7221182999Smav{ 7222182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7223182999Smav struct hdac_widget *w; 7224182999Smav int i; 7225182999Smav int printed = 0; 7226182999Smav 7227182999Smav if (pdevinfo->index != 0) 7228182999Smav return; 7229182999Smav 7230182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7231182999Smav w = hdac_widget_get(devinfo, i); 7232182999Smav if (w == NULL || w->enable == 0) 7233182999Smav continue; 7234202789Smav if (w->ossdev != SOUND_MIXER_IMIX) 7235182999Smav continue; 7236182999Smav if (printed == 0) { 7237182999Smav printed = 1; 7238182999Smav device_printf(pdevinfo->dev, "\n"); 7239182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 7240162922Sariff } 7241182999Smav device_printf(pdevinfo->dev, "\n"); 7242182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7243162922Sariff } 7244162922Sariff} 7245162922Sariff 7246162922Sariffstatic void 7247182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 7248162922Sariff{ 7249182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7250162922Sariff nid_t *nids; 7251182999Smav int i; 7252162922Sariff 7253182999Smav if (pdevinfo->play >= 0) { 7254182999Smav i = pdevinfo->play; 7255182999Smav device_printf(pdevinfo->dev, "\n"); 7256182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7257182999Smav device_printf(pdevinfo->dev, "\n"); 7258182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7259182999Smav sc->chans[i].supp_pcm_size_rate); 7260182999Smav device_printf(pdevinfo->dev, " DAC:"); 7261182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7262162922Sariff printf(" %d", *nids); 7263162922Sariff printf("\n"); 7264162922Sariff } 7265182999Smav if (pdevinfo->rec >= 0) { 7266182999Smav i = pdevinfo->rec; 7267182999Smav device_printf(pdevinfo->dev, "\n"); 7268182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7269182999Smav device_printf(pdevinfo->dev, "\n"); 7270182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7271182999Smav sc->chans[i].supp_pcm_size_rate); 7272182999Smav device_printf(pdevinfo->dev, " ADC:"); 7273182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7274162922Sariff printf(" %d", *nids); 7275162922Sariff printf("\n"); 7276162922Sariff } 7277162922Sariff} 7278162922Sariff 7279162922Sariffstatic void 7280163057Sariffhdac_release_resources(struct hdac_softc *sc) 7281163057Sariff{ 7282182999Smav int i, j; 7283163057Sariff 7284163057Sariff if (sc == NULL) 7285163057Sariff return; 7286163057Sariff 7287163057Sariff hdac_lock(sc); 7288169277Sariff sc->polling = 0; 7289169277Sariff sc->poll_ival = 0; 7290170721Sariff callout_stop(&sc->poll_hda); 7291169277Sariff callout_stop(&sc->poll_hdac); 7292169277Sariff callout_stop(&sc->poll_jack); 7293182999Smav hdac_reset(sc, 0); 7294163057Sariff hdac_unlock(sc); 7295171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7296170721Sariff callout_drain(&sc->poll_hda); 7297169277Sariff callout_drain(&sc->poll_hdac); 7298169277Sariff callout_drain(&sc->poll_jack); 7299163057Sariff 7300169277Sariff hdac_irq_free(sc); 7301169277Sariff 7302182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7303182999Smav if (sc->codecs[i] == NULL) 7304163057Sariff continue; 7305182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7306182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7307182999Smav if (sc->codecs[i]->fgs[j].node_type == 7308182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7309182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7310182999Smav M_HDAC); 7311182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7312182999Smav M_HDAC); 7313182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7314182999Smav M_HDAC); 7315182999Smav } 7316182999Smav } 7317182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7318182999Smav free(sc->codecs[i], M_HDAC); 7319163057Sariff sc->codecs[i] = NULL; 7320163057Sariff } 7321163057Sariff 7322169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7323169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7324169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7325182999Smav for (i = 0; i < sc->num_chans; i++) { 7326182999Smav if (sc->chans[i].blkcnt > 0) 7327182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7328182999Smav } 7329182999Smav free(sc->chans, M_HDAC); 7330167702Sariff if (sc->chan_dmat != NULL) { 7331167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7332167702Sariff sc->chan_dmat = NULL; 7333167702Sariff } 7334163057Sariff hdac_mem_free(sc); 7335169277Sariff snd_mtxfree(sc->lock); 7336163057Sariff} 7337163057Sariff 7338163057Sariff/* This function surely going to make its way into upper level someday. */ 7339163057Sariffstatic void 7340163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7341163057Sariff{ 7342163057Sariff const char *res = NULL; 7343163057Sariff int i = 0, j, k, len, inv; 7344163057Sariff 7345163057Sariff if (on != NULL) 7346163057Sariff *on = 0; 7347163057Sariff if (off != NULL) 7348163057Sariff *off = 0; 7349163057Sariff if (sc == NULL) 7350163057Sariff return; 7351163057Sariff if (resource_string_value(device_get_name(sc->dev), 7352163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7353163057Sariff return; 7354163057Sariff if (!(res != NULL && strlen(res) > 0)) 7355163057Sariff return; 7356163057Sariff HDA_BOOTVERBOSE( 7357182999Smav device_printf(sc->dev, "HDA Config:"); 7358163057Sariff ); 7359163057Sariff for (;;) { 7360163057Sariff while (res[i] != '\0' && 7361163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7362163057Sariff i++; 7363163057Sariff if (res[i] == '\0') { 7364163057Sariff HDA_BOOTVERBOSE( 7365163057Sariff printf("\n"); 7366163057Sariff ); 7367163057Sariff return; 7368163057Sariff } 7369163057Sariff j = i; 7370163057Sariff while (res[j] != '\0' && 7371163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7372163057Sariff j++; 7373163057Sariff len = j - i; 7374163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7375163057Sariff inv = 2; 7376163057Sariff else 7377163057Sariff inv = 0; 7378163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7379163057Sariff if (strncmp(res + i + inv, 7380163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7381163057Sariff continue; 7382163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7383187944Smav continue; 7384163057Sariff HDA_BOOTVERBOSE( 7385163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7386163057Sariff hdac_quirks_tab[k].key); 7387163057Sariff ); 7388163057Sariff if (inv == 0 && on != NULL) 7389163057Sariff *on |= hdac_quirks_tab[k].value; 7390163057Sariff else if (inv != 0 && off != NULL) 7391163057Sariff *off |= hdac_quirks_tab[k].value; 7392163057Sariff break; 7393163057Sariff } 7394163057Sariff i = j; 7395163057Sariff } 7396163057Sariff} 7397163057Sariff 7398164614Sariffstatic int 7399164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7400164614Sariff{ 7401164614Sariff struct hdac_softc *sc; 7402164614Sariff device_t dev; 7403164614Sariff uint32_t ctl; 7404164614Sariff int err, val; 7405164614Sariff 7406164614Sariff dev = oidp->oid_arg1; 7407182999Smav sc = device_get_softc(dev); 7408182999Smav if (sc == NULL) 7409164614Sariff return (EINVAL); 7410164614Sariff hdac_lock(sc); 7411164614Sariff val = sc->polling; 7412164614Sariff hdac_unlock(sc); 7413170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7414164614Sariff 7415169277Sariff if (err != 0 || req->newptr == NULL) 7416164614Sariff return (err); 7417164614Sariff if (val < 0 || val > 1) 7418164614Sariff return (EINVAL); 7419164614Sariff 7420164614Sariff hdac_lock(sc); 7421164614Sariff if (val != sc->polling) { 7422182999Smav if (val == 0) { 7423182999Smav callout_stop(&sc->poll_hda); 7424164614Sariff callout_stop(&sc->poll_hdac); 7425169277Sariff hdac_unlock(sc); 7426182999Smav callout_drain(&sc->poll_hda); 7427169277Sariff callout_drain(&sc->poll_hdac); 7428169277Sariff hdac_lock(sc); 7429164614Sariff sc->polling = 0; 7430182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7431182999Smav ctl |= HDAC_INTCTL_GIE; 7432182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7433164614Sariff } else { 7434182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7435182999Smav ctl &= ~HDAC_INTCTL_GIE; 7436182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7437171141Sariff hdac_unlock(sc); 7438171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7439171141Sariff hdac_lock(sc); 7440164614Sariff sc->polling = 1; 7441182999Smav hdac_poll_reinit(sc); 7442182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7443164614Sariff } 7444164614Sariff } 7445164614Sariff hdac_unlock(sc); 7446164614Sariff 7447164614Sariff return (err); 7448164614Sariff} 7449169277Sariff 7450169277Sariffstatic int 7451169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7452169277Sariff{ 7453169277Sariff struct hdac_softc *sc; 7454169277Sariff device_t dev; 7455169277Sariff int err, val; 7456169277Sariff 7457169277Sariff dev = oidp->oid_arg1; 7458182999Smav sc = device_get_softc(dev); 7459182999Smav if (sc == NULL) 7460169277Sariff return (EINVAL); 7461169277Sariff hdac_lock(sc); 7462169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7463169277Sariff hdac_unlock(sc); 7464170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7465169277Sariff 7466169277Sariff if (err != 0 || req->newptr == NULL) 7467169277Sariff return (err); 7468169277Sariff 7469169277Sariff if (val < 1) 7470169277Sariff val = 1; 7471169277Sariff if (val > 5000) 7472169277Sariff val = 5000; 7473169277Sariff val = ((uint64_t)val * hz) / 1000; 7474169277Sariff if (val < 1) 7475169277Sariff val = 1; 7476169277Sariff if (val > (hz * 5)) 7477169277Sariff val = hz * 5; 7478169277Sariff 7479169277Sariff hdac_lock(sc); 7480169277Sariff sc->poll_ival = val; 7481169277Sariff hdac_unlock(sc); 7482169277Sariff 7483169277Sariff return (err); 7484169277Sariff} 7485169277Sariff 7486169277Sariffstatic int 7487171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7488169277Sariff{ 7489169277Sariff struct hdac_softc *sc; 7490182999Smav struct hdac_codec *codec; 7491169277Sariff struct hdac_devinfo *devinfo; 7492169277Sariff struct hdac_widget *w; 7493169277Sariff device_t dev; 7494182999Smav uint32_t res, pincap, delay; 7495182999Smav int codec_index, fg_index; 7496169277Sariff int i, err, val; 7497169277Sariff nid_t cad; 7498169277Sariff 7499169277Sariff dev = oidp->oid_arg1; 7500182999Smav sc = device_get_softc(dev); 7501182999Smav if (sc == NULL) 7502169277Sariff return (EINVAL); 7503169277Sariff val = 0; 7504170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7505169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7506169277Sariff return (err); 7507182999Smav 7508182999Smav /* XXX: Temporary. For debugging. */ 7509182999Smav if (val == 100) { 7510182999Smav hdac_suspend(dev); 7511182999Smav return (0); 7512182999Smav } else if (val == 101) { 7513182999Smav hdac_resume(dev); 7514182999Smav return (0); 7515182999Smav } 7516182999Smav 7517169277Sariff hdac_lock(sc); 7518182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7519182999Smav codec = sc->codecs[codec_index]; 7520182999Smav if (codec == NULL) 7521169277Sariff continue; 7522182999Smav cad = codec->cad; 7523182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7524182999Smav devinfo = &codec->fgs[fg_index]; 7525182999Smav if (devinfo->node_type != 7526182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7527182999Smav continue; 7528182999Smav 7529182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7530182999Smav codec_index, devinfo->nid); 7531182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7532182999Smav w = hdac_widget_get(devinfo, i); 7533182999Smav if (w == NULL || w->type != 7534182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7535182999Smav continue; 7536182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7537182999Smav pincap = w->wclass.pin.cap; 7538182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7539182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7540182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7541182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7542182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7543182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7544182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7545182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7546182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7547182999Smav delay = 0; 7548182999Smav hdac_command(sc, 7549182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7550182999Smav do { 7551182999Smav res = hdac_command(sc, 7552182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7553182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7554182999Smav break; 7555182999Smav DELAY(10); 7556182999Smav } while (++delay < 10000); 7557182999Smav } else { 7558182999Smav delay = 0; 7559182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7560182999Smav w->nid), cad); 7561182999Smav } 7562182999Smav printf(" Sense: 0x%08x", res); 7563182999Smav if (delay > 0) 7564182999Smav printf(" delay %dus", delay * 10); 7565182999Smav } 7566182999Smav printf("\n"); 7567182999Smav } 7568182999Smav device_printf(dev, 7569182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7570182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7571182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7572182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7573182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7574182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7575182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7576182999Smav device_printf(dev, " GPI:"); 7577171141Sariff res = hdac_command(sc, 7578182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7579182999Smav printf(" data=0x%08x", res); 7580182999Smav res = hdac_command(sc, 7581182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7582182999Smav cad); 7583182999Smav printf(" wake=0x%08x", res); 7584182999Smav res = hdac_command(sc, 7585182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7586182999Smav cad); 7587182999Smav printf(" unsol=0x%08x", res); 7588182999Smav res = hdac_command(sc, 7589182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7590182999Smav printf(" sticky=0x%08x\n", res); 7591182999Smav } 7592182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7593182999Smav device_printf(dev, " GPO:"); 7594182999Smav res = hdac_command(sc, 7595182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7596182999Smav printf(" data=0x%08x\n", res); 7597182999Smav } 7598182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7599182999Smav device_printf(dev, "GPIO:"); 7600182999Smav res = hdac_command(sc, 7601182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7602182999Smav printf(" data=0x%08x", res); 7603182999Smav res = hdac_command(sc, 7604182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7605182999Smav printf(" enable=0x%08x", res); 7606182999Smav res = hdac_command(sc, 7607182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7608182999Smav printf(" direction=0x%08x\n", res); 7609182999Smav res = hdac_command(sc, 7610182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7611182999Smav device_printf(dev, " wake=0x%08x", res); 7612182999Smav res = hdac_command(sc, 7613182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7614182999Smav cad); 7615182999Smav printf(" unsol=0x%08x", res); 7616182999Smav res = hdac_command(sc, 7617182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7618182999Smav printf(" sticky=0x%08x\n", res); 7619182999Smav } 7620171141Sariff } 7621169277Sariff } 7622169277Sariff hdac_unlock(sc); 7623169277Sariff return (0); 7624169277Sariff} 7625164614Sariff 7626163057Sariffstatic void 7627162922Sariffhdac_attach2(void *arg) 7628162922Sariff{ 7629182999Smav struct hdac_codec *codec; 7630162922Sariff struct hdac_softc *sc; 7631162922Sariff struct hdac_audio_ctl *ctl; 7632163057Sariff uint32_t quirks_on, quirks_off; 7633182999Smav int codec_index, fg_index; 7634185225Smav int i, dmaalloc = 0; 7635182999Smav struct hdac_devinfo *devinfo; 7636162922Sariff 7637162922Sariff sc = (struct hdac_softc *)arg; 7638162922Sariff 7639163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7640162922Sariff 7641183097Smav HDA_BOOTHVERBOSE( 7642182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7643163057Sariff quirks_on, quirks_off); 7644163057Sariff ); 7645163057Sariff 7646162922Sariff hdac_lock(sc); 7647162922Sariff 7648162922Sariff /* Remove ourselves from the config hooks */ 7649162922Sariff if (sc->intrhook.ich_func != NULL) { 7650162922Sariff config_intrhook_disestablish(&sc->intrhook); 7651162922Sariff sc->intrhook.ich_func = NULL; 7652162922Sariff } 7653162922Sariff 7654162922Sariff /* Start the corb and rirb engines */ 7655183097Smav HDA_BOOTHVERBOSE( 7656182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7657162922Sariff ); 7658162922Sariff hdac_corb_start(sc); 7659183097Smav HDA_BOOTHVERBOSE( 7660182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7661162922Sariff ); 7662162922Sariff hdac_rirb_start(sc); 7663162922Sariff 7664183097Smav HDA_BOOTHVERBOSE( 7665162922Sariff device_printf(sc->dev, 7666182999Smav "Enabling controller interrupt...\n"); 7667162922Sariff ); 7668182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7669182999Smav HDAC_GCTL_UNSOL); 7670182999Smav if (sc->polling == 0) { 7671164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7672164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7673182999Smav } else { 7674182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7675182999Smav } 7676162922Sariff DELAY(1000); 7677162922Sariff 7678183097Smav HDA_BOOTHVERBOSE( 7679172811Sariff device_printf(sc->dev, 7680182999Smav "Scanning HDA codecs ...\n"); 7681162922Sariff ); 7682182999Smav hdac_scan_codecs(sc); 7683182999Smav 7684182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7685182999Smav codec = sc->codecs[codec_index]; 7686182999Smav if (codec == NULL) 7687182999Smav continue; 7688182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7689182999Smav devinfo = &codec->fgs[fg_index]; 7690183019Smav HDA_BOOTVERBOSE( 7691183019Smav device_printf(sc->dev, "\n"); 7692183097Smav device_printf(sc->dev, 7693183097Smav "Processing %s FG cad=%d nid=%d...\n", 7694183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7695183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7696183097Smav "unknown", 7697183097Smav devinfo->codec->cad, devinfo->nid); 7698183019Smav ); 7699182999Smav if (devinfo->node_type != 7700182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7701183097Smav HDA_BOOTHVERBOSE( 7702182999Smav device_printf(sc->dev, 7703183097Smav "Powering down...\n"); 7704182999Smav ); 7705182999Smav hdac_command(sc, 7706182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7707182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7708182999Smav codec->cad); 7709182999Smav continue; 7710182999Smav } 7711162922Sariff 7712183097Smav HDA_BOOTHVERBOSE( 7713183097Smav device_printf(sc->dev, "Powering up...\n"); 7714182999Smav ); 7715182999Smav hdac_powerup(devinfo); 7716183097Smav HDA_BOOTHVERBOSE( 7717182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7718182999Smav ); 7719182999Smav hdac_audio_parse(devinfo); 7720183097Smav HDA_BOOTHVERBOSE( 7721182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7722182999Smav ); 7723182999Smav hdac_audio_ctl_parse(devinfo); 7724183097Smav HDA_BOOTHVERBOSE( 7725182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7726182999Smav ); 7727182999Smav hdac_vendor_patch_parse(devinfo); 7728182999Smav devinfo->function.audio.quirks |= quirks_on; 7729182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7730162922Sariff 7731183097Smav HDA_BOOTHVERBOSE( 7732182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7733182999Smav ); 7734182999Smav hdac_audio_disable_nonaudio(devinfo); 7735183097Smav HDA_BOOTHVERBOSE( 7736182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7737182999Smav ); 7738182999Smav hdac_audio_disable_useless(devinfo); 7739182999Smav HDA_BOOTVERBOSE( 7740182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7741182999Smav hdac_dump_pin_configs(devinfo); 7742183097Smav ); 7743183097Smav HDA_BOOTHVERBOSE( 7744182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7745182999Smav ); 7746182999Smav hdac_audio_as_parse(devinfo); 7747183097Smav HDA_BOOTHVERBOSE( 7748182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7749182999Smav ); 7750182999Smav hdac_audio_build_tree(devinfo); 7751183097Smav HDA_BOOTHVERBOSE( 7752182999Smav device_printf(sc->dev, "Disabling unassociated " 7753182999Smav "widgets...\n"); 7754182999Smav ); 7755182999Smav hdac_audio_disable_unas(devinfo); 7756183097Smav HDA_BOOTHVERBOSE( 7757182999Smav device_printf(sc->dev, "Disabling nonselected " 7758182999Smav "inputs...\n"); 7759182999Smav ); 7760182999Smav hdac_audio_disable_notselected(devinfo); 7761183097Smav HDA_BOOTHVERBOSE( 7762182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7763182999Smav ); 7764182999Smav hdac_audio_disable_useless(devinfo); 7765183097Smav HDA_BOOTHVERBOSE( 7766182999Smav device_printf(sc->dev, "Disabling " 7767182999Smav "crossassociatement connections...\n"); 7768182999Smav ); 7769182999Smav hdac_audio_disable_crossas(devinfo); 7770183097Smav HDA_BOOTHVERBOSE( 7771182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7772182999Smav ); 7773182999Smav hdac_audio_disable_useless(devinfo); 7774183097Smav HDA_BOOTHVERBOSE( 7775182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7776182999Smav ); 7777182999Smav hdac_audio_bind_as(devinfo); 7778183097Smav HDA_BOOTHVERBOSE( 7779182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7780182999Smav ); 7781182999Smav hdac_audio_assign_names(devinfo); 7782183097Smav HDA_BOOTHVERBOSE( 7783182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7784182999Smav ); 7785182999Smav hdac_audio_assign_mixers(devinfo); 7786183097Smav HDA_BOOTHVERBOSE( 7787182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7788182999Smav ); 7789182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7790183097Smav HDA_BOOTHVERBOSE( 7791182999Smav device_printf(sc->dev, "AFG commit...\n"); 7792182999Smav ); 7793182999Smav hdac_audio_commit(devinfo); 7794183097Smav HDA_BOOTHVERBOSE( 7795182999Smav device_printf(sc->dev, "HP switch init...\n"); 7796182999Smav ); 7797182999Smav hdac_hp_switch_init(devinfo); 7798182999Smav 7799182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7800182999Smav dmaalloc == 0) { 7801182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7802182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7803182999Smav HDA_BOOTVERBOSE( 7804182999Smav device_printf(sc->dev, "Failed to " 7805182999Smav "allocate DMA pos buffer " 7806182999Smav "(non-fatal)\n"); 7807182999Smav ); 7808182999Smav } else 7809182999Smav dmaalloc = 1; 7810182999Smav } 7811182999Smav 7812185225Smav HDA_BOOTHVERBOSE( 7813185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7814185225Smav ); 7815185225Smav hdac_create_pcms(devinfo); 7816182999Smav 7817182999Smav HDA_BOOTVERBOSE( 7818182999Smav if (devinfo->function.audio.quirks != 0) { 7819183097Smav device_printf(sc->dev, "FG config/quirks:"); 7820182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7821182999Smav if ((devinfo->function.audio.quirks & 7822182999Smav hdac_quirks_tab[i].value) == 7823182999Smav hdac_quirks_tab[i].value) 7824182999Smav printf(" %s", hdac_quirks_tab[i].key); 7825182999Smav } 7826182999Smav printf("\n"); 7827182999Smav } 7828182999Smav 7829182999Smav device_printf(sc->dev, "\n"); 7830182999Smav device_printf(sc->dev, "+-------------------+\n"); 7831182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7832182999Smav device_printf(sc->dev, "+-------------------+\n"); 7833182999Smav hdac_dump_nodes(devinfo); 7834183097Smav ); 7835182999Smav 7836183097Smav HDA_BOOTHVERBOSE( 7837182999Smav device_printf(sc->dev, "\n"); 7838182999Smav device_printf(sc->dev, "+------------------------+\n"); 7839182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7840182999Smav device_printf(sc->dev, "+------------------------+\n"); 7841182999Smav device_printf(sc->dev, "\n"); 7842182999Smav i = 0; 7843182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7844182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7845182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7846182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7847182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7848182999Smav ctl->index); 7849182999Smav if (ctl->childwidget != NULL) 7850182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7851182999Smav else 7852182999Smav printf(" "); 7853182999Smav printf(" ossmask=0x%08x\n", 7854182999Smav ctl->ossmask); 7855182999Smav device_printf(sc->dev, 7856182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7857182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7858182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7859182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7860182999Smav } 7861182999Smav ); 7862182999Smav } 7863162922Sariff } 7864182999Smav hdac_unlock(sc); 7865162922Sariff 7866163057Sariff HDA_BOOTVERBOSE( 7867182999Smav device_printf(sc->dev, "\n"); 7868162922Sariff ); 7869182999Smav 7870182999Smav bus_generic_attach(sc->dev); 7871182999Smav 7872182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7873182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7874182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7875182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7876182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7877182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7878182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7879182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7880182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7881182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7882182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7883182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7884182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7885182999Smav} 7886182999Smav 7887182999Smav/**************************************************************************** 7888182999Smav * int hdac_suspend(device_t) 7889182999Smav * 7890182999Smav * Suspend and power down HDA bus and codecs. 7891182999Smav ****************************************************************************/ 7892182999Smavstatic int 7893182999Smavhdac_suspend(device_t dev) 7894182999Smav{ 7895182999Smav struct hdac_softc *sc; 7896182999Smav struct hdac_codec *codec; 7897182999Smav struct hdac_devinfo *devinfo; 7898182999Smav int codec_index, fg_index, i; 7899182999Smav 7900183097Smav HDA_BOOTHVERBOSE( 7901182999Smav device_printf(dev, "Suspend...\n"); 7902162922Sariff ); 7903182999Smav 7904182999Smav sc = device_get_softc(dev); 7905182999Smav hdac_lock(sc); 7906182999Smav 7907183097Smav HDA_BOOTHVERBOSE( 7908182999Smav device_printf(dev, "Stop streams...\n"); 7909162922Sariff ); 7910182999Smav for (i = 0; i < sc->num_chans; i++) { 7911182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7912182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7913182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7914182999Smav } 7915182999Smav } 7916162922Sariff 7917182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7918182999Smav codec = sc->codecs[codec_index]; 7919182999Smav if (codec == NULL) 7920162922Sariff continue; 7921182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7922182999Smav devinfo = &codec->fgs[fg_index]; 7923183097Smav HDA_BOOTHVERBOSE( 7924182999Smav device_printf(dev, 7925182999Smav "Power down FG" 7926182999Smav " cad=%d nid=%d to the D3 state...\n", 7927182999Smav codec->cad, devinfo->nid); 7928182999Smav ); 7929182999Smav hdac_command(sc, 7930182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7931182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7932182999Smav codec->cad); 7933162922Sariff } 7934162922Sariff } 7935162922Sariff 7936183097Smav HDA_BOOTHVERBOSE( 7937182999Smav device_printf(dev, "Reset controller...\n"); 7938162922Sariff ); 7939182999Smav callout_stop(&sc->poll_hda); 7940182999Smav callout_stop(&sc->poll_hdac); 7941182999Smav callout_stop(&sc->poll_jack); 7942182999Smav hdac_reset(sc, 0); 7943182999Smav hdac_unlock(sc); 7944182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7945182999Smav callout_drain(&sc->poll_hda); 7946182999Smav callout_drain(&sc->poll_hdac); 7947182999Smav callout_drain(&sc->poll_jack); 7948162922Sariff 7949183097Smav HDA_BOOTHVERBOSE( 7950182999Smav device_printf(dev, "Suspend done\n"); 7951162922Sariff ); 7952182999Smav 7953182999Smav return (0); 7954182999Smav} 7955182999Smav 7956182999Smav/**************************************************************************** 7957182999Smav * int hdac_resume(device_t) 7958182999Smav * 7959182999Smav * Powerup and restore HDA bus and codecs state. 7960182999Smav ****************************************************************************/ 7961182999Smavstatic int 7962182999Smavhdac_resume(device_t dev) 7963182999Smav{ 7964182999Smav struct hdac_softc *sc; 7965182999Smav struct hdac_codec *codec; 7966182999Smav struct hdac_devinfo *devinfo; 7967182999Smav int codec_index, fg_index, i; 7968182999Smav 7969183097Smav HDA_BOOTHVERBOSE( 7970182999Smav device_printf(dev, "Resume...\n"); 7971162922Sariff ); 7972162922Sariff 7973182999Smav sc = device_get_softc(dev); 7974182999Smav hdac_lock(sc); 7975182999Smav 7976182999Smav /* Quiesce everything */ 7977183097Smav HDA_BOOTHVERBOSE( 7978182999Smav device_printf(dev, "Reset controller...\n"); 7979162922Sariff ); 7980182999Smav hdac_reset(sc, 1); 7981182999Smav 7982182999Smav /* Initialize the CORB and RIRB */ 7983182999Smav hdac_corb_init(sc); 7984182999Smav hdac_rirb_init(sc); 7985182999Smav 7986182999Smav /* Start the corb and rirb engines */ 7987183097Smav HDA_BOOTHVERBOSE( 7988182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7989162922Sariff ); 7990182999Smav hdac_corb_start(sc); 7991183097Smav HDA_BOOTHVERBOSE( 7992182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7993162922Sariff ); 7994182999Smav hdac_rirb_start(sc); 7995163057Sariff 7996183097Smav HDA_BOOTHVERBOSE( 7997182999Smav device_printf(dev, 7998182999Smav "Enabling controller interrupt...\n"); 7999162922Sariff ); 8000182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 8001182999Smav HDAC_GCTL_UNSOL); 8002182999Smav if (sc->polling == 0) { 8003182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 8004182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 8005182999Smav } else { 8006182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 8007182999Smav } 8008182999Smav DELAY(1000); 8009162922Sariff 8010182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 8011182999Smav codec = sc->codecs[codec_index]; 8012182999Smav if (codec == NULL) 8013182999Smav continue; 8014182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 8015182999Smav devinfo = &codec->fgs[fg_index]; 8016182999Smav if (devinfo->node_type != 8017182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 8018183097Smav HDA_BOOTHVERBOSE( 8019182999Smav device_printf(dev, 8020182999Smav "Power down unsupported non-audio FG" 8021182999Smav " cad=%d nid=%d to the D3 state...\n", 8022182999Smav codec->cad, devinfo->nid); 8023182999Smav ); 8024182999Smav hdac_command(sc, 8025182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 8026182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 8027182999Smav codec->cad); 8028182999Smav continue; 8029182999Smav } 8030162922Sariff 8031183097Smav HDA_BOOTHVERBOSE( 8032182999Smav device_printf(dev, 8033182999Smav "Power up audio FG cad=%d nid=%d...\n", 8034182999Smav devinfo->codec->cad, devinfo->nid); 8035182999Smav ); 8036182999Smav hdac_powerup(devinfo); 8037183097Smav HDA_BOOTHVERBOSE( 8038182999Smav device_printf(dev, "AFG commit...\n"); 8039182999Smav ); 8040182999Smav hdac_audio_commit(devinfo); 8041183097Smav HDA_BOOTHVERBOSE( 8042182999Smav device_printf(dev, "HP switch init...\n"); 8043182999Smav ); 8044182999Smav hdac_hp_switch_init(devinfo); 8045182999Smav 8046182999Smav hdac_unlock(sc); 8047182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 8048182999Smav struct hdac_pcm_devinfo *pdevinfo = 8049182999Smav &devinfo->function.audio.devs[i]; 8050183097Smav HDA_BOOTHVERBOSE( 8051182999Smav device_printf(pdevinfo->dev, 8052182999Smav "OSS mixer reinitialization...\n"); 8053182999Smav ); 8054182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 8055182999Smav device_printf(pdevinfo->dev, 8056182999Smav "unable to reinitialize the mixer\n"); 8057182999Smav } 8058182999Smav hdac_lock(sc); 8059182999Smav } 8060169277Sariff } 8061169277Sariff 8062183097Smav HDA_BOOTHVERBOSE( 8063182999Smav device_printf(dev, "Start streams...\n"); 8064163057Sariff ); 8065182999Smav for (i = 0; i < sc->num_chans; i++) { 8066182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 8067182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 8068182999Smav hdac_channel_start(sc, &sc->chans[i]); 8069182999Smav } 8070182999Smav } 8071162922Sariff 8072182999Smav hdac_unlock(sc); 8073182999Smav 8074183097Smav HDA_BOOTHVERBOSE( 8075182999Smav device_printf(dev, "Resume done\n"); 8076162922Sariff ); 8077164614Sariff 8078182999Smav return (0); 8079162922Sariff} 8080162922Sariff/**************************************************************************** 8081162922Sariff * int hdac_detach(device_t) 8082162922Sariff * 8083162922Sariff * Detach and free up resources utilized by the hdac device. 8084162922Sariff ****************************************************************************/ 8085162922Sariffstatic int 8086162922Sariffhdac_detach(device_t dev) 8087162922Sariff{ 8088182999Smav struct hdac_softc *sc; 8089185177Smav device_t *devlist; 8090185177Smav int i, devcount, error; 8091162922Sariff 8092185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 8093185177Smav return (error); 8094185177Smav for (i = 0; i < devcount; i++) { 8095185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 8096185178Smav free(devlist, M_TEMP); 8097185178Smav return (error); 8098185178Smav } 8099185177Smav } 8100185177Smav free(devlist, M_TEMP); 8101185177Smav 8102182999Smav sc = device_get_softc(dev); 8103163057Sariff hdac_release_resources(sc); 8104162922Sariff 8105162922Sariff return (0); 8106162922Sariff} 8107162922Sariff 8108184095Smavstatic int 8109184095Smavhdac_print_child(device_t dev, device_t child) 8110184095Smav{ 8111184095Smav struct hdac_pcm_devinfo *pdevinfo = 8112184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 8113184095Smav int retval; 8114184095Smav 8115184095Smav retval = bus_print_child_header(dev, child); 8116184095Smav retval += printf(" at cad %d nid %d", 8117184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 8118184095Smav retval += bus_print_child_footer(dev, child); 8119184095Smav 8120184095Smav return (retval); 8121184095Smav} 8122184095Smav 8123162922Sariffstatic device_method_t hdac_methods[] = { 8124162922Sariff /* device interface */ 8125162922Sariff DEVMETHOD(device_probe, hdac_probe), 8126162922Sariff DEVMETHOD(device_attach, hdac_attach), 8127162922Sariff DEVMETHOD(device_detach, hdac_detach), 8128182999Smav DEVMETHOD(device_suspend, hdac_suspend), 8129182999Smav DEVMETHOD(device_resume, hdac_resume), 8130184095Smav /* Bus interface */ 8131184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 8132162922Sariff { 0, 0 } 8133162922Sariff}; 8134162922Sariff 8135162922Sariffstatic driver_t hdac_driver = { 8136182999Smav "hdac", 8137162922Sariff hdac_methods, 8138182999Smav sizeof(struct hdac_softc), 8139162922Sariff}; 8140162922Sariff 8141182999Smavstatic devclass_t hdac_devclass; 8142182999Smav 8143182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 8144162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 8145162922SariffMODULE_VERSION(snd_hda, 1); 8146182999Smav 8147182999Smavstatic int 8148182999Smavhdac_pcm_probe(device_t dev) 8149182999Smav{ 8150182999Smav struct hdac_pcm_devinfo *pdevinfo = 8151182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8152182999Smav char buf[128]; 8153182999Smav 8154185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 8155182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 8156185225Smav pdevinfo->index, 8157197611Smav (pdevinfo->digital == 3)?"DisplayPort": 8158197611Smav ((pdevinfo->digital == 2)?"HDMI": 8159197611Smav ((pdevinfo->digital)?"Digital":"Analog"))); 8160182999Smav device_set_desc_copy(dev, buf); 8161182999Smav return (0); 8162182999Smav} 8163182999Smav 8164182999Smavstatic int 8165182999Smavhdac_pcm_attach(device_t dev) 8166182999Smav{ 8167182999Smav struct hdac_pcm_devinfo *pdevinfo = 8168182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8169182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 8170182999Smav char status[SND_STATUSLEN]; 8171182999Smav int i; 8172182999Smav 8173182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 8174182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 8175182999Smav 8176182999Smav HDA_BOOTVERBOSE( 8177182999Smav device_printf(dev, "+--------------------------------------+\n"); 8178182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 8179182999Smav device_printf(dev, "+--------------------------------------+\n"); 8180182999Smav hdac_dump_pcmchannels(pdevinfo); 8181182999Smav device_printf(dev, "\n"); 8182189876Smav device_printf(dev, "+-------------------------------+\n"); 8183189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 8184189876Smav device_printf(dev, "+-------------------------------+\n"); 8185182999Smav hdac_dump_dac(pdevinfo); 8186182999Smav hdac_dump_adc(pdevinfo); 8187182999Smav hdac_dump_mix(pdevinfo); 8188182999Smav device_printf(dev, "\n"); 8189182999Smav device_printf(dev, "+-------------------------+\n"); 8190182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 8191182999Smav device_printf(dev, "+-------------------------+\n"); 8192182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 8193182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 8194182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 8195182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 8196182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 8197182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 8198182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 8199182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 8200202796Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 8201202796Smav hdac_dump_ctls(pdevinfo, "Input Monitoring Level", SOUND_MASK_IGAIN); 8202182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 8203182999Smav device_printf(dev, "\n"); 8204182999Smav ); 8205182999Smav 8206182999Smav if (resource_int_value(device_get_name(dev), 8207182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 8208182999Smav i &= HDA_BLK_ALIGN; 8209182999Smav if (i < HDA_BLK_MIN) 8210182999Smav i = HDA_BLK_MIN; 8211182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 8212182999Smav i = 0; 8213182999Smav while (pdevinfo->chan_blkcnt >> i) 8214182999Smav i++; 8215182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 8216182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 8217182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 8218182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 8219182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 8220182999Smav } else 8221182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 8222182999Smav 8223182999Smav /* 8224182999Smav * We don't register interrupt handler with snd_setup_intr 8225182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 8226182999Smav */ 8227182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 8228182999Smav 8229183097Smav HDA_BOOTHVERBOSE( 8230182999Smav device_printf(dev, "OSS mixer initialization...\n"); 8231182999Smav ); 8232182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 8233182999Smav device_printf(dev, "Can't register mixer\n"); 8234182999Smav 8235183097Smav HDA_BOOTHVERBOSE( 8236182999Smav device_printf(dev, "Registering PCM channels...\n"); 8237182999Smav ); 8238182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 8239182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 8240182999Smav device_printf(dev, "Can't register PCM\n"); 8241182999Smav 8242182999Smav pdevinfo->registered++; 8243182999Smav 8244182999Smav if (pdevinfo->play >= 0) 8245182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 8246182999Smav if (pdevinfo->rec >= 0) 8247182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 8248182999Smav 8249184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 8250184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 8251184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 8252182999Smav pcm_setstatus(dev, status); 8253182999Smav 8254182999Smav return (0); 8255182999Smav} 8256182999Smav 8257182999Smavstatic int 8258182999Smavhdac_pcm_detach(device_t dev) 8259182999Smav{ 8260182999Smav struct hdac_pcm_devinfo *pdevinfo = 8261182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8262182999Smav int err; 8263182999Smav 8264182999Smav if (pdevinfo->registered > 0) { 8265182999Smav err = pcm_unregister(dev); 8266182999Smav if (err != 0) 8267182999Smav return (err); 8268182999Smav } 8269182999Smav 8270182999Smav return (0); 8271182999Smav} 8272182999Smav 8273182999Smavstatic device_method_t hdac_pcm_methods[] = { 8274182999Smav /* device interface */ 8275182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8276182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8277182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8278182999Smav { 0, 0 } 8279182999Smav}; 8280182999Smav 8281182999Smavstatic driver_t hdac_pcm_driver = { 8282182999Smav "pcm", 8283182999Smav hdac_pcm_methods, 8284182999Smav PCM_SOFTC_SIZE, 8285182999Smav}; 8286182999Smav 8287182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8288182999Smav 8289