hdac.c revision 223118
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 223118 2011-06-15 19:53:08Z joel $"); 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) 757223058Smav#define HDA_CODEC_CX20584 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5068) 758208934Smav#define HDA_CODEC_CX20585 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5069) 759223058Smav#define HDA_CODEC_CX20590 HDA_CODEC_CONSTRUCT(CONEXANT, 0x506e) 760223058Smav#define HDA_CODEC_CX20631 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5097) 761223058Smav#define HDA_CODEC_CX20632 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5098) 762223058Smav#define HDA_CODEC_CX20641 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50a1) 763223058Smav#define HDA_CODEC_CX20642 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50a2) 764223058Smav#define HDA_CODEC_CX20651 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50ab) 765223058Smav#define HDA_CODEC_CX20652 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50ac) 766223058Smav#define HDA_CODEC_CX20664 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50b8) 767223058Smav#define HDA_CODEC_CX20665 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50b9) 768162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 769162922Sariff 770169277Sariff/* VIA */ 771169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 772169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 773169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 774169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 775169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 776169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 777169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 778169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 779169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 780169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 781169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 782169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 783186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 784186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 785186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 786186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 787186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 788186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 789186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 790186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 791187020Smav#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) 792187020Smav#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) 793187020Smav#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) 794187020Smav#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) 795187020Smav#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) 796187020Smav#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) 797187020Smav#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) 798187020Smav#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) 799187020Smav#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) 800187020Smav#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) 801187020Smav#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) 802187020Smav#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) 803187020Smav#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) 804187020Smav#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) 805187020Smav#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) 806187020Smav#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) 807199258Smav#define HDA_CODEC_VT1716S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0433) 808199258Smav#define HDA_CODEC_VT1716S_1 HDA_CODEC_CONSTRUCT(VIA, 0xa721) 809199258Smav#define HDA_CODEC_VT1718S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0428) 810199258Smav#define HDA_CODEC_VT1718S_1 HDA_CODEC_CONSTRUCT(VIA, 0x4428) 811199258Smav#define HDA_CODEC_VT1812 HDA_CODEC_CONSTRUCT(VIA, 0x0448) 812199258Smav#define HDA_CODEC_VT1818S HDA_CODEC_CONSTRUCT(VIA, 0x0440) 813199258Smav#define HDA_CODEC_VT1828S HDA_CODEC_CONSTRUCT(VIA, 0x4441) 814199258Smav#define HDA_CODEC_VT2002P_0 HDA_CODEC_CONSTRUCT(VIA, 0x0438) 815199258Smav#define HDA_CODEC_VT2002P_1 HDA_CODEC_CONSTRUCT(VIA, 0x4438) 816199258Smav#define HDA_CODEC_VT2020 HDA_CODEC_CONSTRUCT(VIA, 0x0441) 817169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 818162922Sariff 819182999Smav/* ATI */ 820186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 821186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 822186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 823186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 824182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 825169277Sariff 826182999Smav/* NVIDIA */ 827187020Smav#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) 828187445Smav#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) 829187020Smav#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) 830208934Smav#define HDA_CODEC_NVIDIAGT220 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000a) 831208934Smav#define HDA_CODEC_NVIDIAGT21X HDA_CODEC_CONSTRUCT(NVIDIA, 0x000b) 832208934Smav#define HDA_CODEC_NVIDIAMCP89 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000c) 833208934Smav#define HDA_CODEC_NVIDIAGT240 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000d) 834187020Smav#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) 835187445Smav#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) 836182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 837182999Smav 838183894Smav/* INTEL */ 839222298Smav#define HDA_CODEC_INTELIP HDA_CODEC_CONSTRUCT(INTEL, 0x0054) 840222298Smav#define HDA_CODEC_INTELBL HDA_CODEC_CONSTRUCT(INTEL, 0x2801) 841222298Smav#define HDA_CODEC_INTELCA HDA_CODEC_CONSTRUCT(INTEL, 0x2802) 842222298Smav#define HDA_CODEC_INTELEL HDA_CODEC_CONSTRUCT(INTEL, 0x2803) 843222298Smav#define HDA_CODEC_INTELIP2 HDA_CODEC_CONSTRUCT(INTEL, 0x2804) 844222298Smav#define HDA_CODEC_INTELCPT HDA_CODEC_CONSTRUCT(INTEL, 0x2805) 845222298Smav#define HDA_CODEC_INTELCL HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) 846183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 847183894Smav 848162922Sariff/* Codecs */ 849162922Sariffstatic const struct { 850162922Sariff uint32_t id; 851162922Sariff char *name; 852162922Sariff} hdac_codecs[] = { 853199846Smav { HDA_CODEC_CS4206, "Cirrus Logic CS4206" }, 854199846Smav { HDA_CODEC_CS4207, "Cirrus Logic CS4207" }, 855162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 856169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 857183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 858171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 859183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 860205413Smav { HDA_CODEC_ALC270, "Realtek ALC270" }, 861183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 862205413Smav { HDA_CODEC_ALC273, "Realtek ALC273" }, 863205413Smav { HDA_CODEC_ALC275, "Realtek ALC275" }, 864170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 865183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 866183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 867205413Smav { HDA_CODEC_ALC665, "Realtek ALC665" }, 868162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 869169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 870162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 871162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 872163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 873169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 874197640Smav { HDA_CODEC_ALC887, "Realtek ALC887" }, 875165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 876182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 877205413Smav { HDA_CODEC_ALC892, "Realtek ALC892" }, 878186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 879186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 880186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 881186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 882186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 883169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 884169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 885174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 886186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 887186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 888169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 889186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 890186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 891170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 892186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 893162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 894200375Smav { HDA_CODEC_CXD9872RDK, "Sigmatel CXD9872RD/K" }, 895200375Smav { HDA_CODEC_CXD9872AKD, "Sigmatel CXD9872AKD" }, 896183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 897183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 898183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 899183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 900183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 901183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 902183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 903183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 904162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 905183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 906162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 907162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 908183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 909183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 910183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 911183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 912183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 913183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 914182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 915182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 916183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 917183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 918183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 919166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 920183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 921183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 922183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 923183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 924183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 925183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 926183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 927183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 928183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 929183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 930183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 931183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 932183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 933183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 934183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 935183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 936183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 937183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 938183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 939183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 940183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 941183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 942183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 943183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 944183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 945183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 946183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 947186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 948186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 949186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 950200375Smav { HDA_CODEC_CX20582, "Conexant CX20582 (Pebble)" }, 951205413Smav { HDA_CODEC_CX20583, "Conexant CX20583 (Pebble HSF)" }, 952223058Smav { HDA_CODEC_CX20584, "Conexant CX20584" }, 953208934Smav { HDA_CODEC_CX20585, "Conexant CX20585" }, 954223058Smav { HDA_CODEC_CX20590, "Conexant CX20590" }, 955223058Smav { HDA_CODEC_CX20631, "Conexant CX20631" }, 956223058Smav { HDA_CODEC_CX20632, "Conexant CX20632" }, 957223058Smav { HDA_CODEC_CX20641, "Conexant CX20641" }, 958223058Smav { HDA_CODEC_CX20642, "Conexant CX20642" }, 959223058Smav { HDA_CODEC_CX20651, "Conexant CX20651" }, 960223058Smav { HDA_CODEC_CX20652, "Conexant CX20652" }, 961223058Smav { HDA_CODEC_CX20664, "Conexant CX20664" }, 962223058Smav { HDA_CODEC_CX20665, "Conexant CX20665" }, 963169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 964169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 965169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 966169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 967169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 968169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 969169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 970169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 971169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 972169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 973169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 974169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 975186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 976186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 977186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 978186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 979186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 980186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 981186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 982186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 983187020Smav { HDA_CODEC_VT1708S_0, "VIA VT1708S_0" }, 984187020Smav { HDA_CODEC_VT1708S_1, "VIA VT1708S_1" }, 985187020Smav { HDA_CODEC_VT1708S_2, "VIA VT1708S_2" }, 986187020Smav { HDA_CODEC_VT1708S_3, "VIA VT1708S_3" }, 987187020Smav { HDA_CODEC_VT1708S_4, "VIA VT1708S_4" }, 988187020Smav { HDA_CODEC_VT1708S_5, "VIA VT1708S_5" }, 989187020Smav { HDA_CODEC_VT1708S_6, "VIA VT1708S_6" }, 990187020Smav { HDA_CODEC_VT1708S_7, "VIA VT1708S_7" }, 991187020Smav { HDA_CODEC_VT1702_0, "VIA VT1702_0" }, 992187020Smav { HDA_CODEC_VT1702_1, "VIA VT1702_1" }, 993187020Smav { HDA_CODEC_VT1702_2, "VIA VT1702_2" }, 994187020Smav { HDA_CODEC_VT1702_3, "VIA VT1702_3" }, 995187020Smav { HDA_CODEC_VT1702_4, "VIA VT1702_4" }, 996187020Smav { HDA_CODEC_VT1702_5, "VIA VT1702_5" }, 997187020Smav { HDA_CODEC_VT1702_6, "VIA VT1702_6" }, 998187020Smav { HDA_CODEC_VT1702_7, "VIA VT1702_7" }, 999199258Smav { HDA_CODEC_VT1716S_0, "VIA VT1716S_0" }, 1000199258Smav { HDA_CODEC_VT1716S_1, "VIA VT1716S_1" }, 1001199258Smav { HDA_CODEC_VT1718S_0, "VIA VT1718S_0" }, 1002199258Smav { HDA_CODEC_VT1718S_1, "VIA VT1718S_1" }, 1003199258Smav { HDA_CODEC_VT1812, "VIA VT1812" }, 1004199258Smav { HDA_CODEC_VT1818S, "VIA VT1818S" }, 1005199258Smav { HDA_CODEC_VT1828S, "VIA VT1828S" }, 1006199258Smav { HDA_CODEC_VT2002P_0, "VIA VT2002P_0" }, 1007199258Smav { HDA_CODEC_VT2002P_1, "VIA VT2002P_1" }, 1008199258Smav { HDA_CODEC_VT2020, "VIA VT2020" }, 1009186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 1010186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 1011186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 1012186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 1013187020Smav { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, 1014187445Smav { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, 1015187020Smav { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, 1016187445Smav { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, 1017187020Smav { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, 1018208934Smav { HDA_CODEC_NVIDIAGT220, "NVidia GT220 HDMI" }, 1019208934Smav { HDA_CODEC_NVIDIAGT21X, "NVidia GT21x HDMI" }, 1020208934Smav { HDA_CODEC_NVIDIAMCP89, "NVidia MCP89 HDMI" }, 1021208934Smav { HDA_CODEC_NVIDIAGT240, "NVidia GT240 HDMI" }, 1022222298Smav { HDA_CODEC_INTELIP, "Intel Ibex Peak HDMI" }, 1023222298Smav { HDA_CODEC_INTELBL, "Intel Bearlake HDMI" }, 1024222298Smav { HDA_CODEC_INTELCA, "Intel Cantiga HDMI" }, 1025222298Smav { HDA_CODEC_INTELEL, "Intel Eaglelake HDMI" }, 1026222298Smav { HDA_CODEC_INTELIP2, "Intel Ibex Peak HDMI" }, 1027222298Smav { HDA_CODEC_INTELCPT, "Intel Cougar Point HDMI" }, 1028222298Smav { HDA_CODEC_INTELCL, "Intel Crestline HDMI" }, 1029187020Smav { HDA_CODEC_SII1390, "Silicon Image SiI1390 HDMI" }, 1030186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 1031162922Sariff /* Unknown codec */ 1032162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 1033169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 1034200375Smav { HDA_CODEC_CSXXXX, "Cirrus Logic (Unknown)" }, 1035162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 1036162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 1037182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 1038182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 1039162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 1040169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 1041182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 1042182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 1043183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 1044183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 1045162922Sariff}; 1046162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 1047162922Sariff 1048162922Sariff 1049162922Sariff/**************************************************************************** 1050162922Sariff * Function prototypes 1051162922Sariff ****************************************************************************/ 1052162922Sariffstatic void hdac_intr_handler(void *); 1053182999Smavstatic int hdac_reset(struct hdac_softc *, int); 1054162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 1055162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 1056162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 1057162922Sariff struct hdac_dma *, bus_size_t); 1058169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 1059162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 1060162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 1061162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 1062162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 1063162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 1064162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 1065162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 1066162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 1067182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 1068182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 1069182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 1070182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 1071162922Sariff 1072162922Sariffstatic void hdac_attach2(void *); 1073162922Sariff 1074162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 1075162922Sariff uint32_t, int); 1076162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 1077162922Sariff struct hdac_command_list *, int); 1078162922Sariff 1079162922Sariffstatic int hdac_probe(device_t); 1080162922Sariffstatic int hdac_attach(device_t); 1081162922Sariffstatic int hdac_detach(device_t); 1082182999Smavstatic int hdac_suspend(device_t); 1083182999Smavstatic int hdac_resume(device_t); 1084162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 1085162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 1086162922Sariff uint32_t, int, int); 1087162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 1088182999Smav nid_t, int, int, int); 1089162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 1090162922Sariff nid_t, nid_t, int, int, int, int, int, int); 1091162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 1092162922Sariff 1093164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 1094164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 1095164614Sariff 1096182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 1097182999Smav 1098162922Sariff#define hdac_command(a1, a2, a3) \ 1099162922Sariff hdac_command_sendone_internal(a1, a2, a3) 1100162922Sariff 1101182999Smav#define hdac_codec_id(c) \ 1102182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 1103182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 1104182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 1105162922Sariff 1106162922Sariffstatic char * 1107182999Smavhdac_codec_name(struct hdac_codec *codec) 1108162922Sariff{ 1109162922Sariff uint32_t id; 1110162922Sariff int i; 1111162922Sariff 1112182999Smav id = hdac_codec_id(codec); 1113162922Sariff 1114162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 1115163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 1116162922Sariff return (hdac_codecs[i].name); 1117162922Sariff } 1118162922Sariff 1119162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 1120162922Sariff} 1121162922Sariff 1122162922Sariffstatic char * 1123162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 1124162922Sariff{ 1125162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 1126162922Sariff int i, first = 1; 1127162922Sariff 1128162922Sariff bzero(buf, len); 1129162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 1130162922Sariff if (mask & (1 << i)) { 1131162922Sariff if (first == 0) 1132162922Sariff strlcat(buf, ", ", len); 1133162922Sariff strlcat(buf, ossname[i], len); 1134162922Sariff first = 0; 1135162922Sariff } 1136162922Sariff } 1137182999Smav return (buf); 1138162922Sariff} 1139162922Sariff 1140162922Sariffstatic struct hdac_audio_ctl * 1141162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 1142162922Sariff{ 1143162922Sariff if (devinfo == NULL || 1144162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 1145162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 1146162922Sariff devinfo->function.audio.ctlcnt < 1 || 1147162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 1148162922Sariff return (NULL); 1149162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 1150162922Sariff} 1151162922Sariff 1152162922Sariffstatic struct hdac_audio_ctl * 1153182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 1154162922Sariff int index, int cnt) 1155162922Sariff{ 1156182999Smav struct hdac_audio_ctl *ctl; 1157182999Smav int i, found = 0; 1158162922Sariff 1159162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 1160162922Sariff return (NULL); 1161162922Sariff 1162162922Sariff i = 0; 1163162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 1164182999Smav if (ctl->enable == 0) 1165162922Sariff continue; 1166182999Smav if (ctl->widget->nid != nid) 1167162922Sariff continue; 1168182999Smav if (dir && ctl->ndir != dir) 1169182999Smav continue; 1170182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 1171182999Smav ctl->dir == ctl->ndir && ctl->index != index) 1172182999Smav continue; 1173162922Sariff found++; 1174182999Smav if (found == cnt || cnt <= 0) 1175162922Sariff return (ctl); 1176162922Sariff } 1177162922Sariff 1178182999Smav return (NULL); 1179162922Sariff} 1180162922Sariff 1181182999Smav/* 1182182999Smav * Jack detection (Speaker/HP redirection) event handler. 1183182999Smav */ 1184162922Sariffstatic void 1185162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 1186162922Sariff{ 1187182999Smav struct hdac_audio_as *as; 1188162922Sariff struct hdac_softc *sc; 1189162922Sariff struct hdac_widget *w; 1190162922Sariff struct hdac_audio_ctl *ctl; 1191182999Smav uint32_t val, res; 1192182999Smav int i, j; 1193162922Sariff nid_t cad; 1194162922Sariff 1195162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1196162922Sariff devinfo->codec->sc == NULL) 1197162922Sariff return; 1198162922Sariff 1199162922Sariff sc = devinfo->codec->sc; 1200162922Sariff cad = devinfo->codec->cad; 1201182999Smav as = devinfo->function.audio.as; 1202182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1203182999Smav if (as[i].hpredir < 0) 1204182999Smav continue; 1205182999Smav 1206182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1207182999Smav if (w == NULL || w->enable == 0 || w->type != 1208182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1209182999Smav continue; 1210162922Sariff 1211171141Sariff res = hdac_command(sc, 1212182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1213171141Sariff 1214182999Smav HDA_BOOTVERBOSE( 1215182999Smav device_printf(sc->dev, 1216182999Smav "Pin sense: nid=%d res=0x%08x\n", 1217182999Smav as[i].pins[15], res); 1218182999Smav ); 1219171141Sariff 1220182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1221182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1222182999Smav res ^= 1; 1223162922Sariff 1224182999Smav /* (Un)Mute headphone pin. */ 1225162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1226182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1227182999Smav if (ctl != NULL && ctl->mute) { 1228182999Smav /* If pin has muter - use it. */ 1229182999Smav val = (res != 0) ? 0 : 1; 1230182999Smav if (val != ctl->forcemute) { 1231182999Smav ctl->forcemute = val; 1232162922Sariff hdac_audio_ctl_amp_set(ctl, 1233182999Smav HDA_AMP_MUTE_DEFAULT, 1234182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1235162922Sariff } 1236182999Smav } else { 1237182999Smav /* If there is no muter - disable pin output. */ 1238182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1239163057Sariff if (w != NULL && w->type == 1240163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1241182999Smav if (res != 0) 1242169277Sariff val = w->wclass.pin.ctrl | 1243162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1244162922Sariff else 1245169277Sariff val = w->wclass.pin.ctrl & 1246162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1247169277Sariff if (val != w->wclass.pin.ctrl) { 1248169277Sariff w->wclass.pin.ctrl = val; 1249169277Sariff hdac_command(sc, 1250169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1251169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1252169277Sariff } 1253162922Sariff } 1254182999Smav } 1255182999Smav /* (Un)Mute other pins. */ 1256182999Smav for (j = 0; j < 15; j++) { 1257182999Smav if (as[i].pins[j] <= 0) 1258182999Smav continue; 1259182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1260182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1261182999Smav if (ctl != NULL && ctl->mute) { 1262182999Smav /* If pin has muter - use it. */ 1263182999Smav val = (res != 0) ? 1 : 0; 1264182999Smav if (val == ctl->forcemute) 1265169277Sariff continue; 1266182999Smav ctl->forcemute = val; 1267182999Smav hdac_audio_ctl_amp_set(ctl, 1268182999Smav HDA_AMP_MUTE_DEFAULT, 1269182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1270182999Smav continue; 1271162922Sariff } 1272182999Smav /* If there is no muter - disable pin output. */ 1273182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1274163057Sariff if (w != NULL && w->type == 1275163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1276182999Smav if (res != 0) 1277182999Smav val = w->wclass.pin.ctrl & 1278182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1279182999Smav else 1280182999Smav val = w->wclass.pin.ctrl | 1281182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1282169277Sariff if (val != w->wclass.pin.ctrl) { 1283169277Sariff w->wclass.pin.ctrl = val; 1284169277Sariff hdac_command(sc, 1285169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1286169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1287169277Sariff } 1288162922Sariff } 1289162922Sariff } 1290182999Smav } 1291182999Smav} 1292182999Smav 1293182999Smav/* 1294182999Smav * Callback for poll based jack detection. 1295182999Smav */ 1296182999Smavstatic void 1297182999Smavhdac_jack_poll_callback(void *arg) 1298182999Smav{ 1299182999Smav struct hdac_devinfo *devinfo = arg; 1300182999Smav struct hdac_softc *sc; 1301182999Smav 1302182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1303182999Smav devinfo->codec->sc == NULL) 1304182999Smav return; 1305182999Smav sc = devinfo->codec->sc; 1306182999Smav hdac_lock(sc); 1307182999Smav if (sc->poll_ival == 0) { 1308182999Smav hdac_unlock(sc); 1309182999Smav return; 1310182999Smav } 1311182999Smav hdac_hp_switch_handler(devinfo); 1312182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1313182999Smav hdac_jack_poll_callback, devinfo); 1314182999Smav hdac_unlock(sc); 1315182999Smav} 1316182999Smav 1317182999Smav/* 1318182999Smav * Jack detection initializer. 1319182999Smav */ 1320182999Smavstatic void 1321182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1322182999Smav{ 1323182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1324182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1325182999Smav struct hdac_widget *w; 1326182999Smav uint32_t id; 1327182999Smav int i, enable = 0, poll = 0; 1328182999Smav nid_t cad; 1329182999Smav 1330182999Smav id = hdac_codec_id(devinfo->codec); 1331182999Smav cad = devinfo->codec->cad; 1332182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1333182999Smav if (as[i].hpredir < 0) 1334182999Smav continue; 1335182999Smav 1336182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1337182999Smav if (w == NULL || w->enable == 0 || w->type != 1338182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1339182999Smav continue; 1340182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1341182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1342182999Smav device_printf(sc->dev, 1343182999Smav "No jack detection support at pin %d\n", 1344182999Smav as[i].pins[15]); 1345182999Smav continue; 1346182999Smav } 1347182999Smav enable = 1; 1348182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1349169277Sariff hdac_command(sc, 1350182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1351182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1352182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1353182999Smav } else 1354182999Smav poll = 1; 1355182999Smav HDA_BOOTVERBOSE( 1356169277Sariff device_printf(sc->dev, 1357182999Smav "Enabling headphone/speaker " 1358182999Smav "audio routing switching:\n"); 1359182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1360182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1361182999Smav ); 1362182999Smav } 1363182999Smav if (enable) { 1364182999Smav hdac_hp_switch_handler(devinfo); 1365182999Smav if (poll) { 1366182999Smav callout_reset(&sc->poll_jack, 1, 1367182999Smav hdac_jack_poll_callback, devinfo); 1368169277Sariff } 1369162922Sariff } 1370162922Sariff} 1371162922Sariff 1372182999Smav/* 1373182999Smav * Unsolicited messages handler. 1374182999Smav */ 1375162922Sariffstatic void 1376162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1377162922Sariff{ 1378162922Sariff struct hdac_softc *sc; 1379162922Sariff struct hdac_devinfo *devinfo = NULL; 1380182999Smav int i; 1381162922Sariff 1382162922Sariff if (codec == NULL || codec->sc == NULL) 1383162922Sariff return; 1384162922Sariff 1385162922Sariff sc = codec->sc; 1386162922Sariff 1387163057Sariff HDA_BOOTVERBOSE( 1388182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1389162922Sariff ); 1390162922Sariff 1391182999Smav for (i = 0; i < codec->num_fgs; i++) { 1392182999Smav if (codec->fgs[i].node_type == 1393182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1394182999Smav devinfo = &codec->fgs[i]; 1395162965Sariff break; 1396182999Smav } 1397162922Sariff } 1398162965Sariff 1399162922Sariff if (devinfo == NULL) 1400162922Sariff return; 1401162922Sariff 1402162922Sariff switch (tag) { 1403162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1404162922Sariff hdac_hp_switch_handler(devinfo); 1405162922Sariff break; 1406162922Sariff default: 1407182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1408162922Sariff break; 1409162922Sariff } 1410162922Sariff} 1411162922Sariff 1412164614Sariffstatic int 1413162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1414162922Sariff{ 1415162922Sariff /* XXX to be removed */ 1416162922Sariff#ifdef HDAC_INTR_EXTRA 1417162922Sariff uint32_t res; 1418162922Sariff#endif 1419162922Sariff 1420171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1421164614Sariff return (0); 1422162922Sariff 1423162922Sariff /* XXX to be removed */ 1424162922Sariff#ifdef HDAC_INTR_EXTRA 1425162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1426162922Sariff#endif 1427162922Sariff 1428162922Sariff /* XXX to be removed */ 1429162922Sariff#ifdef HDAC_INTR_EXTRA 1430163057Sariff HDA_BOOTVERBOSE( 1431163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1432182999Smav device_printf(ch->pdevinfo->dev, 1433163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1434163057Sariff "%08x\n", 1435163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1436163057Sariff ); 1437162922Sariff#endif 1438162922Sariff 1439162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1440163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1441162922Sariff 1442162922Sariff /* XXX to be removed */ 1443162922Sariff#ifdef HDAC_INTR_EXTRA 1444162922Sariff if (res & HDAC_SDSTS_BCIS) { 1445162922Sariff#endif 1446164614Sariff return (1); 1447162922Sariff /* XXX to be removed */ 1448162922Sariff#ifdef HDAC_INTR_EXTRA 1449162922Sariff } 1450162922Sariff#endif 1451164614Sariff 1452164614Sariff return (0); 1453162922Sariff} 1454162922Sariff 1455162922Sariff/**************************************************************************** 1456162922Sariff * void hdac_intr_handler(void *) 1457162922Sariff * 1458162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1459162922Sariff ****************************************************************************/ 1460162922Sariffstatic void 1461162922Sariffhdac_intr_handler(void *context) 1462162922Sariff{ 1463162922Sariff struct hdac_softc *sc; 1464162922Sariff uint32_t intsts; 1465162922Sariff uint8_t rirbsts; 1466164614Sariff struct hdac_rirb *rirb_base; 1467171141Sariff uint32_t trigger; 1468182999Smav int i; 1469162922Sariff 1470162922Sariff sc = (struct hdac_softc *)context; 1471162922Sariff 1472162922Sariff hdac_lock(sc); 1473164614Sariff if (sc->polling != 0) { 1474164614Sariff hdac_unlock(sc); 1475164614Sariff return; 1476164614Sariff } 1477171141Sariff 1478162922Sariff /* Do we have anything to do? */ 1479162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1480163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1481162922Sariff hdac_unlock(sc); 1482162922Sariff return; 1483162922Sariff } 1484162922Sariff 1485171141Sariff trigger = 0; 1486171141Sariff 1487162922Sariff /* Was this a controller interrupt? */ 1488163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1489162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1490162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1491162922Sariff /* Get as many responses that we can */ 1492163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1493164614Sariff HDAC_WRITE_1(&sc->mem, 1494164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1495171141Sariff if (hdac_rirb_flush(sc) != 0) 1496171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1497162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1498162922Sariff } 1499162922Sariff /* XXX to be removed */ 1500162922Sariff /* Clear interrupt and exit */ 1501162922Sariff#ifdef HDAC_INTR_EXTRA 1502162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1503162922Sariff#endif 1504162922Sariff } 1505164614Sariff 1506163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1507182999Smav for (i = 0; i < sc->num_chans; i++) { 1508182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1509182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1510182999Smav trigger |= (1 << i); 1511182999Smav } 1512162922Sariff /* XXX to be removed */ 1513162922Sariff#ifdef HDAC_INTR_EXTRA 1514164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1515164614Sariff HDAC_INTSTS_SIS_MASK); 1516162922Sariff#endif 1517162922Sariff } 1518162922Sariff 1519164614Sariff hdac_unlock(sc); 1520162922Sariff 1521182999Smav for (i = 0; i < sc->num_chans; i++) { 1522182999Smav if (trigger & (1 << i)) 1523182999Smav chn_intr(sc->chans[i].c); 1524182999Smav } 1525171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1526171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1527162922Sariff} 1528162922Sariff 1529162922Sariff/**************************************************************************** 1530182999Smav * int hdac_reset(hdac_softc *, int) 1531162922Sariff * 1532162922Sariff * Reset the hdac to a quiescent and known state. 1533162922Sariff ****************************************************************************/ 1534162922Sariffstatic int 1535182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1536162922Sariff{ 1537162922Sariff uint32_t gctl; 1538162922Sariff int count, i; 1539162922Sariff 1540162922Sariff /* 1541162922Sariff * Stop all Streams DMA engine 1542162922Sariff */ 1543162922Sariff for (i = 0; i < sc->num_iss; i++) 1544162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1545162922Sariff for (i = 0; i < sc->num_oss; i++) 1546162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1547162922Sariff for (i = 0; i < sc->num_bss; i++) 1548162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1549162922Sariff 1550162922Sariff /* 1551169277Sariff * Stop Control DMA engines. 1552162922Sariff */ 1553162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1554162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1555162922Sariff 1556162922Sariff /* 1557169277Sariff * Reset DMA position buffer. 1558169277Sariff */ 1559169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1560169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1561169277Sariff 1562169277Sariff /* 1563162922Sariff * Reset the controller. The reset must remain asserted for 1564162922Sariff * a minimum of 100us. 1565162922Sariff */ 1566162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1567162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1568162922Sariff count = 10000; 1569162922Sariff do { 1570162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1571162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1572162922Sariff break; 1573162922Sariff DELAY(10); 1574162922Sariff } while (--count); 1575162922Sariff if (gctl & HDAC_GCTL_CRST) { 1576162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1577162922Sariff return (ENXIO); 1578162922Sariff } 1579182999Smav 1580182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1581182999Smav if (!wakeup) 1582182999Smav return (0); 1583182999Smav 1584162922Sariff DELAY(100); 1585162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1586162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1587162922Sariff count = 10000; 1588162922Sariff do { 1589162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1590163057Sariff if (gctl & HDAC_GCTL_CRST) 1591162922Sariff break; 1592162922Sariff DELAY(10); 1593162922Sariff } while (--count); 1594162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1595162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1596162922Sariff return (ENXIO); 1597162922Sariff } 1598162922Sariff 1599162922Sariff /* 1600162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1601162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1602162922Sariff * computer. Let's use twice as much as necessary to make sure that 1603162922Sariff * it's reset properly. 1604162922Sariff */ 1605162922Sariff DELAY(1000); 1606162922Sariff 1607162922Sariff return (0); 1608162922Sariff} 1609162922Sariff 1610162922Sariff 1611162922Sariff/**************************************************************************** 1612162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1613162922Sariff * 1614162922Sariff * Retreive the general capabilities of the hdac; 1615162922Sariff * Number of Input Streams 1616162922Sariff * Number of Output Streams 1617162922Sariff * Number of bidirectional Streams 1618162922Sariff * 64bit ready 1619162922Sariff * CORB and RIRB sizes 1620162922Sariff ****************************************************************************/ 1621162922Sariffstatic int 1622162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1623162922Sariff{ 1624162922Sariff uint16_t gcap; 1625162922Sariff uint8_t corbsize, rirbsize; 1626162922Sariff 1627162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1628162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1629162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1630162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1631196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 1632163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1633162922Sariff 1634162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1635162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1636162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1637162922Sariff sc->corb_size = 256; 1638162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1639162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1640162922Sariff sc->corb_size = 16; 1641162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1642162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1643162922Sariff sc->corb_size = 2; 1644162922Sariff else { 1645162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1646162922Sariff __func__, corbsize); 1647162922Sariff return (ENXIO); 1648162922Sariff } 1649162922Sariff 1650162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1651162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1652162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1653162922Sariff sc->rirb_size = 256; 1654162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1655162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1656162922Sariff sc->rirb_size = 16; 1657162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1658162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1659162922Sariff sc->rirb_size = 2; 1660162922Sariff else { 1661162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1662162922Sariff __func__, rirbsize); 1663162922Sariff return (ENXIO); 1664162922Sariff } 1665162922Sariff 1666196762Smav HDA_BOOTVERBOSE( 1667196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 1668196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 1669196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 1670196762Smav sc->support_64bit ? ", 64bit" : "", 1671196762Smav sc->corb_size, sc->rirb_size); 1672182999Smav ); 1673182999Smav 1674162922Sariff return (0); 1675162922Sariff} 1676162922Sariff 1677162922Sariff 1678162922Sariff/**************************************************************************** 1679162922Sariff * void hdac_dma_cb 1680162922Sariff * 1681162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1682162922Sariff * established. We just record the physical address of the mapping into 1683162922Sariff * the struct hdac_dma passed in. 1684162922Sariff ****************************************************************************/ 1685162922Sariffstatic void 1686162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1687162922Sariff{ 1688162922Sariff struct hdac_dma *dma; 1689162922Sariff 1690162922Sariff if (error == 0) { 1691162922Sariff dma = (struct hdac_dma *)callback_arg; 1692162922Sariff dma->dma_paddr = segs[0].ds_addr; 1693162922Sariff } 1694162922Sariff} 1695162922Sariff 1696162922Sariff 1697162922Sariff/**************************************************************************** 1698162922Sariff * int hdac_dma_alloc 1699162922Sariff * 1700162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1701162922Sariff * It must be freed by a corresponding hdac_dma_free. 1702162922Sariff ****************************************************************************/ 1703162922Sariffstatic int 1704162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1705162922Sariff{ 1706169277Sariff bus_size_t roundsz; 1707162922Sariff int result; 1708162922Sariff 1709169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1710162922Sariff bzero(dma, sizeof(*dma)); 1711162922Sariff 1712162922Sariff /* 1713162922Sariff * Create a DMA tag 1714162922Sariff */ 1715194861Smav result = bus_dma_tag_create( 1716194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1717162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1718162922Sariff 0, /* boundary */ 1719194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1720194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1721162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1722162922Sariff NULL, /* filtfunc */ 1723162922Sariff NULL, /* fistfuncarg */ 1724169277Sariff roundsz, /* maxsize */ 1725162922Sariff 1, /* nsegments */ 1726169277Sariff roundsz, /* maxsegsz */ 1727162922Sariff 0, /* flags */ 1728162922Sariff NULL, /* lockfunc */ 1729162922Sariff NULL, /* lockfuncarg */ 1730162922Sariff &dma->dma_tag); /* dmat */ 1731162922Sariff if (result != 0) { 1732162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1733162922Sariff __func__, result); 1734167773Sariff goto hdac_dma_alloc_fail; 1735162922Sariff } 1736162922Sariff 1737162922Sariff /* 1738162922Sariff * Allocate DMA memory 1739162922Sariff */ 1740162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1741169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1742171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1743171330Sariff &dma->dma_map); 1744162922Sariff if (result != 0) { 1745162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1746162922Sariff __func__, result); 1747167773Sariff goto hdac_dma_alloc_fail; 1748162922Sariff } 1749162922Sariff 1750169277Sariff dma->dma_size = roundsz; 1751169277Sariff 1752162922Sariff /* 1753162922Sariff * Map the memory 1754162922Sariff */ 1755162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1756169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1757162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1758167773Sariff if (result == 0) 1759167773Sariff result = ENOMEM; 1760162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1761162922Sariff __func__, result); 1762167773Sariff goto hdac_dma_alloc_fail; 1763162922Sariff } 1764162922Sariff 1765183097Smav HDA_BOOTHVERBOSE( 1766169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1767169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1768169277Sariff ); 1769169277Sariff 1770162922Sariff return (0); 1771169277Sariff 1772167773Sariffhdac_dma_alloc_fail: 1773169277Sariff hdac_dma_free(sc, dma); 1774167773Sariff 1775162922Sariff return (result); 1776162922Sariff} 1777162922Sariff 1778162922Sariff 1779162922Sariff/**************************************************************************** 1780169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1781162922Sariff * 1782162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1783162922Sariff * hdac_dma_alloc function. 1784162922Sariff ****************************************************************************/ 1785162922Sariffstatic void 1786169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1787162922Sariff{ 1788167773Sariff if (dma->dma_map != NULL) { 1789169277Sariff#if 0 1790162922Sariff /* Flush caches */ 1791162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1792162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1793169277Sariff#endif 1794162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1795167773Sariff } 1796167773Sariff if (dma->dma_vaddr != NULL) { 1797162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1798167773Sariff dma->dma_vaddr = NULL; 1799167773Sariff } 1800167773Sariff dma->dma_map = NULL; 1801167773Sariff if (dma->dma_tag != NULL) { 1802162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1803167773Sariff dma->dma_tag = NULL; 1804162922Sariff } 1805167773Sariff dma->dma_size = 0; 1806162922Sariff} 1807162922Sariff 1808162922Sariff/**************************************************************************** 1809162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1810162922Sariff * 1811162922Sariff * Allocate all the bus resources necessary to speak with the physical 1812162922Sariff * controller. 1813162922Sariff ****************************************************************************/ 1814162922Sariffstatic int 1815162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1816162922Sariff{ 1817162922Sariff struct hdac_mem *mem; 1818162922Sariff 1819162922Sariff mem = &sc->mem; 1820162922Sariff mem->mem_rid = PCIR_BAR(0); 1821162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1822162922Sariff &mem->mem_rid, RF_ACTIVE); 1823162922Sariff if (mem->mem_res == NULL) { 1824162922Sariff device_printf(sc->dev, 1825162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1826162922Sariff return (ENOMEM); 1827162922Sariff } 1828162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1829162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1830162922Sariff 1831162922Sariff return (0); 1832162922Sariff} 1833162922Sariff 1834162922Sariff/**************************************************************************** 1835162922Sariff * void hdac_mem_free(struct hdac_softc *) 1836162922Sariff * 1837162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1838162922Sariff ****************************************************************************/ 1839162922Sariffstatic void 1840162922Sariffhdac_mem_free(struct hdac_softc *sc) 1841162922Sariff{ 1842162922Sariff struct hdac_mem *mem; 1843162922Sariff 1844162922Sariff mem = &sc->mem; 1845162922Sariff if (mem->mem_res != NULL) 1846162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1847162922Sariff mem->mem_res); 1848164614Sariff mem->mem_res = NULL; 1849162922Sariff} 1850162922Sariff 1851162922Sariff/**************************************************************************** 1852162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1853162922Sariff * 1854162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1855162922Sariff ****************************************************************************/ 1856162922Sariffstatic int 1857162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1858162922Sariff{ 1859162922Sariff struct hdac_irq *irq; 1860162922Sariff int result; 1861162922Sariff 1862162922Sariff irq = &sc->irq; 1863162922Sariff irq->irq_rid = 0x0; 1864171330Sariff 1865171330Sariff if ((sc->flags & HDAC_F_MSI) && 1866171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1867171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1868171330Sariff irq->irq_rid = 0x1; 1869171330Sariff else 1870171330Sariff sc->flags &= ~HDAC_F_MSI; 1871171330Sariff 1872162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1873162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1874162922Sariff if (irq->irq_res == NULL) { 1875162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1876162922Sariff __func__); 1877167773Sariff goto hdac_irq_alloc_fail; 1878162922Sariff } 1879182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1880182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1881162922Sariff if (result != 0) { 1882162922Sariff device_printf(sc->dev, 1883162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1884162922Sariff __func__, result); 1885167773Sariff goto hdac_irq_alloc_fail; 1886162922Sariff } 1887162922Sariff 1888162922Sariff return (0); 1889162922Sariff 1890167773Sariffhdac_irq_alloc_fail: 1891164614Sariff hdac_irq_free(sc); 1892164614Sariff 1893162922Sariff return (ENXIO); 1894162922Sariff} 1895162922Sariff 1896162922Sariff/**************************************************************************** 1897162922Sariff * void hdac_irq_free(struct hdac_softc *) 1898162922Sariff * 1899162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1900162922Sariff ****************************************************************************/ 1901162922Sariffstatic void 1902162922Sariffhdac_irq_free(struct hdac_softc *sc) 1903162922Sariff{ 1904162922Sariff struct hdac_irq *irq; 1905162922Sariff 1906162922Sariff irq = &sc->irq; 1907164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1908162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1909162922Sariff if (irq->irq_res != NULL) 1910162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1911162922Sariff irq->irq_res); 1912188656Smav if (irq->irq_rid == 0x1) 1913171330Sariff pci_release_msi(sc->dev); 1914164614Sariff irq->irq_handle = NULL; 1915164614Sariff irq->irq_res = NULL; 1916171330Sariff irq->irq_rid = 0x0; 1917162922Sariff} 1918162922Sariff 1919162922Sariff/**************************************************************************** 1920162922Sariff * void hdac_corb_init(struct hdac_softc *) 1921162922Sariff * 1922162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1923162922Sariff * The CORB engine must not be running when this function is called. 1924162922Sariff ****************************************************************************/ 1925162922Sariffstatic void 1926162922Sariffhdac_corb_init(struct hdac_softc *sc) 1927162922Sariff{ 1928162922Sariff uint8_t corbsize; 1929162922Sariff uint64_t corbpaddr; 1930162922Sariff 1931162922Sariff /* Setup the CORB size. */ 1932162922Sariff switch (sc->corb_size) { 1933162922Sariff case 256: 1934162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1935162922Sariff break; 1936162922Sariff case 16: 1937162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1938162922Sariff break; 1939162922Sariff case 2: 1940162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1941162922Sariff break; 1942162922Sariff default: 1943162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1944162922Sariff } 1945162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1946162922Sariff 1947162922Sariff /* Setup the CORB Address in the hdac */ 1948162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1949162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1950162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1951162922Sariff 1952162922Sariff /* Set the WP and RP */ 1953162922Sariff sc->corb_wp = 0; 1954162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1955162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1956162922Sariff /* 1957162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1958162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1959162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1960162922Sariff * manually reset the bit to zero before continuing. 1961162922Sariff */ 1962162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1963162922Sariff 1964162922Sariff /* Enable CORB error reporting */ 1965162922Sariff#if 0 1966162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1967162922Sariff#endif 1968162922Sariff} 1969162922Sariff 1970162922Sariff/**************************************************************************** 1971162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1972162922Sariff * 1973162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1974162922Sariff * The RIRB engine must not be running when this function is called. 1975162922Sariff ****************************************************************************/ 1976162922Sariffstatic void 1977162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1978162922Sariff{ 1979162922Sariff uint8_t rirbsize; 1980162922Sariff uint64_t rirbpaddr; 1981162922Sariff 1982162922Sariff /* Setup the RIRB size. */ 1983162922Sariff switch (sc->rirb_size) { 1984162922Sariff case 256: 1985162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1986162922Sariff break; 1987162922Sariff case 16: 1988162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1989162922Sariff break; 1990162922Sariff case 2: 1991162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1992162922Sariff break; 1993162922Sariff default: 1994162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1995162922Sariff } 1996162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1997162922Sariff 1998162922Sariff /* Setup the RIRB Address in the hdac */ 1999162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 2000162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 2001162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 2002162922Sariff 2003162922Sariff /* Setup the WP and RP */ 2004162922Sariff sc->rirb_rp = 0; 2005162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 2006162922Sariff 2007182999Smav /* Setup the interrupt threshold */ 2008182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 2009162922Sariff 2010182999Smav /* Enable Overrun and response received reporting */ 2011162922Sariff#if 0 2012182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 2013182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 2014162922Sariff#else 2015182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 2016162922Sariff#endif 2017162922Sariff 2018169277Sariff#if 0 2019162922Sariff /* 2020162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 2021162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 2022162922Sariff * should be sufficient to do this only once as the rirb is purely 2023162922Sariff * read-only from now on. 2024162922Sariff */ 2025162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2026162922Sariff BUS_DMASYNC_PREREAD); 2027169277Sariff#endif 2028162922Sariff} 2029162922Sariff 2030162922Sariff/**************************************************************************** 2031162922Sariff * void hdac_corb_start(hdac_softc *) 2032162922Sariff * 2033162922Sariff * Startup the corb DMA engine 2034162922Sariff ****************************************************************************/ 2035162922Sariffstatic void 2036162922Sariffhdac_corb_start(struct hdac_softc *sc) 2037162922Sariff{ 2038162922Sariff uint32_t corbctl; 2039162922Sariff 2040162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 2041162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 2042162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 2043162922Sariff} 2044162922Sariff 2045162922Sariff/**************************************************************************** 2046162922Sariff * void hdac_rirb_start(hdac_softc *) 2047162922Sariff * 2048162922Sariff * Startup the rirb DMA engine 2049162922Sariff ****************************************************************************/ 2050162922Sariffstatic void 2051162922Sariffhdac_rirb_start(struct hdac_softc *sc) 2052162922Sariff{ 2053162922Sariff uint32_t rirbctl; 2054162922Sariff 2055162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 2056162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 2057162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 2058162922Sariff} 2059162922Sariff 2060162922Sariff 2061162922Sariff/**************************************************************************** 2062172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 2063162922Sariff * 2064172811Sariff * Scan the bus for available codecs, starting with num. 2065162922Sariff ****************************************************************************/ 2066162922Sariffstatic void 2067182999Smavhdac_scan_codecs(struct hdac_softc *sc) 2068162922Sariff{ 2069162922Sariff struct hdac_codec *codec; 2070162922Sariff int i; 2071162922Sariff uint16_t statests; 2072162922Sariff 2073162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 2074182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 2075162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 2076162922Sariff /* We have found a codec. */ 2077162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 2078162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 2079162922Sariff if (codec == NULL) { 2080162922Sariff device_printf(sc->dev, 2081162922Sariff "Unable to allocate memory for codec\n"); 2082162922Sariff continue; 2083162922Sariff } 2084164614Sariff codec->commands = NULL; 2085164614Sariff codec->responses_received = 0; 2086162922Sariff codec->verbs_sent = 0; 2087162922Sariff codec->sc = sc; 2088162922Sariff codec->cad = i; 2089162922Sariff sc->codecs[i] = codec; 2090182999Smav hdac_probe_codec(codec); 2091162922Sariff } 2092162922Sariff } 2093162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 2094163057Sariff /* bus_generic_attach(sc->dev); */ 2095162922Sariff} 2096162922Sariff 2097162922Sariff/**************************************************************************** 2098162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 2099162922Sariff * 2100162922Sariff * Probe a the given codec_id for available function groups. 2101162922Sariff ****************************************************************************/ 2102182999Smavstatic void 2103162922Sariffhdac_probe_codec(struct hdac_codec *codec) 2104162922Sariff{ 2105162922Sariff struct hdac_softc *sc = codec->sc; 2106162922Sariff uint32_t vendorid, revisionid, subnode; 2107162922Sariff int startnode; 2108162922Sariff int endnode; 2109162922Sariff int i; 2110162922Sariff nid_t cad = codec->cad; 2111162922Sariff 2112163057Sariff HDA_BOOTVERBOSE( 2113184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 2114162922Sariff ); 2115162922Sariff vendorid = hdac_command(sc, 2116162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 2117162922Sariff cad); 2118162922Sariff revisionid = hdac_command(sc, 2119162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 2120162922Sariff cad); 2121182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 2122182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 2123182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 2124182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 2125182999Smav 2126182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 2127182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 2128182999Smav " Probing aborted.\n", cad); 2129182999Smav return; 2130182999Smav } 2131182999Smav 2132184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 2133182999Smav cad, hdac_codec_name(codec)); 2134182999Smav HDA_BOOTVERBOSE( 2135184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 2136182999Smav hdac_codec_id(codec)); 2137182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 2138182999Smav codec->vendor_id); 2139182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 2140182999Smav codec->device_id); 2141182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 2142182999Smav codec->revision_id); 2143182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 2144182999Smav codec->stepping_id); 2145182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2146182999Smav sc->pci_subvendor); 2147182999Smav ); 2148162922Sariff subnode = hdac_command(sc, 2149162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 2150162922Sariff cad); 2151162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 2152162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 2153162922Sariff 2154183097Smav HDA_BOOTHVERBOSE( 2155182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 2156163057Sariff startnode, endnode); 2157162922Sariff ); 2158182999Smav 2159182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 2160182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 2161182999Smav if (codec->fgs == NULL) { 2162183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 2163182999Smav __func__); 2164182999Smav return; 2165162922Sariff } 2166162922Sariff 2167182999Smav for (i = startnode; i < endnode; i++) 2168182999Smav hdac_probe_function(codec, i); 2169182999Smav return; 2170162922Sariff} 2171162922Sariff 2172182999Smav/* 2173182999Smav * Probe codec function and add it to the list. 2174182999Smav */ 2175182999Smavstatic void 2176162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 2177162922Sariff{ 2178162922Sariff struct hdac_softc *sc = codec->sc; 2179182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 2180162922Sariff uint32_t fctgrptype; 2181182999Smav uint32_t res; 2182162922Sariff nid_t cad = codec->cad; 2183162922Sariff 2184162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 2185162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 2186162922Sariff 2187162922Sariff devinfo->nid = nid; 2188162965Sariff devinfo->node_type = fctgrptype; 2189162922Sariff devinfo->codec = codec; 2190162922Sariff 2191182999Smav res = hdac_command(sc, 2192182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2193162922Sariff 2194182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2195182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2196182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2197162922Sariff 2198182999Smav HDA_BOOTVERBOSE( 2199182999Smav device_printf(sc->dev, 2200182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2201182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2202182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2203182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2204182999Smav devinfo->nodecnt); 2205182999Smav ); 2206182999Smav 2207182999Smav if (devinfo->nodecnt > 0) 2208182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2209182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2210182999Smav M_NOWAIT | M_ZERO); 2211182999Smav else 2212182999Smav devinfo->widget = NULL; 2213182999Smav 2214182999Smav if (devinfo->widget == NULL) { 2215182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2216182999Smav devinfo->endnode = devinfo->startnode; 2217182999Smav devinfo->nodecnt = 0; 2218182999Smav return; 2219182999Smav } 2220182999Smav 2221182999Smav codec->num_fgs++; 2222162922Sariff} 2223162922Sariff 2224162922Sariffstatic void 2225162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2226162922Sariff{ 2227162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2228162922Sariff uint32_t res; 2229169277Sariff int i, j, max, ents, entnum; 2230162922Sariff nid_t cad = w->devinfo->codec->cad; 2231162922Sariff nid_t nid = w->nid; 2232169277Sariff nid_t cnid, addcnid, prevcnid; 2233162922Sariff 2234169277Sariff w->nconns = 0; 2235169277Sariff 2236162922Sariff res = hdac_command(sc, 2237162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2238162922Sariff 2239169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2240162922Sariff 2241169277Sariff if (ents < 1) 2242162922Sariff return; 2243162922Sariff 2244162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2245162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2246169277Sariff prevcnid = 0; 2247162922Sariff 2248169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2249169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2250169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2251169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2252169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2253169277Sariff 2254169277Sariff for (i = 0; i < ents; i += entnum) { 2255162922Sariff res = hdac_command(sc, 2256162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2257162922Sariff for (j = 0; j < entnum; j++) { 2258169277Sariff cnid = CONN_CNID(res, entnum, j); 2259169277Sariff if (cnid == 0) { 2260169277Sariff if (w->nconns < ents) 2261169277Sariff device_printf(sc->dev, 2262169277Sariff "%s: nid=%d WARNING: zero cnid " 2263169277Sariff "entnum=%d j=%d index=%d " 2264169277Sariff "entries=%d found=%d res=0x%08x\n", 2265169277Sariff __func__, nid, entnum, j, i, 2266169277Sariff ents, w->nconns, res); 2267169277Sariff else 2268169277Sariff goto getconns_out; 2269169277Sariff } 2270169277Sariff if (cnid < w->devinfo->startnode || 2271169277Sariff cnid >= w->devinfo->endnode) { 2272169277Sariff HDA_BOOTVERBOSE( 2273169277Sariff device_printf(sc->dev, 2274182999Smav "GHOST: nid=%d j=%d " 2275169277Sariff "entnum=%d index=%d res=0x%08x\n", 2276182999Smav nid, j, entnum, i, res); 2277169277Sariff ); 2278169277Sariff } 2279169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2280169277Sariff addcnid = cnid; 2281169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2282162922Sariff device_printf(sc->dev, 2283169277Sariff "%s: WARNING: Invalid child range " 2284169277Sariff "nid=%d index=%d j=%d entnum=%d " 2285169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2286169277Sariff __func__, nid, i, j, entnum, prevcnid, 2287169277Sariff cnid, res); 2288169277Sariff addcnid = cnid; 2289169277Sariff } else 2290169277Sariff addcnid = prevcnid + 1; 2291169277Sariff while (addcnid <= cnid) { 2292169277Sariff if (w->nconns > max) { 2293169277Sariff device_printf(sc->dev, 2294182999Smav "Adding %d (nid=%d): " 2295169277Sariff "Max connection reached! max=%d\n", 2296182999Smav addcnid, nid, max + 1); 2297169277Sariff goto getconns_out; 2298169277Sariff } 2299182999Smav w->connsenable[w->nconns] = 1; 2300169277Sariff w->conns[w->nconns++] = addcnid++; 2301162922Sariff } 2302169277Sariff prevcnid = cnid; 2303162922Sariff } 2304162922Sariff } 2305162922Sariff 2306169277Sariffgetconns_out: 2307169277Sariff return; 2308162922Sariff} 2309162922Sariff 2310162922Sariffstatic uint32_t 2311182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2312182999Smav{ 2313182999Smav char buf[256]; 2314182999Smav char *key, *value, *rest, *bad; 2315182999Smav int ival, i; 2316182999Smav 2317182999Smav strlcpy(buf, str, sizeof(buf)); 2318182999Smav rest = buf; 2319182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2320182999Smav value = strsep(&rest, " \t"); 2321182999Smav if (value == NULL) 2322182999Smav break; 2323182999Smav ival = strtol(value, &bad, 10); 2324182999Smav if (strcmp(key, "seq") == 0) { 2325182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2326182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2327182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2328182999Smav } else if (strcmp(key, "as") == 0) { 2329182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2330182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2331182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2332182999Smav } else if (strcmp(key, "misc") == 0) { 2333182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2334182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2335182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2336182999Smav } else if (strcmp(key, "color") == 0) { 2337182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2338182999Smav if (bad[0] == 0) { 2339182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2340182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2341182999Smav }; 2342182999Smav for (i = 0; i < 16; i++) { 2343182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2344182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2345182999Smav break; 2346182999Smav } 2347182999Smav } 2348182999Smav } else if (strcmp(key, "ctype") == 0) { 2349182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2350182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2351182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2352182999Smav } else if (strcmp(key, "device") == 0) { 2353182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2354182999Smav if (bad[0] == 0) { 2355182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2356182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2357182999Smav continue; 2358182999Smav }; 2359182999Smav for (i = 0; i < 16; i++) { 2360182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2361182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2362182999Smav break; 2363182999Smav } 2364182999Smav } 2365182999Smav } else if (strcmp(key, "loc") == 0) { 2366182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2367182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2368182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2369182999Smav } else if (strcmp(key, "conn") == 0) { 2370182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2371182999Smav if (bad[0] == 0) { 2372182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2373182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2374182999Smav continue; 2375182999Smav }; 2376182999Smav for (i = 0; i < 4; i++) { 2377182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2378182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2379182999Smav break; 2380182999Smav } 2381182999Smav } 2382182999Smav } 2383182999Smav } 2384182999Smav return (config); 2385182999Smav} 2386182999Smav 2387182999Smavstatic uint32_t 2388162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2389162922Sariff{ 2390162922Sariff struct hdac_softc *sc; 2391166965Sariff uint32_t config, orig, id; 2392162922Sariff nid_t cad, nid; 2393182999Smav char buf[32]; 2394182999Smav const char *res = NULL, *patch = NULL; 2395162922Sariff 2396162922Sariff sc = w->devinfo->codec->sc; 2397162922Sariff cad = w->devinfo->codec->cad; 2398162922Sariff nid = w->nid; 2399182999Smav id = hdac_codec_id(w->devinfo->codec); 2400162922Sariff 2401162922Sariff config = hdac_command(sc, 2402162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2403162922Sariff cad); 2404166965Sariff orig = config; 2405166965Sariff 2406182999Smav HDA_BOOTVERBOSE( 2407182999Smav hdac_dump_pin_config(w, orig); 2408182999Smav ); 2409182999Smav 2410182999Smav /* XXX: Old patches require complete review. 2411182999Smav * Now they may create more problem then solve due to 2412182999Smav * incorrect associations. 2413162965Sariff */ 2414165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2415165281Sariff switch (nid) { 2416165281Sariff case 26: 2417165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2418165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2419165281Sariff break; 2420165281Sariff case 27: 2421165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2422165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2423165281Sariff break; 2424167610Sariff default: 2425167610Sariff break; 2426165281Sariff } 2427165281Sariff } else if (id == HDA_CODEC_ALC880 && 2428162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2429162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2430162922Sariff /* 2431162965Sariff * Super broken BIOS 2432162922Sariff */ 2433162922Sariff switch (nid) { 2434162922Sariff case 24: /* MIC1 */ 2435162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2436162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2437162922Sariff break; 2438162922Sariff case 25: /* XXX MIC2 */ 2439162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2440162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2441162922Sariff break; 2442162922Sariff case 26: /* LINE1 */ 2443162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2444162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2445162922Sariff break; 2446162922Sariff case 27: /* XXX LINE2 */ 2447162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2448162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2449162922Sariff break; 2450162922Sariff case 28: /* CD */ 2451162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2452162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2453162922Sariff break; 2454162922Sariff } 2455166965Sariff } else if (id == HDA_CODEC_ALC883 && 2456172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2457172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2458166965Sariff switch (nid) { 2459166965Sariff case 25: 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; 2465169277Sariff case 28: 2466169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2467169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2468169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2469169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2470169277Sariff break; 2471166965Sariff } 2472186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2473166965Sariff HP_V3000_SUBVENDOR) { 2474166965Sariff switch (nid) { 2475166965Sariff case 18: 2476166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2477166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2478166965Sariff break; 2479166965Sariff case 20: 2480166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2481166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2482166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2483166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2484166965Sariff break; 2485167454Sariff case 21: 2486167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2487167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2488167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2489167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2490167454Sariff break; 2491166965Sariff } 2492186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2493169277Sariff HP_DV5000_SUBVENDOR) { 2494169277Sariff switch (nid) { 2495169277Sariff case 20: 2496169277Sariff case 21: 2497169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2498169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2499169277Sariff break; 2500169277Sariff } 2501169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2502169277Sariff ASUS_W6F_SUBVENDOR) { 2503169277Sariff switch (nid) { 2504169277Sariff case 11: 2505169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2506169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2507169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2508169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2509169277Sariff break; 2510178324Sariff case 12: 2511178324Sariff case 14: 2512178324Sariff case 16: 2513178324Sariff case 31: 2514178324Sariff case 32: 2515178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2516178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2517178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2518178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2519178324Sariff break; 2520169277Sariff case 15: 2521169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2522169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2523169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2524169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2525169277Sariff break; 2526169277Sariff } 2527169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2528169277Sariff UNIWILL_9075_SUBVENDOR) { 2529169277Sariff switch (nid) { 2530169277Sariff case 15: 2531169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2532169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2533169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2534169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2535169277Sariff break; 2536169277Sariff } 2537182999Smav } 2538182999Smav 2539182999Smav /* New patches */ 2540182999Smav if (id == HDA_CODEC_AD1986A && 2541171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2542190630Smav sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR || 2543190630Smav sc->pci_subvendor == ASUS_P5PL2_SUBVENDOR)) { 2544169277Sariff switch (nid) { 2545190630Smav case 26: /* Headphones with redirection */ 2546190630Smav patch = "as=1 seq=15"; 2547190630Smav break; 2548190630Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 2549182999Smav patch = "device=Line-in as=8 seq=1"; 2550169277Sariff break; 2551190630Smav case 29: /* Can't use this as input, as the only available mic 2552190630Smav * preamplifier is busy by front panel mic (nid 31). 2553190630Smav * If you want to use this rear connector as mic input, 2554190630Smav * you have to disable the front panel one. */ 2555190630Smav patch = "as=0"; 2556169277Sariff break; 2557182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2558182999Smav patch = "as=8 seq=3"; 2559169277Sariff break; 2560182999Smav case 32: 2561182999Smav patch = "as=8 seq=4"; 2562182999Smav break; 2563182999Smav case 34: 2564182999Smav patch = "as=8 seq=5"; 2565182999Smav break; 2566182999Smav case 36: 2567182999Smav patch = "as=8 seq=6"; 2568182999Smav break; 2569169277Sariff } 2570182999Smav } else if (id == HDA_CODEC_ALC260 && 2571182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2572182999Smav switch (nid) { 2573182999Smav case 16: 2574182999Smav patch = "seq=15 device=Headphones"; 2575182999Smav break; 2576182999Smav } 2577189879Smav } else if (id == HDA_CODEC_ALC268) { 2578189879Smav if (sc->pci_subvendor == ACER_T5320_SUBVENDOR) { 2579174578Sariff switch (nid) { 2580189879Smav case 20: /* Headphones Jack */ 2581189879Smav patch = "as=1 seq=15"; 2582174578Sariff break; 2583174578Sariff } 2584189879Smav } 2585162922Sariff } 2586162922Sariff 2587182999Smav if (patch != NULL) 2588182999Smav config = hdac_widget_pin_patch(config, patch); 2589182999Smav 2590182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2591182999Smav if (resource_string_value(device_get_name(sc->dev), 2592182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2593182999Smav if (strncmp(res, "0x", 2) == 0) { 2594182999Smav config = strtol(res + 2, NULL, 16); 2595182999Smav } else { 2596182999Smav config = hdac_widget_pin_patch(config, res); 2597182999Smav } 2598182999Smav } 2599182999Smav 2600166965Sariff HDA_BOOTVERBOSE( 2601166965Sariff if (config != orig) 2602166965Sariff device_printf(sc->dev, 2603182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2604166965Sariff nid, orig, config); 2605166965Sariff ); 2606166965Sariff 2607162922Sariff return (config); 2608162922Sariff} 2609162922Sariff 2610166965Sariffstatic uint32_t 2611166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2612166965Sariff{ 2613166965Sariff struct hdac_softc *sc; 2614166965Sariff uint32_t caps, orig, id; 2615166965Sariff nid_t cad, nid; 2616166965Sariff 2617166965Sariff sc = w->devinfo->codec->sc; 2618166965Sariff cad = w->devinfo->codec->cad; 2619166965Sariff nid = w->nid; 2620182999Smav id = hdac_codec_id(w->devinfo->codec); 2621166965Sariff 2622166965Sariff caps = hdac_command(sc, 2623166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2624166965Sariff orig = caps; 2625166965Sariff 2626166965Sariff HDA_BOOTVERBOSE( 2627166965Sariff if (caps != orig) 2628166965Sariff device_printf(sc->dev, 2629182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2630166965Sariff nid, orig, caps); 2631166965Sariff ); 2632166965Sariff 2633166965Sariff return (caps); 2634166965Sariff} 2635166965Sariff 2636162922Sariffstatic void 2637162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2638162922Sariff{ 2639162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2640162922Sariff uint32_t config, pincap; 2641186912Smav const char *devstr; 2642162922Sariff nid_t cad = w->devinfo->codec->cad; 2643162922Sariff nid_t nid = w->nid; 2644186912Smav int conn, color; 2645162922Sariff 2646162922Sariff config = hdac_widget_pin_getconfig(w); 2647162922Sariff w->wclass.pin.config = config; 2648162922Sariff 2649166965Sariff pincap = hdac_widget_pin_getcaps(w); 2650162922Sariff w->wclass.pin.cap = pincap; 2651162922Sariff 2652162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2653182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2654162922Sariff 2655162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2656162922Sariff w->param.eapdbtl = hdac_command(sc, 2657162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2658162922Sariff w->param.eapdbtl &= 0x7; 2659162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2660162922Sariff } else 2661162965Sariff w->param.eapdbtl = HDAC_INVALID; 2662162922Sariff 2663182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2664182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2665162922Sariff 2666186912Smav conn = (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2667186912Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT; 2668186912Smav color = (config & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> 2669186912Smav HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT; 2670162922Sariff 2671162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2672162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2673162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2674186912Smav if (conn == 0 && color != 0 && color != 15) { 2675186912Smav strlcat(w->name, HDA_COLORS[color], sizeof(w->name)); 2676186912Smav strlcat(w->name, " ", sizeof(w->name)); 2677186912Smav } 2678186912Smav strlcat(w->name, HDA_CONNS[conn], sizeof(w->name)); 2679162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2680162922Sariff} 2681162922Sariff 2682182999Smavstatic uint32_t 2683182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2684182999Smav{ 2685182999Smav struct hdac_softc *sc; 2686182999Smav uint32_t caps, orig, id; 2687182999Smav nid_t cad, nid, beeper = -1; 2688182999Smav 2689182999Smav sc = w->devinfo->codec->sc; 2690182999Smav cad = w->devinfo->codec->cad; 2691182999Smav nid = w->nid; 2692182999Smav id = hdac_codec_id(w->devinfo->codec); 2693182999Smav 2694182999Smav caps = hdac_command(sc, 2695182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2696182999Smav cad); 2697182999Smav orig = caps; 2698182999Smav 2699182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2700182999Smav alone. Also most of BIOSes does not declare beeper pin. 2701182999Smav Change beeper pin node type to beeper to help parser. */ 2702182999Smav *waspin = 0; 2703182999Smav switch (id) { 2704187721Smav case HDA_CODEC_AD1882: 2705187721Smav case HDA_CODEC_AD1883: 2706187721Smav case HDA_CODEC_AD1984: 2707187721Smav case HDA_CODEC_AD1984A: 2708187721Smav case HDA_CODEC_AD1984B: 2709187721Smav case HDA_CODEC_AD1987: 2710182999Smav case HDA_CODEC_AD1988: 2711182999Smav case HDA_CODEC_AD1988B: 2712187721Smav case HDA_CODEC_AD1989B: 2713182999Smav beeper = 26; 2714182999Smav break; 2715182999Smav case HDA_CODEC_ALC260: 2716182999Smav beeper = 23; 2717182999Smav break; 2718182999Smav case HDA_CODEC_ALC262: 2719182999Smav case HDA_CODEC_ALC268: 2720182999Smav case HDA_CODEC_ALC880: 2721182999Smav case HDA_CODEC_ALC882: 2722182999Smav case HDA_CODEC_ALC883: 2723182999Smav case HDA_CODEC_ALC885: 2724182999Smav case HDA_CODEC_ALC888: 2725182999Smav case HDA_CODEC_ALC889: 2726182999Smav beeper = 29; 2727182999Smav break; 2728182999Smav } 2729182999Smav if (nid == beeper) { 2730182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2731182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2732182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2733182999Smav *waspin = 1; 2734182999Smav } 2735182999Smav 2736182999Smav HDA_BOOTVERBOSE( 2737182999Smav if (caps != orig) { 2738182999Smav device_printf(sc->dev, 2739182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2740182999Smav nid, orig, caps); 2741182999Smav } 2742182999Smav ); 2743182999Smav 2744182999Smav return (caps); 2745182999Smav} 2746182999Smav 2747162922Sariffstatic void 2748162922Sariffhdac_widget_parse(struct hdac_widget *w) 2749162922Sariff{ 2750162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2751162922Sariff uint32_t wcap, cap; 2752162922Sariff char *typestr; 2753162922Sariff nid_t cad = w->devinfo->codec->cad; 2754162922Sariff nid_t nid = w->nid; 2755162922Sariff 2756182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2757182999Smav 2758162922Sariff w->param.widget_cap = wcap; 2759162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2760162922Sariff 2761162922Sariff switch (w->type) { 2762162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2763162922Sariff typestr = "audio output"; 2764162922Sariff break; 2765162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2766162922Sariff typestr = "audio input"; 2767162922Sariff break; 2768162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2769162922Sariff typestr = "audio mixer"; 2770162922Sariff break; 2771162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2772162922Sariff typestr = "audio selector"; 2773162922Sariff break; 2774162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2775162922Sariff typestr = "pin"; 2776162922Sariff break; 2777162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2778162922Sariff typestr = "power widget"; 2779162922Sariff break; 2780162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2781162922Sariff typestr = "volume widget"; 2782162922Sariff break; 2783162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2784162922Sariff typestr = "beep widget"; 2785162922Sariff break; 2786162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2787162922Sariff typestr = "vendor widget"; 2788162922Sariff break; 2789162922Sariff default: 2790162922Sariff typestr = "unknown type"; 2791162922Sariff break; 2792162922Sariff } 2793162922Sariff 2794162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2795162922Sariff 2796162922Sariff hdac_widget_connection_parse(w); 2797162922Sariff 2798162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2799162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2800162922Sariff w->param.outamp_cap = 2801162922Sariff hdac_command(sc, 2802162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2803162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2804162922Sariff else 2805162922Sariff w->param.outamp_cap = 2806162922Sariff w->devinfo->function.audio.outamp_cap; 2807162922Sariff } else 2808162922Sariff w->param.outamp_cap = 0; 2809162922Sariff 2810162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2811162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2812162922Sariff w->param.inamp_cap = 2813162922Sariff hdac_command(sc, 2814162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2815162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2816162922Sariff else 2817162922Sariff w->param.inamp_cap = 2818162922Sariff w->devinfo->function.audio.inamp_cap; 2819162922Sariff } else 2820162922Sariff w->param.inamp_cap = 0; 2821162922Sariff 2822162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2823162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2824162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2825162922Sariff cap = hdac_command(sc, 2826162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2827162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2828162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2829162922Sariff w->devinfo->function.audio.supp_stream_formats; 2830162922Sariff cap = hdac_command(sc, 2831162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2832162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2833162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2834162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2835162922Sariff } else { 2836162922Sariff w->param.supp_stream_formats = 2837162922Sariff w->devinfo->function.audio.supp_stream_formats; 2838162922Sariff w->param.supp_pcm_size_rate = 2839162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2840162922Sariff } 2841162922Sariff } else { 2842162922Sariff w->param.supp_stream_formats = 0; 2843162922Sariff w->param.supp_pcm_size_rate = 0; 2844162922Sariff } 2845162922Sariff 2846162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2847162922Sariff hdac_widget_pin_parse(w); 2848162922Sariff} 2849162922Sariff 2850162922Sariffstatic struct hdac_widget * 2851162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2852162922Sariff{ 2853162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2854162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2855162922Sariff return (NULL); 2856162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2857162922Sariff} 2858162922Sariff 2859164614Sariffstatic __inline int 2860164614Sariffhda_poll_channel(struct hdac_chan *ch) 2861164614Sariff{ 2862164614Sariff uint32_t sz, delta; 2863164614Sariff volatile uint32_t ptr; 2864164614Sariff 2865171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2866164614Sariff return (0); 2867164614Sariff 2868164614Sariff sz = ch->blksz * ch->blkcnt; 2869169277Sariff if (ch->dmapos != NULL) 2870169277Sariff ptr = *(ch->dmapos); 2871169277Sariff else 2872169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2873169277Sariff ch->off + HDAC_SDLPIB); 2874164614Sariff ch->ptr = ptr; 2875164614Sariff ptr %= sz; 2876164614Sariff ptr &= ~(ch->blksz - 1); 2877164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2878164614Sariff 2879164614Sariff if (delta < ch->blksz) 2880164614Sariff return (0); 2881164614Sariff 2882164614Sariff ch->prevptr = ptr; 2883164614Sariff 2884164614Sariff return (1); 2885164614Sariff} 2886164614Sariff 2887162922Sariffstatic void 2888164614Sariffhda_poll_callback(void *arg) 2889164614Sariff{ 2890164614Sariff struct hdac_softc *sc = arg; 2891171141Sariff uint32_t trigger; 2892182999Smav int i, active = 0; 2893164614Sariff 2894164614Sariff if (sc == NULL) 2895164614Sariff return; 2896164614Sariff 2897164614Sariff hdac_lock(sc); 2898182999Smav if (sc->polling == 0) { 2899164614Sariff hdac_unlock(sc); 2900164614Sariff return; 2901164614Sariff } 2902164614Sariff 2903171141Sariff trigger = 0; 2904182999Smav for (i = 0; i < sc->num_chans; i++) { 2905182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2906182999Smav continue; 2907182999Smav active = 1; 2908182999Smav if (hda_poll_channel(&sc->chans[i])) 2909182999Smav trigger |= (1 << i); 2910182999Smav } 2911164614Sariff 2912164614Sariff /* XXX */ 2913182999Smav if (active) 2914182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2915182999Smav hda_poll_callback, sc); 2916164614Sariff 2917164614Sariff hdac_unlock(sc); 2918164614Sariff 2919182999Smav for (i = 0; i < sc->num_chans; i++) { 2920182999Smav if (trigger & (1 << i)) 2921182999Smav chn_intr(sc->chans[i].c); 2922182999Smav } 2923164614Sariff} 2924164614Sariff 2925164614Sariffstatic int 2926164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2927164614Sariff{ 2928164614Sariff struct hdac_rirb *rirb_base, *rirb; 2929164614Sariff struct hdac_codec *codec; 2930164614Sariff struct hdac_command_list *commands; 2931164614Sariff nid_t cad; 2932164614Sariff uint32_t resp; 2933164614Sariff uint8_t rirbwp; 2934171141Sariff int ret; 2935164614Sariff 2936164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2937164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2938169277Sariff#if 0 2939164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2940164614Sariff BUS_DMASYNC_POSTREAD); 2941169277Sariff#endif 2942164614Sariff 2943171141Sariff ret = 0; 2944171141Sariff 2945164614Sariff while (sc->rirb_rp != rirbwp) { 2946164614Sariff sc->rirb_rp++; 2947164614Sariff sc->rirb_rp %= sc->rirb_size; 2948164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2949164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2950164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2951164614Sariff sc->codecs[cad] == NULL) 2952164614Sariff continue; 2953164614Sariff resp = rirb->response; 2954164614Sariff codec = sc->codecs[cad]; 2955164614Sariff commands = codec->commands; 2956164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2957164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2958164614Sariff ((resp >> 26) & 0xffff); 2959164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2960164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2961164614Sariff codec->responses_received < commands->num_commands) 2962164614Sariff commands->responses[codec->responses_received++] = 2963164614Sariff resp; 2964164614Sariff ret++; 2965164614Sariff } 2966164614Sariff 2967164614Sariff return (ret); 2968164614Sariff} 2969164614Sariff 2970164614Sariffstatic int 2971164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2972164614Sariff{ 2973164614Sariff nid_t cad; 2974164614Sariff uint32_t tag; 2975164614Sariff int ret = 0; 2976164614Sariff 2977164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2978164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2979164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2980164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2981164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2982164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2983164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2984164614Sariff ret++; 2985164614Sariff } 2986164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2987164614Sariff } 2988164614Sariff 2989164614Sariff return (ret); 2990164614Sariff} 2991164614Sariff 2992164614Sariffstatic void 2993164614Sariffhdac_poll_callback(void *arg) 2994164614Sariff{ 2995164614Sariff struct hdac_softc *sc = arg; 2996164614Sariff if (sc == NULL) 2997164614Sariff return; 2998166796Sariff 2999164614Sariff hdac_lock(sc); 3000169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 3001164614Sariff hdac_unlock(sc); 3002164614Sariff return; 3003164614Sariff } 3004171141Sariff if (hdac_rirb_flush(sc) != 0) 3005171141Sariff hdac_unsolq_flush(sc); 3006169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 3007164614Sariff hdac_unlock(sc); 3008164614Sariff} 3009164614Sariff 3010164614Sariffstatic void 3011182999Smavhdac_poll_reinit(struct hdac_softc *sc) 3012182999Smav{ 3013182999Smav int i, pollticks, min = 1000000; 3014182999Smav struct hdac_chan *ch; 3015182999Smav 3016182999Smav for (i = 0; i < sc->num_chans; i++) { 3017182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 3018182999Smav continue; 3019182999Smav ch = &sc->chans[i]; 3020182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 3021193640Sariff ((uint64_t)sndbuf_getalign(ch->b) * sndbuf_getspd(ch->b)); 3022182999Smav pollticks >>= 1; 3023182999Smav if (pollticks > hz) 3024182999Smav pollticks = hz; 3025182999Smav if (pollticks < 1) { 3026182999Smav HDA_BOOTVERBOSE( 3027182999Smav device_printf(sc->dev, 3028182999Smav "%s: pollticks=%d < 1 !\n", 3029182999Smav __func__, pollticks); 3030182999Smav ); 3031182999Smav pollticks = 1; 3032182999Smav } 3033182999Smav if (min > pollticks) 3034182999Smav min = pollticks; 3035182999Smav } 3036182999Smav HDA_BOOTVERBOSE( 3037182999Smav device_printf(sc->dev, 3038182999Smav "%s: pollticks %d -> %d\n", 3039182999Smav __func__, sc->poll_ticks, min); 3040182999Smav ); 3041182999Smav sc->poll_ticks = min; 3042182999Smav if (min == 1000000) 3043182999Smav callout_stop(&sc->poll_hda); 3044182999Smav else 3045182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 3046182999Smav} 3047182999Smav 3048182999Smavstatic void 3049162922Sariffhdac_stream_stop(struct hdac_chan *ch) 3050162922Sariff{ 3051162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3052162922Sariff uint32_t ctl; 3053162922Sariff 3054162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3055162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3056162922Sariff HDAC_SDCTL_RUN); 3057162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3058162922Sariff 3059171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 3060164614Sariff 3061182999Smav if (sc->polling != 0) 3062182999Smav hdac_poll_reinit(sc); 3063164614Sariff 3064182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3065182999Smav ctl &= ~(1 << (ch->off >> 5)); 3066182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3067162922Sariff} 3068162922Sariff 3069162922Sariffstatic void 3070162922Sariffhdac_stream_start(struct hdac_chan *ch) 3071162922Sariff{ 3072162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3073162922Sariff uint32_t ctl; 3074162922Sariff 3075182999Smav ch->flags |= HDAC_CHN_RUNNING; 3076162922Sariff 3077182999Smav if (sc->polling != 0) 3078182999Smav hdac_poll_reinit(sc); 3079182999Smav 3080182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3081182999Smav ctl |= 1 << (ch->off >> 5); 3082182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3083182999Smav 3084182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3085182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3086182999Smav HDAC_SDCTL_RUN; 3087162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3088162922Sariff} 3089162922Sariff 3090162922Sariffstatic void 3091162922Sariffhdac_stream_reset(struct hdac_chan *ch) 3092162922Sariff{ 3093162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3094162922Sariff int timeout = 1000; 3095162922Sariff int to = timeout; 3096162922Sariff uint32_t ctl; 3097162922Sariff 3098162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3099162922Sariff ctl |= HDAC_SDCTL_SRST; 3100162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3101162922Sariff do { 3102162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3103162922Sariff if (ctl & HDAC_SDCTL_SRST) 3104162922Sariff break; 3105162922Sariff DELAY(10); 3106162922Sariff } while (--to); 3107162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 3108162922Sariff device_printf(sc->dev, "timeout in reset\n"); 3109162922Sariff } 3110162922Sariff ctl &= ~HDAC_SDCTL_SRST; 3111162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3112162922Sariff to = timeout; 3113162922Sariff do { 3114162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3115162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 3116162922Sariff break; 3117162922Sariff DELAY(10); 3118162922Sariff } while (--to); 3119163057Sariff if (ctl & HDAC_SDCTL_SRST) 3120162922Sariff device_printf(sc->dev, "can't reset!\n"); 3121162922Sariff} 3122162922Sariff 3123162922Sariffstatic void 3124162922Sariffhdac_stream_setid(struct hdac_chan *ch) 3125162922Sariff{ 3126162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3127162922Sariff uint32_t ctl; 3128162922Sariff 3129162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 3130162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 3131162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 3132162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 3133162922Sariff} 3134162922Sariff 3135162922Sariffstatic void 3136162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 3137162922Sariff{ 3138162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3139164614Sariff struct hdac_bdle *bdle; 3140162922Sariff uint64_t addr; 3141164614Sariff uint32_t blksz, blkcnt; 3142162922Sariff int i; 3143162922Sariff 3144162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 3145164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 3146162922Sariff 3147182999Smav blksz = ch->blksz; 3148182999Smav blkcnt = ch->blkcnt; 3149164614Sariff 3150164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 3151162922Sariff bdle->addrl = (uint32_t)addr; 3152162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 3153164614Sariff bdle->len = blksz; 3154182999Smav bdle->ioc = 1; 3155164614Sariff addr += blksz; 3156162922Sariff } 3157162922Sariff 3158164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 3159164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 3160162922Sariff addr = ch->bdl_dma.dma_paddr; 3161162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 3162162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 3163169277Sariff if (ch->dmapos != NULL && 3164169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 3165169277Sariff addr = sc->pos_dma.dma_paddr; 3166169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 3167169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 3168169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 3169169277Sariff } 3170162922Sariff} 3171162922Sariff 3172162922Sariffstatic int 3173162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 3174162922Sariff{ 3175162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3176162922Sariff int rc; 3177162922Sariff 3178162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 3179162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 3180162922Sariff if (rc) { 3181162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 3182162922Sariff return (rc); 3183162922Sariff } 3184162922Sariff 3185162922Sariff return (0); 3186162922Sariff} 3187162922Sariff 3188162922Sariffstatic void 3189162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 3190162922Sariff int index, int lmute, int rmute, 3191162922Sariff int left, int right, int dir) 3192162922Sariff{ 3193162922Sariff uint16_t v = 0; 3194162922Sariff 3195162922Sariff if (sc == NULL) 3196162922Sariff return; 3197162922Sariff 3198162922Sariff if (left != right || lmute != rmute) { 3199162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 3200162922Sariff (lmute << 7) | left; 3201162922Sariff hdac_command(sc, 3202164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3203162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 3204162922Sariff (rmute << 7) | right; 3205162922Sariff } else 3206162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 3207162922Sariff (lmute << 7) | left; 3208162922Sariff 3209162922Sariff hdac_command(sc, 3210162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3211162922Sariff} 3212162922Sariff 3213162922Sariffstatic void 3214162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3215162922Sariff int left, int right) 3216162922Sariff{ 3217162922Sariff struct hdac_softc *sc; 3218162922Sariff nid_t nid, cad; 3219162922Sariff int lmute, rmute; 3220162922Sariff 3221162922Sariff sc = ctl->widget->devinfo->codec->sc; 3222162922Sariff cad = ctl->widget->devinfo->codec->cad; 3223162922Sariff nid = ctl->widget->nid; 3224162922Sariff 3225182999Smav /* Save new values if valid. */ 3226182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3227182999Smav ctl->muted = mute; 3228182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3229182999Smav ctl->left = left; 3230182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3231182999Smav ctl->right = right; 3232182999Smav /* Prepare effective values */ 3233182999Smav if (ctl->forcemute) { 3234182999Smav lmute = 1; 3235182999Smav rmute = 1; 3236182999Smav left = 0; 3237182999Smav right = 0; 3238182999Smav } else { 3239162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3240162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3241182999Smav left = ctl->left; 3242182999Smav right = ctl->right; 3243162922Sariff } 3244182999Smav /* Apply effective values */ 3245162922Sariff if (ctl->dir & HDA_CTL_OUT) 3246162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3247162922Sariff lmute, rmute, left, right, 0); 3248162922Sariff if (ctl->dir & HDA_CTL_IN) 3249182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3250162922Sariff lmute, rmute, left, right, 1); 3251162922Sariff} 3252162922Sariff 3253162922Sariffstatic void 3254162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3255162922Sariff{ 3256162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3257162922Sariff return; 3258162922Sariff hdac_command(w->devinfo->codec->sc, 3259162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3260162922Sariff w->nid, index), w->devinfo->codec->cad); 3261162922Sariff w->selconn = index; 3262162922Sariff} 3263162922Sariff 3264162922Sariff 3265162922Sariff/**************************************************************************** 3266162922Sariff * uint32_t hdac_command_sendone_internal 3267162922Sariff * 3268162922Sariff * Wrapper function that sends only one command to a given codec 3269162922Sariff ****************************************************************************/ 3270162922Sariffstatic uint32_t 3271162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3272162922Sariff{ 3273162922Sariff struct hdac_command_list cl; 3274162965Sariff uint32_t response = HDAC_INVALID; 3275162922Sariff 3276163057Sariff if (!hdac_lockowned(sc)) 3277162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3278162922Sariff cl.num_commands = 1; 3279162922Sariff cl.verbs = &verb; 3280162922Sariff cl.responses = &response; 3281162922Sariff 3282162922Sariff hdac_command_send_internal(sc, &cl, cad); 3283162922Sariff 3284162922Sariff return (response); 3285162922Sariff} 3286162922Sariff 3287162922Sariff/**************************************************************************** 3288162922Sariff * hdac_command_send_internal 3289162922Sariff * 3290162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3291162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3292162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3293162922Sariff * if any. 3294162922Sariff ****************************************************************************/ 3295162922Sariffstatic void 3296162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3297162922Sariff struct hdac_command_list *commands, nid_t cad) 3298162922Sariff{ 3299162922Sariff struct hdac_codec *codec; 3300162922Sariff int corbrp; 3301162922Sariff uint32_t *corb; 3302162922Sariff int timeout; 3303162922Sariff int retry = 10; 3304164614Sariff struct hdac_rirb *rirb_base; 3305162922Sariff 3306164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3307164614Sariff commands->num_commands < 1) 3308162922Sariff return; 3309162922Sariff 3310162922Sariff codec = sc->codecs[cad]; 3311162922Sariff codec->commands = commands; 3312162922Sariff codec->responses_received = 0; 3313162922Sariff codec->verbs_sent = 0; 3314162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3315162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3316162922Sariff 3317162922Sariff do { 3318162922Sariff if (codec->verbs_sent != commands->num_commands) { 3319162922Sariff /* Queue as many verbs as possible */ 3320162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3321169277Sariff#if 0 3322162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3323162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3324169277Sariff#endif 3325162922Sariff while (codec->verbs_sent != commands->num_commands && 3326162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3327162922Sariff sc->corb_wp++; 3328162922Sariff sc->corb_wp %= sc->corb_size; 3329162922Sariff corb[sc->corb_wp] = 3330162922Sariff commands->verbs[codec->verbs_sent++]; 3331162922Sariff } 3332162922Sariff 3333162922Sariff /* Send the verbs to the codecs */ 3334169277Sariff#if 0 3335162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3336162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3337169277Sariff#endif 3338162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3339162922Sariff } 3340162922Sariff 3341162922Sariff timeout = 1000; 3342164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3343162922Sariff DELAY(10); 3344162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3345164614Sariff codec->responses_received != commands->num_commands) && --retry); 3346162922Sariff 3347162922Sariff if (retry == 0) 3348162922Sariff device_printf(sc->dev, 3349164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3350164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3351164614Sariff codec->responses_received); 3352162922Sariff 3353164614Sariff codec->commands = NULL; 3354164614Sariff codec->responses_received = 0; 3355162922Sariff codec->verbs_sent = 0; 3356162922Sariff 3357164614Sariff hdac_unsolq_flush(sc); 3358162922Sariff} 3359162922Sariff 3360162922Sariff 3361162922Sariff/**************************************************************************** 3362162922Sariff * Device Methods 3363162922Sariff ****************************************************************************/ 3364162922Sariff 3365162922Sariff/**************************************************************************** 3366162922Sariff * int hdac_probe(device_t) 3367162922Sariff * 3368162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3369162922Sariff * match using the subclass of the device. 3370162922Sariff ****************************************************************************/ 3371162922Sariffstatic int 3372162922Sariffhdac_probe(device_t dev) 3373162922Sariff{ 3374162922Sariff int i, result; 3375163257Sariff uint32_t model; 3376163257Sariff uint16_t class, subclass; 3377162922Sariff char desc[64]; 3378162922Sariff 3379162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3380162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3381162922Sariff class = pci_get_class(dev); 3382162922Sariff subclass = pci_get_subclass(dev); 3383162922Sariff 3384162922Sariff bzero(desc, sizeof(desc)); 3385162922Sariff result = ENXIO; 3386162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3387162922Sariff if (hdac_devices[i].model == model) { 3388162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3389162922Sariff result = BUS_PROBE_DEFAULT; 3390162922Sariff break; 3391162922Sariff } 3392163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3393162922Sariff class == PCIC_MULTIMEDIA && 3394162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3395162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3396162922Sariff result = BUS_PROBE_GENERIC; 3397162922Sariff break; 3398162922Sariff } 3399162922Sariff } 3400162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3401162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3402162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3403162922Sariff result = BUS_PROBE_GENERIC; 3404162922Sariff } 3405162922Sariff if (result != ENXIO) { 3406162922Sariff strlcat(desc, " High Definition Audio Controller", 3407162922Sariff sizeof(desc)); 3408162922Sariff device_set_desc_copy(dev, desc); 3409162922Sariff } 3410162922Sariff 3411162922Sariff return (result); 3412162922Sariff} 3413162922Sariff 3414162922Sariffstatic void * 3415162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3416162922Sariff struct pcm_channel *c, int dir) 3417162922Sariff{ 3418182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3419182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3420162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3421162922Sariff struct hdac_chan *ch; 3422182999Smav int i, ord = 0, chid; 3423162922Sariff 3424162922Sariff hdac_lock(sc); 3425182999Smav 3426182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3427182999Smav ch = &sc->chans[chid]; 3428182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3429182999Smav if (ch->dir == sc->chans[i].dir) 3430182999Smav ord++; 3431182999Smav } 3432162922Sariff if (dir == PCMDIR_PLAY) { 3433182999Smav ch->off = (sc->num_iss + ord) << 5; 3434162922Sariff } else { 3435182999Smav ch->off = ord << 5; 3436162922Sariff } 3437182999Smav 3438162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3439162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3440162922Sariff ch->pcmrates[0] = 48000; 3441162922Sariff ch->pcmrates[1] = 0; 3442162922Sariff } 3443169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3444169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3445169277Sariff (sc->streamcnt * 8)); 3446169277Sariff else 3447169277Sariff ch->dmapos = NULL; 3448169277Sariff ch->sid = ++sc->streamcnt; 3449169277Sariff ch->dir = dir; 3450162922Sariff ch->b = b; 3451162922Sariff ch->c = c; 3452182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3453182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3454162922Sariff hdac_unlock(sc); 3455162922Sariff 3456162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3457162922Sariff ch->blkcnt = 0; 3458162922Sariff return (NULL); 3459162922Sariff } 3460162922Sariff 3461169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3462171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3463182999Smav pdevinfo->chan_size) != 0) 3464162922Sariff return (NULL); 3465162922Sariff 3466162922Sariff return (ch); 3467162922Sariff} 3468162922Sariff 3469162922Sariffstatic int 3470162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3471162922Sariff{ 3472162922Sariff struct hdac_chan *ch = data; 3473162922Sariff int i; 3474162922Sariff 3475162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3476162922Sariff if (format == ch->caps.fmtlist[i]) { 3477162922Sariff ch->fmt = format; 3478162922Sariff return (0); 3479162922Sariff } 3480162922Sariff } 3481162922Sariff 3482162922Sariff return (EINVAL); 3483162922Sariff} 3484162922Sariff 3485193640Sariffstatic uint32_t 3486162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3487162922Sariff{ 3488162922Sariff struct hdac_chan *ch = data; 3489164614Sariff uint32_t spd = 0, threshold; 3490162922Sariff int i; 3491162922Sariff 3492162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3493162922Sariff spd = ch->pcmrates[i]; 3494164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3495164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3496164614Sariff if (speed < threshold) 3497162922Sariff break; 3498162922Sariff } 3499162922Sariff 3500164614Sariff if (spd == 0) /* impossible */ 3501162922Sariff ch->spd = 48000; 3502162922Sariff else 3503162922Sariff ch->spd = spd; 3504162922Sariff 3505162922Sariff return (ch->spd); 3506162922Sariff} 3507162922Sariff 3508162922Sariffstatic void 3509162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3510162922Sariff{ 3511162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3512182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3513173817Sariff struct hdac_widget *w; 3514182999Smav int i, chn, totalchn, c; 3515162922Sariff nid_t cad = ch->devinfo->codec->cad; 3516182999Smav uint16_t fmt, dfmt; 3517202127Smav uint16_t chmap[2][5] = {{ 0x0010, 0x0001, 0x0201, 0x0231, 0x0231 }, /* 5.1 */ 3518202127Smav { 0x0010, 0x0001, 0x2001, 0x2031, 0x2431 }};/* 7.1 */ 3519202127Smav int map = -1; 3520162922Sariff 3521202127Smav totalchn = AFMT_CHANNEL(ch->fmt); 3522183097Smav HDA_BOOTHVERBOSE( 3523182999Smav device_printf(ch->pdevinfo->dev, 3524182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3525182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3526182999Smav ch->fmt, ch->spd); 3527182999Smav ); 3528162922Sariff fmt = 0; 3529162922Sariff if (ch->fmt & AFMT_S16_LE) 3530162922Sariff fmt |= ch->bit16 << 4; 3531162922Sariff else if (ch->fmt & AFMT_S32_LE) 3532162922Sariff fmt |= ch->bit32 << 4; 3533162922Sariff else 3534162922Sariff fmt |= 1 << 4; 3535162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3536162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3537162922Sariff fmt |= hda_rate_tab[i].base; 3538162922Sariff fmt |= hda_rate_tab[i].mul; 3539162922Sariff fmt |= hda_rate_tab[i].div; 3540162922Sariff break; 3541162922Sariff } 3542162922Sariff } 3543202127Smav fmt |= (totalchn - 1); 3544162922Sariff 3545202127Smav /* Set channel mapping for known speaker setups. */ 3546202127Smav if (as->pinset == 0x0007 || as->pinset == 0x0013) /* Standard 5.1 */ 3547202127Smav map = 0; 3548202127Smav else if (as->pinset == 0x0017) /* Standard 7.1 */ 3549202127Smav map = 1; 3550162922Sariff 3551162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3552182999Smav 3553182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3554182999Smav if (ch->fmt & AFMT_AC3) 3555182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3556162922Sariff 3557173817Sariff chn = 0; 3558162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3559173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3560173817Sariff if (w == NULL) 3561173817Sariff continue; 3562182999Smav 3563202127Smav /* If HP redirection is enabled, but failed to use same 3564202127Smav DAC, make last DAC to duplicate first one. */ 3565204351Smav if (as->fakeredir && i == (as->pincnt - 1)) { 3566202127Smav c = (ch->sid << 4); 3567202127Smav } else { 3568202127Smav if (map >= 0) /* Map known speaker setups. */ 3569202127Smav chn = (((chmap[map][totalchn / 2] >> i * 4) & 3570202127Smav 0xf) - 1) * 2; 3571202127Smav if (chn < 0 || chn >= totalchn) { 3572202127Smav c = 0; 3573202127Smav } else { 3574202127Smav c = (ch->sid << 4) | chn; 3575202127Smav } 3576202127Smav } 3577183097Smav HDA_BOOTHVERBOSE( 3578182999Smav device_printf(ch->pdevinfo->dev, 3579182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3580202127Smav "fmt=0x%04x, dfmt=0x%04x, chan=0x%04x\n", 3581162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3582202127Smav ch->io[i], fmt, dfmt, c); 3583162922Sariff ); 3584162922Sariff hdac_command(sc, 3585162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3586182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3587174025Sariff hdac_command(sc, 3588182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3589174025Sariff cad); 3590182999Smav } 3591182999Smav hdac_command(sc, 3592182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3593197611Smav#if 0 3594197611Smav hdac_command(sc, 3595197611Smav HDA_CMD_SET_CONV_CHAN_COUNT(cad, ch->io[i], 1), cad); 3596197611Smav hdac_command(sc, 3597197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x00), cad); 3598197611Smav hdac_command(sc, 3599197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x11), cad); 3600197611Smav#endif 3601202127Smav chn += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 3602162922Sariff } 3603162922Sariff} 3604162922Sariff 3605202156Smav/* 3606202156Smav * Greatest Common Divisor. 3607202156Smav */ 3608202156Smavstatic unsigned 3609202156Smavgcd(unsigned a, unsigned b) 3610202156Smav{ 3611202156Smav u_int c; 3612202156Smav 3613202156Smav while (b != 0) { 3614202156Smav c = a; 3615202156Smav a = b; 3616202156Smav b = (c % b); 3617202156Smav } 3618202156Smav return (a); 3619202156Smav} 3620202156Smav 3621202156Smav/* 3622202156Smav * Least Common Multiple. 3623202156Smav */ 3624202156Smavstatic unsigned 3625202156Smavlcm(unsigned a, unsigned b) 3626202156Smav{ 3627202156Smav 3628202156Smav return ((a * b) / gcd(a, b)); 3629202156Smav} 3630202156Smav 3631162922Sariffstatic int 3632167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3633167648Sariff uint32_t blksz, uint32_t blkcnt) 3634162922Sariff{ 3635162922Sariff struct hdac_chan *ch = data; 3636164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3637162922Sariff 3638202156Smav blksz -= blksz % lcm(HDAC_DMA_ALIGNMENT, sndbuf_getalign(ch->b)); 3639162922Sariff 3640167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3641167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3642167648Sariff if (blksz < HDA_BLK_MIN) 3643167648Sariff blksz = HDA_BLK_MIN; 3644167648Sariff if (blkcnt > HDA_BDL_MAX) 3645167648Sariff blkcnt = HDA_BDL_MAX; 3646167648Sariff if (blkcnt < HDA_BDL_MIN) 3647167648Sariff blkcnt = HDA_BDL_MIN; 3648164614Sariff 3649167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3650167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3651167648Sariff blkcnt >>= 1; 3652167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3653167648Sariff blksz >>= 1; 3654167648Sariff else 3655167648Sariff break; 3656167648Sariff } 3657167648Sariff 3658164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3659167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3660167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3661164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3662167648Sariff __func__, blksz, blkcnt); 3663164614Sariff 3664164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3665167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3666164614Sariff 3667193640Sariff return (0); 3668167648Sariff} 3669167648Sariff 3670193640Sariffstatic uint32_t 3671167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3672167648Sariff{ 3673167648Sariff struct hdac_chan *ch = data; 3674167648Sariff 3675182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3676167648Sariff 3677162922Sariff return (ch->blksz); 3678162922Sariff} 3679162922Sariff 3680162922Sariffstatic void 3681162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3682162922Sariff{ 3683162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3684182999Smav struct hdac_widget *w; 3685162922Sariff nid_t cad = devinfo->codec->cad; 3686162922Sariff int i; 3687162922Sariff 3688162922Sariff hdac_stream_stop(ch); 3689162922Sariff 3690162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3691182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3692182999Smav if (w == NULL) 3693182999Smav continue; 3694182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3695182999Smav hdac_command(sc, 3696182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3697182999Smav cad); 3698182999Smav } 3699162922Sariff hdac_command(sc, 3700162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3701162922Sariff 0), cad); 3702162922Sariff } 3703162922Sariff} 3704162922Sariff 3705162922Sariffstatic void 3706162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3707162922Sariff{ 3708162922Sariff ch->ptr = 0; 3709162922Sariff ch->prevptr = 0; 3710162922Sariff hdac_stream_stop(ch); 3711162922Sariff hdac_stream_reset(ch); 3712162922Sariff hdac_bdl_setup(ch); 3713162922Sariff hdac_stream_setid(ch); 3714162922Sariff hdac_stream_setup(ch); 3715162922Sariff hdac_stream_start(ch); 3716162922Sariff} 3717162922Sariff 3718162922Sariffstatic int 3719162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3720162922Sariff{ 3721162922Sariff struct hdac_chan *ch = data; 3722162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3723162922Sariff 3724170521Sariff if (!PCMTRIG_COMMON(go)) 3725170521Sariff return (0); 3726170521Sariff 3727162922Sariff hdac_lock(sc); 3728162922Sariff switch (go) { 3729162922Sariff case PCMTRIG_START: 3730162922Sariff hdac_channel_start(sc, ch); 3731162922Sariff break; 3732162922Sariff case PCMTRIG_STOP: 3733162922Sariff case PCMTRIG_ABORT: 3734162922Sariff hdac_channel_stop(sc, ch); 3735162922Sariff break; 3736167610Sariff default: 3737167610Sariff break; 3738162922Sariff } 3739162922Sariff hdac_unlock(sc); 3740162922Sariff 3741162922Sariff return (0); 3742162922Sariff} 3743162922Sariff 3744193640Sariffstatic uint32_t 3745162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3746162922Sariff{ 3747162922Sariff struct hdac_chan *ch = data; 3748162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3749162922Sariff uint32_t ptr; 3750162922Sariff 3751162922Sariff hdac_lock(sc); 3752164614Sariff if (sc->polling != 0) 3753164614Sariff ptr = ch->ptr; 3754169277Sariff else if (ch->dmapos != NULL) 3755169277Sariff ptr = *(ch->dmapos); 3756164614Sariff else 3757164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3758162922Sariff hdac_unlock(sc); 3759162922Sariff 3760164614Sariff /* 3761164614Sariff * Round to available space and force 128 bytes aligment. 3762164614Sariff */ 3763164614Sariff ptr %= ch->blksz * ch->blkcnt; 3764167648Sariff ptr &= HDA_BLK_ALIGN; 3765162922Sariff 3766162922Sariff return (ptr); 3767162922Sariff} 3768162922Sariff 3769162922Sariffstatic struct pcmchan_caps * 3770162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3771162922Sariff{ 3772162922Sariff return (&((struct hdac_chan *)data)->caps); 3773162922Sariff} 3774162922Sariff 3775162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3776162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3777162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3778162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3779162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3780167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3781162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3782162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3783162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3784193640Sariff KOBJMETHOD_END 3785162922Sariff}; 3786162922SariffCHANNEL_DECLARE(hdac_channel); 3787162922Sariff 3788162922Sariffstatic int 3789162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3790162922Sariff{ 3791182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3792182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3793162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3794162922Sariff struct hdac_widget *w, *cw; 3795162922Sariff struct hdac_audio_ctl *ctl; 3796162922Sariff uint32_t mask, recmask, id; 3797162922Sariff int i, j, softpcmvol; 3798162922Sariff 3799162922Sariff hdac_lock(sc); 3800162922Sariff 3801182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3802182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3803182999Smav pdevinfo->left[i] = 100; 3804182999Smav pdevinfo->right[i] = 100; 3805182999Smav } 3806182999Smav 3807162922Sariff mask = 0; 3808162922Sariff recmask = 0; 3809182999Smav id = hdac_codec_id(devinfo->codec); 3810162922Sariff 3811182999Smav /* Declate EAPD as ogain control. */ 3812182999Smav if (pdevinfo->play >= 0) { 3813182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3814182999Smav w = hdac_widget_get(devinfo, i); 3815182999Smav if (w == NULL || w->enable == 0) 3816182999Smav continue; 3817182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3818182999Smav w->param.eapdbtl == HDAC_INVALID || 3819182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3820182999Smav continue; 3821182999Smav mask |= SOUND_MASK_OGAIN; 3822162922Sariff break; 3823162922Sariff } 3824162922Sariff } 3825162922Sariff 3826182999Smav /* Declare volume controls assigned to this association. */ 3827162922Sariff i = 0; 3828162922Sariff ctl = NULL; 3829162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3830182999Smav if (ctl->enable == 0) 3831162922Sariff continue; 3832182999Smav if ((pdevinfo->play >= 0 && 3833182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3834182999Smav (pdevinfo->rec >= 0 && 3835182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3836182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3837182999Smav mask |= ctl->ossmask; 3838162922Sariff } 3839162922Sariff 3840182999Smav /* Declare record sources available to this association. */ 3841182999Smav if (pdevinfo->rec >= 0) { 3842182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3843182999Smav for (i = 0; ch->io[i] != -1; i++) { 3844182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3845182999Smav if (w == NULL || w->enable == 0) 3846182999Smav continue; 3847182999Smav for (j = 0; j < w->nconns; j++) { 3848182999Smav if (w->connsenable[j] == 0) 3849162922Sariff continue; 3850182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3851182999Smav if (cw == NULL || cw->enable == 0) 3852165992Sariff continue; 3853182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3854182999Smav cw->bindas != -2) 3855165992Sariff continue; 3856182999Smav recmask |= cw->ossmask; 3857165992Sariff } 3858182999Smav } 3859182999Smav } 3860182999Smav 3861185230Smav /* Declare soft PCM volume if needed. */ 3862193640Sariff if (pdevinfo->play >= 0) { 3863182999Smav ctl = NULL; 3864182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3865182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3866182999Smav softpcmvol = 1; 3867182999Smav mask |= SOUND_MASK_PCM; 3868162922Sariff } else { 3869182999Smav softpcmvol = 0; 3870182999Smav i = 0; 3871182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3872182999Smav if (ctl->enable == 0) 3873162922Sariff continue; 3874182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3875182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3876162922Sariff continue; 3877182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3878182999Smav continue; 3879182999Smav if (ctl->step > 0) 3880182999Smav break; 3881162922Sariff } 3882162922Sariff } 3883182999Smav 3884182999Smav if (softpcmvol == 1 || ctl == NULL) { 3885182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3886182999Smav HDA_BOOTVERBOSE( 3887182999Smav device_printf(pdevinfo->dev, 3888182999Smav "%s Soft PCM volume\n", 3889182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3890182999Smav ); 3891182999Smav } 3892185230Smav } 3893182999Smav 3894185230Smav /* Declare master volume if needed. */ 3895185230Smav if (pdevinfo->play >= 0) { 3896185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3897185230Smav SOUND_MASK_PCM) { 3898182999Smav mask |= SOUND_MASK_VOLUME; 3899182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3900182999Smav SOUND_MASK_PCM); 3901182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3902182999Smav SOUND_MIXER_NONE); 3903182999Smav HDA_BOOTVERBOSE( 3904182999Smav device_printf(pdevinfo->dev, 3905182999Smav "Forcing master volume with PCM\n"); 3906182999Smav ); 3907182999Smav } 3908162922Sariff } 3909162922Sariff 3910169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3911169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3912162922Sariff 3913162922Sariff mix_setrecdevs(m, recmask); 3914162922Sariff mix_setdevs(m, mask); 3915162922Sariff 3916162922Sariff hdac_unlock(sc); 3917162922Sariff 3918162922Sariff return (0); 3919162922Sariff} 3920162922Sariff 3921162922Sariffstatic int 3922162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3923162922Sariff unsigned left, unsigned right) 3924162922Sariff{ 3925182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3926182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3927162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3928162922Sariff struct hdac_widget *w; 3929162922Sariff struct hdac_audio_ctl *ctl; 3930182999Smav uint32_t mute; 3931182999Smav int lvol, rvol; 3932182999Smav int i, j; 3933162922Sariff 3934162922Sariff hdac_lock(sc); 3935182999Smav /* Save new values. */ 3936182999Smav pdevinfo->left[dev] = left; 3937182999Smav pdevinfo->right[dev] = right; 3938182999Smav 3939182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3940162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3941163257Sariff uint32_t orig; 3942182999Smav w = NULL; 3943182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3944182999Smav w = hdac_widget_get(devinfo, i); 3945182999Smav if (w == NULL || w->enable == 0) 3946182999Smav continue; 3947182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3948182999Smav w->param.eapdbtl == HDAC_INVALID) 3949182999Smav continue; 3950182999Smav break; 3951162922Sariff } 3952182999Smav if (i >= devinfo->endnode) { 3953162922Sariff hdac_unlock(sc); 3954162922Sariff return (-1); 3955162922Sariff } 3956163257Sariff orig = w->param.eapdbtl; 3957163432Sariff if (left == 0) 3958162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3959162922Sariff else 3960162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3961163257Sariff if (orig != w->param.eapdbtl) { 3962163432Sariff uint32_t val; 3963163432Sariff 3964163432Sariff val = w->param.eapdbtl; 3965163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3966163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3967163257Sariff hdac_command(sc, 3968163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3969163432Sariff w->nid, val), devinfo->codec->cad); 3970163257Sariff } 3971162922Sariff hdac_unlock(sc); 3972162922Sariff return (left | (left << 8)); 3973162922Sariff } 3974162922Sariff 3975182999Smav /* Recalculate all controls related to this OSS device. */ 3976162922Sariff i = 0; 3977162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3978182999Smav if (ctl->enable == 0 || 3979162922Sariff !(ctl->ossmask & (1 << dev))) 3980162922Sariff continue; 3981182999Smav if (!((pdevinfo->play >= 0 && 3982182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3983182999Smav (pdevinfo->rec >= 0 && 3984182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3985182999Smav ctl->widget->bindas == -2)) 3986182999Smav continue; 3987182999Smav 3988182999Smav lvol = 100; 3989182999Smav rvol = 100; 3990182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3991182999Smav if (ctl->ossmask & (1 << j)) { 3992182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3993182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3994162922Sariff } 3995162922Sariff } 3996202789Smav mute = (lvol == 0) ? HDA_AMP_MUTE_LEFT : 0; 3997202789Smav mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3998182999Smav lvol = (lvol * ctl->step + 50) / 100; 3999182999Smav rvol = (rvol * ctl->step + 50) / 100; 4000162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 4001162922Sariff } 4002162922Sariff hdac_unlock(sc); 4003162922Sariff 4004162922Sariff return (left | (right << 8)); 4005162922Sariff} 4006162922Sariff 4007182999Smav/* 4008182999Smav * Commutate specified record source. 4009182999Smav */ 4010182999Smavstatic uint32_t 4011182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 4012162922Sariff{ 4013182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 4014162922Sariff struct hdac_widget *w, *cw; 4015182999Smav struct hdac_audio_ctl *ctl; 4016182999Smav char buf[64]; 4017182999Smav int i, muted; 4018182999Smav uint32_t res = 0; 4019162922Sariff 4020182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4021182999Smav return (0); 4022182999Smav 4023182999Smav w = hdac_widget_get(devinfo, nid); 4024182999Smav if (w == NULL || w->enable == 0) 4025182999Smav return (0); 4026182999Smav 4027182999Smav for (i = 0; i < w->nconns; i++) { 4028182999Smav if (w->connsenable[i] == 0) 4029182999Smav continue; 4030182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 4031182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 4032182999Smav continue; 4033182999Smav /* Call recursively to trace signal to it's source if needed. */ 4034182999Smav if ((src & cw->ossmask) != 0) { 4035182999Smav if (cw->ossdev < 0) { 4036182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 4037182999Smav w->conns[i], depth + 1); 4038182999Smav } else { 4039182999Smav res |= cw->ossmask; 4040182999Smav } 4041182999Smav } 4042182999Smav /* We have two special cases: mixers and others (selectors). */ 4043182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 4044182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 4045182999Smav w->nid, HDA_CTL_IN, i, 1); 4046182999Smav if (ctl == NULL) 4047182999Smav continue; 4048182999Smav /* If we have input control on this node mute them 4049182999Smav * according to requested sources. */ 4050182999Smav muted = (src & cw->ossmask) ? 0 : 1; 4051182999Smav if (muted != ctl->forcemute) { 4052182999Smav ctl->forcemute = muted; 4053182999Smav hdac_audio_ctl_amp_set(ctl, 4054182999Smav HDA_AMP_MUTE_DEFAULT, 4055182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 4056182999Smav } 4057183097Smav HDA_BOOTHVERBOSE( 4058182999Smav device_printf(pdevinfo->dev, 4059182999Smav "Recsel (%s): nid %d source %d %s\n", 4060182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4061182999Smav src, buf, sizeof(buf)), 4062182999Smav nid, i, muted?"mute":"unmute"); 4063182999Smav ); 4064182999Smav } else { 4065182999Smav if (w->nconns == 1) 4066182999Smav break; 4067182999Smav if ((src & cw->ossmask) == 0) 4068182999Smav continue; 4069182999Smav /* If we found requested source - select it and exit. */ 4070182999Smav hdac_widget_connection_select(w, i); 4071183097Smav HDA_BOOTHVERBOSE( 4072182999Smav device_printf(pdevinfo->dev, 4073182999Smav "Recsel (%s): nid %d source %d select\n", 4074182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4075182999Smav src, buf, sizeof(buf)), 4076182999Smav nid, i); 4077182999Smav ); 4078162922Sariff break; 4079162922Sariff } 4080162922Sariff } 4081182999Smav return (res); 4082182999Smav} 4083162922Sariff 4084182999Smavstatic uint32_t 4085182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 4086182999Smav{ 4087182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 4088182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 4089182999Smav struct hdac_widget *w; 4090182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4091182999Smav struct hdac_chan *ch; 4092182999Smav int i; 4093182999Smav uint32_t ret = 0xffffffff; 4094182999Smav 4095162922Sariff hdac_lock(sc); 4096162922Sariff 4097182999Smav /* Commutate requested recsrc for each ADC. */ 4098182999Smav ch = &sc->chans[pdevinfo->rec]; 4099182999Smav for (i = 0; ch->io[i] != -1; i++) { 4100182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 4101162965Sariff if (w == NULL || w->enable == 0) 4102162922Sariff continue; 4103182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 4104162922Sariff } 4105162922Sariff 4106162922Sariff hdac_unlock(sc); 4107162922Sariff 4108182999Smav return ((ret == 0xffffffff)? 0 : ret); 4109162922Sariff} 4110162922Sariff 4111162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 4112162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 4113162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 4114162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 4115193640Sariff KOBJMETHOD_END 4116162922Sariff}; 4117162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 4118162922Sariff 4119171141Sariffstatic void 4120171141Sariffhdac_unsolq_task(void *context, int pending) 4121171141Sariff{ 4122171141Sariff struct hdac_softc *sc; 4123171141Sariff 4124171141Sariff sc = (struct hdac_softc *)context; 4125171141Sariff 4126171141Sariff hdac_lock(sc); 4127171141Sariff hdac_unsolq_flush(sc); 4128171141Sariff hdac_unlock(sc); 4129171141Sariff} 4130171141Sariff 4131162922Sariff/**************************************************************************** 4132162922Sariff * int hdac_attach(device_t) 4133162922Sariff * 4134162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 4135162922Sariff * when this function is called. Setup everything that doesn't require 4136162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 4137162922Sariff ****************************************************************************/ 4138162922Sariffstatic int 4139162922Sariffhdac_attach(device_t dev) 4140162922Sariff{ 4141162922Sariff struct hdac_softc *sc; 4142162922Sariff int result; 4143189086Smav int i, devid = -1; 4144189086Smav uint32_t model; 4145189086Smav uint16_t class, subclass; 4146169277Sariff uint16_t vendor; 4147169277Sariff uint8_t v; 4148162922Sariff 4149223118Sjoel HDA_BOOTVERBOSE( 4150223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 4151223118Sjoel HDA_DRV_TEST_REV); 4152223118Sjoel ); 4153182999Smav 4154189086Smav model = (uint32_t)pci_get_device(dev) << 16; 4155189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 4156189086Smav class = pci_get_class(dev); 4157189086Smav subclass = pci_get_subclass(dev); 4158189086Smav 4159189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 4160189086Smav if (hdac_devices[i].model == model) { 4161189086Smav devid = i; 4162189086Smav break; 4163189086Smav } 4164189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 4165189086Smav class == PCIC_MULTIMEDIA && 4166189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 4167189086Smav devid = i; 4168189086Smav break; 4169189086Smav } 4170189086Smav } 4171189086Smav 4172182999Smav sc = device_get_softc(dev); 4173163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 4174162922Sariff sc->dev = dev; 4175163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 4176163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 4177169277Sariff vendor = pci_get_vendor(dev); 4178162922Sariff 4179165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 4180165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 4181165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 4182165281Sariff } 4183165281Sariff 4184164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 4185164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 4186169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 4187164614Sariff 4188171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 4189171141Sariff 4190182999Smav sc->poll_ticks = 1000000; 4191169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 4192169277Sariff if (resource_int_value(device_get_name(dev), 4193169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 4194164614Sariff sc->polling = 1; 4195164614Sariff else 4196164614Sariff sc->polling = 0; 4197164614Sariff 4198162922Sariff sc->hdabus = NULL; 4199162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 4200162922Sariff sc->codecs[i] = NULL; 4201162922Sariff 4202162922Sariff pci_enable_busmaster(dev); 4203162922Sariff 4204169277Sariff if (vendor == INTEL_VENDORID) { 4205169277Sariff /* TCSEL -> TC0 */ 4206169277Sariff v = pci_read_config(dev, 0x44, 1); 4207169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 4208183097Smav HDA_BOOTHVERBOSE( 4209169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 4210169277Sariff pci_read_config(dev, 0x44, 1)); 4211169277Sariff ); 4212169277Sariff } 4213169277Sariff 4214189127Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_MSI)) 4215188656Smav sc->flags &= ~HDAC_F_MSI; 4216188656Smav else 4217171330Sariff sc->flags |= HDAC_F_MSI; 4218189086Smav if (resource_int_value(device_get_name(dev), 4219189086Smav device_get_unit(dev), "msi", &i) == 0) { 4220189086Smav if (i == 0) 4221189086Smav sc->flags &= ~HDAC_F_MSI; 4222189086Smav else 4223189086Smav sc->flags |= HDAC_F_MSI; 4224189086Smav } 4225171330Sariff 4226169277Sariff#if defined(__i386__) || defined(__amd64__) 4227171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4228169277Sariff 4229169277Sariff if (resource_int_value(device_get_name(dev), 4230169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 4231169277Sariff#else 4232171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4233169277Sariff#endif 4234169277Sariff /* 4235169277Sariff * Try to enable PCIe snoop to avoid messing around with 4236169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 4237169277Sariff * config is pretty much vendor specific, there are no 4238169277Sariff * general solutions on how to enable it, forcing us (even 4239169277Sariff * Microsoft) to enable uncacheable or write combined DMA 4240169277Sariff * by default. 4241169277Sariff * 4242169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 4243169277Sariff */ 4244169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 4245169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 4246169277Sariff continue; 4247171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4248169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4249169277Sariff break; 4250169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4251169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4252169277Sariff hdac_pcie_snoop[i].enable) 4253169277Sariff break; 4254169277Sariff v &= hdac_pcie_snoop[i].mask; 4255169277Sariff v |= hdac_pcie_snoop[i].enable; 4256169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4257169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4258169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4259169277Sariff hdac_pcie_snoop[i].enable) { 4260169277Sariff HDA_BOOTVERBOSE( 4261169277Sariff device_printf(dev, 4262169277Sariff "WARNING: Failed to enable PCIe " 4263169277Sariff "snoop!\n"); 4264169277Sariff ); 4265169277Sariff#if defined(__i386__) || defined(__amd64__) 4266171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4267169277Sariff#endif 4268169277Sariff } 4269169277Sariff break; 4270169277Sariff } 4271169277Sariff#if defined(__i386__) || defined(__amd64__) 4272169277Sariff } 4273169277Sariff#endif 4274169277Sariff 4275183097Smav HDA_BOOTHVERBOSE( 4276169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4277171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4278171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4279169277Sariff ); 4280169277Sariff 4281162922Sariff /* Allocate resources */ 4282162922Sariff result = hdac_mem_alloc(sc); 4283162922Sariff if (result != 0) 4284163057Sariff goto hdac_attach_fail; 4285162922Sariff result = hdac_irq_alloc(sc); 4286162922Sariff if (result != 0) 4287163057Sariff goto hdac_attach_fail; 4288162922Sariff 4289162922Sariff /* Get Capabilities */ 4290162922Sariff result = hdac_get_capabilities(sc); 4291162922Sariff if (result != 0) 4292163057Sariff goto hdac_attach_fail; 4293162922Sariff 4294194861Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_64BIT)) 4295194861Smav sc->support_64bit = 0; 4296194861Smav 4297162922Sariff /* Allocate CORB and RIRB dma memory */ 4298162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4299162922Sariff sc->corb_size * sizeof(uint32_t)); 4300162922Sariff if (result != 0) 4301163057Sariff goto hdac_attach_fail; 4302162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4303162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4304162922Sariff if (result != 0) 4305163057Sariff goto hdac_attach_fail; 4306162922Sariff 4307194861Smav result = bus_dma_tag_create( 4308194861Smav bus_get_dma_tag(sc->dev), /* parent */ 4309194861Smav HDAC_DMA_ALIGNMENT, /* alignment */ 4310194861Smav 0, /* boundary */ 4311194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 4312194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 4313194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 4314194861Smav NULL, /* filtfunc */ 4315194861Smav NULL, /* fistfuncarg */ 4316194861Smav HDA_BUFSZ_MAX, /* maxsize */ 4317194861Smav 1, /* nsegments */ 4318194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 4319194861Smav 0, /* flags */ 4320194861Smav NULL, /* lockfunc */ 4321194861Smav NULL, /* lockfuncarg */ 4322194861Smav &sc->chan_dmat); /* dmat */ 4323194861Smav if (result != 0) { 4324194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 4325194861Smav __func__, result); 4326194861Smav goto hdac_attach_fail; 4327194861Smav } 4328194861Smav 4329162922Sariff /* Quiesce everything */ 4330183097Smav HDA_BOOTHVERBOSE( 4331182999Smav device_printf(dev, "Reset controller...\n"); 4332182999Smav ); 4333182999Smav hdac_reset(sc, 1); 4334162922Sariff 4335162922Sariff /* Initialize the CORB and RIRB */ 4336162922Sariff hdac_corb_init(sc); 4337162922Sariff hdac_rirb_init(sc); 4338162922Sariff 4339162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4340162922Sariff sc->intrhook.ich_func = hdac_attach2; 4341162922Sariff sc->intrhook.ich_arg = (void *)sc; 4342162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4343162922Sariff sc->intrhook.ich_func = NULL; 4344162922Sariff hdac_attach2((void *)sc); 4345162922Sariff } 4346162922Sariff 4347163057Sariff return (0); 4348162922Sariff 4349163057Sariffhdac_attach_fail: 4350162922Sariff hdac_irq_free(sc); 4351169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4352169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4353162922Sariff hdac_mem_free(sc); 4354162922Sariff snd_mtxfree(sc->lock); 4355162922Sariff 4356163057Sariff return (ENXIO); 4357162922Sariff} 4358162922Sariff 4359162922Sariffstatic void 4360162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4361162922Sariff{ 4362182999Smav struct hdac_codec *codec = devinfo->codec; 4363182999Smav struct hdac_softc *sc = codec->sc; 4364162922Sariff struct hdac_widget *w; 4365162922Sariff uint32_t res; 4366162922Sariff int i; 4367162922Sariff nid_t cad, nid; 4368162922Sariff 4369162922Sariff cad = devinfo->codec->cad; 4370162922Sariff nid = devinfo->nid; 4371162922Sariff 4372162922Sariff res = hdac_command(sc, 4373169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4374169277Sariff devinfo->function.audio.gpio = res; 4375169277Sariff 4376163057Sariff HDA_BOOTVERBOSE( 4377183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4378183097Smav "NumGPIO=%d NumGPO=%d " 4379169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4380183097Smav devinfo->function.audio.gpio, 4381169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4382169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4383169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4384169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4385169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4386162922Sariff ); 4387162922Sariff 4388162922Sariff res = hdac_command(sc, 4389162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4390162922Sariff cad); 4391162922Sariff devinfo->function.audio.supp_stream_formats = res; 4392162922Sariff 4393162922Sariff res = hdac_command(sc, 4394162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4395162922Sariff cad); 4396162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4397162922Sariff 4398162922Sariff res = hdac_command(sc, 4399162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4400162922Sariff cad); 4401162922Sariff devinfo->function.audio.outamp_cap = res; 4402162922Sariff 4403162922Sariff res = hdac_command(sc, 4404162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4405162922Sariff cad); 4406162922Sariff devinfo->function.audio.inamp_cap = res; 4407162922Sariff 4408162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4409162922Sariff w = hdac_widget_get(devinfo, i); 4410162922Sariff if (w == NULL) 4411162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4412162922Sariff else { 4413162922Sariff w->devinfo = devinfo; 4414162922Sariff w->nid = i; 4415162922Sariff w->enable = 1; 4416162922Sariff w->selconn = -1; 4417162922Sariff w->pflags = 0; 4418182999Smav w->ossdev = -1; 4419182999Smav w->bindas = -1; 4420162965Sariff w->param.eapdbtl = HDAC_INVALID; 4421162922Sariff hdac_widget_parse(w); 4422162922Sariff } 4423162922Sariff } 4424162922Sariff} 4425162922Sariff 4426162922Sariffstatic void 4427162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4428162922Sariff{ 4429162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4430162922Sariff struct hdac_audio_ctl *ctls; 4431162922Sariff struct hdac_widget *w, *cw; 4432162922Sariff int i, j, cnt, max, ocap, icap; 4433163057Sariff int mute, offset, step, size; 4434162922Sariff 4435162922Sariff /* XXX This is redundant */ 4436162922Sariff max = 0; 4437162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4438162922Sariff w = hdac_widget_get(devinfo, i); 4439162922Sariff if (w == NULL || w->enable == 0) 4440162922Sariff continue; 4441162922Sariff if (w->param.outamp_cap != 0) 4442162922Sariff max++; 4443162922Sariff if (w->param.inamp_cap != 0) { 4444162922Sariff switch (w->type) { 4445162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4446162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4447162922Sariff for (j = 0; j < w->nconns; j++) { 4448162922Sariff cw = hdac_widget_get(devinfo, 4449162922Sariff w->conns[j]); 4450162922Sariff if (cw == NULL || cw->enable == 0) 4451162922Sariff continue; 4452162922Sariff max++; 4453162922Sariff } 4454162922Sariff break; 4455162922Sariff default: 4456162922Sariff max++; 4457162922Sariff break; 4458162922Sariff } 4459162922Sariff } 4460162922Sariff } 4461162922Sariff 4462162922Sariff devinfo->function.audio.ctlcnt = max; 4463162922Sariff 4464162922Sariff if (max < 1) 4465162922Sariff return; 4466162922Sariff 4467162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4468162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4469162922Sariff 4470162922Sariff if (ctls == NULL) { 4471162922Sariff /* Blekh! */ 4472162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4473162922Sariff devinfo->function.audio.ctlcnt = 0; 4474162922Sariff return; 4475162922Sariff } 4476162922Sariff 4477162922Sariff cnt = 0; 4478162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4479162922Sariff if (cnt >= max) { 4480162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4481162922Sariff __func__); 4482162922Sariff break; 4483162922Sariff } 4484162922Sariff w = hdac_widget_get(devinfo, i); 4485162922Sariff if (w == NULL || w->enable == 0) 4486162922Sariff continue; 4487162922Sariff ocap = w->param.outamp_cap; 4488162922Sariff icap = w->param.inamp_cap; 4489162922Sariff if (ocap != 0) { 4490163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4491163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4492163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4493163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4494163057Sariff /*if (offset > step) { 4495163057Sariff HDA_BOOTVERBOSE( 4496163057Sariff device_printf(sc->dev, 4497182999Smav "BUGGY outamp: nid=%d " 4498163057Sariff "[offset=%d > step=%d]\n", 4499163057Sariff w->nid, offset, step); 4500163057Sariff ); 4501163057Sariff offset = step; 4502163057Sariff }*/ 4503162922Sariff ctls[cnt].enable = 1; 4504162922Sariff ctls[cnt].widget = w; 4505163057Sariff ctls[cnt].mute = mute; 4506163057Sariff ctls[cnt].step = step; 4507163057Sariff ctls[cnt].size = size; 4508163057Sariff ctls[cnt].offset = offset; 4509163057Sariff ctls[cnt].left = offset; 4510163057Sariff ctls[cnt].right = offset; 4511182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4512182999Smav w->waspin) 4513182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4514182999Smav else 4515182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4516162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4517162922Sariff } 4518162922Sariff 4519162922Sariff if (icap != 0) { 4520163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4521163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4522163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4523163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4524163057Sariff /*if (offset > step) { 4525163057Sariff HDA_BOOTVERBOSE( 4526163057Sariff device_printf(sc->dev, 4527182999Smav "BUGGY inamp: nid=%d " 4528163057Sariff "[offset=%d > step=%d]\n", 4529163057Sariff w->nid, offset, step); 4530163057Sariff ); 4531163057Sariff offset = step; 4532163057Sariff }*/ 4533162922Sariff switch (w->type) { 4534162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4535162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4536162922Sariff for (j = 0; j < w->nconns; j++) { 4537162922Sariff if (cnt >= max) { 4538162922Sariff device_printf(sc->dev, 4539162922Sariff "%s: Ctl overflow!\n", 4540162922Sariff __func__); 4541162922Sariff break; 4542162922Sariff } 4543162922Sariff cw = hdac_widget_get(devinfo, 4544162922Sariff w->conns[j]); 4545162922Sariff if (cw == NULL || cw->enable == 0) 4546162922Sariff continue; 4547162922Sariff ctls[cnt].enable = 1; 4548162922Sariff ctls[cnt].widget = w; 4549162922Sariff ctls[cnt].childwidget = cw; 4550162922Sariff ctls[cnt].index = j; 4551163057Sariff ctls[cnt].mute = mute; 4552163057Sariff ctls[cnt].step = step; 4553163057Sariff ctls[cnt].size = size; 4554163057Sariff ctls[cnt].offset = offset; 4555163057Sariff ctls[cnt].left = offset; 4556163057Sariff ctls[cnt].right = offset; 4557182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4558162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4559162922Sariff } 4560162922Sariff break; 4561162922Sariff default: 4562162922Sariff if (cnt >= max) { 4563162922Sariff device_printf(sc->dev, 4564162922Sariff "%s: Ctl overflow!\n", 4565162922Sariff __func__); 4566162922Sariff break; 4567162922Sariff } 4568162922Sariff ctls[cnt].enable = 1; 4569162922Sariff ctls[cnt].widget = w; 4570163057Sariff ctls[cnt].mute = mute; 4571163057Sariff ctls[cnt].step = step; 4572163057Sariff ctls[cnt].size = size; 4573163057Sariff ctls[cnt].offset = offset; 4574163057Sariff ctls[cnt].left = offset; 4575163057Sariff ctls[cnt].right = offset; 4576182999Smav if (w->type == 4577182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4578182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4579182999Smav else 4580182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4581162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4582162922Sariff break; 4583162922Sariff } 4584162922Sariff } 4585162922Sariff } 4586162922Sariff 4587162922Sariff devinfo->function.audio.ctl = ctls; 4588162922Sariff} 4589162922Sariff 4590182999Smavstatic void 4591182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4592182999Smav{ 4593182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4594182999Smav struct hdac_audio_as *as; 4595182999Smav struct hdac_widget *w; 4596182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4597182999Smav 4598184991Smav /* Count present associations */ 4599182999Smav max = 0; 4600184991Smav for (j = 1; j < 16; j++) { 4601182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4602182999Smav w = hdac_widget_get(devinfo, i); 4603182999Smav if (w == NULL || w->enable == 0) 4604182999Smav continue; 4605182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4606182999Smav continue; 4607182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4608182999Smav != j) 4609182999Smav continue; 4610182999Smav max++; 4611182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4612182999Smav break; 4613182999Smav } 4614182999Smav } 4615182999Smav 4616182999Smav devinfo->function.audio.ascnt = max; 4617182999Smav 4618182999Smav if (max < 1) 4619182999Smav return; 4620182999Smav 4621182999Smav as = (struct hdac_audio_as *)malloc( 4622182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4623182999Smav 4624182999Smav if (as == NULL) { 4625182999Smav /* Blekh! */ 4626182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4627182999Smav devinfo->function.audio.ascnt = 0; 4628182999Smav return; 4629182999Smav } 4630182999Smav 4631182999Smav for (i = 0; i < max; i++) { 4632182999Smav as[i].hpredir = -1; 4633182999Smav as[i].chan = -1; 4634197611Smav as[i].digital = 0; 4635182999Smav } 4636182999Smav 4637182999Smav /* Scan associations skipping as=0. */ 4638182999Smav cnt = 0; 4639182999Smav for (j = 1; j < 16; j++) { 4640182999Smav first = 16; 4641182999Smav hpredir = 0; 4642182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4643182999Smav w = hdac_widget_get(devinfo, i); 4644182999Smav if (w == NULL || w->enable == 0) 4645182999Smav continue; 4646182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4647182999Smav continue; 4648182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4649182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4650182999Smav if (assoc != j) { 4651182999Smav continue; 4652182999Smav } 4653182999Smav KASSERT(cnt < max, 4654182999Smav ("%s: Associations owerflow (%d of %d)", 4655182999Smav __func__, cnt, max)); 4656182999Smav type = w->wclass.pin.config & 4657182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4658182999Smav /* Get pin direction. */ 4659182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4660182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4661182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4662182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4663182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4664182999Smav dir = HDA_CTL_OUT; 4665182999Smav else 4666182999Smav dir = HDA_CTL_IN; 4667182999Smav /* If this is a first pin - create new association. */ 4668182999Smav if (as[cnt].pincnt == 0) { 4669182999Smav as[cnt].enable = 1; 4670182999Smav as[cnt].index = j; 4671182999Smav as[cnt].dir = dir; 4672182999Smav } 4673182999Smav if (seq < first) 4674182999Smav first = seq; 4675182999Smav /* Check association correctness. */ 4676182999Smav if (as[cnt].pins[seq] != 0) { 4677182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4678182999Smav "in association %d! Disabling association.\n", 4679182999Smav __func__, seq, w->nid, j); 4680182999Smav as[cnt].enable = 0; 4681182999Smav } 4682182999Smav if (dir != as[cnt].dir) { 4683182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4684182999Smav "direction for association %d! Disabling " 4685182999Smav "association.\n", 4686182999Smav __func__, w->nid, j); 4687182999Smav as[cnt].enable = 0; 4688182999Smav } 4689197611Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 4690197611Smav if (HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap)) 4691197611Smav as[cnt].digital = 3; 4692197611Smav else if (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap)) 4693197611Smav as[cnt].digital = 2; 4694197611Smav else 4695197611Smav as[cnt].digital = 1; 4696197611Smav } 4697182999Smav /* Headphones with seq=15 may mean redirection. */ 4698182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4699182999Smav seq == 15) 4700182999Smav hpredir = 1; 4701182999Smav as[cnt].pins[seq] = w->nid; 4702182999Smav as[cnt].pincnt++; 4703182999Smav /* Association 15 is a multiple unassociated pins. */ 4704182999Smav if (j == 15) 4705182999Smav cnt++; 4706182999Smav } 4707182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4708182999Smav if (hpredir && as[cnt].pincnt > 1) 4709182999Smav as[cnt].hpredir = first; 4710182999Smav cnt++; 4711182999Smav } 4712182999Smav } 4713182999Smav HDA_BOOTVERBOSE( 4714182999Smav device_printf(sc->dev, 4715183097Smav "%d associations found:\n", max); 4716182999Smav for (i = 0; i < max; i++) { 4717182999Smav device_printf(sc->dev, 4718182999Smav "Association %d (%d) %s%s:\n", 4719182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4720182999Smav as[i].enable?"":" (disabled)"); 4721182999Smav for (j = 0; j < 16; j++) { 4722182999Smav if (as[i].pins[j] == 0) 4723182999Smav continue; 4724182999Smav device_printf(sc->dev, 4725183097Smav " Pin nid=%d seq=%d\n", 4726182999Smav as[i].pins[j], j); 4727182999Smav } 4728182999Smav } 4729182999Smav ); 4730182999Smav 4731182999Smav devinfo->function.audio.as = as; 4732182999Smav} 4733182999Smav 4734162965Sariffstatic const struct { 4735162965Sariff uint32_t model; 4736162965Sariff uint32_t id; 4737162965Sariff uint32_t set, unset; 4738162965Sariff} hdac_quirks[] = { 4739163057Sariff /* 4740163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4741163057Sariff * on few codecs (especially ALC880) seems broken or 4742163057Sariff * perhaps unsupported. 4743163057Sariff */ 4744163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4745169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4746162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4747165039Sariff HDA_QUIRK_GPIO0, 0 }, 4748178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4749178155Sariff HDA_QUIRK_GPIO0, 0 }, 4750162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4751165039Sariff HDA_QUIRK_GPIO0, 0 }, 4752165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4753165281Sariff HDA_QUIRK_GPIO0, 0 }, 4754167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4755167623Sariff HDA_QUIRK_GPIO0, 0 }, 4756169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4757169277Sariff HDA_QUIRK_GPIO0, 0 }, 4758163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4759163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4760178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4761163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4762169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4763169277Sariff HDA_QUIRK_OVREF, 0 }, 4764169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4765169277Sariff HDA_QUIRK_OVREF, 0 }, 4766169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4767169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4768165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4769165281Sariff HDA_QUIRK_GPIO1, 0 }, 4770164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4771182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4772164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4773164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4774173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4775173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4776165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4777165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4778199846Smav { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, 4779199846Smav HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 }, 4780183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4781180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4782184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4783184483Smav HDA_QUIRK_GPIO2, 0 }, 4784183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4785178155Sariff HDA_QUIRK_GPIO0, 0 }, 4786169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4787169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4788170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4789170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4790186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4791182999Smav 0, HDA_QUIRK_FORCESTEREO } 4792162965Sariff}; 4793162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4794162965Sariff 4795162922Sariffstatic void 4796162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4797162922Sariff{ 4798162922Sariff struct hdac_widget *w; 4799162965Sariff uint32_t id, subvendor; 4800162922Sariff int i; 4801162922Sariff 4802182999Smav id = hdac_codec_id(devinfo->codec); 4803163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4804163057Sariff 4805162922Sariff /* 4806163057Sariff * Quirks 4807162922Sariff */ 4808163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4809163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4810163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4811163057Sariff continue; 4812163057Sariff if (hdac_quirks[i].set != 0) 4813163057Sariff devinfo->function.audio.quirks |= 4814163057Sariff hdac_quirks[i].set; 4815163057Sariff if (hdac_quirks[i].unset != 0) 4816163057Sariff devinfo->function.audio.quirks &= 4817163057Sariff ~(hdac_quirks[i].unset); 4818163057Sariff } 4819163057Sariff 4820162922Sariff switch (id) { 4821187196Smav case HDA_CODEC_AD1983: 4822187196Smav /* 4823187202Smav * This codec has several possible usages, but none 4824187202Smav * fit the parser best. Help parser to choose better. 4825187196Smav */ 4826187196Smav /* Disable direct unmixed playback to get pcm volume. */ 4827187196Smav w = hdac_widget_get(devinfo, 5); 4828187196Smav if (w != NULL) 4829187196Smav w->connsenable[0] = 0; 4830187196Smav w = hdac_widget_get(devinfo, 6); 4831187196Smav if (w != NULL) 4832187196Smav w->connsenable[0] = 0; 4833187196Smav w = hdac_widget_get(devinfo, 11); 4834187196Smav if (w != NULL) 4835187196Smav w->connsenable[0] = 0; 4836187196Smav /* Disable mic and line selectors. */ 4837187196Smav w = hdac_widget_get(devinfo, 12); 4838187196Smav if (w != NULL) 4839187196Smav w->connsenable[1] = 0; 4840187196Smav w = hdac_widget_get(devinfo, 13); 4841187196Smav if (w != NULL) 4842187196Smav w->connsenable[1] = 0; 4843187196Smav /* Disable recording from mono playback mix. */ 4844187196Smav w = hdac_widget_get(devinfo, 20); 4845187196Smav if (w != NULL) 4846187196Smav w->connsenable[3] = 0; 4847187196Smav break; 4848162922Sariff case HDA_CODEC_AD1986A: 4849186503Smav /* 4850186503Smav * This codec has overcomplicated input mixing. 4851186503Smav * Make some cleaning there. 4852186503Smav */ 4853186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4854186503Smav w = hdac_widget_get(devinfo, 43); 4855186503Smav if (w != NULL) 4856186503Smav w->enable = 0; 4857186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4858186503Smav w = hdac_widget_get(devinfo, 39); 4859186503Smav if (w != NULL) 4860186503Smav w->enable = 0; 4861186503Smav w = hdac_widget_get(devinfo, 40); 4862186503Smav if (w != NULL) 4863186503Smav w->enable = 0; 4864186503Smav w = hdac_widget_get(devinfo, 41); 4865186503Smav if (w != NULL) 4866186503Smav w->enable = 0; 4867186503Smav w = hdac_widget_get(devinfo, 42); 4868186503Smav if (w != NULL) 4869186503Smav w->enable = 0; 4870186503Smav /* Disable duplicate mixer node connector. */ 4871186503Smav w = hdac_widget_get(devinfo, 15); 4872186503Smav if (w != NULL) 4873186503Smav w->connsenable[3] = 0; 4874190630Smav /* There is only one mic preamplifier, use it effectively. */ 4875190630Smav w = hdac_widget_get(devinfo, 31); 4876190630Smav if (w != NULL) { 4877190630Smav if ((w->wclass.pin.config & 4878190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4879190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4880190630Smav w = hdac_widget_get(devinfo, 16); 4881190630Smav if (w != NULL) 4882190630Smav w->connsenable[2] = 0; 4883190630Smav } else { 4884190630Smav w = hdac_widget_get(devinfo, 15); 4885190630Smav if (w != NULL) 4886190630Smav w->connsenable[0] = 0; 4887190630Smav } 4888190630Smav } 4889190630Smav w = hdac_widget_get(devinfo, 32); 4890190630Smav if (w != NULL) { 4891190630Smav if ((w->wclass.pin.config & 4892190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4893190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4894190630Smav w = hdac_widget_get(devinfo, 16); 4895190630Smav if (w != NULL) 4896190630Smav w->connsenable[0] = 0; 4897190630Smav } else { 4898190630Smav w = hdac_widget_get(devinfo, 15); 4899190630Smav if (w != NULL) 4900190630Smav w->connsenable[1] = 0; 4901190630Smav } 4902190630Smav } 4903186503Smav 4904182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4905178155Sariff /* 4906178155Sariff * This is just plain ridiculous.. There 4907178155Sariff * are several A8 series that share the same 4908178155Sariff * pci id but works differently (EAPD). 4909178155Sariff */ 4910178155Sariff w = hdac_widget_get(devinfo, 26); 4911178155Sariff if (w != NULL && w->type == 4912178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4913178155Sariff (w->wclass.pin.config & 4914178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4915178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4916178155Sariff devinfo->function.audio.quirks &= 4917178155Sariff ~HDA_QUIRK_EAPDINV; 4918169277Sariff } 4919162922Sariff break; 4920184230Smav case HDA_CODEC_AD1981HD: 4921184230Smav /* 4922184230Smav * This codec has very unusual design with several 4923184254Smav * points inappropriate for the present parser. 4924184230Smav */ 4925184230Smav /* Disable recording from mono playback mix. */ 4926184230Smav w = hdac_widget_get(devinfo, 21); 4927184230Smav if (w != NULL) 4928184230Smav w->connsenable[3] = 0; 4929184230Smav /* Disable rear to front mic mixer, use separately. */ 4930184230Smav w = hdac_widget_get(devinfo, 31); 4931184230Smav if (w != NULL) 4932184230Smav w->enable = 0; 4933202789Smav /* Disable direct playback, use mixer. */ 4934202789Smav w = hdac_widget_get(devinfo, 5); 4935184230Smav if (w != NULL) 4936202789Smav w->connsenable[0] = 0; 4937202789Smav w = hdac_widget_get(devinfo, 6); 4938202789Smav if (w != NULL) 4939202789Smav w->connsenable[0] = 0; 4940202789Smav w = hdac_widget_get(devinfo, 9); 4941202789Smav if (w != NULL) 4942202789Smav w->connsenable[0] = 0; 4943202789Smav w = hdac_widget_get(devinfo, 24); 4944202789Smav if (w != NULL) 4945202789Smav w->connsenable[0] = 0; 4946184230Smav break; 4947223058Smav case HDA_CODEC_CX20582: 4948223058Smav case HDA_CODEC_CX20583: 4949223058Smav case HDA_CODEC_CX20584: 4950223058Smav case HDA_CODEC_CX20585: 4951223058Smav case HDA_CODEC_CX20590: 4952223058Smav /* 4953223058Smav * These codecs have extra connectivity on record side 4954223058Smav * too reach for the present parser. 4955223058Smav */ 4956223058Smav w = hdac_widget_get(devinfo, 20); 4957223058Smav if (w != NULL) 4958223058Smav w->connsenable[1] = 0; 4959223058Smav w = hdac_widget_get(devinfo, 21); 4960223058Smav if (w != NULL) 4961223058Smav w->connsenable[1] = 0; 4962223058Smav w = hdac_widget_get(devinfo, 22); 4963223058Smav if (w != NULL) 4964223058Smav w->connsenable[0] = 0; 4965223058Smav break; 4966182999Smav } 4967182999Smav} 4968182999Smav 4969182999Smav/* 4970182999Smav * Trace path from DAC to pin. 4971182999Smav */ 4972182999Smavstatic nid_t 4973182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4974182999Smav int dupseq, int min, int only, int depth) 4975182999Smav{ 4976182999Smav struct hdac_widget *w; 4977182999Smav int i, im = -1; 4978182999Smav nid_t m = 0, ret; 4979182999Smav 4980182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4981182999Smav return (0); 4982182999Smav w = hdac_widget_get(devinfo, nid); 4983182999Smav if (w == NULL || w->enable == 0) 4984182999Smav return (0); 4985183097Smav HDA_BOOTHVERBOSE( 4986182999Smav if (!only) { 4987182999Smav device_printf(devinfo->codec->sc->dev, 4988182999Smav " %*stracing via nid %d\n", 4989182999Smav depth + 1, "", w->nid); 4990169277Sariff } 4991182999Smav ); 4992182999Smav /* Use only unused widgets */ 4993182999Smav if (w->bindas >= 0 && w->bindas != as) { 4994183097Smav HDA_BOOTHVERBOSE( 4995182999Smav if (!only) { 4996182999Smav device_printf(devinfo->codec->sc->dev, 4997182999Smav " %*snid %d busy by association %d\n", 4998182999Smav depth + 1, "", w->nid, w->bindas); 4999182999Smav } 5000182999Smav ); 5001182999Smav return (0); 5002182999Smav } 5003182999Smav if (dupseq < 0) { 5004182999Smav if (w->bindseqmask != 0) { 5005183097Smav HDA_BOOTHVERBOSE( 5006182999Smav if (!only) { 5007182999Smav device_printf(devinfo->codec->sc->dev, 5008182999Smav " %*snid %d busy by seqmask %x\n", 5009182999Smav depth + 1, "", w->nid, w->bindseqmask); 5010182999Smav } 5011182999Smav ); 5012182999Smav return (0); 5013169277Sariff } 5014182999Smav } else { 5015182999Smav /* If this is headphones - allow duplicate first pin. */ 5016182999Smav if (w->bindseqmask != 0 && 5017182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 5018183097Smav HDA_BOOTHVERBOSE( 5019182999Smav device_printf(devinfo->codec->sc->dev, 5020182999Smav " %*snid %d busy by seqmask %x\n", 5021182999Smav depth + 1, "", w->nid, w->bindseqmask); 5022182999Smav ); 5023182999Smav return (0); 5024169277Sariff } 5025182999Smav } 5026182999Smav 5027182999Smav switch (w->type) { 5028182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5029182999Smav /* Do not traverse input. AD1988 has digital monitor 5030182999Smav for which we are not ready. */ 5031169277Sariff break; 5032182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5033182999Smav /* If we are tracing HP take only dac of first pin. */ 5034182999Smav if ((only == 0 || only == w->nid) && 5035182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 5036182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 5037182999Smav m = w->nid; 5038178155Sariff break; 5039182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5040182999Smav if (depth > 0) 5041169277Sariff break; 5042182999Smav /* Fall */ 5043182999Smav default: 5044182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 5045182999Smav for (i = 0; i < w->nconns; i++) { 5046182999Smav if (w->connsenable[i] == 0) 5047162922Sariff continue; 5048182999Smav if (w->selconn != -1 && w->selconn != i) 5049162922Sariff continue; 5050182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 5051182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 5052182999Smav if (m == 0 || ret < m) { 5053182999Smav m = ret; 5054182999Smav im = i; 5055182999Smav } 5056182999Smav if (only || dupseq >= 0) 5057182999Smav break; 5058182999Smav } 5059162922Sariff } 5060182999Smav if (m && only && ((w->nconns > 1 && 5061182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5062182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 5063182999Smav w->selconn = im; 5064162922Sariff break; 5065182999Smav } 5066182999Smav if (m && only) { 5067182999Smav w->bindas = as; 5068182999Smav w->bindseqmask |= (1 << seq); 5069182999Smav } 5070183097Smav HDA_BOOTHVERBOSE( 5071182999Smav if (!only) { 5072182999Smav device_printf(devinfo->codec->sc->dev, 5073182999Smav " %*snid %d returned %d\n", 5074182999Smav depth + 1, "", w->nid, m); 5075182999Smav } 5076182999Smav ); 5077182999Smav return (m); 5078182999Smav} 5079162922Sariff 5080182999Smav/* 5081182999Smav * Trace path from widget to ADC. 5082182999Smav */ 5083182999Smavstatic nid_t 5084182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 5085182999Smav int only, int depth) 5086182999Smav{ 5087182999Smav struct hdac_widget *w, *wc; 5088182999Smav int i, j; 5089182999Smav nid_t res = 0; 5090182999Smav 5091182999Smav if (depth > HDA_PARSE_MAXDEPTH) 5092182999Smav return (0); 5093182999Smav w = hdac_widget_get(devinfo, nid); 5094182999Smav if (w == NULL || w->enable == 0) 5095182999Smav return (0); 5096183097Smav HDA_BOOTHVERBOSE( 5097182999Smav device_printf(devinfo->codec->sc->dev, 5098182999Smav " %*stracing via nid %d\n", 5099182999Smav depth + 1, "", w->nid); 5100182999Smav ); 5101182999Smav /* Use only unused widgets */ 5102182999Smav if (w->bindas >= 0 && w->bindas != as) { 5103183097Smav HDA_BOOTHVERBOSE( 5104182999Smav device_printf(devinfo->codec->sc->dev, 5105182999Smav " %*snid %d busy by association %d\n", 5106182999Smav depth + 1, "", w->nid, w->bindas); 5107182999Smav ); 5108182999Smav return (0); 5109182999Smav } 5110182999Smav 5111182999Smav switch (w->type) { 5112182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5113182999Smav /* If we are tracing HP take only dac of first pin. */ 5114182999Smav if (only == w->nid) 5115182999Smav res = 1; 5116162922Sariff break; 5117182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5118182999Smav if (depth > 0) 5119182999Smav break; 5120182999Smav /* Fall */ 5121182999Smav default: 5122182999Smav /* Try to find reachable ADCs with specified nid. */ 5123182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5124182999Smav wc = hdac_widget_get(devinfo, j); 5125182999Smav if (wc == NULL || wc->enable == 0) 5126182999Smav continue; 5127182999Smav for (i = 0; i < wc->nconns; i++) { 5128182999Smav if (wc->connsenable[i] == 0) 5129182999Smav continue; 5130182999Smav if (wc->conns[i] != nid) 5131182999Smav continue; 5132182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 5133182999Smav j, only, depth + 1) != 0) { 5134182999Smav res = 1; 5135182999Smav if (((wc->nconns > 1 && 5136182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5137182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 5138182999Smav wc->selconn == -1) 5139182999Smav wc->selconn = i; 5140182999Smav } 5141182999Smav } 5142169277Sariff } 5143169277Sariff break; 5144162922Sariff } 5145182999Smav if (res) { 5146182999Smav w->bindas = as; 5147182999Smav w->bindseqmask |= (1 << seq); 5148182999Smav } 5149183097Smav HDA_BOOTHVERBOSE( 5150182999Smav device_printf(devinfo->codec->sc->dev, 5151182999Smav " %*snid %d returned %d\n", 5152182999Smav depth + 1, "", w->nid, res); 5153182999Smav ); 5154182999Smav return (res); 5155162922Sariff} 5156162922Sariff 5157182999Smav/* 5158182999Smav * Erase trace path of the specified association. 5159182999Smav */ 5160182999Smavstatic void 5161182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 5162182999Smav{ 5163182999Smav struct hdac_widget *w; 5164182999Smav int i; 5165182999Smav 5166182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5167182999Smav w = hdac_widget_get(devinfo, i); 5168182999Smav if (w == NULL || w->enable == 0) 5169182999Smav continue; 5170182999Smav if (w->bindas == as) { 5171182999Smav if (seq >= 0) { 5172182999Smav w->bindseqmask &= ~(1 << seq); 5173182999Smav if (w->bindseqmask == 0) { 5174182999Smav w->bindas = -1; 5175182999Smav w->selconn = -1; 5176182999Smav } 5177182999Smav } else { 5178182999Smav w->bindas = -1; 5179182999Smav w->bindseqmask = 0; 5180182999Smav w->selconn = -1; 5181182999Smav } 5182182999Smav } 5183182999Smav } 5184182999Smav} 5185182999Smav 5186182999Smav/* 5187182999Smav * Trace association path from DAC to output 5188182999Smav */ 5189162922Sariffstatic int 5190182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 5191162922Sariff{ 5192182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5193182999Smav int i, hpredir; 5194182999Smav nid_t min, res; 5195162922Sariff 5196182999Smav /* Find next pin */ 5197185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 5198182999Smav ; 5199188510Smav /* Check if there is no any left. If so - we succeeded. */ 5200182999Smav if (i == 16) 5201182999Smav return (1); 5202182999Smav 5203182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 5204182999Smav min = 0; 5205182999Smav res = 0; 5206182999Smav do { 5207183097Smav HDA_BOOTHVERBOSE( 5208182999Smav device_printf(devinfo->codec->sc->dev, 5209182999Smav " Tracing pin %d with min nid %d", 5210182999Smav ases[as].pins[i], min); 5211182999Smav if (hpredir >= 0) 5212183097Smav printf(" and hpredir %d", hpredir); 5213183097Smav printf("\n"); 5214182999Smav ); 5215182999Smav /* Trace this pin taking min nid into account. */ 5216182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 5217182999Smav ases[as].pins[i], hpredir, min, 0, 0); 5218182999Smav if (res == 0) { 5219182999Smav /* If we failed - return to previous and redo it. */ 5220182999Smav HDA_BOOTVERBOSE( 5221182999Smav device_printf(devinfo->codec->sc->dev, 5222182999Smav " Unable to trace pin %d seq %d with min " 5223183097Smav "nid %d", 5224183097Smav ases[as].pins[i], i, min); 5225183097Smav if (hpredir >= 0) 5226183097Smav printf(" and hpredir %d", hpredir); 5227183097Smav printf("\n"); 5228182999Smav ); 5229182999Smav return (0); 5230162922Sariff } 5231182999Smav HDA_BOOTVERBOSE( 5232182999Smav device_printf(devinfo->codec->sc->dev, 5233183097Smav " Pin %d traced to DAC %d", 5234183097Smav ases[as].pins[i], res); 5235183097Smav if (hpredir >= 0) 5236183097Smav printf(" and hpredir %d", hpredir); 5237183097Smav if (ases[as].fakeredir) 5238183097Smav printf(" with fake redirection"); 5239183097Smav printf("\n"); 5240182999Smav ); 5241182999Smav /* Trace again to mark the path */ 5242182999Smav hdac_audio_trace_dac(devinfo, as, i, 5243182999Smav ases[as].pins[i], hpredir, min, res, 0); 5244182999Smav ases[as].dacs[i] = res; 5245188510Smav /* We succeeded, so call next. */ 5246182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 5247182999Smav return (1); 5248182999Smav /* If next failed, we should retry with next min */ 5249182999Smav hdac_audio_undo_trace(devinfo, as, i); 5250182999Smav ases[as].dacs[i] = 0; 5251182999Smav min = res + 1; 5252182999Smav } while (1); 5253162922Sariff} 5254162922Sariff 5255182999Smav/* 5256182999Smav * Trace association path from input to ADC 5257182999Smav */ 5258162922Sariffstatic int 5259182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 5260162922Sariff{ 5261182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5262162922Sariff struct hdac_widget *w; 5263182999Smav int i, j, k; 5264162922Sariff 5265182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5266182999Smav w = hdac_widget_get(devinfo, j); 5267182999Smav if (w == NULL || w->enable == 0) 5268182999Smav continue; 5269182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5270182999Smav continue; 5271182999Smav if (w->bindas >= 0 && w->bindas != as) 5272182999Smav continue; 5273182999Smav 5274182999Smav /* Find next pin */ 5275182999Smav for (i = 0; i < 16; i++) { 5276182999Smav if (ases[as].pins[i] == 0) 5277182999Smav continue; 5278182999Smav 5279183097Smav HDA_BOOTHVERBOSE( 5280182999Smav device_printf(devinfo->codec->sc->dev, 5281182999Smav " Tracing pin %d to ADC %d\n", 5282182999Smav ases[as].pins[i], j); 5283182999Smav ); 5284182999Smav /* Trace this pin taking goal into account. */ 5285182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 5286182999Smav ases[as].pins[i], j, 0) == 0) { 5287182999Smav /* If we failed - return to previous and redo it. */ 5288182999Smav HDA_BOOTVERBOSE( 5289182999Smav device_printf(devinfo->codec->sc->dev, 5290183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 5291182999Smav ases[as].pins[i], j); 5292182999Smav ); 5293182999Smav hdac_audio_undo_trace(devinfo, as, -1); 5294182999Smav for (k = 0; k < 16; k++) 5295182999Smav ases[as].dacs[k] = 0; 5296182999Smav break; 5297162922Sariff } 5298182999Smav HDA_BOOTVERBOSE( 5299182999Smav device_printf(devinfo->codec->sc->dev, 5300183097Smav " Pin %d traced to ADC %d\n", 5301183097Smav ases[as].pins[i], j); 5302182999Smav ); 5303182999Smav ases[as].dacs[i] = j; 5304162922Sariff } 5305182999Smav if (i == 16) 5306182999Smav return (1); 5307162922Sariff } 5308182999Smav return (0); 5309162922Sariff} 5310162922Sariff 5311182999Smav/* 5312182999Smav * Trace input monitor path from mixer to output association. 5313182999Smav */ 5314183097Smavstatic int 5315182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5316162922Sariff{ 5317182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5318182999Smav struct hdac_widget *w, *wc; 5319182999Smav int i, j; 5320182999Smav nid_t res = 0; 5321162922Sariff 5322162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5323162922Sariff return (0); 5324162922Sariff w = hdac_widget_get(devinfo, nid); 5325162922Sariff if (w == NULL || w->enable == 0) 5326162922Sariff return (0); 5327183097Smav HDA_BOOTHVERBOSE( 5328182999Smav device_printf(devinfo->codec->sc->dev, 5329182999Smav " %*stracing via nid %d\n", 5330182999Smav depth + 1, "", w->nid); 5331182999Smav ); 5332182999Smav /* Use only unused widgets */ 5333182999Smav if (depth > 0 && w->bindas != -1) { 5334182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5335183097Smav HDA_BOOTHVERBOSE( 5336182999Smav device_printf(devinfo->codec->sc->dev, 5337182999Smav " %*snid %d found output association %d\n", 5338182999Smav depth + 1, "", w->nid, w->bindas); 5339182999Smav ); 5340202789Smav if (w->bindas >= 0) 5341202789Smav w->pflags |= HDA_ADC_MONITOR; 5342182999Smav return (1); 5343182999Smav } else { 5344183097Smav HDA_BOOTHVERBOSE( 5345182999Smav device_printf(devinfo->codec->sc->dev, 5346182999Smav " %*snid %d busy by input association %d\n", 5347182999Smav depth + 1, "", w->nid, w->bindas); 5348182999Smav ); 5349182999Smav return (0); 5350182999Smav } 5351182999Smav } 5352182999Smav 5353162922Sariff switch (w->type) { 5354162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5355182999Smav /* Do not traverse input. AD1988 has digital monitor 5356182999Smav for which we are not ready. */ 5357162922Sariff break; 5358162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5359182999Smav if (depth > 0) 5360182999Smav break; 5361182999Smav /* Fall */ 5362182999Smav default: 5363182999Smav /* Try to find reachable ADCs with specified nid. */ 5364182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5365182999Smav wc = hdac_widget_get(devinfo, j); 5366182999Smav if (wc == NULL || wc->enable == 0) 5367182999Smav continue; 5368182999Smav for (i = 0; i < wc->nconns; i++) { 5369182999Smav if (wc->connsenable[i] == 0) 5370182999Smav continue; 5371182999Smav if (wc->conns[i] != nid) 5372182999Smav continue; 5373182999Smav if (hdac_audio_trace_to_out(devinfo, 5374182999Smav j, depth + 1) != 0) { 5375182999Smav res = 1; 5376182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5377182999Smav wc->selconn == -1) 5378182999Smav wc->selconn = i; 5379182999Smav } 5380182999Smav } 5381162922Sariff } 5382162922Sariff break; 5383182999Smav } 5384202789Smav if (res && w->bindas == -1) 5385182999Smav w->bindas = -2; 5386182999Smav 5387183097Smav HDA_BOOTHVERBOSE( 5388182999Smav device_printf(devinfo->codec->sc->dev, 5389182999Smav " %*snid %d returned %d\n", 5390182999Smav depth + 1, "", w->nid, res); 5391182999Smav ); 5392182999Smav return (res); 5393182999Smav} 5394182999Smav 5395182999Smav/* 5396182999Smav * Trace extra associations (beeper, monitor) 5397182999Smav */ 5398182999Smavstatic void 5399182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5400182999Smav{ 5401182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5402182999Smav struct hdac_widget *w; 5403182999Smav int j; 5404182999Smav 5405182999Smav /* Input monitor */ 5406182999Smav /* Find mixer associated with input, but supplying signal 5407182999Smav for output associations. Hope it will be input monitor. */ 5408182999Smav HDA_BOOTVERBOSE( 5409182999Smav device_printf(devinfo->codec->sc->dev, 5410182999Smav "Tracing input monitor\n"); 5411182999Smav ); 5412182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5413182999Smav w = hdac_widget_get(devinfo, j); 5414182999Smav if (w == NULL || w->enable == 0) 5415182999Smav continue; 5416182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5417182999Smav continue; 5418182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5419182999Smav continue; 5420182999Smav HDA_BOOTVERBOSE( 5421182999Smav device_printf(devinfo->codec->sc->dev, 5422182999Smav " Tracing nid %d to out\n", 5423182999Smav j); 5424182999Smav ); 5425182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5426182999Smav HDA_BOOTVERBOSE( 5427182999Smav device_printf(devinfo->codec->sc->dev, 5428182999Smav " nid %d is input monitor\n", 5429182999Smav w->nid); 5430182999Smav ); 5431182999Smav w->ossdev = SOUND_MIXER_IMIX; 5432162922Sariff } 5433162922Sariff } 5434182999Smav 5435202789Smav /* Other inputs monitor */ 5436202789Smav /* Find input pins supplying signal for output associations. 5437202789Smav Hope it will be input monitoring. */ 5438202789Smav HDA_BOOTVERBOSE( 5439202789Smav device_printf(devinfo->codec->sc->dev, 5440202789Smav "Tracing other input monitors\n"); 5441202789Smav ); 5442202789Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5443202789Smav w = hdac_widget_get(devinfo, j); 5444202789Smav if (w == NULL || w->enable == 0) 5445202789Smav continue; 5446202789Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5447202789Smav continue; 5448202789Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5449202789Smav continue; 5450202789Smav HDA_BOOTVERBOSE( 5451202789Smav device_printf(devinfo->codec->sc->dev, 5452202789Smav " Tracing nid %d to out\n", 5453202789Smav j); 5454202789Smav ); 5455202789Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5456202789Smav HDA_BOOTVERBOSE( 5457202789Smav device_printf(devinfo->codec->sc->dev, 5458202789Smav " nid %d is input monitor\n", 5459202789Smav w->nid); 5460202789Smav ); 5461202789Smav } 5462202789Smav } 5463202789Smav 5464182999Smav /* Beeper */ 5465182999Smav HDA_BOOTVERBOSE( 5466182999Smav device_printf(devinfo->codec->sc->dev, 5467182999Smav "Tracing beeper\n"); 5468182999Smav ); 5469182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5470182999Smav w = hdac_widget_get(devinfo, j); 5471182999Smav if (w == NULL || w->enable == 0) 5472182999Smav continue; 5473182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5474182999Smav continue; 5475183097Smav HDA_BOOTHVERBOSE( 5476182999Smav device_printf(devinfo->codec->sc->dev, 5477182999Smav " Tracing nid %d to out\n", 5478182999Smav j); 5479182999Smav ); 5480183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5481183097Smav HDA_BOOTVERBOSE( 5482183097Smav device_printf(devinfo->codec->sc->dev, 5483183097Smav " nid %d traced to out\n", 5484183097Smav j); 5485183097Smav ); 5486183097Smav } 5487182999Smav w->bindas = -2; 5488182999Smav } 5489162922Sariff} 5490162922Sariff 5491182999Smav/* 5492182999Smav * Bind assotiations to PCM channels 5493182999Smav */ 5494182999Smavstatic void 5495182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5496162922Sariff{ 5497182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5498182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5499182999Smav int j, cnt = 0, free; 5500162922Sariff 5501182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5502182999Smav if (as[j].enable) 5503182999Smav cnt++; 5504182999Smav } 5505182999Smav if (sc->num_chans == 0) { 5506182999Smav sc->chans = (struct hdac_chan *)malloc( 5507182999Smav sizeof(struct hdac_chan) * cnt, 5508182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5509182999Smav if (sc->chans == NULL) { 5510190519Smav device_printf(sc->dev, 5511182999Smav "Channels memory allocation failed!\n"); 5512182999Smav return; 5513182999Smav } 5514182999Smav } else { 5515182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5516183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5517182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5518182999Smav if (sc->chans == NULL) { 5519182999Smav sc->num_chans = 0; 5520190519Smav device_printf(sc->dev, 5521182999Smav "Channels memory allocation failed!\n"); 5522182999Smav return; 5523182999Smav } 5524190519Smav /* Fixup relative pointers after realloc */ 5525190519Smav for (j = 0; j < sc->num_chans; j++) 5526190519Smav sc->chans[j].caps.fmtlist = sc->chans[j].fmtlist; 5527182999Smav } 5528182999Smav free = sc->num_chans; 5529182999Smav sc->num_chans += cnt; 5530162922Sariff 5531182999Smav for (j = free; j < free + cnt; j++) { 5532190519Smav sc->chans[j].devinfo = devinfo; 5533190519Smav sc->chans[j].as = -1; 5534182999Smav } 5535162922Sariff 5536182999Smav /* Assign associations in order of their numbers, */ 5537182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5538182999Smav if (as[j].enable == 0) 5539182999Smav continue; 5540182999Smav 5541182999Smav as[j].chan = free; 5542190519Smav sc->chans[free].as = j; 5543190519Smav sc->chans[free].dir = 5544185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5545190519Smav hdac_pcmchannel_setup(&sc->chans[free]); 5546182999Smav free++; 5547182999Smav } 5548182999Smav} 5549162922Sariff 5550182999Smavstatic void 5551182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5552182999Smav{ 5553182999Smav struct hdac_widget *w; 5554182999Smav int i; 5555182999Smav 5556182999Smav /* Disable power and volume widgets. */ 5557182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5558182999Smav w = hdac_widget_get(devinfo, i); 5559182999Smav if (w == NULL || w->enable == 0) 5560182999Smav continue; 5561182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5562182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5563182999Smav w->enable = 0; 5564183097Smav HDA_BOOTHVERBOSE( 5565182999Smav device_printf(devinfo->codec->sc->dev, 5566182999Smav " Disabling nid %d due to it's" 5567182999Smav " non-audio type.\n", 5568182999Smav w->nid); 5569182999Smav ); 5570162922Sariff } 5571182999Smav } 5572182999Smav} 5573182999Smav 5574182999Smavstatic void 5575182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5576182999Smav{ 5577182999Smav struct hdac_widget *w, *cw; 5578182999Smav struct hdac_audio_ctl *ctl; 5579182999Smav int done, found, i, j, k; 5580182999Smav 5581182999Smav /* Disable useless pins. */ 5582182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5583182999Smav w = hdac_widget_get(devinfo, i); 5584182999Smav if (w == NULL || w->enable == 0) 5585182999Smav continue; 5586184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5587184991Smav if ((w->wclass.pin.config & 5588184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5589184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5590184991Smav w->enable = 0; 5591184991Smav HDA_BOOTHVERBOSE( 5592184991Smav device_printf(devinfo->codec->sc->dev, 5593184991Smav " Disabling pin nid %d due" 5594184991Smav " to None connectivity.\n", 5595184991Smav w->nid); 5596184991Smav ); 5597184991Smav } else if ((w->wclass.pin.config & 5598184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5599184991Smav w->enable = 0; 5600184991Smav HDA_BOOTHVERBOSE( 5601184991Smav device_printf(devinfo->codec->sc->dev, 5602184991Smav " Disabling unassociated" 5603184991Smav " pin nid %d.\n", 5604184991Smav w->nid); 5605184991Smav ); 5606184991Smav } 5607182999Smav } 5608182999Smav } 5609182999Smav do { 5610182999Smav done = 1; 5611182999Smav /* Disable and mute controls for disabled widgets. */ 5612162922Sariff i = 0; 5613162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5614182999Smav if (ctl->enable == 0) 5615162922Sariff continue; 5616182999Smav if (ctl->widget->enable == 0 || 5617182999Smav (ctl->childwidget != NULL && 5618182999Smav ctl->childwidget->enable == 0)) { 5619182999Smav ctl->forcemute = 1; 5620182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5621182999Smav ctl->left = 0; 5622182999Smav ctl->right = 0; 5623182999Smav ctl->enable = 0; 5624182999Smav if (ctl->ndir == HDA_CTL_IN) 5625182999Smav ctl->widget->connsenable[ctl->index] = 0; 5626182999Smav done = 0; 5627183097Smav HDA_BOOTHVERBOSE( 5628182999Smav device_printf(devinfo->codec->sc->dev, 5629182999Smav " Disabling ctl %d nid %d cnid %d due" 5630182999Smav " to disabled widget.\n", i, 5631182999Smav ctl->widget->nid, 5632182999Smav (ctl->childwidget != NULL)? 5633182999Smav ctl->childwidget->nid:-1); 5634182999Smav ); 5635182999Smav } 5636182999Smav } 5637182999Smav /* Disable useless widgets. */ 5638182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5639182999Smav w = hdac_widget_get(devinfo, i); 5640182999Smav if (w == NULL || w->enable == 0) 5641182999Smav continue; 5642182999Smav /* Disable inputs with disabled child widgets. */ 5643182999Smav for (j = 0; j < w->nconns; j++) { 5644182999Smav if (w->connsenable[j]) { 5645182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5646182999Smav if (cw == NULL || cw->enable == 0) { 5647182999Smav w->connsenable[j] = 0; 5648183097Smav HDA_BOOTHVERBOSE( 5649182999Smav device_printf(devinfo->codec->sc->dev, 5650182999Smav " Disabling nid %d connection %d due" 5651182999Smav " to disabled child widget.\n", 5652182999Smav i, j); 5653182999Smav ); 5654163057Sariff } 5655163057Sariff } 5656162922Sariff } 5657182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5658182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5659162922Sariff continue; 5660182999Smav /* Disable mixers and selectors without inputs. */ 5661182999Smav found = 0; 5662182999Smav for (j = 0; j < w->nconns; j++) { 5663182999Smav if (w->connsenable[j]) { 5664182999Smav found = 1; 5665162922Sariff break; 5666162922Sariff } 5667182999Smav } 5668182999Smav if (found == 0) { 5669182999Smav w->enable = 0; 5670182999Smav done = 0; 5671183097Smav HDA_BOOTHVERBOSE( 5672182999Smav device_printf(devinfo->codec->sc->dev, 5673182999Smav " Disabling nid %d due to all it's" 5674182999Smav " inputs disabled.\n", w->nid); 5675182999Smav ); 5676182999Smav } 5677182999Smav /* Disable nodes without consumers. */ 5678182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5679182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5680182999Smav continue; 5681182999Smav found = 0; 5682182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5683182999Smav cw = hdac_widget_get(devinfo, k); 5684182999Smav if (cw == NULL || cw->enable == 0) 5685182999Smav continue; 5686182999Smav for (j = 0; j < cw->nconns; j++) { 5687182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5688182999Smav found = 1; 5689182999Smav break; 5690182999Smav } 5691162922Sariff } 5692162922Sariff } 5693182999Smav if (found == 0) { 5694182999Smav w->enable = 0; 5695182999Smav done = 0; 5696183097Smav HDA_BOOTHVERBOSE( 5697182999Smav device_printf(devinfo->codec->sc->dev, 5698182999Smav " Disabling nid %d due to all it's" 5699182999Smav " consumers disabled.\n", w->nid); 5700182999Smav ); 5701182999Smav } 5702162922Sariff } 5703182999Smav } while (done == 0); 5704182999Smav 5705182999Smav} 5706182999Smav 5707182999Smavstatic void 5708182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5709182999Smav{ 5710182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5711182999Smav struct hdac_widget *w, *cw; 5712182999Smav struct hdac_audio_ctl *ctl; 5713182999Smav int i, j, k; 5714182999Smav 5715182999Smav /* Disable unassosiated widgets. */ 5716182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5717182999Smav w = hdac_widget_get(devinfo, i); 5718182999Smav if (w == NULL || w->enable == 0) 5719182999Smav continue; 5720182999Smav if (w->bindas == -1) { 5721182999Smav w->enable = 0; 5722183097Smav HDA_BOOTHVERBOSE( 5723182999Smav device_printf(devinfo->codec->sc->dev, 5724182999Smav " Disabling unassociated nid %d.\n", 5725182999Smav w->nid); 5726182999Smav ); 5727182999Smav } 5728182999Smav } 5729182999Smav /* Disable input connections on input pin and 5730182999Smav * output on output. */ 5731182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5732182999Smav w = hdac_widget_get(devinfo, i); 5733182999Smav if (w == NULL || w->enable == 0) 5734182999Smav continue; 5735182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5736182999Smav continue; 5737182999Smav if (w->bindas < 0) 5738182999Smav continue; 5739182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5740182999Smav for (j = 0; j < w->nconns; j++) { 5741182999Smav if (w->connsenable[j] == 0) 5742182999Smav continue; 5743182999Smav w->connsenable[j] = 0; 5744183097Smav HDA_BOOTHVERBOSE( 5745182999Smav device_printf(devinfo->codec->sc->dev, 5746182999Smav " Disabling connection to input pin " 5747182999Smav "nid %d conn %d.\n", 5748182999Smav i, j); 5749182999Smav ); 5750162922Sariff } 5751182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5752182999Smav HDA_CTL_IN, -1, 1); 5753182999Smav if (ctl && ctl->enable) { 5754182999Smav ctl->forcemute = 1; 5755182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5756182999Smav ctl->left = 0; 5757182999Smav ctl->right = 0; 5758182999Smav ctl->enable = 0; 5759182999Smav } 5760182999Smav } else { 5761182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5762182999Smav HDA_CTL_OUT, -1, 1); 5763182999Smav if (ctl && ctl->enable) { 5764182999Smav ctl->forcemute = 1; 5765182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5766182999Smav ctl->left = 0; 5767182999Smav ctl->right = 0; 5768182999Smav ctl->enable = 0; 5769182999Smav } 5770182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5771182999Smav cw = hdac_widget_get(devinfo, k); 5772182999Smav if (cw == NULL || cw->enable == 0) 5773182999Smav continue; 5774182999Smav for (j = 0; j < cw->nconns; j++) { 5775182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5776182999Smav cw->connsenable[j] = 0; 5777183097Smav HDA_BOOTHVERBOSE( 5778182999Smav device_printf(devinfo->codec->sc->dev, 5779182999Smav " Disabling connection from output pin " 5780182999Smav "nid %d conn %d cnid %d.\n", 5781182999Smav k, j, i); 5782182999Smav ); 5783182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5784182999Smav cw->nconns > 1) 5785182999Smav continue; 5786182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5787182999Smav HDA_CTL_IN, j, 1); 5788182999Smav if (ctl && ctl->enable) { 5789182999Smav ctl->forcemute = 1; 5790182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5791182999Smav ctl->left = 0; 5792182999Smav ctl->right = 0; 5793182999Smav ctl->enable = 0; 5794182999Smav } 5795182999Smav } 5796182999Smav } 5797182999Smav } 5798162922Sariff } 5799162922Sariff } 5800162922Sariff} 5801162922Sariff 5802182999Smavstatic void 5803182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5804162922Sariff{ 5805182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5806182999Smav struct hdac_widget *w; 5807182999Smav int i, j; 5808182999Smav 5809182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5810182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5811182999Smav w = hdac_widget_get(devinfo, i); 5812182999Smav if (w == NULL || w->enable == 0) 5813182999Smav continue; 5814182999Smav if (w->nconns <= 1) 5815182999Smav continue; 5816182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5817182999Smav continue; 5818182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5819182999Smav continue; 5820182999Smav for (j = 0; j < w->nconns; j++) { 5821182999Smav if (w->connsenable[j] == 0) 5822182999Smav continue; 5823182999Smav if (w->selconn < 0 || w->selconn == j) 5824182999Smav continue; 5825182999Smav w->connsenable[j] = 0; 5826183097Smav HDA_BOOTHVERBOSE( 5827182999Smav device_printf(devinfo->codec->sc->dev, 5828182999Smav " Disabling unselected connection " 5829182999Smav "nid %d conn %d.\n", 5830182999Smav i, j); 5831182999Smav ); 5832182999Smav } 5833182999Smav } 5834182999Smav} 5835182999Smav 5836182999Smavstatic void 5837182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5838182999Smav{ 5839202789Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5840162922Sariff struct hdac_widget *w, *cw; 5841162922Sariff struct hdac_audio_ctl *ctl; 5842182999Smav int i, j; 5843162922Sariff 5844187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5845182999Smav /* ... using selectors */ 5846182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5847182999Smav w = hdac_widget_get(devinfo, i); 5848182999Smav if (w == NULL || w->enable == 0) 5849182999Smav continue; 5850182999Smav if (w->nconns <= 1) 5851182999Smav continue; 5852182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5853182999Smav continue; 5854182999Smav if (w->bindas == -2) 5855182999Smav continue; 5856182999Smav for (j = 0; j < w->nconns; j++) { 5857182999Smav if (w->connsenable[j] == 0) 5858182999Smav continue; 5859182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5860182999Smav if (cw == NULL || w->enable == 0) 5861182999Smav continue; 5862202789Smav if (cw->bindas == -2 || 5863202789Smav ((w->pflags & HDA_ADC_MONITOR) && 5864202789Smav cw->bindas >= 0 && 5865202789Smav ases[cw->bindas].dir == HDA_CTL_IN)) 5866182999Smav continue; 5867187052Smav if (w->bindas == cw->bindas && 5868187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5869187052Smav continue; 5870182999Smav w->connsenable[j] = 0; 5871183097Smav HDA_BOOTHVERBOSE( 5872182999Smav device_printf(devinfo->codec->sc->dev, 5873182999Smav " Disabling crossassociatement connection " 5874182999Smav "nid %d conn %d cnid %d.\n", 5875182999Smav i, j, cw->nid); 5876182999Smav ); 5877182999Smav } 5878182999Smav } 5879182999Smav /* ... using controls */ 5880182999Smav i = 0; 5881182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5882182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5883182999Smav continue; 5884202789Smav if (ctl->widget->bindas == -2) 5885182999Smav continue; 5886202789Smav if (ctl->childwidget->bindas == -2 || 5887202789Smav ((ctl->widget->pflags & HDA_ADC_MONITOR) && 5888202789Smav ctl->childwidget->bindas >= 0 && 5889202789Smav ases[ctl->childwidget->bindas].dir == HDA_CTL_IN)) 5890202789Smav continue; 5891187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5892187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5893182999Smav ctl->forcemute = 1; 5894182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5895182999Smav ctl->left = 0; 5896182999Smav ctl->right = 0; 5897182999Smav ctl->enable = 0; 5898182999Smav if (ctl->ndir == HDA_CTL_IN) 5899182999Smav ctl->widget->connsenable[ctl->index] = 0; 5900183097Smav HDA_BOOTHVERBOSE( 5901182999Smav device_printf(devinfo->codec->sc->dev, 5902182999Smav " Disabling crossassociatement connection " 5903182999Smav "ctl %d nid %d cnid %d.\n", i, 5904182999Smav ctl->widget->nid, 5905182999Smav ctl->childwidget->nid); 5906182999Smav ); 5907182999Smav } 5908182999Smav } 5909182999Smav 5910182999Smav} 5911182999Smav 5912182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5913182999Smav 5914182999Smav/* 5915182999Smav * Find controls to control amplification for source. 5916182999Smav */ 5917182999Smavstatic int 5918182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5919182999Smav int ossdev, int ctlable, int depth, int need) 5920182999Smav{ 5921182999Smav struct hdac_widget *w, *wc; 5922182999Smav struct hdac_audio_ctl *ctl; 5923182999Smav int i, j, conns = 0, rneed; 5924182999Smav 5925162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5926182999Smav return (need); 5927162922Sariff 5928162922Sariff w = hdac_widget_get(devinfo, nid); 5929162922Sariff if (w == NULL || w->enable == 0) 5930182999Smav return (need); 5931182999Smav 5932182999Smav /* Count number of active inputs. */ 5933182999Smav if (depth > 0) { 5934182999Smav for (j = 0; j < w->nconns; j++) { 5935182999Smav if (w->connsenable[j]) 5936182999Smav conns++; 5937162922Sariff } 5938162922Sariff } 5939182999Smav 5940182999Smav /* If this is not a first step - use input mixer. 5941182999Smav Pins have common input ctl so care must be taken. */ 5942182999Smav if (depth > 0 && ctlable && (conns == 1 || 5943182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5944182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5945182999Smav index, 1); 5946182999Smav if (ctl) { 5947182999Smav if (HDA_CTL_GIVE(ctl) & need) 5948182999Smav ctl->ossmask |= (1 << ossdev); 5949182999Smav else 5950182999Smav ctl->possmask |= (1 << ossdev); 5951182999Smav need &= ~HDA_CTL_GIVE(ctl); 5952182999Smav } 5953182999Smav } 5954182999Smav 5955182999Smav /* If widget has own ossdev - not traverse it. 5956182999Smav It will be traversed on it's own. */ 5957182999Smav if (w->ossdev >= 0 && depth > 0) 5958182999Smav return (need); 5959182999Smav 5960182999Smav /* We must not traverse pin */ 5961182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5962182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5963182999Smav depth > 0) 5964182999Smav return (need); 5965182999Smav 5966182999Smav /* record that this widget exports such signal, */ 5967182999Smav w->ossmask |= (1 << ossdev); 5968182999Smav 5969182999Smav /* If signals mixed, we can't assign controls farther. 5970182999Smav * Ignore this on depth zero. Caller must knows why. 5971182999Smav * Ignore this for static selectors if this input selected. 5972182999Smav */ 5973182999Smav if (conns > 1) 5974182999Smav ctlable = 0; 5975182999Smav 5976182999Smav if (ctlable) { 5977182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5978182999Smav if (ctl) { 5979182999Smav if (HDA_CTL_GIVE(ctl) & need) 5980182999Smav ctl->ossmask |= (1 << ossdev); 5981182999Smav else 5982182999Smav ctl->possmask |= (1 << ossdev); 5983182999Smav need &= ~HDA_CTL_GIVE(ctl); 5984182999Smav } 5985182999Smav } 5986182999Smav 5987182999Smav rneed = 0; 5988182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5989182999Smav wc = hdac_widget_get(devinfo, i); 5990182999Smav if (wc == NULL || wc->enable == 0) 5991162922Sariff continue; 5992182999Smav for (j = 0; j < wc->nconns; j++) { 5993182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5994182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5995182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5996182999Smav } 5997162922Sariff } 5998162922Sariff } 5999182999Smav rneed &= need; 6000182999Smav 6001182999Smav return (rneed); 6002162922Sariff} 6003162922Sariff 6004182999Smav/* 6005182999Smav * Find controls to control amplification for destination. 6006182999Smav */ 6007182999Smavstatic void 6008202789Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 6009182999Smav int ossdev, int depth, int need) 6010162922Sariff{ 6011182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6012182999Smav struct hdac_widget *w, *wc; 6013182999Smav struct hdac_audio_ctl *ctl; 6014182999Smav int i, j, consumers; 6015182999Smav 6016162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 6017182999Smav return; 6018162922Sariff 6019162922Sariff w = hdac_widget_get(devinfo, nid); 6020162922Sariff if (w == NULL || w->enable == 0) 6021182999Smav return; 6022182999Smav 6023182999Smav if (depth > 0) { 6024182999Smav /* If this node produce output for several consumers, 6025182999Smav we can't touch it. */ 6026182999Smav consumers = 0; 6027182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6028182999Smav wc = hdac_widget_get(devinfo, i); 6029182999Smav if (wc == NULL || wc->enable == 0) 6030182999Smav continue; 6031182999Smav for (j = 0; j < wc->nconns; j++) { 6032182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 6033182999Smav consumers++; 6034182999Smav } 6035182999Smav } 6036182999Smav /* The only exception is if real HP redirection is configured 6037182999Smav and this is a duplication point. 6038182999Smav XXX: Actually exception is not completely correct. 6039182999Smav XXX: Duplication point check is not perfect. */ 6040182999Smav if ((consumers == 2 && (w->bindas < 0 || 6041182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 6042182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 6043182999Smav consumers > 2) 6044182999Smav return; 6045182999Smav 6046182999Smav /* Else use it's output mixer. */ 6047182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 6048182999Smav HDA_CTL_OUT, -1, 1); 6049182999Smav if (ctl) { 6050182999Smav if (HDA_CTL_GIVE(ctl) & need) 6051182999Smav ctl->ossmask |= (1 << ossdev); 6052182999Smav else 6053182999Smav ctl->possmask |= (1 << ossdev); 6054182999Smav need &= ~HDA_CTL_GIVE(ctl); 6055182999Smav } 6056182999Smav } 6057182999Smav 6058182999Smav /* We must not traverse pin */ 6059182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6060182999Smav depth > 0) 6061182999Smav return; 6062182999Smav 6063162922Sariff for (i = 0; i < w->nconns; i++) { 6064182999Smav int tneed = need; 6065182999Smav if (w->connsenable[i] == 0) 6066162922Sariff continue; 6067202789Smav if (index >= 0 && i != index) 6068202789Smav continue; 6069182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 6070182999Smav HDA_CTL_IN, i, 1); 6071182999Smav if (ctl) { 6072182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 6073182999Smav ctl->ossmask |= (1 << ossdev); 6074182999Smav else 6075182999Smav ctl->possmask |= (1 << ossdev); 6076182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 6077162922Sariff } 6078202789Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev, 6079182999Smav depth + 1, tneed); 6080162922Sariff } 6081162922Sariff} 6082162922Sariff 6083182999Smav/* 6084182999Smav * Assign OSS names to sound sources 6085182999Smav */ 6086182999Smavstatic void 6087182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 6088162922Sariff{ 6089182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6090182999Smav struct hdac_widget *w; 6091182999Smav int i, j; 6092182999Smav int type = -1, use, used = 0; 6093182999Smav static const int types[7][13] = { 6094182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6095182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 6096182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 6097182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 6098182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 6099182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 6100182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 6101182999Smav -1 }, /* digital */ 6102182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6103182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 6104182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 6105182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 6106182999Smav -1 } /* others */ 6107182999Smav }; 6108162922Sariff 6109182999Smav /* Surely known names */ 6110162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6111162922Sariff w = hdac_widget_get(devinfo, i); 6112162922Sariff if (w == NULL || w->enable == 0) 6113162922Sariff continue; 6114182999Smav if (w->bindas == -1) 6115182999Smav continue; 6116182999Smav use = -1; 6117182999Smav switch (w->type) { 6118182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 6119182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6120182999Smav break; 6121182999Smav type = -1; 6122182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6123182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 6124182999Smav type = 0; 6125182999Smav break; 6126182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6127182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 6128182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 6129182999Smav break; 6130182999Smav type = 1; 6131182999Smav break; 6132182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 6133182999Smav type = 3; 6134182999Smav break; 6135182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6136182999Smav type = 4; 6137182999Smav break; 6138182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 6139182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 6140182999Smav type = 5; 6141182999Smav break; 6142182999Smav } 6143182999Smav if (type == -1) 6144182999Smav break; 6145182999Smav j = 0; 6146182999Smav while (types[type][j] >= 0 && 6147182999Smav (used & (1 << types[type][j])) != 0) { 6148182999Smav j++; 6149182999Smav } 6150182999Smav if (types[type][j] >= 0) 6151182999Smav use = types[type][j]; 6152182999Smav break; 6153182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 6154182999Smav use = SOUND_MIXER_PCM; 6155182999Smav break; 6156182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 6157182999Smav use = SOUND_MIXER_SPEAKER; 6158182999Smav break; 6159182999Smav default: 6160182999Smav break; 6161182999Smav } 6162182999Smav if (use >= 0) { 6163182999Smav w->ossdev = use; 6164182999Smav used |= (1 << use); 6165182999Smav } 6166182999Smav } 6167182999Smav /* Semi-known names */ 6168182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6169182999Smav w = hdac_widget_get(devinfo, i); 6170182999Smav if (w == NULL || w->enable == 0) 6171182999Smav continue; 6172182999Smav if (w->ossdev >= 0) 6173182999Smav continue; 6174182999Smav if (w->bindas == -1) 6175182999Smav continue; 6176162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6177162922Sariff continue; 6178182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6179162922Sariff continue; 6180182999Smav type = -1; 6181182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6182182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 6183182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6184182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 6185182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 6186182999Smav type = 0; 6187182999Smav break; 6188182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6189182999Smav type = 2; 6190182999Smav break; 6191182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 6192182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 6193182999Smav type = 5; 6194182999Smav break; 6195182999Smav } 6196182999Smav if (type == -1) 6197182999Smav break; 6198182999Smav j = 0; 6199182999Smav while (types[type][j] >= 0 && 6200182999Smav (used & (1 << types[type][j])) != 0) { 6201182999Smav j++; 6202182999Smav } 6203182999Smav if (types[type][j] >= 0) { 6204182999Smav w->ossdev = types[type][j]; 6205182999Smav used |= (1 << types[type][j]); 6206182999Smav } 6207182999Smav } 6208182999Smav /* Others */ 6209182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6210182999Smav w = hdac_widget_get(devinfo, i); 6211182999Smav if (w == NULL || w->enable == 0) 6212162922Sariff continue; 6213182999Smav if (w->ossdev >= 0) 6214182999Smav continue; 6215182999Smav if (w->bindas == -1) 6216182999Smav continue; 6217182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6218182999Smav continue; 6219182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6220182999Smav continue; 6221182999Smav j = 0; 6222182999Smav while (types[6][j] >= 0 && 6223182999Smav (used & (1 << types[6][j])) != 0) { 6224182999Smav j++; 6225162922Sariff } 6226182999Smav if (types[6][j] >= 0) { 6227182999Smav w->ossdev = types[6][j]; 6228182999Smav used |= (1 << types[6][j]); 6229182999Smav } 6230162922Sariff } 6231162922Sariff} 6232162922Sariff 6233162922Sariffstatic void 6234162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 6235162922Sariff{ 6236182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6237182999Smav int j, res; 6238162922Sariff 6239182999Smav /* Trace all associations in order of their numbers, */ 6240182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 6241182999Smav if (as[j].enable == 0) 6242182999Smav continue; 6243163057Sariff HDA_BOOTVERBOSE( 6244162922Sariff device_printf(devinfo->codec->sc->dev, 6245182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6246162922Sariff ); 6247182999Smav if (as[j].dir == HDA_CTL_OUT) { 6248182999Smavretry: 6249182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6250182999Smav if (res == 0 && as[j].hpredir >= 0 && 6251182999Smav as[j].fakeredir == 0) { 6252182999Smav /* If codec can't do analog HP redirection 6253182999Smav try to make it using one more DAC. */ 6254182999Smav as[j].fakeredir = 1; 6255182999Smav goto retry; 6256182999Smav } 6257182999Smav } else { 6258182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6259182999Smav } 6260182999Smav if (res) { 6261182999Smav HDA_BOOTVERBOSE( 6262182999Smav device_printf(devinfo->codec->sc->dev, 6263188510Smav "Association %d (%d) trace succeeded\n", 6264182999Smav j, as[j].index); 6265182999Smav ); 6266182999Smav } else { 6267182999Smav HDA_BOOTVERBOSE( 6268182999Smav device_printf(devinfo->codec->sc->dev, 6269182999Smav "Association %d (%d) trace failed\n", 6270182999Smav j, as[j].index); 6271182999Smav ); 6272182999Smav as[j].enable = 0; 6273182999Smav } 6274162922Sariff } 6275162922Sariff 6276182999Smav /* Trace mixer and beeper pseudo associations. */ 6277182999Smav hdac_audio_trace_as_extra(devinfo); 6278182999Smav} 6279162922Sariff 6280182999Smavstatic void 6281182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6282182999Smav{ 6283182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6284182999Smav struct hdac_audio_ctl *ctl; 6285202789Smav struct hdac_widget *w, *cw; 6286202789Smav int i, j; 6287162922Sariff 6288182999Smav /* Assign mixers to the tree. */ 6289162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6290162922Sariff w = hdac_widget_get(devinfo, i); 6291162922Sariff if (w == NULL || w->enable == 0) 6292162922Sariff continue; 6293182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6294182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6295182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6296182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6297182999Smav if (w->ossdev < 0) 6298182999Smav continue; 6299182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6300182999Smav w->ossdev, 1, 0, 1); 6301182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6302202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6303182999Smav SOUND_MIXER_RECLEV, 0, 1); 6304182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6305182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6306202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6307182999Smav SOUND_MIXER_VOLUME, 0, 1); 6308162922Sariff } 6309202796Smav if (w->ossdev == SOUND_MIXER_IMIX) { 6310202796Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6311202796Smav w->ossdev, 1, 0, 1)) { 6312202796Smav /* If we are unable to control input monitor 6313202796Smav as source - try to control it as destination. */ 6314202796Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6315202796Smav w->ossdev, 0, 1); 6316202796Smav } 6317202796Smav } 6318202789Smav if (w->pflags & HDA_ADC_MONITOR) { 6319202789Smav for (j = 0; j < w->nconns; j++) { 6320202789Smav if (!w->connsenable[j]) 6321202789Smav continue; 6322202789Smav cw = hdac_widget_get(devinfo, w->conns[j]); 6323202789Smav if (cw == NULL || cw->enable == 0) 6324202789Smav continue; 6325202789Smav if (cw->bindas == -1) 6326202789Smav continue; 6327202789Smav if (cw->bindas >= 0 && 6328202789Smav as[cw->bindas].dir != HDA_CTL_IN) 6329202789Smav continue; 6330202789Smav hdac_audio_ctl_dest_amp(devinfo, 6331202796Smav w->nid, j, SOUND_MIXER_IGAIN, 0, 1); 6332202789Smav } 6333202789Smav } 6334162922Sariff } 6335182999Smav /* Treat unrequired as possible. */ 6336182999Smav i = 0; 6337182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6338182999Smav if (ctl->ossmask == 0) 6339182999Smav ctl->ossmask = ctl->possmask; 6340182999Smav } 6341182999Smav} 6342162922Sariff 6343182999Smavstatic void 6344182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6345182999Smav{ 6346182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6347182999Smav struct hdac_widget *w; 6348182999Smav uint32_t pincap; 6349182999Smav int i; 6350182999Smav 6351182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6352182999Smav w = &devinfo->widget[i]; 6353182999Smav if (w == NULL) 6354162922Sariff continue; 6355182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6356162922Sariff continue; 6357182999Smav 6358182999Smav pincap = w->wclass.pin.cap; 6359182999Smav 6360182999Smav /* Disable everything. */ 6361182999Smav w->wclass.pin.ctrl &= ~( 6362182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6363182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6364182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6365182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6366182999Smav 6367182999Smav if (w->enable == 0 || 6368182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6369182999Smav /* Pin is unused so left it disabled. */ 6370182999Smav continue; 6371182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6372182999Smav /* Input pin, configure for input. */ 6373182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6374182999Smav w->wclass.pin.ctrl |= 6375182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6376182999Smav 6377182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6378182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6379182999Smav w->wclass.pin.ctrl |= 6380182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6381182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6382182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6383182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6384182999Smav w->wclass.pin.ctrl |= 6385182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6386182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6387182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6388182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6389182999Smav w->wclass.pin.ctrl |= 6390182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6391182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6392182999Smav } else { 6393182999Smav /* Output pin, configure for output. */ 6394182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6395182999Smav w->wclass.pin.ctrl |= 6396182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6397182999Smav 6398182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6399182999Smav (w->wclass.pin.config & 6400182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6401182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6402182999Smav w->wclass.pin.ctrl |= 6403182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6404182999Smav 6405182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6406182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6407182999Smav w->wclass.pin.ctrl |= 6408182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6409182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6410182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6411182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6412182999Smav w->wclass.pin.ctrl |= 6413182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6414182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6415182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6416182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6417182999Smav w->wclass.pin.ctrl |= 6418182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6419182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6420182999Smav } 6421162922Sariff } 6422162922Sariff} 6423162922Sariff 6424162922Sariffstatic void 6425187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6426187154Smav{ 6427187154Smav struct hdac_audio_ctl *ctl; 6428187154Smav int i, z; 6429187154Smav 6430187154Smav i = 0; 6431187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6432187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6433187154Smav /* Mute disabled and mixer controllable controls. 6434187154Smav * Last will be initialized by mixer_init(). 6435187154Smav * This expected to reduce click on startup. */ 6436187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6437187154Smav continue; 6438187154Smav } 6439187154Smav /* Init fixed controls to 0dB amplification. */ 6440187154Smav z = ctl->offset; 6441187154Smav if (z > ctl->step) 6442187154Smav z = ctl->step; 6443187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6444187154Smav } 6445187154Smav} 6446187154Smav 6447187154Smavstatic void 6448182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6449162922Sariff{ 6450162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6451162922Sariff struct hdac_widget *w; 6452164750Sariff nid_t cad; 6453182999Smav uint32_t gdata, gmask, gdir; 6454182999Smav int commitgpio, numgpio; 6455164750Sariff int i; 6456162922Sariff 6457162922Sariff cad = devinfo->codec->cad; 6458162922Sariff 6459182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6460182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6461182999Smav 0x7e7, 0), cad); 6462169277Sariff 6463187154Smav /* Commit controls. */ 6464187154Smav hdac_audio_ctl_commit(devinfo); 6465187154Smav 6466187154Smav /* Commit selectors, pins and EAPD. */ 6467187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6468187154Smav w = &devinfo->widget[i]; 6469187154Smav if (w == NULL) 6470187154Smav continue; 6471187154Smav if (w->selconn == -1) 6472187154Smav w->selconn = 0; 6473187154Smav if (w->nconns > 0) 6474187154Smav hdac_widget_connection_select(w, w->selconn); 6475187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6476187154Smav hdac_command(sc, 6477187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6478187154Smav w->wclass.pin.ctrl), cad); 6479187154Smav } 6480187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6481187154Smav uint32_t val; 6482187154Smav 6483187154Smav val = w->param.eapdbtl; 6484187154Smav if (devinfo->function.audio.quirks & 6485187154Smav HDA_QUIRK_EAPDINV) 6486187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6487187154Smav hdac_command(sc, 6488187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6489187154Smav val), cad); 6490187154Smav } 6491187154Smav } 6492187154Smav 6493187154Smav /* Commit GPIOs. */ 6494182999Smav gdata = 0; 6495182999Smav gmask = 0; 6496182999Smav gdir = 0; 6497182999Smav commitgpio = 0; 6498182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6499182999Smav devinfo->function.audio.gpio); 6500166796Sariff 6501182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6502182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6503182999Smav else { 6504182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6505182999Smav if (!(devinfo->function.audio.quirks & 6506182999Smav (1 << i))) 6507182999Smav continue; 6508182999Smav if (commitgpio == 0) { 6509182999Smav commitgpio = 1; 6510182999Smav HDA_BOOTVERBOSE( 6511182999Smav gdata = hdac_command(sc, 6512182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6513182999Smav devinfo->nid), cad); 6514182999Smav gmask = hdac_command(sc, 6515182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6516182999Smav devinfo->nid), cad); 6517182999Smav gdir = hdac_command(sc, 6518182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6519182999Smav devinfo->nid), cad); 6520182999Smav device_printf(sc->dev, 6521182999Smav "GPIO init: data=0x%08x " 6522182999Smav "mask=0x%08x dir=0x%08x\n", 6523182999Smav gdata, gmask, gdir); 6524182999Smav gdata = 0; 6525182999Smav gmask = 0; 6526182999Smav gdir = 0; 6527182999Smav ); 6528165039Sariff } 6529182999Smav gdata |= 1 << i; 6530182999Smav gmask |= 1 << i; 6531182999Smav gdir |= 1 << i; 6532165039Sariff } 6533182999Smav } 6534165039Sariff 6535182999Smav if (commitgpio != 0) { 6536182999Smav HDA_BOOTVERBOSE( 6537182999Smav device_printf(sc->dev, 6538182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6539182999Smav "dir=0x%08x\n", 6540182999Smav gdata, gmask, gdir); 6541182999Smav ); 6542182999Smav hdac_command(sc, 6543182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6544182999Smav gmask), cad); 6545182999Smav hdac_command(sc, 6546182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6547182999Smav gdir), cad); 6548182999Smav hdac_command(sc, 6549182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6550182999Smav gdata), cad); 6551162922Sariff } 6552162922Sariff} 6553162922Sariff 6554162922Sariffstatic void 6555182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6556182999Smav{ 6557182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6558182999Smav nid_t cad = devinfo->codec->cad; 6559182999Smav int i; 6560182999Smav 6561182999Smav hdac_command(sc, 6562182999Smav HDA_CMD_SET_POWER_STATE(cad, 6563182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6564182999Smav cad); 6565182999Smav DELAY(100); 6566182999Smav 6567182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6568182999Smav hdac_command(sc, 6569182999Smav HDA_CMD_SET_POWER_STATE(cad, 6570182999Smav i, HDA_CMD_POWER_STATE_D0), 6571182999Smav cad); 6572182999Smav } 6573182999Smav DELAY(1000); 6574182999Smav} 6575182999Smav 6576162922Sariffstatic int 6577182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6578162922Sariff{ 6579182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6580182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6581162922Sariff struct hdac_widget *w; 6582182999Smav uint32_t cap, fmtcap, pcmcap; 6583202127Smav int i, j, ret, channels, onlystereo; 6584202127Smav uint16_t pinset; 6585162922Sariff 6586162922Sariff ch->caps = hdac_caps; 6587162922Sariff ch->caps.fmtlist = ch->fmtlist; 6588162922Sariff ch->bit16 = 1; 6589162922Sariff ch->bit32 = 0; 6590162922Sariff ch->pcmrates[0] = 48000; 6591162922Sariff ch->pcmrates[1] = 0; 6592162922Sariff 6593162922Sariff ret = 0; 6594202127Smav channels = 0; 6595202127Smav onlystereo = 1; 6596202127Smav pinset = 0; 6597162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6598162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6599162922Sariff 6600202127Smav for (i = 0; i < 16; i++) { 6601182999Smav /* Check as is correct */ 6602182999Smav if (ch->as < 0) 6603182999Smav break; 6604182999Smav /* Cound only present DACs */ 6605182999Smav if (as[ch->as].dacs[i] <= 0) 6606162922Sariff continue; 6607182999Smav /* Ignore duplicates */ 6608182999Smav for (j = 0; j < ret; j++) { 6609182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6610182999Smav break; 6611182999Smav } 6612182999Smav if (j < ret) 6613162922Sariff continue; 6614182999Smav 6615182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6616182999Smav if (w == NULL || w->enable == 0) 6617182999Smav continue; 6618162922Sariff cap = w->param.supp_stream_formats; 6619182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6620182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6621162922Sariff continue; 6622202127Smav /* Many CODECs does not declare AC3 support on SPDIF. 6623182999Smav I don't beleave that they doesn't support it! */ 6624182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6625182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6626164614Sariff if (ret == 0) { 6627182999Smav fmtcap = cap; 6628164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6629164614Sariff } else { 6630182999Smav fmtcap &= cap; 6631164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6632164614Sariff } 6633182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6634202127Smav /* Do not count redirection pin/dac channels. */ 6635202127Smav if (i == 15 && as[ch->as].hpredir >= 0) 6636202127Smav continue; 6637202127Smav channels += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 6638202127Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) != 1) 6639202127Smav onlystereo = 0; 6640202127Smav pinset |= (1 << i); 6641162922Sariff } 6642162922Sariff ch->io[ret] = -1; 6643162922Sariff 6644202127Smav if (as[ch->as].fakeredir) 6645202127Smav ret--; 6646202127Smav /* Standard speaks only about stereo pins and playback, ... */ 6647202127Smav if ((!onlystereo) || as[ch->as].dir != HDA_CTL_OUT) 6648202127Smav pinset = 0; 6649202127Smav /* ..., but there it gives us info about speakers layout. */ 6650202127Smav as[ch->as].pinset = pinset; 6651202127Smav 6652162922Sariff ch->supp_stream_formats = fmtcap; 6653162922Sariff ch->supp_pcm_size_rate = pcmcap; 6654162922Sariff 6655162922Sariff /* 6656162922Sariff * 8bit = 0 6657162922Sariff * 16bit = 1 6658162922Sariff * 20bit = 2 6659162922Sariff * 24bit = 3 6660162922Sariff * 32bit = 4 6661162922Sariff */ 6662162922Sariff if (ret > 0) { 6663162922Sariff i = 0; 6664182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6665182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6666182999Smav ch->bit16 = 1; 6667182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6668182999Smav ch->bit16 = 0; 6669182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6670182999Smav ch->bit32 = 4; 6671182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6672182999Smav ch->bit32 = 3; 6673182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6674182999Smav ch->bit32 = 2; 6675202127Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) { 6676202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 1, 0); 6677202127Smav if (ch->bit32) 6678202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 1, 0); 6679182999Smav } 6680202127Smav if (channels >= 2) { 6681202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 2, 0); 6682202127Smav if (ch->bit32) 6683202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 2, 0); 6684202127Smav } 6685202127Smav if (channels == 4 || /* Any 4-channel */ 6686202127Smav pinset == 0x0007 || /* 5.1 */ 6687202127Smav pinset == 0x0013 || /* 5.1 */ 6688202127Smav pinset == 0x0017) { /* 7.1 */ 6689202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 4, 0); 6690202127Smav if (ch->bit32) 6691202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 0); 6692202127Smav } 6693202127Smav if (channels == 6 || /* Any 6-channel */ 6694202127Smav pinset == 0x0017) { /* 7.1 */ 6695202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 1); 6696202127Smav if (ch->bit32) 6697202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 1); 6698202127Smav } 6699202127Smav if (channels == 8) { /* Any 8-channel */ 6700202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 8, 1); 6701202127Smav if (ch->bit32) 6702202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 8, 1); 6703202127Smav } 6704162922Sariff } 6705182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6706193640Sariff ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 2, 0); 6707182999Smav } 6708162922Sariff ch->fmtlist[i] = 0; 6709162922Sariff i = 0; 6710182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6711162922Sariff ch->pcmrates[i++] = 8000; 6712182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6713162922Sariff ch->pcmrates[i++] = 11025; 6714182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6715162922Sariff ch->pcmrates[i++] = 16000; 6716182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6717162922Sariff ch->pcmrates[i++] = 22050; 6718182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6719162922Sariff ch->pcmrates[i++] = 32000; 6720182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6721162922Sariff ch->pcmrates[i++] = 44100; 6722182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6723162922Sariff ch->pcmrates[i++] = 48000; 6724182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6725162922Sariff ch->pcmrates[i++] = 88200; 6726182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6727162922Sariff ch->pcmrates[i++] = 96000; 6728182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6729162922Sariff ch->pcmrates[i++] = 176400; 6730182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6731162922Sariff ch->pcmrates[i++] = 192000; 6732182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6733162922Sariff ch->pcmrates[i] = 0; 6734162922Sariff if (i > 0) { 6735162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6736162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6737162922Sariff } 6738162922Sariff } 6739162922Sariff 6740162922Sariff return (ret); 6741162922Sariff} 6742162922Sariff 6743162922Sariffstatic void 6744185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6745185225Smav{ 6746185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6747185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6748185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6749185225Smav 6750185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6751185225Smav if (as[i].enable == 0) 6752185225Smav continue; 6753185225Smav if (as[i].dir == HDA_CTL_IN) { 6754185225Smav if (as[i].digital) 6755185225Smav drdev++; 6756185225Smav else 6757185225Smav ardev++; 6758185225Smav } else { 6759185225Smav if (as[i].digital) 6760185225Smav dpdev++; 6761185225Smav else 6762185225Smav apdev++; 6763185225Smav } 6764185225Smav } 6765185225Smav devinfo->function.audio.num_devs = 6766185225Smav max(ardev, apdev) + max(drdev, dpdev); 6767185225Smav devinfo->function.audio.devs = 6768185225Smav (struct hdac_pcm_devinfo *)malloc( 6769185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6770185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6771185225Smav if (devinfo->function.audio.devs == NULL) { 6772185225Smav device_printf(sc->dev, 6773185225Smav "Unable to allocate memory for devices\n"); 6774185225Smav return; 6775185225Smav } 6776185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6777185225Smav devinfo->function.audio.devs[i].index = i; 6778185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6779185225Smav devinfo->function.audio.devs[i].play = -1; 6780185225Smav devinfo->function.audio.devs[i].rec = -1; 6781197611Smav devinfo->function.audio.devs[i].digital = 255; 6782185225Smav } 6783185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6784185225Smav if (as[i].enable == 0) 6785185225Smav continue; 6786185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6787197611Smav if (devinfo->function.audio.devs[j].digital != 255 && 6788197640Smav (!devinfo->function.audio.devs[j].digital) != 6789197611Smav (!as[i].digital)) 6790185225Smav continue; 6791185225Smav if (as[i].dir == HDA_CTL_IN) { 6792185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6793185225Smav continue; 6794185225Smav devinfo->function.audio.devs[j].rec 6795185225Smav = as[i].chan; 6796185225Smav } else { 6797185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6798185225Smav continue; 6799185225Smav devinfo->function.audio.devs[j].play 6800185225Smav = as[i].chan; 6801185225Smav } 6802185225Smav sc->chans[as[i].chan].pdevinfo = 6803185225Smav &devinfo->function.audio.devs[j]; 6804185225Smav devinfo->function.audio.devs[j].digital = 6805185225Smav as[i].digital; 6806185225Smav break; 6807185225Smav } 6808185225Smav } 6809185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6810185225Smav struct hdac_pcm_devinfo *pdevinfo = 6811185225Smav &devinfo->function.audio.devs[i]; 6812185225Smav pdevinfo->dev = 6813185225Smav device_add_child(sc->dev, "pcm", -1); 6814185225Smav device_set_ivars(pdevinfo->dev, 6815185225Smav (void *)pdevinfo); 6816185225Smav } 6817185225Smav} 6818185225Smav 6819185225Smavstatic void 6820182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6821162922Sariff{ 6822182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6823162922Sariff struct hdac_audio_ctl *ctl; 6824162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6825182999Smav char buf[64]; 6826182999Smav int i, j, printed; 6827162922Sariff 6828162922Sariff if (flag == 0) { 6829182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6830162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6831202796Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IGAIN | 6832202796Smav SOUND_MASK_OGAIN | SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6833162922Sariff } 6834162922Sariff 6835182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6836182999Smav if ((flag & (1 << j)) == 0) 6837162922Sariff continue; 6838182999Smav i = 0; 6839182999Smav printed = 0; 6840182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6841182999Smav if (ctl->enable == 0 || 6842182999Smav ctl->widget->enable == 0) 6843182999Smav continue; 6844182999Smav if (!((pdevinfo->play >= 0 && 6845182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6846182999Smav (pdevinfo->rec >= 0 && 6847182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6848182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6849182999Smav continue; 6850182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6851182999Smav continue; 6852182999Smav 6853182999Smav if (printed == 0) { 6854182999Smav device_printf(pdevinfo->dev, "\n"); 6855182999Smav if (banner != NULL) { 6856182999Smav device_printf(pdevinfo->dev, "%s", banner); 6857182999Smav } else { 6858182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6859182999Smav } 6860182999Smav printf(" (OSS: %s)\n", 6861182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6862182999Smav buf, sizeof(buf))); 6863182999Smav device_printf(pdevinfo->dev, " |\n"); 6864182999Smav printed = 1; 6865162922Sariff } 6866182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6867182999Smav ctl->widget->nid, 6868182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6869182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6870182999Smav printf(" %2d): ", ctl->index); 6871182999Smav else 6872182999Smav printf("): "); 6873182999Smav if (ctl->step > 0) { 6874182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6875182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6876182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6877182999Smav ctl->step + 1, 6878182999Smav ctl->mute?" + mute":""); 6879182999Smav } else 6880182999Smav printf("%s\n", ctl->mute?"mute":""); 6881162922Sariff } 6882162922Sariff } 6883162922Sariff} 6884162922Sariff 6885162922Sariffstatic void 6886182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6887162922Sariff{ 6888162922Sariff uint32_t cap; 6889162922Sariff 6890162922Sariff cap = fcap; 6891162922Sariff if (cap != 0) { 6892182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6893183097Smav device_printf(dev, " "); 6894162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6895162922Sariff printf(" AC3"); 6896162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6897162922Sariff printf(" FLOAT32"); 6898162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6899162922Sariff printf(" PCM"); 6900162922Sariff printf("\n"); 6901162922Sariff } 6902162922Sariff cap = pcmcap; 6903162922Sariff if (cap != 0) { 6904182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6905183097Smav device_printf(dev, " "); 6906162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6907162922Sariff printf(" 8"); 6908162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6909162922Sariff printf(" 16"); 6910162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6911162922Sariff printf(" 20"); 6912162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6913162922Sariff printf(" 24"); 6914162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6915162922Sariff printf(" 32"); 6916183097Smav printf(" bits,"); 6917162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6918162922Sariff printf(" 8"); 6919162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6920162922Sariff printf(" 11"); 6921162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6922162922Sariff printf(" 16"); 6923162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6924162922Sariff printf(" 22"); 6925162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6926162922Sariff printf(" 32"); 6927162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6928162922Sariff printf(" 44"); 6929162922Sariff printf(" 48"); 6930162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6931162922Sariff printf(" 88"); 6932162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6933162922Sariff printf(" 96"); 6934162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6935162922Sariff printf(" 176"); 6936162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6937162922Sariff printf(" 192"); 6938183097Smav printf(" KHz\n"); 6939162922Sariff } 6940162922Sariff} 6941162922Sariff 6942162922Sariffstatic void 6943162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6944162922Sariff{ 6945183097Smav uint32_t pincap; 6946162922Sariff 6947162922Sariff pincap = w->wclass.pin.cap; 6948162922Sariff 6949162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6950162922Sariff device_printf(sc->dev, " "); 6951162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6952162922Sariff printf(" ISC"); 6953162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6954162922Sariff printf(" TRQD"); 6955162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6956162922Sariff printf(" PDC"); 6957162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6958162922Sariff printf(" HP"); 6959162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6960162922Sariff printf(" OUT"); 6961162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6962162922Sariff printf(" IN"); 6963162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6964162922Sariff printf(" BAL"); 6965197611Smav if (HDA_PARAM_PIN_CAP_HDMI(pincap)) 6966197611Smav printf(" HDMI"); 6967165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6968165069Sariff printf(" VREF["); 6969165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6970165069Sariff printf(" 50"); 6971165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6972165069Sariff printf(" 80"); 6973165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6974165069Sariff printf(" 100"); 6975165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6976165069Sariff printf(" GROUND"); 6977165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6978165069Sariff printf(" HIZ"); 6979165069Sariff printf(" ]"); 6980165069Sariff } 6981162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6982162922Sariff printf(" EAPD"); 6983197611Smav if (HDA_PARAM_PIN_CAP_DP(pincap)) 6984197611Smav printf(" DP"); 6985197611Smav if (HDA_PARAM_PIN_CAP_HBR(pincap)) 6986197611Smav printf(" HBR"); 6987162922Sariff printf("\n"); 6988162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6989162922Sariff w->wclass.pin.config); 6990162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6991162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6992162922Sariff printf(" HP"); 6993162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6994162922Sariff printf(" IN"); 6995162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6996162922Sariff printf(" OUT"); 6997182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6998182999Smav printf(" VREFs"); 6999162922Sariff printf("\n"); 7000162922Sariff} 7001162922Sariff 7002162922Sariffstatic void 7003182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 7004182999Smav{ 7005182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 7006182999Smav 7007183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 7008182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 7009182999Smav w->nid, conf, 7010182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 7011182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 7012182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 7013182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 7014182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 7015182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 7016182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 7017182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 7018182999Smav (w->enable == 0)?" [DISABLED]":""); 7019182999Smav} 7020182999Smav 7021182999Smavstatic void 7022182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 7023182999Smav{ 7024182999Smav struct hdac_widget *w; 7025182999Smav int i; 7026182999Smav 7027182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7028182999Smav w = hdac_widget_get(devinfo, i); 7029182999Smav if (w == NULL) 7030182999Smav continue; 7031182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7032182999Smav continue; 7033182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7034182999Smav } 7035182999Smav} 7036182999Smav 7037182999Smavstatic void 7038162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 7039162922Sariff{ 7040163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 7041162922Sariff device_printf(sc->dev, " " 7042162922Sariff "mute=%d step=%d size=%d offset=%d\n", 7043162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 7044162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 7045162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 7046162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 7047162922Sariff} 7048162922Sariff 7049162922Sariffstatic void 7050162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 7051162922Sariff{ 7052162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 7053182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 7054162922Sariff struct hdac_widget *w, *cw; 7055182999Smav char buf[64]; 7056162922Sariff int i, j; 7057162922Sariff 7058162922Sariff device_printf(sc->dev, "\n"); 7059162922Sariff device_printf(sc->dev, "Default Parameter\n"); 7060162922Sariff device_printf(sc->dev, "-----------------\n"); 7061182999Smav hdac_dump_audio_formats(sc->dev, 7062162922Sariff devinfo->function.audio.supp_stream_formats, 7063162922Sariff devinfo->function.audio.supp_pcm_size_rate); 7064162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 7065162922Sariff devinfo->function.audio.inamp_cap); 7066162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 7067162922Sariff devinfo->function.audio.outamp_cap); 7068162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7069162922Sariff w = hdac_widget_get(devinfo, i); 7070162922Sariff if (w == NULL) { 7071162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 7072162922Sariff continue; 7073162922Sariff } 7074162922Sariff device_printf(sc->dev, "\n"); 7075183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 7076162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 7077183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 7078183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 7079162922Sariff w->param.widget_cap); 7080183097Smav if (w->param.widget_cap & 0x0ee1) { 7081183097Smav device_printf(sc->dev, " "); 7082183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 7083183097Smav printf(" LRSWAP"); 7084183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 7085183097Smav printf(" PWR"); 7086183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 7087183097Smav printf(" DIGITAL"); 7088183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 7089183097Smav printf(" UNSOL"); 7090183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 7091183097Smav printf(" PROC"); 7092183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 7093183097Smav printf(" STRIPE"); 7094197611Smav j = HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap); 7095197611Smav if (j == 1) 7096183097Smav printf(" STEREO"); 7097197611Smav else if (j > 1) 7098197611Smav printf(" %dCH", j + 1); 7099183097Smav printf("\n"); 7100183097Smav } 7101183097Smav if (w->bindas != -1) { 7102183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 7103183097Smav w->bindas, w->bindseqmask); 7104183097Smav } 7105183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 7106183097Smav device_printf(sc->dev, " OSS: %s", 7107183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 7108183097Smav if (w->ossdev >= 0) 7109183097Smav printf(" (%s)", ossname[w->ossdev]); 7110183097Smav printf("\n"); 7111183097Smav } 7112162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 7113162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 7114182999Smav hdac_dump_audio_formats(sc->dev, 7115162922Sariff w->param.supp_stream_formats, 7116162922Sariff w->param.supp_pcm_size_rate); 7117162922Sariff } else if (w->type == 7118162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7119162922Sariff hdac_dump_pin(sc, w); 7120162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 7121162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 7122162922Sariff w->param.eapdbtl); 7123163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 7124163057Sariff w->param.outamp_cap != 0) 7125162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 7126163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 7127163057Sariff w->param.inamp_cap != 0) 7128162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 7129183097Smav if (w->nconns > 0) { 7130183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 7131182999Smav device_printf(sc->dev, " |\n"); 7132183097Smav } 7133162922Sariff for (j = 0; j < w->nconns; j++) { 7134162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 7135182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 7136182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 7137162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 7138162922Sariff if (cw == NULL) 7139162922Sariff printf(" [UNKNOWN]"); 7140162922Sariff else if (cw->enable == 0) 7141162922Sariff printf(" [DISABLED]"); 7142162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 7143162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 7144162922Sariff printf(" (selected)"); 7145162922Sariff printf("\n"); 7146162922Sariff } 7147162922Sariff } 7148162922Sariff 7149162922Sariff} 7150162922Sariff 7151182999Smavstatic void 7152182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 7153163057Sariff{ 7154182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7155163057Sariff struct hdac_widget *w, *cw; 7156182999Smav char buf[64]; 7157182999Smav int i, printed = 0; 7158163057Sariff 7159163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 7160182999Smav return; 7161163057Sariff 7162163057Sariff w = hdac_widget_get(devinfo, nid); 7163182999Smav if (w == NULL || w->enable == 0) 7164182999Smav return; 7165163057Sariff 7166182999Smav if (depth == 0) 7167182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 7168182999Smav else 7169182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 7170182999Smav printf("nid=%d [%s]", w->nid, w->name); 7171163057Sariff 7172182999Smav if (depth > 0) { 7173182999Smav if (w->ossmask == 0) { 7174182999Smav printf("\n"); 7175182999Smav return; 7176163057Sariff } 7177182999Smav printf(" [src: %s]", 7178182999Smav hdac_audio_ctl_ossmixer_mask2allname( 7179182999Smav w->ossmask, buf, sizeof(buf))); 7180182999Smav if (w->ossdev >= 0) { 7181182999Smav printf("\n"); 7182182999Smav return; 7183182999Smav } 7184163057Sariff } 7185182999Smav printf("\n"); 7186182999Smav 7187182999Smav for (i = 0; i < w->nconns; i++) { 7188182999Smav if (w->connsenable[i] == 0) 7189182999Smav continue; 7190182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 7191182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 7192182999Smav continue; 7193182999Smav if (printed == 0) { 7194182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 7195182999Smav printed = 1; 7196182999Smav } 7197182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 7198182999Smav } 7199163057Sariff 7200163057Sariff} 7201163057Sariff 7202162922Sariffstatic void 7203182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 7204162922Sariff{ 7205182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7206182999Smav struct hdac_softc *sc = devinfo->codec->sc; 7207202736Smav struct hdac_audio_as *as; 7208163057Sariff struct hdac_widget *w; 7209163057Sariff int i, printed = 0; 7210163057Sariff 7211182999Smav if (pdevinfo->play < 0) 7212182999Smav return; 7213182999Smav 7214202736Smav as = &devinfo->function.audio.as[sc->chans[pdevinfo->play].as]; 7215202736Smav for (i = 0; i < 16; i++) { 7216202736Smav if (as->pins[i] <= 0) 7217202736Smav continue; 7218202736Smav w = hdac_widget_get(devinfo, as->pins[i]); 7219163057Sariff if (w == NULL || w->enable == 0) 7220163057Sariff continue; 7221163057Sariff if (printed == 0) { 7222163057Sariff printed = 1; 7223182999Smav device_printf(pdevinfo->dev, "\n"); 7224182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7225163057Sariff } 7226182999Smav device_printf(pdevinfo->dev, "\n"); 7227202736Smav hdac_dump_dst_nid(pdevinfo, as->pins[i], 0); 7228163057Sariff } 7229162922Sariff} 7230162922Sariff 7231162922Sariffstatic void 7232182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 7233162922Sariff{ 7234182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7235162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 7236182999Smav struct hdac_widget *w; 7237182999Smav int i; 7238162922Sariff int printed = 0; 7239162922Sariff 7240182999Smav if (pdevinfo->rec < 0) 7241182999Smav return; 7242182999Smav 7243162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7244162922Sariff w = hdac_widget_get(devinfo, i); 7245162922Sariff if (w == NULL || w->enable == 0) 7246162922Sariff continue; 7247182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 7248162922Sariff continue; 7249182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 7250182999Smav continue; 7251162922Sariff if (printed == 0) { 7252162922Sariff printed = 1; 7253182999Smav device_printf(pdevinfo->dev, "\n"); 7254182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7255162922Sariff } 7256182999Smav device_printf(pdevinfo->dev, "\n"); 7257182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7258182999Smav } 7259182999Smav} 7260182999Smav 7261182999Smavstatic void 7262182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 7263182999Smav{ 7264182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7265182999Smav struct hdac_widget *w; 7266182999Smav int i; 7267182999Smav int printed = 0; 7268182999Smav 7269182999Smav if (pdevinfo->index != 0) 7270182999Smav return; 7271182999Smav 7272182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7273182999Smav w = hdac_widget_get(devinfo, i); 7274182999Smav if (w == NULL || w->enable == 0) 7275182999Smav continue; 7276202789Smav if (w->ossdev != SOUND_MIXER_IMIX) 7277182999Smav continue; 7278182999Smav if (printed == 0) { 7279182999Smav printed = 1; 7280182999Smav device_printf(pdevinfo->dev, "\n"); 7281182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 7282162922Sariff } 7283182999Smav device_printf(pdevinfo->dev, "\n"); 7284182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7285162922Sariff } 7286162922Sariff} 7287162922Sariff 7288162922Sariffstatic void 7289182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 7290162922Sariff{ 7291182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7292162922Sariff nid_t *nids; 7293182999Smav int i; 7294162922Sariff 7295182999Smav if (pdevinfo->play >= 0) { 7296182999Smav i = pdevinfo->play; 7297182999Smav device_printf(pdevinfo->dev, "\n"); 7298182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7299182999Smav device_printf(pdevinfo->dev, "\n"); 7300182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7301182999Smav sc->chans[i].supp_pcm_size_rate); 7302182999Smav device_printf(pdevinfo->dev, " DAC:"); 7303182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7304162922Sariff printf(" %d", *nids); 7305162922Sariff printf("\n"); 7306162922Sariff } 7307182999Smav if (pdevinfo->rec >= 0) { 7308182999Smav i = pdevinfo->rec; 7309182999Smav device_printf(pdevinfo->dev, "\n"); 7310182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7311182999Smav device_printf(pdevinfo->dev, "\n"); 7312182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7313182999Smav sc->chans[i].supp_pcm_size_rate); 7314182999Smav device_printf(pdevinfo->dev, " ADC:"); 7315182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7316162922Sariff printf(" %d", *nids); 7317162922Sariff printf("\n"); 7318162922Sariff } 7319162922Sariff} 7320162922Sariff 7321162922Sariffstatic void 7322163057Sariffhdac_release_resources(struct hdac_softc *sc) 7323163057Sariff{ 7324182999Smav int i, j; 7325163057Sariff 7326163057Sariff if (sc == NULL) 7327163057Sariff return; 7328163057Sariff 7329163057Sariff hdac_lock(sc); 7330169277Sariff sc->polling = 0; 7331169277Sariff sc->poll_ival = 0; 7332170721Sariff callout_stop(&sc->poll_hda); 7333169277Sariff callout_stop(&sc->poll_hdac); 7334169277Sariff callout_stop(&sc->poll_jack); 7335182999Smav hdac_reset(sc, 0); 7336163057Sariff hdac_unlock(sc); 7337171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7338170721Sariff callout_drain(&sc->poll_hda); 7339169277Sariff callout_drain(&sc->poll_hdac); 7340169277Sariff callout_drain(&sc->poll_jack); 7341163057Sariff 7342169277Sariff hdac_irq_free(sc); 7343169277Sariff 7344182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7345182999Smav if (sc->codecs[i] == NULL) 7346163057Sariff continue; 7347182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7348182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7349182999Smav if (sc->codecs[i]->fgs[j].node_type == 7350182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7351182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7352182999Smav M_HDAC); 7353182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7354182999Smav M_HDAC); 7355182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7356182999Smav M_HDAC); 7357182999Smav } 7358182999Smav } 7359182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7360182999Smav free(sc->codecs[i], M_HDAC); 7361163057Sariff sc->codecs[i] = NULL; 7362163057Sariff } 7363163057Sariff 7364169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7365169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7366169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7367182999Smav for (i = 0; i < sc->num_chans; i++) { 7368182999Smav if (sc->chans[i].blkcnt > 0) 7369182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7370182999Smav } 7371182999Smav free(sc->chans, M_HDAC); 7372167702Sariff if (sc->chan_dmat != NULL) { 7373167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7374167702Sariff sc->chan_dmat = NULL; 7375167702Sariff } 7376163057Sariff hdac_mem_free(sc); 7377169277Sariff snd_mtxfree(sc->lock); 7378163057Sariff} 7379163057Sariff 7380163057Sariff/* This function surely going to make its way into upper level someday. */ 7381163057Sariffstatic void 7382163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7383163057Sariff{ 7384163057Sariff const char *res = NULL; 7385163057Sariff int i = 0, j, k, len, inv; 7386163057Sariff 7387163057Sariff if (on != NULL) 7388163057Sariff *on = 0; 7389163057Sariff if (off != NULL) 7390163057Sariff *off = 0; 7391163057Sariff if (sc == NULL) 7392163057Sariff return; 7393163057Sariff if (resource_string_value(device_get_name(sc->dev), 7394163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7395163057Sariff return; 7396163057Sariff if (!(res != NULL && strlen(res) > 0)) 7397163057Sariff return; 7398163057Sariff HDA_BOOTVERBOSE( 7399182999Smav device_printf(sc->dev, "HDA Config:"); 7400163057Sariff ); 7401163057Sariff for (;;) { 7402163057Sariff while (res[i] != '\0' && 7403163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7404163057Sariff i++; 7405163057Sariff if (res[i] == '\0') { 7406163057Sariff HDA_BOOTVERBOSE( 7407163057Sariff printf("\n"); 7408163057Sariff ); 7409163057Sariff return; 7410163057Sariff } 7411163057Sariff j = i; 7412163057Sariff while (res[j] != '\0' && 7413163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7414163057Sariff j++; 7415163057Sariff len = j - i; 7416163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7417163057Sariff inv = 2; 7418163057Sariff else 7419163057Sariff inv = 0; 7420163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7421163057Sariff if (strncmp(res + i + inv, 7422163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7423163057Sariff continue; 7424163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7425187944Smav continue; 7426163057Sariff HDA_BOOTVERBOSE( 7427163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7428163057Sariff hdac_quirks_tab[k].key); 7429163057Sariff ); 7430163057Sariff if (inv == 0 && on != NULL) 7431163057Sariff *on |= hdac_quirks_tab[k].value; 7432163057Sariff else if (inv != 0 && off != NULL) 7433163057Sariff *off |= hdac_quirks_tab[k].value; 7434163057Sariff break; 7435163057Sariff } 7436163057Sariff i = j; 7437163057Sariff } 7438163057Sariff} 7439163057Sariff 7440164614Sariffstatic int 7441164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7442164614Sariff{ 7443164614Sariff struct hdac_softc *sc; 7444164614Sariff device_t dev; 7445164614Sariff uint32_t ctl; 7446164614Sariff int err, val; 7447164614Sariff 7448164614Sariff dev = oidp->oid_arg1; 7449182999Smav sc = device_get_softc(dev); 7450182999Smav if (sc == NULL) 7451164614Sariff return (EINVAL); 7452164614Sariff hdac_lock(sc); 7453164614Sariff val = sc->polling; 7454164614Sariff hdac_unlock(sc); 7455170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7456164614Sariff 7457169277Sariff if (err != 0 || req->newptr == NULL) 7458164614Sariff return (err); 7459164614Sariff if (val < 0 || val > 1) 7460164614Sariff return (EINVAL); 7461164614Sariff 7462164614Sariff hdac_lock(sc); 7463164614Sariff if (val != sc->polling) { 7464182999Smav if (val == 0) { 7465182999Smav callout_stop(&sc->poll_hda); 7466164614Sariff callout_stop(&sc->poll_hdac); 7467169277Sariff hdac_unlock(sc); 7468182999Smav callout_drain(&sc->poll_hda); 7469169277Sariff callout_drain(&sc->poll_hdac); 7470169277Sariff hdac_lock(sc); 7471164614Sariff sc->polling = 0; 7472182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7473182999Smav ctl |= HDAC_INTCTL_GIE; 7474182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7475164614Sariff } else { 7476182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7477182999Smav ctl &= ~HDAC_INTCTL_GIE; 7478182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7479171141Sariff hdac_unlock(sc); 7480171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7481171141Sariff hdac_lock(sc); 7482164614Sariff sc->polling = 1; 7483182999Smav hdac_poll_reinit(sc); 7484182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7485164614Sariff } 7486164614Sariff } 7487164614Sariff hdac_unlock(sc); 7488164614Sariff 7489164614Sariff return (err); 7490164614Sariff} 7491169277Sariff 7492169277Sariffstatic int 7493169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7494169277Sariff{ 7495169277Sariff struct hdac_softc *sc; 7496169277Sariff device_t dev; 7497169277Sariff int err, val; 7498169277Sariff 7499169277Sariff dev = oidp->oid_arg1; 7500182999Smav sc = device_get_softc(dev); 7501182999Smav if (sc == NULL) 7502169277Sariff return (EINVAL); 7503169277Sariff hdac_lock(sc); 7504169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7505169277Sariff hdac_unlock(sc); 7506170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7507169277Sariff 7508169277Sariff if (err != 0 || req->newptr == NULL) 7509169277Sariff return (err); 7510169277Sariff 7511169277Sariff if (val < 1) 7512169277Sariff val = 1; 7513169277Sariff if (val > 5000) 7514169277Sariff val = 5000; 7515169277Sariff val = ((uint64_t)val * hz) / 1000; 7516169277Sariff if (val < 1) 7517169277Sariff val = 1; 7518169277Sariff if (val > (hz * 5)) 7519169277Sariff val = hz * 5; 7520169277Sariff 7521169277Sariff hdac_lock(sc); 7522169277Sariff sc->poll_ival = val; 7523169277Sariff hdac_unlock(sc); 7524169277Sariff 7525169277Sariff return (err); 7526169277Sariff} 7527169277Sariff 7528169277Sariffstatic int 7529171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7530169277Sariff{ 7531169277Sariff struct hdac_softc *sc; 7532182999Smav struct hdac_codec *codec; 7533169277Sariff struct hdac_devinfo *devinfo; 7534169277Sariff struct hdac_widget *w; 7535169277Sariff device_t dev; 7536182999Smav uint32_t res, pincap, delay; 7537182999Smav int codec_index, fg_index; 7538169277Sariff int i, err, val; 7539169277Sariff nid_t cad; 7540169277Sariff 7541169277Sariff dev = oidp->oid_arg1; 7542182999Smav sc = device_get_softc(dev); 7543182999Smav if (sc == NULL) 7544169277Sariff return (EINVAL); 7545169277Sariff val = 0; 7546170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7547169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7548169277Sariff return (err); 7549182999Smav 7550182999Smav /* XXX: Temporary. For debugging. */ 7551182999Smav if (val == 100) { 7552182999Smav hdac_suspend(dev); 7553182999Smav return (0); 7554182999Smav } else if (val == 101) { 7555182999Smav hdac_resume(dev); 7556182999Smav return (0); 7557182999Smav } 7558182999Smav 7559169277Sariff hdac_lock(sc); 7560182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7561182999Smav codec = sc->codecs[codec_index]; 7562182999Smav if (codec == NULL) 7563169277Sariff continue; 7564182999Smav cad = codec->cad; 7565182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7566182999Smav devinfo = &codec->fgs[fg_index]; 7567182999Smav if (devinfo->node_type != 7568182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7569182999Smav continue; 7570182999Smav 7571182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7572182999Smav codec_index, devinfo->nid); 7573182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7574182999Smav w = hdac_widget_get(devinfo, i); 7575182999Smav if (w == NULL || w->type != 7576182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7577182999Smav continue; 7578182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7579182999Smav pincap = w->wclass.pin.cap; 7580182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7581182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7582182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7583182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7584182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7585182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7586182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7587182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7588182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7589182999Smav delay = 0; 7590182999Smav hdac_command(sc, 7591182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7592182999Smav do { 7593182999Smav res = hdac_command(sc, 7594182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7595182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7596182999Smav break; 7597182999Smav DELAY(10); 7598182999Smav } while (++delay < 10000); 7599182999Smav } else { 7600182999Smav delay = 0; 7601182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7602182999Smav w->nid), cad); 7603182999Smav } 7604182999Smav printf(" Sense: 0x%08x", res); 7605182999Smav if (delay > 0) 7606182999Smav printf(" delay %dus", delay * 10); 7607182999Smav } 7608182999Smav printf("\n"); 7609182999Smav } 7610182999Smav device_printf(dev, 7611182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7612182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7613182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7614182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7615182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7616182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7617182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7618182999Smav device_printf(dev, " GPI:"); 7619171141Sariff res = hdac_command(sc, 7620182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7621182999Smav printf(" data=0x%08x", res); 7622182999Smav res = hdac_command(sc, 7623182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7624182999Smav cad); 7625182999Smav printf(" wake=0x%08x", res); 7626182999Smav res = hdac_command(sc, 7627182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7628182999Smav cad); 7629182999Smav printf(" unsol=0x%08x", res); 7630182999Smav res = hdac_command(sc, 7631182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7632182999Smav printf(" sticky=0x%08x\n", res); 7633182999Smav } 7634182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7635182999Smav device_printf(dev, " GPO:"); 7636182999Smav res = hdac_command(sc, 7637182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7638182999Smav printf(" data=0x%08x\n", res); 7639182999Smav } 7640182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7641182999Smav device_printf(dev, "GPIO:"); 7642182999Smav res = hdac_command(sc, 7643182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7644182999Smav printf(" data=0x%08x", res); 7645182999Smav res = hdac_command(sc, 7646182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7647182999Smav printf(" enable=0x%08x", res); 7648182999Smav res = hdac_command(sc, 7649182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7650182999Smav printf(" direction=0x%08x\n", res); 7651182999Smav res = hdac_command(sc, 7652182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7653182999Smav device_printf(dev, " wake=0x%08x", res); 7654182999Smav res = hdac_command(sc, 7655182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7656182999Smav cad); 7657182999Smav printf(" unsol=0x%08x", res); 7658182999Smav res = hdac_command(sc, 7659182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7660182999Smav printf(" sticky=0x%08x\n", res); 7661182999Smav } 7662171141Sariff } 7663169277Sariff } 7664169277Sariff hdac_unlock(sc); 7665169277Sariff return (0); 7666169277Sariff} 7667164614Sariff 7668163057Sariffstatic void 7669162922Sariffhdac_attach2(void *arg) 7670162922Sariff{ 7671182999Smav struct hdac_codec *codec; 7672162922Sariff struct hdac_softc *sc; 7673162922Sariff struct hdac_audio_ctl *ctl; 7674163057Sariff uint32_t quirks_on, quirks_off; 7675182999Smav int codec_index, fg_index; 7676185225Smav int i, dmaalloc = 0; 7677182999Smav struct hdac_devinfo *devinfo; 7678162922Sariff 7679162922Sariff sc = (struct hdac_softc *)arg; 7680162922Sariff 7681163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7682162922Sariff 7683183097Smav HDA_BOOTHVERBOSE( 7684182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7685163057Sariff quirks_on, quirks_off); 7686163057Sariff ); 7687163057Sariff 7688162922Sariff hdac_lock(sc); 7689162922Sariff 7690162922Sariff /* Remove ourselves from the config hooks */ 7691162922Sariff if (sc->intrhook.ich_func != NULL) { 7692162922Sariff config_intrhook_disestablish(&sc->intrhook); 7693162922Sariff sc->intrhook.ich_func = NULL; 7694162922Sariff } 7695162922Sariff 7696162922Sariff /* Start the corb and rirb engines */ 7697183097Smav HDA_BOOTHVERBOSE( 7698182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7699162922Sariff ); 7700162922Sariff hdac_corb_start(sc); 7701183097Smav HDA_BOOTHVERBOSE( 7702182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7703162922Sariff ); 7704162922Sariff hdac_rirb_start(sc); 7705162922Sariff 7706183097Smav HDA_BOOTHVERBOSE( 7707162922Sariff device_printf(sc->dev, 7708182999Smav "Enabling controller interrupt...\n"); 7709162922Sariff ); 7710182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7711182999Smav HDAC_GCTL_UNSOL); 7712182999Smav if (sc->polling == 0) { 7713164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7714164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7715182999Smav } else { 7716182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7717182999Smav } 7718162922Sariff DELAY(1000); 7719162922Sariff 7720183097Smav HDA_BOOTHVERBOSE( 7721172811Sariff device_printf(sc->dev, 7722182999Smav "Scanning HDA codecs ...\n"); 7723162922Sariff ); 7724182999Smav hdac_scan_codecs(sc); 7725182999Smav 7726182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7727182999Smav codec = sc->codecs[codec_index]; 7728182999Smav if (codec == NULL) 7729182999Smav continue; 7730182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7731182999Smav devinfo = &codec->fgs[fg_index]; 7732183019Smav HDA_BOOTVERBOSE( 7733183019Smav device_printf(sc->dev, "\n"); 7734183097Smav device_printf(sc->dev, 7735183097Smav "Processing %s FG cad=%d nid=%d...\n", 7736183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7737183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7738183097Smav "unknown", 7739183097Smav devinfo->codec->cad, devinfo->nid); 7740183019Smav ); 7741182999Smav if (devinfo->node_type != 7742182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7743183097Smav HDA_BOOTHVERBOSE( 7744182999Smav device_printf(sc->dev, 7745183097Smav "Powering down...\n"); 7746182999Smav ); 7747182999Smav hdac_command(sc, 7748182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7749182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7750182999Smav codec->cad); 7751182999Smav continue; 7752182999Smav } 7753162922Sariff 7754183097Smav HDA_BOOTHVERBOSE( 7755183097Smav device_printf(sc->dev, "Powering up...\n"); 7756182999Smav ); 7757182999Smav hdac_powerup(devinfo); 7758183097Smav HDA_BOOTHVERBOSE( 7759182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7760182999Smav ); 7761182999Smav hdac_audio_parse(devinfo); 7762183097Smav HDA_BOOTHVERBOSE( 7763182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7764182999Smav ); 7765182999Smav hdac_audio_ctl_parse(devinfo); 7766183097Smav HDA_BOOTHVERBOSE( 7767182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7768182999Smav ); 7769182999Smav hdac_vendor_patch_parse(devinfo); 7770182999Smav devinfo->function.audio.quirks |= quirks_on; 7771182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7772162922Sariff 7773183097Smav HDA_BOOTHVERBOSE( 7774182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7775182999Smav ); 7776182999Smav hdac_audio_disable_nonaudio(devinfo); 7777183097Smav HDA_BOOTHVERBOSE( 7778182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7779182999Smav ); 7780182999Smav hdac_audio_disable_useless(devinfo); 7781182999Smav HDA_BOOTVERBOSE( 7782182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7783182999Smav hdac_dump_pin_configs(devinfo); 7784183097Smav ); 7785183097Smav HDA_BOOTHVERBOSE( 7786182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7787182999Smav ); 7788182999Smav hdac_audio_as_parse(devinfo); 7789183097Smav HDA_BOOTHVERBOSE( 7790182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7791182999Smav ); 7792182999Smav hdac_audio_build_tree(devinfo); 7793183097Smav HDA_BOOTHVERBOSE( 7794182999Smav device_printf(sc->dev, "Disabling unassociated " 7795182999Smav "widgets...\n"); 7796182999Smav ); 7797182999Smav hdac_audio_disable_unas(devinfo); 7798183097Smav HDA_BOOTHVERBOSE( 7799182999Smav device_printf(sc->dev, "Disabling nonselected " 7800182999Smav "inputs...\n"); 7801182999Smav ); 7802182999Smav hdac_audio_disable_notselected(devinfo); 7803183097Smav HDA_BOOTHVERBOSE( 7804182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7805182999Smav ); 7806182999Smav hdac_audio_disable_useless(devinfo); 7807183097Smav HDA_BOOTHVERBOSE( 7808182999Smav device_printf(sc->dev, "Disabling " 7809182999Smav "crossassociatement connections...\n"); 7810182999Smav ); 7811182999Smav hdac_audio_disable_crossas(devinfo); 7812183097Smav HDA_BOOTHVERBOSE( 7813182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7814182999Smav ); 7815182999Smav hdac_audio_disable_useless(devinfo); 7816183097Smav HDA_BOOTHVERBOSE( 7817182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7818182999Smav ); 7819182999Smav hdac_audio_bind_as(devinfo); 7820183097Smav HDA_BOOTHVERBOSE( 7821182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7822182999Smav ); 7823182999Smav hdac_audio_assign_names(devinfo); 7824183097Smav HDA_BOOTHVERBOSE( 7825182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7826182999Smav ); 7827182999Smav hdac_audio_assign_mixers(devinfo); 7828183097Smav HDA_BOOTHVERBOSE( 7829182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7830182999Smav ); 7831182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7832183097Smav HDA_BOOTHVERBOSE( 7833182999Smav device_printf(sc->dev, "AFG commit...\n"); 7834182999Smav ); 7835182999Smav hdac_audio_commit(devinfo); 7836183097Smav HDA_BOOTHVERBOSE( 7837182999Smav device_printf(sc->dev, "HP switch init...\n"); 7838182999Smav ); 7839182999Smav hdac_hp_switch_init(devinfo); 7840182999Smav 7841182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7842182999Smav dmaalloc == 0) { 7843182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7844182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7845182999Smav HDA_BOOTVERBOSE( 7846182999Smav device_printf(sc->dev, "Failed to " 7847182999Smav "allocate DMA pos buffer " 7848182999Smav "(non-fatal)\n"); 7849182999Smav ); 7850182999Smav } else 7851182999Smav dmaalloc = 1; 7852182999Smav } 7853182999Smav 7854185225Smav HDA_BOOTHVERBOSE( 7855185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7856185225Smav ); 7857185225Smav hdac_create_pcms(devinfo); 7858182999Smav 7859182999Smav HDA_BOOTVERBOSE( 7860182999Smav if (devinfo->function.audio.quirks != 0) { 7861183097Smav device_printf(sc->dev, "FG config/quirks:"); 7862182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7863182999Smav if ((devinfo->function.audio.quirks & 7864182999Smav hdac_quirks_tab[i].value) == 7865182999Smav hdac_quirks_tab[i].value) 7866182999Smav printf(" %s", hdac_quirks_tab[i].key); 7867182999Smav } 7868182999Smav printf("\n"); 7869182999Smav } 7870182999Smav 7871182999Smav device_printf(sc->dev, "\n"); 7872182999Smav device_printf(sc->dev, "+-------------------+\n"); 7873182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7874182999Smav device_printf(sc->dev, "+-------------------+\n"); 7875182999Smav hdac_dump_nodes(devinfo); 7876183097Smav ); 7877182999Smav 7878183097Smav HDA_BOOTHVERBOSE( 7879182999Smav device_printf(sc->dev, "\n"); 7880182999Smav device_printf(sc->dev, "+------------------------+\n"); 7881182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7882182999Smav device_printf(sc->dev, "+------------------------+\n"); 7883182999Smav device_printf(sc->dev, "\n"); 7884182999Smav i = 0; 7885182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7886182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7887182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7888182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7889182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7890182999Smav ctl->index); 7891182999Smav if (ctl->childwidget != NULL) 7892182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7893182999Smav else 7894182999Smav printf(" "); 7895182999Smav printf(" ossmask=0x%08x\n", 7896182999Smav ctl->ossmask); 7897182999Smav device_printf(sc->dev, 7898182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7899182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7900182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7901182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7902182999Smav } 7903182999Smav ); 7904182999Smav } 7905162922Sariff } 7906182999Smav hdac_unlock(sc); 7907162922Sariff 7908163057Sariff HDA_BOOTVERBOSE( 7909182999Smav device_printf(sc->dev, "\n"); 7910162922Sariff ); 7911182999Smav 7912182999Smav bus_generic_attach(sc->dev); 7913182999Smav 7914182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7915182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7916182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7917182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7918182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7919182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7920182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7921182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7922182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7923182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7924182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7925182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7926182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7927182999Smav} 7928182999Smav 7929182999Smav/**************************************************************************** 7930182999Smav * int hdac_suspend(device_t) 7931182999Smav * 7932182999Smav * Suspend and power down HDA bus and codecs. 7933182999Smav ****************************************************************************/ 7934182999Smavstatic int 7935182999Smavhdac_suspend(device_t dev) 7936182999Smav{ 7937182999Smav struct hdac_softc *sc; 7938182999Smav struct hdac_codec *codec; 7939182999Smav struct hdac_devinfo *devinfo; 7940182999Smav int codec_index, fg_index, i; 7941182999Smav 7942183097Smav HDA_BOOTHVERBOSE( 7943182999Smav device_printf(dev, "Suspend...\n"); 7944162922Sariff ); 7945182999Smav 7946182999Smav sc = device_get_softc(dev); 7947182999Smav hdac_lock(sc); 7948182999Smav 7949183097Smav HDA_BOOTHVERBOSE( 7950182999Smav device_printf(dev, "Stop streams...\n"); 7951162922Sariff ); 7952182999Smav for (i = 0; i < sc->num_chans; i++) { 7953182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7954182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7955182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7956182999Smav } 7957182999Smav } 7958162922Sariff 7959182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7960182999Smav codec = sc->codecs[codec_index]; 7961182999Smav if (codec == NULL) 7962162922Sariff continue; 7963182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7964182999Smav devinfo = &codec->fgs[fg_index]; 7965183097Smav HDA_BOOTHVERBOSE( 7966182999Smav device_printf(dev, 7967182999Smav "Power down FG" 7968182999Smav " cad=%d nid=%d to the D3 state...\n", 7969182999Smav codec->cad, devinfo->nid); 7970182999Smav ); 7971182999Smav hdac_command(sc, 7972182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7973182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7974182999Smav codec->cad); 7975162922Sariff } 7976162922Sariff } 7977162922Sariff 7978183097Smav HDA_BOOTHVERBOSE( 7979182999Smav device_printf(dev, "Reset controller...\n"); 7980162922Sariff ); 7981182999Smav callout_stop(&sc->poll_hda); 7982182999Smav callout_stop(&sc->poll_hdac); 7983182999Smav callout_stop(&sc->poll_jack); 7984182999Smav hdac_reset(sc, 0); 7985182999Smav hdac_unlock(sc); 7986182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7987182999Smav callout_drain(&sc->poll_hda); 7988182999Smav callout_drain(&sc->poll_hdac); 7989182999Smav callout_drain(&sc->poll_jack); 7990162922Sariff 7991183097Smav HDA_BOOTHVERBOSE( 7992182999Smav device_printf(dev, "Suspend done\n"); 7993162922Sariff ); 7994182999Smav 7995182999Smav return (0); 7996182999Smav} 7997182999Smav 7998182999Smav/**************************************************************************** 7999182999Smav * int hdac_resume(device_t) 8000182999Smav * 8001182999Smav * Powerup and restore HDA bus and codecs state. 8002182999Smav ****************************************************************************/ 8003182999Smavstatic int 8004182999Smavhdac_resume(device_t dev) 8005182999Smav{ 8006182999Smav struct hdac_softc *sc; 8007182999Smav struct hdac_codec *codec; 8008182999Smav struct hdac_devinfo *devinfo; 8009182999Smav int codec_index, fg_index, i; 8010182999Smav 8011183097Smav HDA_BOOTHVERBOSE( 8012182999Smav device_printf(dev, "Resume...\n"); 8013162922Sariff ); 8014162922Sariff 8015182999Smav sc = device_get_softc(dev); 8016182999Smav hdac_lock(sc); 8017182999Smav 8018182999Smav /* Quiesce everything */ 8019183097Smav HDA_BOOTHVERBOSE( 8020182999Smav device_printf(dev, "Reset controller...\n"); 8021162922Sariff ); 8022182999Smav hdac_reset(sc, 1); 8023182999Smav 8024182999Smav /* Initialize the CORB and RIRB */ 8025182999Smav hdac_corb_init(sc); 8026182999Smav hdac_rirb_init(sc); 8027182999Smav 8028182999Smav /* Start the corb and rirb engines */ 8029183097Smav HDA_BOOTHVERBOSE( 8030182999Smav device_printf(dev, "Starting CORB Engine...\n"); 8031162922Sariff ); 8032182999Smav hdac_corb_start(sc); 8033183097Smav HDA_BOOTHVERBOSE( 8034182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 8035162922Sariff ); 8036182999Smav hdac_rirb_start(sc); 8037163057Sariff 8038183097Smav HDA_BOOTHVERBOSE( 8039182999Smav device_printf(dev, 8040182999Smav "Enabling controller interrupt...\n"); 8041162922Sariff ); 8042182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 8043182999Smav HDAC_GCTL_UNSOL); 8044182999Smav if (sc->polling == 0) { 8045182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 8046182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 8047182999Smav } else { 8048182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 8049182999Smav } 8050182999Smav DELAY(1000); 8051162922Sariff 8052182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 8053182999Smav codec = sc->codecs[codec_index]; 8054182999Smav if (codec == NULL) 8055182999Smav continue; 8056182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 8057182999Smav devinfo = &codec->fgs[fg_index]; 8058182999Smav if (devinfo->node_type != 8059182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 8060183097Smav HDA_BOOTHVERBOSE( 8061182999Smav device_printf(dev, 8062182999Smav "Power down unsupported non-audio FG" 8063182999Smav " cad=%d nid=%d to the D3 state...\n", 8064182999Smav codec->cad, devinfo->nid); 8065182999Smav ); 8066182999Smav hdac_command(sc, 8067182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 8068182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 8069182999Smav codec->cad); 8070182999Smav continue; 8071182999Smav } 8072162922Sariff 8073183097Smav HDA_BOOTHVERBOSE( 8074182999Smav device_printf(dev, 8075182999Smav "Power up audio FG cad=%d nid=%d...\n", 8076182999Smav devinfo->codec->cad, devinfo->nid); 8077182999Smav ); 8078182999Smav hdac_powerup(devinfo); 8079183097Smav HDA_BOOTHVERBOSE( 8080182999Smav device_printf(dev, "AFG commit...\n"); 8081182999Smav ); 8082182999Smav hdac_audio_commit(devinfo); 8083183097Smav HDA_BOOTHVERBOSE( 8084182999Smav device_printf(dev, "HP switch init...\n"); 8085182999Smav ); 8086182999Smav hdac_hp_switch_init(devinfo); 8087182999Smav 8088182999Smav hdac_unlock(sc); 8089182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 8090182999Smav struct hdac_pcm_devinfo *pdevinfo = 8091182999Smav &devinfo->function.audio.devs[i]; 8092183097Smav HDA_BOOTHVERBOSE( 8093182999Smav device_printf(pdevinfo->dev, 8094182999Smav "OSS mixer reinitialization...\n"); 8095182999Smav ); 8096182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 8097182999Smav device_printf(pdevinfo->dev, 8098182999Smav "unable to reinitialize the mixer\n"); 8099182999Smav } 8100182999Smav hdac_lock(sc); 8101182999Smav } 8102169277Sariff } 8103169277Sariff 8104183097Smav HDA_BOOTHVERBOSE( 8105182999Smav device_printf(dev, "Start streams...\n"); 8106163057Sariff ); 8107182999Smav for (i = 0; i < sc->num_chans; i++) { 8108182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 8109182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 8110182999Smav hdac_channel_start(sc, &sc->chans[i]); 8111182999Smav } 8112182999Smav } 8113162922Sariff 8114182999Smav hdac_unlock(sc); 8115182999Smav 8116183097Smav HDA_BOOTHVERBOSE( 8117182999Smav device_printf(dev, "Resume done\n"); 8118162922Sariff ); 8119164614Sariff 8120182999Smav return (0); 8121162922Sariff} 8122162922Sariff/**************************************************************************** 8123162922Sariff * int hdac_detach(device_t) 8124162922Sariff * 8125162922Sariff * Detach and free up resources utilized by the hdac device. 8126162922Sariff ****************************************************************************/ 8127162922Sariffstatic int 8128162922Sariffhdac_detach(device_t dev) 8129162922Sariff{ 8130182999Smav struct hdac_softc *sc; 8131185177Smav device_t *devlist; 8132185177Smav int i, devcount, error; 8133162922Sariff 8134185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 8135185177Smav return (error); 8136185177Smav for (i = 0; i < devcount; i++) { 8137185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 8138185178Smav free(devlist, M_TEMP); 8139185178Smav return (error); 8140185178Smav } 8141185177Smav } 8142185177Smav free(devlist, M_TEMP); 8143185177Smav 8144182999Smav sc = device_get_softc(dev); 8145163057Sariff hdac_release_resources(sc); 8146162922Sariff 8147162922Sariff return (0); 8148162922Sariff} 8149162922Sariff 8150184095Smavstatic int 8151184095Smavhdac_print_child(device_t dev, device_t child) 8152184095Smav{ 8153184095Smav struct hdac_pcm_devinfo *pdevinfo = 8154184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 8155184095Smav int retval; 8156184095Smav 8157184095Smav retval = bus_print_child_header(dev, child); 8158184095Smav retval += printf(" at cad %d nid %d", 8159184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 8160184095Smav retval += bus_print_child_footer(dev, child); 8161184095Smav 8162184095Smav return (retval); 8163184095Smav} 8164184095Smav 8165162922Sariffstatic device_method_t hdac_methods[] = { 8166162922Sariff /* device interface */ 8167162922Sariff DEVMETHOD(device_probe, hdac_probe), 8168162922Sariff DEVMETHOD(device_attach, hdac_attach), 8169162922Sariff DEVMETHOD(device_detach, hdac_detach), 8170182999Smav DEVMETHOD(device_suspend, hdac_suspend), 8171182999Smav DEVMETHOD(device_resume, hdac_resume), 8172184095Smav /* Bus interface */ 8173184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 8174162922Sariff { 0, 0 } 8175162922Sariff}; 8176162922Sariff 8177162922Sariffstatic driver_t hdac_driver = { 8178182999Smav "hdac", 8179162922Sariff hdac_methods, 8180182999Smav sizeof(struct hdac_softc), 8181162922Sariff}; 8182162922Sariff 8183182999Smavstatic devclass_t hdac_devclass; 8184182999Smav 8185182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 8186162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 8187162922SariffMODULE_VERSION(snd_hda, 1); 8188182999Smav 8189182999Smavstatic int 8190182999Smavhdac_pcm_probe(device_t dev) 8191182999Smav{ 8192182999Smav struct hdac_pcm_devinfo *pdevinfo = 8193182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8194182999Smav char buf[128]; 8195182999Smav 8196185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 8197182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 8198185225Smav pdevinfo->index, 8199197611Smav (pdevinfo->digital == 3)?"DisplayPort": 8200197611Smav ((pdevinfo->digital == 2)?"HDMI": 8201197611Smav ((pdevinfo->digital)?"Digital":"Analog"))); 8202182999Smav device_set_desc_copy(dev, buf); 8203182999Smav return (0); 8204182999Smav} 8205182999Smav 8206182999Smavstatic int 8207182999Smavhdac_pcm_attach(device_t dev) 8208182999Smav{ 8209182999Smav struct hdac_pcm_devinfo *pdevinfo = 8210182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8211182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 8212182999Smav char status[SND_STATUSLEN]; 8213182999Smav int i; 8214182999Smav 8215182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 8216182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 8217182999Smav 8218182999Smav HDA_BOOTVERBOSE( 8219182999Smav device_printf(dev, "+--------------------------------------+\n"); 8220182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 8221182999Smav device_printf(dev, "+--------------------------------------+\n"); 8222182999Smav hdac_dump_pcmchannels(pdevinfo); 8223182999Smav device_printf(dev, "\n"); 8224189876Smav device_printf(dev, "+-------------------------------+\n"); 8225189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 8226189876Smav device_printf(dev, "+-------------------------------+\n"); 8227182999Smav hdac_dump_dac(pdevinfo); 8228182999Smav hdac_dump_adc(pdevinfo); 8229182999Smav hdac_dump_mix(pdevinfo); 8230182999Smav device_printf(dev, "\n"); 8231182999Smav device_printf(dev, "+-------------------------+\n"); 8232182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 8233182999Smav device_printf(dev, "+-------------------------+\n"); 8234182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 8235182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 8236182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 8237182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 8238182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 8239182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 8240182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 8241182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 8242202796Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 8243202796Smav hdac_dump_ctls(pdevinfo, "Input Monitoring Level", SOUND_MASK_IGAIN); 8244182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 8245182999Smav device_printf(dev, "\n"); 8246182999Smav ); 8247182999Smav 8248182999Smav if (resource_int_value(device_get_name(dev), 8249182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 8250182999Smav i &= HDA_BLK_ALIGN; 8251182999Smav if (i < HDA_BLK_MIN) 8252182999Smav i = HDA_BLK_MIN; 8253182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 8254182999Smav i = 0; 8255182999Smav while (pdevinfo->chan_blkcnt >> i) 8256182999Smav i++; 8257182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 8258182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 8259182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 8260182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 8261182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 8262182999Smav } else 8263182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 8264182999Smav 8265182999Smav /* 8266182999Smav * We don't register interrupt handler with snd_setup_intr 8267182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 8268182999Smav */ 8269182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 8270182999Smav 8271183097Smav HDA_BOOTHVERBOSE( 8272182999Smav device_printf(dev, "OSS mixer initialization...\n"); 8273182999Smav ); 8274182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 8275182999Smav device_printf(dev, "Can't register mixer\n"); 8276182999Smav 8277183097Smav HDA_BOOTHVERBOSE( 8278182999Smav device_printf(dev, "Registering PCM channels...\n"); 8279182999Smav ); 8280182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 8281182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 8282182999Smav device_printf(dev, "Can't register PCM\n"); 8283182999Smav 8284182999Smav pdevinfo->registered++; 8285182999Smav 8286182999Smav if (pdevinfo->play >= 0) 8287182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 8288182999Smav if (pdevinfo->rec >= 0) 8289182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 8290182999Smav 8291184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 8292184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 8293184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 8294182999Smav pcm_setstatus(dev, status); 8295182999Smav 8296182999Smav return (0); 8297182999Smav} 8298182999Smav 8299182999Smavstatic int 8300182999Smavhdac_pcm_detach(device_t dev) 8301182999Smav{ 8302182999Smav struct hdac_pcm_devinfo *pdevinfo = 8303182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8304182999Smav int err; 8305182999Smav 8306182999Smav if (pdevinfo->registered > 0) { 8307182999Smav err = pcm_unregister(dev); 8308182999Smav if (err != 0) 8309182999Smav return (err); 8310182999Smav } 8311182999Smav 8312182999Smav return (0); 8313182999Smav} 8314182999Smav 8315182999Smavstatic device_method_t hdac_pcm_methods[] = { 8316182999Smav /* device interface */ 8317182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8318182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8319182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8320182999Smav { 0, 0 } 8321182999Smav}; 8322182999Smav 8323182999Smavstatic driver_t hdac_pcm_driver = { 8324182999Smav "pcm", 8325182999Smav hdac_pcm_methods, 8326182999Smav PCM_SOFTC_SIZE, 8327182999Smav}; 8328182999Smav 8329182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8330182999Smav 8331