hdac.c revision 185178
1162922Sariff/*- 2162922Sariff * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3162922Sariff * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4182999Smav * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org> 5162922Sariff * All rights reserved. 6162922Sariff * 7162922Sariff * Redistribution and use in source and binary forms, with or without 8162922Sariff * modification, are permitted provided that the following conditions 9162922Sariff * are met: 10162922Sariff * 1. Redistributions of source code must retain the above copyright 11162922Sariff * notice, this list of conditions and the following disclaimer. 12162922Sariff * 2. Redistributions in binary form must reproduce the above copyright 13162922Sariff * notice, this list of conditions and the following disclaimer in the 14162922Sariff * documentation and/or other materials provided with the distribution. 15162922Sariff * 16162922Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19162922Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26162922Sariff * SUCH DAMAGE. 27162922Sariff */ 28162922Sariff 29162922Sariff/* 30162922Sariff * Intel High Definition Audio (Controller) driver for FreeBSD. Be advised 31162922Sariff * that this driver still in its early stage, and possible of rewrite are 32162922Sariff * pretty much guaranteed. There are supposedly several distinct parent/child 33162922Sariff * busses to make this "perfect", but as for now and for the sake of 34162922Sariff * simplicity, everything is gobble up within single source. 35162922Sariff * 36162922Sariff * List of subsys: 37162922Sariff * 1) HDA Controller support 38162922Sariff * 2) HDA Codecs support, which may include 39162922Sariff * - HDA 40162922Sariff * - Modem 41162922Sariff * - HDMI 42162922Sariff * 3) Widget parser - the real magic of why this driver works on so 43162922Sariff * many hardwares with minimal vendor specific quirk. The original 44162922Sariff * parser was written using Ruby and can be found at 45162922Sariff * http://people.freebsd.org/~ariff/HDA/parser.rb . This crude 46162922Sariff * ruby parser take the verbose dmesg dump as its input. Refer to 47162922Sariff * http://www.microsoft.com/whdc/device/audio/default.mspx for various 48164614Sariff * interesting documents, especially UAA (Universal Audio Architecture). 49162922Sariff * 4) Possible vendor specific support. 50162922Sariff * (snd_hda_intel, snd_hda_ati, etc..) 51162922Sariff * 52162922Sariff * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the 53162922Sariff * Compaq V3000 with Conexant HDA. 54162922Sariff * 55162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 56162922Sariff * * * 57162922Sariff * * This driver is a collaborative effort made by: * 58162922Sariff * * * 59162922Sariff * * Stephane E. Potvin <sepotvin@videotron.ca> * 60162922Sariff * * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * 61162922Sariff * * Wesley Morgan <morganw@chemikals.org> * 62162922Sariff * * Daniel Eischen <deischen@FreeBSD.org> * 63162922Sariff * * Maxime Guillaud <bsd-ports@mguillaud.net> * 64162922Sariff * * Ariff Abdullah <ariff@FreeBSD.org> * 65182999Smav * * Alexander Motin <mav@FreeBSD.org> * 66162922Sariff * * * 67162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 68162922Sariff * * * 69162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 70162922Sariff */ 71162922Sariff 72162922Sariff#include <dev/sound/pcm/sound.h> 73162922Sariff#include <dev/pci/pcireg.h> 74162922Sariff#include <dev/pci/pcivar.h> 75162922Sariff 76171141Sariff#include <sys/ctype.h> 77171141Sariff#include <sys/taskqueue.h> 78171141Sariff 79162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 80162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 81162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 82162922Sariff#include <dev/sound/pci/hda/hdac.h> 83162922Sariff 84162922Sariff#include "mixer_if.h" 85162922Sariff 86185176Smav#define HDA_DRV_TEST_REV "20081122_0117" 87162922Sariff 88162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 185178 2008-11-22 15:38:24Z mav $"); 89162922Sariff 90169277Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 91169277Sariff if (bootverbose != 0 || snd_verbose > 3) { \ 92169277Sariff stmt \ 93169277Sariff } \ 94162922Sariff} while(0) 95162922Sariff 96183097Smav#define HDA_BOOTHVERBOSE(stmt) do { \ 97183097Smav if (snd_verbose > 3) { \ 98183097Smav stmt \ 99183097Smav } \ 100183097Smav} while(0) 101183097Smav 102162965Sariff#if 1 103162922Sariff#undef HDAC_INTR_EXTRA 104162922Sariff#define HDAC_INTR_EXTRA 1 105162922Sariff#endif 106162922Sariff 107162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 108162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 109163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 110163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 111162922Sariff 112178155Sariff#undef HDAC_MSI_ENABLED 113178155Sariff#if __FreeBSD_version >= 700026 || \ 114178155Sariff (__FreeBSD_version < 700000 && __FreeBSD_version >= 602106) 115178155Sariff#define HDAC_MSI_ENABLED 1 116178155Sariff#endif 117178155Sariff 118162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 119163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 120163257Sariff (fl) == 0xffffffff || \ 121163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 122163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 123163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 124163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 125162965Sariff#define HDA_MATCH_ALL 0xffffffff 126162965Sariff#define HDAC_INVALID 0xffffffff 127162965Sariff 128169277Sariff/* Default controller / jack sense poll: 250ms */ 129169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 130169277Sariff 131171141Sariff/* 132171141Sariff * Make room for possible 4096 playback/record channels, in 100 years to come. 133171141Sariff */ 134171141Sariff#define HDAC_TRIGGER_NONE 0x00000000 135171141Sariff#define HDAC_TRIGGER_PLAY 0x00000fff 136171141Sariff#define HDAC_TRIGGER_REC 0x00fff000 137171141Sariff#define HDAC_TRIGGER_UNSOL 0x80000000 138171141Sariff 139162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 140162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 141162922Sariff 142162922Sariff/* Controller models */ 143162922Sariff 144162922Sariff/* Intel */ 145162922Sariff#define INTEL_VENDORID 0x8086 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) 151184207Smav#define HDA_INTEL_82801J HDA_MODEL_CONSTRUCT(INTEL, 0x3a3e) 152184207Smav#define HDA_INTEL_SCH HDA_MODEL_CONSTRUCT(INTEL, 0x811b) 153162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 154162922Sariff 155162922Sariff/* Nvidia */ 156162922Sariff#define NVIDIA_VENDORID 0x10de 157162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 158162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 159173817Sariff#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 160173817Sariff#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 161173817Sariff#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 162173817Sariff#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 163173817Sariff#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c) 164173817Sariff#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d) 165162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 166162922Sariff 167162922Sariff/* ATI */ 168162922Sariff#define ATI_VENDORID 0x1002 169162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 170163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 171162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 172162922Sariff 173163136Sariff/* VIA */ 174163136Sariff#define VIA_VENDORID 0x1106 175163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 176163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 177163136Sariff 178163136Sariff/* SiS */ 179163136Sariff#define SIS_VENDORID 0x1039 180163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 181163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 182163136Sariff 183162922Sariff/* OEM/subvendors */ 184162922Sariff 185165466Sariff/* Intel */ 186165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 187165466Sariff 188162922Sariff/* HP/Compaq */ 189162922Sariff#define HP_VENDORID 0x103c 190162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 191162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 192162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 193165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 194166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 195169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 196169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 197174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 198172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 199162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 200165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 201165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 202162922Sariff 203162922Sariff/* Dell */ 204162922Sariff#define DELL_VENDORID 0x1028 205180532Sdelphij#define DELL_D630_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01f9) 206162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 207184483Smav#define DELL_V1400_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0227) 208178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 209162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 210169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 211169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 212162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 213162922Sariff 214162922Sariff/* Clevo */ 215162922Sariff#define CLEVO_VENDORID 0x1558 216162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 217162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 218162922Sariff 219162922Sariff/* Acer */ 220162922Sariff#define ACER_VENDORID 0x1025 221165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 222173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 223174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 224182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 225169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 226182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 227162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 228162922Sariff 229162965Sariff/* Asus */ 230162965Sariff#define ASUS_VENDORID 0x1043 231178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 232163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 233178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 234165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 235178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 236178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 237167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 238169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 239178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 240178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 241178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 242170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 243178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 244169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 245171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 246162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 247162922Sariff 248163257Sariff/* IBM / Lenovo */ 249163257Sariff#define IBM_VENDORID 0x1014 250163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 251163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 252162965Sariff 253164614Sariff/* Lenovo */ 254164657Sariff#define LENOVO_VENDORID 0x17aa 255164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 256182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 257172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 258164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 259163257Sariff 260164657Sariff/* Samsung */ 261164657Sariff#define SAMSUNG_VENDORID 0x144d 262164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 263164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 264164614Sariff 265164750Sariff/* Medion ? */ 266164750Sariff#define MEDION_VENDORID 0x161f 267164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 268164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 269164750Sariff 270173817Sariff/* Apple Computer Inc. */ 271173817Sariff#define APPLE_VENDORID 0x106b 272173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 273173817Sariff 274182999Smav/* Sony */ 275182999Smav#define SONY_VENDORID 0x104d 276182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 277182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 278182999Smav 279164828Sariff/* 280164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 281164828Sariff * instead of their own, which is beyond my comprehension 282164828Sariff * (see HDA_CODEC_STAC9221 below). 283164828Sariff */ 284164828Sariff#define APPLE_INTEL_MAC 0x76808384 285164828Sariff 286165281Sariff/* LG Electronics */ 287165281Sariff#define LG_VENDORID 0x1854 288165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 289165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 290165281Sariff 291165351Sariff/* Fujitsu Siemens */ 292165351Sariff#define FS_VENDORID 0x1734 293165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 294172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 295165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 296165351Sariff 297172811Sariff/* Fujitsu Limited */ 298172811Sariff#define FL_VENDORID 0x10cf 299172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 300182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 301172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 302172811Sariff 303165770Sariff/* Toshiba */ 304165770Sariff#define TOSHIBA_VENDORID 0x1179 305165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 306173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 307165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 308165770Sariff 309165992Sariff/* Micro-Star International (MSI) */ 310165992Sariff#define MSI_VENDORID 0x1462 311165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 312172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 313165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 314165992Sariff 315172811Sariff/* Giga-Byte Technology */ 316172811Sariff#define GB_VENDORID 0x1458 317172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 318172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 319172811Sariff 320169277Sariff/* Uniwill ? */ 321169277Sariff#define UNIWILL_VENDORID 0x1584 322169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 323170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 324169277Sariff 325169277Sariff 326162922Sariff/* Misc constants.. */ 327182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 328162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 329162922Sariff#define HDA_AMP_MUTE_NONE (0) 330162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 331162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 332162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 333162922Sariff 334162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 335162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 336162922Sariff 337182999Smav#define HDA_ADC_MONITOR (1 << 0) 338162922Sariff 339182999Smav#define HDA_CTL_OUT 1 340182999Smav#define HDA_CTL_IN 2 341169277Sariff 342169277Sariff#define HDA_GPIO_MAX 8 343169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 344163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 345163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 346163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 347169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 348169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 349169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 350169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 351169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 352169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 353162922Sariff 354169277Sariff/* 9 - 25 = anything else */ 355169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 356169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 357169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 358169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 359169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 360182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 361169277Sariff 362169277Sariff/* 26 - 31 = vrefs */ 363169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 364169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 365169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 366169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 367169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 368169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 369169277Sariff 370169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 371169277Sariff HDA_QUIRK_IVREF100) 372169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 373169277Sariff HDA_QUIRK_OVREF100) 374169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 375169277Sariff 376171141Sariff#if __FreeBSD_version < 600000 377171141Sariff#define taskqueue_drain(...) 378171141Sariff#endif 379171141Sariff 380163057Sariffstatic const struct { 381163057Sariff char *key; 382163057Sariff uint32_t value; 383163057Sariff} hdac_quirks_tab[] = { 384163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 385163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 386163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 387169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 388169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 389169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 390169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 391169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 392165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 393163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 394163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 395163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 396163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 397169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 398182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 399169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 400169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 401169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 402169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 403169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 404169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 405169277Sariff { "ivref", HDA_QUIRK_IVREF }, 406169277Sariff { "ovref", HDA_QUIRK_OVREF }, 407165069Sariff { "vref", HDA_QUIRK_VREF }, 408163057Sariff}; 409163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 410163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 411163057Sariff 412162922Sariff#define HDA_BDL_MIN 2 413162922Sariff#define HDA_BDL_MAX 256 414162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 415162922Sariff 416169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 417167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 418167648Sariff 419162922Sariff#define HDA_BUFSZ_MIN 4096 420162922Sariff#define HDA_BUFSZ_MAX 65536 421162922Sariff#define HDA_BUFSZ_DEFAULT 16384 422162922Sariff 423162922Sariff#define HDA_PARSE_MAXDEPTH 10 424162922Sariff 425169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 426162922Sariff 427165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 428162922Sariff 429182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 430182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 431182999Smav "White", "Other"}; 432162922Sariff 433182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 434182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 435182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 436182999Smav 437182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 438182999Smav 439162922Sariff/* Default */ 440162922Sariffstatic uint32_t hdac_fmt[] = { 441162922Sariff AFMT_STEREO | AFMT_S16_LE, 442162922Sariff 0 443162922Sariff}; 444162922Sariff 445162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 446162922Sariff 447162922Sariffstatic const struct { 448162922Sariff uint32_t model; 449162922Sariff char *desc; 450162922Sariff} hdac_devices[] = { 451162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 452171330Sariff { HDA_INTEL_63XXESB, "Intel 631x/632xESB" }, 453162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 454163136Sariff { HDA_INTEL_82801H, "Intel 82801H" }, 455171330Sariff { HDA_INTEL_82801I, "Intel 82801I" }, 456184207Smav { HDA_INTEL_82801J, "Intel 82801J" }, 457184207Smav { HDA_INTEL_SCH, "Intel SCH" }, 458162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 459162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 460173817Sariff { HDA_NVIDIA_MCP61_1, "NVidia MCP61" }, 461173817Sariff { HDA_NVIDIA_MCP61_2, "NVidia MCP61" }, 462173817Sariff { HDA_NVIDIA_MCP65_1, "NVidia MCP65" }, 463174004Sariff { HDA_NVIDIA_MCP65_2, "NVidia MCP65" }, 464173817Sariff { HDA_NVIDIA_MCP67_1, "NVidia MCP67" }, 465173817Sariff { HDA_NVIDIA_MCP67_2, "NVidia MCP67" }, 466162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 467163136Sariff { HDA_ATI_SB600, "ATI SB600" }, 468163136Sariff { HDA_VIA_VT82XX, "VIA VT8251/8237A" }, 469163136Sariff { HDA_SIS_966, "SiS 966" }, 470162922Sariff /* Unknown */ 471162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 472162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 473162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 474163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 475163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 476162922Sariff}; 477162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 478162922Sariff 479162922Sariffstatic const struct { 480169277Sariff uint16_t vendor; 481169277Sariff uint8_t reg; 482169277Sariff uint8_t mask; 483169277Sariff uint8_t enable; 484169277Sariff} hdac_pcie_snoop[] = { 485169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 486169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 487169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 488169277Sariff}; 489169277Sariff#define HDAC_PCIESNOOP_LEN \ 490169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 491169277Sariff 492169277Sariffstatic const struct { 493162922Sariff uint32_t rate; 494162922Sariff int valid; 495162922Sariff uint16_t base; 496162922Sariff uint16_t mul; 497162922Sariff uint16_t div; 498162922Sariff} hda_rate_tab[] = { 499162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 500162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 501162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 502162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 503162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 504162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 505162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 506162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 507162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 508162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 509162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 510162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 511162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 512162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 513162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 514162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 515162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 516162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 517162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 518162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 519162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 520162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 521162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 522162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 523162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 524162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 525162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 526162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 527162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 528162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 529162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 530162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 531162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 532162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 533162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 534162922Sariff}; 535162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 536162922Sariff 537162922Sariff/* All codecs you can eat... */ 538162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 539162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 540162922Sariff 541162922Sariff/* Realtek */ 542162922Sariff#define REALTEK_VENDORID 0x10ec 543162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 544169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 545183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 546171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 547183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 548183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 549170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 550183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 551183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 552162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 553169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 554162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 555163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 556163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 557169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 558165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 559182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 560162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 561162922Sariff 562169277Sariff/* Analog Devices */ 563169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 564169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 565169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 566174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 567169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 568169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 569170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 570169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 571162922Sariff 572162922Sariff/* CMedia */ 573162922Sariff#define CMEDIA_VENDORID 0x434d 574162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 575162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 576162922Sariff 577162922Sariff/* Sigmatel */ 578162922Sariff#define SIGMATEL_VENDORID 0x8384 579182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 580182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 581182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 582182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 583182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 584182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 585182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 586182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 587183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 588183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 589183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 590183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 591183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 592183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 593183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 594182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 595183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 596183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 597183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 598183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 599183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 600183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 601183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 602183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 603182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 604162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 605182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 606183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 607162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 608162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 609183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 610183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 611183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 612183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 613183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 614183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 615183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 616183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 617183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 618162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 619162922Sariff 620183894Smav/* IDT */ 621183894Smav#define IDT_VENDORID 0x111d 622183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 623183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 624183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 625183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 626183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 627183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 628183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 629183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 630183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 631183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 632183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 633183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 634183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 635183894Smav 636182999Smav/* Silicon Image */ 637182999Smav#define SII_VENDORID 0x1095 638182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 639182999Smav 640182999Smav/* Lucent/Agere */ 641182999Smav#define AGERE_VENDORID 0x11c1 642182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 643182999Smav 644162922Sariff/* 645162922Sariff * Conexant 646162922Sariff * 647162922Sariff * Ok, the truth is, I don't have any idea at all whether 648162922Sariff * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only 649162922Sariff * place that tell me it is "Venice" is from its Windows driver INF. 650163057Sariff * 651163057Sariff * Venice - CX????? 652163057Sariff * Waikiki - CX20551-22 653162922Sariff */ 654162922Sariff#define CONEXANT_VENDORID 0x14f1 655162922Sariff#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 656163057Sariff#define HDA_CODEC_CXWAIKIKI HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 657162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 658162922Sariff 659169277Sariff/* VIA */ 660169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 661169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 662169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 663169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 664169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 665169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 666169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 667169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 668169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 669169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 670169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 671169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 672169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 673162922Sariff 674182999Smav/* ATI */ 675182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 676169277Sariff 677182999Smav/* NVIDIA */ 678182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 679182999Smav 680183894Smav/* INTEL */ 681183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 682183894Smav 683162922Sariff/* Codecs */ 684162922Sariffstatic const struct { 685162922Sariff uint32_t id; 686162922Sariff char *name; 687162922Sariff} hdac_codecs[] = { 688162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 689169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 690183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 691171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 692183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 693183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 694170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 695183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 696183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 697162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 698169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 699162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 700162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 701163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 702169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 703165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 704182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 705169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 706169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 707174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 708169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 709169277Sariff { HDA_CODEC_AD1988, "Analog Devices AD1988" }, 710170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 711162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 712183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 713183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 714183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 715183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 716183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 717183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 718183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 719183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 720162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 721183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 722162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 723162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 724183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 725183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 726183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 727183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 728183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 729183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 730182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 731182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 732183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 733183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 734183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 735166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 736183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 737183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 738183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 739183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 740183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 741183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 742183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 743183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 744183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 745183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 746183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 747183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 748183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 749183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 750183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 751183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 752183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 753183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 754183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 755183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 756183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 757183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 758183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 759183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 760183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 761183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 762183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 763162922Sariff { HDA_CODEC_CXVENICE, "Conexant Venice" }, 764163057Sariff { HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" }, 765169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 766169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 767169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 768169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 769169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 770169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 771169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 772169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 773169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 774169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 775169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 776169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 777162922Sariff /* Unknown codec */ 778162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 779169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 780162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 781162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 782182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 783182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 784162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 785169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 786182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 787182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 788183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 789183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 790162922Sariff}; 791162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 792162922Sariff 793162922Sariff 794162922Sariff/**************************************************************************** 795162922Sariff * Function prototypes 796162922Sariff ****************************************************************************/ 797162922Sariffstatic void hdac_intr_handler(void *); 798182999Smavstatic int hdac_reset(struct hdac_softc *, int); 799162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 800162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 801162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 802162922Sariff struct hdac_dma *, bus_size_t); 803169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 804162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 805162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 806162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 807162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 808162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 809162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 810162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 811162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 812182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 813182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 814182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 815182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 816162922Sariff 817162922Sariffstatic void hdac_attach2(void *); 818162922Sariff 819162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 820162922Sariff uint32_t, int); 821162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 822162922Sariff struct hdac_command_list *, int); 823162922Sariff 824162922Sariffstatic int hdac_probe(device_t); 825162922Sariffstatic int hdac_attach(device_t); 826162922Sariffstatic int hdac_detach(device_t); 827182999Smavstatic int hdac_suspend(device_t); 828182999Smavstatic int hdac_resume(device_t); 829162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 830162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 831162922Sariff uint32_t, int, int); 832162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 833182999Smav nid_t, int, int, int); 834162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 835162922Sariff nid_t, nid_t, int, int, int, int, int, int); 836162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 837162922Sariff 838164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 839164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 840164614Sariff 841182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 842182999Smav 843162922Sariff#define hdac_command(a1, a2, a3) \ 844162922Sariff hdac_command_sendone_internal(a1, a2, a3) 845162922Sariff 846182999Smav#define hdac_codec_id(c) \ 847182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 848182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 849182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 850162922Sariff 851162922Sariffstatic char * 852182999Smavhdac_codec_name(struct hdac_codec *codec) 853162922Sariff{ 854162922Sariff uint32_t id; 855162922Sariff int i; 856162922Sariff 857182999Smav id = hdac_codec_id(codec); 858162922Sariff 859162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 860163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 861162922Sariff return (hdac_codecs[i].name); 862162922Sariff } 863162922Sariff 864162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 865162922Sariff} 866162922Sariff 867162922Sariffstatic char * 868162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 869162922Sariff{ 870162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 871162922Sariff int i, first = 1; 872162922Sariff 873162922Sariff bzero(buf, len); 874162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 875162922Sariff if (mask & (1 << i)) { 876162922Sariff if (first == 0) 877162922Sariff strlcat(buf, ", ", len); 878162922Sariff strlcat(buf, ossname[i], len); 879162922Sariff first = 0; 880162922Sariff } 881162922Sariff } 882182999Smav return (buf); 883162922Sariff} 884162922Sariff 885162922Sariffstatic struct hdac_audio_ctl * 886162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 887162922Sariff{ 888162922Sariff if (devinfo == NULL || 889162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 890162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 891162922Sariff devinfo->function.audio.ctlcnt < 1 || 892162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 893162922Sariff return (NULL); 894162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 895162922Sariff} 896162922Sariff 897162922Sariffstatic struct hdac_audio_ctl * 898182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 899162922Sariff int index, int cnt) 900162922Sariff{ 901182999Smav struct hdac_audio_ctl *ctl; 902182999Smav int i, found = 0; 903162922Sariff 904162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 905162922Sariff return (NULL); 906162922Sariff 907162922Sariff i = 0; 908162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 909182999Smav if (ctl->enable == 0) 910162922Sariff continue; 911182999Smav if (ctl->widget->nid != nid) 912162922Sariff continue; 913182999Smav if (dir && ctl->ndir != dir) 914182999Smav continue; 915182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 916182999Smav ctl->dir == ctl->ndir && ctl->index != index) 917182999Smav continue; 918162922Sariff found++; 919182999Smav if (found == cnt || cnt <= 0) 920162922Sariff return (ctl); 921162922Sariff } 922162922Sariff 923182999Smav return (NULL); 924162922Sariff} 925162922Sariff 926182999Smav/* 927182999Smav * Jack detection (Speaker/HP redirection) event handler. 928182999Smav */ 929162922Sariffstatic void 930162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 931162922Sariff{ 932182999Smav struct hdac_audio_as *as; 933162922Sariff struct hdac_softc *sc; 934162922Sariff struct hdac_widget *w; 935162922Sariff struct hdac_audio_ctl *ctl; 936182999Smav uint32_t val, res; 937182999Smav int i, j; 938162922Sariff nid_t cad; 939162922Sariff 940162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 941162922Sariff devinfo->codec->sc == NULL) 942162922Sariff return; 943162922Sariff 944162922Sariff sc = devinfo->codec->sc; 945162922Sariff cad = devinfo->codec->cad; 946182999Smav as = devinfo->function.audio.as; 947182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 948182999Smav if (as[i].hpredir < 0) 949182999Smav continue; 950182999Smav 951182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 952182999Smav if (w == NULL || w->enable == 0 || w->type != 953182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 954182999Smav continue; 955162922Sariff 956171141Sariff res = hdac_command(sc, 957182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 958171141Sariff 959182999Smav HDA_BOOTVERBOSE( 960182999Smav device_printf(sc->dev, 961182999Smav "Pin sense: nid=%d res=0x%08x\n", 962182999Smav as[i].pins[15], res); 963182999Smav ); 964171141Sariff 965182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 966182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 967182999Smav res ^= 1; 968162922Sariff 969182999Smav /* (Un)Mute headphone pin. */ 970162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 971182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 972182999Smav if (ctl != NULL && ctl->mute) { 973182999Smav /* If pin has muter - use it. */ 974182999Smav val = (res != 0) ? 0 : 1; 975182999Smav if (val != ctl->forcemute) { 976182999Smav ctl->forcemute = val; 977162922Sariff hdac_audio_ctl_amp_set(ctl, 978182999Smav HDA_AMP_MUTE_DEFAULT, 979182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 980162922Sariff } 981182999Smav } else { 982182999Smav /* If there is no muter - disable pin output. */ 983182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 984163057Sariff if (w != NULL && w->type == 985163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 986182999Smav if (res != 0) 987169277Sariff val = w->wclass.pin.ctrl | 988162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 989162922Sariff else 990169277Sariff val = w->wclass.pin.ctrl & 991162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 992169277Sariff if (val != w->wclass.pin.ctrl) { 993169277Sariff w->wclass.pin.ctrl = val; 994169277Sariff hdac_command(sc, 995169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 996169277Sariff w->nid, w->wclass.pin.ctrl), cad); 997169277Sariff } 998162922Sariff } 999182999Smav } 1000182999Smav /* (Un)Mute other pins. */ 1001182999Smav for (j = 0; j < 15; j++) { 1002182999Smav if (as[i].pins[j] <= 0) 1003182999Smav continue; 1004182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1005182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1006182999Smav if (ctl != NULL && ctl->mute) { 1007182999Smav /* If pin has muter - use it. */ 1008182999Smav val = (res != 0) ? 1 : 0; 1009182999Smav if (val == ctl->forcemute) 1010169277Sariff continue; 1011182999Smav ctl->forcemute = val; 1012182999Smav hdac_audio_ctl_amp_set(ctl, 1013182999Smav HDA_AMP_MUTE_DEFAULT, 1014182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1015182999Smav continue; 1016162922Sariff } 1017182999Smav /* If there is no muter - disable pin output. */ 1018182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1019163057Sariff if (w != NULL && w->type == 1020163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1021182999Smav if (res != 0) 1022182999Smav val = w->wclass.pin.ctrl & 1023182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1024182999Smav else 1025182999Smav val = w->wclass.pin.ctrl | 1026182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1027169277Sariff if (val != w->wclass.pin.ctrl) { 1028169277Sariff w->wclass.pin.ctrl = val; 1029169277Sariff hdac_command(sc, 1030169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1031169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1032169277Sariff } 1033162922Sariff } 1034162922Sariff } 1035182999Smav } 1036182999Smav} 1037182999Smav 1038182999Smav/* 1039182999Smav * Callback for poll based jack detection. 1040182999Smav */ 1041182999Smavstatic void 1042182999Smavhdac_jack_poll_callback(void *arg) 1043182999Smav{ 1044182999Smav struct hdac_devinfo *devinfo = arg; 1045182999Smav struct hdac_softc *sc; 1046182999Smav 1047182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1048182999Smav devinfo->codec->sc == NULL) 1049182999Smav return; 1050182999Smav sc = devinfo->codec->sc; 1051182999Smav hdac_lock(sc); 1052182999Smav if (sc->poll_ival == 0) { 1053182999Smav hdac_unlock(sc); 1054182999Smav return; 1055182999Smav } 1056182999Smav hdac_hp_switch_handler(devinfo); 1057182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1058182999Smav hdac_jack_poll_callback, devinfo); 1059182999Smav hdac_unlock(sc); 1060182999Smav} 1061182999Smav 1062182999Smav/* 1063182999Smav * Jack detection initializer. 1064182999Smav */ 1065182999Smavstatic void 1066182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1067182999Smav{ 1068182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1069182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1070182999Smav struct hdac_widget *w; 1071182999Smav uint32_t id; 1072182999Smav int i, enable = 0, poll = 0; 1073182999Smav nid_t cad; 1074182999Smav 1075182999Smav id = hdac_codec_id(devinfo->codec); 1076182999Smav cad = devinfo->codec->cad; 1077182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1078182999Smav if (as[i].hpredir < 0) 1079182999Smav continue; 1080182999Smav 1081182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1082182999Smav if (w == NULL || w->enable == 0 || w->type != 1083182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1084182999Smav continue; 1085182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1086182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1087182999Smav device_printf(sc->dev, 1088182999Smav "No jack detection support at pin %d\n", 1089182999Smav as[i].pins[15]); 1090182999Smav continue; 1091182999Smav } 1092182999Smav enable = 1; 1093182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1094169277Sariff hdac_command(sc, 1095182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1096182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1097182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1098182999Smav } else 1099182999Smav poll = 1; 1100182999Smav HDA_BOOTVERBOSE( 1101169277Sariff device_printf(sc->dev, 1102182999Smav "Enabling headphone/speaker " 1103182999Smav "audio routing switching:\n"); 1104182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1105182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1106182999Smav ); 1107182999Smav } 1108182999Smav if (enable) { 1109182999Smav hdac_hp_switch_handler(devinfo); 1110182999Smav if (poll) { 1111182999Smav callout_reset(&sc->poll_jack, 1, 1112182999Smav hdac_jack_poll_callback, devinfo); 1113169277Sariff } 1114162922Sariff } 1115162922Sariff} 1116162922Sariff 1117182999Smav/* 1118182999Smav * Unsolicited messages handler. 1119182999Smav */ 1120162922Sariffstatic void 1121162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1122162922Sariff{ 1123162922Sariff struct hdac_softc *sc; 1124162922Sariff struct hdac_devinfo *devinfo = NULL; 1125182999Smav int i; 1126162922Sariff 1127162922Sariff if (codec == NULL || codec->sc == NULL) 1128162922Sariff return; 1129162922Sariff 1130162922Sariff sc = codec->sc; 1131162922Sariff 1132163057Sariff HDA_BOOTVERBOSE( 1133182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1134162922Sariff ); 1135162922Sariff 1136182999Smav for (i = 0; i < codec->num_fgs; i++) { 1137182999Smav if (codec->fgs[i].node_type == 1138182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1139182999Smav devinfo = &codec->fgs[i]; 1140162965Sariff break; 1141182999Smav } 1142162922Sariff } 1143162965Sariff 1144162922Sariff if (devinfo == NULL) 1145162922Sariff return; 1146162922Sariff 1147162922Sariff switch (tag) { 1148162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1149162922Sariff hdac_hp_switch_handler(devinfo); 1150162922Sariff break; 1151162922Sariff default: 1152182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1153162922Sariff break; 1154162922Sariff } 1155162922Sariff} 1156162922Sariff 1157164614Sariffstatic int 1158162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1159162922Sariff{ 1160162922Sariff /* XXX to be removed */ 1161162922Sariff#ifdef HDAC_INTR_EXTRA 1162162922Sariff uint32_t res; 1163162922Sariff#endif 1164162922Sariff 1165171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1166164614Sariff return (0); 1167162922Sariff 1168162922Sariff /* XXX to be removed */ 1169162922Sariff#ifdef HDAC_INTR_EXTRA 1170162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1171162922Sariff#endif 1172162922Sariff 1173162922Sariff /* XXX to be removed */ 1174162922Sariff#ifdef HDAC_INTR_EXTRA 1175163057Sariff HDA_BOOTVERBOSE( 1176163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1177182999Smav device_printf(ch->pdevinfo->dev, 1178163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1179163057Sariff "%08x\n", 1180163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1181163057Sariff ); 1182162922Sariff#endif 1183162922Sariff 1184162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1185163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1186162922Sariff 1187162922Sariff /* XXX to be removed */ 1188162922Sariff#ifdef HDAC_INTR_EXTRA 1189162922Sariff if (res & HDAC_SDSTS_BCIS) { 1190162922Sariff#endif 1191164614Sariff return (1); 1192162922Sariff /* XXX to be removed */ 1193162922Sariff#ifdef HDAC_INTR_EXTRA 1194162922Sariff } 1195162922Sariff#endif 1196164614Sariff 1197164614Sariff return (0); 1198162922Sariff} 1199162922Sariff 1200162922Sariff/**************************************************************************** 1201162922Sariff * void hdac_intr_handler(void *) 1202162922Sariff * 1203162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1204162922Sariff ****************************************************************************/ 1205162922Sariffstatic void 1206162922Sariffhdac_intr_handler(void *context) 1207162922Sariff{ 1208162922Sariff struct hdac_softc *sc; 1209162922Sariff uint32_t intsts; 1210162922Sariff uint8_t rirbsts; 1211164614Sariff struct hdac_rirb *rirb_base; 1212171141Sariff uint32_t trigger; 1213182999Smav int i; 1214162922Sariff 1215162922Sariff sc = (struct hdac_softc *)context; 1216162922Sariff 1217162922Sariff hdac_lock(sc); 1218164614Sariff if (sc->polling != 0) { 1219164614Sariff hdac_unlock(sc); 1220164614Sariff return; 1221164614Sariff } 1222171141Sariff 1223162922Sariff /* Do we have anything to do? */ 1224162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1225163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1226162922Sariff hdac_unlock(sc); 1227162922Sariff return; 1228162922Sariff } 1229162922Sariff 1230171141Sariff trigger = 0; 1231171141Sariff 1232162922Sariff /* Was this a controller interrupt? */ 1233163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1234162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1235162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1236162922Sariff /* Get as many responses that we can */ 1237163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1238164614Sariff HDAC_WRITE_1(&sc->mem, 1239164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1240171141Sariff if (hdac_rirb_flush(sc) != 0) 1241171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1242162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1243162922Sariff } 1244162922Sariff /* XXX to be removed */ 1245162922Sariff /* Clear interrupt and exit */ 1246162922Sariff#ifdef HDAC_INTR_EXTRA 1247162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1248162922Sariff#endif 1249162922Sariff } 1250164614Sariff 1251163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1252182999Smav for (i = 0; i < sc->num_chans; i++) { 1253182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1254182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1255182999Smav trigger |= (1 << i); 1256182999Smav } 1257162922Sariff /* XXX to be removed */ 1258162922Sariff#ifdef HDAC_INTR_EXTRA 1259164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1260164614Sariff HDAC_INTSTS_SIS_MASK); 1261162922Sariff#endif 1262162922Sariff } 1263162922Sariff 1264164614Sariff hdac_unlock(sc); 1265162922Sariff 1266182999Smav for (i = 0; i < sc->num_chans; i++) { 1267182999Smav if (trigger & (1 << i)) 1268182999Smav chn_intr(sc->chans[i].c); 1269182999Smav } 1270171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1271171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1272162922Sariff} 1273162922Sariff 1274162922Sariff/**************************************************************************** 1275182999Smav * int hdac_reset(hdac_softc *, int) 1276162922Sariff * 1277162922Sariff * Reset the hdac to a quiescent and known state. 1278162922Sariff ****************************************************************************/ 1279162922Sariffstatic int 1280182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1281162922Sariff{ 1282162922Sariff uint32_t gctl; 1283162922Sariff int count, i; 1284162922Sariff 1285162922Sariff /* 1286162922Sariff * Stop all Streams DMA engine 1287162922Sariff */ 1288162922Sariff for (i = 0; i < sc->num_iss; i++) 1289162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1290162922Sariff for (i = 0; i < sc->num_oss; i++) 1291162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1292162922Sariff for (i = 0; i < sc->num_bss; i++) 1293162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1294162922Sariff 1295162922Sariff /* 1296169277Sariff * Stop Control DMA engines. 1297162922Sariff */ 1298162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1299162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1300162922Sariff 1301162922Sariff /* 1302169277Sariff * Reset DMA position buffer. 1303169277Sariff */ 1304169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1305169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1306169277Sariff 1307169277Sariff /* 1308162922Sariff * Reset the controller. The reset must remain asserted for 1309162922Sariff * a minimum of 100us. 1310162922Sariff */ 1311162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1312162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1313162922Sariff count = 10000; 1314162922Sariff do { 1315162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1316162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1317162922Sariff break; 1318162922Sariff DELAY(10); 1319162922Sariff } while (--count); 1320162922Sariff if (gctl & HDAC_GCTL_CRST) { 1321162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1322162922Sariff return (ENXIO); 1323162922Sariff } 1324182999Smav 1325182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1326182999Smav if (!wakeup) 1327182999Smav return (0); 1328182999Smav 1329162922Sariff DELAY(100); 1330162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1331162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1332162922Sariff count = 10000; 1333162922Sariff do { 1334162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1335163057Sariff if (gctl & HDAC_GCTL_CRST) 1336162922Sariff break; 1337162922Sariff DELAY(10); 1338162922Sariff } while (--count); 1339162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1340162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1341162922Sariff return (ENXIO); 1342162922Sariff } 1343162922Sariff 1344162922Sariff /* 1345162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1346162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1347162922Sariff * computer. Let's use twice as much as necessary to make sure that 1348162922Sariff * it's reset properly. 1349162922Sariff */ 1350162922Sariff DELAY(1000); 1351162922Sariff 1352162922Sariff return (0); 1353162922Sariff} 1354162922Sariff 1355162922Sariff 1356162922Sariff/**************************************************************************** 1357162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1358162922Sariff * 1359162922Sariff * Retreive the general capabilities of the hdac; 1360162922Sariff * Number of Input Streams 1361162922Sariff * Number of Output Streams 1362162922Sariff * Number of bidirectional Streams 1363162922Sariff * 64bit ready 1364162922Sariff * CORB and RIRB sizes 1365162922Sariff ****************************************************************************/ 1366162922Sariffstatic int 1367162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1368162922Sariff{ 1369162922Sariff uint16_t gcap; 1370162922Sariff uint8_t corbsize, rirbsize; 1371162922Sariff 1372162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1373162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1374162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1375162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1376162922Sariff 1377163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1378162922Sariff 1379162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1380162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1381162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1382162922Sariff sc->corb_size = 256; 1383162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1384162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1385162922Sariff sc->corb_size = 16; 1386162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1387162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1388162922Sariff sc->corb_size = 2; 1389162922Sariff else { 1390162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1391162922Sariff __func__, corbsize); 1392162922Sariff return (ENXIO); 1393162922Sariff } 1394162922Sariff 1395162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1396162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1397162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1398162922Sariff sc->rirb_size = 256; 1399162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1400162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1401162922Sariff sc->rirb_size = 16; 1402162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1403162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1404162922Sariff sc->rirb_size = 2; 1405162922Sariff else { 1406162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1407162922Sariff __func__, rirbsize); 1408162922Sariff return (ENXIO); 1409162922Sariff } 1410162922Sariff 1411183097Smav HDA_BOOTHVERBOSE( 1412182999Smav device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 1413182999Smav device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 1414182999Smav device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 1415182999Smav sc->num_iss, sc->num_oss, sc->num_bss); 1416182999Smav ); 1417182999Smav 1418162922Sariff return (0); 1419162922Sariff} 1420162922Sariff 1421162922Sariff 1422162922Sariff/**************************************************************************** 1423162922Sariff * void hdac_dma_cb 1424162922Sariff * 1425162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1426162922Sariff * established. We just record the physical address of the mapping into 1427162922Sariff * the struct hdac_dma passed in. 1428162922Sariff ****************************************************************************/ 1429162922Sariffstatic void 1430162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1431162922Sariff{ 1432162922Sariff struct hdac_dma *dma; 1433162922Sariff 1434162922Sariff if (error == 0) { 1435162922Sariff dma = (struct hdac_dma *)callback_arg; 1436162922Sariff dma->dma_paddr = segs[0].ds_addr; 1437162922Sariff } 1438162922Sariff} 1439162922Sariff 1440162922Sariff 1441162922Sariff/**************************************************************************** 1442162922Sariff * int hdac_dma_alloc 1443162922Sariff * 1444162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1445162922Sariff * It must be freed by a corresponding hdac_dma_free. 1446162922Sariff ****************************************************************************/ 1447162922Sariffstatic int 1448162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1449162922Sariff{ 1450169277Sariff bus_size_t roundsz; 1451162922Sariff int result; 1452162922Sariff int lowaddr; 1453162922Sariff 1454169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1455162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1456162922Sariff BUS_SPACE_MAXADDR_32BIT; 1457162922Sariff bzero(dma, sizeof(*dma)); 1458162922Sariff 1459162922Sariff /* 1460162922Sariff * Create a DMA tag 1461162922Sariff */ 1462162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1463162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1464162922Sariff 0, /* boundary */ 1465162922Sariff lowaddr, /* lowaddr */ 1466162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1467162922Sariff NULL, /* filtfunc */ 1468162922Sariff NULL, /* fistfuncarg */ 1469169277Sariff roundsz, /* maxsize */ 1470162922Sariff 1, /* nsegments */ 1471169277Sariff roundsz, /* maxsegsz */ 1472162922Sariff 0, /* flags */ 1473162922Sariff NULL, /* lockfunc */ 1474162922Sariff NULL, /* lockfuncarg */ 1475162922Sariff &dma->dma_tag); /* dmat */ 1476162922Sariff if (result != 0) { 1477162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1478162922Sariff __func__, result); 1479167773Sariff goto hdac_dma_alloc_fail; 1480162922Sariff } 1481162922Sariff 1482162922Sariff /* 1483162922Sariff * Allocate DMA memory 1484162922Sariff */ 1485162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1486169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1487171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1488171330Sariff &dma->dma_map); 1489162922Sariff if (result != 0) { 1490162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1491162922Sariff __func__, result); 1492167773Sariff goto hdac_dma_alloc_fail; 1493162922Sariff } 1494162922Sariff 1495169277Sariff dma->dma_size = roundsz; 1496169277Sariff 1497162922Sariff /* 1498162922Sariff * Map the memory 1499162922Sariff */ 1500162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1501169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1502162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1503167773Sariff if (result == 0) 1504167773Sariff result = ENOMEM; 1505162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1506162922Sariff __func__, result); 1507167773Sariff goto hdac_dma_alloc_fail; 1508162922Sariff } 1509162922Sariff 1510183097Smav HDA_BOOTHVERBOSE( 1511169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1512169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1513169277Sariff ); 1514169277Sariff 1515162922Sariff return (0); 1516169277Sariff 1517167773Sariffhdac_dma_alloc_fail: 1518169277Sariff hdac_dma_free(sc, dma); 1519167773Sariff 1520162922Sariff return (result); 1521162922Sariff} 1522162922Sariff 1523162922Sariff 1524162922Sariff/**************************************************************************** 1525169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1526162922Sariff * 1527162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1528162922Sariff * hdac_dma_alloc function. 1529162922Sariff ****************************************************************************/ 1530162922Sariffstatic void 1531169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1532162922Sariff{ 1533167773Sariff if (dma->dma_map != NULL) { 1534169277Sariff#if 0 1535162922Sariff /* Flush caches */ 1536162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1537162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1538169277Sariff#endif 1539162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1540167773Sariff } 1541167773Sariff if (dma->dma_vaddr != NULL) { 1542162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1543167773Sariff dma->dma_vaddr = NULL; 1544167773Sariff } 1545167773Sariff dma->dma_map = NULL; 1546167773Sariff if (dma->dma_tag != NULL) { 1547162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1548167773Sariff dma->dma_tag = NULL; 1549162922Sariff } 1550167773Sariff dma->dma_size = 0; 1551162922Sariff} 1552162922Sariff 1553162922Sariff/**************************************************************************** 1554162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1555162922Sariff * 1556162922Sariff * Allocate all the bus resources necessary to speak with the physical 1557162922Sariff * controller. 1558162922Sariff ****************************************************************************/ 1559162922Sariffstatic int 1560162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1561162922Sariff{ 1562162922Sariff struct hdac_mem *mem; 1563162922Sariff 1564162922Sariff mem = &sc->mem; 1565162922Sariff mem->mem_rid = PCIR_BAR(0); 1566162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1567162922Sariff &mem->mem_rid, RF_ACTIVE); 1568162922Sariff if (mem->mem_res == NULL) { 1569162922Sariff device_printf(sc->dev, 1570162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1571162922Sariff return (ENOMEM); 1572162922Sariff } 1573162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1574162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1575162922Sariff 1576162922Sariff return (0); 1577162922Sariff} 1578162922Sariff 1579162922Sariff/**************************************************************************** 1580162922Sariff * void hdac_mem_free(struct hdac_softc *) 1581162922Sariff * 1582162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1583162922Sariff ****************************************************************************/ 1584162922Sariffstatic void 1585162922Sariffhdac_mem_free(struct hdac_softc *sc) 1586162922Sariff{ 1587162922Sariff struct hdac_mem *mem; 1588162922Sariff 1589162922Sariff mem = &sc->mem; 1590162922Sariff if (mem->mem_res != NULL) 1591162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1592162922Sariff mem->mem_res); 1593164614Sariff mem->mem_res = NULL; 1594162922Sariff} 1595162922Sariff 1596162922Sariff/**************************************************************************** 1597162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1598162922Sariff * 1599162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1600162922Sariff ****************************************************************************/ 1601162922Sariffstatic int 1602162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1603162922Sariff{ 1604162922Sariff struct hdac_irq *irq; 1605162922Sariff int result; 1606162922Sariff 1607162922Sariff irq = &sc->irq; 1608162922Sariff irq->irq_rid = 0x0; 1609171330Sariff 1610178155Sariff#ifdef HDAC_MSI_ENABLED 1611171330Sariff if ((sc->flags & HDAC_F_MSI) && 1612171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1613171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1614171330Sariff irq->irq_rid = 0x1; 1615171330Sariff else 1616171330Sariff#endif 1617171330Sariff sc->flags &= ~HDAC_F_MSI; 1618171330Sariff 1619162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1620162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1621162922Sariff if (irq->irq_res == NULL) { 1622162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1623162922Sariff __func__); 1624167773Sariff goto hdac_irq_alloc_fail; 1625162922Sariff } 1626182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1627182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1628162922Sariff if (result != 0) { 1629162922Sariff device_printf(sc->dev, 1630162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1631162922Sariff __func__, result); 1632167773Sariff goto hdac_irq_alloc_fail; 1633162922Sariff } 1634162922Sariff 1635162922Sariff return (0); 1636162922Sariff 1637167773Sariffhdac_irq_alloc_fail: 1638164614Sariff hdac_irq_free(sc); 1639164614Sariff 1640162922Sariff return (ENXIO); 1641162922Sariff} 1642162922Sariff 1643162922Sariff/**************************************************************************** 1644162922Sariff * void hdac_irq_free(struct hdac_softc *) 1645162922Sariff * 1646162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1647162922Sariff ****************************************************************************/ 1648162922Sariffstatic void 1649162922Sariffhdac_irq_free(struct hdac_softc *sc) 1650162922Sariff{ 1651162922Sariff struct hdac_irq *irq; 1652162922Sariff 1653162922Sariff irq = &sc->irq; 1654164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1655162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1656162922Sariff if (irq->irq_res != NULL) 1657162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1658162922Sariff irq->irq_res); 1659178155Sariff#ifdef HDAC_MSI_ENABLED 1660171330Sariff if ((sc->flags & HDAC_F_MSI) && irq->irq_rid == 0x1) 1661171330Sariff pci_release_msi(sc->dev); 1662171330Sariff#endif 1663164614Sariff irq->irq_handle = NULL; 1664164614Sariff irq->irq_res = NULL; 1665171330Sariff irq->irq_rid = 0x0; 1666162922Sariff} 1667162922Sariff 1668162922Sariff/**************************************************************************** 1669162922Sariff * void hdac_corb_init(struct hdac_softc *) 1670162922Sariff * 1671162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1672162922Sariff * The CORB engine must not be running when this function is called. 1673162922Sariff ****************************************************************************/ 1674162922Sariffstatic void 1675162922Sariffhdac_corb_init(struct hdac_softc *sc) 1676162922Sariff{ 1677162922Sariff uint8_t corbsize; 1678162922Sariff uint64_t corbpaddr; 1679162922Sariff 1680162922Sariff /* Setup the CORB size. */ 1681162922Sariff switch (sc->corb_size) { 1682162922Sariff case 256: 1683162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1684162922Sariff break; 1685162922Sariff case 16: 1686162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1687162922Sariff break; 1688162922Sariff case 2: 1689162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1690162922Sariff break; 1691162922Sariff default: 1692162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1693162922Sariff } 1694162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1695162922Sariff 1696162922Sariff /* Setup the CORB Address in the hdac */ 1697162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1698162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1699162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1700162922Sariff 1701162922Sariff /* Set the WP and RP */ 1702162922Sariff sc->corb_wp = 0; 1703162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1704162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1705162922Sariff /* 1706162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1707162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1708162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1709162922Sariff * manually reset the bit to zero before continuing. 1710162922Sariff */ 1711162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1712162922Sariff 1713162922Sariff /* Enable CORB error reporting */ 1714162922Sariff#if 0 1715162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1716162922Sariff#endif 1717162922Sariff} 1718162922Sariff 1719162922Sariff/**************************************************************************** 1720162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1721162922Sariff * 1722162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1723162922Sariff * The RIRB engine must not be running when this function is called. 1724162922Sariff ****************************************************************************/ 1725162922Sariffstatic void 1726162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1727162922Sariff{ 1728162922Sariff uint8_t rirbsize; 1729162922Sariff uint64_t rirbpaddr; 1730162922Sariff 1731162922Sariff /* Setup the RIRB size. */ 1732162922Sariff switch (sc->rirb_size) { 1733162922Sariff case 256: 1734162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1735162922Sariff break; 1736162922Sariff case 16: 1737162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1738162922Sariff break; 1739162922Sariff case 2: 1740162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1741162922Sariff break; 1742162922Sariff default: 1743162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1744162922Sariff } 1745162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1746162922Sariff 1747162922Sariff /* Setup the RIRB Address in the hdac */ 1748162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1749162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1750162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1751162922Sariff 1752162922Sariff /* Setup the WP and RP */ 1753162922Sariff sc->rirb_rp = 0; 1754162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1755162922Sariff 1756182999Smav /* Setup the interrupt threshold */ 1757182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1758162922Sariff 1759182999Smav /* Enable Overrun and response received reporting */ 1760162922Sariff#if 0 1761182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1762182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1763162922Sariff#else 1764182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1765162922Sariff#endif 1766162922Sariff 1767169277Sariff#if 0 1768162922Sariff /* 1769162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1770162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1771162922Sariff * should be sufficient to do this only once as the rirb is purely 1772162922Sariff * read-only from now on. 1773162922Sariff */ 1774162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1775162922Sariff BUS_DMASYNC_PREREAD); 1776169277Sariff#endif 1777162922Sariff} 1778162922Sariff 1779162922Sariff/**************************************************************************** 1780162922Sariff * void hdac_corb_start(hdac_softc *) 1781162922Sariff * 1782162922Sariff * Startup the corb DMA engine 1783162922Sariff ****************************************************************************/ 1784162922Sariffstatic void 1785162922Sariffhdac_corb_start(struct hdac_softc *sc) 1786162922Sariff{ 1787162922Sariff uint32_t corbctl; 1788162922Sariff 1789162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1790162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1791162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1792162922Sariff} 1793162922Sariff 1794162922Sariff/**************************************************************************** 1795162922Sariff * void hdac_rirb_start(hdac_softc *) 1796162922Sariff * 1797162922Sariff * Startup the rirb DMA engine 1798162922Sariff ****************************************************************************/ 1799162922Sariffstatic void 1800162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1801162922Sariff{ 1802162922Sariff uint32_t rirbctl; 1803162922Sariff 1804162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1805162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1806162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1807162922Sariff} 1808162922Sariff 1809162922Sariff 1810162922Sariff/**************************************************************************** 1811172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 1812162922Sariff * 1813172811Sariff * Scan the bus for available codecs, starting with num. 1814162922Sariff ****************************************************************************/ 1815162922Sariffstatic void 1816182999Smavhdac_scan_codecs(struct hdac_softc *sc) 1817162922Sariff{ 1818162922Sariff struct hdac_codec *codec; 1819162922Sariff int i; 1820162922Sariff uint16_t statests; 1821162922Sariff 1822162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1823182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1824162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1825162922Sariff /* We have found a codec. */ 1826162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1827162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1828162922Sariff if (codec == NULL) { 1829162922Sariff device_printf(sc->dev, 1830162922Sariff "Unable to allocate memory for codec\n"); 1831162922Sariff continue; 1832162922Sariff } 1833164614Sariff codec->commands = NULL; 1834164614Sariff codec->responses_received = 0; 1835162922Sariff codec->verbs_sent = 0; 1836162922Sariff codec->sc = sc; 1837162922Sariff codec->cad = i; 1838162922Sariff sc->codecs[i] = codec; 1839182999Smav hdac_probe_codec(codec); 1840162922Sariff } 1841162922Sariff } 1842162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1843163057Sariff /* bus_generic_attach(sc->dev); */ 1844162922Sariff} 1845162922Sariff 1846162922Sariff/**************************************************************************** 1847162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1848162922Sariff * 1849162922Sariff * Probe a the given codec_id for available function groups. 1850162922Sariff ****************************************************************************/ 1851182999Smavstatic void 1852162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1853162922Sariff{ 1854162922Sariff struct hdac_softc *sc = codec->sc; 1855162922Sariff uint32_t vendorid, revisionid, subnode; 1856162922Sariff int startnode; 1857162922Sariff int endnode; 1858162922Sariff int i; 1859162922Sariff nid_t cad = codec->cad; 1860162922Sariff 1861163057Sariff HDA_BOOTVERBOSE( 1862184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 1863162922Sariff ); 1864162922Sariff vendorid = hdac_command(sc, 1865162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1866162922Sariff cad); 1867162922Sariff revisionid = hdac_command(sc, 1868162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1869162922Sariff cad); 1870182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1871182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1872182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1873182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1874182999Smav 1875182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 1876182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 1877182999Smav " Probing aborted.\n", cad); 1878182999Smav return; 1879182999Smav } 1880182999Smav 1881184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 1882182999Smav cad, hdac_codec_name(codec)); 1883182999Smav HDA_BOOTVERBOSE( 1884184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 1885182999Smav hdac_codec_id(codec)); 1886182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 1887182999Smav codec->vendor_id); 1888182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 1889182999Smav codec->device_id); 1890182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 1891182999Smav codec->revision_id); 1892182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 1893182999Smav codec->stepping_id); 1894182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 1895182999Smav sc->pci_subvendor); 1896182999Smav ); 1897162922Sariff subnode = hdac_command(sc, 1898162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1899162922Sariff cad); 1900162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1901162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1902162922Sariff 1903183097Smav HDA_BOOTHVERBOSE( 1904182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 1905163057Sariff startnode, endnode); 1906162922Sariff ); 1907182999Smav 1908182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 1909182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 1910182999Smav if (codec->fgs == NULL) { 1911183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 1912182999Smav __func__); 1913182999Smav return; 1914162922Sariff } 1915162922Sariff 1916182999Smav for (i = startnode; i < endnode; i++) 1917182999Smav hdac_probe_function(codec, i); 1918182999Smav return; 1919162922Sariff} 1920162922Sariff 1921182999Smav/* 1922182999Smav * Probe codec function and add it to the list. 1923182999Smav */ 1924182999Smavstatic void 1925162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1926162922Sariff{ 1927162922Sariff struct hdac_softc *sc = codec->sc; 1928182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 1929162922Sariff uint32_t fctgrptype; 1930182999Smav uint32_t res; 1931162922Sariff nid_t cad = codec->cad; 1932162922Sariff 1933162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1934162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1935162922Sariff 1936162922Sariff devinfo->nid = nid; 1937162965Sariff devinfo->node_type = fctgrptype; 1938162922Sariff devinfo->codec = codec; 1939162922Sariff 1940182999Smav res = hdac_command(sc, 1941182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 1942162922Sariff 1943182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 1944182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 1945182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 1946162922Sariff 1947182999Smav HDA_BOOTVERBOSE( 1948182999Smav device_printf(sc->dev, 1949182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 1950182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 1951182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 1952182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 1953182999Smav devinfo->nodecnt); 1954182999Smav ); 1955182999Smav 1956182999Smav if (devinfo->nodecnt > 0) 1957182999Smav devinfo->widget = (struct hdac_widget *)malloc( 1958182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 1959182999Smav M_NOWAIT | M_ZERO); 1960182999Smav else 1961182999Smav devinfo->widget = NULL; 1962182999Smav 1963182999Smav if (devinfo->widget == NULL) { 1964182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 1965182999Smav devinfo->endnode = devinfo->startnode; 1966182999Smav devinfo->nodecnt = 0; 1967182999Smav return; 1968182999Smav } 1969182999Smav 1970182999Smav codec->num_fgs++; 1971162922Sariff} 1972162922Sariff 1973162922Sariffstatic void 1974162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 1975162922Sariff{ 1976162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1977162922Sariff uint32_t res; 1978169277Sariff int i, j, max, ents, entnum; 1979162922Sariff nid_t cad = w->devinfo->codec->cad; 1980162922Sariff nid_t nid = w->nid; 1981169277Sariff nid_t cnid, addcnid, prevcnid; 1982162922Sariff 1983169277Sariff w->nconns = 0; 1984169277Sariff 1985162922Sariff res = hdac_command(sc, 1986162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 1987162922Sariff 1988169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 1989162922Sariff 1990169277Sariff if (ents < 1) 1991162922Sariff return; 1992162922Sariff 1993162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 1994162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 1995169277Sariff prevcnid = 0; 1996162922Sariff 1997169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 1998169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 1999169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2000169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2001169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2002169277Sariff 2003169277Sariff for (i = 0; i < ents; i += entnum) { 2004162922Sariff res = hdac_command(sc, 2005162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2006162922Sariff for (j = 0; j < entnum; j++) { 2007169277Sariff cnid = CONN_CNID(res, entnum, j); 2008169277Sariff if (cnid == 0) { 2009169277Sariff if (w->nconns < ents) 2010169277Sariff device_printf(sc->dev, 2011169277Sariff "%s: nid=%d WARNING: zero cnid " 2012169277Sariff "entnum=%d j=%d index=%d " 2013169277Sariff "entries=%d found=%d res=0x%08x\n", 2014169277Sariff __func__, nid, entnum, j, i, 2015169277Sariff ents, w->nconns, res); 2016169277Sariff else 2017169277Sariff goto getconns_out; 2018169277Sariff } 2019169277Sariff if (cnid < w->devinfo->startnode || 2020169277Sariff cnid >= w->devinfo->endnode) { 2021169277Sariff HDA_BOOTVERBOSE( 2022169277Sariff device_printf(sc->dev, 2023182999Smav "GHOST: nid=%d j=%d " 2024169277Sariff "entnum=%d index=%d res=0x%08x\n", 2025182999Smav nid, j, entnum, i, res); 2026169277Sariff ); 2027169277Sariff } 2028169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2029169277Sariff addcnid = cnid; 2030169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2031162922Sariff device_printf(sc->dev, 2032169277Sariff "%s: WARNING: Invalid child range " 2033169277Sariff "nid=%d index=%d j=%d entnum=%d " 2034169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2035169277Sariff __func__, nid, i, j, entnum, prevcnid, 2036169277Sariff cnid, res); 2037169277Sariff addcnid = cnid; 2038169277Sariff } else 2039169277Sariff addcnid = prevcnid + 1; 2040169277Sariff while (addcnid <= cnid) { 2041169277Sariff if (w->nconns > max) { 2042169277Sariff device_printf(sc->dev, 2043182999Smav "Adding %d (nid=%d): " 2044169277Sariff "Max connection reached! max=%d\n", 2045182999Smav addcnid, nid, max + 1); 2046169277Sariff goto getconns_out; 2047169277Sariff } 2048182999Smav w->connsenable[w->nconns] = 1; 2049169277Sariff w->conns[w->nconns++] = addcnid++; 2050162922Sariff } 2051169277Sariff prevcnid = cnid; 2052162922Sariff } 2053162922Sariff } 2054162922Sariff 2055169277Sariffgetconns_out: 2056169277Sariff return; 2057162922Sariff} 2058162922Sariff 2059162922Sariffstatic uint32_t 2060182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2061182999Smav{ 2062182999Smav char buf[256]; 2063182999Smav char *key, *value, *rest, *bad; 2064182999Smav int ival, i; 2065182999Smav 2066182999Smav strlcpy(buf, str, sizeof(buf)); 2067182999Smav rest = buf; 2068182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2069182999Smav value = strsep(&rest, " \t"); 2070182999Smav if (value == NULL) 2071182999Smav break; 2072182999Smav ival = strtol(value, &bad, 10); 2073182999Smav if (strcmp(key, "seq") == 0) { 2074182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2075182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2076182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2077182999Smav } else if (strcmp(key, "as") == 0) { 2078182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2079182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2080182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2081182999Smav } else if (strcmp(key, "misc") == 0) { 2082182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2083182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2084182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2085182999Smav } else if (strcmp(key, "color") == 0) { 2086182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2087182999Smav if (bad[0] == 0) { 2088182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2089182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2090182999Smav }; 2091182999Smav for (i = 0; i < 16; i++) { 2092182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2093182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2094182999Smav break; 2095182999Smav } 2096182999Smav } 2097182999Smav } else if (strcmp(key, "ctype") == 0) { 2098182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2099182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2100182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2101182999Smav } else if (strcmp(key, "device") == 0) { 2102182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2103182999Smav if (bad[0] == 0) { 2104182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2105182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2106182999Smav continue; 2107182999Smav }; 2108182999Smav for (i = 0; i < 16; i++) { 2109182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2110182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2111182999Smav break; 2112182999Smav } 2113182999Smav } 2114182999Smav } else if (strcmp(key, "loc") == 0) { 2115182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2116182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2117182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2118182999Smav } else if (strcmp(key, "conn") == 0) { 2119182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2120182999Smav if (bad[0] == 0) { 2121182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2122182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2123182999Smav continue; 2124182999Smav }; 2125182999Smav for (i = 0; i < 4; i++) { 2126182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2127182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2128182999Smav break; 2129182999Smav } 2130182999Smav } 2131182999Smav } 2132182999Smav } 2133182999Smav return (config); 2134182999Smav} 2135182999Smav 2136182999Smavstatic uint32_t 2137162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2138162922Sariff{ 2139162922Sariff struct hdac_softc *sc; 2140166965Sariff uint32_t config, orig, id; 2141162922Sariff nid_t cad, nid; 2142182999Smav char buf[32]; 2143182999Smav const char *res = NULL, *patch = NULL; 2144162922Sariff 2145162922Sariff sc = w->devinfo->codec->sc; 2146162922Sariff cad = w->devinfo->codec->cad; 2147162922Sariff nid = w->nid; 2148182999Smav id = hdac_codec_id(w->devinfo->codec); 2149162922Sariff 2150162922Sariff config = hdac_command(sc, 2151162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2152162922Sariff cad); 2153166965Sariff orig = config; 2154166965Sariff 2155182999Smav HDA_BOOTVERBOSE( 2156182999Smav hdac_dump_pin_config(w, orig); 2157182999Smav ); 2158182999Smav 2159182999Smav /* XXX: Old patches require complete review. 2160182999Smav * Now they may create more problem then solve due to 2161182999Smav * incorrect associations. 2162162965Sariff */ 2163165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2164165281Sariff switch (nid) { 2165165281Sariff case 26: 2166165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2167165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2168165281Sariff break; 2169165281Sariff case 27: 2170165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2171165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2172165281Sariff break; 2173167610Sariff default: 2174167610Sariff break; 2175165281Sariff } 2176165281Sariff } else if (id == HDA_CODEC_ALC880 && 2177162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2178162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2179162922Sariff /* 2180162965Sariff * Super broken BIOS 2181162922Sariff */ 2182162922Sariff switch (nid) { 2183162922Sariff case 24: /* MIC1 */ 2184162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2185162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2186162922Sariff break; 2187162922Sariff case 25: /* XXX MIC2 */ 2188162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2189162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2190162922Sariff break; 2191162922Sariff case 26: /* LINE1 */ 2192162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2193162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2194162922Sariff break; 2195162922Sariff case 27: /* XXX LINE2 */ 2196162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2197162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2198162922Sariff break; 2199162922Sariff case 28: /* CD */ 2200162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2201162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2202162922Sariff break; 2203162922Sariff } 2204166965Sariff } else if (id == HDA_CODEC_ALC883 && 2205172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2206172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2207166965Sariff switch (nid) { 2208166965Sariff case 25: 2209166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2210166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2211166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2212166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2213166965Sariff break; 2214169277Sariff case 28: 2215169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2216169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2217169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2218169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2219169277Sariff break; 2220166965Sariff } 2221166965Sariff } else if (id == HDA_CODEC_CXVENICE && sc->pci_subvendor == 2222166965Sariff HP_V3000_SUBVENDOR) { 2223166965Sariff switch (nid) { 2224166965Sariff case 18: 2225166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2226166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2227166965Sariff break; 2228166965Sariff case 20: 2229166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2230166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2231166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2232166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2233166965Sariff break; 2234167454Sariff case 21: 2235167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2236167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2237167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2238167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2239167454Sariff break; 2240166965Sariff } 2241169277Sariff } else if (id == HDA_CODEC_CXWAIKIKI && sc->pci_subvendor == 2242169277Sariff HP_DV5000_SUBVENDOR) { 2243169277Sariff switch (nid) { 2244169277Sariff case 20: 2245169277Sariff case 21: 2246169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2247169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2248169277Sariff break; 2249169277Sariff } 2250169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2251169277Sariff ASUS_W6F_SUBVENDOR) { 2252169277Sariff switch (nid) { 2253169277Sariff case 11: 2254169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2255169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2256169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2257169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2258169277Sariff break; 2259178324Sariff case 12: 2260178324Sariff case 14: 2261178324Sariff case 16: 2262178324Sariff case 31: 2263178324Sariff case 32: 2264178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2265178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2266178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2267178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2268178324Sariff break; 2269169277Sariff case 15: 2270169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2271169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2272169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2273169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2274169277Sariff break; 2275169277Sariff } 2276169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2277169277Sariff UNIWILL_9075_SUBVENDOR) { 2278169277Sariff switch (nid) { 2279169277Sariff case 15: 2280169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2281169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2282169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2283169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2284169277Sariff break; 2285169277Sariff } 2286182999Smav } 2287182999Smav 2288182999Smav /* New patches */ 2289182999Smav if (id == HDA_CODEC_AD1986A && 2290171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2291171141Sariff sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) { 2292169277Sariff switch (nid) { 2293182999Smav case 28: /* 5.1 out => 2.0 out + 2 inputs */ 2294182999Smav patch = "device=Line-in as=8 seq=1"; 2295169277Sariff break; 2296182999Smav case 29: 2297182999Smav patch = "device=Mic as=8 seq=2"; 2298169277Sariff break; 2299182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2300182999Smav patch = "as=8 seq=3"; 2301169277Sariff break; 2302182999Smav case 32: 2303182999Smav patch = "as=8 seq=4"; 2304182999Smav break; 2305182999Smav case 34: 2306182999Smav patch = "as=8 seq=5"; 2307182999Smav break; 2308182999Smav case 36: 2309182999Smav patch = "as=8 seq=6"; 2310182999Smav break; 2311169277Sariff } 2312182999Smav } else if (id == HDA_CODEC_ALC260 && 2313182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2314182999Smav switch (nid) { 2315182999Smav case 16: 2316182999Smav patch = "seq=15 device=Headphones"; 2317182999Smav break; 2318182999Smav } 2319174578Sariff } else if (id == HDA_CODEC_ALC268 && 2320174578Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) { 2321174578Sariff switch (nid) { 2322174578Sariff case 28: 2323182999Smav patch = "device=CD conn=fixed"; 2324174578Sariff break; 2325174578Sariff } 2326162922Sariff } 2327162922Sariff 2328182999Smav if (patch != NULL) 2329182999Smav config = hdac_widget_pin_patch(config, patch); 2330182999Smav 2331182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2332182999Smav if (resource_string_value(device_get_name(sc->dev), 2333182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2334182999Smav if (strncmp(res, "0x", 2) == 0) { 2335182999Smav config = strtol(res + 2, NULL, 16); 2336182999Smav } else { 2337182999Smav config = hdac_widget_pin_patch(config, res); 2338182999Smav } 2339182999Smav } 2340182999Smav 2341166965Sariff HDA_BOOTVERBOSE( 2342166965Sariff if (config != orig) 2343166965Sariff device_printf(sc->dev, 2344182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2345166965Sariff nid, orig, config); 2346166965Sariff ); 2347166965Sariff 2348162922Sariff return (config); 2349162922Sariff} 2350162922Sariff 2351166965Sariffstatic uint32_t 2352166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2353166965Sariff{ 2354166965Sariff struct hdac_softc *sc; 2355166965Sariff uint32_t caps, orig, id; 2356166965Sariff nid_t cad, nid; 2357166965Sariff 2358166965Sariff sc = w->devinfo->codec->sc; 2359166965Sariff cad = w->devinfo->codec->cad; 2360166965Sariff nid = w->nid; 2361182999Smav id = hdac_codec_id(w->devinfo->codec); 2362166965Sariff 2363166965Sariff caps = hdac_command(sc, 2364166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2365166965Sariff orig = caps; 2366166965Sariff 2367166965Sariff HDA_BOOTVERBOSE( 2368166965Sariff if (caps != orig) 2369166965Sariff device_printf(sc->dev, 2370182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2371166965Sariff nid, orig, caps); 2372166965Sariff ); 2373166965Sariff 2374166965Sariff return (caps); 2375166965Sariff} 2376166965Sariff 2377162922Sariffstatic void 2378162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2379162922Sariff{ 2380162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2381162922Sariff uint32_t config, pincap; 2382182999Smav const char *devstr, *connstr; 2383162922Sariff nid_t cad = w->devinfo->codec->cad; 2384162922Sariff nid_t nid = w->nid; 2385162922Sariff 2386162922Sariff config = hdac_widget_pin_getconfig(w); 2387162922Sariff w->wclass.pin.config = config; 2388162922Sariff 2389166965Sariff pincap = hdac_widget_pin_getcaps(w); 2390162922Sariff w->wclass.pin.cap = pincap; 2391162922Sariff 2392162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2393182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2394162922Sariff 2395162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2396162922Sariff w->param.eapdbtl = hdac_command(sc, 2397162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2398162922Sariff w->param.eapdbtl &= 0x7; 2399162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2400162922Sariff } else 2401162965Sariff w->param.eapdbtl = HDAC_INVALID; 2402162922Sariff 2403182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2404182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2405162922Sariff 2406182999Smav connstr = HDA_CONNS[(config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2407182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT]; 2408162922Sariff 2409162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2410162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2411162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2412162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 2413162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2414162922Sariff} 2415162922Sariff 2416182999Smavstatic uint32_t 2417182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2418182999Smav{ 2419182999Smav struct hdac_softc *sc; 2420182999Smav uint32_t caps, orig, id; 2421182999Smav nid_t cad, nid, beeper = -1; 2422182999Smav 2423182999Smav sc = w->devinfo->codec->sc; 2424182999Smav cad = w->devinfo->codec->cad; 2425182999Smav nid = w->nid; 2426182999Smav id = hdac_codec_id(w->devinfo->codec); 2427182999Smav 2428182999Smav caps = hdac_command(sc, 2429182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2430182999Smav cad); 2431182999Smav orig = caps; 2432182999Smav 2433182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2434182999Smav alone. Also most of BIOSes does not declare beeper pin. 2435182999Smav Change beeper pin node type to beeper to help parser. */ 2436182999Smav *waspin = 0; 2437182999Smav switch (id) { 2438182999Smav case HDA_CODEC_AD1988: 2439182999Smav case HDA_CODEC_AD1988B: 2440182999Smav beeper = 26; 2441182999Smav break; 2442182999Smav case HDA_CODEC_ALC260: 2443182999Smav beeper = 23; 2444182999Smav break; 2445182999Smav case HDA_CODEC_ALC262: 2446182999Smav case HDA_CODEC_ALC268: 2447182999Smav case HDA_CODEC_ALC880: 2448182999Smav case HDA_CODEC_ALC882: 2449182999Smav case HDA_CODEC_ALC883: 2450182999Smav case HDA_CODEC_ALC885: 2451182999Smav case HDA_CODEC_ALC888: 2452182999Smav case HDA_CODEC_ALC889: 2453182999Smav beeper = 29; 2454182999Smav break; 2455182999Smav } 2456182999Smav if (nid == beeper) { 2457182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2458182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2459182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2460182999Smav *waspin = 1; 2461182999Smav } 2462182999Smav 2463182999Smav HDA_BOOTVERBOSE( 2464182999Smav if (caps != orig) { 2465182999Smav device_printf(sc->dev, 2466182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2467182999Smav nid, orig, caps); 2468182999Smav } 2469182999Smav ); 2470182999Smav 2471182999Smav return (caps); 2472182999Smav} 2473182999Smav 2474162922Sariffstatic void 2475162922Sariffhdac_widget_parse(struct hdac_widget *w) 2476162922Sariff{ 2477162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2478162922Sariff uint32_t wcap, cap; 2479162922Sariff char *typestr; 2480162922Sariff nid_t cad = w->devinfo->codec->cad; 2481162922Sariff nid_t nid = w->nid; 2482162922Sariff 2483182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2484182999Smav 2485162922Sariff w->param.widget_cap = wcap; 2486162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2487162922Sariff 2488162922Sariff switch (w->type) { 2489162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2490162922Sariff typestr = "audio output"; 2491162922Sariff break; 2492162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2493162922Sariff typestr = "audio input"; 2494162922Sariff break; 2495162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2496162922Sariff typestr = "audio mixer"; 2497162922Sariff break; 2498162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2499162922Sariff typestr = "audio selector"; 2500162922Sariff break; 2501162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2502162922Sariff typestr = "pin"; 2503162922Sariff break; 2504162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2505162922Sariff typestr = "power widget"; 2506162922Sariff break; 2507162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2508162922Sariff typestr = "volume widget"; 2509162922Sariff break; 2510162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2511162922Sariff typestr = "beep widget"; 2512162922Sariff break; 2513162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2514162922Sariff typestr = "vendor widget"; 2515162922Sariff break; 2516162922Sariff default: 2517162922Sariff typestr = "unknown type"; 2518162922Sariff break; 2519162922Sariff } 2520162922Sariff 2521162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2522162922Sariff 2523162922Sariff hdac_widget_connection_parse(w); 2524162922Sariff 2525162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2526162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2527162922Sariff w->param.outamp_cap = 2528162922Sariff hdac_command(sc, 2529162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2530162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2531162922Sariff else 2532162922Sariff w->param.outamp_cap = 2533162922Sariff w->devinfo->function.audio.outamp_cap; 2534162922Sariff } else 2535162922Sariff w->param.outamp_cap = 0; 2536162922Sariff 2537162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2538162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2539162922Sariff w->param.inamp_cap = 2540162922Sariff hdac_command(sc, 2541162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2542162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2543162922Sariff else 2544162922Sariff w->param.inamp_cap = 2545162922Sariff w->devinfo->function.audio.inamp_cap; 2546162922Sariff } else 2547162922Sariff w->param.inamp_cap = 0; 2548162922Sariff 2549162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2550162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2551162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2552162922Sariff cap = hdac_command(sc, 2553162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2554162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2555162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2556162922Sariff w->devinfo->function.audio.supp_stream_formats; 2557162922Sariff cap = hdac_command(sc, 2558162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2559162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2560162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2561162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2562162922Sariff } else { 2563162922Sariff w->param.supp_stream_formats = 2564162922Sariff w->devinfo->function.audio.supp_stream_formats; 2565162922Sariff w->param.supp_pcm_size_rate = 2566162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2567162922Sariff } 2568162922Sariff } else { 2569162922Sariff w->param.supp_stream_formats = 0; 2570162922Sariff w->param.supp_pcm_size_rate = 0; 2571162922Sariff } 2572162922Sariff 2573162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2574162922Sariff hdac_widget_pin_parse(w); 2575162922Sariff} 2576162922Sariff 2577162922Sariffstatic struct hdac_widget * 2578162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2579162922Sariff{ 2580162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2581162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2582162922Sariff return (NULL); 2583162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2584162922Sariff} 2585162922Sariff 2586164614Sariffstatic __inline int 2587164614Sariffhda_poll_channel(struct hdac_chan *ch) 2588164614Sariff{ 2589164614Sariff uint32_t sz, delta; 2590164614Sariff volatile uint32_t ptr; 2591164614Sariff 2592171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2593164614Sariff return (0); 2594164614Sariff 2595164614Sariff sz = ch->blksz * ch->blkcnt; 2596169277Sariff if (ch->dmapos != NULL) 2597169277Sariff ptr = *(ch->dmapos); 2598169277Sariff else 2599169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2600169277Sariff ch->off + HDAC_SDLPIB); 2601164614Sariff ch->ptr = ptr; 2602164614Sariff ptr %= sz; 2603164614Sariff ptr &= ~(ch->blksz - 1); 2604164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2605164614Sariff 2606164614Sariff if (delta < ch->blksz) 2607164614Sariff return (0); 2608164614Sariff 2609164614Sariff ch->prevptr = ptr; 2610164614Sariff 2611164614Sariff return (1); 2612164614Sariff} 2613164614Sariff 2614162922Sariffstatic void 2615164614Sariffhda_poll_callback(void *arg) 2616164614Sariff{ 2617164614Sariff struct hdac_softc *sc = arg; 2618171141Sariff uint32_t trigger; 2619182999Smav int i, active = 0; 2620164614Sariff 2621164614Sariff if (sc == NULL) 2622164614Sariff return; 2623164614Sariff 2624164614Sariff hdac_lock(sc); 2625182999Smav if (sc->polling == 0) { 2626164614Sariff hdac_unlock(sc); 2627164614Sariff return; 2628164614Sariff } 2629164614Sariff 2630171141Sariff trigger = 0; 2631182999Smav for (i = 0; i < sc->num_chans; i++) { 2632182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2633182999Smav continue; 2634182999Smav active = 1; 2635182999Smav if (hda_poll_channel(&sc->chans[i])) 2636182999Smav trigger |= (1 << i); 2637182999Smav } 2638164614Sariff 2639164614Sariff /* XXX */ 2640182999Smav if (active) 2641182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2642182999Smav hda_poll_callback, sc); 2643164614Sariff 2644164614Sariff hdac_unlock(sc); 2645164614Sariff 2646182999Smav for (i = 0; i < sc->num_chans; i++) { 2647182999Smav if (trigger & (1 << i)) 2648182999Smav chn_intr(sc->chans[i].c); 2649182999Smav } 2650164614Sariff} 2651164614Sariff 2652164614Sariffstatic int 2653164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2654164614Sariff{ 2655164614Sariff struct hdac_rirb *rirb_base, *rirb; 2656164614Sariff struct hdac_codec *codec; 2657164614Sariff struct hdac_command_list *commands; 2658164614Sariff nid_t cad; 2659164614Sariff uint32_t resp; 2660164614Sariff uint8_t rirbwp; 2661171141Sariff int ret; 2662164614Sariff 2663164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2664164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2665169277Sariff#if 0 2666164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2667164614Sariff BUS_DMASYNC_POSTREAD); 2668169277Sariff#endif 2669164614Sariff 2670171141Sariff ret = 0; 2671171141Sariff 2672164614Sariff while (sc->rirb_rp != rirbwp) { 2673164614Sariff sc->rirb_rp++; 2674164614Sariff sc->rirb_rp %= sc->rirb_size; 2675164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2676164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2677164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2678164614Sariff sc->codecs[cad] == NULL) 2679164614Sariff continue; 2680164614Sariff resp = rirb->response; 2681164614Sariff codec = sc->codecs[cad]; 2682164614Sariff commands = codec->commands; 2683164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2684164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2685164614Sariff ((resp >> 26) & 0xffff); 2686164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2687164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2688164614Sariff codec->responses_received < commands->num_commands) 2689164614Sariff commands->responses[codec->responses_received++] = 2690164614Sariff resp; 2691164614Sariff ret++; 2692164614Sariff } 2693164614Sariff 2694164614Sariff return (ret); 2695164614Sariff} 2696164614Sariff 2697164614Sariffstatic int 2698164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2699164614Sariff{ 2700164614Sariff nid_t cad; 2701164614Sariff uint32_t tag; 2702164614Sariff int ret = 0; 2703164614Sariff 2704164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2705164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2706164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2707164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2708164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2709164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2710164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2711164614Sariff ret++; 2712164614Sariff } 2713164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2714164614Sariff } 2715164614Sariff 2716164614Sariff return (ret); 2717164614Sariff} 2718164614Sariff 2719164614Sariffstatic void 2720164614Sariffhdac_poll_callback(void *arg) 2721164614Sariff{ 2722164614Sariff struct hdac_softc *sc = arg; 2723164614Sariff if (sc == NULL) 2724164614Sariff return; 2725166796Sariff 2726164614Sariff hdac_lock(sc); 2727169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2728164614Sariff hdac_unlock(sc); 2729164614Sariff return; 2730164614Sariff } 2731171141Sariff if (hdac_rirb_flush(sc) != 0) 2732171141Sariff hdac_unsolq_flush(sc); 2733169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2734164614Sariff hdac_unlock(sc); 2735164614Sariff} 2736164614Sariff 2737164614Sariffstatic void 2738182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2739182999Smav{ 2740182999Smav int i, pollticks, min = 1000000; 2741182999Smav struct hdac_chan *ch; 2742182999Smav 2743182999Smav for (i = 0; i < sc->num_chans; i++) { 2744182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2745182999Smav continue; 2746182999Smav ch = &sc->chans[i]; 2747182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2748182999Smav ((uint64_t)sndbuf_getbps(ch->b) * 2749182999Smav sndbuf_getspd(ch->b)); 2750182999Smav pollticks >>= 1; 2751182999Smav if (pollticks > hz) 2752182999Smav pollticks = hz; 2753182999Smav if (pollticks < 1) { 2754182999Smav HDA_BOOTVERBOSE( 2755182999Smav device_printf(sc->dev, 2756182999Smav "%s: pollticks=%d < 1 !\n", 2757182999Smav __func__, pollticks); 2758182999Smav ); 2759182999Smav pollticks = 1; 2760182999Smav } 2761182999Smav if (min > pollticks) 2762182999Smav min = pollticks; 2763182999Smav } 2764182999Smav HDA_BOOTVERBOSE( 2765182999Smav device_printf(sc->dev, 2766182999Smav "%s: pollticks %d -> %d\n", 2767182999Smav __func__, sc->poll_ticks, min); 2768182999Smav ); 2769182999Smav sc->poll_ticks = min; 2770182999Smav if (min == 1000000) 2771182999Smav callout_stop(&sc->poll_hda); 2772182999Smav else 2773182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 2774182999Smav} 2775182999Smav 2776182999Smavstatic void 2777162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2778162922Sariff{ 2779162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2780162922Sariff uint32_t ctl; 2781162922Sariff 2782162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2783162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2784162922Sariff HDAC_SDCTL_RUN); 2785162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2786162922Sariff 2787171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 2788164614Sariff 2789182999Smav if (sc->polling != 0) 2790182999Smav hdac_poll_reinit(sc); 2791164614Sariff 2792182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2793182999Smav ctl &= ~(1 << (ch->off >> 5)); 2794182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2795162922Sariff} 2796162922Sariff 2797162922Sariffstatic void 2798162922Sariffhdac_stream_start(struct hdac_chan *ch) 2799162922Sariff{ 2800162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2801162922Sariff uint32_t ctl; 2802162922Sariff 2803182999Smav ch->flags |= HDAC_CHN_RUNNING; 2804162922Sariff 2805182999Smav if (sc->polling != 0) 2806182999Smav hdac_poll_reinit(sc); 2807182999Smav 2808182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2809182999Smav ctl |= 1 << (ch->off >> 5); 2810182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2811182999Smav 2812182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2813182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2814182999Smav HDAC_SDCTL_RUN; 2815162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2816162922Sariff} 2817162922Sariff 2818162922Sariffstatic void 2819162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2820162922Sariff{ 2821162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2822162922Sariff int timeout = 1000; 2823162922Sariff int to = timeout; 2824162922Sariff uint32_t ctl; 2825162922Sariff 2826162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2827162922Sariff ctl |= HDAC_SDCTL_SRST; 2828162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2829162922Sariff do { 2830162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2831162922Sariff if (ctl & HDAC_SDCTL_SRST) 2832162922Sariff break; 2833162922Sariff DELAY(10); 2834162922Sariff } while (--to); 2835162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2836162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2837162922Sariff } 2838162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2839162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2840162922Sariff to = timeout; 2841162922Sariff do { 2842162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2843162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2844162922Sariff break; 2845162922Sariff DELAY(10); 2846162922Sariff } while (--to); 2847163057Sariff if (ctl & HDAC_SDCTL_SRST) 2848162922Sariff device_printf(sc->dev, "can't reset!\n"); 2849162922Sariff} 2850162922Sariff 2851162922Sariffstatic void 2852162922Sariffhdac_stream_setid(struct hdac_chan *ch) 2853162922Sariff{ 2854162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2855162922Sariff uint32_t ctl; 2856162922Sariff 2857162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 2858162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 2859162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 2860162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 2861162922Sariff} 2862162922Sariff 2863162922Sariffstatic void 2864162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 2865162922Sariff{ 2866162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2867164614Sariff struct hdac_bdle *bdle; 2868162922Sariff uint64_t addr; 2869164614Sariff uint32_t blksz, blkcnt; 2870162922Sariff int i; 2871162922Sariff 2872162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 2873164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 2874162922Sariff 2875182999Smav blksz = ch->blksz; 2876182999Smav blkcnt = ch->blkcnt; 2877164614Sariff 2878164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 2879162922Sariff bdle->addrl = (uint32_t)addr; 2880162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 2881164614Sariff bdle->len = blksz; 2882182999Smav bdle->ioc = 1; 2883164614Sariff addr += blksz; 2884162922Sariff } 2885162922Sariff 2886164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 2887164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 2888162922Sariff addr = ch->bdl_dma.dma_paddr; 2889162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 2890162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 2891169277Sariff if (ch->dmapos != NULL && 2892169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 2893169277Sariff addr = sc->pos_dma.dma_paddr; 2894169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 2895169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 2896169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 2897169277Sariff } 2898162922Sariff} 2899162922Sariff 2900162922Sariffstatic int 2901162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 2902162922Sariff{ 2903162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2904162922Sariff int rc; 2905162922Sariff 2906162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 2907162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 2908162922Sariff if (rc) { 2909162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 2910162922Sariff return (rc); 2911162922Sariff } 2912162922Sariff 2913162922Sariff return (0); 2914162922Sariff} 2915162922Sariff 2916162922Sariffstatic void 2917162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 2918162922Sariff int index, int lmute, int rmute, 2919162922Sariff int left, int right, int dir) 2920162922Sariff{ 2921162922Sariff uint16_t v = 0; 2922162922Sariff 2923162922Sariff if (sc == NULL) 2924162922Sariff return; 2925162922Sariff 2926162922Sariff if (left != right || lmute != rmute) { 2927162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 2928162922Sariff (lmute << 7) | left; 2929162922Sariff hdac_command(sc, 2930164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2931162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 2932162922Sariff (rmute << 7) | right; 2933162922Sariff } else 2934162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 2935162922Sariff (lmute << 7) | left; 2936162922Sariff 2937162922Sariff hdac_command(sc, 2938162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2939162922Sariff} 2940162922Sariff 2941162922Sariffstatic void 2942162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 2943162922Sariff int left, int right) 2944162922Sariff{ 2945162922Sariff struct hdac_softc *sc; 2946162922Sariff nid_t nid, cad; 2947162922Sariff int lmute, rmute; 2948162922Sariff 2949162922Sariff sc = ctl->widget->devinfo->codec->sc; 2950162922Sariff cad = ctl->widget->devinfo->codec->cad; 2951162922Sariff nid = ctl->widget->nid; 2952162922Sariff 2953182999Smav /* Save new values if valid. */ 2954182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 2955182999Smav ctl->muted = mute; 2956182999Smav if (left != HDA_AMP_VOL_DEFAULT) 2957182999Smav ctl->left = left; 2958182999Smav if (right != HDA_AMP_VOL_DEFAULT) 2959182999Smav ctl->right = right; 2960182999Smav /* Prepare effective values */ 2961182999Smav if (ctl->forcemute) { 2962182999Smav lmute = 1; 2963182999Smav rmute = 1; 2964182999Smav left = 0; 2965182999Smav right = 0; 2966182999Smav } else { 2967162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 2968162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 2969182999Smav left = ctl->left; 2970182999Smav right = ctl->right; 2971162922Sariff } 2972182999Smav /* Apply effective values */ 2973162922Sariff if (ctl->dir & HDA_CTL_OUT) 2974162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2975162922Sariff lmute, rmute, left, right, 0); 2976162922Sariff if (ctl->dir & HDA_CTL_IN) 2977182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2978162922Sariff lmute, rmute, left, right, 1); 2979162922Sariff} 2980162922Sariff 2981162922Sariffstatic void 2982162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 2983162922Sariff{ 2984162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 2985162922Sariff return; 2986162922Sariff hdac_command(w->devinfo->codec->sc, 2987162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 2988162922Sariff w->nid, index), w->devinfo->codec->cad); 2989162922Sariff w->selconn = index; 2990162922Sariff} 2991162922Sariff 2992162922Sariff 2993162922Sariff/**************************************************************************** 2994162922Sariff * uint32_t hdac_command_sendone_internal 2995162922Sariff * 2996162922Sariff * Wrapper function that sends only one command to a given codec 2997162922Sariff ****************************************************************************/ 2998162922Sariffstatic uint32_t 2999162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3000162922Sariff{ 3001162922Sariff struct hdac_command_list cl; 3002162965Sariff uint32_t response = HDAC_INVALID; 3003162922Sariff 3004163057Sariff if (!hdac_lockowned(sc)) 3005162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3006162922Sariff cl.num_commands = 1; 3007162922Sariff cl.verbs = &verb; 3008162922Sariff cl.responses = &response; 3009162922Sariff 3010162922Sariff hdac_command_send_internal(sc, &cl, cad); 3011162922Sariff 3012162922Sariff return (response); 3013162922Sariff} 3014162922Sariff 3015162922Sariff/**************************************************************************** 3016162922Sariff * hdac_command_send_internal 3017162922Sariff * 3018162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3019162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3020162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3021162922Sariff * if any. 3022162922Sariff ****************************************************************************/ 3023162922Sariffstatic void 3024162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3025162922Sariff struct hdac_command_list *commands, nid_t cad) 3026162922Sariff{ 3027162922Sariff struct hdac_codec *codec; 3028162922Sariff int corbrp; 3029162922Sariff uint32_t *corb; 3030162922Sariff int timeout; 3031162922Sariff int retry = 10; 3032164614Sariff struct hdac_rirb *rirb_base; 3033162922Sariff 3034164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3035164614Sariff commands->num_commands < 1) 3036162922Sariff return; 3037162922Sariff 3038162922Sariff codec = sc->codecs[cad]; 3039162922Sariff codec->commands = commands; 3040162922Sariff codec->responses_received = 0; 3041162922Sariff codec->verbs_sent = 0; 3042162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3043162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3044162922Sariff 3045162922Sariff do { 3046162922Sariff if (codec->verbs_sent != commands->num_commands) { 3047162922Sariff /* Queue as many verbs as possible */ 3048162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3049169277Sariff#if 0 3050162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3051162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3052169277Sariff#endif 3053162922Sariff while (codec->verbs_sent != commands->num_commands && 3054162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3055162922Sariff sc->corb_wp++; 3056162922Sariff sc->corb_wp %= sc->corb_size; 3057162922Sariff corb[sc->corb_wp] = 3058162922Sariff commands->verbs[codec->verbs_sent++]; 3059162922Sariff } 3060162922Sariff 3061162922Sariff /* Send the verbs to the codecs */ 3062169277Sariff#if 0 3063162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3064162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3065169277Sariff#endif 3066162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3067162922Sariff } 3068162922Sariff 3069162922Sariff timeout = 1000; 3070164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3071162922Sariff DELAY(10); 3072162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3073164614Sariff codec->responses_received != commands->num_commands) && --retry); 3074162922Sariff 3075162922Sariff if (retry == 0) 3076162922Sariff device_printf(sc->dev, 3077164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3078164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3079164614Sariff codec->responses_received); 3080162922Sariff 3081164614Sariff codec->commands = NULL; 3082164614Sariff codec->responses_received = 0; 3083162922Sariff codec->verbs_sent = 0; 3084162922Sariff 3085164614Sariff hdac_unsolq_flush(sc); 3086162922Sariff} 3087162922Sariff 3088162922Sariff 3089162922Sariff/**************************************************************************** 3090162922Sariff * Device Methods 3091162922Sariff ****************************************************************************/ 3092162922Sariff 3093162922Sariff/**************************************************************************** 3094162922Sariff * int hdac_probe(device_t) 3095162922Sariff * 3096162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3097162922Sariff * match using the subclass of the device. 3098162922Sariff ****************************************************************************/ 3099162922Sariffstatic int 3100162922Sariffhdac_probe(device_t dev) 3101162922Sariff{ 3102162922Sariff int i, result; 3103163257Sariff uint32_t model; 3104163257Sariff uint16_t class, subclass; 3105162922Sariff char desc[64]; 3106162922Sariff 3107162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3108162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3109162922Sariff class = pci_get_class(dev); 3110162922Sariff subclass = pci_get_subclass(dev); 3111162922Sariff 3112162922Sariff bzero(desc, sizeof(desc)); 3113162922Sariff result = ENXIO; 3114162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3115162922Sariff if (hdac_devices[i].model == model) { 3116162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3117162922Sariff result = BUS_PROBE_DEFAULT; 3118162922Sariff break; 3119162922Sariff } 3120163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3121162922Sariff class == PCIC_MULTIMEDIA && 3122162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3123162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3124162922Sariff result = BUS_PROBE_GENERIC; 3125162922Sariff break; 3126162922Sariff } 3127162922Sariff } 3128162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3129162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3130162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3131162922Sariff result = BUS_PROBE_GENERIC; 3132162922Sariff } 3133162922Sariff if (result != ENXIO) { 3134162922Sariff strlcat(desc, " High Definition Audio Controller", 3135162922Sariff sizeof(desc)); 3136162922Sariff device_set_desc_copy(dev, desc); 3137162922Sariff } 3138162922Sariff 3139162922Sariff return (result); 3140162922Sariff} 3141162922Sariff 3142162922Sariffstatic void * 3143162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3144162922Sariff struct pcm_channel *c, int dir) 3145162922Sariff{ 3146182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3147182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3148162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3149162922Sariff struct hdac_chan *ch; 3150182999Smav int i, ord = 0, chid; 3151162922Sariff 3152162922Sariff hdac_lock(sc); 3153182999Smav 3154182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3155182999Smav ch = &sc->chans[chid]; 3156182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3157182999Smav if (ch->dir == sc->chans[i].dir) 3158182999Smav ord++; 3159182999Smav } 3160162922Sariff if (dir == PCMDIR_PLAY) { 3161182999Smav ch->off = (sc->num_iss + ord) << 5; 3162162922Sariff } else { 3163182999Smav ch->off = ord << 5; 3164162922Sariff } 3165182999Smav 3166162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3167162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3168162922Sariff ch->pcmrates[0] = 48000; 3169162922Sariff ch->pcmrates[1] = 0; 3170162922Sariff } 3171169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3172169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3173169277Sariff (sc->streamcnt * 8)); 3174169277Sariff else 3175169277Sariff ch->dmapos = NULL; 3176169277Sariff ch->sid = ++sc->streamcnt; 3177169277Sariff ch->dir = dir; 3178162922Sariff ch->b = b; 3179162922Sariff ch->c = c; 3180182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3181182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3182162922Sariff hdac_unlock(sc); 3183162922Sariff 3184162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3185162922Sariff ch->blkcnt = 0; 3186162922Sariff return (NULL); 3187162922Sariff } 3188162922Sariff 3189169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3190171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3191182999Smav pdevinfo->chan_size) != 0) 3192162922Sariff return (NULL); 3193162922Sariff 3194162922Sariff return (ch); 3195162922Sariff} 3196162922Sariff 3197162922Sariffstatic int 3198162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3199162922Sariff{ 3200162922Sariff struct hdac_chan *ch = data; 3201162922Sariff int i; 3202162922Sariff 3203162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3204162922Sariff if (format == ch->caps.fmtlist[i]) { 3205162922Sariff ch->fmt = format; 3206162922Sariff return (0); 3207162922Sariff } 3208162922Sariff } 3209162922Sariff 3210162922Sariff return (EINVAL); 3211162922Sariff} 3212162922Sariff 3213162922Sariffstatic int 3214162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3215162922Sariff{ 3216162922Sariff struct hdac_chan *ch = data; 3217164614Sariff uint32_t spd = 0, threshold; 3218162922Sariff int i; 3219162922Sariff 3220162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3221162922Sariff spd = ch->pcmrates[i]; 3222164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3223164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3224164614Sariff if (speed < threshold) 3225162922Sariff break; 3226162922Sariff } 3227162922Sariff 3228164614Sariff if (spd == 0) /* impossible */ 3229162922Sariff ch->spd = 48000; 3230162922Sariff else 3231162922Sariff ch->spd = spd; 3232162922Sariff 3233162922Sariff return (ch->spd); 3234162922Sariff} 3235162922Sariff 3236162922Sariffstatic void 3237162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3238162922Sariff{ 3239162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3240182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3241173817Sariff struct hdac_widget *w; 3242182999Smav int i, chn, totalchn, c; 3243162922Sariff nid_t cad = ch->devinfo->codec->cad; 3244182999Smav uint16_t fmt, dfmt; 3245162922Sariff 3246183097Smav HDA_BOOTHVERBOSE( 3247182999Smav device_printf(ch->pdevinfo->dev, 3248182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3249182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3250182999Smav ch->fmt, ch->spd); 3251182999Smav ); 3252162922Sariff fmt = 0; 3253162922Sariff if (ch->fmt & AFMT_S16_LE) 3254162922Sariff fmt |= ch->bit16 << 4; 3255162922Sariff else if (ch->fmt & AFMT_S32_LE) 3256162922Sariff fmt |= ch->bit32 << 4; 3257162922Sariff else 3258162922Sariff fmt |= 1 << 4; 3259162922Sariff 3260162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3261162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3262162922Sariff fmt |= hda_rate_tab[i].base; 3263162922Sariff fmt |= hda_rate_tab[i].mul; 3264162922Sariff fmt |= hda_rate_tab[i].div; 3265162922Sariff break; 3266162922Sariff } 3267162922Sariff } 3268162922Sariff 3269182999Smav if (ch->fmt & (AFMT_STEREO | AFMT_AC3)) { 3270162922Sariff fmt |= 1; 3271173817Sariff totalchn = 2; 3272173817Sariff } else 3273173817Sariff totalchn = 1; 3274162922Sariff 3275162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3276182999Smav 3277182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3278182999Smav if (ch->fmt & AFMT_AC3) 3279182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3280162922Sariff 3281173817Sariff chn = 0; 3282162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3283173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3284173817Sariff if (w == NULL) 3285173817Sariff continue; 3286182999Smav 3287182999Smav if (as->hpredir >= 0 && i == as->pincnt) 3288182999Smav chn = 0; 3289183097Smav HDA_BOOTHVERBOSE( 3290182999Smav device_printf(ch->pdevinfo->dev, 3291182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3292182999Smav "fmt=0x%04x, dfmt=0x%04x\n", 3293162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3294182999Smav ch->io[i], fmt, dfmt); 3295162922Sariff ); 3296162922Sariff hdac_command(sc, 3297162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3298182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3299174025Sariff hdac_command(sc, 3300182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3301174025Sariff cad); 3302182999Smav } 3303182999Smav /* If HP redirection is enabled, but failed to use same 3304182999Smav DAC make last DAC one to duplicate first one. */ 3305182999Smav if (as->hpredir >= 0 && i == as->pincnt) { 3306182999Smav c = (ch->sid << 4); 3307182999Smav } else if (chn >= totalchn) { 3308182999Smav /* This is until OSS will support multichannel. 3309182999Smav Should be: c = 0; to disable unused DAC */ 3310182999Smav c = (ch->sid << 4); 3311182999Smav }else { 3312182999Smav c = (ch->sid << 4) | chn; 3313182999Smav } 3314182999Smav hdac_command(sc, 3315182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3316173817Sariff chn += 3317173817Sariff HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ? 3318173817Sariff 2 : 1; 3319162922Sariff } 3320162922Sariff} 3321162922Sariff 3322162922Sariffstatic int 3323167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3324167648Sariff uint32_t blksz, uint32_t blkcnt) 3325162922Sariff{ 3326162922Sariff struct hdac_chan *ch = data; 3327164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3328162922Sariff 3329167648Sariff blksz &= HDA_BLK_ALIGN; 3330162922Sariff 3331167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3332167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3333167648Sariff if (blksz < HDA_BLK_MIN) 3334167648Sariff blksz = HDA_BLK_MIN; 3335167648Sariff if (blkcnt > HDA_BDL_MAX) 3336167648Sariff blkcnt = HDA_BDL_MAX; 3337167648Sariff if (blkcnt < HDA_BDL_MIN) 3338167648Sariff blkcnt = HDA_BDL_MIN; 3339164614Sariff 3340167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3341167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3342167648Sariff blkcnt >>= 1; 3343167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3344167648Sariff blksz >>= 1; 3345167648Sariff else 3346167648Sariff break; 3347167648Sariff } 3348167648Sariff 3349164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3350167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3351167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3352164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3353167648Sariff __func__, blksz, blkcnt); 3354164614Sariff 3355164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3356167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3357164614Sariff 3358167648Sariff return (1); 3359167648Sariff} 3360167648Sariff 3361167648Sariffstatic int 3362167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3363167648Sariff{ 3364167648Sariff struct hdac_chan *ch = data; 3365167648Sariff 3366182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3367167648Sariff 3368162922Sariff return (ch->blksz); 3369162922Sariff} 3370162922Sariff 3371162922Sariffstatic void 3372162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3373162922Sariff{ 3374162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3375182999Smav struct hdac_widget *w; 3376162922Sariff nid_t cad = devinfo->codec->cad; 3377162922Sariff int i; 3378162922Sariff 3379162922Sariff hdac_stream_stop(ch); 3380162922Sariff 3381162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3382182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3383182999Smav if (w == NULL) 3384182999Smav continue; 3385182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3386182999Smav hdac_command(sc, 3387182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3388182999Smav cad); 3389182999Smav } 3390162922Sariff hdac_command(sc, 3391162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3392162922Sariff 0), cad); 3393162922Sariff } 3394162922Sariff} 3395162922Sariff 3396162922Sariffstatic void 3397162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3398162922Sariff{ 3399162922Sariff ch->ptr = 0; 3400162922Sariff ch->prevptr = 0; 3401162922Sariff hdac_stream_stop(ch); 3402162922Sariff hdac_stream_reset(ch); 3403162922Sariff hdac_bdl_setup(ch); 3404162922Sariff hdac_stream_setid(ch); 3405162922Sariff hdac_stream_setup(ch); 3406162922Sariff hdac_stream_start(ch); 3407162922Sariff} 3408162922Sariff 3409162922Sariffstatic int 3410162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3411162922Sariff{ 3412162922Sariff struct hdac_chan *ch = data; 3413162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3414162922Sariff 3415170521Sariff if (!PCMTRIG_COMMON(go)) 3416170521Sariff return (0); 3417170521Sariff 3418162922Sariff hdac_lock(sc); 3419162922Sariff switch (go) { 3420162922Sariff case PCMTRIG_START: 3421162922Sariff hdac_channel_start(sc, ch); 3422162922Sariff break; 3423162922Sariff case PCMTRIG_STOP: 3424162922Sariff case PCMTRIG_ABORT: 3425162922Sariff hdac_channel_stop(sc, ch); 3426162922Sariff break; 3427167610Sariff default: 3428167610Sariff break; 3429162922Sariff } 3430162922Sariff hdac_unlock(sc); 3431162922Sariff 3432162922Sariff return (0); 3433162922Sariff} 3434162922Sariff 3435162922Sariffstatic int 3436162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3437162922Sariff{ 3438162922Sariff struct hdac_chan *ch = data; 3439162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3440162922Sariff uint32_t ptr; 3441162922Sariff 3442162922Sariff hdac_lock(sc); 3443164614Sariff if (sc->polling != 0) 3444164614Sariff ptr = ch->ptr; 3445169277Sariff else if (ch->dmapos != NULL) 3446169277Sariff ptr = *(ch->dmapos); 3447164614Sariff else 3448164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3449162922Sariff hdac_unlock(sc); 3450162922Sariff 3451164614Sariff /* 3452164614Sariff * Round to available space and force 128 bytes aligment. 3453164614Sariff */ 3454164614Sariff ptr %= ch->blksz * ch->blkcnt; 3455167648Sariff ptr &= HDA_BLK_ALIGN; 3456162922Sariff 3457162922Sariff return (ptr); 3458162922Sariff} 3459162922Sariff 3460162922Sariffstatic struct pcmchan_caps * 3461162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3462162922Sariff{ 3463162922Sariff return (&((struct hdac_chan *)data)->caps); 3464162922Sariff} 3465162922Sariff 3466162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3467162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3468162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3469162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3470162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3471167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3472162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3473162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3474162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3475162922Sariff { 0, 0 } 3476162922Sariff}; 3477162922SariffCHANNEL_DECLARE(hdac_channel); 3478162922Sariff 3479162922Sariffstatic int 3480162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3481162922Sariff{ 3482182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3483182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3484162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3485162922Sariff struct hdac_widget *w, *cw; 3486162922Sariff struct hdac_audio_ctl *ctl; 3487162922Sariff uint32_t mask, recmask, id; 3488162922Sariff int i, j, softpcmvol; 3489162922Sariff 3490162922Sariff hdac_lock(sc); 3491162922Sariff 3492182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3493182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3494182999Smav pdevinfo->left[i] = 100; 3495182999Smav pdevinfo->right[i] = 100; 3496182999Smav } 3497182999Smav 3498162922Sariff mask = 0; 3499162922Sariff recmask = 0; 3500182999Smav id = hdac_codec_id(devinfo->codec); 3501162922Sariff 3502182999Smav /* Declate EAPD as ogain control. */ 3503182999Smav if (pdevinfo->play >= 0) { 3504182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3505182999Smav w = hdac_widget_get(devinfo, i); 3506182999Smav if (w == NULL || w->enable == 0) 3507182999Smav continue; 3508182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3509182999Smav w->param.eapdbtl == HDAC_INVALID || 3510182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3511182999Smav continue; 3512182999Smav mask |= SOUND_MASK_OGAIN; 3513162922Sariff break; 3514162922Sariff } 3515162922Sariff } 3516162922Sariff 3517182999Smav /* Declare volume controls assigned to this association. */ 3518162922Sariff i = 0; 3519162922Sariff ctl = NULL; 3520162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3521182999Smav if (ctl->enable == 0) 3522162922Sariff continue; 3523182999Smav if ((pdevinfo->play >= 0 && 3524182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3525182999Smav (pdevinfo->rec >= 0 && 3526182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3527182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3528182999Smav mask |= ctl->ossmask; 3529162922Sariff } 3530162922Sariff 3531182999Smav /* Declare record sources available to this association. */ 3532182999Smav if (pdevinfo->rec >= 0) { 3533182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3534182999Smav for (i = 0; ch->io[i] != -1; i++) { 3535182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3536182999Smav if (w == NULL || w->enable == 0) 3537182999Smav continue; 3538182999Smav for (j = 0; j < w->nconns; j++) { 3539182999Smav if (w->connsenable[j] == 0) 3540162922Sariff continue; 3541182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3542182999Smav if (cw == NULL || cw->enable == 0) 3543165992Sariff continue; 3544182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3545182999Smav cw->bindas != -2) 3546165992Sariff continue; 3547182999Smav recmask |= cw->ossmask; 3548165992Sariff } 3549182999Smav } 3550182999Smav } 3551182999Smav 3552182999Smav /* Declare soft PCM and master volume if needed. */ 3553182999Smav if (pdevinfo->play >= 0) { 3554182999Smav ctl = NULL; 3555182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3556182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3557182999Smav softpcmvol = 1; 3558182999Smav mask |= SOUND_MASK_PCM; 3559162922Sariff } else { 3560182999Smav softpcmvol = 0; 3561182999Smav i = 0; 3562182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3563182999Smav if (ctl->enable == 0) 3564162922Sariff continue; 3565182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3566182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3567162922Sariff continue; 3568182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3569182999Smav continue; 3570182999Smav if (ctl->step > 0) 3571182999Smav break; 3572162922Sariff } 3573162922Sariff } 3574182999Smav 3575182999Smav if (softpcmvol == 1 || ctl == NULL) { 3576182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3577182999Smav HDA_BOOTVERBOSE( 3578182999Smav device_printf(pdevinfo->dev, 3579182999Smav "%s Soft PCM volume\n", 3580182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3581182999Smav ); 3582182999Smav } 3583182999Smav 3584182999Smav if ((mask & SOUND_MASK_VOLUME) == 0) { 3585182999Smav mask |= SOUND_MASK_VOLUME; 3586182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3587182999Smav SOUND_MASK_PCM); 3588182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3589182999Smav SOUND_MIXER_NONE); 3590182999Smav HDA_BOOTVERBOSE( 3591182999Smav device_printf(pdevinfo->dev, 3592182999Smav "Forcing master volume with PCM\n"); 3593182999Smav ); 3594182999Smav } 3595162922Sariff } 3596162922Sariff 3597169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3598169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3599162922Sariff 3600162922Sariff mix_setrecdevs(m, recmask); 3601162922Sariff mix_setdevs(m, mask); 3602162922Sariff 3603162922Sariff hdac_unlock(sc); 3604162922Sariff 3605162922Sariff return (0); 3606162922Sariff} 3607162922Sariff 3608162922Sariffstatic int 3609162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3610162922Sariff unsigned left, unsigned right) 3611162922Sariff{ 3612182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3613182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3614162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3615162922Sariff struct hdac_widget *w; 3616162922Sariff struct hdac_audio_ctl *ctl; 3617182999Smav uint32_t mute; 3618182999Smav int lvol, rvol; 3619182999Smav int i, j; 3620162922Sariff 3621162922Sariff hdac_lock(sc); 3622182999Smav /* Save new values. */ 3623182999Smav pdevinfo->left[dev] = left; 3624182999Smav pdevinfo->right[dev] = right; 3625182999Smav 3626182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3627162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3628163257Sariff uint32_t orig; 3629182999Smav w = NULL; 3630182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3631182999Smav w = hdac_widget_get(devinfo, i); 3632182999Smav if (w == NULL || w->enable == 0) 3633182999Smav continue; 3634182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3635182999Smav w->param.eapdbtl == HDAC_INVALID) 3636182999Smav continue; 3637182999Smav break; 3638162922Sariff } 3639182999Smav if (i >= devinfo->endnode) { 3640162922Sariff hdac_unlock(sc); 3641162922Sariff return (-1); 3642162922Sariff } 3643163257Sariff orig = w->param.eapdbtl; 3644163432Sariff if (left == 0) 3645162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3646162922Sariff else 3647162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3648163257Sariff if (orig != w->param.eapdbtl) { 3649163432Sariff uint32_t val; 3650163432Sariff 3651163432Sariff val = w->param.eapdbtl; 3652163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3653163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3654163257Sariff hdac_command(sc, 3655163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3656163432Sariff w->nid, val), devinfo->codec->cad); 3657163257Sariff } 3658162922Sariff hdac_unlock(sc); 3659162922Sariff return (left | (left << 8)); 3660162922Sariff } 3661162922Sariff 3662182999Smav /* Recalculate all controls related to this OSS device. */ 3663162922Sariff i = 0; 3664162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3665182999Smav if (ctl->enable == 0 || 3666162922Sariff !(ctl->ossmask & (1 << dev))) 3667162922Sariff continue; 3668182999Smav if (!((pdevinfo->play >= 0 && 3669182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3670182999Smav (pdevinfo->rec >= 0 && 3671182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3672182999Smav ctl->widget->bindas == -2)) 3673182999Smav continue; 3674182999Smav 3675182999Smav lvol = 100; 3676182999Smav rvol = 100; 3677182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3678182999Smav if (ctl->ossmask & (1 << j)) { 3679182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3680182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3681162922Sariff } 3682162922Sariff } 3683182999Smav mute = (left == 0) ? HDA_AMP_MUTE_LEFT : 0; 3684182999Smav mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3685182999Smav lvol = (lvol * ctl->step + 50) / 100; 3686182999Smav rvol = (rvol * ctl->step + 50) / 100; 3687162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3688162922Sariff } 3689162922Sariff hdac_unlock(sc); 3690162922Sariff 3691162922Sariff return (left | (right << 8)); 3692162922Sariff} 3693162922Sariff 3694182999Smav/* 3695182999Smav * Commutate specified record source. 3696182999Smav */ 3697182999Smavstatic uint32_t 3698182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3699162922Sariff{ 3700182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3701162922Sariff struct hdac_widget *w, *cw; 3702182999Smav struct hdac_audio_ctl *ctl; 3703182999Smav char buf[64]; 3704182999Smav int i, muted; 3705182999Smav uint32_t res = 0; 3706162922Sariff 3707182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3708182999Smav return (0); 3709182999Smav 3710182999Smav w = hdac_widget_get(devinfo, nid); 3711182999Smav if (w == NULL || w->enable == 0) 3712182999Smav return (0); 3713182999Smav 3714182999Smav for (i = 0; i < w->nconns; i++) { 3715182999Smav if (w->connsenable[i] == 0) 3716182999Smav continue; 3717182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3718182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3719182999Smav continue; 3720182999Smav /* Call recursively to trace signal to it's source if needed. */ 3721182999Smav if ((src & cw->ossmask) != 0) { 3722182999Smav if (cw->ossdev < 0) { 3723182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 3724182999Smav w->conns[i], depth + 1); 3725182999Smav } else { 3726182999Smav res |= cw->ossmask; 3727182999Smav } 3728182999Smav } 3729182999Smav /* We have two special cases: mixers and others (selectors). */ 3730182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 3731182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 3732182999Smav w->nid, HDA_CTL_IN, i, 1); 3733182999Smav if (ctl == NULL) 3734182999Smav continue; 3735182999Smav /* If we have input control on this node mute them 3736182999Smav * according to requested sources. */ 3737182999Smav muted = (src & cw->ossmask) ? 0 : 1; 3738182999Smav if (muted != ctl->forcemute) { 3739182999Smav ctl->forcemute = muted; 3740182999Smav hdac_audio_ctl_amp_set(ctl, 3741182999Smav HDA_AMP_MUTE_DEFAULT, 3742182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 3743182999Smav } 3744183097Smav HDA_BOOTHVERBOSE( 3745182999Smav device_printf(pdevinfo->dev, 3746182999Smav "Recsel (%s): nid %d source %d %s\n", 3747182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3748182999Smav src, buf, sizeof(buf)), 3749182999Smav nid, i, muted?"mute":"unmute"); 3750182999Smav ); 3751182999Smav } else { 3752182999Smav if (w->nconns == 1) 3753182999Smav break; 3754182999Smav if ((src & cw->ossmask) == 0) 3755182999Smav continue; 3756182999Smav /* If we found requested source - select it and exit. */ 3757182999Smav hdac_widget_connection_select(w, i); 3758183097Smav HDA_BOOTHVERBOSE( 3759182999Smav device_printf(pdevinfo->dev, 3760182999Smav "Recsel (%s): nid %d source %d select\n", 3761182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3762182999Smav src, buf, sizeof(buf)), 3763182999Smav nid, i); 3764182999Smav ); 3765162922Sariff break; 3766162922Sariff } 3767162922Sariff } 3768182999Smav return (res); 3769182999Smav} 3770162922Sariff 3771182999Smavstatic uint32_t 3772182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3773182999Smav{ 3774182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3775182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3776182999Smav struct hdac_widget *w; 3777182999Smav struct hdac_softc *sc = devinfo->codec->sc; 3778182999Smav struct hdac_chan *ch; 3779182999Smav int i; 3780182999Smav uint32_t ret = 0xffffffff; 3781182999Smav 3782162922Sariff hdac_lock(sc); 3783162922Sariff 3784182999Smav /* Commutate requested recsrc for each ADC. */ 3785182999Smav ch = &sc->chans[pdevinfo->rec]; 3786182999Smav for (i = 0; ch->io[i] != -1; i++) { 3787182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3788162965Sariff if (w == NULL || w->enable == 0) 3789162922Sariff continue; 3790182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 3791162922Sariff } 3792162922Sariff 3793162922Sariff hdac_unlock(sc); 3794162922Sariff 3795182999Smav return ((ret == 0xffffffff)? 0 : ret); 3796162922Sariff} 3797162922Sariff 3798162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3799162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3800162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3801162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3802162922Sariff { 0, 0 } 3803162922Sariff}; 3804162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3805162922Sariff 3806171141Sariffstatic void 3807171141Sariffhdac_unsolq_task(void *context, int pending) 3808171141Sariff{ 3809171141Sariff struct hdac_softc *sc; 3810171141Sariff 3811171141Sariff sc = (struct hdac_softc *)context; 3812171141Sariff 3813171141Sariff hdac_lock(sc); 3814171141Sariff hdac_unsolq_flush(sc); 3815171141Sariff hdac_unlock(sc); 3816171141Sariff} 3817171141Sariff 3818162922Sariff/**************************************************************************** 3819162922Sariff * int hdac_attach(device_t) 3820162922Sariff * 3821162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3822162922Sariff * when this function is called. Setup everything that doesn't require 3823162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3824162922Sariff ****************************************************************************/ 3825162922Sariffstatic int 3826162922Sariffhdac_attach(device_t dev) 3827162922Sariff{ 3828162922Sariff struct hdac_softc *sc; 3829162922Sariff int result; 3830169277Sariff int i; 3831169277Sariff uint16_t vendor; 3832169277Sariff uint8_t v; 3833162922Sariff 3834184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 3835182999Smav 3836182999Smav sc = device_get_softc(dev); 3837163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 3838162922Sariff sc->dev = dev; 3839163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 3840163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 3841169277Sariff vendor = pci_get_vendor(dev); 3842162922Sariff 3843165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 3844165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 3845165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 3846165281Sariff } 3847165281Sariff 3848164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 3849164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 3850169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 3851164614Sariff 3852171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 3853171141Sariff 3854182999Smav sc->poll_ticks = 1000000; 3855169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 3856169277Sariff if (resource_int_value(device_get_name(dev), 3857169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 3858164614Sariff sc->polling = 1; 3859164614Sariff else 3860164614Sariff sc->polling = 0; 3861164614Sariff 3862162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 3863162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 3864162922Sariff 0, /* boundary */ 3865162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 3866162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 3867162922Sariff NULL, /* filtfunc */ 3868162922Sariff NULL, /* fistfuncarg */ 3869182999Smav HDA_BUFSZ_MAX, /* maxsize */ 3870162922Sariff 1, /* nsegments */ 3871182999Smav HDA_BUFSZ_MAX, /* maxsegsz */ 3872162922Sariff 0, /* flags */ 3873162922Sariff NULL, /* lockfunc */ 3874162922Sariff NULL, /* lockfuncarg */ 3875162922Sariff &sc->chan_dmat); /* dmat */ 3876162922Sariff if (result != 0) { 3877169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 3878162922Sariff __func__, result); 3879163057Sariff snd_mtxfree(sc->lock); 3880162922Sariff free(sc, M_DEVBUF); 3881162922Sariff return (ENXIO); 3882162922Sariff } 3883162922Sariff 3884162922Sariff 3885162922Sariff sc->hdabus = NULL; 3886162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 3887162922Sariff sc->codecs[i] = NULL; 3888162922Sariff 3889162922Sariff pci_enable_busmaster(dev); 3890162922Sariff 3891169277Sariff if (vendor == INTEL_VENDORID) { 3892169277Sariff /* TCSEL -> TC0 */ 3893169277Sariff v = pci_read_config(dev, 0x44, 1); 3894169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 3895183097Smav HDA_BOOTHVERBOSE( 3896169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 3897169277Sariff pci_read_config(dev, 0x44, 1)); 3898169277Sariff ); 3899169277Sariff } 3900169277Sariff 3901178155Sariff#ifdef HDAC_MSI_ENABLED 3902171330Sariff if (resource_int_value(device_get_name(dev), 3903171330Sariff device_get_unit(dev), "msi", &i) == 0 && i != 0 && 3904171330Sariff pci_msi_count(dev) == 1) 3905171330Sariff sc->flags |= HDAC_F_MSI; 3906171330Sariff else 3907171330Sariff#endif 3908171330Sariff sc->flags &= ~HDAC_F_MSI; 3909171330Sariff 3910169277Sariff#if defined(__i386__) || defined(__amd64__) 3911171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3912169277Sariff 3913169277Sariff if (resource_int_value(device_get_name(dev), 3914169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 3915169277Sariff#else 3916171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3917169277Sariff#endif 3918169277Sariff /* 3919169277Sariff * Try to enable PCIe snoop to avoid messing around with 3920169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 3921169277Sariff * config is pretty much vendor specific, there are no 3922169277Sariff * general solutions on how to enable it, forcing us (even 3923169277Sariff * Microsoft) to enable uncacheable or write combined DMA 3924169277Sariff * by default. 3925169277Sariff * 3926169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 3927169277Sariff */ 3928169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 3929169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 3930169277Sariff continue; 3931171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3932169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 3933169277Sariff break; 3934169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3935169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 3936169277Sariff hdac_pcie_snoop[i].enable) 3937169277Sariff break; 3938169277Sariff v &= hdac_pcie_snoop[i].mask; 3939169277Sariff v |= hdac_pcie_snoop[i].enable; 3940169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 3941169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3942169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 3943169277Sariff hdac_pcie_snoop[i].enable) { 3944169277Sariff HDA_BOOTVERBOSE( 3945169277Sariff device_printf(dev, 3946169277Sariff "WARNING: Failed to enable PCIe " 3947169277Sariff "snoop!\n"); 3948169277Sariff ); 3949169277Sariff#if defined(__i386__) || defined(__amd64__) 3950171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3951169277Sariff#endif 3952169277Sariff } 3953169277Sariff break; 3954169277Sariff } 3955169277Sariff#if defined(__i386__) || defined(__amd64__) 3956169277Sariff } 3957169277Sariff#endif 3958169277Sariff 3959183097Smav HDA_BOOTHVERBOSE( 3960169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 3961171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 3962171330Sariff "Uncacheable" : "PCIe snoop", vendor); 3963169277Sariff ); 3964169277Sariff 3965162922Sariff /* Allocate resources */ 3966162922Sariff result = hdac_mem_alloc(sc); 3967162922Sariff if (result != 0) 3968163057Sariff goto hdac_attach_fail; 3969162922Sariff result = hdac_irq_alloc(sc); 3970162922Sariff if (result != 0) 3971163057Sariff goto hdac_attach_fail; 3972162922Sariff 3973162922Sariff /* Get Capabilities */ 3974162922Sariff result = hdac_get_capabilities(sc); 3975162922Sariff if (result != 0) 3976163057Sariff goto hdac_attach_fail; 3977162922Sariff 3978162922Sariff /* Allocate CORB and RIRB dma memory */ 3979162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 3980162922Sariff sc->corb_size * sizeof(uint32_t)); 3981162922Sariff if (result != 0) 3982163057Sariff goto hdac_attach_fail; 3983162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 3984162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 3985162922Sariff if (result != 0) 3986163057Sariff goto hdac_attach_fail; 3987162922Sariff 3988162922Sariff /* Quiesce everything */ 3989183097Smav HDA_BOOTHVERBOSE( 3990182999Smav device_printf(dev, "Reset controller...\n"); 3991182999Smav ); 3992182999Smav hdac_reset(sc, 1); 3993162922Sariff 3994162922Sariff /* Initialize the CORB and RIRB */ 3995162922Sariff hdac_corb_init(sc); 3996162922Sariff hdac_rirb_init(sc); 3997162922Sariff 3998162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 3999162922Sariff sc->intrhook.ich_func = hdac_attach2; 4000162922Sariff sc->intrhook.ich_arg = (void *)sc; 4001162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4002162922Sariff sc->intrhook.ich_func = NULL; 4003162922Sariff hdac_attach2((void *)sc); 4004162922Sariff } 4005162922Sariff 4006163057Sariff return (0); 4007162922Sariff 4008163057Sariffhdac_attach_fail: 4009162922Sariff hdac_irq_free(sc); 4010169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4011169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4012162922Sariff hdac_mem_free(sc); 4013162922Sariff snd_mtxfree(sc->lock); 4014163057Sariff free(sc, M_DEVBUF); 4015162922Sariff 4016163057Sariff return (ENXIO); 4017162922Sariff} 4018162922Sariff 4019162922Sariffstatic void 4020162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4021162922Sariff{ 4022182999Smav struct hdac_codec *codec = devinfo->codec; 4023182999Smav struct hdac_softc *sc = codec->sc; 4024162922Sariff struct hdac_widget *w; 4025162922Sariff uint32_t res; 4026162922Sariff int i; 4027162922Sariff nid_t cad, nid; 4028162922Sariff 4029162922Sariff cad = devinfo->codec->cad; 4030162922Sariff nid = devinfo->nid; 4031162922Sariff 4032162922Sariff res = hdac_command(sc, 4033169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4034169277Sariff devinfo->function.audio.gpio = res; 4035169277Sariff 4036163057Sariff HDA_BOOTVERBOSE( 4037183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4038183097Smav "NumGPIO=%d NumGPO=%d " 4039169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4040183097Smav devinfo->function.audio.gpio, 4041169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4042169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4043169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4044169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4045169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4046162922Sariff ); 4047162922Sariff 4048162922Sariff res = hdac_command(sc, 4049162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4050162922Sariff cad); 4051162922Sariff devinfo->function.audio.supp_stream_formats = res; 4052162922Sariff 4053162922Sariff res = hdac_command(sc, 4054162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4055162922Sariff cad); 4056162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4057162922Sariff 4058162922Sariff res = hdac_command(sc, 4059162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4060162922Sariff cad); 4061162922Sariff devinfo->function.audio.outamp_cap = res; 4062162922Sariff 4063162922Sariff res = hdac_command(sc, 4064162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4065162922Sariff cad); 4066162922Sariff devinfo->function.audio.inamp_cap = res; 4067162922Sariff 4068162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4069162922Sariff w = hdac_widget_get(devinfo, i); 4070162922Sariff if (w == NULL) 4071162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4072162922Sariff else { 4073162922Sariff w->devinfo = devinfo; 4074162922Sariff w->nid = i; 4075162922Sariff w->enable = 1; 4076162922Sariff w->selconn = -1; 4077162922Sariff w->pflags = 0; 4078182999Smav w->ossdev = -1; 4079182999Smav w->bindas = -1; 4080162965Sariff w->param.eapdbtl = HDAC_INVALID; 4081162922Sariff hdac_widget_parse(w); 4082162922Sariff } 4083162922Sariff } 4084162922Sariff} 4085162922Sariff 4086162922Sariffstatic void 4087162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4088162922Sariff{ 4089162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4090162922Sariff struct hdac_audio_ctl *ctls; 4091162922Sariff struct hdac_widget *w, *cw; 4092162922Sariff int i, j, cnt, max, ocap, icap; 4093163057Sariff int mute, offset, step, size; 4094162922Sariff 4095162922Sariff /* XXX This is redundant */ 4096162922Sariff max = 0; 4097162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4098162922Sariff w = hdac_widget_get(devinfo, i); 4099162922Sariff if (w == NULL || w->enable == 0) 4100162922Sariff continue; 4101162922Sariff if (w->param.outamp_cap != 0) 4102162922Sariff max++; 4103162922Sariff if (w->param.inamp_cap != 0) { 4104162922Sariff switch (w->type) { 4105162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4106162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4107162922Sariff for (j = 0; j < w->nconns; j++) { 4108162922Sariff cw = hdac_widget_get(devinfo, 4109162922Sariff w->conns[j]); 4110162922Sariff if (cw == NULL || cw->enable == 0) 4111162922Sariff continue; 4112162922Sariff max++; 4113162922Sariff } 4114162922Sariff break; 4115162922Sariff default: 4116162922Sariff max++; 4117162922Sariff break; 4118162922Sariff } 4119162922Sariff } 4120162922Sariff } 4121162922Sariff 4122162922Sariff devinfo->function.audio.ctlcnt = max; 4123162922Sariff 4124162922Sariff if (max < 1) 4125162922Sariff return; 4126162922Sariff 4127162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4128162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4129162922Sariff 4130162922Sariff if (ctls == NULL) { 4131162922Sariff /* Blekh! */ 4132162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4133162922Sariff devinfo->function.audio.ctlcnt = 0; 4134162922Sariff return; 4135162922Sariff } 4136162922Sariff 4137162922Sariff cnt = 0; 4138162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4139162922Sariff if (cnt >= max) { 4140162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4141162922Sariff __func__); 4142162922Sariff break; 4143162922Sariff } 4144162922Sariff w = hdac_widget_get(devinfo, i); 4145162922Sariff if (w == NULL || w->enable == 0) 4146162922Sariff continue; 4147162922Sariff ocap = w->param.outamp_cap; 4148162922Sariff icap = w->param.inamp_cap; 4149162922Sariff if (ocap != 0) { 4150163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4151163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4152163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4153163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4154163057Sariff /*if (offset > step) { 4155163057Sariff HDA_BOOTVERBOSE( 4156163057Sariff device_printf(sc->dev, 4157182999Smav "BUGGY outamp: nid=%d " 4158163057Sariff "[offset=%d > step=%d]\n", 4159163057Sariff w->nid, offset, step); 4160163057Sariff ); 4161163057Sariff offset = step; 4162163057Sariff }*/ 4163162922Sariff ctls[cnt].enable = 1; 4164162922Sariff ctls[cnt].widget = w; 4165163057Sariff ctls[cnt].mute = mute; 4166163057Sariff ctls[cnt].step = step; 4167163057Sariff ctls[cnt].size = size; 4168163057Sariff ctls[cnt].offset = offset; 4169163057Sariff ctls[cnt].left = offset; 4170163057Sariff ctls[cnt].right = offset; 4171182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4172182999Smav w->waspin) 4173182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4174182999Smav else 4175182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4176162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4177162922Sariff } 4178162922Sariff 4179162922Sariff if (icap != 0) { 4180163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4181163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4182163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4183163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4184163057Sariff /*if (offset > step) { 4185163057Sariff HDA_BOOTVERBOSE( 4186163057Sariff device_printf(sc->dev, 4187182999Smav "BUGGY inamp: nid=%d " 4188163057Sariff "[offset=%d > step=%d]\n", 4189163057Sariff w->nid, offset, step); 4190163057Sariff ); 4191163057Sariff offset = step; 4192163057Sariff }*/ 4193162922Sariff switch (w->type) { 4194162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4195162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4196162922Sariff for (j = 0; j < w->nconns; j++) { 4197162922Sariff if (cnt >= max) { 4198162922Sariff device_printf(sc->dev, 4199162922Sariff "%s: Ctl overflow!\n", 4200162922Sariff __func__); 4201162922Sariff break; 4202162922Sariff } 4203162922Sariff cw = hdac_widget_get(devinfo, 4204162922Sariff w->conns[j]); 4205162922Sariff if (cw == NULL || cw->enable == 0) 4206162922Sariff continue; 4207162922Sariff ctls[cnt].enable = 1; 4208162922Sariff ctls[cnt].widget = w; 4209162922Sariff ctls[cnt].childwidget = cw; 4210162922Sariff ctls[cnt].index = j; 4211163057Sariff ctls[cnt].mute = mute; 4212163057Sariff ctls[cnt].step = step; 4213163057Sariff ctls[cnt].size = size; 4214163057Sariff ctls[cnt].offset = offset; 4215163057Sariff ctls[cnt].left = offset; 4216163057Sariff ctls[cnt].right = offset; 4217182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4218162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4219162922Sariff } 4220162922Sariff break; 4221162922Sariff default: 4222162922Sariff if (cnt >= max) { 4223162922Sariff device_printf(sc->dev, 4224162922Sariff "%s: Ctl overflow!\n", 4225162922Sariff __func__); 4226162922Sariff break; 4227162922Sariff } 4228162922Sariff ctls[cnt].enable = 1; 4229162922Sariff ctls[cnt].widget = w; 4230163057Sariff ctls[cnt].mute = mute; 4231163057Sariff ctls[cnt].step = step; 4232163057Sariff ctls[cnt].size = size; 4233163057Sariff ctls[cnt].offset = offset; 4234163057Sariff ctls[cnt].left = offset; 4235163057Sariff ctls[cnt].right = offset; 4236182999Smav if (w->type == 4237182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4238182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4239182999Smav else 4240182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4241162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4242162922Sariff break; 4243162922Sariff } 4244162922Sariff } 4245162922Sariff } 4246162922Sariff 4247162922Sariff devinfo->function.audio.ctl = ctls; 4248162922Sariff} 4249162922Sariff 4250182999Smavstatic void 4251182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4252182999Smav{ 4253182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4254182999Smav struct hdac_audio_as *as; 4255182999Smav struct hdac_widget *w; 4256182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4257182999Smav 4258184991Smav /* Count present associations */ 4259182999Smav max = 0; 4260184991Smav for (j = 1; j < 16; j++) { 4261182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4262182999Smav w = hdac_widget_get(devinfo, i); 4263182999Smav if (w == NULL || w->enable == 0) 4264182999Smav continue; 4265182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4266182999Smav continue; 4267182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4268182999Smav != j) 4269182999Smav continue; 4270182999Smav max++; 4271182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4272182999Smav break; 4273182999Smav } 4274182999Smav } 4275182999Smav 4276182999Smav devinfo->function.audio.ascnt = max; 4277182999Smav 4278182999Smav if (max < 1) 4279182999Smav return; 4280182999Smav 4281182999Smav as = (struct hdac_audio_as *)malloc( 4282182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4283182999Smav 4284182999Smav if (as == NULL) { 4285182999Smav /* Blekh! */ 4286182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4287182999Smav devinfo->function.audio.ascnt = 0; 4288182999Smav return; 4289182999Smav } 4290182999Smav 4291182999Smav for (i = 0; i < max; i++) { 4292182999Smav as[i].hpredir = -1; 4293182999Smav as[i].chan = -1; 4294182999Smav } 4295182999Smav 4296182999Smav /* Scan associations skipping as=0. */ 4297182999Smav cnt = 0; 4298182999Smav for (j = 1; j < 16; j++) { 4299182999Smav first = 16; 4300182999Smav hpredir = 0; 4301182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4302182999Smav w = hdac_widget_get(devinfo, i); 4303182999Smav if (w == NULL || w->enable == 0) 4304182999Smav continue; 4305182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4306182999Smav continue; 4307182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4308182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4309182999Smav if (assoc != j) { 4310182999Smav continue; 4311182999Smav } 4312182999Smav KASSERT(cnt < max, 4313182999Smav ("%s: Associations owerflow (%d of %d)", 4314182999Smav __func__, cnt, max)); 4315182999Smav type = w->wclass.pin.config & 4316182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4317182999Smav /* Get pin direction. */ 4318182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4319182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4320182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4321182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4322182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4323182999Smav dir = HDA_CTL_OUT; 4324182999Smav else 4325182999Smav dir = HDA_CTL_IN; 4326182999Smav /* If this is a first pin - create new association. */ 4327182999Smav if (as[cnt].pincnt == 0) { 4328182999Smav as[cnt].enable = 1; 4329182999Smav as[cnt].index = j; 4330182999Smav as[cnt].dir = dir; 4331182999Smav } 4332182999Smav if (seq < first) 4333182999Smav first = seq; 4334182999Smav /* Check association correctness. */ 4335182999Smav if (as[cnt].pins[seq] != 0) { 4336182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4337182999Smav "in association %d! Disabling association.\n", 4338182999Smav __func__, seq, w->nid, j); 4339182999Smav as[cnt].enable = 0; 4340182999Smav } 4341182999Smav if (dir != as[cnt].dir) { 4342182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4343182999Smav "direction for association %d! Disabling " 4344182999Smav "association.\n", 4345182999Smav __func__, w->nid, j); 4346182999Smav as[cnt].enable = 0; 4347182999Smav } 4348182999Smav /* Headphones with seq=15 may mean redirection. */ 4349182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4350182999Smav seq == 15) 4351182999Smav hpredir = 1; 4352182999Smav as[cnt].pins[seq] = w->nid; 4353182999Smav as[cnt].pincnt++; 4354182999Smav /* Association 15 is a multiple unassociated pins. */ 4355182999Smav if (j == 15) 4356182999Smav cnt++; 4357182999Smav } 4358182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4359182999Smav if (hpredir && as[cnt].pincnt > 1) 4360182999Smav as[cnt].hpredir = first; 4361182999Smav cnt++; 4362182999Smav } 4363182999Smav } 4364182999Smav HDA_BOOTVERBOSE( 4365182999Smav device_printf(sc->dev, 4366183097Smav "%d associations found:\n", max); 4367182999Smav for (i = 0; i < max; i++) { 4368182999Smav device_printf(sc->dev, 4369182999Smav "Association %d (%d) %s%s:\n", 4370182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4371182999Smav as[i].enable?"":" (disabled)"); 4372182999Smav for (j = 0; j < 16; j++) { 4373182999Smav if (as[i].pins[j] == 0) 4374182999Smav continue; 4375182999Smav device_printf(sc->dev, 4376183097Smav " Pin nid=%d seq=%d\n", 4377182999Smav as[i].pins[j], j); 4378182999Smav } 4379182999Smav } 4380182999Smav ); 4381182999Smav 4382182999Smav devinfo->function.audio.as = as; 4383182999Smav} 4384182999Smav 4385162965Sariffstatic const struct { 4386162965Sariff uint32_t model; 4387162965Sariff uint32_t id; 4388162965Sariff uint32_t set, unset; 4389162965Sariff} hdac_quirks[] = { 4390163057Sariff /* 4391163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4392163057Sariff * on few codecs (especially ALC880) seems broken or 4393163057Sariff * perhaps unsupported. 4394163057Sariff */ 4395163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4396169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4397162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4398165039Sariff HDA_QUIRK_GPIO0, 0 }, 4399178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4400178155Sariff HDA_QUIRK_GPIO0, 0 }, 4401162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4402165039Sariff HDA_QUIRK_GPIO0, 0 }, 4403165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4404165281Sariff HDA_QUIRK_GPIO0, 0 }, 4405167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4406167623Sariff HDA_QUIRK_GPIO0, 0 }, 4407169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4408169277Sariff HDA_QUIRK_GPIO0, 0 }, 4409163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4410163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4411178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4412163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4413169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4414169277Sariff HDA_QUIRK_OVREF, 0 }, 4415169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4416169277Sariff HDA_QUIRK_OVREF, 0 }, 4417169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4418169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4419165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4420165281Sariff HDA_QUIRK_GPIO1, 0 }, 4421164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4422182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4423164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4424164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4425173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4426173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4427165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4428165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4429183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4430180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4431184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4432184483Smav HDA_QUIRK_GPIO2, 0 }, 4433183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4434178155Sariff HDA_QUIRK_GPIO0, 0 }, 4435169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4436169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4437170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4438170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4439162965Sariff { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 4440182999Smav 0, HDA_QUIRK_FORCESTEREO } 4441162965Sariff}; 4442162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4443162965Sariff 4444162922Sariffstatic void 4445162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4446162922Sariff{ 4447162922Sariff struct hdac_widget *w; 4448162965Sariff uint32_t id, subvendor; 4449162922Sariff int i; 4450162922Sariff 4451182999Smav id = hdac_codec_id(devinfo->codec); 4452163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4453163057Sariff 4454162922Sariff /* 4455163057Sariff * Quirks 4456162922Sariff */ 4457163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4458163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4459163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4460163057Sariff continue; 4461163057Sariff if (hdac_quirks[i].set != 0) 4462163057Sariff devinfo->function.audio.quirks |= 4463163057Sariff hdac_quirks[i].set; 4464163057Sariff if (hdac_quirks[i].unset != 0) 4465163057Sariff devinfo->function.audio.quirks &= 4466163057Sariff ~(hdac_quirks[i].unset); 4467163057Sariff } 4468163057Sariff 4469162922Sariff switch (id) { 4470166965Sariff case HDA_CODEC_ALC883: 4471166965Sariff /* 4472166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4473166965Sariff * Clear vref cap for jack connectivity. 4474166965Sariff */ 4475166965Sariff w = hdac_widget_get(devinfo, 24); 4476166965Sariff if (w != NULL && w->enable != 0 && w->type == 4477166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4478166965Sariff (w->wclass.pin.config & 4479166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4480166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4481166965Sariff w->wclass.pin.cap &= ~( 4482166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4483166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4484166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4485166965Sariff w = hdac_widget_get(devinfo, 25); 4486166965Sariff if (w != NULL && w->enable != 0 && w->type == 4487166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4488166965Sariff (w->wclass.pin.config & 4489166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4490166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4491166965Sariff w->wclass.pin.cap &= ~( 4492166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4493166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4494166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4495166965Sariff /* 4496166965Sariff * nid: 26 = Line-in, leave it alone. 4497166965Sariff */ 4498166965Sariff break; 4499162922Sariff case HDA_CODEC_AD1986A: 4500182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4501178155Sariff /* 4502178155Sariff * This is just plain ridiculous.. There 4503178155Sariff * are several A8 series that share the same 4504178155Sariff * pci id but works differently (EAPD). 4505178155Sariff */ 4506178155Sariff w = hdac_widget_get(devinfo, 26); 4507178155Sariff if (w != NULL && w->type == 4508178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4509178155Sariff (w->wclass.pin.config & 4510178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4511178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4512178155Sariff devinfo->function.audio.quirks &= 4513178155Sariff ~HDA_QUIRK_EAPDINV; 4514169277Sariff } 4515162922Sariff break; 4516184230Smav case HDA_CODEC_AD1981HD: 4517184230Smav /* 4518184230Smav * This codec has very unusual design with several 4519184254Smav * points inappropriate for the present parser. 4520184230Smav */ 4521184230Smav /* Disable recording from mono playback mix. */ 4522184230Smav w = hdac_widget_get(devinfo, 21); 4523184230Smav if (w != NULL) 4524184230Smav w->connsenable[3] = 0; 4525184230Smav /* Disable rear to front mic mixer, use separately. */ 4526184230Smav w = hdac_widget_get(devinfo, 31); 4527184230Smav if (w != NULL) 4528184230Smav w->enable = 0; 4529184230Smav /* Disable playback mixer, use direct bypass. */ 4530184230Smav w = hdac_widget_get(devinfo, 14); 4531184230Smav if (w != NULL) 4532184230Smav w->enable = 0; 4533184230Smav break; 4534182999Smav } 4535182999Smav} 4536182999Smav 4537182999Smav/* 4538182999Smav * Trace path from DAC to pin. 4539182999Smav */ 4540182999Smavstatic nid_t 4541182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4542182999Smav int dupseq, int min, int only, int depth) 4543182999Smav{ 4544182999Smav struct hdac_widget *w; 4545182999Smav int i, im = -1; 4546182999Smav nid_t m = 0, ret; 4547182999Smav 4548182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4549182999Smav return (0); 4550182999Smav w = hdac_widget_get(devinfo, nid); 4551182999Smav if (w == NULL || w->enable == 0) 4552182999Smav return (0); 4553183097Smav HDA_BOOTHVERBOSE( 4554182999Smav if (!only) { 4555182999Smav device_printf(devinfo->codec->sc->dev, 4556182999Smav " %*stracing via nid %d\n", 4557182999Smav depth + 1, "", w->nid); 4558169277Sariff } 4559182999Smav ); 4560182999Smav /* Use only unused widgets */ 4561182999Smav if (w->bindas >= 0 && w->bindas != as) { 4562183097Smav HDA_BOOTHVERBOSE( 4563182999Smav if (!only) { 4564182999Smav device_printf(devinfo->codec->sc->dev, 4565182999Smav " %*snid %d busy by association %d\n", 4566182999Smav depth + 1, "", w->nid, w->bindas); 4567182999Smav } 4568182999Smav ); 4569182999Smav return (0); 4570182999Smav } 4571182999Smav if (dupseq < 0) { 4572182999Smav if (w->bindseqmask != 0) { 4573183097Smav HDA_BOOTHVERBOSE( 4574182999Smav if (!only) { 4575182999Smav device_printf(devinfo->codec->sc->dev, 4576182999Smav " %*snid %d busy by seqmask %x\n", 4577182999Smav depth + 1, "", w->nid, w->bindseqmask); 4578182999Smav } 4579182999Smav ); 4580182999Smav return (0); 4581169277Sariff } 4582182999Smav } else { 4583182999Smav /* If this is headphones - allow duplicate first pin. */ 4584182999Smav if (w->bindseqmask != 0 && 4585182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4586183097Smav HDA_BOOTHVERBOSE( 4587182999Smav device_printf(devinfo->codec->sc->dev, 4588182999Smav " %*snid %d busy by seqmask %x\n", 4589182999Smav depth + 1, "", w->nid, w->bindseqmask); 4590182999Smav ); 4591182999Smav return (0); 4592169277Sariff } 4593182999Smav } 4594182999Smav 4595182999Smav switch (w->type) { 4596182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4597182999Smav /* Do not traverse input. AD1988 has digital monitor 4598182999Smav for which we are not ready. */ 4599169277Sariff break; 4600182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4601182999Smav /* If we are tracing HP take only dac of first pin. */ 4602182999Smav if ((only == 0 || only == w->nid) && 4603182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4604182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4605182999Smav m = w->nid; 4606178155Sariff break; 4607182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4608182999Smav if (depth > 0) 4609169277Sariff break; 4610182999Smav /* Fall */ 4611182999Smav default: 4612182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4613182999Smav for (i = 0; i < w->nconns; i++) { 4614182999Smav if (w->connsenable[i] == 0) 4615162922Sariff continue; 4616182999Smav if (w->selconn != -1 && w->selconn != i) 4617162922Sariff continue; 4618182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4619182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4620182999Smav if (m == 0 || ret < m) { 4621182999Smav m = ret; 4622182999Smav im = i; 4623182999Smav } 4624182999Smav if (only || dupseq >= 0) 4625182999Smav break; 4626182999Smav } 4627162922Sariff } 4628182999Smav if (m && only && ((w->nconns > 1 && 4629182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4630182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4631182999Smav w->selconn = im; 4632162922Sariff break; 4633182999Smav } 4634182999Smav if (m && only) { 4635182999Smav w->bindas = as; 4636182999Smav w->bindseqmask |= (1 << seq); 4637182999Smav } 4638183097Smav HDA_BOOTHVERBOSE( 4639182999Smav if (!only) { 4640182999Smav device_printf(devinfo->codec->sc->dev, 4641182999Smav " %*snid %d returned %d\n", 4642182999Smav depth + 1, "", w->nid, m); 4643182999Smav } 4644182999Smav ); 4645182999Smav return (m); 4646182999Smav} 4647162922Sariff 4648182999Smav/* 4649182999Smav * Trace path from widget to ADC. 4650182999Smav */ 4651182999Smavstatic nid_t 4652182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4653182999Smav int only, int depth) 4654182999Smav{ 4655182999Smav struct hdac_widget *w, *wc; 4656182999Smav int i, j; 4657182999Smav nid_t res = 0; 4658182999Smav 4659182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4660182999Smav return (0); 4661182999Smav w = hdac_widget_get(devinfo, nid); 4662182999Smav if (w == NULL || w->enable == 0) 4663182999Smav return (0); 4664183097Smav HDA_BOOTHVERBOSE( 4665182999Smav device_printf(devinfo->codec->sc->dev, 4666182999Smav " %*stracing via nid %d\n", 4667182999Smav depth + 1, "", w->nid); 4668182999Smav ); 4669182999Smav /* Use only unused widgets */ 4670182999Smav if (w->bindas >= 0 && w->bindas != as) { 4671183097Smav HDA_BOOTHVERBOSE( 4672182999Smav device_printf(devinfo->codec->sc->dev, 4673182999Smav " %*snid %d busy by association %d\n", 4674182999Smav depth + 1, "", w->nid, w->bindas); 4675182999Smav ); 4676182999Smav return (0); 4677182999Smav } 4678182999Smav 4679182999Smav switch (w->type) { 4680182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4681182999Smav /* If we are tracing HP take only dac of first pin. */ 4682182999Smav if (only == w->nid) 4683182999Smav res = 1; 4684162922Sariff break; 4685182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4686182999Smav if (depth > 0) 4687182999Smav break; 4688182999Smav /* Fall */ 4689182999Smav default: 4690182999Smav /* Try to find reachable ADCs with specified nid. */ 4691182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4692182999Smav wc = hdac_widget_get(devinfo, j); 4693182999Smav if (wc == NULL || wc->enable == 0) 4694182999Smav continue; 4695182999Smav for (i = 0; i < wc->nconns; i++) { 4696182999Smav if (wc->connsenable[i] == 0) 4697182999Smav continue; 4698182999Smav if (wc->conns[i] != nid) 4699182999Smav continue; 4700182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 4701182999Smav j, only, depth + 1) != 0) { 4702182999Smav res = 1; 4703182999Smav if (((wc->nconns > 1 && 4704182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4705182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 4706182999Smav wc->selconn == -1) 4707182999Smav wc->selconn = i; 4708182999Smav } 4709182999Smav } 4710169277Sariff } 4711169277Sariff break; 4712162922Sariff } 4713182999Smav if (res) { 4714182999Smav w->bindas = as; 4715182999Smav w->bindseqmask |= (1 << seq); 4716182999Smav } 4717183097Smav HDA_BOOTHVERBOSE( 4718182999Smav device_printf(devinfo->codec->sc->dev, 4719182999Smav " %*snid %d returned %d\n", 4720182999Smav depth + 1, "", w->nid, res); 4721182999Smav ); 4722182999Smav return (res); 4723162922Sariff} 4724162922Sariff 4725182999Smav/* 4726182999Smav * Erase trace path of the specified association. 4727182999Smav */ 4728182999Smavstatic void 4729182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 4730182999Smav{ 4731182999Smav struct hdac_widget *w; 4732182999Smav int i; 4733182999Smav 4734182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4735182999Smav w = hdac_widget_get(devinfo, i); 4736182999Smav if (w == NULL || w->enable == 0) 4737182999Smav continue; 4738182999Smav if (w->bindas == as) { 4739182999Smav if (seq >= 0) { 4740182999Smav w->bindseqmask &= ~(1 << seq); 4741182999Smav if (w->bindseqmask == 0) { 4742182999Smav w->bindas = -1; 4743182999Smav w->selconn = -1; 4744182999Smav } 4745182999Smav } else { 4746182999Smav w->bindas = -1; 4747182999Smav w->bindseqmask = 0; 4748182999Smav w->selconn = -1; 4749182999Smav } 4750182999Smav } 4751182999Smav } 4752182999Smav} 4753182999Smav 4754182999Smav/* 4755182999Smav * Trace association path from DAC to output 4756182999Smav */ 4757162922Sariffstatic int 4758182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 4759162922Sariff{ 4760182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4761182999Smav int i, hpredir; 4762182999Smav nid_t min, res; 4763162922Sariff 4764182999Smav /* Find next pin */ 4765185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 4766182999Smav ; 4767182999Smav /* Check if there is no any left. If so - we succeded. */ 4768182999Smav if (i == 16) 4769182999Smav return (1); 4770182999Smav 4771182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 4772182999Smav min = 0; 4773182999Smav res = 0; 4774182999Smav do { 4775183097Smav HDA_BOOTHVERBOSE( 4776182999Smav device_printf(devinfo->codec->sc->dev, 4777182999Smav " Tracing pin %d with min nid %d", 4778182999Smav ases[as].pins[i], min); 4779182999Smav if (hpredir >= 0) 4780183097Smav printf(" and hpredir %d", hpredir); 4781183097Smav printf("\n"); 4782182999Smav ); 4783182999Smav /* Trace this pin taking min nid into account. */ 4784182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 4785182999Smav ases[as].pins[i], hpredir, min, 0, 0); 4786182999Smav if (res == 0) { 4787182999Smav /* If we failed - return to previous and redo it. */ 4788182999Smav HDA_BOOTVERBOSE( 4789182999Smav device_printf(devinfo->codec->sc->dev, 4790182999Smav " Unable to trace pin %d seq %d with min " 4791183097Smav "nid %d", 4792183097Smav ases[as].pins[i], i, min); 4793183097Smav if (hpredir >= 0) 4794183097Smav printf(" and hpredir %d", hpredir); 4795183097Smav printf("\n"); 4796182999Smav ); 4797182999Smav return (0); 4798162922Sariff } 4799182999Smav HDA_BOOTVERBOSE( 4800182999Smav device_printf(devinfo->codec->sc->dev, 4801183097Smav " Pin %d traced to DAC %d", 4802183097Smav ases[as].pins[i], res); 4803183097Smav if (hpredir >= 0) 4804183097Smav printf(" and hpredir %d", hpredir); 4805183097Smav if (ases[as].fakeredir) 4806183097Smav printf(" with fake redirection"); 4807183097Smav printf("\n"); 4808182999Smav ); 4809182999Smav /* Trace again to mark the path */ 4810182999Smav hdac_audio_trace_dac(devinfo, as, i, 4811182999Smav ases[as].pins[i], hpredir, min, res, 0); 4812182999Smav ases[as].dacs[i] = res; 4813182999Smav /* We succeded, so call next. */ 4814182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 4815182999Smav return (1); 4816182999Smav /* If next failed, we should retry with next min */ 4817182999Smav hdac_audio_undo_trace(devinfo, as, i); 4818182999Smav ases[as].dacs[i] = 0; 4819182999Smav min = res + 1; 4820182999Smav } while (1); 4821162922Sariff} 4822162922Sariff 4823182999Smav/* 4824182999Smav * Trace association path from input to ADC 4825182999Smav */ 4826162922Sariffstatic int 4827182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 4828162922Sariff{ 4829182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4830162922Sariff struct hdac_widget *w; 4831182999Smav int i, j, k; 4832162922Sariff 4833182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4834182999Smav w = hdac_widget_get(devinfo, j); 4835182999Smav if (w == NULL || w->enable == 0) 4836182999Smav continue; 4837182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4838182999Smav continue; 4839182999Smav if (w->bindas >= 0 && w->bindas != as) 4840182999Smav continue; 4841182999Smav 4842182999Smav /* Find next pin */ 4843182999Smav for (i = 0; i < 16; i++) { 4844182999Smav if (ases[as].pins[i] == 0) 4845182999Smav continue; 4846182999Smav 4847183097Smav HDA_BOOTHVERBOSE( 4848182999Smav device_printf(devinfo->codec->sc->dev, 4849182999Smav " Tracing pin %d to ADC %d\n", 4850182999Smav ases[as].pins[i], j); 4851182999Smav ); 4852182999Smav /* Trace this pin taking goal into account. */ 4853182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 4854182999Smav ases[as].pins[i], j, 0) == 0) { 4855182999Smav /* If we failed - return to previous and redo it. */ 4856182999Smav HDA_BOOTVERBOSE( 4857182999Smav device_printf(devinfo->codec->sc->dev, 4858183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 4859182999Smav ases[as].pins[i], j); 4860182999Smav ); 4861182999Smav hdac_audio_undo_trace(devinfo, as, -1); 4862182999Smav for (k = 0; k < 16; k++) 4863182999Smav ases[as].dacs[k] = 0; 4864182999Smav break; 4865162922Sariff } 4866182999Smav HDA_BOOTVERBOSE( 4867182999Smav device_printf(devinfo->codec->sc->dev, 4868183097Smav " Pin %d traced to ADC %d\n", 4869183097Smav ases[as].pins[i], j); 4870182999Smav ); 4871182999Smav ases[as].dacs[i] = j; 4872162922Sariff } 4873182999Smav if (i == 16) 4874182999Smav return (1); 4875162922Sariff } 4876182999Smav return (0); 4877162922Sariff} 4878162922Sariff 4879182999Smav/* 4880182999Smav * Trace input monitor path from mixer to output association. 4881182999Smav */ 4882183097Smavstatic int 4883182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4884162922Sariff{ 4885182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4886182999Smav struct hdac_widget *w, *wc; 4887182999Smav int i, j; 4888182999Smav nid_t res = 0; 4889162922Sariff 4890162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4891162922Sariff return (0); 4892162922Sariff w = hdac_widget_get(devinfo, nid); 4893162922Sariff if (w == NULL || w->enable == 0) 4894162922Sariff return (0); 4895183097Smav HDA_BOOTHVERBOSE( 4896182999Smav device_printf(devinfo->codec->sc->dev, 4897182999Smav " %*stracing via nid %d\n", 4898182999Smav depth + 1, "", w->nid); 4899182999Smav ); 4900182999Smav /* Use only unused widgets */ 4901182999Smav if (depth > 0 && w->bindas != -1) { 4902182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 4903183097Smav HDA_BOOTHVERBOSE( 4904182999Smav device_printf(devinfo->codec->sc->dev, 4905182999Smav " %*snid %d found output association %d\n", 4906182999Smav depth + 1, "", w->nid, w->bindas); 4907182999Smav ); 4908182999Smav return (1); 4909182999Smav } else { 4910183097Smav HDA_BOOTHVERBOSE( 4911182999Smav device_printf(devinfo->codec->sc->dev, 4912182999Smav " %*snid %d busy by input association %d\n", 4913182999Smav depth + 1, "", w->nid, w->bindas); 4914182999Smav ); 4915182999Smav return (0); 4916182999Smav } 4917182999Smav } 4918182999Smav 4919162922Sariff switch (w->type) { 4920162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4921182999Smav /* Do not traverse input. AD1988 has digital monitor 4922182999Smav for which we are not ready. */ 4923162922Sariff break; 4924162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4925182999Smav if (depth > 0) 4926182999Smav break; 4927182999Smav /* Fall */ 4928182999Smav default: 4929182999Smav /* Try to find reachable ADCs with specified nid. */ 4930182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4931182999Smav wc = hdac_widget_get(devinfo, j); 4932182999Smav if (wc == NULL || wc->enable == 0) 4933182999Smav continue; 4934182999Smav for (i = 0; i < wc->nconns; i++) { 4935182999Smav if (wc->connsenable[i] == 0) 4936182999Smav continue; 4937182999Smav if (wc->conns[i] != nid) 4938182999Smav continue; 4939182999Smav if (hdac_audio_trace_to_out(devinfo, 4940182999Smav j, depth + 1) != 0) { 4941182999Smav res = 1; 4942182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4943182999Smav wc->selconn == -1) 4944182999Smav wc->selconn = i; 4945182999Smav } 4946182999Smav } 4947162922Sariff } 4948162922Sariff break; 4949182999Smav } 4950182999Smav if (res) 4951182999Smav w->bindas = -2; 4952182999Smav 4953183097Smav HDA_BOOTHVERBOSE( 4954182999Smav device_printf(devinfo->codec->sc->dev, 4955182999Smav " %*snid %d returned %d\n", 4956182999Smav depth + 1, "", w->nid, res); 4957182999Smav ); 4958182999Smav return (res); 4959182999Smav} 4960182999Smav 4961182999Smav/* 4962182999Smav * Trace extra associations (beeper, monitor) 4963182999Smav */ 4964182999Smavstatic void 4965182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 4966182999Smav{ 4967182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 4968182999Smav struct hdac_widget *w; 4969182999Smav int j; 4970182999Smav 4971182999Smav /* Input monitor */ 4972182999Smav /* Find mixer associated with input, but supplying signal 4973182999Smav for output associations. Hope it will be input monitor. */ 4974182999Smav HDA_BOOTVERBOSE( 4975182999Smav device_printf(devinfo->codec->sc->dev, 4976182999Smav "Tracing input monitor\n"); 4977182999Smav ); 4978182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4979182999Smav w = hdac_widget_get(devinfo, j); 4980182999Smav if (w == NULL || w->enable == 0) 4981182999Smav continue; 4982182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 4983182999Smav continue; 4984182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 4985182999Smav continue; 4986182999Smav HDA_BOOTVERBOSE( 4987182999Smav device_printf(devinfo->codec->sc->dev, 4988182999Smav " Tracing nid %d to out\n", 4989182999Smav j); 4990182999Smav ); 4991182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 4992182999Smav HDA_BOOTVERBOSE( 4993182999Smav device_printf(devinfo->codec->sc->dev, 4994182999Smav " nid %d is input monitor\n", 4995182999Smav w->nid); 4996182999Smav ); 4997182999Smav w->pflags |= HDA_ADC_MONITOR; 4998182999Smav w->ossdev = SOUND_MIXER_IMIX; 4999162922Sariff } 5000162922Sariff } 5001182999Smav 5002182999Smav /* Beeper */ 5003182999Smav HDA_BOOTVERBOSE( 5004182999Smav device_printf(devinfo->codec->sc->dev, 5005182999Smav "Tracing beeper\n"); 5006182999Smav ); 5007182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5008182999Smav w = hdac_widget_get(devinfo, j); 5009182999Smav if (w == NULL || w->enable == 0) 5010182999Smav continue; 5011182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5012182999Smav continue; 5013183097Smav HDA_BOOTHVERBOSE( 5014182999Smav device_printf(devinfo->codec->sc->dev, 5015182999Smav " Tracing nid %d to out\n", 5016182999Smav j); 5017182999Smav ); 5018183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5019183097Smav HDA_BOOTVERBOSE( 5020183097Smav device_printf(devinfo->codec->sc->dev, 5021183097Smav " nid %d traced to out\n", 5022183097Smav j); 5023183097Smav ); 5024183097Smav } 5025182999Smav w->bindas = -2; 5026182999Smav } 5027162922Sariff} 5028162922Sariff 5029182999Smav/* 5030182999Smav * Bind assotiations to PCM channels 5031182999Smav */ 5032182999Smavstatic void 5033182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5034162922Sariff{ 5035182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5036182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5037182999Smav int j, cnt = 0, free; 5038162922Sariff 5039182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5040182999Smav if (as[j].enable) 5041182999Smav cnt++; 5042182999Smav } 5043182999Smav if (sc->num_chans == 0) { 5044182999Smav sc->chans = (struct hdac_chan *)malloc( 5045182999Smav sizeof(struct hdac_chan) * cnt, 5046182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5047182999Smav if (sc->chans == NULL) { 5048182999Smav device_printf(devinfo->codec->sc->dev, 5049182999Smav "Channels memory allocation failed!\n"); 5050182999Smav return; 5051182999Smav } 5052182999Smav } else { 5053182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5054183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5055182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5056182999Smav if (sc->chans == NULL) { 5057182999Smav sc->num_chans = 0; 5058182999Smav device_printf(devinfo->codec->sc->dev, 5059182999Smav "Channels memory allocation failed!\n"); 5060182999Smav return; 5061182999Smav } 5062182999Smav } 5063182999Smav free = sc->num_chans; 5064182999Smav sc->num_chans += cnt; 5065162922Sariff 5066182999Smav for (j = free; j < free + cnt; j++) { 5067182999Smav devinfo->codec->sc->chans[j].devinfo = devinfo; 5068182999Smav devinfo->codec->sc->chans[j].as = -1; 5069182999Smav } 5070162922Sariff 5071182999Smav /* Assign associations in order of their numbers, */ 5072182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5073182999Smav if (as[j].enable == 0) 5074182999Smav continue; 5075182999Smav 5076182999Smav as[j].chan = free; 5077182999Smav devinfo->codec->sc->chans[free].as = j; 5078182999Smav if (as[j].dir == HDA_CTL_IN) { 5079182999Smav devinfo->codec->sc->chans[free].dir = PCMDIR_REC; 5080182999Smav devinfo->function.audio.reccnt++; 5081182999Smav } else { 5082182999Smav devinfo->codec->sc->chans[free].dir = PCMDIR_PLAY; 5083182999Smav devinfo->function.audio.playcnt++; 5084182999Smav } 5085182999Smav hdac_pcmchannel_setup(&devinfo->codec->sc->chans[free]); 5086182999Smav free++; 5087182999Smav } 5088182999Smav} 5089162922Sariff 5090182999Smavstatic void 5091182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5092182999Smav{ 5093182999Smav struct hdac_widget *w; 5094182999Smav int i; 5095182999Smav 5096182999Smav /* Disable power and volume widgets. */ 5097182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5098182999Smav w = hdac_widget_get(devinfo, i); 5099182999Smav if (w == NULL || w->enable == 0) 5100182999Smav continue; 5101182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5102182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5103182999Smav w->enable = 0; 5104183097Smav HDA_BOOTHVERBOSE( 5105182999Smav device_printf(devinfo->codec->sc->dev, 5106182999Smav " Disabling nid %d due to it's" 5107182999Smav " non-audio type.\n", 5108182999Smav w->nid); 5109182999Smav ); 5110162922Sariff } 5111182999Smav } 5112182999Smav} 5113182999Smav 5114182999Smavstatic void 5115182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5116182999Smav{ 5117182999Smav struct hdac_widget *w, *cw; 5118182999Smav struct hdac_audio_ctl *ctl; 5119182999Smav int done, found, i, j, k; 5120182999Smav 5121182999Smav /* Disable useless pins. */ 5122182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5123182999Smav w = hdac_widget_get(devinfo, i); 5124182999Smav if (w == NULL || w->enable == 0) 5125182999Smav continue; 5126184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5127184991Smav if ((w->wclass.pin.config & 5128184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5129184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5130184991Smav w->enable = 0; 5131184991Smav HDA_BOOTHVERBOSE( 5132184991Smav device_printf(devinfo->codec->sc->dev, 5133184991Smav " Disabling pin nid %d due" 5134184991Smav " to None connectivity.\n", 5135184991Smav w->nid); 5136184991Smav ); 5137184991Smav } else if ((w->wclass.pin.config & 5138184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5139184991Smav w->enable = 0; 5140184991Smav HDA_BOOTHVERBOSE( 5141184991Smav device_printf(devinfo->codec->sc->dev, 5142184991Smav " Disabling unassociated" 5143184991Smav " pin nid %d.\n", 5144184991Smav w->nid); 5145184991Smav ); 5146184991Smav } 5147182999Smav } 5148182999Smav } 5149182999Smav do { 5150182999Smav done = 1; 5151182999Smav /* Disable and mute controls for disabled widgets. */ 5152162922Sariff i = 0; 5153162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5154182999Smav if (ctl->enable == 0) 5155162922Sariff continue; 5156182999Smav if (ctl->widget->enable == 0 || 5157182999Smav (ctl->childwidget != NULL && 5158182999Smav ctl->childwidget->enable == 0)) { 5159182999Smav ctl->forcemute = 1; 5160182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5161182999Smav ctl->left = 0; 5162182999Smav ctl->right = 0; 5163182999Smav ctl->enable = 0; 5164182999Smav if (ctl->ndir == HDA_CTL_IN) 5165182999Smav ctl->widget->connsenable[ctl->index] = 0; 5166182999Smav done = 0; 5167183097Smav HDA_BOOTHVERBOSE( 5168182999Smav device_printf(devinfo->codec->sc->dev, 5169182999Smav " Disabling ctl %d nid %d cnid %d due" 5170182999Smav " to disabled widget.\n", i, 5171182999Smav ctl->widget->nid, 5172182999Smav (ctl->childwidget != NULL)? 5173182999Smav ctl->childwidget->nid:-1); 5174182999Smav ); 5175182999Smav } 5176182999Smav } 5177182999Smav /* Disable useless widgets. */ 5178182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5179182999Smav w = hdac_widget_get(devinfo, i); 5180182999Smav if (w == NULL || w->enable == 0) 5181182999Smav continue; 5182182999Smav /* Disable inputs with disabled child widgets. */ 5183182999Smav for (j = 0; j < w->nconns; j++) { 5184182999Smav if (w->connsenable[j]) { 5185182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5186182999Smav if (cw == NULL || cw->enable == 0) { 5187182999Smav w->connsenable[j] = 0; 5188183097Smav HDA_BOOTHVERBOSE( 5189182999Smav device_printf(devinfo->codec->sc->dev, 5190182999Smav " Disabling nid %d connection %d due" 5191182999Smav " to disabled child widget.\n", 5192182999Smav i, j); 5193182999Smav ); 5194163057Sariff } 5195163057Sariff } 5196162922Sariff } 5197182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5198182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5199162922Sariff continue; 5200182999Smav /* Disable mixers and selectors without inputs. */ 5201182999Smav found = 0; 5202182999Smav for (j = 0; j < w->nconns; j++) { 5203182999Smav if (w->connsenable[j]) { 5204182999Smav found = 1; 5205162922Sariff break; 5206162922Sariff } 5207182999Smav } 5208182999Smav if (found == 0) { 5209182999Smav w->enable = 0; 5210182999Smav done = 0; 5211183097Smav HDA_BOOTHVERBOSE( 5212182999Smav device_printf(devinfo->codec->sc->dev, 5213182999Smav " Disabling nid %d due to all it's" 5214182999Smav " inputs disabled.\n", w->nid); 5215182999Smav ); 5216182999Smav } 5217182999Smav /* Disable nodes without consumers. */ 5218182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5219182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5220182999Smav continue; 5221182999Smav found = 0; 5222182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5223182999Smav cw = hdac_widget_get(devinfo, k); 5224182999Smav if (cw == NULL || cw->enable == 0) 5225182999Smav continue; 5226182999Smav for (j = 0; j < cw->nconns; j++) { 5227182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5228182999Smav found = 1; 5229182999Smav break; 5230182999Smav } 5231162922Sariff } 5232162922Sariff } 5233182999Smav if (found == 0) { 5234182999Smav w->enable = 0; 5235182999Smav done = 0; 5236183097Smav HDA_BOOTHVERBOSE( 5237182999Smav device_printf(devinfo->codec->sc->dev, 5238182999Smav " Disabling nid %d due to all it's" 5239182999Smav " consumers disabled.\n", w->nid); 5240182999Smav ); 5241182999Smav } 5242162922Sariff } 5243182999Smav } while (done == 0); 5244182999Smav 5245182999Smav} 5246182999Smav 5247182999Smavstatic void 5248182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5249182999Smav{ 5250182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5251182999Smav struct hdac_widget *w, *cw; 5252182999Smav struct hdac_audio_ctl *ctl; 5253182999Smav int i, j, k; 5254182999Smav 5255182999Smav /* Disable unassosiated widgets. */ 5256182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5257182999Smav w = hdac_widget_get(devinfo, i); 5258182999Smav if (w == NULL || w->enable == 0) 5259182999Smav continue; 5260182999Smav if (w->bindas == -1) { 5261182999Smav w->enable = 0; 5262183097Smav HDA_BOOTHVERBOSE( 5263182999Smav device_printf(devinfo->codec->sc->dev, 5264182999Smav " Disabling unassociated nid %d.\n", 5265182999Smav w->nid); 5266182999Smav ); 5267182999Smav } 5268182999Smav } 5269182999Smav /* Disable input connections on input pin and 5270182999Smav * output on output. */ 5271182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5272182999Smav w = hdac_widget_get(devinfo, i); 5273182999Smav if (w == NULL || w->enable == 0) 5274182999Smav continue; 5275182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5276182999Smav continue; 5277182999Smav if (w->bindas < 0) 5278182999Smav continue; 5279182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5280182999Smav for (j = 0; j < w->nconns; j++) { 5281182999Smav if (w->connsenable[j] == 0) 5282182999Smav continue; 5283182999Smav w->connsenable[j] = 0; 5284183097Smav HDA_BOOTHVERBOSE( 5285182999Smav device_printf(devinfo->codec->sc->dev, 5286182999Smav " Disabling connection to input pin " 5287182999Smav "nid %d conn %d.\n", 5288182999Smav i, j); 5289182999Smav ); 5290162922Sariff } 5291182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5292182999Smav HDA_CTL_IN, -1, 1); 5293182999Smav if (ctl && ctl->enable) { 5294182999Smav ctl->forcemute = 1; 5295182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5296182999Smav ctl->left = 0; 5297182999Smav ctl->right = 0; 5298182999Smav ctl->enable = 0; 5299182999Smav } 5300182999Smav } else { 5301182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5302182999Smav HDA_CTL_OUT, -1, 1); 5303182999Smav if (ctl && ctl->enable) { 5304182999Smav ctl->forcemute = 1; 5305182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5306182999Smav ctl->left = 0; 5307182999Smav ctl->right = 0; 5308182999Smav ctl->enable = 0; 5309182999Smav } 5310182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5311182999Smav cw = hdac_widget_get(devinfo, k); 5312182999Smav if (cw == NULL || cw->enable == 0) 5313182999Smav continue; 5314182999Smav for (j = 0; j < cw->nconns; j++) { 5315182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5316182999Smav cw->connsenable[j] = 0; 5317183097Smav HDA_BOOTHVERBOSE( 5318182999Smav device_printf(devinfo->codec->sc->dev, 5319182999Smav " Disabling connection from output pin " 5320182999Smav "nid %d conn %d cnid %d.\n", 5321182999Smav k, j, i); 5322182999Smav ); 5323182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5324182999Smav cw->nconns > 1) 5325182999Smav continue; 5326182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5327182999Smav HDA_CTL_IN, j, 1); 5328182999Smav if (ctl && ctl->enable) { 5329182999Smav ctl->forcemute = 1; 5330182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5331182999Smav ctl->left = 0; 5332182999Smav ctl->right = 0; 5333182999Smav ctl->enable = 0; 5334182999Smav } 5335182999Smav } 5336182999Smav } 5337182999Smav } 5338162922Sariff } 5339162922Sariff } 5340162922Sariff} 5341162922Sariff 5342182999Smavstatic void 5343182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5344162922Sariff{ 5345182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5346182999Smav struct hdac_widget *w; 5347182999Smav int i, j; 5348182999Smav 5349182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5350182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5351182999Smav w = hdac_widget_get(devinfo, i); 5352182999Smav if (w == NULL || w->enable == 0) 5353182999Smav continue; 5354182999Smav if (w->nconns <= 1) 5355182999Smav continue; 5356182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5357182999Smav continue; 5358182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5359182999Smav continue; 5360182999Smav for (j = 0; j < w->nconns; j++) { 5361182999Smav if (w->connsenable[j] == 0) 5362182999Smav continue; 5363182999Smav if (w->selconn < 0 || w->selconn == j) 5364182999Smav continue; 5365182999Smav w->connsenable[j] = 0; 5366183097Smav HDA_BOOTHVERBOSE( 5367182999Smav device_printf(devinfo->codec->sc->dev, 5368182999Smav " Disabling unselected connection " 5369182999Smav "nid %d conn %d.\n", 5370182999Smav i, j); 5371182999Smav ); 5372182999Smav } 5373182999Smav } 5374182999Smav} 5375182999Smav 5376182999Smavstatic void 5377182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5378182999Smav{ 5379162922Sariff struct hdac_widget *w, *cw; 5380162922Sariff struct hdac_audio_ctl *ctl; 5381182999Smav int i, j; 5382162922Sariff 5383182999Smav /* Disable crossassociatement connections. */ 5384182999Smav /* ... using selectors */ 5385182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5386182999Smav w = hdac_widget_get(devinfo, i); 5387182999Smav if (w == NULL || w->enable == 0) 5388182999Smav continue; 5389182999Smav if (w->nconns <= 1) 5390182999Smav continue; 5391182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5392182999Smav continue; 5393182999Smav if (w->bindas == -2) 5394182999Smav continue; 5395182999Smav for (j = 0; j < w->nconns; j++) { 5396182999Smav if (w->connsenable[j] == 0) 5397182999Smav continue; 5398182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5399182999Smav if (cw == NULL || w->enable == 0) 5400182999Smav continue; 5401182999Smav if (w->bindas == cw->bindas || cw->bindas == -2) 5402182999Smav continue; 5403182999Smav w->connsenable[j] = 0; 5404183097Smav HDA_BOOTHVERBOSE( 5405182999Smav device_printf(devinfo->codec->sc->dev, 5406182999Smav " Disabling crossassociatement connection " 5407182999Smav "nid %d conn %d cnid %d.\n", 5408182999Smav i, j, cw->nid); 5409182999Smav ); 5410182999Smav } 5411182999Smav } 5412182999Smav /* ... using controls */ 5413182999Smav i = 0; 5414182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5415182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5416182999Smav continue; 5417182999Smav if (ctl->widget->bindas == -2 || 5418182999Smav ctl->childwidget->bindas == -2) 5419182999Smav continue; 5420182999Smav if (ctl->widget->bindas != ctl->childwidget->bindas) { 5421182999Smav ctl->forcemute = 1; 5422182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5423182999Smav ctl->left = 0; 5424182999Smav ctl->right = 0; 5425182999Smav ctl->enable = 0; 5426182999Smav if (ctl->ndir == HDA_CTL_IN) 5427182999Smav ctl->widget->connsenable[ctl->index] = 0; 5428183097Smav HDA_BOOTHVERBOSE( 5429182999Smav device_printf(devinfo->codec->sc->dev, 5430182999Smav " Disabling crossassociatement connection " 5431182999Smav "ctl %d nid %d cnid %d.\n", i, 5432182999Smav ctl->widget->nid, 5433182999Smav ctl->childwidget->nid); 5434182999Smav ); 5435182999Smav } 5436182999Smav } 5437182999Smav 5438182999Smav} 5439182999Smav 5440182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5441182999Smav 5442182999Smav/* 5443182999Smav * Find controls to control amplification for source. 5444182999Smav */ 5445182999Smavstatic int 5446182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5447182999Smav int ossdev, int ctlable, int depth, int need) 5448182999Smav{ 5449182999Smav struct hdac_widget *w, *wc; 5450182999Smav struct hdac_audio_ctl *ctl; 5451182999Smav int i, j, conns = 0, rneed; 5452182999Smav 5453162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5454182999Smav return (need); 5455162922Sariff 5456162922Sariff w = hdac_widget_get(devinfo, nid); 5457162922Sariff if (w == NULL || w->enable == 0) 5458182999Smav return (need); 5459182999Smav 5460182999Smav /* Count number of active inputs. */ 5461182999Smav if (depth > 0) { 5462182999Smav for (j = 0; j < w->nconns; j++) { 5463182999Smav if (w->connsenable[j]) 5464182999Smav conns++; 5465162922Sariff } 5466162922Sariff } 5467182999Smav 5468182999Smav /* If this is not a first step - use input mixer. 5469182999Smav Pins have common input ctl so care must be taken. */ 5470182999Smav if (depth > 0 && ctlable && (conns == 1 || 5471182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5472182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5473182999Smav index, 1); 5474182999Smav if (ctl) { 5475182999Smav if (HDA_CTL_GIVE(ctl) & need) 5476182999Smav ctl->ossmask |= (1 << ossdev); 5477182999Smav else 5478182999Smav ctl->possmask |= (1 << ossdev); 5479182999Smav need &= ~HDA_CTL_GIVE(ctl); 5480182999Smav } 5481182999Smav } 5482182999Smav 5483182999Smav /* If widget has own ossdev - not traverse it. 5484182999Smav It will be traversed on it's own. */ 5485182999Smav if (w->ossdev >= 0 && depth > 0) 5486182999Smav return (need); 5487182999Smav 5488182999Smav /* We must not traverse pin */ 5489182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5490182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5491182999Smav depth > 0) 5492182999Smav return (need); 5493182999Smav 5494182999Smav /* record that this widget exports such signal, */ 5495182999Smav w->ossmask |= (1 << ossdev); 5496182999Smav 5497182999Smav /* If signals mixed, we can't assign controls farther. 5498182999Smav * Ignore this on depth zero. Caller must knows why. 5499182999Smav * Ignore this for static selectors if this input selected. 5500182999Smav */ 5501182999Smav if (conns > 1) 5502182999Smav ctlable = 0; 5503182999Smav 5504182999Smav if (ctlable) { 5505182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5506182999Smav if (ctl) { 5507182999Smav if (HDA_CTL_GIVE(ctl) & need) 5508182999Smav ctl->ossmask |= (1 << ossdev); 5509182999Smav else 5510182999Smav ctl->possmask |= (1 << ossdev); 5511182999Smav need &= ~HDA_CTL_GIVE(ctl); 5512182999Smav } 5513182999Smav } 5514182999Smav 5515182999Smav rneed = 0; 5516182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5517182999Smav wc = hdac_widget_get(devinfo, i); 5518182999Smav if (wc == NULL || wc->enable == 0) 5519162922Sariff continue; 5520182999Smav for (j = 0; j < wc->nconns; j++) { 5521182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5522182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5523182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5524182999Smav } 5525162922Sariff } 5526162922Sariff } 5527182999Smav rneed &= need; 5528182999Smav 5529182999Smav return (rneed); 5530162922Sariff} 5531162922Sariff 5532182999Smav/* 5533182999Smav * Find controls to control amplification for destination. 5534182999Smav */ 5535182999Smavstatic void 5536182999Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, 5537182999Smav int ossdev, int depth, int need) 5538162922Sariff{ 5539182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5540182999Smav struct hdac_widget *w, *wc; 5541182999Smav struct hdac_audio_ctl *ctl; 5542182999Smav int i, j, consumers; 5543182999Smav 5544162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5545182999Smav return; 5546162922Sariff 5547162922Sariff w = hdac_widget_get(devinfo, nid); 5548162922Sariff if (w == NULL || w->enable == 0) 5549182999Smav return; 5550182999Smav 5551182999Smav if (depth > 0) { 5552182999Smav /* If this node produce output for several consumers, 5553182999Smav we can't touch it. */ 5554182999Smav consumers = 0; 5555182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5556182999Smav wc = hdac_widget_get(devinfo, i); 5557182999Smav if (wc == NULL || wc->enable == 0) 5558182999Smav continue; 5559182999Smav for (j = 0; j < wc->nconns; j++) { 5560182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5561182999Smav consumers++; 5562182999Smav } 5563182999Smav } 5564182999Smav /* The only exception is if real HP redirection is configured 5565182999Smav and this is a duplication point. 5566182999Smav XXX: Actually exception is not completely correct. 5567182999Smav XXX: Duplication point check is not perfect. */ 5568182999Smav if ((consumers == 2 && (w->bindas < 0 || 5569182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5570182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5571182999Smav consumers > 2) 5572182999Smav return; 5573182999Smav 5574182999Smav /* Else use it's output mixer. */ 5575182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5576182999Smav HDA_CTL_OUT, -1, 1); 5577182999Smav if (ctl) { 5578182999Smav if (HDA_CTL_GIVE(ctl) & need) 5579182999Smav ctl->ossmask |= (1 << ossdev); 5580182999Smav else 5581182999Smav ctl->possmask |= (1 << ossdev); 5582182999Smav need &= ~HDA_CTL_GIVE(ctl); 5583182999Smav } 5584182999Smav } 5585182999Smav 5586182999Smav /* We must not traverse pin */ 5587182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5588182999Smav depth > 0) 5589182999Smav return; 5590182999Smav 5591162922Sariff for (i = 0; i < w->nconns; i++) { 5592182999Smav int tneed = need; 5593182999Smav if (w->connsenable[i] == 0) 5594162922Sariff continue; 5595182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5596182999Smav HDA_CTL_IN, i, 1); 5597182999Smav if (ctl) { 5598182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 5599182999Smav ctl->ossmask |= (1 << ossdev); 5600182999Smav else 5601182999Smav ctl->possmask |= (1 << ossdev); 5602182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 5603162922Sariff } 5604182999Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev, 5605182999Smav depth + 1, tneed); 5606162922Sariff } 5607162922Sariff} 5608162922Sariff 5609182999Smav/* 5610182999Smav * Assign OSS names to sound sources 5611182999Smav */ 5612182999Smavstatic void 5613182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 5614162922Sariff{ 5615182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5616182999Smav struct hdac_widget *w; 5617182999Smav int i, j; 5618182999Smav int type = -1, use, used = 0; 5619182999Smav static const int types[7][13] = { 5620182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5621182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 5622182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 5623182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 5624182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 5625182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 5626182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 5627182999Smav -1 }, /* digital */ 5628182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5629182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 5630182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 5631182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 5632182999Smav -1 } /* others */ 5633182999Smav }; 5634162922Sariff 5635182999Smav /* Surely known names */ 5636162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5637162922Sariff w = hdac_widget_get(devinfo, i); 5638162922Sariff if (w == NULL || w->enable == 0) 5639162922Sariff continue; 5640182999Smav if (w->bindas == -1) 5641182999Smav continue; 5642182999Smav use = -1; 5643182999Smav switch (w->type) { 5644182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5645182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5646182999Smav break; 5647182999Smav type = -1; 5648182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5649182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 5650182999Smav type = 0; 5651182999Smav break; 5652182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5653182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 5654182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 5655182999Smav break; 5656182999Smav type = 1; 5657182999Smav break; 5658182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 5659182999Smav type = 3; 5660182999Smav break; 5661182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5662182999Smav type = 4; 5663182999Smav break; 5664182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 5665182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 5666182999Smav type = 5; 5667182999Smav break; 5668182999Smav } 5669182999Smav if (type == -1) 5670182999Smav break; 5671182999Smav j = 0; 5672182999Smav while (types[type][j] >= 0 && 5673182999Smav (used & (1 << types[type][j])) != 0) { 5674182999Smav j++; 5675182999Smav } 5676182999Smav if (types[type][j] >= 0) 5677182999Smav use = types[type][j]; 5678182999Smav break; 5679182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5680182999Smav use = SOUND_MIXER_PCM; 5681182999Smav break; 5682182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 5683182999Smav use = SOUND_MIXER_SPEAKER; 5684182999Smav break; 5685182999Smav default: 5686182999Smav break; 5687182999Smav } 5688182999Smav if (use >= 0) { 5689182999Smav w->ossdev = use; 5690182999Smav used |= (1 << use); 5691182999Smav } 5692182999Smav } 5693182999Smav /* Semi-known names */ 5694182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5695182999Smav w = hdac_widget_get(devinfo, i); 5696182999Smav if (w == NULL || w->enable == 0) 5697182999Smav continue; 5698182999Smav if (w->ossdev >= 0) 5699182999Smav continue; 5700182999Smav if (w->bindas == -1) 5701182999Smav continue; 5702162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5703162922Sariff continue; 5704182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5705162922Sariff continue; 5706182999Smav type = -1; 5707182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5708182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 5709182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5710182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 5711182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 5712182999Smav type = 0; 5713182999Smav break; 5714182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5715182999Smav type = 2; 5716182999Smav break; 5717182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 5718182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 5719182999Smav type = 5; 5720182999Smav break; 5721182999Smav } 5722182999Smav if (type == -1) 5723182999Smav break; 5724182999Smav j = 0; 5725182999Smav while (types[type][j] >= 0 && 5726182999Smav (used & (1 << types[type][j])) != 0) { 5727182999Smav j++; 5728182999Smav } 5729182999Smav if (types[type][j] >= 0) { 5730182999Smav w->ossdev = types[type][j]; 5731182999Smav used |= (1 << types[type][j]); 5732182999Smav } 5733182999Smav } 5734182999Smav /* Others */ 5735182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5736182999Smav w = hdac_widget_get(devinfo, i); 5737182999Smav if (w == NULL || w->enable == 0) 5738162922Sariff continue; 5739182999Smav if (w->ossdev >= 0) 5740182999Smav continue; 5741182999Smav if (w->bindas == -1) 5742182999Smav continue; 5743182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5744182999Smav continue; 5745182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5746182999Smav continue; 5747182999Smav j = 0; 5748182999Smav while (types[6][j] >= 0 && 5749182999Smav (used & (1 << types[6][j])) != 0) { 5750182999Smav j++; 5751162922Sariff } 5752182999Smav if (types[6][j] >= 0) { 5753182999Smav w->ossdev = types[6][j]; 5754182999Smav used |= (1 << types[6][j]); 5755182999Smav } 5756162922Sariff } 5757162922Sariff} 5758162922Sariff 5759162922Sariffstatic void 5760162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5761162922Sariff{ 5762182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5763182999Smav int j, res; 5764162922Sariff 5765182999Smav /* Trace all associations in order of their numbers, */ 5766182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5767182999Smav if (as[j].enable == 0) 5768182999Smav continue; 5769163057Sariff HDA_BOOTVERBOSE( 5770162922Sariff device_printf(devinfo->codec->sc->dev, 5771182999Smav "Tracing association %d (%d)\n", j, as[j].index); 5772162922Sariff ); 5773182999Smav if (as[j].dir == HDA_CTL_OUT) { 5774182999Smavretry: 5775182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 5776182999Smav if (res == 0 && as[j].hpredir >= 0 && 5777182999Smav as[j].fakeredir == 0) { 5778182999Smav /* If codec can't do analog HP redirection 5779182999Smav try to make it using one more DAC. */ 5780182999Smav as[j].fakeredir = 1; 5781182999Smav goto retry; 5782182999Smav } 5783182999Smav } else { 5784182999Smav res = hdac_audio_trace_as_in(devinfo, j); 5785182999Smav } 5786182999Smav if (res) { 5787182999Smav HDA_BOOTVERBOSE( 5788182999Smav device_printf(devinfo->codec->sc->dev, 5789182999Smav "Association %d (%d) trace succeded\n", 5790182999Smav j, as[j].index); 5791182999Smav ); 5792182999Smav } else { 5793182999Smav HDA_BOOTVERBOSE( 5794182999Smav device_printf(devinfo->codec->sc->dev, 5795182999Smav "Association %d (%d) trace failed\n", 5796182999Smav j, as[j].index); 5797182999Smav ); 5798182999Smav as[j].enable = 0; 5799182999Smav } 5800162922Sariff } 5801162922Sariff 5802182999Smav /* Trace mixer and beeper pseudo associations. */ 5803182999Smav hdac_audio_trace_as_extra(devinfo); 5804182999Smav} 5805162922Sariff 5806182999Smavstatic void 5807182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 5808182999Smav{ 5809182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5810182999Smav struct hdac_audio_ctl *ctl; 5811182999Smav struct hdac_widget *w; 5812182999Smav int i; 5813162922Sariff 5814182999Smav /* Assign mixers to the tree. */ 5815162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5816162922Sariff w = hdac_widget_get(devinfo, i); 5817162922Sariff if (w == NULL || w->enable == 0) 5818162922Sariff continue; 5819182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 5820182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 5821182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5822182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 5823182999Smav if (w->ossdev < 0) 5824182999Smav continue; 5825182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 5826182999Smav w->ossdev, 1, 0, 1); 5827182999Smav } else if ((w->pflags & HDA_ADC_MONITOR) != 0) { 5828182999Smav if (w->ossdev < 0) 5829182999Smav continue; 5830182999Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 5831182999Smav w->ossdev, 1, 0, 1)) { 5832182999Smav /* If we are unable to control input monitor 5833182999Smav as source - try to control it as destination. */ 5834182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5835182999Smav w->ossdev, 0, 1); 5836162922Sariff } 5837182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 5838182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5839182999Smav SOUND_MIXER_RECLEV, 0, 1); 5840182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5841182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 5842182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5843182999Smav SOUND_MIXER_VOLUME, 0, 1); 5844162922Sariff } 5845162922Sariff } 5846182999Smav /* Treat unrequired as possible. */ 5847182999Smav i = 0; 5848182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5849182999Smav if (ctl->ossmask == 0) 5850182999Smav ctl->ossmask = ctl->possmask; 5851182999Smav } 5852182999Smav} 5853162922Sariff 5854182999Smavstatic void 5855182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 5856182999Smav{ 5857182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5858182999Smav struct hdac_widget *w; 5859182999Smav uint32_t pincap; 5860182999Smav int i; 5861182999Smav 5862182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 5863182999Smav w = &devinfo->widget[i]; 5864182999Smav if (w == NULL) 5865162922Sariff continue; 5866182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5867162922Sariff continue; 5868182999Smav 5869182999Smav pincap = w->wclass.pin.cap; 5870182999Smav 5871182999Smav /* Disable everything. */ 5872182999Smav w->wclass.pin.ctrl &= ~( 5873182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 5874182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 5875182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 5876182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 5877182999Smav 5878182999Smav if (w->enable == 0 || 5879182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 5880182999Smav /* Pin is unused so left it disabled. */ 5881182999Smav continue; 5882182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 5883182999Smav /* Input pin, configure for input. */ 5884182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 5885182999Smav w->wclass.pin.ctrl |= 5886182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 5887182999Smav 5888182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 5889182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5890182999Smav w->wclass.pin.ctrl |= 5891182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5892182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5893182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 5894182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5895182999Smav w->wclass.pin.ctrl |= 5896182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5897182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5898182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 5899182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5900182999Smav w->wclass.pin.ctrl |= 5901182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5902182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5903182999Smav } else { 5904182999Smav /* Output pin, configure for output. */ 5905182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 5906182999Smav w->wclass.pin.ctrl |= 5907182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 5908182999Smav 5909182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 5910182999Smav (w->wclass.pin.config & 5911182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 5912182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 5913182999Smav w->wclass.pin.ctrl |= 5914182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 5915182999Smav 5916182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 5917182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5918182999Smav w->wclass.pin.ctrl |= 5919182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5920182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5921182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 5922182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5923182999Smav w->wclass.pin.ctrl |= 5924182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5925182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5926182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 5927182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5928182999Smav w->wclass.pin.ctrl |= 5929182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5930182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5931182999Smav } 5932162922Sariff } 5933162922Sariff} 5934162922Sariff 5935162922Sariffstatic void 5936182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 5937162922Sariff{ 5938162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5939162922Sariff struct hdac_widget *w; 5940164750Sariff nid_t cad; 5941182999Smav uint32_t gdata, gmask, gdir; 5942182999Smav int commitgpio, numgpio; 5943164750Sariff int i; 5944162922Sariff 5945162922Sariff cad = devinfo->codec->cad; 5946162922Sariff 5947182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 5948182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 5949182999Smav 0x7e7, 0), cad); 5950169277Sariff 5951182999Smav gdata = 0; 5952182999Smav gmask = 0; 5953182999Smav gdir = 0; 5954182999Smav commitgpio = 0; 5955164828Sariff 5956182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 5957182999Smav devinfo->function.audio.gpio); 5958166796Sariff 5959182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 5960182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 5961182999Smav else { 5962182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 5963182999Smav if (!(devinfo->function.audio.quirks & 5964182999Smav (1 << i))) 5965182999Smav continue; 5966182999Smav if (commitgpio == 0) { 5967182999Smav commitgpio = 1; 5968182999Smav HDA_BOOTVERBOSE( 5969182999Smav gdata = hdac_command(sc, 5970182999Smav HDA_CMD_GET_GPIO_DATA(cad, 5971182999Smav devinfo->nid), cad); 5972182999Smav gmask = hdac_command(sc, 5973182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 5974182999Smav devinfo->nid), cad); 5975182999Smav gdir = hdac_command(sc, 5976182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 5977182999Smav devinfo->nid), cad); 5978182999Smav device_printf(sc->dev, 5979182999Smav "GPIO init: data=0x%08x " 5980182999Smav "mask=0x%08x dir=0x%08x\n", 5981182999Smav gdata, gmask, gdir); 5982182999Smav gdata = 0; 5983182999Smav gmask = 0; 5984182999Smav gdir = 0; 5985182999Smav ); 5986165039Sariff } 5987182999Smav gdata |= 1 << i; 5988182999Smav gmask |= 1 << i; 5989182999Smav gdir |= 1 << i; 5990165039Sariff } 5991182999Smav } 5992165039Sariff 5993182999Smav if (commitgpio != 0) { 5994182999Smav HDA_BOOTVERBOSE( 5995182999Smav device_printf(sc->dev, 5996182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 5997182999Smav "dir=0x%08x\n", 5998182999Smav gdata, gmask, gdir); 5999182999Smav ); 6000182999Smav hdac_command(sc, 6001182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6002182999Smav gmask), cad); 6003182999Smav hdac_command(sc, 6004182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6005182999Smav gdir), cad); 6006182999Smav hdac_command(sc, 6007182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6008182999Smav gdata), cad); 6009162922Sariff } 6010162922Sariff 6011162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 6012162922Sariff w = &devinfo->widget[i]; 6013182999Smav if (w == NULL) 6014162922Sariff continue; 6015182999Smav if (w->selconn == -1) 6016182999Smav w->selconn = 0; 6017182999Smav if (w->nconns > 0) 6018182999Smav hdac_widget_connection_select(w, w->selconn); 6019182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6020162922Sariff hdac_command(sc, 6021162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6022162922Sariff w->wclass.pin.ctrl), cad); 6023162922Sariff } 6024182999Smav if (w->param.eapdbtl != HDAC_INVALID) { 6025163432Sariff uint32_t val; 6026163432Sariff 6027163432Sariff val = w->param.eapdbtl; 6028163276Sariff if (devinfo->function.audio.quirks & 6029163432Sariff HDA_QUIRK_EAPDINV) 6030163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6031162922Sariff hdac_command(sc, 6032162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6033163432Sariff val), cad); 6034162922Sariff 6035163276Sariff } 6036162922Sariff DELAY(1000); 6037162922Sariff } 6038162922Sariff} 6039162922Sariff 6040162922Sariffstatic void 6041162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6042162922Sariff{ 6043162922Sariff struct hdac_audio_ctl *ctl; 6044182999Smav int i, z; 6045162922Sariff 6046162922Sariff i = 0; 6047162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6048182999Smav if (ctl->enable == 0) { 6049182999Smav /* Mute disabled controls. */ 6050182999Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6051162922Sariff continue; 6052162922Sariff } 6053182999Smav /* Init controls to 0dB amplification. */ 6054182999Smav z = ctl->offset; 6055182999Smav if (z > ctl->step) 6056182999Smav z = ctl->step; 6057182999Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6058162922Sariff } 6059162922Sariff} 6060162922Sariff 6061182999Smavstatic void 6062182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6063182999Smav{ 6064182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6065182999Smav nid_t cad = devinfo->codec->cad; 6066182999Smav int i; 6067182999Smav 6068182999Smav hdac_command(sc, 6069182999Smav HDA_CMD_SET_POWER_STATE(cad, 6070182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6071182999Smav cad); 6072182999Smav DELAY(100); 6073182999Smav 6074182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6075182999Smav hdac_command(sc, 6076182999Smav HDA_CMD_SET_POWER_STATE(cad, 6077182999Smav i, HDA_CMD_POWER_STATE_D0), 6078182999Smav cad); 6079182999Smav } 6080182999Smav DELAY(1000); 6081182999Smav} 6082182999Smav 6083162922Sariffstatic int 6084182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6085162922Sariff{ 6086182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6087182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6088162922Sariff struct hdac_widget *w; 6089182999Smav uint32_t cap, fmtcap, pcmcap; 6090182999Smav int i, j, ret, max; 6091162922Sariff 6092162922Sariff ch->caps = hdac_caps; 6093162922Sariff ch->caps.fmtlist = ch->fmtlist; 6094162922Sariff ch->bit16 = 1; 6095162922Sariff ch->bit32 = 0; 6096162922Sariff ch->pcmrates[0] = 48000; 6097162922Sariff ch->pcmrates[1] = 0; 6098162922Sariff 6099162922Sariff ret = 0; 6100162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6101162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6102162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 6103162922Sariff 6104182999Smav for (i = 0; i < 16 && ret < max; i++) { 6105182999Smav /* Check as is correct */ 6106182999Smav if (ch->as < 0) 6107182999Smav break; 6108182999Smav /* Cound only present DACs */ 6109182999Smav if (as[ch->as].dacs[i] <= 0) 6110162922Sariff continue; 6111182999Smav /* Ignore duplicates */ 6112182999Smav for (j = 0; j < ret; j++) { 6113182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6114182999Smav break; 6115182999Smav } 6116182999Smav if (j < ret) 6117162922Sariff continue; 6118182999Smav 6119182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6120182999Smav if (w == NULL || w->enable == 0) 6121182999Smav continue; 6122182999Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6123182999Smav continue; 6124162922Sariff cap = w->param.supp_stream_formats; 6125182999Smav /*if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 6126162922Sariff }*/ 6127182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6128182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6129162922Sariff continue; 6130182999Smav /* Many codec does not declare AC3 support on SPDIF. 6131182999Smav I don't beleave that they doesn't support it! */ 6132182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6133182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6134164614Sariff if (ret == 0) { 6135182999Smav fmtcap = cap; 6136164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6137164614Sariff } else { 6138182999Smav fmtcap &= cap; 6139164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6140164614Sariff } 6141182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6142162922Sariff } 6143162922Sariff ch->io[ret] = -1; 6144162922Sariff 6145162922Sariff ch->supp_stream_formats = fmtcap; 6146162922Sariff ch->supp_pcm_size_rate = pcmcap; 6147162922Sariff 6148162922Sariff /* 6149162922Sariff * 8bit = 0 6150162922Sariff * 16bit = 1 6151162922Sariff * 20bit = 2 6152162922Sariff * 24bit = 3 6153162922Sariff * 32bit = 4 6154162922Sariff */ 6155162922Sariff if (ret > 0) { 6156162922Sariff i = 0; 6157182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6158182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6159182999Smav ch->bit16 = 1; 6160182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6161182999Smav ch->bit16 = 0; 6162182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6163182999Smav ch->bit32 = 4; 6164182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6165182999Smav ch->bit32 = 3; 6166182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6167182999Smav ch->bit32 = 2; 6168182999Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 6169182999Smav ch->fmtlist[i++] = AFMT_S16_LE; 6170182999Smav ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 6171182999Smav if (ch->bit32 > 0) { 6172182999Smav if (!(devinfo->function.audio.quirks & 6173182999Smav HDA_QUIRK_FORCESTEREO)) 6174182999Smav ch->fmtlist[i++] = AFMT_S32_LE; 6175182999Smav ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 6176182999Smav } 6177162922Sariff } 6178182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6179182999Smav ch->fmtlist[i++] = AFMT_AC3; 6180182999Smav } 6181162922Sariff ch->fmtlist[i] = 0; 6182162922Sariff i = 0; 6183182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6184162922Sariff ch->pcmrates[i++] = 8000; 6185182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6186162922Sariff ch->pcmrates[i++] = 11025; 6187182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6188162922Sariff ch->pcmrates[i++] = 16000; 6189182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6190162922Sariff ch->pcmrates[i++] = 22050; 6191182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6192162922Sariff ch->pcmrates[i++] = 32000; 6193182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6194162922Sariff ch->pcmrates[i++] = 44100; 6195182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6196162922Sariff ch->pcmrates[i++] = 48000; 6197182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6198162922Sariff ch->pcmrates[i++] = 88200; 6199182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6200162922Sariff ch->pcmrates[i++] = 96000; 6201182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6202162922Sariff ch->pcmrates[i++] = 176400; 6203182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6204162922Sariff ch->pcmrates[i++] = 192000; 6205182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6206162922Sariff ch->pcmrates[i] = 0; 6207162922Sariff if (i > 0) { 6208162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6209162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6210162922Sariff } 6211162922Sariff } 6212162922Sariff 6213162922Sariff return (ret); 6214162922Sariff} 6215162922Sariff 6216162922Sariffstatic void 6217182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6218162922Sariff{ 6219182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6220162922Sariff struct hdac_audio_ctl *ctl; 6221162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6222182999Smav char buf[64]; 6223182999Smav int i, j, printed; 6224162922Sariff 6225162922Sariff if (flag == 0) { 6226182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6227162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6228182999Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN | 6229182999Smav SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6230162922Sariff } 6231162922Sariff 6232182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6233182999Smav if ((flag & (1 << j)) == 0) 6234162922Sariff continue; 6235182999Smav i = 0; 6236182999Smav printed = 0; 6237182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6238182999Smav if (ctl->enable == 0 || 6239182999Smav ctl->widget->enable == 0) 6240182999Smav continue; 6241182999Smav if (!((pdevinfo->play >= 0 && 6242182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6243182999Smav (pdevinfo->rec >= 0 && 6244182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6245182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6246182999Smav continue; 6247182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6248182999Smav continue; 6249182999Smav 6250182999Smav if (printed == 0) { 6251182999Smav device_printf(pdevinfo->dev, "\n"); 6252182999Smav if (banner != NULL) { 6253182999Smav device_printf(pdevinfo->dev, "%s", banner); 6254182999Smav } else { 6255182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6256182999Smav } 6257182999Smav printf(" (OSS: %s)\n", 6258182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6259182999Smav buf, sizeof(buf))); 6260182999Smav device_printf(pdevinfo->dev, " |\n"); 6261182999Smav printed = 1; 6262162922Sariff } 6263182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6264182999Smav ctl->widget->nid, 6265182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6266182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6267182999Smav printf(" %2d): ", ctl->index); 6268182999Smav else 6269182999Smav printf("): "); 6270182999Smav if (ctl->step > 0) { 6271182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6272182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6273182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6274182999Smav ctl->step + 1, 6275182999Smav ctl->mute?" + mute":""); 6276182999Smav } else 6277182999Smav printf("%s\n", ctl->mute?"mute":""); 6278162922Sariff } 6279162922Sariff } 6280162922Sariff} 6281162922Sariff 6282162922Sariffstatic void 6283182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6284162922Sariff{ 6285162922Sariff uint32_t cap; 6286162922Sariff 6287162922Sariff cap = fcap; 6288162922Sariff if (cap != 0) { 6289182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6290183097Smav device_printf(dev, " "); 6291162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6292162922Sariff printf(" AC3"); 6293162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6294162922Sariff printf(" FLOAT32"); 6295162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6296162922Sariff printf(" PCM"); 6297162922Sariff printf("\n"); 6298162922Sariff } 6299162922Sariff cap = pcmcap; 6300162922Sariff if (cap != 0) { 6301182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6302183097Smav device_printf(dev, " "); 6303162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6304162922Sariff printf(" 8"); 6305162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6306162922Sariff printf(" 16"); 6307162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6308162922Sariff printf(" 20"); 6309162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6310162922Sariff printf(" 24"); 6311162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6312162922Sariff printf(" 32"); 6313183097Smav printf(" bits,"); 6314162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6315162922Sariff printf(" 8"); 6316162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6317162922Sariff printf(" 11"); 6318162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6319162922Sariff printf(" 16"); 6320162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6321162922Sariff printf(" 22"); 6322162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6323162922Sariff printf(" 32"); 6324162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6325162922Sariff printf(" 44"); 6326162922Sariff printf(" 48"); 6327162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6328162922Sariff printf(" 88"); 6329162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6330162922Sariff printf(" 96"); 6331162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6332162922Sariff printf(" 176"); 6333162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6334162922Sariff printf(" 192"); 6335183097Smav printf(" KHz\n"); 6336162922Sariff } 6337162922Sariff} 6338162922Sariff 6339162922Sariffstatic void 6340162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6341162922Sariff{ 6342183097Smav uint32_t pincap; 6343162922Sariff 6344162922Sariff pincap = w->wclass.pin.cap; 6345162922Sariff 6346162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6347162922Sariff device_printf(sc->dev, " "); 6348162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6349162922Sariff printf(" ISC"); 6350162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6351162922Sariff printf(" TRQD"); 6352162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6353162922Sariff printf(" PDC"); 6354162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6355162922Sariff printf(" HP"); 6356162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6357162922Sariff printf(" OUT"); 6358162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6359162922Sariff printf(" IN"); 6360162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6361162922Sariff printf(" BAL"); 6362165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6363165069Sariff printf(" VREF["); 6364165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6365165069Sariff printf(" 50"); 6366165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6367165069Sariff printf(" 80"); 6368165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6369165069Sariff printf(" 100"); 6370165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6371165069Sariff printf(" GROUND"); 6372165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6373165069Sariff printf(" HIZ"); 6374165069Sariff printf(" ]"); 6375165069Sariff } 6376162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6377162922Sariff printf(" EAPD"); 6378162922Sariff printf("\n"); 6379162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6380162922Sariff w->wclass.pin.config); 6381162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6382162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6383162922Sariff printf(" HP"); 6384162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6385162922Sariff printf(" IN"); 6386162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6387162922Sariff printf(" OUT"); 6388182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6389182999Smav printf(" VREFs"); 6390162922Sariff printf("\n"); 6391162922Sariff} 6392162922Sariff 6393162922Sariffstatic void 6394182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6395182999Smav{ 6396182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6397182999Smav 6398183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6399182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6400182999Smav w->nid, conf, 6401182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6402182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6403182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6404182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6405182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6406182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6407182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6408182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6409182999Smav (w->enable == 0)?" [DISABLED]":""); 6410182999Smav} 6411182999Smav 6412182999Smavstatic void 6413182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6414182999Smav{ 6415182999Smav struct hdac_widget *w; 6416182999Smav int i; 6417182999Smav 6418182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6419182999Smav w = hdac_widget_get(devinfo, i); 6420182999Smav if (w == NULL) 6421182999Smav continue; 6422182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6423182999Smav continue; 6424182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6425182999Smav } 6426182999Smav} 6427182999Smav 6428182999Smavstatic void 6429162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6430162922Sariff{ 6431163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6432162922Sariff device_printf(sc->dev, " " 6433162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6434162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6435162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6436162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6437162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6438162922Sariff} 6439162922Sariff 6440162922Sariffstatic void 6441162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6442162922Sariff{ 6443162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6444182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6445162922Sariff struct hdac_widget *w, *cw; 6446182999Smav char buf[64]; 6447162922Sariff int i, j; 6448162922Sariff 6449162922Sariff device_printf(sc->dev, "\n"); 6450162922Sariff device_printf(sc->dev, "Default Parameter\n"); 6451162922Sariff device_printf(sc->dev, "-----------------\n"); 6452182999Smav hdac_dump_audio_formats(sc->dev, 6453162922Sariff devinfo->function.audio.supp_stream_formats, 6454162922Sariff devinfo->function.audio.supp_pcm_size_rate); 6455162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 6456162922Sariff devinfo->function.audio.inamp_cap); 6457162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 6458162922Sariff devinfo->function.audio.outamp_cap); 6459162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6460162922Sariff w = hdac_widget_get(devinfo, i); 6461162922Sariff if (w == NULL) { 6462162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 6463162922Sariff continue; 6464162922Sariff } 6465162922Sariff device_printf(sc->dev, "\n"); 6466183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 6467162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 6468183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 6469183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 6470162922Sariff w->param.widget_cap); 6471183097Smav if (w->param.widget_cap & 0x0ee1) { 6472183097Smav device_printf(sc->dev, " "); 6473183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 6474183097Smav printf(" LRSWAP"); 6475183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 6476183097Smav printf(" PWR"); 6477183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6478183097Smav printf(" DIGITAL"); 6479183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 6480183097Smav printf(" UNSOL"); 6481183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 6482183097Smav printf(" PROC"); 6483183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 6484183097Smav printf(" STRIPE"); 6485183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6486183097Smav printf(" STEREO"); 6487183097Smav printf("\n"); 6488183097Smav } 6489183097Smav if (w->bindas != -1) { 6490183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 6491183097Smav w->bindas, w->bindseqmask); 6492183097Smav } 6493183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 6494183097Smav device_printf(sc->dev, " OSS: %s", 6495183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 6496183097Smav if (w->ossdev >= 0) 6497183097Smav printf(" (%s)", ossname[w->ossdev]); 6498183097Smav printf("\n"); 6499183097Smav } 6500162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6501162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6502182999Smav hdac_dump_audio_formats(sc->dev, 6503162922Sariff w->param.supp_stream_formats, 6504162922Sariff w->param.supp_pcm_size_rate); 6505162922Sariff } else if (w->type == 6506162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6507162922Sariff hdac_dump_pin(sc, w); 6508162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 6509162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 6510162922Sariff w->param.eapdbtl); 6511163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 6512163057Sariff w->param.outamp_cap != 0) 6513162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 6514163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 6515163057Sariff w->param.inamp_cap != 0) 6516162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 6517183097Smav if (w->nconns > 0) { 6518183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 6519182999Smav device_printf(sc->dev, " |\n"); 6520183097Smav } 6521162922Sariff for (j = 0; j < w->nconns; j++) { 6522162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 6523182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 6524182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 6525162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 6526162922Sariff if (cw == NULL) 6527162922Sariff printf(" [UNKNOWN]"); 6528162922Sariff else if (cw->enable == 0) 6529162922Sariff printf(" [DISABLED]"); 6530162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 6531162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 6532162922Sariff printf(" (selected)"); 6533162922Sariff printf("\n"); 6534162922Sariff } 6535162922Sariff } 6536162922Sariff 6537162922Sariff} 6538162922Sariff 6539182999Smavstatic void 6540182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 6541163057Sariff{ 6542182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6543163057Sariff struct hdac_widget *w, *cw; 6544182999Smav char buf[64]; 6545182999Smav int i, printed = 0; 6546163057Sariff 6547163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 6548182999Smav return; 6549163057Sariff 6550163057Sariff w = hdac_widget_get(devinfo, nid); 6551182999Smav if (w == NULL || w->enable == 0) 6552182999Smav return; 6553163057Sariff 6554182999Smav if (depth == 0) 6555182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 6556182999Smav else 6557182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 6558182999Smav printf("nid=%d [%s]", w->nid, w->name); 6559163057Sariff 6560182999Smav if (depth > 0) { 6561182999Smav if (w->ossmask == 0) { 6562182999Smav printf("\n"); 6563182999Smav return; 6564163057Sariff } 6565182999Smav printf(" [src: %s]", 6566182999Smav hdac_audio_ctl_ossmixer_mask2allname( 6567182999Smav w->ossmask, buf, sizeof(buf))); 6568182999Smav if (w->ossdev >= 0) { 6569182999Smav printf("\n"); 6570182999Smav return; 6571182999Smav } 6572163057Sariff } 6573182999Smav printf("\n"); 6574182999Smav 6575182999Smav for (i = 0; i < w->nconns; i++) { 6576182999Smav if (w->connsenable[i] == 0) 6577182999Smav continue; 6578182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 6579182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 6580182999Smav continue; 6581182999Smav if (printed == 0) { 6582182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 6583182999Smav printed = 1; 6584182999Smav } 6585182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 6586182999Smav } 6587163057Sariff 6588163057Sariff} 6589163057Sariff 6590162922Sariffstatic void 6591182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 6592162922Sariff{ 6593182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6594182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6595163057Sariff struct hdac_widget *w; 6596163057Sariff int i, printed = 0; 6597163057Sariff 6598182999Smav if (pdevinfo->play < 0) 6599182999Smav return; 6600182999Smav 6601163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6602163057Sariff w = hdac_widget_get(devinfo, i); 6603163057Sariff if (w == NULL || w->enable == 0) 6604163057Sariff continue; 6605182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6606163057Sariff continue; 6607182999Smav if (w->bindas != sc->chans[pdevinfo->play].as) 6608182999Smav continue; 6609163057Sariff if (printed == 0) { 6610163057Sariff printed = 1; 6611182999Smav device_printf(pdevinfo->dev, "\n"); 6612182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6613163057Sariff } 6614182999Smav device_printf(pdevinfo->dev, "\n"); 6615182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6616163057Sariff } 6617162922Sariff} 6618162922Sariff 6619162922Sariffstatic void 6620182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 6621162922Sariff{ 6622182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6623162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6624182999Smav struct hdac_widget *w; 6625182999Smav int i; 6626162922Sariff int printed = 0; 6627162922Sariff 6628182999Smav if (pdevinfo->rec < 0) 6629182999Smav return; 6630182999Smav 6631162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6632162922Sariff w = hdac_widget_get(devinfo, i); 6633162922Sariff if (w == NULL || w->enable == 0) 6634162922Sariff continue; 6635182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 6636162922Sariff continue; 6637182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 6638182999Smav continue; 6639162922Sariff if (printed == 0) { 6640162922Sariff printed = 1; 6641182999Smav device_printf(pdevinfo->dev, "\n"); 6642182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6643162922Sariff } 6644182999Smav device_printf(pdevinfo->dev, "\n"); 6645182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6646182999Smav } 6647182999Smav} 6648182999Smav 6649182999Smavstatic void 6650182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 6651182999Smav{ 6652182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6653182999Smav struct hdac_widget *w; 6654182999Smav int i; 6655182999Smav int printed = 0; 6656182999Smav 6657182999Smav if (pdevinfo->index != 0) 6658182999Smav return; 6659182999Smav 6660182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6661182999Smav w = hdac_widget_get(devinfo, i); 6662182999Smav if (w == NULL || w->enable == 0) 6663182999Smav continue; 6664182999Smav if ((w->pflags & HDA_ADC_MONITOR) == 0) 6665182999Smav continue; 6666182999Smav if (printed == 0) { 6667182999Smav printed = 1; 6668182999Smav device_printf(pdevinfo->dev, "\n"); 6669182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 6670162922Sariff } 6671182999Smav device_printf(pdevinfo->dev, "\n"); 6672182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6673162922Sariff } 6674162922Sariff} 6675162922Sariff 6676162922Sariffstatic void 6677182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 6678162922Sariff{ 6679182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 6680162922Sariff nid_t *nids; 6681182999Smav int i; 6682162922Sariff 6683182999Smav if (pdevinfo->play >= 0) { 6684182999Smav i = pdevinfo->play; 6685182999Smav device_printf(pdevinfo->dev, "\n"); 6686182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6687182999Smav device_printf(pdevinfo->dev, "\n"); 6688182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 6689182999Smav sc->chans[i].supp_pcm_size_rate); 6690182999Smav device_printf(pdevinfo->dev, " DAC:"); 6691182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 6692162922Sariff printf(" %d", *nids); 6693162922Sariff printf("\n"); 6694162922Sariff } 6695182999Smav if (pdevinfo->rec >= 0) { 6696182999Smav i = pdevinfo->rec; 6697182999Smav device_printf(pdevinfo->dev, "\n"); 6698182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6699182999Smav device_printf(pdevinfo->dev, "\n"); 6700182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 6701182999Smav sc->chans[i].supp_pcm_size_rate); 6702182999Smav device_printf(pdevinfo->dev, " ADC:"); 6703182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 6704162922Sariff printf(" %d", *nids); 6705162922Sariff printf("\n"); 6706162922Sariff } 6707162922Sariff} 6708162922Sariff 6709162922Sariffstatic void 6710163057Sariffhdac_release_resources(struct hdac_softc *sc) 6711163057Sariff{ 6712182999Smav int i, j; 6713163057Sariff 6714163057Sariff if (sc == NULL) 6715163057Sariff return; 6716163057Sariff 6717163057Sariff hdac_lock(sc); 6718169277Sariff sc->polling = 0; 6719169277Sariff sc->poll_ival = 0; 6720170721Sariff callout_stop(&sc->poll_hda); 6721169277Sariff callout_stop(&sc->poll_hdac); 6722169277Sariff callout_stop(&sc->poll_jack); 6723182999Smav hdac_reset(sc, 0); 6724163057Sariff hdac_unlock(sc); 6725171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 6726170721Sariff callout_drain(&sc->poll_hda); 6727169277Sariff callout_drain(&sc->poll_hdac); 6728169277Sariff callout_drain(&sc->poll_jack); 6729163057Sariff 6730169277Sariff hdac_irq_free(sc); 6731169277Sariff 6732182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 6733182999Smav if (sc->codecs[i] == NULL) 6734163057Sariff continue; 6735182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 6736182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 6737182999Smav if (sc->codecs[i]->fgs[j].node_type == 6738182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 6739182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 6740182999Smav M_HDAC); 6741182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 6742182999Smav M_HDAC); 6743182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 6744182999Smav M_HDAC); 6745182999Smav } 6746182999Smav } 6747182999Smav free(sc->codecs[i]->fgs, M_HDAC); 6748182999Smav free(sc->codecs[i], M_HDAC); 6749163057Sariff sc->codecs[i] = NULL; 6750163057Sariff } 6751163057Sariff 6752169277Sariff hdac_dma_free(sc, &sc->pos_dma); 6753169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 6754169277Sariff hdac_dma_free(sc, &sc->corb_dma); 6755182999Smav for (i = 0; i < sc->num_chans; i++) { 6756182999Smav if (sc->chans[i].blkcnt > 0) 6757182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 6758182999Smav } 6759182999Smav free(sc->chans, M_HDAC); 6760167702Sariff if (sc->chan_dmat != NULL) { 6761167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 6762167702Sariff sc->chan_dmat = NULL; 6763167702Sariff } 6764163057Sariff hdac_mem_free(sc); 6765169277Sariff snd_mtxfree(sc->lock); 6766163057Sariff} 6767163057Sariff 6768163057Sariff/* This function surely going to make its way into upper level someday. */ 6769163057Sariffstatic void 6770163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 6771163057Sariff{ 6772163057Sariff const char *res = NULL; 6773163057Sariff int i = 0, j, k, len, inv; 6774163057Sariff 6775163057Sariff if (on != NULL) 6776163057Sariff *on = 0; 6777163057Sariff if (off != NULL) 6778163057Sariff *off = 0; 6779163057Sariff if (sc == NULL) 6780163057Sariff return; 6781163057Sariff if (resource_string_value(device_get_name(sc->dev), 6782163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 6783163057Sariff return; 6784163057Sariff if (!(res != NULL && strlen(res) > 0)) 6785163057Sariff return; 6786163057Sariff HDA_BOOTVERBOSE( 6787182999Smav device_printf(sc->dev, "HDA Config:"); 6788163057Sariff ); 6789163057Sariff for (;;) { 6790163057Sariff while (res[i] != '\0' && 6791163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 6792163057Sariff i++; 6793163057Sariff if (res[i] == '\0') { 6794163057Sariff HDA_BOOTVERBOSE( 6795163057Sariff printf("\n"); 6796163057Sariff ); 6797163057Sariff return; 6798163057Sariff } 6799163057Sariff j = i; 6800163057Sariff while (res[j] != '\0' && 6801163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 6802163057Sariff j++; 6803163057Sariff len = j - i; 6804163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 6805163057Sariff inv = 2; 6806163057Sariff else 6807163057Sariff inv = 0; 6808163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 6809163057Sariff if (strncmp(res + i + inv, 6810163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 6811163057Sariff continue; 6812163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 6813163057Sariff break; 6814163057Sariff HDA_BOOTVERBOSE( 6815163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 6816163057Sariff hdac_quirks_tab[k].key); 6817163057Sariff ); 6818163057Sariff if (inv == 0 && on != NULL) 6819163057Sariff *on |= hdac_quirks_tab[k].value; 6820163057Sariff else if (inv != 0 && off != NULL) 6821163057Sariff *off |= hdac_quirks_tab[k].value; 6822163057Sariff break; 6823163057Sariff } 6824163057Sariff i = j; 6825163057Sariff } 6826163057Sariff} 6827163057Sariff 6828164614Sariff#ifdef SND_DYNSYSCTL 6829164614Sariffstatic int 6830164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 6831164614Sariff{ 6832164614Sariff struct hdac_softc *sc; 6833164614Sariff device_t dev; 6834164614Sariff uint32_t ctl; 6835164614Sariff int err, val; 6836164614Sariff 6837164614Sariff dev = oidp->oid_arg1; 6838182999Smav sc = device_get_softc(dev); 6839182999Smav if (sc == NULL) 6840164614Sariff return (EINVAL); 6841164614Sariff hdac_lock(sc); 6842164614Sariff val = sc->polling; 6843164614Sariff hdac_unlock(sc); 6844170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6845164614Sariff 6846169277Sariff if (err != 0 || req->newptr == NULL) 6847164614Sariff return (err); 6848164614Sariff if (val < 0 || val > 1) 6849164614Sariff return (EINVAL); 6850164614Sariff 6851164614Sariff hdac_lock(sc); 6852164614Sariff if (val != sc->polling) { 6853182999Smav if (val == 0) { 6854182999Smav callout_stop(&sc->poll_hda); 6855164614Sariff callout_stop(&sc->poll_hdac); 6856169277Sariff hdac_unlock(sc); 6857182999Smav callout_drain(&sc->poll_hda); 6858169277Sariff callout_drain(&sc->poll_hdac); 6859169277Sariff hdac_lock(sc); 6860164614Sariff sc->polling = 0; 6861182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 6862182999Smav ctl |= HDAC_INTCTL_GIE; 6863182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 6864164614Sariff } else { 6865182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 6866182999Smav ctl &= ~HDAC_INTCTL_GIE; 6867182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 6868171141Sariff hdac_unlock(sc); 6869171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 6870171141Sariff hdac_lock(sc); 6871164614Sariff sc->polling = 1; 6872182999Smav hdac_poll_reinit(sc); 6873182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 6874164614Sariff } 6875164614Sariff } 6876164614Sariff hdac_unlock(sc); 6877164614Sariff 6878164614Sariff return (err); 6879164614Sariff} 6880169277Sariff 6881169277Sariffstatic int 6882169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 6883169277Sariff{ 6884169277Sariff struct hdac_softc *sc; 6885169277Sariff device_t dev; 6886169277Sariff int err, val; 6887169277Sariff 6888169277Sariff dev = oidp->oid_arg1; 6889182999Smav sc = device_get_softc(dev); 6890182999Smav if (sc == NULL) 6891169277Sariff return (EINVAL); 6892169277Sariff hdac_lock(sc); 6893169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 6894169277Sariff hdac_unlock(sc); 6895170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6896169277Sariff 6897169277Sariff if (err != 0 || req->newptr == NULL) 6898169277Sariff return (err); 6899169277Sariff 6900169277Sariff if (val < 1) 6901169277Sariff val = 1; 6902169277Sariff if (val > 5000) 6903169277Sariff val = 5000; 6904169277Sariff val = ((uint64_t)val * hz) / 1000; 6905169277Sariff if (val < 1) 6906169277Sariff val = 1; 6907169277Sariff if (val > (hz * 5)) 6908169277Sariff val = hz * 5; 6909169277Sariff 6910169277Sariff hdac_lock(sc); 6911169277Sariff sc->poll_ival = val; 6912169277Sariff hdac_unlock(sc); 6913169277Sariff 6914169277Sariff return (err); 6915169277Sariff} 6916169277Sariff 6917169277Sariffstatic int 6918171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 6919169277Sariff{ 6920169277Sariff struct hdac_softc *sc; 6921182999Smav struct hdac_codec *codec; 6922169277Sariff struct hdac_devinfo *devinfo; 6923169277Sariff struct hdac_widget *w; 6924169277Sariff device_t dev; 6925182999Smav uint32_t res, pincap, delay; 6926182999Smav int codec_index, fg_index; 6927169277Sariff int i, err, val; 6928169277Sariff nid_t cad; 6929169277Sariff 6930169277Sariff dev = oidp->oid_arg1; 6931182999Smav sc = device_get_softc(dev); 6932182999Smav if (sc == NULL) 6933169277Sariff return (EINVAL); 6934169277Sariff val = 0; 6935170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6936169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 6937169277Sariff return (err); 6938182999Smav 6939182999Smav /* XXX: Temporary. For debugging. */ 6940182999Smav if (val == 100) { 6941182999Smav hdac_suspend(dev); 6942182999Smav return (0); 6943182999Smav } else if (val == 101) { 6944182999Smav hdac_resume(dev); 6945182999Smav return (0); 6946182999Smav } 6947182999Smav 6948169277Sariff hdac_lock(sc); 6949182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 6950182999Smav codec = sc->codecs[codec_index]; 6951182999Smav if (codec == NULL) 6952169277Sariff continue; 6953182999Smav cad = codec->cad; 6954182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 6955182999Smav devinfo = &codec->fgs[fg_index]; 6956182999Smav if (devinfo->node_type != 6957182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 6958182999Smav continue; 6959182999Smav 6960182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 6961182999Smav codec_index, devinfo->nid); 6962182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6963182999Smav w = hdac_widget_get(devinfo, i); 6964182999Smav if (w == NULL || w->type != 6965182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6966182999Smav continue; 6967182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6968182999Smav pincap = w->wclass.pin.cap; 6969182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 6970182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 6971182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 6972182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 6973182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 6974182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 6975182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 6976182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 6977182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 6978182999Smav delay = 0; 6979182999Smav hdac_command(sc, 6980182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 6981182999Smav do { 6982182999Smav res = hdac_command(sc, 6983182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 6984182999Smav if (res != 0x7fffffff && res != 0xffffffff) 6985182999Smav break; 6986182999Smav DELAY(10); 6987182999Smav } while (++delay < 10000); 6988182999Smav } else { 6989182999Smav delay = 0; 6990182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 6991182999Smav w->nid), cad); 6992182999Smav } 6993182999Smav printf(" Sense: 0x%08x", res); 6994182999Smav if (delay > 0) 6995182999Smav printf(" delay %dus", delay * 10); 6996182999Smav } 6997182999Smav printf("\n"); 6998182999Smav } 6999182999Smav device_printf(dev, 7000182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7001182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7002182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7003182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7004182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7005182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7006182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7007182999Smav device_printf(dev, " GPI:"); 7008171141Sariff res = hdac_command(sc, 7009182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7010182999Smav printf(" data=0x%08x", res); 7011182999Smav res = hdac_command(sc, 7012182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7013182999Smav cad); 7014182999Smav printf(" wake=0x%08x", res); 7015182999Smav res = hdac_command(sc, 7016182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7017182999Smav cad); 7018182999Smav printf(" unsol=0x%08x", res); 7019182999Smav res = hdac_command(sc, 7020182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7021182999Smav printf(" sticky=0x%08x\n", res); 7022182999Smav } 7023182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7024182999Smav device_printf(dev, " GPO:"); 7025182999Smav res = hdac_command(sc, 7026182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7027182999Smav printf(" data=0x%08x\n", res); 7028182999Smav } 7029182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7030182999Smav device_printf(dev, "GPIO:"); 7031182999Smav res = hdac_command(sc, 7032182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7033182999Smav printf(" data=0x%08x", res); 7034182999Smav res = hdac_command(sc, 7035182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7036182999Smav printf(" enable=0x%08x", res); 7037182999Smav res = hdac_command(sc, 7038182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7039182999Smav printf(" direction=0x%08x\n", res); 7040182999Smav res = hdac_command(sc, 7041182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7042182999Smav device_printf(dev, " wake=0x%08x", res); 7043182999Smav res = hdac_command(sc, 7044182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7045182999Smav cad); 7046182999Smav printf(" unsol=0x%08x", res); 7047182999Smav res = hdac_command(sc, 7048182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7049182999Smav printf(" sticky=0x%08x\n", res); 7050182999Smav } 7051171141Sariff } 7052169277Sariff } 7053169277Sariff hdac_unlock(sc); 7054169277Sariff return (0); 7055169277Sariff} 7056164614Sariff#endif 7057164614Sariff 7058163057Sariffstatic void 7059162922Sariffhdac_attach2(void *arg) 7060162922Sariff{ 7061182999Smav struct hdac_codec *codec; 7062162922Sariff struct hdac_softc *sc; 7063162922Sariff struct hdac_audio_ctl *ctl; 7064163057Sariff uint32_t quirks_on, quirks_off; 7065182999Smav int codec_index, fg_index; 7066182999Smav int i, pdev, rdev, dmaalloc = 0; 7067182999Smav struct hdac_devinfo *devinfo; 7068162922Sariff 7069162922Sariff sc = (struct hdac_softc *)arg; 7070162922Sariff 7071163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7072162922Sariff 7073183097Smav HDA_BOOTHVERBOSE( 7074182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7075163057Sariff quirks_on, quirks_off); 7076163057Sariff ); 7077163057Sariff 7078162922Sariff hdac_lock(sc); 7079162922Sariff 7080162922Sariff /* Remove ourselves from the config hooks */ 7081162922Sariff if (sc->intrhook.ich_func != NULL) { 7082162922Sariff config_intrhook_disestablish(&sc->intrhook); 7083162922Sariff sc->intrhook.ich_func = NULL; 7084162922Sariff } 7085162922Sariff 7086162922Sariff /* Start the corb and rirb engines */ 7087183097Smav HDA_BOOTHVERBOSE( 7088182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7089162922Sariff ); 7090162922Sariff hdac_corb_start(sc); 7091183097Smav HDA_BOOTHVERBOSE( 7092182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7093162922Sariff ); 7094162922Sariff hdac_rirb_start(sc); 7095162922Sariff 7096183097Smav HDA_BOOTHVERBOSE( 7097162922Sariff device_printf(sc->dev, 7098182999Smav "Enabling controller interrupt...\n"); 7099162922Sariff ); 7100182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7101182999Smav HDAC_GCTL_UNSOL); 7102182999Smav if (sc->polling == 0) { 7103164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7104164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7105182999Smav } else { 7106182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7107182999Smav } 7108162922Sariff DELAY(1000); 7109162922Sariff 7110183097Smav HDA_BOOTHVERBOSE( 7111172811Sariff device_printf(sc->dev, 7112182999Smav "Scanning HDA codecs ...\n"); 7113162922Sariff ); 7114182999Smav hdac_scan_codecs(sc); 7115182999Smav 7116182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7117182999Smav codec = sc->codecs[codec_index]; 7118182999Smav if (codec == NULL) 7119182999Smav continue; 7120182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7121182999Smav devinfo = &codec->fgs[fg_index]; 7122183019Smav HDA_BOOTVERBOSE( 7123183019Smav device_printf(sc->dev, "\n"); 7124183097Smav device_printf(sc->dev, 7125183097Smav "Processing %s FG cad=%d nid=%d...\n", 7126183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7127183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7128183097Smav "unknown", 7129183097Smav devinfo->codec->cad, devinfo->nid); 7130183019Smav ); 7131182999Smav if (devinfo->node_type != 7132182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7133183097Smav HDA_BOOTHVERBOSE( 7134182999Smav device_printf(sc->dev, 7135183097Smav "Powering down...\n"); 7136182999Smav ); 7137182999Smav hdac_command(sc, 7138182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7139182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7140182999Smav codec->cad); 7141182999Smav continue; 7142182999Smav } 7143162922Sariff 7144183097Smav HDA_BOOTHVERBOSE( 7145183097Smav device_printf(sc->dev, "Powering up...\n"); 7146182999Smav ); 7147182999Smav hdac_powerup(devinfo); 7148183097Smav HDA_BOOTHVERBOSE( 7149182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7150182999Smav ); 7151182999Smav hdac_audio_parse(devinfo); 7152183097Smav HDA_BOOTHVERBOSE( 7153182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7154182999Smav ); 7155182999Smav hdac_audio_ctl_parse(devinfo); 7156183097Smav HDA_BOOTHVERBOSE( 7157182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7158182999Smav ); 7159182999Smav hdac_vendor_patch_parse(devinfo); 7160182999Smav devinfo->function.audio.quirks |= quirks_on; 7161182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7162162922Sariff 7163183097Smav HDA_BOOTHVERBOSE( 7164182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7165182999Smav ); 7166182999Smav hdac_audio_disable_nonaudio(devinfo); 7167183097Smav HDA_BOOTHVERBOSE( 7168182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7169182999Smav ); 7170182999Smav hdac_audio_disable_useless(devinfo); 7171182999Smav HDA_BOOTVERBOSE( 7172182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7173182999Smav hdac_dump_pin_configs(devinfo); 7174183097Smav ); 7175183097Smav HDA_BOOTHVERBOSE( 7176182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7177182999Smav ); 7178182999Smav hdac_audio_as_parse(devinfo); 7179183097Smav HDA_BOOTHVERBOSE( 7180182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7181182999Smav ); 7182182999Smav hdac_audio_build_tree(devinfo); 7183183097Smav HDA_BOOTHVERBOSE( 7184182999Smav device_printf(sc->dev, "Disabling unassociated " 7185182999Smav "widgets...\n"); 7186182999Smav ); 7187182999Smav hdac_audio_disable_unas(devinfo); 7188183097Smav HDA_BOOTHVERBOSE( 7189182999Smav device_printf(sc->dev, "Disabling nonselected " 7190182999Smav "inputs...\n"); 7191182999Smav ); 7192182999Smav hdac_audio_disable_notselected(devinfo); 7193183097Smav HDA_BOOTHVERBOSE( 7194182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7195182999Smav ); 7196182999Smav hdac_audio_disable_useless(devinfo); 7197183097Smav HDA_BOOTHVERBOSE( 7198182999Smav device_printf(sc->dev, "Disabling " 7199182999Smav "crossassociatement connections...\n"); 7200182999Smav ); 7201182999Smav hdac_audio_disable_crossas(devinfo); 7202183097Smav HDA_BOOTHVERBOSE( 7203182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7204182999Smav ); 7205182999Smav hdac_audio_disable_useless(devinfo); 7206183097Smav HDA_BOOTHVERBOSE( 7207182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7208182999Smav ); 7209182999Smav hdac_audio_bind_as(devinfo); 7210183097Smav HDA_BOOTHVERBOSE( 7211182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7212182999Smav ); 7213182999Smav hdac_audio_assign_names(devinfo); 7214183097Smav HDA_BOOTHVERBOSE( 7215182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7216182999Smav ); 7217182999Smav hdac_audio_assign_mixers(devinfo); 7218183097Smav HDA_BOOTHVERBOSE( 7219182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7220182999Smav ); 7221182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7222183097Smav HDA_BOOTHVERBOSE( 7223182999Smav device_printf(sc->dev, "AFG commit...\n"); 7224182999Smav ); 7225182999Smav hdac_audio_commit(devinfo); 7226183097Smav HDA_BOOTHVERBOSE( 7227182999Smav device_printf(sc->dev, "Ctls commit...\n"); 7228182999Smav ); 7229182999Smav hdac_audio_ctl_commit(devinfo); 7230183097Smav HDA_BOOTHVERBOSE( 7231182999Smav device_printf(sc->dev, "HP switch init...\n"); 7232182999Smav ); 7233182999Smav hdac_hp_switch_init(devinfo); 7234182999Smav 7235182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7236182999Smav dmaalloc == 0) { 7237182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7238182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7239182999Smav HDA_BOOTVERBOSE( 7240182999Smav device_printf(sc->dev, "Failed to " 7241182999Smav "allocate DMA pos buffer " 7242182999Smav "(non-fatal)\n"); 7243182999Smav ); 7244182999Smav } else 7245182999Smav dmaalloc = 1; 7246182999Smav } 7247182999Smav 7248182999Smav i = devinfo->function.audio.playcnt; 7249182999Smav if (devinfo->function.audio.reccnt > i) 7250182999Smav i = devinfo->function.audio.reccnt; 7251182999Smav devinfo->function.audio.devs = 7252182999Smav (struct hdac_pcm_devinfo *)malloc( 7253182999Smav sizeof(struct hdac_pcm_devinfo) * i, 7254182999Smav M_HDAC, M_ZERO | M_NOWAIT); 7255182999Smav if (devinfo->function.audio.devs == NULL) { 7256182999Smav device_printf(sc->dev, 7257182999Smav "Unable to allocate memory for devices\n"); 7258182999Smav continue; 7259182999Smav } 7260182999Smav devinfo->function.audio.num_devs = i; 7261182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7262182999Smav devinfo->function.audio.devs[i].index = i; 7263182999Smav devinfo->function.audio.devs[i].devinfo = devinfo; 7264182999Smav devinfo->function.audio.devs[i].play = -1; 7265182999Smav devinfo->function.audio.devs[i].rec = -1; 7266182999Smav } 7267182999Smav pdev = 0; 7268182999Smav rdev = 0; 7269182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 7270182999Smav if (devinfo->function.audio.as[i].enable == 0) 7271182999Smav continue; 7272182999Smav if (devinfo->function.audio.as[i].dir == 7273182999Smav HDA_CTL_IN) { 7274182999Smav devinfo->function.audio.devs[rdev].rec 7275182999Smav = devinfo->function.audio.as[i].chan; 7276182999Smav sc->chans[devinfo->function.audio.as[i].chan].pdevinfo = 7277182999Smav &devinfo->function.audio.devs[rdev]; 7278182999Smav rdev++; 7279182999Smav } else { 7280182999Smav devinfo->function.audio.devs[pdev].play 7281182999Smav = devinfo->function.audio.as[i].chan; 7282182999Smav sc->chans[devinfo->function.audio.as[i].chan].pdevinfo = 7283182999Smav &devinfo->function.audio.devs[pdev]; 7284182999Smav pdev++; 7285182999Smav } 7286182999Smav } 7287182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7288182999Smav struct hdac_pcm_devinfo *pdevinfo = 7289182999Smav &devinfo->function.audio.devs[i]; 7290182999Smav pdevinfo->dev = 7291182999Smav device_add_child(sc->dev, "pcm", -1); 7292182999Smav device_set_ivars(pdevinfo->dev, 7293182999Smav (void *)pdevinfo); 7294182999Smav } 7295182999Smav 7296182999Smav HDA_BOOTVERBOSE( 7297182999Smav if (devinfo->function.audio.quirks != 0) { 7298183097Smav device_printf(sc->dev, "FG config/quirks:"); 7299182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7300182999Smav if ((devinfo->function.audio.quirks & 7301182999Smav hdac_quirks_tab[i].value) == 7302182999Smav hdac_quirks_tab[i].value) 7303182999Smav printf(" %s", hdac_quirks_tab[i].key); 7304182999Smav } 7305182999Smav printf("\n"); 7306182999Smav } 7307182999Smav 7308182999Smav device_printf(sc->dev, "\n"); 7309182999Smav device_printf(sc->dev, "+-------------------+\n"); 7310182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7311182999Smav device_printf(sc->dev, "+-------------------+\n"); 7312182999Smav hdac_dump_nodes(devinfo); 7313183097Smav ); 7314182999Smav 7315183097Smav HDA_BOOTHVERBOSE( 7316182999Smav device_printf(sc->dev, "\n"); 7317182999Smav device_printf(sc->dev, "+------------------------+\n"); 7318182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7319182999Smav device_printf(sc->dev, "+------------------------+\n"); 7320182999Smav device_printf(sc->dev, "\n"); 7321182999Smav i = 0; 7322182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7323182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7324182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7325182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7326182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7327182999Smav ctl->index); 7328182999Smav if (ctl->childwidget != NULL) 7329182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7330182999Smav else 7331182999Smav printf(" "); 7332182999Smav printf(" ossmask=0x%08x\n", 7333182999Smav ctl->ossmask); 7334182999Smav device_printf(sc->dev, 7335182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7336182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7337182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7338182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7339182999Smav } 7340182999Smav ); 7341182999Smav } 7342162922Sariff } 7343182999Smav hdac_unlock(sc); 7344162922Sariff 7345163057Sariff HDA_BOOTVERBOSE( 7346182999Smav device_printf(sc->dev, "\n"); 7347162922Sariff ); 7348182999Smav 7349182999Smav bus_generic_attach(sc->dev); 7350182999Smav 7351182999Smav#ifdef SND_DYNSYSCTL 7352182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7353182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7354182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7355182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7356182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7357182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7358182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7359182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7360182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7361182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7362182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7363182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7364182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7365182999Smav#endif 7366182999Smav} 7367182999Smav 7368182999Smav/**************************************************************************** 7369182999Smav * int hdac_suspend(device_t) 7370182999Smav * 7371182999Smav * Suspend and power down HDA bus and codecs. 7372182999Smav ****************************************************************************/ 7373182999Smavstatic int 7374182999Smavhdac_suspend(device_t dev) 7375182999Smav{ 7376182999Smav struct hdac_softc *sc; 7377182999Smav struct hdac_codec *codec; 7378182999Smav struct hdac_devinfo *devinfo; 7379182999Smav int codec_index, fg_index, i; 7380182999Smav 7381183097Smav HDA_BOOTHVERBOSE( 7382182999Smav device_printf(dev, "Suspend...\n"); 7383162922Sariff ); 7384182999Smav 7385182999Smav sc = device_get_softc(dev); 7386182999Smav hdac_lock(sc); 7387182999Smav 7388183097Smav HDA_BOOTHVERBOSE( 7389182999Smav device_printf(dev, "Stop streams...\n"); 7390162922Sariff ); 7391182999Smav for (i = 0; i < sc->num_chans; i++) { 7392182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7393182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7394182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7395182999Smav } 7396182999Smav } 7397162922Sariff 7398182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7399182999Smav codec = sc->codecs[codec_index]; 7400182999Smav if (codec == NULL) 7401162922Sariff continue; 7402182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7403182999Smav devinfo = &codec->fgs[fg_index]; 7404183097Smav HDA_BOOTHVERBOSE( 7405182999Smav device_printf(dev, 7406182999Smav "Power down FG" 7407182999Smav " cad=%d nid=%d to the D3 state...\n", 7408182999Smav codec->cad, devinfo->nid); 7409182999Smav ); 7410182999Smav hdac_command(sc, 7411182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7412182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7413182999Smav codec->cad); 7414162922Sariff } 7415162922Sariff } 7416162922Sariff 7417183097Smav HDA_BOOTHVERBOSE( 7418182999Smav device_printf(dev, "Reset controller...\n"); 7419162922Sariff ); 7420182999Smav callout_stop(&sc->poll_hda); 7421182999Smav callout_stop(&sc->poll_hdac); 7422182999Smav callout_stop(&sc->poll_jack); 7423182999Smav hdac_reset(sc, 0); 7424182999Smav hdac_unlock(sc); 7425182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7426182999Smav callout_drain(&sc->poll_hda); 7427182999Smav callout_drain(&sc->poll_hdac); 7428182999Smav callout_drain(&sc->poll_jack); 7429162922Sariff 7430183097Smav HDA_BOOTHVERBOSE( 7431182999Smav device_printf(dev, "Suspend done\n"); 7432162922Sariff ); 7433182999Smav 7434182999Smav return (0); 7435182999Smav} 7436182999Smav 7437182999Smav/**************************************************************************** 7438182999Smav * int hdac_resume(device_t) 7439182999Smav * 7440182999Smav * Powerup and restore HDA bus and codecs state. 7441182999Smav ****************************************************************************/ 7442182999Smavstatic int 7443182999Smavhdac_resume(device_t dev) 7444182999Smav{ 7445182999Smav struct hdac_softc *sc; 7446182999Smav struct hdac_codec *codec; 7447182999Smav struct hdac_devinfo *devinfo; 7448182999Smav int codec_index, fg_index, i; 7449182999Smav 7450183097Smav HDA_BOOTHVERBOSE( 7451182999Smav device_printf(dev, "Resume...\n"); 7452162922Sariff ); 7453162922Sariff 7454182999Smav sc = device_get_softc(dev); 7455182999Smav hdac_lock(sc); 7456182999Smav 7457182999Smav /* Quiesce everything */ 7458183097Smav HDA_BOOTHVERBOSE( 7459182999Smav device_printf(dev, "Reset controller...\n"); 7460162922Sariff ); 7461182999Smav hdac_reset(sc, 1); 7462182999Smav 7463182999Smav /* Initialize the CORB and RIRB */ 7464182999Smav hdac_corb_init(sc); 7465182999Smav hdac_rirb_init(sc); 7466182999Smav 7467182999Smav /* Start the corb and rirb engines */ 7468183097Smav HDA_BOOTHVERBOSE( 7469182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7470162922Sariff ); 7471182999Smav hdac_corb_start(sc); 7472183097Smav HDA_BOOTHVERBOSE( 7473182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7474162922Sariff ); 7475182999Smav hdac_rirb_start(sc); 7476163057Sariff 7477183097Smav HDA_BOOTHVERBOSE( 7478182999Smav device_printf(dev, 7479182999Smav "Enabling controller interrupt...\n"); 7480162922Sariff ); 7481182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7482182999Smav HDAC_GCTL_UNSOL); 7483182999Smav if (sc->polling == 0) { 7484182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7485182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7486182999Smav } else { 7487182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7488182999Smav } 7489182999Smav DELAY(1000); 7490162922Sariff 7491182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7492182999Smav codec = sc->codecs[codec_index]; 7493182999Smav if (codec == NULL) 7494182999Smav continue; 7495182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7496182999Smav devinfo = &codec->fgs[fg_index]; 7497182999Smav if (devinfo->node_type != 7498182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7499183097Smav HDA_BOOTHVERBOSE( 7500182999Smav device_printf(dev, 7501182999Smav "Power down unsupported non-audio FG" 7502182999Smav " cad=%d nid=%d to the D3 state...\n", 7503182999Smav codec->cad, devinfo->nid); 7504182999Smav ); 7505182999Smav hdac_command(sc, 7506182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7507182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7508182999Smav codec->cad); 7509182999Smav continue; 7510182999Smav } 7511162922Sariff 7512183097Smav HDA_BOOTHVERBOSE( 7513182999Smav device_printf(dev, 7514182999Smav "Power up audio FG cad=%d nid=%d...\n", 7515182999Smav devinfo->codec->cad, devinfo->nid); 7516182999Smav ); 7517182999Smav hdac_powerup(devinfo); 7518183097Smav HDA_BOOTHVERBOSE( 7519182999Smav device_printf(dev, "AFG commit...\n"); 7520182999Smav ); 7521182999Smav hdac_audio_commit(devinfo); 7522183097Smav HDA_BOOTHVERBOSE( 7523182999Smav device_printf(dev, "Ctls commit...\n"); 7524182999Smav ); 7525182999Smav hdac_audio_ctl_commit(devinfo); 7526183097Smav HDA_BOOTHVERBOSE( 7527182999Smav device_printf(dev, "HP switch init...\n"); 7528182999Smav ); 7529182999Smav hdac_hp_switch_init(devinfo); 7530182999Smav 7531182999Smav hdac_unlock(sc); 7532182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7533182999Smav struct hdac_pcm_devinfo *pdevinfo = 7534182999Smav &devinfo->function.audio.devs[i]; 7535183097Smav HDA_BOOTHVERBOSE( 7536182999Smav device_printf(pdevinfo->dev, 7537182999Smav "OSS mixer reinitialization...\n"); 7538182999Smav ); 7539182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 7540182999Smav device_printf(pdevinfo->dev, 7541182999Smav "unable to reinitialize the mixer\n"); 7542182999Smav } 7543182999Smav hdac_lock(sc); 7544182999Smav } 7545169277Sariff } 7546169277Sariff 7547183097Smav HDA_BOOTHVERBOSE( 7548182999Smav device_printf(dev, "Start streams...\n"); 7549163057Sariff ); 7550182999Smav for (i = 0; i < sc->num_chans; i++) { 7551182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 7552182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 7553182999Smav hdac_channel_start(sc, &sc->chans[i]); 7554182999Smav } 7555182999Smav } 7556162922Sariff 7557182999Smav hdac_unlock(sc); 7558182999Smav 7559183097Smav HDA_BOOTHVERBOSE( 7560182999Smav device_printf(dev, "Resume done\n"); 7561162922Sariff ); 7562164614Sariff 7563182999Smav return (0); 7564162922Sariff} 7565162922Sariff/**************************************************************************** 7566162922Sariff * int hdac_detach(device_t) 7567162922Sariff * 7568162922Sariff * Detach and free up resources utilized by the hdac device. 7569162922Sariff ****************************************************************************/ 7570162922Sariffstatic int 7571162922Sariffhdac_detach(device_t dev) 7572162922Sariff{ 7573182999Smav struct hdac_softc *sc; 7574185177Smav device_t *devlist; 7575185177Smav int i, devcount, error; 7576162922Sariff 7577185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 7578185177Smav return (error); 7579185177Smav for (i = 0; i < devcount; i++) { 7580185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 7581185178Smav free(devlist, M_TEMP); 7582185178Smav return (error); 7583185178Smav } 7584185177Smav } 7585185177Smav free(devlist, M_TEMP); 7586185177Smav 7587182999Smav sc = device_get_softc(dev); 7588163057Sariff hdac_release_resources(sc); 7589162922Sariff 7590162922Sariff return (0); 7591162922Sariff} 7592162922Sariff 7593184095Smavstatic int 7594184095Smavhdac_print_child(device_t dev, device_t child) 7595184095Smav{ 7596184095Smav struct hdac_pcm_devinfo *pdevinfo = 7597184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 7598184095Smav int retval; 7599184095Smav 7600184095Smav retval = bus_print_child_header(dev, child); 7601184095Smav retval += printf(" at cad %d nid %d", 7602184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 7603184095Smav retval += bus_print_child_footer(dev, child); 7604184095Smav 7605184095Smav return (retval); 7606184095Smav} 7607184095Smav 7608162922Sariffstatic device_method_t hdac_methods[] = { 7609162922Sariff /* device interface */ 7610162922Sariff DEVMETHOD(device_probe, hdac_probe), 7611162922Sariff DEVMETHOD(device_attach, hdac_attach), 7612162922Sariff DEVMETHOD(device_detach, hdac_detach), 7613182999Smav DEVMETHOD(device_suspend, hdac_suspend), 7614182999Smav DEVMETHOD(device_resume, hdac_resume), 7615184095Smav /* Bus interface */ 7616184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 7617162922Sariff { 0, 0 } 7618162922Sariff}; 7619162922Sariff 7620162922Sariffstatic driver_t hdac_driver = { 7621182999Smav "hdac", 7622162922Sariff hdac_methods, 7623182999Smav sizeof(struct hdac_softc), 7624162922Sariff}; 7625162922Sariff 7626182999Smavstatic devclass_t hdac_devclass; 7627182999Smav 7628182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 7629162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 7630162922SariffMODULE_VERSION(snd_hda, 1); 7631182999Smav 7632182999Smavstatic int 7633182999Smavhdac_pcm_probe(device_t dev) 7634182999Smav{ 7635182999Smav struct hdac_pcm_devinfo *pdevinfo = 7636182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7637182999Smav char buf[128]; 7638182999Smav 7639184095Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d", 7640182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 7641182999Smav pdevinfo->index); 7642182999Smav device_set_desc_copy(dev, buf); 7643182999Smav return (0); 7644182999Smav} 7645182999Smav 7646182999Smavstatic int 7647182999Smavhdac_pcm_attach(device_t dev) 7648182999Smav{ 7649182999Smav struct hdac_pcm_devinfo *pdevinfo = 7650182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7651182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7652182999Smav char status[SND_STATUSLEN]; 7653182999Smav int i; 7654182999Smav 7655182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 7656182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 7657182999Smav 7658182999Smav HDA_BOOTVERBOSE( 7659182999Smav device_printf(dev, "+--------------------------------------+\n"); 7660182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 7661182999Smav device_printf(dev, "+--------------------------------------+\n"); 7662182999Smav hdac_dump_pcmchannels(pdevinfo); 7663182999Smav device_printf(dev, "\n"); 7664182999Smav device_printf(dev, "+--------------------------------+\n"); 7665182999Smav device_printf(dev, "| DUMPING Playback/Record Pathes |\n"); 7666182999Smav device_printf(dev, "+--------------------------------+\n"); 7667182999Smav hdac_dump_dac(pdevinfo); 7668182999Smav hdac_dump_adc(pdevinfo); 7669182999Smav hdac_dump_mix(pdevinfo); 7670182999Smav device_printf(dev, "\n"); 7671182999Smav device_printf(dev, "+-------------------------+\n"); 7672182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 7673182999Smav device_printf(dev, "+-------------------------+\n"); 7674182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 7675182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 7676182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 7677182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 7678182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 7679182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 7680182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 7681182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 7682182999Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 7683182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 7684182999Smav device_printf(dev, "\n"); 7685182999Smav ); 7686182999Smav 7687182999Smav if (resource_int_value(device_get_name(dev), 7688182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 7689182999Smav i &= HDA_BLK_ALIGN; 7690182999Smav if (i < HDA_BLK_MIN) 7691182999Smav i = HDA_BLK_MIN; 7692182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 7693182999Smav i = 0; 7694182999Smav while (pdevinfo->chan_blkcnt >> i) 7695182999Smav i++; 7696182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 7697182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 7698182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 7699182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 7700182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 7701182999Smav } else 7702182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 7703182999Smav 7704182999Smav /* 7705182999Smav * We don't register interrupt handler with snd_setup_intr 7706182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 7707182999Smav */ 7708182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 7709182999Smav 7710183097Smav HDA_BOOTHVERBOSE( 7711182999Smav device_printf(dev, "OSS mixer initialization...\n"); 7712182999Smav ); 7713182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 7714182999Smav device_printf(dev, "Can't register mixer\n"); 7715182999Smav 7716183097Smav HDA_BOOTHVERBOSE( 7717182999Smav device_printf(dev, "Registering PCM channels...\n"); 7718182999Smav ); 7719182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 7720182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 7721182999Smav device_printf(dev, "Can't register PCM\n"); 7722182999Smav 7723182999Smav pdevinfo->registered++; 7724182999Smav 7725182999Smav if (pdevinfo->play >= 0) 7726182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 7727182999Smav if (pdevinfo->rec >= 0) 7728182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 7729182999Smav 7730184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 7731184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 7732184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 7733182999Smav pcm_setstatus(dev, status); 7734182999Smav 7735182999Smav return (0); 7736182999Smav} 7737182999Smav 7738182999Smavstatic int 7739182999Smavhdac_pcm_detach(device_t dev) 7740182999Smav{ 7741182999Smav struct hdac_pcm_devinfo *pdevinfo = 7742182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7743182999Smav int err; 7744182999Smav 7745182999Smav if (pdevinfo->registered > 0) { 7746182999Smav err = pcm_unregister(dev); 7747182999Smav if (err != 0) 7748182999Smav return (err); 7749182999Smav } 7750182999Smav 7751182999Smav return (0); 7752182999Smav} 7753182999Smav 7754182999Smavstatic device_method_t hdac_pcm_methods[] = { 7755182999Smav /* device interface */ 7756182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 7757182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 7758182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 7759182999Smav { 0, 0 } 7760182999Smav}; 7761182999Smav 7762182999Smavstatic driver_t hdac_pcm_driver = { 7763182999Smav "pcm", 7764182999Smav hdac_pcm_methods, 7765182999Smav PCM_SOFTC_SIZE, 7766182999Smav}; 7767182999Smav 7768182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 7769182999Smav 7770