hdac.c revision 184254
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 86184231Smav#define HDA_DRV_TEST_REV "20081024_0114" 87162922Sariff 88162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 184254 2008-10-25 08:31:20Z 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) 207178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 208162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 209169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 210169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 211162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 212162922Sariff 213162922Sariff/* Clevo */ 214162922Sariff#define CLEVO_VENDORID 0x1558 215162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 216162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 217162922Sariff 218162922Sariff/* Acer */ 219162922Sariff#define ACER_VENDORID 0x1025 220165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 221173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 222174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 223182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 224169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 225182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 226162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 227162922Sariff 228162965Sariff/* Asus */ 229162965Sariff#define ASUS_VENDORID 0x1043 230178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 231163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 232178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 233165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 234178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 235178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 236167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 237169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 238178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 239178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 240178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 241170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 242178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 243169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 244171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 245162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 246162922Sariff 247163257Sariff/* IBM / Lenovo */ 248163257Sariff#define IBM_VENDORID 0x1014 249163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 250163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 251162965Sariff 252164614Sariff/* Lenovo */ 253164657Sariff#define LENOVO_VENDORID 0x17aa 254164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 255182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 256172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 257164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 258163257Sariff 259164657Sariff/* Samsung */ 260164657Sariff#define SAMSUNG_VENDORID 0x144d 261164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 262164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 263164614Sariff 264164750Sariff/* Medion ? */ 265164750Sariff#define MEDION_VENDORID 0x161f 266164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 267164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 268164750Sariff 269173817Sariff/* Apple Computer Inc. */ 270173817Sariff#define APPLE_VENDORID 0x106b 271173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 272173817Sariff 273182999Smav/* Sony */ 274182999Smav#define SONY_VENDORID 0x104d 275182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 276182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 277182999Smav 278164828Sariff/* 279164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 280164828Sariff * instead of their own, which is beyond my comprehension 281164828Sariff * (see HDA_CODEC_STAC9221 below). 282164828Sariff */ 283164828Sariff#define APPLE_INTEL_MAC 0x76808384 284164828Sariff 285165281Sariff/* LG Electronics */ 286165281Sariff#define LG_VENDORID 0x1854 287165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 288165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 289165281Sariff 290165351Sariff/* Fujitsu Siemens */ 291165351Sariff#define FS_VENDORID 0x1734 292165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 293172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 294165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 295165351Sariff 296172811Sariff/* Fujitsu Limited */ 297172811Sariff#define FL_VENDORID 0x10cf 298172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 299182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 300172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 301172811Sariff 302165770Sariff/* Toshiba */ 303165770Sariff#define TOSHIBA_VENDORID 0x1179 304165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 305173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 306165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 307165770Sariff 308165992Sariff/* Micro-Star International (MSI) */ 309165992Sariff#define MSI_VENDORID 0x1462 310165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 311172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 312165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 313165992Sariff 314172811Sariff/* Giga-Byte Technology */ 315172811Sariff#define GB_VENDORID 0x1458 316172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 317172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 318172811Sariff 319169277Sariff/* Uniwill ? */ 320169277Sariff#define UNIWILL_VENDORID 0x1584 321169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 322170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 323169277Sariff 324169277Sariff 325162922Sariff/* Misc constants.. */ 326182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 327162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 328162922Sariff#define HDA_AMP_MUTE_NONE (0) 329162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 330162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 331162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 332162922Sariff 333162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 334162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 335162922Sariff 336182999Smav#define HDA_ADC_MONITOR (1 << 0) 337162922Sariff 338182999Smav#define HDA_CTL_OUT 1 339182999Smav#define HDA_CTL_IN 2 340169277Sariff 341169277Sariff#define HDA_GPIO_MAX 8 342169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 343163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 344163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 345163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 346169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 347169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 348169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 349169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 350169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 351169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 352162922Sariff 353169277Sariff/* 9 - 25 = anything else */ 354169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 355169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 356169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 357169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 358169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 359182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 360169277Sariff 361169277Sariff/* 26 - 31 = vrefs */ 362169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 363169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 364169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 365169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 366169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 367169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 368169277Sariff 369169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 370169277Sariff HDA_QUIRK_IVREF100) 371169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 372169277Sariff HDA_QUIRK_OVREF100) 373169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 374169277Sariff 375171141Sariff#if __FreeBSD_version < 600000 376171141Sariff#define taskqueue_drain(...) 377171141Sariff#endif 378171141Sariff 379163057Sariffstatic const struct { 380163057Sariff char *key; 381163057Sariff uint32_t value; 382163057Sariff} hdac_quirks_tab[] = { 383163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 384163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 385163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 386169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 387169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 388169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 389169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 390169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 391165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 392163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 393163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 394163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 395163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 396169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 397182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 398169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 399169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 400169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 401169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 402169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 403169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 404169277Sariff { "ivref", HDA_QUIRK_IVREF }, 405169277Sariff { "ovref", HDA_QUIRK_OVREF }, 406165069Sariff { "vref", HDA_QUIRK_VREF }, 407163057Sariff}; 408163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 409163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 410163057Sariff 411162922Sariff#define HDA_BDL_MIN 2 412162922Sariff#define HDA_BDL_MAX 256 413162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 414162922Sariff 415169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 416167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 417167648Sariff 418162922Sariff#define HDA_BUFSZ_MIN 4096 419162922Sariff#define HDA_BUFSZ_MAX 65536 420162922Sariff#define HDA_BUFSZ_DEFAULT 16384 421162922Sariff 422162922Sariff#define HDA_PARSE_MAXDEPTH 10 423162922Sariff 424169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 425162922Sariff 426165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 427162922Sariff 428182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 429182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 430182999Smav "White", "Other"}; 431162922Sariff 432182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 433182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 434182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 435182999Smav 436182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 437182999Smav 438162922Sariff/* Default */ 439162922Sariffstatic uint32_t hdac_fmt[] = { 440162922Sariff AFMT_STEREO | AFMT_S16_LE, 441162922Sariff 0 442162922Sariff}; 443162922Sariff 444162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 445162922Sariff 446162922Sariffstatic const struct { 447162922Sariff uint32_t model; 448162922Sariff char *desc; 449162922Sariff} hdac_devices[] = { 450162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 451171330Sariff { HDA_INTEL_63XXESB, "Intel 631x/632xESB" }, 452162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 453163136Sariff { HDA_INTEL_82801H, "Intel 82801H" }, 454171330Sariff { HDA_INTEL_82801I, "Intel 82801I" }, 455184207Smav { HDA_INTEL_82801J, "Intel 82801J" }, 456184207Smav { HDA_INTEL_SCH, "Intel SCH" }, 457162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 458162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 459173817Sariff { HDA_NVIDIA_MCP61_1, "NVidia MCP61" }, 460173817Sariff { HDA_NVIDIA_MCP61_2, "NVidia MCP61" }, 461173817Sariff { HDA_NVIDIA_MCP65_1, "NVidia MCP65" }, 462174004Sariff { HDA_NVIDIA_MCP65_2, "NVidia MCP65" }, 463173817Sariff { HDA_NVIDIA_MCP67_1, "NVidia MCP67" }, 464173817Sariff { HDA_NVIDIA_MCP67_2, "NVidia MCP67" }, 465162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 466163136Sariff { HDA_ATI_SB600, "ATI SB600" }, 467163136Sariff { HDA_VIA_VT82XX, "VIA VT8251/8237A" }, 468163136Sariff { HDA_SIS_966, "SiS 966" }, 469162922Sariff /* Unknown */ 470162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 471162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 472162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 473163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 474163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 475162922Sariff}; 476162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 477162922Sariff 478162922Sariffstatic const struct { 479169277Sariff uint16_t vendor; 480169277Sariff uint8_t reg; 481169277Sariff uint8_t mask; 482169277Sariff uint8_t enable; 483169277Sariff} hdac_pcie_snoop[] = { 484169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 485169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 486169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 487169277Sariff}; 488169277Sariff#define HDAC_PCIESNOOP_LEN \ 489169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 490169277Sariff 491169277Sariffstatic const struct { 492162922Sariff uint32_t rate; 493162922Sariff int valid; 494162922Sariff uint16_t base; 495162922Sariff uint16_t mul; 496162922Sariff uint16_t div; 497162922Sariff} hda_rate_tab[] = { 498162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 499162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 500162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 501162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 502162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 503162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 504162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 505162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 506162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 507162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 508162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 509162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 510162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 511162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 512162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 513162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 514162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 515162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 516162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 517162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 518162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 519162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 520162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 521162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 522162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 523162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 524162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 525162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 526162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 527162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 528162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 529162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 530162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 531162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 532162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 533162922Sariff}; 534162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 535162922Sariff 536162922Sariff/* All codecs you can eat... */ 537162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 538162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 539162922Sariff 540162922Sariff/* Realtek */ 541162922Sariff#define REALTEK_VENDORID 0x10ec 542162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 543169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 544183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 545171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 546183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 547183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 548170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 549183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 550183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 551162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 552169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 553162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 554163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 555163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 556169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 557165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 558182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 559162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 560162922Sariff 561169277Sariff/* Analog Devices */ 562169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 563169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 564169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 565174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 566169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 567169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 568170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 569169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 570162922Sariff 571162922Sariff/* CMedia */ 572162922Sariff#define CMEDIA_VENDORID 0x434d 573162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 574162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 575162922Sariff 576162922Sariff/* Sigmatel */ 577162922Sariff#define SIGMATEL_VENDORID 0x8384 578182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 579182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 580182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 581182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 582182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 583182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 584182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 585182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 586183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 587183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 588183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 589183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 590183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 591183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 592183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 593182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 594183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 595183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 596183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 597183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 598183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 599183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 600183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 601183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 602182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 603162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 604182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 605183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 606162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 607162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 608183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 609183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 610183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 611183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 612183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 613183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 614183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 615183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 616183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 617162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 618162922Sariff 619183894Smav/* IDT */ 620183894Smav#define IDT_VENDORID 0x111d 621183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 622183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 623183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 624183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 625183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 626183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 627183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 628183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 629183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 630183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 631183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 632183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 633183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 634183894Smav 635182999Smav/* Silicon Image */ 636182999Smav#define SII_VENDORID 0x1095 637182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 638182999Smav 639182999Smav/* Lucent/Agere */ 640182999Smav#define AGERE_VENDORID 0x11c1 641182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 642182999Smav 643162922Sariff/* 644162922Sariff * Conexant 645162922Sariff * 646162922Sariff * Ok, the truth is, I don't have any idea at all whether 647162922Sariff * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only 648162922Sariff * place that tell me it is "Venice" is from its Windows driver INF. 649163057Sariff * 650163057Sariff * Venice - CX????? 651163057Sariff * Waikiki - CX20551-22 652162922Sariff */ 653162922Sariff#define CONEXANT_VENDORID 0x14f1 654162922Sariff#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 655163057Sariff#define HDA_CODEC_CXWAIKIKI HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 656162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 657162922Sariff 658169277Sariff/* VIA */ 659169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 660169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 661169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 662169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 663169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 664169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 665169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 666169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 667169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 668169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 669169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 670169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 671169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 672162922Sariff 673182999Smav/* ATI */ 674182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 675169277Sariff 676182999Smav/* NVIDIA */ 677182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 678182999Smav 679183894Smav/* INTEL */ 680183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 681183894Smav 682162922Sariff/* Codecs */ 683162922Sariffstatic const struct { 684162922Sariff uint32_t id; 685162922Sariff char *name; 686162922Sariff} hdac_codecs[] = { 687162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 688169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 689183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 690171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 691183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 692183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 693170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 694183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 695183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 696162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 697169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 698162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 699162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 700163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 701169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 702165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 703182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 704169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 705169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 706174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 707169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 708169277Sariff { HDA_CODEC_AD1988, "Analog Devices AD1988" }, 709170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 710162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 711183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 712183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 713183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 714183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 715183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 716183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 717183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 718183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 719162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 720183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 721162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 722162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 723183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 724183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 725183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 726183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 727183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 728183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 729182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 730182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 731183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 732183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 733183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 734166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 735183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 736183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 737183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 738183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 739183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 740183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 741183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 742183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 743183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 744183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 745183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 746183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 747183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 748183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 749183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 750183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 751183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 752183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 753183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 754183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 755183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 756183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 757183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 758183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 759183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 760183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 761183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 762162922Sariff { HDA_CODEC_CXVENICE, "Conexant Venice" }, 763163057Sariff { HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" }, 764169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 765169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 766169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 767169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 768169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 769169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 770169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 771169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 772169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 773169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 774169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 775169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 776162922Sariff /* Unknown codec */ 777162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 778169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 779162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 780162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 781182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 782182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 783162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 784169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 785182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 786182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 787183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 788183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 789162922Sariff}; 790162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 791162922Sariff 792162922Sariff 793162922Sariff/**************************************************************************** 794162922Sariff * Function prototypes 795162922Sariff ****************************************************************************/ 796162922Sariffstatic void hdac_intr_handler(void *); 797182999Smavstatic int hdac_reset(struct hdac_softc *, int); 798162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 799162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 800162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 801162922Sariff struct hdac_dma *, bus_size_t); 802169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 803162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 804162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 805162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 806162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 807162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 808162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 809162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 810162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 811182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 812182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 813182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 814182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 815162922Sariff 816162922Sariffstatic void hdac_attach2(void *); 817162922Sariff 818162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 819162922Sariff uint32_t, int); 820162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 821162922Sariff struct hdac_command_list *, int); 822162922Sariff 823162922Sariffstatic int hdac_probe(device_t); 824162922Sariffstatic int hdac_attach(device_t); 825162922Sariffstatic int hdac_detach(device_t); 826182999Smavstatic int hdac_suspend(device_t); 827182999Smavstatic int hdac_resume(device_t); 828162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 829162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 830162922Sariff uint32_t, int, int); 831162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 832182999Smav nid_t, int, int, int); 833162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 834162922Sariff nid_t, nid_t, int, int, int, int, int, int); 835162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 836162922Sariff 837164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 838164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 839164614Sariff 840182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 841182999Smav 842162922Sariff#define hdac_command(a1, a2, a3) \ 843162922Sariff hdac_command_sendone_internal(a1, a2, a3) 844162922Sariff 845182999Smav#define hdac_codec_id(c) \ 846182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 847182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 848182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 849162922Sariff 850162922Sariffstatic char * 851182999Smavhdac_codec_name(struct hdac_codec *codec) 852162922Sariff{ 853162922Sariff uint32_t id; 854162922Sariff int i; 855162922Sariff 856182999Smav id = hdac_codec_id(codec); 857162922Sariff 858162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 859163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 860162922Sariff return (hdac_codecs[i].name); 861162922Sariff } 862162922Sariff 863162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 864162922Sariff} 865162922Sariff 866162922Sariffstatic char * 867162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 868162922Sariff{ 869162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 870162922Sariff int i, first = 1; 871162922Sariff 872162922Sariff bzero(buf, len); 873162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 874162922Sariff if (mask & (1 << i)) { 875162922Sariff if (first == 0) 876162922Sariff strlcat(buf, ", ", len); 877162922Sariff strlcat(buf, ossname[i], len); 878162922Sariff first = 0; 879162922Sariff } 880162922Sariff } 881182999Smav return (buf); 882162922Sariff} 883162922Sariff 884162922Sariffstatic struct hdac_audio_ctl * 885162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 886162922Sariff{ 887162922Sariff if (devinfo == NULL || 888162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 889162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 890162922Sariff devinfo->function.audio.ctlcnt < 1 || 891162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 892162922Sariff return (NULL); 893162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 894162922Sariff} 895162922Sariff 896162922Sariffstatic struct hdac_audio_ctl * 897182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 898162922Sariff int index, int cnt) 899162922Sariff{ 900182999Smav struct hdac_audio_ctl *ctl; 901182999Smav int i, found = 0; 902162922Sariff 903162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 904162922Sariff return (NULL); 905162922Sariff 906162922Sariff i = 0; 907162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 908182999Smav if (ctl->enable == 0) 909162922Sariff continue; 910182999Smav if (ctl->widget->nid != nid) 911162922Sariff continue; 912182999Smav if (dir && ctl->ndir != dir) 913182999Smav continue; 914182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 915182999Smav ctl->dir == ctl->ndir && ctl->index != index) 916182999Smav continue; 917162922Sariff found++; 918182999Smav if (found == cnt || cnt <= 0) 919162922Sariff return (ctl); 920162922Sariff } 921162922Sariff 922182999Smav return (NULL); 923162922Sariff} 924162922Sariff 925182999Smav/* 926182999Smav * Jack detection (Speaker/HP redirection) event handler. 927182999Smav */ 928162922Sariffstatic void 929162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 930162922Sariff{ 931182999Smav struct hdac_audio_as *as; 932162922Sariff struct hdac_softc *sc; 933162922Sariff struct hdac_widget *w; 934162922Sariff struct hdac_audio_ctl *ctl; 935182999Smav uint32_t val, res; 936182999Smav int i, j; 937162922Sariff nid_t cad; 938162922Sariff 939162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 940162922Sariff devinfo->codec->sc == NULL) 941162922Sariff return; 942162922Sariff 943162922Sariff sc = devinfo->codec->sc; 944162922Sariff cad = devinfo->codec->cad; 945182999Smav as = devinfo->function.audio.as; 946182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 947182999Smav if (as[i].hpredir < 0) 948182999Smav continue; 949182999Smav 950182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 951182999Smav if (w == NULL || w->enable == 0 || w->type != 952182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 953182999Smav continue; 954162922Sariff 955171141Sariff res = hdac_command(sc, 956182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 957171141Sariff 958182999Smav HDA_BOOTVERBOSE( 959182999Smav device_printf(sc->dev, 960182999Smav "Pin sense: nid=%d res=0x%08x\n", 961182999Smav as[i].pins[15], res); 962182999Smav ); 963171141Sariff 964182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 965182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 966182999Smav res ^= 1; 967162922Sariff 968182999Smav /* (Un)Mute headphone pin. */ 969162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 970182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 971182999Smav if (ctl != NULL && ctl->mute) { 972182999Smav /* If pin has muter - use it. */ 973182999Smav val = (res != 0) ? 0 : 1; 974182999Smav if (val != ctl->forcemute) { 975182999Smav ctl->forcemute = val; 976162922Sariff hdac_audio_ctl_amp_set(ctl, 977182999Smav HDA_AMP_MUTE_DEFAULT, 978182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 979162922Sariff } 980182999Smav } else { 981182999Smav /* If there is no muter - disable pin output. */ 982182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 983163057Sariff if (w != NULL && w->type == 984163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 985182999Smav if (res != 0) 986169277Sariff val = w->wclass.pin.ctrl | 987162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 988162922Sariff else 989169277Sariff val = w->wclass.pin.ctrl & 990162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 991169277Sariff if (val != w->wclass.pin.ctrl) { 992169277Sariff w->wclass.pin.ctrl = val; 993169277Sariff hdac_command(sc, 994169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 995169277Sariff w->nid, w->wclass.pin.ctrl), cad); 996169277Sariff } 997162922Sariff } 998182999Smav } 999182999Smav /* (Un)Mute other pins. */ 1000182999Smav for (j = 0; j < 15; j++) { 1001182999Smav if (as[i].pins[j] <= 0) 1002182999Smav continue; 1003182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1004182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1005182999Smav if (ctl != NULL && ctl->mute) { 1006182999Smav /* If pin has muter - use it. */ 1007182999Smav val = (res != 0) ? 1 : 0; 1008182999Smav if (val == ctl->forcemute) 1009169277Sariff continue; 1010182999Smav ctl->forcemute = val; 1011182999Smav hdac_audio_ctl_amp_set(ctl, 1012182999Smav HDA_AMP_MUTE_DEFAULT, 1013182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1014182999Smav continue; 1015162922Sariff } 1016182999Smav /* If there is no muter - disable pin output. */ 1017182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1018163057Sariff if (w != NULL && w->type == 1019163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1020182999Smav if (res != 0) 1021182999Smav val = w->wclass.pin.ctrl & 1022182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1023182999Smav else 1024182999Smav val = w->wclass.pin.ctrl | 1025182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1026169277Sariff if (val != w->wclass.pin.ctrl) { 1027169277Sariff w->wclass.pin.ctrl = val; 1028169277Sariff hdac_command(sc, 1029169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1030169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1031169277Sariff } 1032162922Sariff } 1033162922Sariff } 1034182999Smav } 1035182999Smav} 1036182999Smav 1037182999Smav/* 1038182999Smav * Callback for poll based jack detection. 1039182999Smav */ 1040182999Smavstatic void 1041182999Smavhdac_jack_poll_callback(void *arg) 1042182999Smav{ 1043182999Smav struct hdac_devinfo *devinfo = arg; 1044182999Smav struct hdac_softc *sc; 1045182999Smav 1046182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1047182999Smav devinfo->codec->sc == NULL) 1048182999Smav return; 1049182999Smav sc = devinfo->codec->sc; 1050182999Smav hdac_lock(sc); 1051182999Smav if (sc->poll_ival == 0) { 1052182999Smav hdac_unlock(sc); 1053182999Smav return; 1054182999Smav } 1055182999Smav hdac_hp_switch_handler(devinfo); 1056182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1057182999Smav hdac_jack_poll_callback, devinfo); 1058182999Smav hdac_unlock(sc); 1059182999Smav} 1060182999Smav 1061182999Smav/* 1062182999Smav * Jack detection initializer. 1063182999Smav */ 1064182999Smavstatic void 1065182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1066182999Smav{ 1067182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1068182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1069182999Smav struct hdac_widget *w; 1070182999Smav uint32_t id; 1071182999Smav int i, enable = 0, poll = 0; 1072182999Smav nid_t cad; 1073182999Smav 1074182999Smav id = hdac_codec_id(devinfo->codec); 1075182999Smav cad = devinfo->codec->cad; 1076182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1077182999Smav if (as[i].hpredir < 0) 1078182999Smav continue; 1079182999Smav 1080182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1081182999Smav if (w == NULL || w->enable == 0 || w->type != 1082182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1083182999Smav continue; 1084182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1085182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1086182999Smav device_printf(sc->dev, 1087182999Smav "No jack detection support at pin %d\n", 1088182999Smav as[i].pins[15]); 1089182999Smav continue; 1090182999Smav } 1091182999Smav enable = 1; 1092182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1093169277Sariff hdac_command(sc, 1094182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1095182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1096182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1097182999Smav } else 1098182999Smav poll = 1; 1099182999Smav HDA_BOOTVERBOSE( 1100169277Sariff device_printf(sc->dev, 1101182999Smav "Enabling headphone/speaker " 1102182999Smav "audio routing switching:\n"); 1103182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1104182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1105182999Smav ); 1106182999Smav } 1107182999Smav if (enable) { 1108182999Smav hdac_hp_switch_handler(devinfo); 1109182999Smav if (poll) { 1110182999Smav callout_reset(&sc->poll_jack, 1, 1111182999Smav hdac_jack_poll_callback, devinfo); 1112169277Sariff } 1113162922Sariff } 1114162922Sariff} 1115162922Sariff 1116182999Smav/* 1117182999Smav * Unsolicited messages handler. 1118182999Smav */ 1119162922Sariffstatic void 1120162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1121162922Sariff{ 1122162922Sariff struct hdac_softc *sc; 1123162922Sariff struct hdac_devinfo *devinfo = NULL; 1124182999Smav int i; 1125162922Sariff 1126162922Sariff if (codec == NULL || codec->sc == NULL) 1127162922Sariff return; 1128162922Sariff 1129162922Sariff sc = codec->sc; 1130162922Sariff 1131163057Sariff HDA_BOOTVERBOSE( 1132182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1133162922Sariff ); 1134162922Sariff 1135182999Smav for (i = 0; i < codec->num_fgs; i++) { 1136182999Smav if (codec->fgs[i].node_type == 1137182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1138182999Smav devinfo = &codec->fgs[i]; 1139162965Sariff break; 1140182999Smav } 1141162922Sariff } 1142162965Sariff 1143162922Sariff if (devinfo == NULL) 1144162922Sariff return; 1145162922Sariff 1146162922Sariff switch (tag) { 1147162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1148162922Sariff hdac_hp_switch_handler(devinfo); 1149162922Sariff break; 1150162922Sariff default: 1151182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1152162922Sariff break; 1153162922Sariff } 1154162922Sariff} 1155162922Sariff 1156164614Sariffstatic int 1157162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1158162922Sariff{ 1159162922Sariff /* XXX to be removed */ 1160162922Sariff#ifdef HDAC_INTR_EXTRA 1161162922Sariff uint32_t res; 1162162922Sariff#endif 1163162922Sariff 1164171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1165164614Sariff return (0); 1166162922Sariff 1167162922Sariff /* XXX to be removed */ 1168162922Sariff#ifdef HDAC_INTR_EXTRA 1169162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1170162922Sariff#endif 1171162922Sariff 1172162922Sariff /* XXX to be removed */ 1173162922Sariff#ifdef HDAC_INTR_EXTRA 1174163057Sariff HDA_BOOTVERBOSE( 1175163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1176182999Smav device_printf(ch->pdevinfo->dev, 1177163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1178163057Sariff "%08x\n", 1179163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1180163057Sariff ); 1181162922Sariff#endif 1182162922Sariff 1183162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1184163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1185162922Sariff 1186162922Sariff /* XXX to be removed */ 1187162922Sariff#ifdef HDAC_INTR_EXTRA 1188162922Sariff if (res & HDAC_SDSTS_BCIS) { 1189162922Sariff#endif 1190164614Sariff return (1); 1191162922Sariff /* XXX to be removed */ 1192162922Sariff#ifdef HDAC_INTR_EXTRA 1193162922Sariff } 1194162922Sariff#endif 1195164614Sariff 1196164614Sariff return (0); 1197162922Sariff} 1198162922Sariff 1199162922Sariff/**************************************************************************** 1200162922Sariff * void hdac_intr_handler(void *) 1201162922Sariff * 1202162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1203162922Sariff ****************************************************************************/ 1204162922Sariffstatic void 1205162922Sariffhdac_intr_handler(void *context) 1206162922Sariff{ 1207162922Sariff struct hdac_softc *sc; 1208162922Sariff uint32_t intsts; 1209162922Sariff uint8_t rirbsts; 1210164614Sariff struct hdac_rirb *rirb_base; 1211171141Sariff uint32_t trigger; 1212182999Smav int i; 1213162922Sariff 1214162922Sariff sc = (struct hdac_softc *)context; 1215162922Sariff 1216162922Sariff hdac_lock(sc); 1217164614Sariff if (sc->polling != 0) { 1218164614Sariff hdac_unlock(sc); 1219164614Sariff return; 1220164614Sariff } 1221171141Sariff 1222162922Sariff /* Do we have anything to do? */ 1223162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1224163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1225162922Sariff hdac_unlock(sc); 1226162922Sariff return; 1227162922Sariff } 1228162922Sariff 1229171141Sariff trigger = 0; 1230171141Sariff 1231162922Sariff /* Was this a controller interrupt? */ 1232163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1233162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1234162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1235162922Sariff /* Get as many responses that we can */ 1236163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1237164614Sariff HDAC_WRITE_1(&sc->mem, 1238164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1239171141Sariff if (hdac_rirb_flush(sc) != 0) 1240171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1241162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1242162922Sariff } 1243162922Sariff /* XXX to be removed */ 1244162922Sariff /* Clear interrupt and exit */ 1245162922Sariff#ifdef HDAC_INTR_EXTRA 1246162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1247162922Sariff#endif 1248162922Sariff } 1249164614Sariff 1250163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1251182999Smav for (i = 0; i < sc->num_chans; i++) { 1252182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1253182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1254182999Smav trigger |= (1 << i); 1255182999Smav } 1256162922Sariff /* XXX to be removed */ 1257162922Sariff#ifdef HDAC_INTR_EXTRA 1258164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1259164614Sariff HDAC_INTSTS_SIS_MASK); 1260162922Sariff#endif 1261162922Sariff } 1262162922Sariff 1263164614Sariff hdac_unlock(sc); 1264162922Sariff 1265182999Smav for (i = 0; i < sc->num_chans; i++) { 1266182999Smav if (trigger & (1 << i)) 1267182999Smav chn_intr(sc->chans[i].c); 1268182999Smav } 1269171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1270171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1271162922Sariff} 1272162922Sariff 1273162922Sariff/**************************************************************************** 1274182999Smav * int hdac_reset(hdac_softc *, int) 1275162922Sariff * 1276162922Sariff * Reset the hdac to a quiescent and known state. 1277162922Sariff ****************************************************************************/ 1278162922Sariffstatic int 1279182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1280162922Sariff{ 1281162922Sariff uint32_t gctl; 1282162922Sariff int count, i; 1283162922Sariff 1284162922Sariff /* 1285162922Sariff * Stop all Streams DMA engine 1286162922Sariff */ 1287162922Sariff for (i = 0; i < sc->num_iss; i++) 1288162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1289162922Sariff for (i = 0; i < sc->num_oss; i++) 1290162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1291162922Sariff for (i = 0; i < sc->num_bss; i++) 1292162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1293162922Sariff 1294162922Sariff /* 1295169277Sariff * Stop Control DMA engines. 1296162922Sariff */ 1297162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1298162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1299162922Sariff 1300162922Sariff /* 1301169277Sariff * Reset DMA position buffer. 1302169277Sariff */ 1303169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1304169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1305169277Sariff 1306169277Sariff /* 1307162922Sariff * Reset the controller. The reset must remain asserted for 1308162922Sariff * a minimum of 100us. 1309162922Sariff */ 1310162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1311162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1312162922Sariff count = 10000; 1313162922Sariff do { 1314162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1315162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1316162922Sariff break; 1317162922Sariff DELAY(10); 1318162922Sariff } while (--count); 1319162922Sariff if (gctl & HDAC_GCTL_CRST) { 1320162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1321162922Sariff return (ENXIO); 1322162922Sariff } 1323182999Smav 1324182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1325182999Smav if (!wakeup) 1326182999Smav return (0); 1327182999Smav 1328162922Sariff DELAY(100); 1329162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1330162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1331162922Sariff count = 10000; 1332162922Sariff do { 1333162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1334163057Sariff if (gctl & HDAC_GCTL_CRST) 1335162922Sariff break; 1336162922Sariff DELAY(10); 1337162922Sariff } while (--count); 1338162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1339162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1340162922Sariff return (ENXIO); 1341162922Sariff } 1342162922Sariff 1343162922Sariff /* 1344162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1345162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1346162922Sariff * computer. Let's use twice as much as necessary to make sure that 1347162922Sariff * it's reset properly. 1348162922Sariff */ 1349162922Sariff DELAY(1000); 1350162922Sariff 1351162922Sariff return (0); 1352162922Sariff} 1353162922Sariff 1354162922Sariff 1355162922Sariff/**************************************************************************** 1356162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1357162922Sariff * 1358162922Sariff * Retreive the general capabilities of the hdac; 1359162922Sariff * Number of Input Streams 1360162922Sariff * Number of Output Streams 1361162922Sariff * Number of bidirectional Streams 1362162922Sariff * 64bit ready 1363162922Sariff * CORB and RIRB sizes 1364162922Sariff ****************************************************************************/ 1365162922Sariffstatic int 1366162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1367162922Sariff{ 1368162922Sariff uint16_t gcap; 1369162922Sariff uint8_t corbsize, rirbsize; 1370162922Sariff 1371162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1372162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1373162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1374162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1375162922Sariff 1376163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1377162922Sariff 1378162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1379162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1380162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1381162922Sariff sc->corb_size = 256; 1382162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1383162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1384162922Sariff sc->corb_size = 16; 1385162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1386162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1387162922Sariff sc->corb_size = 2; 1388162922Sariff else { 1389162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1390162922Sariff __func__, corbsize); 1391162922Sariff return (ENXIO); 1392162922Sariff } 1393162922Sariff 1394162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1395162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1396162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1397162922Sariff sc->rirb_size = 256; 1398162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1399162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1400162922Sariff sc->rirb_size = 16; 1401162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1402162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1403162922Sariff sc->rirb_size = 2; 1404162922Sariff else { 1405162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1406162922Sariff __func__, rirbsize); 1407162922Sariff return (ENXIO); 1408162922Sariff } 1409162922Sariff 1410183097Smav HDA_BOOTHVERBOSE( 1411182999Smav device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 1412182999Smav device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 1413182999Smav device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 1414182999Smav sc->num_iss, sc->num_oss, sc->num_bss); 1415182999Smav ); 1416182999Smav 1417162922Sariff return (0); 1418162922Sariff} 1419162922Sariff 1420162922Sariff 1421162922Sariff/**************************************************************************** 1422162922Sariff * void hdac_dma_cb 1423162922Sariff * 1424162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1425162922Sariff * established. We just record the physical address of the mapping into 1426162922Sariff * the struct hdac_dma passed in. 1427162922Sariff ****************************************************************************/ 1428162922Sariffstatic void 1429162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1430162922Sariff{ 1431162922Sariff struct hdac_dma *dma; 1432162922Sariff 1433162922Sariff if (error == 0) { 1434162922Sariff dma = (struct hdac_dma *)callback_arg; 1435162922Sariff dma->dma_paddr = segs[0].ds_addr; 1436162922Sariff } 1437162922Sariff} 1438162922Sariff 1439162922Sariff 1440162922Sariff/**************************************************************************** 1441162922Sariff * int hdac_dma_alloc 1442162922Sariff * 1443162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1444162922Sariff * It must be freed by a corresponding hdac_dma_free. 1445162922Sariff ****************************************************************************/ 1446162922Sariffstatic int 1447162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1448162922Sariff{ 1449169277Sariff bus_size_t roundsz; 1450162922Sariff int result; 1451162922Sariff int lowaddr; 1452162922Sariff 1453169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1454162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1455162922Sariff BUS_SPACE_MAXADDR_32BIT; 1456162922Sariff bzero(dma, sizeof(*dma)); 1457162922Sariff 1458162922Sariff /* 1459162922Sariff * Create a DMA tag 1460162922Sariff */ 1461162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1462162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1463162922Sariff 0, /* boundary */ 1464162922Sariff lowaddr, /* lowaddr */ 1465162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1466162922Sariff NULL, /* filtfunc */ 1467162922Sariff NULL, /* fistfuncarg */ 1468169277Sariff roundsz, /* maxsize */ 1469162922Sariff 1, /* nsegments */ 1470169277Sariff roundsz, /* maxsegsz */ 1471162922Sariff 0, /* flags */ 1472162922Sariff NULL, /* lockfunc */ 1473162922Sariff NULL, /* lockfuncarg */ 1474162922Sariff &dma->dma_tag); /* dmat */ 1475162922Sariff if (result != 0) { 1476162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1477162922Sariff __func__, result); 1478167773Sariff goto hdac_dma_alloc_fail; 1479162922Sariff } 1480162922Sariff 1481162922Sariff /* 1482162922Sariff * Allocate DMA memory 1483162922Sariff */ 1484162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1485169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1486171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1487171330Sariff &dma->dma_map); 1488162922Sariff if (result != 0) { 1489162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1490162922Sariff __func__, result); 1491167773Sariff goto hdac_dma_alloc_fail; 1492162922Sariff } 1493162922Sariff 1494169277Sariff dma->dma_size = roundsz; 1495169277Sariff 1496162922Sariff /* 1497162922Sariff * Map the memory 1498162922Sariff */ 1499162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1500169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1501162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1502167773Sariff if (result == 0) 1503167773Sariff result = ENOMEM; 1504162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1505162922Sariff __func__, result); 1506167773Sariff goto hdac_dma_alloc_fail; 1507162922Sariff } 1508162922Sariff 1509183097Smav HDA_BOOTHVERBOSE( 1510169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1511169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1512169277Sariff ); 1513169277Sariff 1514162922Sariff return (0); 1515169277Sariff 1516167773Sariffhdac_dma_alloc_fail: 1517169277Sariff hdac_dma_free(sc, dma); 1518167773Sariff 1519162922Sariff return (result); 1520162922Sariff} 1521162922Sariff 1522162922Sariff 1523162922Sariff/**************************************************************************** 1524169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1525162922Sariff * 1526162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1527162922Sariff * hdac_dma_alloc function. 1528162922Sariff ****************************************************************************/ 1529162922Sariffstatic void 1530169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1531162922Sariff{ 1532167773Sariff if (dma->dma_map != NULL) { 1533169277Sariff#if 0 1534162922Sariff /* Flush caches */ 1535162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1536162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1537169277Sariff#endif 1538162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1539167773Sariff } 1540167773Sariff if (dma->dma_vaddr != NULL) { 1541162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1542167773Sariff dma->dma_vaddr = NULL; 1543167773Sariff } 1544167773Sariff dma->dma_map = NULL; 1545167773Sariff if (dma->dma_tag != NULL) { 1546162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1547167773Sariff dma->dma_tag = NULL; 1548162922Sariff } 1549167773Sariff dma->dma_size = 0; 1550162922Sariff} 1551162922Sariff 1552162922Sariff/**************************************************************************** 1553162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1554162922Sariff * 1555162922Sariff * Allocate all the bus resources necessary to speak with the physical 1556162922Sariff * controller. 1557162922Sariff ****************************************************************************/ 1558162922Sariffstatic int 1559162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1560162922Sariff{ 1561162922Sariff struct hdac_mem *mem; 1562162922Sariff 1563162922Sariff mem = &sc->mem; 1564162922Sariff mem->mem_rid = PCIR_BAR(0); 1565162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1566162922Sariff &mem->mem_rid, RF_ACTIVE); 1567162922Sariff if (mem->mem_res == NULL) { 1568162922Sariff device_printf(sc->dev, 1569162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1570162922Sariff return (ENOMEM); 1571162922Sariff } 1572162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1573162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1574162922Sariff 1575162922Sariff return (0); 1576162922Sariff} 1577162922Sariff 1578162922Sariff/**************************************************************************** 1579162922Sariff * void hdac_mem_free(struct hdac_softc *) 1580162922Sariff * 1581162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1582162922Sariff ****************************************************************************/ 1583162922Sariffstatic void 1584162922Sariffhdac_mem_free(struct hdac_softc *sc) 1585162922Sariff{ 1586162922Sariff struct hdac_mem *mem; 1587162922Sariff 1588162922Sariff mem = &sc->mem; 1589162922Sariff if (mem->mem_res != NULL) 1590162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1591162922Sariff mem->mem_res); 1592164614Sariff mem->mem_res = NULL; 1593162922Sariff} 1594162922Sariff 1595162922Sariff/**************************************************************************** 1596162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1597162922Sariff * 1598162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1599162922Sariff ****************************************************************************/ 1600162922Sariffstatic int 1601162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1602162922Sariff{ 1603162922Sariff struct hdac_irq *irq; 1604162922Sariff int result; 1605162922Sariff 1606162922Sariff irq = &sc->irq; 1607162922Sariff irq->irq_rid = 0x0; 1608171330Sariff 1609178155Sariff#ifdef HDAC_MSI_ENABLED 1610171330Sariff if ((sc->flags & HDAC_F_MSI) && 1611171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1612171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1613171330Sariff irq->irq_rid = 0x1; 1614171330Sariff else 1615171330Sariff#endif 1616171330Sariff sc->flags &= ~HDAC_F_MSI; 1617171330Sariff 1618162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1619162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1620162922Sariff if (irq->irq_res == NULL) { 1621162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1622162922Sariff __func__); 1623167773Sariff goto hdac_irq_alloc_fail; 1624162922Sariff } 1625182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1626182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1627162922Sariff if (result != 0) { 1628162922Sariff device_printf(sc->dev, 1629162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1630162922Sariff __func__, result); 1631167773Sariff goto hdac_irq_alloc_fail; 1632162922Sariff } 1633162922Sariff 1634162922Sariff return (0); 1635162922Sariff 1636167773Sariffhdac_irq_alloc_fail: 1637164614Sariff hdac_irq_free(sc); 1638164614Sariff 1639162922Sariff return (ENXIO); 1640162922Sariff} 1641162922Sariff 1642162922Sariff/**************************************************************************** 1643162922Sariff * void hdac_irq_free(struct hdac_softc *) 1644162922Sariff * 1645162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1646162922Sariff ****************************************************************************/ 1647162922Sariffstatic void 1648162922Sariffhdac_irq_free(struct hdac_softc *sc) 1649162922Sariff{ 1650162922Sariff struct hdac_irq *irq; 1651162922Sariff 1652162922Sariff irq = &sc->irq; 1653164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1654162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1655162922Sariff if (irq->irq_res != NULL) 1656162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1657162922Sariff irq->irq_res); 1658178155Sariff#ifdef HDAC_MSI_ENABLED 1659171330Sariff if ((sc->flags & HDAC_F_MSI) && irq->irq_rid == 0x1) 1660171330Sariff pci_release_msi(sc->dev); 1661171330Sariff#endif 1662164614Sariff irq->irq_handle = NULL; 1663164614Sariff irq->irq_res = NULL; 1664171330Sariff irq->irq_rid = 0x0; 1665162922Sariff} 1666162922Sariff 1667162922Sariff/**************************************************************************** 1668162922Sariff * void hdac_corb_init(struct hdac_softc *) 1669162922Sariff * 1670162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1671162922Sariff * The CORB engine must not be running when this function is called. 1672162922Sariff ****************************************************************************/ 1673162922Sariffstatic void 1674162922Sariffhdac_corb_init(struct hdac_softc *sc) 1675162922Sariff{ 1676162922Sariff uint8_t corbsize; 1677162922Sariff uint64_t corbpaddr; 1678162922Sariff 1679162922Sariff /* Setup the CORB size. */ 1680162922Sariff switch (sc->corb_size) { 1681162922Sariff case 256: 1682162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1683162922Sariff break; 1684162922Sariff case 16: 1685162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1686162922Sariff break; 1687162922Sariff case 2: 1688162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1689162922Sariff break; 1690162922Sariff default: 1691162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1692162922Sariff } 1693162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1694162922Sariff 1695162922Sariff /* Setup the CORB Address in the hdac */ 1696162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1697162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1698162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1699162922Sariff 1700162922Sariff /* Set the WP and RP */ 1701162922Sariff sc->corb_wp = 0; 1702162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1703162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1704162922Sariff /* 1705162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1706162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1707162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1708162922Sariff * manually reset the bit to zero before continuing. 1709162922Sariff */ 1710162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1711162922Sariff 1712162922Sariff /* Enable CORB error reporting */ 1713162922Sariff#if 0 1714162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1715162922Sariff#endif 1716162922Sariff} 1717162922Sariff 1718162922Sariff/**************************************************************************** 1719162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1720162922Sariff * 1721162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1722162922Sariff * The RIRB engine must not be running when this function is called. 1723162922Sariff ****************************************************************************/ 1724162922Sariffstatic void 1725162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1726162922Sariff{ 1727162922Sariff uint8_t rirbsize; 1728162922Sariff uint64_t rirbpaddr; 1729162922Sariff 1730162922Sariff /* Setup the RIRB size. */ 1731162922Sariff switch (sc->rirb_size) { 1732162922Sariff case 256: 1733162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1734162922Sariff break; 1735162922Sariff case 16: 1736162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1737162922Sariff break; 1738162922Sariff case 2: 1739162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1740162922Sariff break; 1741162922Sariff default: 1742162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1743162922Sariff } 1744162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1745162922Sariff 1746162922Sariff /* Setup the RIRB Address in the hdac */ 1747162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1748162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1749162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1750162922Sariff 1751162922Sariff /* Setup the WP and RP */ 1752162922Sariff sc->rirb_rp = 0; 1753162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1754162922Sariff 1755182999Smav /* Setup the interrupt threshold */ 1756182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1757162922Sariff 1758182999Smav /* Enable Overrun and response received reporting */ 1759162922Sariff#if 0 1760182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1761182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1762162922Sariff#else 1763182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1764162922Sariff#endif 1765162922Sariff 1766169277Sariff#if 0 1767162922Sariff /* 1768162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1769162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1770162922Sariff * should be sufficient to do this only once as the rirb is purely 1771162922Sariff * read-only from now on. 1772162922Sariff */ 1773162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1774162922Sariff BUS_DMASYNC_PREREAD); 1775169277Sariff#endif 1776162922Sariff} 1777162922Sariff 1778162922Sariff/**************************************************************************** 1779162922Sariff * void hdac_corb_start(hdac_softc *) 1780162922Sariff * 1781162922Sariff * Startup the corb DMA engine 1782162922Sariff ****************************************************************************/ 1783162922Sariffstatic void 1784162922Sariffhdac_corb_start(struct hdac_softc *sc) 1785162922Sariff{ 1786162922Sariff uint32_t corbctl; 1787162922Sariff 1788162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1789162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1790162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1791162922Sariff} 1792162922Sariff 1793162922Sariff/**************************************************************************** 1794162922Sariff * void hdac_rirb_start(hdac_softc *) 1795162922Sariff * 1796162922Sariff * Startup the rirb DMA engine 1797162922Sariff ****************************************************************************/ 1798162922Sariffstatic void 1799162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1800162922Sariff{ 1801162922Sariff uint32_t rirbctl; 1802162922Sariff 1803162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1804162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1805162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1806162922Sariff} 1807162922Sariff 1808162922Sariff 1809162922Sariff/**************************************************************************** 1810172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 1811162922Sariff * 1812172811Sariff * Scan the bus for available codecs, starting with num. 1813162922Sariff ****************************************************************************/ 1814162922Sariffstatic void 1815182999Smavhdac_scan_codecs(struct hdac_softc *sc) 1816162922Sariff{ 1817162922Sariff struct hdac_codec *codec; 1818162922Sariff int i; 1819162922Sariff uint16_t statests; 1820162922Sariff 1821162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1822182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1823162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1824162922Sariff /* We have found a codec. */ 1825162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1826162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1827162922Sariff if (codec == NULL) { 1828162922Sariff device_printf(sc->dev, 1829162922Sariff "Unable to allocate memory for codec\n"); 1830162922Sariff continue; 1831162922Sariff } 1832164614Sariff codec->commands = NULL; 1833164614Sariff codec->responses_received = 0; 1834162922Sariff codec->verbs_sent = 0; 1835162922Sariff codec->sc = sc; 1836162922Sariff codec->cad = i; 1837162922Sariff sc->codecs[i] = codec; 1838182999Smav hdac_probe_codec(codec); 1839162922Sariff } 1840162922Sariff } 1841162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1842163057Sariff /* bus_generic_attach(sc->dev); */ 1843162922Sariff} 1844162922Sariff 1845162922Sariff/**************************************************************************** 1846162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1847162922Sariff * 1848162922Sariff * Probe a the given codec_id for available function groups. 1849162922Sariff ****************************************************************************/ 1850182999Smavstatic void 1851162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1852162922Sariff{ 1853162922Sariff struct hdac_softc *sc = codec->sc; 1854162922Sariff uint32_t vendorid, revisionid, subnode; 1855162922Sariff int startnode; 1856162922Sariff int endnode; 1857162922Sariff int i; 1858162922Sariff nid_t cad = codec->cad; 1859162922Sariff 1860163057Sariff HDA_BOOTVERBOSE( 1861184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 1862162922Sariff ); 1863162922Sariff vendorid = hdac_command(sc, 1864162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1865162922Sariff cad); 1866162922Sariff revisionid = hdac_command(sc, 1867162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1868162922Sariff cad); 1869182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1870182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1871182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1872182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1873182999Smav 1874182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 1875182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 1876182999Smav " Probing aborted.\n", cad); 1877182999Smav return; 1878182999Smav } 1879182999Smav 1880184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 1881182999Smav cad, hdac_codec_name(codec)); 1882182999Smav HDA_BOOTVERBOSE( 1883184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 1884182999Smav hdac_codec_id(codec)); 1885182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 1886182999Smav codec->vendor_id); 1887182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 1888182999Smav codec->device_id); 1889182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 1890182999Smav codec->revision_id); 1891182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 1892182999Smav codec->stepping_id); 1893182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 1894182999Smav sc->pci_subvendor); 1895182999Smav ); 1896162922Sariff subnode = hdac_command(sc, 1897162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1898162922Sariff cad); 1899162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1900162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1901162922Sariff 1902183097Smav HDA_BOOTHVERBOSE( 1903182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 1904163057Sariff startnode, endnode); 1905162922Sariff ); 1906182999Smav 1907182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 1908182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 1909182999Smav if (codec->fgs == NULL) { 1910183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 1911182999Smav __func__); 1912182999Smav return; 1913162922Sariff } 1914162922Sariff 1915182999Smav for (i = startnode; i < endnode; i++) 1916182999Smav hdac_probe_function(codec, i); 1917182999Smav return; 1918162922Sariff} 1919162922Sariff 1920182999Smav/* 1921182999Smav * Probe codec function and add it to the list. 1922182999Smav */ 1923182999Smavstatic void 1924162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1925162922Sariff{ 1926162922Sariff struct hdac_softc *sc = codec->sc; 1927182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 1928162922Sariff uint32_t fctgrptype; 1929182999Smav uint32_t res; 1930162922Sariff nid_t cad = codec->cad; 1931162922Sariff 1932162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1933162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1934162922Sariff 1935162922Sariff devinfo->nid = nid; 1936162965Sariff devinfo->node_type = fctgrptype; 1937162922Sariff devinfo->codec = codec; 1938162922Sariff 1939182999Smav res = hdac_command(sc, 1940182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 1941162922Sariff 1942182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 1943182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 1944182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 1945162922Sariff 1946182999Smav HDA_BOOTVERBOSE( 1947182999Smav device_printf(sc->dev, 1948182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 1949182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 1950182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 1951182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 1952182999Smav devinfo->nodecnt); 1953182999Smav ); 1954182999Smav 1955182999Smav if (devinfo->nodecnt > 0) 1956182999Smav devinfo->widget = (struct hdac_widget *)malloc( 1957182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 1958182999Smav M_NOWAIT | M_ZERO); 1959182999Smav else 1960182999Smav devinfo->widget = NULL; 1961182999Smav 1962182999Smav if (devinfo->widget == NULL) { 1963182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 1964182999Smav devinfo->endnode = devinfo->startnode; 1965182999Smav devinfo->nodecnt = 0; 1966182999Smav return; 1967182999Smav } 1968182999Smav 1969182999Smav codec->num_fgs++; 1970162922Sariff} 1971162922Sariff 1972162922Sariffstatic void 1973162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 1974162922Sariff{ 1975162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1976162922Sariff uint32_t res; 1977169277Sariff int i, j, max, ents, entnum; 1978162922Sariff nid_t cad = w->devinfo->codec->cad; 1979162922Sariff nid_t nid = w->nid; 1980169277Sariff nid_t cnid, addcnid, prevcnid; 1981162922Sariff 1982169277Sariff w->nconns = 0; 1983169277Sariff 1984162922Sariff res = hdac_command(sc, 1985162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 1986162922Sariff 1987169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 1988162922Sariff 1989169277Sariff if (ents < 1) 1990162922Sariff return; 1991162922Sariff 1992162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 1993162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 1994169277Sariff prevcnid = 0; 1995162922Sariff 1996169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 1997169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 1998169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 1999169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2000169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2001169277Sariff 2002169277Sariff for (i = 0; i < ents; i += entnum) { 2003162922Sariff res = hdac_command(sc, 2004162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2005162922Sariff for (j = 0; j < entnum; j++) { 2006169277Sariff cnid = CONN_CNID(res, entnum, j); 2007169277Sariff if (cnid == 0) { 2008169277Sariff if (w->nconns < ents) 2009169277Sariff device_printf(sc->dev, 2010169277Sariff "%s: nid=%d WARNING: zero cnid " 2011169277Sariff "entnum=%d j=%d index=%d " 2012169277Sariff "entries=%d found=%d res=0x%08x\n", 2013169277Sariff __func__, nid, entnum, j, i, 2014169277Sariff ents, w->nconns, res); 2015169277Sariff else 2016169277Sariff goto getconns_out; 2017169277Sariff } 2018169277Sariff if (cnid < w->devinfo->startnode || 2019169277Sariff cnid >= w->devinfo->endnode) { 2020169277Sariff HDA_BOOTVERBOSE( 2021169277Sariff device_printf(sc->dev, 2022182999Smav "GHOST: nid=%d j=%d " 2023169277Sariff "entnum=%d index=%d res=0x%08x\n", 2024182999Smav nid, j, entnum, i, res); 2025169277Sariff ); 2026169277Sariff } 2027169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2028169277Sariff addcnid = cnid; 2029169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2030162922Sariff device_printf(sc->dev, 2031169277Sariff "%s: WARNING: Invalid child range " 2032169277Sariff "nid=%d index=%d j=%d entnum=%d " 2033169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2034169277Sariff __func__, nid, i, j, entnum, prevcnid, 2035169277Sariff cnid, res); 2036169277Sariff addcnid = cnid; 2037169277Sariff } else 2038169277Sariff addcnid = prevcnid + 1; 2039169277Sariff while (addcnid <= cnid) { 2040169277Sariff if (w->nconns > max) { 2041169277Sariff device_printf(sc->dev, 2042182999Smav "Adding %d (nid=%d): " 2043169277Sariff "Max connection reached! max=%d\n", 2044182999Smav addcnid, nid, max + 1); 2045169277Sariff goto getconns_out; 2046169277Sariff } 2047182999Smav w->connsenable[w->nconns] = 1; 2048169277Sariff w->conns[w->nconns++] = addcnid++; 2049162922Sariff } 2050169277Sariff prevcnid = cnid; 2051162922Sariff } 2052162922Sariff } 2053162922Sariff 2054169277Sariffgetconns_out: 2055169277Sariff return; 2056162922Sariff} 2057162922Sariff 2058162922Sariffstatic uint32_t 2059182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2060182999Smav{ 2061182999Smav char buf[256]; 2062182999Smav char *key, *value, *rest, *bad; 2063182999Smav int ival, i; 2064182999Smav 2065182999Smav strlcpy(buf, str, sizeof(buf)); 2066182999Smav rest = buf; 2067182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2068182999Smav value = strsep(&rest, " \t"); 2069182999Smav if (value == NULL) 2070182999Smav break; 2071182999Smav ival = strtol(value, &bad, 10); 2072182999Smav if (strcmp(key, "seq") == 0) { 2073182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2074182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2075182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2076182999Smav } else if (strcmp(key, "as") == 0) { 2077182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2078182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2079182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2080182999Smav } else if (strcmp(key, "misc") == 0) { 2081182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2082182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2083182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2084182999Smav } else if (strcmp(key, "color") == 0) { 2085182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2086182999Smav if (bad[0] == 0) { 2087182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2088182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2089182999Smav }; 2090182999Smav for (i = 0; i < 16; i++) { 2091182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2092182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2093182999Smav break; 2094182999Smav } 2095182999Smav } 2096182999Smav } else if (strcmp(key, "ctype") == 0) { 2097182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2098182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2099182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2100182999Smav } else if (strcmp(key, "device") == 0) { 2101182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2102182999Smav if (bad[0] == 0) { 2103182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2104182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2105182999Smav continue; 2106182999Smav }; 2107182999Smav for (i = 0; i < 16; i++) { 2108182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2109182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2110182999Smav break; 2111182999Smav } 2112182999Smav } 2113182999Smav } else if (strcmp(key, "loc") == 0) { 2114182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2115182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2116182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2117182999Smav } else if (strcmp(key, "conn") == 0) { 2118182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2119182999Smav if (bad[0] == 0) { 2120182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2121182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2122182999Smav continue; 2123182999Smav }; 2124182999Smav for (i = 0; i < 4; i++) { 2125182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2126182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2127182999Smav break; 2128182999Smav } 2129182999Smav } 2130182999Smav } 2131182999Smav } 2132182999Smav return (config); 2133182999Smav} 2134182999Smav 2135182999Smavstatic uint32_t 2136162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2137162922Sariff{ 2138162922Sariff struct hdac_softc *sc; 2139166965Sariff uint32_t config, orig, id; 2140162922Sariff nid_t cad, nid; 2141182999Smav char buf[32]; 2142182999Smav const char *res = NULL, *patch = NULL; 2143162922Sariff 2144162922Sariff sc = w->devinfo->codec->sc; 2145162922Sariff cad = w->devinfo->codec->cad; 2146162922Sariff nid = w->nid; 2147182999Smav id = hdac_codec_id(w->devinfo->codec); 2148162922Sariff 2149162922Sariff config = hdac_command(sc, 2150162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2151162922Sariff cad); 2152166965Sariff orig = config; 2153166965Sariff 2154182999Smav HDA_BOOTVERBOSE( 2155182999Smav hdac_dump_pin_config(w, orig); 2156182999Smav ); 2157182999Smav 2158182999Smav /* XXX: Old patches require complete review. 2159182999Smav * Now they may create more problem then solve due to 2160182999Smav * incorrect associations. 2161162965Sariff */ 2162165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2163165281Sariff switch (nid) { 2164165281Sariff case 26: 2165165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2166165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2167165281Sariff break; 2168165281Sariff case 27: 2169165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2170165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2171165281Sariff break; 2172167610Sariff default: 2173167610Sariff break; 2174165281Sariff } 2175165281Sariff } else if (id == HDA_CODEC_ALC880 && 2176162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2177162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2178162922Sariff /* 2179162965Sariff * Super broken BIOS 2180162922Sariff */ 2181162922Sariff switch (nid) { 2182162922Sariff case 24: /* MIC1 */ 2183162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2184162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2185162922Sariff break; 2186162922Sariff case 25: /* XXX MIC2 */ 2187162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2188162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2189162922Sariff break; 2190162922Sariff case 26: /* LINE1 */ 2191162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2192162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2193162922Sariff break; 2194162922Sariff case 27: /* XXX LINE2 */ 2195162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2196162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2197162922Sariff break; 2198162922Sariff case 28: /* CD */ 2199162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2200162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2201162922Sariff break; 2202162922Sariff } 2203166965Sariff } else if (id == HDA_CODEC_ALC883 && 2204172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2205172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2206166965Sariff switch (nid) { 2207166965Sariff case 25: 2208166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2209166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2210166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2211166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2212166965Sariff break; 2213169277Sariff case 28: 2214169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2215169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2216169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2217169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2218169277Sariff break; 2219166965Sariff } 2220166965Sariff } else if (id == HDA_CODEC_CXVENICE && sc->pci_subvendor == 2221166965Sariff HP_V3000_SUBVENDOR) { 2222166965Sariff switch (nid) { 2223166965Sariff case 18: 2224166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2225166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2226166965Sariff break; 2227166965Sariff case 20: 2228166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2229166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2230166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2231166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2232166965Sariff break; 2233167454Sariff case 21: 2234167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2235167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2236167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2237167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2238167454Sariff break; 2239166965Sariff } 2240169277Sariff } else if (id == HDA_CODEC_CXWAIKIKI && sc->pci_subvendor == 2241169277Sariff HP_DV5000_SUBVENDOR) { 2242169277Sariff switch (nid) { 2243169277Sariff case 20: 2244169277Sariff case 21: 2245169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2246169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2247169277Sariff break; 2248169277Sariff } 2249169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2250169277Sariff ASUS_W6F_SUBVENDOR) { 2251169277Sariff switch (nid) { 2252169277Sariff case 11: 2253169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2254169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2255169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2256169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2257169277Sariff break; 2258178324Sariff case 12: 2259178324Sariff case 14: 2260178324Sariff case 16: 2261178324Sariff case 31: 2262178324Sariff case 32: 2263178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2264178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2265178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2266178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2267178324Sariff break; 2268169277Sariff case 15: 2269169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2270169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2271169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2272169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2273169277Sariff break; 2274169277Sariff } 2275169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2276169277Sariff UNIWILL_9075_SUBVENDOR) { 2277169277Sariff switch (nid) { 2278169277Sariff case 15: 2279169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2280169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2281169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2282169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2283169277Sariff break; 2284169277Sariff } 2285182999Smav } 2286182999Smav 2287182999Smav /* New patches */ 2288182999Smav if (id == HDA_CODEC_AD1986A && 2289171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2290171141Sariff sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) { 2291169277Sariff switch (nid) { 2292182999Smav case 28: /* 5.1 out => 2.0 out + 2 inputs */ 2293182999Smav patch = "device=Line-in as=8 seq=1"; 2294169277Sariff break; 2295182999Smav case 29: 2296182999Smav patch = "device=Mic as=8 seq=2"; 2297169277Sariff break; 2298182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2299182999Smav patch = "as=8 seq=3"; 2300169277Sariff break; 2301182999Smav case 32: 2302182999Smav patch = "as=8 seq=4"; 2303182999Smav break; 2304182999Smav case 34: 2305182999Smav patch = "as=8 seq=5"; 2306182999Smav break; 2307182999Smav case 36: 2308182999Smav patch = "as=8 seq=6"; 2309182999Smav break; 2310169277Sariff } 2311182999Smav } else if (id == HDA_CODEC_ALC260 && 2312182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2313182999Smav switch (nid) { 2314182999Smav case 16: 2315182999Smav patch = "seq=15 device=Headphones"; 2316182999Smav break; 2317182999Smav } 2318174578Sariff } else if (id == HDA_CODEC_ALC268 && 2319174578Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) { 2320174578Sariff switch (nid) { 2321174578Sariff case 28: 2322182999Smav patch = "device=CD conn=fixed"; 2323174578Sariff break; 2324174578Sariff } 2325162922Sariff } 2326162922Sariff 2327182999Smav if (patch != NULL) 2328182999Smav config = hdac_widget_pin_patch(config, patch); 2329182999Smav 2330182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2331182999Smav if (resource_string_value(device_get_name(sc->dev), 2332182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2333182999Smav if (strncmp(res, "0x", 2) == 0) { 2334182999Smav config = strtol(res + 2, NULL, 16); 2335182999Smav } else { 2336182999Smav config = hdac_widget_pin_patch(config, res); 2337182999Smav } 2338182999Smav } 2339182999Smav 2340166965Sariff HDA_BOOTVERBOSE( 2341166965Sariff if (config != orig) 2342166965Sariff device_printf(sc->dev, 2343182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2344166965Sariff nid, orig, config); 2345166965Sariff ); 2346166965Sariff 2347162922Sariff return (config); 2348162922Sariff} 2349162922Sariff 2350166965Sariffstatic uint32_t 2351166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2352166965Sariff{ 2353166965Sariff struct hdac_softc *sc; 2354166965Sariff uint32_t caps, orig, id; 2355166965Sariff nid_t cad, nid; 2356166965Sariff 2357166965Sariff sc = w->devinfo->codec->sc; 2358166965Sariff cad = w->devinfo->codec->cad; 2359166965Sariff nid = w->nid; 2360182999Smav id = hdac_codec_id(w->devinfo->codec); 2361166965Sariff 2362166965Sariff caps = hdac_command(sc, 2363166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2364166965Sariff orig = caps; 2365166965Sariff 2366166965Sariff HDA_BOOTVERBOSE( 2367166965Sariff if (caps != orig) 2368166965Sariff device_printf(sc->dev, 2369182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2370166965Sariff nid, orig, caps); 2371166965Sariff ); 2372166965Sariff 2373166965Sariff return (caps); 2374166965Sariff} 2375166965Sariff 2376162922Sariffstatic void 2377162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2378162922Sariff{ 2379162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2380162922Sariff uint32_t config, pincap; 2381182999Smav const char *devstr, *connstr; 2382162922Sariff nid_t cad = w->devinfo->codec->cad; 2383162922Sariff nid_t nid = w->nid; 2384162922Sariff 2385162922Sariff config = hdac_widget_pin_getconfig(w); 2386162922Sariff w->wclass.pin.config = config; 2387162922Sariff 2388166965Sariff pincap = hdac_widget_pin_getcaps(w); 2389162922Sariff w->wclass.pin.cap = pincap; 2390162922Sariff 2391162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2392182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2393162922Sariff 2394162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2395162922Sariff w->param.eapdbtl = hdac_command(sc, 2396162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2397162922Sariff w->param.eapdbtl &= 0x7; 2398162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2399162922Sariff } else 2400162965Sariff w->param.eapdbtl = HDAC_INVALID; 2401162922Sariff 2402182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2403182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2404162922Sariff 2405182999Smav connstr = HDA_CONNS[(config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2406182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT]; 2407162922Sariff 2408162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2409162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2410162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2411162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 2412162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2413162922Sariff} 2414162922Sariff 2415182999Smavstatic uint32_t 2416182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2417182999Smav{ 2418182999Smav struct hdac_softc *sc; 2419182999Smav uint32_t caps, orig, id; 2420182999Smav nid_t cad, nid, beeper = -1; 2421182999Smav 2422182999Smav sc = w->devinfo->codec->sc; 2423182999Smav cad = w->devinfo->codec->cad; 2424182999Smav nid = w->nid; 2425182999Smav id = hdac_codec_id(w->devinfo->codec); 2426182999Smav 2427182999Smav caps = hdac_command(sc, 2428182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2429182999Smav cad); 2430182999Smav orig = caps; 2431182999Smav 2432182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2433182999Smav alone. Also most of BIOSes does not declare beeper pin. 2434182999Smav Change beeper pin node type to beeper to help parser. */ 2435182999Smav *waspin = 0; 2436182999Smav switch (id) { 2437182999Smav case HDA_CODEC_AD1988: 2438182999Smav case HDA_CODEC_AD1988B: 2439182999Smav beeper = 26; 2440182999Smav break; 2441182999Smav case HDA_CODEC_ALC260: 2442182999Smav beeper = 23; 2443182999Smav break; 2444182999Smav case HDA_CODEC_ALC262: 2445182999Smav case HDA_CODEC_ALC268: 2446182999Smav case HDA_CODEC_ALC880: 2447182999Smav case HDA_CODEC_ALC882: 2448182999Smav case HDA_CODEC_ALC883: 2449182999Smav case HDA_CODEC_ALC885: 2450182999Smav case HDA_CODEC_ALC888: 2451182999Smav case HDA_CODEC_ALC889: 2452182999Smav beeper = 29; 2453182999Smav break; 2454182999Smav } 2455182999Smav if (nid == beeper) { 2456182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2457182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2458182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2459182999Smav *waspin = 1; 2460182999Smav } 2461182999Smav 2462182999Smav HDA_BOOTVERBOSE( 2463182999Smav if (caps != orig) { 2464182999Smav device_printf(sc->dev, 2465182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2466182999Smav nid, orig, caps); 2467182999Smav } 2468182999Smav ); 2469182999Smav 2470182999Smav return (caps); 2471182999Smav} 2472182999Smav 2473162922Sariffstatic void 2474162922Sariffhdac_widget_parse(struct hdac_widget *w) 2475162922Sariff{ 2476162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2477162922Sariff uint32_t wcap, cap; 2478162922Sariff char *typestr; 2479162922Sariff nid_t cad = w->devinfo->codec->cad; 2480162922Sariff nid_t nid = w->nid; 2481162922Sariff 2482182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2483182999Smav 2484162922Sariff w->param.widget_cap = wcap; 2485162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2486162922Sariff 2487162922Sariff switch (w->type) { 2488162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2489162922Sariff typestr = "audio output"; 2490162922Sariff break; 2491162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2492162922Sariff typestr = "audio input"; 2493162922Sariff break; 2494162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2495162922Sariff typestr = "audio mixer"; 2496162922Sariff break; 2497162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2498162922Sariff typestr = "audio selector"; 2499162922Sariff break; 2500162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2501162922Sariff typestr = "pin"; 2502162922Sariff break; 2503162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2504162922Sariff typestr = "power widget"; 2505162922Sariff break; 2506162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2507162922Sariff typestr = "volume widget"; 2508162922Sariff break; 2509162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2510162922Sariff typestr = "beep widget"; 2511162922Sariff break; 2512162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2513162922Sariff typestr = "vendor widget"; 2514162922Sariff break; 2515162922Sariff default: 2516162922Sariff typestr = "unknown type"; 2517162922Sariff break; 2518162922Sariff } 2519162922Sariff 2520162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2521162922Sariff 2522162922Sariff hdac_widget_connection_parse(w); 2523162922Sariff 2524162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2525162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2526162922Sariff w->param.outamp_cap = 2527162922Sariff hdac_command(sc, 2528162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2529162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2530162922Sariff else 2531162922Sariff w->param.outamp_cap = 2532162922Sariff w->devinfo->function.audio.outamp_cap; 2533162922Sariff } else 2534162922Sariff w->param.outamp_cap = 0; 2535162922Sariff 2536162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2537162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2538162922Sariff w->param.inamp_cap = 2539162922Sariff hdac_command(sc, 2540162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2541162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2542162922Sariff else 2543162922Sariff w->param.inamp_cap = 2544162922Sariff w->devinfo->function.audio.inamp_cap; 2545162922Sariff } else 2546162922Sariff w->param.inamp_cap = 0; 2547162922Sariff 2548162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2549162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2550162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2551162922Sariff cap = hdac_command(sc, 2552162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2553162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2554162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2555162922Sariff w->devinfo->function.audio.supp_stream_formats; 2556162922Sariff cap = hdac_command(sc, 2557162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2558162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2559162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2560162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2561162922Sariff } else { 2562162922Sariff w->param.supp_stream_formats = 2563162922Sariff w->devinfo->function.audio.supp_stream_formats; 2564162922Sariff w->param.supp_pcm_size_rate = 2565162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2566162922Sariff } 2567162922Sariff } else { 2568162922Sariff w->param.supp_stream_formats = 0; 2569162922Sariff w->param.supp_pcm_size_rate = 0; 2570162922Sariff } 2571162922Sariff 2572162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2573162922Sariff hdac_widget_pin_parse(w); 2574162922Sariff} 2575162922Sariff 2576162922Sariffstatic struct hdac_widget * 2577162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2578162922Sariff{ 2579162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2580162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2581162922Sariff return (NULL); 2582162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2583162922Sariff} 2584162922Sariff 2585164614Sariffstatic __inline int 2586164614Sariffhda_poll_channel(struct hdac_chan *ch) 2587164614Sariff{ 2588164614Sariff uint32_t sz, delta; 2589164614Sariff volatile uint32_t ptr; 2590164614Sariff 2591171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2592164614Sariff return (0); 2593164614Sariff 2594164614Sariff sz = ch->blksz * ch->blkcnt; 2595169277Sariff if (ch->dmapos != NULL) 2596169277Sariff ptr = *(ch->dmapos); 2597169277Sariff else 2598169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2599169277Sariff ch->off + HDAC_SDLPIB); 2600164614Sariff ch->ptr = ptr; 2601164614Sariff ptr %= sz; 2602164614Sariff ptr &= ~(ch->blksz - 1); 2603164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2604164614Sariff 2605164614Sariff if (delta < ch->blksz) 2606164614Sariff return (0); 2607164614Sariff 2608164614Sariff ch->prevptr = ptr; 2609164614Sariff 2610164614Sariff return (1); 2611164614Sariff} 2612164614Sariff 2613162922Sariffstatic void 2614164614Sariffhda_poll_callback(void *arg) 2615164614Sariff{ 2616164614Sariff struct hdac_softc *sc = arg; 2617171141Sariff uint32_t trigger; 2618182999Smav int i, active = 0; 2619164614Sariff 2620164614Sariff if (sc == NULL) 2621164614Sariff return; 2622164614Sariff 2623164614Sariff hdac_lock(sc); 2624182999Smav if (sc->polling == 0) { 2625164614Sariff hdac_unlock(sc); 2626164614Sariff return; 2627164614Sariff } 2628164614Sariff 2629171141Sariff trigger = 0; 2630182999Smav for (i = 0; i < sc->num_chans; i++) { 2631182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2632182999Smav continue; 2633182999Smav active = 1; 2634182999Smav if (hda_poll_channel(&sc->chans[i])) 2635182999Smav trigger |= (1 << i); 2636182999Smav } 2637164614Sariff 2638164614Sariff /* XXX */ 2639182999Smav if (active) 2640182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2641182999Smav hda_poll_callback, sc); 2642164614Sariff 2643164614Sariff hdac_unlock(sc); 2644164614Sariff 2645182999Smav for (i = 0; i < sc->num_chans; i++) { 2646182999Smav if (trigger & (1 << i)) 2647182999Smav chn_intr(sc->chans[i].c); 2648182999Smav } 2649164614Sariff} 2650164614Sariff 2651164614Sariffstatic int 2652164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2653164614Sariff{ 2654164614Sariff struct hdac_rirb *rirb_base, *rirb; 2655164614Sariff struct hdac_codec *codec; 2656164614Sariff struct hdac_command_list *commands; 2657164614Sariff nid_t cad; 2658164614Sariff uint32_t resp; 2659164614Sariff uint8_t rirbwp; 2660171141Sariff int ret; 2661164614Sariff 2662164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2663164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2664169277Sariff#if 0 2665164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2666164614Sariff BUS_DMASYNC_POSTREAD); 2667169277Sariff#endif 2668164614Sariff 2669171141Sariff ret = 0; 2670171141Sariff 2671164614Sariff while (sc->rirb_rp != rirbwp) { 2672164614Sariff sc->rirb_rp++; 2673164614Sariff sc->rirb_rp %= sc->rirb_size; 2674164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2675164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2676164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2677164614Sariff sc->codecs[cad] == NULL) 2678164614Sariff continue; 2679164614Sariff resp = rirb->response; 2680164614Sariff codec = sc->codecs[cad]; 2681164614Sariff commands = codec->commands; 2682164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2683164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2684164614Sariff ((resp >> 26) & 0xffff); 2685164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2686164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2687164614Sariff codec->responses_received < commands->num_commands) 2688164614Sariff commands->responses[codec->responses_received++] = 2689164614Sariff resp; 2690164614Sariff ret++; 2691164614Sariff } 2692164614Sariff 2693164614Sariff return (ret); 2694164614Sariff} 2695164614Sariff 2696164614Sariffstatic int 2697164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2698164614Sariff{ 2699164614Sariff nid_t cad; 2700164614Sariff uint32_t tag; 2701164614Sariff int ret = 0; 2702164614Sariff 2703164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2704164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2705164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2706164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2707164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2708164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2709164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2710164614Sariff ret++; 2711164614Sariff } 2712164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2713164614Sariff } 2714164614Sariff 2715164614Sariff return (ret); 2716164614Sariff} 2717164614Sariff 2718164614Sariffstatic void 2719164614Sariffhdac_poll_callback(void *arg) 2720164614Sariff{ 2721164614Sariff struct hdac_softc *sc = arg; 2722164614Sariff if (sc == NULL) 2723164614Sariff return; 2724166796Sariff 2725164614Sariff hdac_lock(sc); 2726169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2727164614Sariff hdac_unlock(sc); 2728164614Sariff return; 2729164614Sariff } 2730171141Sariff if (hdac_rirb_flush(sc) != 0) 2731171141Sariff hdac_unsolq_flush(sc); 2732169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2733164614Sariff hdac_unlock(sc); 2734164614Sariff} 2735164614Sariff 2736164614Sariffstatic void 2737182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2738182999Smav{ 2739182999Smav int i, pollticks, min = 1000000; 2740182999Smav struct hdac_chan *ch; 2741182999Smav 2742182999Smav for (i = 0; i < sc->num_chans; i++) { 2743182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2744182999Smav continue; 2745182999Smav ch = &sc->chans[i]; 2746182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2747182999Smav ((uint64_t)sndbuf_getbps(ch->b) * 2748182999Smav sndbuf_getspd(ch->b)); 2749182999Smav pollticks >>= 1; 2750182999Smav if (pollticks > hz) 2751182999Smav pollticks = hz; 2752182999Smav if (pollticks < 1) { 2753182999Smav HDA_BOOTVERBOSE( 2754182999Smav device_printf(sc->dev, 2755182999Smav "%s: pollticks=%d < 1 !\n", 2756182999Smav __func__, pollticks); 2757182999Smav ); 2758182999Smav pollticks = 1; 2759182999Smav } 2760182999Smav if (min > pollticks) 2761182999Smav min = pollticks; 2762182999Smav } 2763182999Smav HDA_BOOTVERBOSE( 2764182999Smav device_printf(sc->dev, 2765182999Smav "%s: pollticks %d -> %d\n", 2766182999Smav __func__, sc->poll_ticks, min); 2767182999Smav ); 2768182999Smav sc->poll_ticks = min; 2769182999Smav if (min == 1000000) 2770182999Smav callout_stop(&sc->poll_hda); 2771182999Smav else 2772182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 2773182999Smav} 2774182999Smav 2775182999Smavstatic void 2776162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2777162922Sariff{ 2778162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2779162922Sariff uint32_t ctl; 2780162922Sariff 2781162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2782162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2783162922Sariff HDAC_SDCTL_RUN); 2784162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2785162922Sariff 2786171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 2787164614Sariff 2788182999Smav if (sc->polling != 0) 2789182999Smav hdac_poll_reinit(sc); 2790164614Sariff 2791182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2792182999Smav ctl &= ~(1 << (ch->off >> 5)); 2793182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2794162922Sariff} 2795162922Sariff 2796162922Sariffstatic void 2797162922Sariffhdac_stream_start(struct hdac_chan *ch) 2798162922Sariff{ 2799162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2800162922Sariff uint32_t ctl; 2801162922Sariff 2802182999Smav ch->flags |= HDAC_CHN_RUNNING; 2803162922Sariff 2804182999Smav if (sc->polling != 0) 2805182999Smav hdac_poll_reinit(sc); 2806182999Smav 2807182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2808182999Smav ctl |= 1 << (ch->off >> 5); 2809182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2810182999Smav 2811182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2812182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2813182999Smav HDAC_SDCTL_RUN; 2814162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2815162922Sariff} 2816162922Sariff 2817162922Sariffstatic void 2818162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2819162922Sariff{ 2820162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2821162922Sariff int timeout = 1000; 2822162922Sariff int to = timeout; 2823162922Sariff uint32_t ctl; 2824162922Sariff 2825162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2826162922Sariff ctl |= HDAC_SDCTL_SRST; 2827162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2828162922Sariff do { 2829162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2830162922Sariff if (ctl & HDAC_SDCTL_SRST) 2831162922Sariff break; 2832162922Sariff DELAY(10); 2833162922Sariff } while (--to); 2834162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2835162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2836162922Sariff } 2837162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2838162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2839162922Sariff to = timeout; 2840162922Sariff do { 2841162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2842162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2843162922Sariff break; 2844162922Sariff DELAY(10); 2845162922Sariff } while (--to); 2846163057Sariff if (ctl & HDAC_SDCTL_SRST) 2847162922Sariff device_printf(sc->dev, "can't reset!\n"); 2848162922Sariff} 2849162922Sariff 2850162922Sariffstatic void 2851162922Sariffhdac_stream_setid(struct hdac_chan *ch) 2852162922Sariff{ 2853162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2854162922Sariff uint32_t ctl; 2855162922Sariff 2856162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 2857162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 2858162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 2859162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 2860162922Sariff} 2861162922Sariff 2862162922Sariffstatic void 2863162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 2864162922Sariff{ 2865162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2866164614Sariff struct hdac_bdle *bdle; 2867162922Sariff uint64_t addr; 2868164614Sariff uint32_t blksz, blkcnt; 2869162922Sariff int i; 2870162922Sariff 2871162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 2872164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 2873162922Sariff 2874182999Smav blksz = ch->blksz; 2875182999Smav blkcnt = ch->blkcnt; 2876164614Sariff 2877164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 2878162922Sariff bdle->addrl = (uint32_t)addr; 2879162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 2880164614Sariff bdle->len = blksz; 2881182999Smav bdle->ioc = 1; 2882164614Sariff addr += blksz; 2883162922Sariff } 2884162922Sariff 2885164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 2886164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 2887162922Sariff addr = ch->bdl_dma.dma_paddr; 2888162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 2889162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 2890169277Sariff if (ch->dmapos != NULL && 2891169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 2892169277Sariff addr = sc->pos_dma.dma_paddr; 2893169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 2894169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 2895169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 2896169277Sariff } 2897162922Sariff} 2898162922Sariff 2899162922Sariffstatic int 2900162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 2901162922Sariff{ 2902162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2903162922Sariff int rc; 2904162922Sariff 2905162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 2906162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 2907162922Sariff if (rc) { 2908162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 2909162922Sariff return (rc); 2910162922Sariff } 2911162922Sariff 2912162922Sariff return (0); 2913162922Sariff} 2914162922Sariff 2915162922Sariffstatic void 2916162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 2917162922Sariff int index, int lmute, int rmute, 2918162922Sariff int left, int right, int dir) 2919162922Sariff{ 2920162922Sariff uint16_t v = 0; 2921162922Sariff 2922162922Sariff if (sc == NULL) 2923162922Sariff return; 2924162922Sariff 2925162922Sariff if (left != right || lmute != rmute) { 2926162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 2927162922Sariff (lmute << 7) | left; 2928162922Sariff hdac_command(sc, 2929164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2930162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 2931162922Sariff (rmute << 7) | right; 2932162922Sariff } else 2933162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 2934162922Sariff (lmute << 7) | left; 2935162922Sariff 2936162922Sariff hdac_command(sc, 2937162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2938162922Sariff} 2939162922Sariff 2940162922Sariffstatic void 2941162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 2942162922Sariff int left, int right) 2943162922Sariff{ 2944162922Sariff struct hdac_softc *sc; 2945162922Sariff nid_t nid, cad; 2946162922Sariff int lmute, rmute; 2947162922Sariff 2948162922Sariff sc = ctl->widget->devinfo->codec->sc; 2949162922Sariff cad = ctl->widget->devinfo->codec->cad; 2950162922Sariff nid = ctl->widget->nid; 2951162922Sariff 2952182999Smav /* Save new values if valid. */ 2953182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 2954182999Smav ctl->muted = mute; 2955182999Smav if (left != HDA_AMP_VOL_DEFAULT) 2956182999Smav ctl->left = left; 2957182999Smav if (right != HDA_AMP_VOL_DEFAULT) 2958182999Smav ctl->right = right; 2959182999Smav /* Prepare effective values */ 2960182999Smav if (ctl->forcemute) { 2961182999Smav lmute = 1; 2962182999Smav rmute = 1; 2963182999Smav left = 0; 2964182999Smav right = 0; 2965182999Smav } else { 2966162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 2967162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 2968182999Smav left = ctl->left; 2969182999Smav right = ctl->right; 2970162922Sariff } 2971182999Smav /* Apply effective values */ 2972162922Sariff if (ctl->dir & HDA_CTL_OUT) 2973162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2974162922Sariff lmute, rmute, left, right, 0); 2975162922Sariff if (ctl->dir & HDA_CTL_IN) 2976182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2977162922Sariff lmute, rmute, left, right, 1); 2978162922Sariff} 2979162922Sariff 2980162922Sariffstatic void 2981162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 2982162922Sariff{ 2983162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 2984162922Sariff return; 2985162922Sariff hdac_command(w->devinfo->codec->sc, 2986162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 2987162922Sariff w->nid, index), w->devinfo->codec->cad); 2988162922Sariff w->selconn = index; 2989162922Sariff} 2990162922Sariff 2991162922Sariff 2992162922Sariff/**************************************************************************** 2993162922Sariff * uint32_t hdac_command_sendone_internal 2994162922Sariff * 2995162922Sariff * Wrapper function that sends only one command to a given codec 2996162922Sariff ****************************************************************************/ 2997162922Sariffstatic uint32_t 2998162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 2999162922Sariff{ 3000162922Sariff struct hdac_command_list cl; 3001162965Sariff uint32_t response = HDAC_INVALID; 3002162922Sariff 3003163057Sariff if (!hdac_lockowned(sc)) 3004162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3005162922Sariff cl.num_commands = 1; 3006162922Sariff cl.verbs = &verb; 3007162922Sariff cl.responses = &response; 3008162922Sariff 3009162922Sariff hdac_command_send_internal(sc, &cl, cad); 3010162922Sariff 3011162922Sariff return (response); 3012162922Sariff} 3013162922Sariff 3014162922Sariff/**************************************************************************** 3015162922Sariff * hdac_command_send_internal 3016162922Sariff * 3017162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3018162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3019162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3020162922Sariff * if any. 3021162922Sariff ****************************************************************************/ 3022162922Sariffstatic void 3023162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3024162922Sariff struct hdac_command_list *commands, nid_t cad) 3025162922Sariff{ 3026162922Sariff struct hdac_codec *codec; 3027162922Sariff int corbrp; 3028162922Sariff uint32_t *corb; 3029162922Sariff int timeout; 3030162922Sariff int retry = 10; 3031164614Sariff struct hdac_rirb *rirb_base; 3032162922Sariff 3033164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3034164614Sariff commands->num_commands < 1) 3035162922Sariff return; 3036162922Sariff 3037162922Sariff codec = sc->codecs[cad]; 3038162922Sariff codec->commands = commands; 3039162922Sariff codec->responses_received = 0; 3040162922Sariff codec->verbs_sent = 0; 3041162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3042162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3043162922Sariff 3044162922Sariff do { 3045162922Sariff if (codec->verbs_sent != commands->num_commands) { 3046162922Sariff /* Queue as many verbs as possible */ 3047162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3048169277Sariff#if 0 3049162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3050162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3051169277Sariff#endif 3052162922Sariff while (codec->verbs_sent != commands->num_commands && 3053162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3054162922Sariff sc->corb_wp++; 3055162922Sariff sc->corb_wp %= sc->corb_size; 3056162922Sariff corb[sc->corb_wp] = 3057162922Sariff commands->verbs[codec->verbs_sent++]; 3058162922Sariff } 3059162922Sariff 3060162922Sariff /* Send the verbs to the codecs */ 3061169277Sariff#if 0 3062162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3063162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3064169277Sariff#endif 3065162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3066162922Sariff } 3067162922Sariff 3068162922Sariff timeout = 1000; 3069164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3070162922Sariff DELAY(10); 3071162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3072164614Sariff codec->responses_received != commands->num_commands) && --retry); 3073162922Sariff 3074162922Sariff if (retry == 0) 3075162922Sariff device_printf(sc->dev, 3076164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3077164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3078164614Sariff codec->responses_received); 3079162922Sariff 3080164614Sariff codec->commands = NULL; 3081164614Sariff codec->responses_received = 0; 3082162922Sariff codec->verbs_sent = 0; 3083162922Sariff 3084164614Sariff hdac_unsolq_flush(sc); 3085162922Sariff} 3086162922Sariff 3087162922Sariff 3088162922Sariff/**************************************************************************** 3089162922Sariff * Device Methods 3090162922Sariff ****************************************************************************/ 3091162922Sariff 3092162922Sariff/**************************************************************************** 3093162922Sariff * int hdac_probe(device_t) 3094162922Sariff * 3095162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3096162922Sariff * match using the subclass of the device. 3097162922Sariff ****************************************************************************/ 3098162922Sariffstatic int 3099162922Sariffhdac_probe(device_t dev) 3100162922Sariff{ 3101162922Sariff int i, result; 3102163257Sariff uint32_t model; 3103163257Sariff uint16_t class, subclass; 3104162922Sariff char desc[64]; 3105162922Sariff 3106162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3107162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3108162922Sariff class = pci_get_class(dev); 3109162922Sariff subclass = pci_get_subclass(dev); 3110162922Sariff 3111162922Sariff bzero(desc, sizeof(desc)); 3112162922Sariff result = ENXIO; 3113162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3114162922Sariff if (hdac_devices[i].model == model) { 3115162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3116162922Sariff result = BUS_PROBE_DEFAULT; 3117162922Sariff break; 3118162922Sariff } 3119163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3120162922Sariff class == PCIC_MULTIMEDIA && 3121162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3122162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3123162922Sariff result = BUS_PROBE_GENERIC; 3124162922Sariff break; 3125162922Sariff } 3126162922Sariff } 3127162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3128162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3129162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3130162922Sariff result = BUS_PROBE_GENERIC; 3131162922Sariff } 3132162922Sariff if (result != ENXIO) { 3133162922Sariff strlcat(desc, " High Definition Audio Controller", 3134162922Sariff sizeof(desc)); 3135162922Sariff device_set_desc_copy(dev, desc); 3136162922Sariff } 3137162922Sariff 3138162922Sariff return (result); 3139162922Sariff} 3140162922Sariff 3141162922Sariffstatic void * 3142162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3143162922Sariff struct pcm_channel *c, int dir) 3144162922Sariff{ 3145182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3146182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3147162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3148162922Sariff struct hdac_chan *ch; 3149182999Smav int i, ord = 0, chid; 3150162922Sariff 3151162922Sariff hdac_lock(sc); 3152182999Smav 3153182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3154182999Smav ch = &sc->chans[chid]; 3155182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3156182999Smav if (ch->dir == sc->chans[i].dir) 3157182999Smav ord++; 3158182999Smav } 3159162922Sariff if (dir == PCMDIR_PLAY) { 3160182999Smav ch->off = (sc->num_iss + ord) << 5; 3161162922Sariff } else { 3162182999Smav ch->off = ord << 5; 3163162922Sariff } 3164182999Smav 3165162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3166162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3167162922Sariff ch->pcmrates[0] = 48000; 3168162922Sariff ch->pcmrates[1] = 0; 3169162922Sariff } 3170169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3171169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3172169277Sariff (sc->streamcnt * 8)); 3173169277Sariff else 3174169277Sariff ch->dmapos = NULL; 3175169277Sariff ch->sid = ++sc->streamcnt; 3176169277Sariff ch->dir = dir; 3177162922Sariff ch->b = b; 3178162922Sariff ch->c = c; 3179182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3180182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3181162922Sariff hdac_unlock(sc); 3182162922Sariff 3183162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3184162922Sariff ch->blkcnt = 0; 3185162922Sariff return (NULL); 3186162922Sariff } 3187162922Sariff 3188169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3189171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3190182999Smav pdevinfo->chan_size) != 0) 3191162922Sariff return (NULL); 3192162922Sariff 3193162922Sariff return (ch); 3194162922Sariff} 3195162922Sariff 3196162922Sariffstatic int 3197162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3198162922Sariff{ 3199162922Sariff struct hdac_chan *ch = data; 3200162922Sariff int i; 3201162922Sariff 3202162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3203162922Sariff if (format == ch->caps.fmtlist[i]) { 3204162922Sariff ch->fmt = format; 3205162922Sariff return (0); 3206162922Sariff } 3207162922Sariff } 3208162922Sariff 3209162922Sariff return (EINVAL); 3210162922Sariff} 3211162922Sariff 3212162922Sariffstatic int 3213162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3214162922Sariff{ 3215162922Sariff struct hdac_chan *ch = data; 3216164614Sariff uint32_t spd = 0, threshold; 3217162922Sariff int i; 3218162922Sariff 3219162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3220162922Sariff spd = ch->pcmrates[i]; 3221164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3222164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3223164614Sariff if (speed < threshold) 3224162922Sariff break; 3225162922Sariff } 3226162922Sariff 3227164614Sariff if (spd == 0) /* impossible */ 3228162922Sariff ch->spd = 48000; 3229162922Sariff else 3230162922Sariff ch->spd = spd; 3231162922Sariff 3232162922Sariff return (ch->spd); 3233162922Sariff} 3234162922Sariff 3235162922Sariffstatic void 3236162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3237162922Sariff{ 3238162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3239182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3240173817Sariff struct hdac_widget *w; 3241182999Smav int i, chn, totalchn, c; 3242162922Sariff nid_t cad = ch->devinfo->codec->cad; 3243182999Smav uint16_t fmt, dfmt; 3244162922Sariff 3245183097Smav HDA_BOOTHVERBOSE( 3246182999Smav device_printf(ch->pdevinfo->dev, 3247182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3248182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3249182999Smav ch->fmt, ch->spd); 3250182999Smav ); 3251162922Sariff fmt = 0; 3252162922Sariff if (ch->fmt & AFMT_S16_LE) 3253162922Sariff fmt |= ch->bit16 << 4; 3254162922Sariff else if (ch->fmt & AFMT_S32_LE) 3255162922Sariff fmt |= ch->bit32 << 4; 3256162922Sariff else 3257162922Sariff fmt |= 1 << 4; 3258162922Sariff 3259162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3260162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3261162922Sariff fmt |= hda_rate_tab[i].base; 3262162922Sariff fmt |= hda_rate_tab[i].mul; 3263162922Sariff fmt |= hda_rate_tab[i].div; 3264162922Sariff break; 3265162922Sariff } 3266162922Sariff } 3267162922Sariff 3268182999Smav if (ch->fmt & (AFMT_STEREO | AFMT_AC3)) { 3269162922Sariff fmt |= 1; 3270173817Sariff totalchn = 2; 3271173817Sariff } else 3272173817Sariff totalchn = 1; 3273162922Sariff 3274162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3275182999Smav 3276182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3277182999Smav if (ch->fmt & AFMT_AC3) 3278182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3279162922Sariff 3280173817Sariff chn = 0; 3281162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3282173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3283173817Sariff if (w == NULL) 3284173817Sariff continue; 3285182999Smav 3286182999Smav if (as->hpredir >= 0 && i == as->pincnt) 3287182999Smav chn = 0; 3288183097Smav HDA_BOOTHVERBOSE( 3289182999Smav device_printf(ch->pdevinfo->dev, 3290182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3291182999Smav "fmt=0x%04x, dfmt=0x%04x\n", 3292162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3293182999Smav ch->io[i], fmt, dfmt); 3294162922Sariff ); 3295162922Sariff hdac_command(sc, 3296162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3297182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3298174025Sariff hdac_command(sc, 3299182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3300174025Sariff cad); 3301182999Smav } 3302182999Smav /* If HP redirection is enabled, but failed to use same 3303182999Smav DAC make last DAC one to duplicate first one. */ 3304182999Smav if (as->hpredir >= 0 && i == as->pincnt) { 3305182999Smav c = (ch->sid << 4); 3306182999Smav } else if (chn >= totalchn) { 3307182999Smav /* This is until OSS will support multichannel. 3308182999Smav Should be: c = 0; to disable unused DAC */ 3309182999Smav c = (ch->sid << 4); 3310182999Smav }else { 3311182999Smav c = (ch->sid << 4) | chn; 3312182999Smav } 3313182999Smav hdac_command(sc, 3314182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3315173817Sariff chn += 3316173817Sariff HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ? 3317173817Sariff 2 : 1; 3318162922Sariff } 3319162922Sariff} 3320162922Sariff 3321162922Sariffstatic int 3322167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3323167648Sariff uint32_t blksz, uint32_t blkcnt) 3324162922Sariff{ 3325162922Sariff struct hdac_chan *ch = data; 3326164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3327162922Sariff 3328167648Sariff blksz &= HDA_BLK_ALIGN; 3329162922Sariff 3330167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3331167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3332167648Sariff if (blksz < HDA_BLK_MIN) 3333167648Sariff blksz = HDA_BLK_MIN; 3334167648Sariff if (blkcnt > HDA_BDL_MAX) 3335167648Sariff blkcnt = HDA_BDL_MAX; 3336167648Sariff if (blkcnt < HDA_BDL_MIN) 3337167648Sariff blkcnt = HDA_BDL_MIN; 3338164614Sariff 3339167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3340167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3341167648Sariff blkcnt >>= 1; 3342167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3343167648Sariff blksz >>= 1; 3344167648Sariff else 3345167648Sariff break; 3346167648Sariff } 3347167648Sariff 3348164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3349167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3350167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3351164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3352167648Sariff __func__, blksz, blkcnt); 3353164614Sariff 3354164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3355167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3356164614Sariff 3357167648Sariff return (1); 3358167648Sariff} 3359167648Sariff 3360167648Sariffstatic int 3361167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3362167648Sariff{ 3363167648Sariff struct hdac_chan *ch = data; 3364167648Sariff 3365182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3366167648Sariff 3367162922Sariff return (ch->blksz); 3368162922Sariff} 3369162922Sariff 3370162922Sariffstatic void 3371162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3372162922Sariff{ 3373162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3374182999Smav struct hdac_widget *w; 3375162922Sariff nid_t cad = devinfo->codec->cad; 3376162922Sariff int i; 3377162922Sariff 3378162922Sariff hdac_stream_stop(ch); 3379162922Sariff 3380162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3381182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3382182999Smav if (w == NULL) 3383182999Smav continue; 3384182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3385182999Smav hdac_command(sc, 3386182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3387182999Smav cad); 3388182999Smav } 3389162922Sariff hdac_command(sc, 3390162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3391162922Sariff 0), cad); 3392162922Sariff } 3393162922Sariff} 3394162922Sariff 3395162922Sariffstatic void 3396162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3397162922Sariff{ 3398162922Sariff ch->ptr = 0; 3399162922Sariff ch->prevptr = 0; 3400162922Sariff hdac_stream_stop(ch); 3401162922Sariff hdac_stream_reset(ch); 3402162922Sariff hdac_bdl_setup(ch); 3403162922Sariff hdac_stream_setid(ch); 3404162922Sariff hdac_stream_setup(ch); 3405162922Sariff hdac_stream_start(ch); 3406162922Sariff} 3407162922Sariff 3408162922Sariffstatic int 3409162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3410162922Sariff{ 3411162922Sariff struct hdac_chan *ch = data; 3412162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3413162922Sariff 3414170521Sariff if (!PCMTRIG_COMMON(go)) 3415170521Sariff return (0); 3416170521Sariff 3417162922Sariff hdac_lock(sc); 3418162922Sariff switch (go) { 3419162922Sariff case PCMTRIG_START: 3420162922Sariff hdac_channel_start(sc, ch); 3421162922Sariff break; 3422162922Sariff case PCMTRIG_STOP: 3423162922Sariff case PCMTRIG_ABORT: 3424162922Sariff hdac_channel_stop(sc, ch); 3425162922Sariff break; 3426167610Sariff default: 3427167610Sariff break; 3428162922Sariff } 3429162922Sariff hdac_unlock(sc); 3430162922Sariff 3431162922Sariff return (0); 3432162922Sariff} 3433162922Sariff 3434162922Sariffstatic int 3435162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3436162922Sariff{ 3437162922Sariff struct hdac_chan *ch = data; 3438162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3439162922Sariff uint32_t ptr; 3440162922Sariff 3441162922Sariff hdac_lock(sc); 3442164614Sariff if (sc->polling != 0) 3443164614Sariff ptr = ch->ptr; 3444169277Sariff else if (ch->dmapos != NULL) 3445169277Sariff ptr = *(ch->dmapos); 3446164614Sariff else 3447164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3448162922Sariff hdac_unlock(sc); 3449162922Sariff 3450164614Sariff /* 3451164614Sariff * Round to available space and force 128 bytes aligment. 3452164614Sariff */ 3453164614Sariff ptr %= ch->blksz * ch->blkcnt; 3454167648Sariff ptr &= HDA_BLK_ALIGN; 3455162922Sariff 3456162922Sariff return (ptr); 3457162922Sariff} 3458162922Sariff 3459162922Sariffstatic struct pcmchan_caps * 3460162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3461162922Sariff{ 3462162922Sariff return (&((struct hdac_chan *)data)->caps); 3463162922Sariff} 3464162922Sariff 3465162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3466162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3467162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3468162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3469162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3470167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3471162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3472162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3473162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3474162922Sariff { 0, 0 } 3475162922Sariff}; 3476162922SariffCHANNEL_DECLARE(hdac_channel); 3477162922Sariff 3478162922Sariffstatic int 3479162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3480162922Sariff{ 3481182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3482182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3483162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3484162922Sariff struct hdac_widget *w, *cw; 3485162922Sariff struct hdac_audio_ctl *ctl; 3486162922Sariff uint32_t mask, recmask, id; 3487162922Sariff int i, j, softpcmvol; 3488162922Sariff 3489162922Sariff hdac_lock(sc); 3490162922Sariff 3491182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3492182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3493182999Smav pdevinfo->left[i] = 100; 3494182999Smav pdevinfo->right[i] = 100; 3495182999Smav } 3496182999Smav 3497162922Sariff mask = 0; 3498162922Sariff recmask = 0; 3499182999Smav id = hdac_codec_id(devinfo->codec); 3500162922Sariff 3501182999Smav /* Declate EAPD as ogain control. */ 3502182999Smav if (pdevinfo->play >= 0) { 3503182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3504182999Smav w = hdac_widget_get(devinfo, i); 3505182999Smav if (w == NULL || w->enable == 0) 3506182999Smav continue; 3507182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3508182999Smav w->param.eapdbtl == HDAC_INVALID || 3509182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3510182999Smav continue; 3511182999Smav mask |= SOUND_MASK_OGAIN; 3512162922Sariff break; 3513162922Sariff } 3514162922Sariff } 3515162922Sariff 3516182999Smav /* Declare volume controls assigned to this association. */ 3517162922Sariff i = 0; 3518162922Sariff ctl = NULL; 3519162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3520182999Smav if (ctl->enable == 0) 3521162922Sariff continue; 3522182999Smav if ((pdevinfo->play >= 0 && 3523182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3524182999Smav (pdevinfo->rec >= 0 && 3525182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3526182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3527182999Smav mask |= ctl->ossmask; 3528162922Sariff } 3529162922Sariff 3530182999Smav /* Declare record sources available to this association. */ 3531182999Smav if (pdevinfo->rec >= 0) { 3532182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3533182999Smav for (i = 0; ch->io[i] != -1; i++) { 3534182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3535182999Smav if (w == NULL || w->enable == 0) 3536182999Smav continue; 3537182999Smav for (j = 0; j < w->nconns; j++) { 3538182999Smav if (w->connsenable[j] == 0) 3539162922Sariff continue; 3540182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3541182999Smav if (cw == NULL || cw->enable == 0) 3542165992Sariff continue; 3543182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3544182999Smav cw->bindas != -2) 3545165992Sariff continue; 3546182999Smav recmask |= cw->ossmask; 3547165992Sariff } 3548182999Smav } 3549182999Smav } 3550182999Smav 3551182999Smav /* Declare soft PCM and master volume if needed. */ 3552182999Smav if (pdevinfo->play >= 0) { 3553182999Smav ctl = NULL; 3554182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3555182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3556182999Smav softpcmvol = 1; 3557182999Smav mask |= SOUND_MASK_PCM; 3558162922Sariff } else { 3559182999Smav softpcmvol = 0; 3560182999Smav i = 0; 3561182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3562182999Smav if (ctl->enable == 0) 3563162922Sariff continue; 3564182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3565182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3566162922Sariff continue; 3567182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3568182999Smav continue; 3569182999Smav if (ctl->step > 0) 3570182999Smav break; 3571162922Sariff } 3572162922Sariff } 3573182999Smav 3574182999Smav if (softpcmvol == 1 || ctl == NULL) { 3575182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3576182999Smav HDA_BOOTVERBOSE( 3577182999Smav device_printf(pdevinfo->dev, 3578182999Smav "%s Soft PCM volume\n", 3579182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3580182999Smav ); 3581182999Smav } 3582182999Smav 3583182999Smav if ((mask & SOUND_MASK_VOLUME) == 0) { 3584182999Smav mask |= SOUND_MASK_VOLUME; 3585182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3586182999Smav SOUND_MASK_PCM); 3587182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3588182999Smav SOUND_MIXER_NONE); 3589182999Smav HDA_BOOTVERBOSE( 3590182999Smav device_printf(pdevinfo->dev, 3591182999Smav "Forcing master volume with PCM\n"); 3592182999Smav ); 3593182999Smav } 3594162922Sariff } 3595162922Sariff 3596169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3597169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3598162922Sariff 3599162922Sariff mix_setrecdevs(m, recmask); 3600162922Sariff mix_setdevs(m, mask); 3601162922Sariff 3602162922Sariff hdac_unlock(sc); 3603162922Sariff 3604162922Sariff return (0); 3605162922Sariff} 3606162922Sariff 3607162922Sariffstatic int 3608162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3609162922Sariff unsigned left, unsigned right) 3610162922Sariff{ 3611182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3612182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3613162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3614162922Sariff struct hdac_widget *w; 3615162922Sariff struct hdac_audio_ctl *ctl; 3616182999Smav uint32_t mute; 3617182999Smav int lvol, rvol; 3618182999Smav int i, j; 3619162922Sariff 3620162922Sariff hdac_lock(sc); 3621182999Smav /* Save new values. */ 3622182999Smav pdevinfo->left[dev] = left; 3623182999Smav pdevinfo->right[dev] = right; 3624182999Smav 3625182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3626162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3627163257Sariff uint32_t orig; 3628182999Smav w = NULL; 3629182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3630182999Smav w = hdac_widget_get(devinfo, i); 3631182999Smav if (w == NULL || w->enable == 0) 3632182999Smav continue; 3633182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3634182999Smav w->param.eapdbtl == HDAC_INVALID) 3635182999Smav continue; 3636182999Smav break; 3637162922Sariff } 3638182999Smav if (i >= devinfo->endnode) { 3639162922Sariff hdac_unlock(sc); 3640162922Sariff return (-1); 3641162922Sariff } 3642163257Sariff orig = w->param.eapdbtl; 3643163432Sariff if (left == 0) 3644162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3645162922Sariff else 3646162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3647163257Sariff if (orig != w->param.eapdbtl) { 3648163432Sariff uint32_t val; 3649163432Sariff 3650163432Sariff val = w->param.eapdbtl; 3651163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3652163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3653163257Sariff hdac_command(sc, 3654163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3655163432Sariff w->nid, val), devinfo->codec->cad); 3656163257Sariff } 3657162922Sariff hdac_unlock(sc); 3658162922Sariff return (left | (left << 8)); 3659162922Sariff } 3660162922Sariff 3661182999Smav /* Recalculate all controls related to this OSS device. */ 3662162922Sariff i = 0; 3663162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3664182999Smav if (ctl->enable == 0 || 3665162922Sariff !(ctl->ossmask & (1 << dev))) 3666162922Sariff continue; 3667182999Smav if (!((pdevinfo->play >= 0 && 3668182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3669182999Smav (pdevinfo->rec >= 0 && 3670182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3671182999Smav ctl->widget->bindas == -2)) 3672182999Smav continue; 3673182999Smav 3674182999Smav lvol = 100; 3675182999Smav rvol = 100; 3676182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3677182999Smav if (ctl->ossmask & (1 << j)) { 3678182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3679182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3680162922Sariff } 3681162922Sariff } 3682182999Smav mute = (left == 0) ? HDA_AMP_MUTE_LEFT : 0; 3683182999Smav mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3684182999Smav lvol = (lvol * ctl->step + 50) / 100; 3685182999Smav rvol = (rvol * ctl->step + 50) / 100; 3686162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3687162922Sariff } 3688162922Sariff hdac_unlock(sc); 3689162922Sariff 3690162922Sariff return (left | (right << 8)); 3691162922Sariff} 3692162922Sariff 3693182999Smav/* 3694182999Smav * Commutate specified record source. 3695182999Smav */ 3696182999Smavstatic uint32_t 3697182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3698162922Sariff{ 3699182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3700162922Sariff struct hdac_widget *w, *cw; 3701182999Smav struct hdac_audio_ctl *ctl; 3702182999Smav char buf[64]; 3703182999Smav int i, muted; 3704182999Smav uint32_t res = 0; 3705162922Sariff 3706182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3707182999Smav return (0); 3708182999Smav 3709182999Smav w = hdac_widget_get(devinfo, nid); 3710182999Smav if (w == NULL || w->enable == 0) 3711182999Smav return (0); 3712182999Smav 3713182999Smav for (i = 0; i < w->nconns; i++) { 3714182999Smav if (w->connsenable[i] == 0) 3715182999Smav continue; 3716182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3717182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3718182999Smav continue; 3719182999Smav /* Call recursively to trace signal to it's source if needed. */ 3720182999Smav if ((src & cw->ossmask) != 0) { 3721182999Smav if (cw->ossdev < 0) { 3722182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 3723182999Smav w->conns[i], depth + 1); 3724182999Smav } else { 3725182999Smav res |= cw->ossmask; 3726182999Smav } 3727182999Smav } 3728182999Smav /* We have two special cases: mixers and others (selectors). */ 3729182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 3730182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 3731182999Smav w->nid, HDA_CTL_IN, i, 1); 3732182999Smav if (ctl == NULL) 3733182999Smav continue; 3734182999Smav /* If we have input control on this node mute them 3735182999Smav * according to requested sources. */ 3736182999Smav muted = (src & cw->ossmask) ? 0 : 1; 3737182999Smav if (muted != ctl->forcemute) { 3738182999Smav ctl->forcemute = muted; 3739182999Smav hdac_audio_ctl_amp_set(ctl, 3740182999Smav HDA_AMP_MUTE_DEFAULT, 3741182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 3742182999Smav } 3743183097Smav HDA_BOOTHVERBOSE( 3744182999Smav device_printf(pdevinfo->dev, 3745182999Smav "Recsel (%s): nid %d source %d %s\n", 3746182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3747182999Smav src, buf, sizeof(buf)), 3748182999Smav nid, i, muted?"mute":"unmute"); 3749182999Smav ); 3750182999Smav } else { 3751182999Smav if (w->nconns == 1) 3752182999Smav break; 3753182999Smav if ((src & cw->ossmask) == 0) 3754182999Smav continue; 3755182999Smav /* If we found requested source - select it and exit. */ 3756182999Smav hdac_widget_connection_select(w, i); 3757183097Smav HDA_BOOTHVERBOSE( 3758182999Smav device_printf(pdevinfo->dev, 3759182999Smav "Recsel (%s): nid %d source %d select\n", 3760182999Smav hdac_audio_ctl_ossmixer_mask2allname( 3761182999Smav src, buf, sizeof(buf)), 3762182999Smav nid, i); 3763182999Smav ); 3764162922Sariff break; 3765162922Sariff } 3766162922Sariff } 3767182999Smav return (res); 3768182999Smav} 3769162922Sariff 3770182999Smavstatic uint32_t 3771182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3772182999Smav{ 3773182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3774182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3775182999Smav struct hdac_widget *w; 3776182999Smav struct hdac_softc *sc = devinfo->codec->sc; 3777182999Smav struct hdac_chan *ch; 3778182999Smav int i; 3779182999Smav uint32_t ret = 0xffffffff; 3780182999Smav 3781162922Sariff hdac_lock(sc); 3782162922Sariff 3783182999Smav /* Commutate requested recsrc for each ADC. */ 3784182999Smav ch = &sc->chans[pdevinfo->rec]; 3785182999Smav for (i = 0; ch->io[i] != -1; i++) { 3786182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3787162965Sariff if (w == NULL || w->enable == 0) 3788162922Sariff continue; 3789182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 3790162922Sariff } 3791162922Sariff 3792162922Sariff hdac_unlock(sc); 3793162922Sariff 3794182999Smav return ((ret == 0xffffffff)? 0 : ret); 3795162922Sariff} 3796162922Sariff 3797162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3798162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3799162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3800162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3801162922Sariff { 0, 0 } 3802162922Sariff}; 3803162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3804162922Sariff 3805171141Sariffstatic void 3806171141Sariffhdac_unsolq_task(void *context, int pending) 3807171141Sariff{ 3808171141Sariff struct hdac_softc *sc; 3809171141Sariff 3810171141Sariff sc = (struct hdac_softc *)context; 3811171141Sariff 3812171141Sariff hdac_lock(sc); 3813171141Sariff hdac_unsolq_flush(sc); 3814171141Sariff hdac_unlock(sc); 3815171141Sariff} 3816171141Sariff 3817162922Sariff/**************************************************************************** 3818162922Sariff * int hdac_attach(device_t) 3819162922Sariff * 3820162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3821162922Sariff * when this function is called. Setup everything that doesn't require 3822162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3823162922Sariff ****************************************************************************/ 3824162922Sariffstatic int 3825162922Sariffhdac_attach(device_t dev) 3826162922Sariff{ 3827162922Sariff struct hdac_softc *sc; 3828162922Sariff int result; 3829169277Sariff int i; 3830169277Sariff uint16_t vendor; 3831169277Sariff uint8_t v; 3832162922Sariff 3833184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 3834182999Smav 3835182999Smav sc = device_get_softc(dev); 3836163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 3837162922Sariff sc->dev = dev; 3838163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 3839163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 3840169277Sariff vendor = pci_get_vendor(dev); 3841162922Sariff 3842165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 3843165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 3844165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 3845165281Sariff } 3846165281Sariff 3847164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 3848164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 3849169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 3850164614Sariff 3851171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 3852171141Sariff 3853182999Smav sc->poll_ticks = 1000000; 3854169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 3855169277Sariff if (resource_int_value(device_get_name(dev), 3856169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 3857164614Sariff sc->polling = 1; 3858164614Sariff else 3859164614Sariff sc->polling = 0; 3860164614Sariff 3861162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 3862162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 3863162922Sariff 0, /* boundary */ 3864162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 3865162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 3866162922Sariff NULL, /* filtfunc */ 3867162922Sariff NULL, /* fistfuncarg */ 3868182999Smav HDA_BUFSZ_MAX, /* maxsize */ 3869162922Sariff 1, /* nsegments */ 3870182999Smav HDA_BUFSZ_MAX, /* maxsegsz */ 3871162922Sariff 0, /* flags */ 3872162922Sariff NULL, /* lockfunc */ 3873162922Sariff NULL, /* lockfuncarg */ 3874162922Sariff &sc->chan_dmat); /* dmat */ 3875162922Sariff if (result != 0) { 3876169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 3877162922Sariff __func__, result); 3878163057Sariff snd_mtxfree(sc->lock); 3879162922Sariff free(sc, M_DEVBUF); 3880162922Sariff return (ENXIO); 3881162922Sariff } 3882162922Sariff 3883162922Sariff 3884162922Sariff sc->hdabus = NULL; 3885162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 3886162922Sariff sc->codecs[i] = NULL; 3887162922Sariff 3888162922Sariff pci_enable_busmaster(dev); 3889162922Sariff 3890169277Sariff if (vendor == INTEL_VENDORID) { 3891169277Sariff /* TCSEL -> TC0 */ 3892169277Sariff v = pci_read_config(dev, 0x44, 1); 3893169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 3894183097Smav HDA_BOOTHVERBOSE( 3895169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 3896169277Sariff pci_read_config(dev, 0x44, 1)); 3897169277Sariff ); 3898169277Sariff } 3899169277Sariff 3900178155Sariff#ifdef HDAC_MSI_ENABLED 3901171330Sariff if (resource_int_value(device_get_name(dev), 3902171330Sariff device_get_unit(dev), "msi", &i) == 0 && i != 0 && 3903171330Sariff pci_msi_count(dev) == 1) 3904171330Sariff sc->flags |= HDAC_F_MSI; 3905171330Sariff else 3906171330Sariff#endif 3907171330Sariff sc->flags &= ~HDAC_F_MSI; 3908171330Sariff 3909169277Sariff#if defined(__i386__) || defined(__amd64__) 3910171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3911169277Sariff 3912169277Sariff if (resource_int_value(device_get_name(dev), 3913169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 3914169277Sariff#else 3915171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3916169277Sariff#endif 3917169277Sariff /* 3918169277Sariff * Try to enable PCIe snoop to avoid messing around with 3919169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 3920169277Sariff * config is pretty much vendor specific, there are no 3921169277Sariff * general solutions on how to enable it, forcing us (even 3922169277Sariff * Microsoft) to enable uncacheable or write combined DMA 3923169277Sariff * by default. 3924169277Sariff * 3925169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 3926169277Sariff */ 3927169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 3928169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 3929169277Sariff continue; 3930171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3931169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 3932169277Sariff break; 3933169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3934169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 3935169277Sariff hdac_pcie_snoop[i].enable) 3936169277Sariff break; 3937169277Sariff v &= hdac_pcie_snoop[i].mask; 3938169277Sariff v |= hdac_pcie_snoop[i].enable; 3939169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 3940169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3941169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 3942169277Sariff hdac_pcie_snoop[i].enable) { 3943169277Sariff HDA_BOOTVERBOSE( 3944169277Sariff device_printf(dev, 3945169277Sariff "WARNING: Failed to enable PCIe " 3946169277Sariff "snoop!\n"); 3947169277Sariff ); 3948169277Sariff#if defined(__i386__) || defined(__amd64__) 3949171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3950169277Sariff#endif 3951169277Sariff } 3952169277Sariff break; 3953169277Sariff } 3954169277Sariff#if defined(__i386__) || defined(__amd64__) 3955169277Sariff } 3956169277Sariff#endif 3957169277Sariff 3958183097Smav HDA_BOOTHVERBOSE( 3959169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 3960171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 3961171330Sariff "Uncacheable" : "PCIe snoop", vendor); 3962169277Sariff ); 3963169277Sariff 3964162922Sariff /* Allocate resources */ 3965162922Sariff result = hdac_mem_alloc(sc); 3966162922Sariff if (result != 0) 3967163057Sariff goto hdac_attach_fail; 3968162922Sariff result = hdac_irq_alloc(sc); 3969162922Sariff if (result != 0) 3970163057Sariff goto hdac_attach_fail; 3971162922Sariff 3972162922Sariff /* Get Capabilities */ 3973162922Sariff result = hdac_get_capabilities(sc); 3974162922Sariff if (result != 0) 3975163057Sariff goto hdac_attach_fail; 3976162922Sariff 3977162922Sariff /* Allocate CORB and RIRB dma memory */ 3978162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 3979162922Sariff sc->corb_size * sizeof(uint32_t)); 3980162922Sariff if (result != 0) 3981163057Sariff goto hdac_attach_fail; 3982162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 3983162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 3984162922Sariff if (result != 0) 3985163057Sariff goto hdac_attach_fail; 3986162922Sariff 3987162922Sariff /* Quiesce everything */ 3988183097Smav HDA_BOOTHVERBOSE( 3989182999Smav device_printf(dev, "Reset controller...\n"); 3990182999Smav ); 3991182999Smav hdac_reset(sc, 1); 3992162922Sariff 3993162922Sariff /* Initialize the CORB and RIRB */ 3994162922Sariff hdac_corb_init(sc); 3995162922Sariff hdac_rirb_init(sc); 3996162922Sariff 3997162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 3998162922Sariff sc->intrhook.ich_func = hdac_attach2; 3999162922Sariff sc->intrhook.ich_arg = (void *)sc; 4000162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4001162922Sariff sc->intrhook.ich_func = NULL; 4002162922Sariff hdac_attach2((void *)sc); 4003162922Sariff } 4004162922Sariff 4005163057Sariff return (0); 4006162922Sariff 4007163057Sariffhdac_attach_fail: 4008162922Sariff hdac_irq_free(sc); 4009169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4010169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4011162922Sariff hdac_mem_free(sc); 4012162922Sariff snd_mtxfree(sc->lock); 4013163057Sariff free(sc, M_DEVBUF); 4014162922Sariff 4015163057Sariff return (ENXIO); 4016162922Sariff} 4017162922Sariff 4018162922Sariffstatic void 4019162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4020162922Sariff{ 4021182999Smav struct hdac_codec *codec = devinfo->codec; 4022182999Smav struct hdac_softc *sc = codec->sc; 4023162922Sariff struct hdac_widget *w; 4024162922Sariff uint32_t res; 4025162922Sariff int i; 4026162922Sariff nid_t cad, nid; 4027162922Sariff 4028162922Sariff cad = devinfo->codec->cad; 4029162922Sariff nid = devinfo->nid; 4030162922Sariff 4031162922Sariff res = hdac_command(sc, 4032169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4033169277Sariff devinfo->function.audio.gpio = res; 4034169277Sariff 4035163057Sariff HDA_BOOTVERBOSE( 4036183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4037183097Smav "NumGPIO=%d NumGPO=%d " 4038169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4039183097Smav devinfo->function.audio.gpio, 4040169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4041169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4042169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4043169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4044169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4045162922Sariff ); 4046162922Sariff 4047162922Sariff res = hdac_command(sc, 4048162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4049162922Sariff cad); 4050162922Sariff devinfo->function.audio.supp_stream_formats = res; 4051162922Sariff 4052162922Sariff res = hdac_command(sc, 4053162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4054162922Sariff cad); 4055162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4056162922Sariff 4057162922Sariff res = hdac_command(sc, 4058162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4059162922Sariff cad); 4060162922Sariff devinfo->function.audio.outamp_cap = res; 4061162922Sariff 4062162922Sariff res = hdac_command(sc, 4063162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4064162922Sariff cad); 4065162922Sariff devinfo->function.audio.inamp_cap = res; 4066162922Sariff 4067162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4068162922Sariff w = hdac_widget_get(devinfo, i); 4069162922Sariff if (w == NULL) 4070162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4071162922Sariff else { 4072162922Sariff w->devinfo = devinfo; 4073162922Sariff w->nid = i; 4074162922Sariff w->enable = 1; 4075162922Sariff w->selconn = -1; 4076162922Sariff w->pflags = 0; 4077182999Smav w->ossdev = -1; 4078182999Smav w->bindas = -1; 4079162965Sariff w->param.eapdbtl = HDAC_INVALID; 4080162922Sariff hdac_widget_parse(w); 4081162922Sariff } 4082162922Sariff } 4083162922Sariff} 4084162922Sariff 4085162922Sariffstatic void 4086162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4087162922Sariff{ 4088162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4089162922Sariff struct hdac_audio_ctl *ctls; 4090162922Sariff struct hdac_widget *w, *cw; 4091162922Sariff int i, j, cnt, max, ocap, icap; 4092163057Sariff int mute, offset, step, size; 4093162922Sariff 4094162922Sariff /* XXX This is redundant */ 4095162922Sariff max = 0; 4096162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4097162922Sariff w = hdac_widget_get(devinfo, i); 4098162922Sariff if (w == NULL || w->enable == 0) 4099162922Sariff continue; 4100162922Sariff if (w->param.outamp_cap != 0) 4101162922Sariff max++; 4102162922Sariff if (w->param.inamp_cap != 0) { 4103162922Sariff switch (w->type) { 4104162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4105162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4106162922Sariff for (j = 0; j < w->nconns; j++) { 4107162922Sariff cw = hdac_widget_get(devinfo, 4108162922Sariff w->conns[j]); 4109162922Sariff if (cw == NULL || cw->enable == 0) 4110162922Sariff continue; 4111162922Sariff max++; 4112162922Sariff } 4113162922Sariff break; 4114162922Sariff default: 4115162922Sariff max++; 4116162922Sariff break; 4117162922Sariff } 4118162922Sariff } 4119162922Sariff } 4120162922Sariff 4121162922Sariff devinfo->function.audio.ctlcnt = max; 4122162922Sariff 4123162922Sariff if (max < 1) 4124162922Sariff return; 4125162922Sariff 4126162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4127162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4128162922Sariff 4129162922Sariff if (ctls == NULL) { 4130162922Sariff /* Blekh! */ 4131162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4132162922Sariff devinfo->function.audio.ctlcnt = 0; 4133162922Sariff return; 4134162922Sariff } 4135162922Sariff 4136162922Sariff cnt = 0; 4137162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4138162922Sariff if (cnt >= max) { 4139162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4140162922Sariff __func__); 4141162922Sariff break; 4142162922Sariff } 4143162922Sariff w = hdac_widget_get(devinfo, i); 4144162922Sariff if (w == NULL || w->enable == 0) 4145162922Sariff continue; 4146162922Sariff ocap = w->param.outamp_cap; 4147162922Sariff icap = w->param.inamp_cap; 4148162922Sariff if (ocap != 0) { 4149163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4150163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4151163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4152163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4153163057Sariff /*if (offset > step) { 4154163057Sariff HDA_BOOTVERBOSE( 4155163057Sariff device_printf(sc->dev, 4156182999Smav "BUGGY outamp: nid=%d " 4157163057Sariff "[offset=%d > step=%d]\n", 4158163057Sariff w->nid, offset, step); 4159163057Sariff ); 4160163057Sariff offset = step; 4161163057Sariff }*/ 4162162922Sariff ctls[cnt].enable = 1; 4163162922Sariff ctls[cnt].widget = w; 4164163057Sariff ctls[cnt].mute = mute; 4165163057Sariff ctls[cnt].step = step; 4166163057Sariff ctls[cnt].size = size; 4167163057Sariff ctls[cnt].offset = offset; 4168163057Sariff ctls[cnt].left = offset; 4169163057Sariff ctls[cnt].right = offset; 4170182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4171182999Smav w->waspin) 4172182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4173182999Smav else 4174182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4175162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4176162922Sariff } 4177162922Sariff 4178162922Sariff if (icap != 0) { 4179163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4180163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4181163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4182163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4183163057Sariff /*if (offset > step) { 4184163057Sariff HDA_BOOTVERBOSE( 4185163057Sariff device_printf(sc->dev, 4186182999Smav "BUGGY inamp: nid=%d " 4187163057Sariff "[offset=%d > step=%d]\n", 4188163057Sariff w->nid, offset, step); 4189163057Sariff ); 4190163057Sariff offset = step; 4191163057Sariff }*/ 4192162922Sariff switch (w->type) { 4193162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4194162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4195162922Sariff for (j = 0; j < w->nconns; j++) { 4196162922Sariff if (cnt >= max) { 4197162922Sariff device_printf(sc->dev, 4198162922Sariff "%s: Ctl overflow!\n", 4199162922Sariff __func__); 4200162922Sariff break; 4201162922Sariff } 4202162922Sariff cw = hdac_widget_get(devinfo, 4203162922Sariff w->conns[j]); 4204162922Sariff if (cw == NULL || cw->enable == 0) 4205162922Sariff continue; 4206162922Sariff ctls[cnt].enable = 1; 4207162922Sariff ctls[cnt].widget = w; 4208162922Sariff ctls[cnt].childwidget = cw; 4209162922Sariff ctls[cnt].index = j; 4210163057Sariff ctls[cnt].mute = mute; 4211163057Sariff ctls[cnt].step = step; 4212163057Sariff ctls[cnt].size = size; 4213163057Sariff ctls[cnt].offset = offset; 4214163057Sariff ctls[cnt].left = offset; 4215163057Sariff ctls[cnt].right = offset; 4216182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4217162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4218162922Sariff } 4219162922Sariff break; 4220162922Sariff default: 4221162922Sariff if (cnt >= max) { 4222162922Sariff device_printf(sc->dev, 4223162922Sariff "%s: Ctl overflow!\n", 4224162922Sariff __func__); 4225162922Sariff break; 4226162922Sariff } 4227162922Sariff ctls[cnt].enable = 1; 4228162922Sariff ctls[cnt].widget = w; 4229163057Sariff ctls[cnt].mute = mute; 4230163057Sariff ctls[cnt].step = step; 4231163057Sariff ctls[cnt].size = size; 4232163057Sariff ctls[cnt].offset = offset; 4233163057Sariff ctls[cnt].left = offset; 4234163057Sariff ctls[cnt].right = offset; 4235182999Smav if (w->type == 4236182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4237182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4238182999Smav else 4239182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4240162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4241162922Sariff break; 4242162922Sariff } 4243162922Sariff } 4244162922Sariff } 4245162922Sariff 4246162922Sariff devinfo->function.audio.ctl = ctls; 4247162922Sariff} 4248162922Sariff 4249182999Smavstatic void 4250182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4251182999Smav{ 4252182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4253182999Smav struct hdac_audio_as *as; 4254182999Smav struct hdac_widget *w; 4255182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4256182999Smav 4257182999Smav /* XXX This is redundant */ 4258182999Smav max = 0; 4259182999Smav for (j = 0; j < 16; j++) { 4260182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4261182999Smav w = hdac_widget_get(devinfo, i); 4262182999Smav if (w == NULL || w->enable == 0) 4263182999Smav continue; 4264182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4265182999Smav continue; 4266182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4267182999Smav != j) 4268182999Smav continue; 4269182999Smav max++; 4270182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4271182999Smav break; 4272182999Smav } 4273182999Smav } 4274182999Smav 4275182999Smav devinfo->function.audio.ascnt = max; 4276182999Smav 4277182999Smav if (max < 1) 4278182999Smav return; 4279182999Smav 4280182999Smav as = (struct hdac_audio_as *)malloc( 4281182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4282182999Smav 4283182999Smav if (as == NULL) { 4284182999Smav /* Blekh! */ 4285182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4286182999Smav devinfo->function.audio.ascnt = 0; 4287182999Smav return; 4288182999Smav } 4289182999Smav 4290182999Smav for (i = 0; i < max; i++) { 4291182999Smav as[i].hpredir = -1; 4292182999Smav as[i].chan = -1; 4293182999Smav } 4294182999Smav 4295182999Smav /* Scan associations skipping as=0. */ 4296182999Smav cnt = 0; 4297182999Smav for (j = 1; j < 16; j++) { 4298182999Smav first = 16; 4299182999Smav hpredir = 0; 4300182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4301182999Smav w = hdac_widget_get(devinfo, i); 4302182999Smav if (w == NULL || w->enable == 0) 4303182999Smav continue; 4304182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4305182999Smav continue; 4306182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4307182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4308182999Smav if (assoc != j) { 4309182999Smav continue; 4310182999Smav } 4311182999Smav KASSERT(cnt < max, 4312182999Smav ("%s: Associations owerflow (%d of %d)", 4313182999Smav __func__, cnt, max)); 4314182999Smav type = w->wclass.pin.config & 4315182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4316182999Smav /* Get pin direction. */ 4317182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4318182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4319182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4320182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4321182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4322182999Smav dir = HDA_CTL_OUT; 4323182999Smav else 4324182999Smav dir = HDA_CTL_IN; 4325182999Smav /* If this is a first pin - create new association. */ 4326182999Smav if (as[cnt].pincnt == 0) { 4327182999Smav as[cnt].enable = 1; 4328182999Smav as[cnt].index = j; 4329182999Smav as[cnt].dir = dir; 4330182999Smav } 4331182999Smav if (seq < first) 4332182999Smav first = seq; 4333182999Smav /* Check association correctness. */ 4334182999Smav if (as[cnt].pins[seq] != 0) { 4335182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4336182999Smav "in association %d! Disabling association.\n", 4337182999Smav __func__, seq, w->nid, j); 4338182999Smav as[cnt].enable = 0; 4339182999Smav } 4340182999Smav if (dir != as[cnt].dir) { 4341182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4342182999Smav "direction for association %d! Disabling " 4343182999Smav "association.\n", 4344182999Smav __func__, w->nid, j); 4345182999Smav as[cnt].enable = 0; 4346182999Smav } 4347182999Smav /* Headphones with seq=15 may mean redirection. */ 4348182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4349182999Smav seq == 15) 4350182999Smav hpredir = 1; 4351182999Smav as[cnt].pins[seq] = w->nid; 4352182999Smav as[cnt].pincnt++; 4353182999Smav /* Association 15 is a multiple unassociated pins. */ 4354182999Smav if (j == 15) 4355182999Smav cnt++; 4356182999Smav } 4357182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4358182999Smav if (hpredir && as[cnt].pincnt > 1) 4359182999Smav as[cnt].hpredir = first; 4360182999Smav cnt++; 4361182999Smav } 4362182999Smav } 4363182999Smav HDA_BOOTVERBOSE( 4364182999Smav device_printf(sc->dev, 4365183097Smav "%d associations found:\n", max); 4366182999Smav for (i = 0; i < max; i++) { 4367182999Smav device_printf(sc->dev, 4368182999Smav "Association %d (%d) %s%s:\n", 4369182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4370182999Smav as[i].enable?"":" (disabled)"); 4371182999Smav for (j = 0; j < 16; j++) { 4372182999Smav if (as[i].pins[j] == 0) 4373182999Smav continue; 4374182999Smav device_printf(sc->dev, 4375183097Smav " Pin nid=%d seq=%d\n", 4376182999Smav as[i].pins[j], j); 4377182999Smav } 4378182999Smav } 4379182999Smav ); 4380182999Smav 4381182999Smav devinfo->function.audio.as = as; 4382182999Smav} 4383182999Smav 4384162965Sariffstatic const struct { 4385162965Sariff uint32_t model; 4386162965Sariff uint32_t id; 4387162965Sariff uint32_t set, unset; 4388162965Sariff} hdac_quirks[] = { 4389163057Sariff /* 4390163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4391163057Sariff * on few codecs (especially ALC880) seems broken or 4392163057Sariff * perhaps unsupported. 4393163057Sariff */ 4394163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4395169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4396162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4397165039Sariff HDA_QUIRK_GPIO0, 0 }, 4398178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4399178155Sariff HDA_QUIRK_GPIO0, 0 }, 4400162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4401165039Sariff HDA_QUIRK_GPIO0, 0 }, 4402165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4403165281Sariff HDA_QUIRK_GPIO0, 0 }, 4404167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4405167623Sariff HDA_QUIRK_GPIO0, 0 }, 4406169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4407169277Sariff HDA_QUIRK_GPIO0, 0 }, 4408163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4409163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4410178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4411163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4412169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4413169277Sariff HDA_QUIRK_OVREF, 0 }, 4414169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4415169277Sariff HDA_QUIRK_OVREF, 0 }, 4416169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4417169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4418165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4419165281Sariff HDA_QUIRK_GPIO1, 0 }, 4420164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4421182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4422164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4423164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4424173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4425173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4426165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4427165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4428183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4429180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4430183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4431178155Sariff HDA_QUIRK_GPIO0, 0 }, 4432169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4433169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4434170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4435170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4436162965Sariff { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 4437182999Smav 0, HDA_QUIRK_FORCESTEREO } 4438162965Sariff}; 4439162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4440162965Sariff 4441162922Sariffstatic void 4442162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4443162922Sariff{ 4444162922Sariff struct hdac_widget *w; 4445162965Sariff uint32_t id, subvendor; 4446162922Sariff int i; 4447162922Sariff 4448182999Smav id = hdac_codec_id(devinfo->codec); 4449163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4450163057Sariff 4451162922Sariff /* 4452163057Sariff * Quirks 4453162922Sariff */ 4454163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4455163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4456163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4457163057Sariff continue; 4458163057Sariff if (hdac_quirks[i].set != 0) 4459163057Sariff devinfo->function.audio.quirks |= 4460163057Sariff hdac_quirks[i].set; 4461163057Sariff if (hdac_quirks[i].unset != 0) 4462163057Sariff devinfo->function.audio.quirks &= 4463163057Sariff ~(hdac_quirks[i].unset); 4464163057Sariff } 4465163057Sariff 4466162922Sariff switch (id) { 4467166965Sariff case HDA_CODEC_ALC883: 4468166965Sariff /* 4469166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4470166965Sariff * Clear vref cap for jack connectivity. 4471166965Sariff */ 4472166965Sariff w = hdac_widget_get(devinfo, 24); 4473166965Sariff if (w != NULL && w->enable != 0 && w->type == 4474166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4475166965Sariff (w->wclass.pin.config & 4476166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4477166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4478166965Sariff w->wclass.pin.cap &= ~( 4479166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4480166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4481166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4482166965Sariff w = hdac_widget_get(devinfo, 25); 4483166965Sariff if (w != NULL && w->enable != 0 && w->type == 4484166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4485166965Sariff (w->wclass.pin.config & 4486166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4487166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4488166965Sariff w->wclass.pin.cap &= ~( 4489166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4490166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4491166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4492166965Sariff /* 4493166965Sariff * nid: 26 = Line-in, leave it alone. 4494166965Sariff */ 4495166965Sariff break; 4496162922Sariff case HDA_CODEC_AD1986A: 4497182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4498178155Sariff /* 4499178155Sariff * This is just plain ridiculous.. There 4500178155Sariff * are several A8 series that share the same 4501178155Sariff * pci id but works differently (EAPD). 4502178155Sariff */ 4503178155Sariff w = hdac_widget_get(devinfo, 26); 4504178155Sariff if (w != NULL && w->type == 4505178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4506178155Sariff (w->wclass.pin.config & 4507178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4508178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4509178155Sariff devinfo->function.audio.quirks &= 4510178155Sariff ~HDA_QUIRK_EAPDINV; 4511169277Sariff } 4512162922Sariff break; 4513184230Smav case HDA_CODEC_AD1981HD: 4514184230Smav /* 4515184230Smav * This codec has very unusual design with several 4516184254Smav * points inappropriate for the present parser. 4517184230Smav */ 4518184230Smav /* Disable recording from mono playback mix. */ 4519184230Smav w = hdac_widget_get(devinfo, 21); 4520184230Smav if (w != NULL) 4521184230Smav w->connsenable[3] = 0; 4522184230Smav /* Disable rear to front mic mixer, use separately. */ 4523184230Smav w = hdac_widget_get(devinfo, 31); 4524184230Smav if (w != NULL) 4525184230Smav w->enable = 0; 4526184230Smav /* Disable playback mixer, use direct bypass. */ 4527184230Smav w = hdac_widget_get(devinfo, 14); 4528184230Smav if (w != NULL) 4529184230Smav w->enable = 0; 4530184230Smav break; 4531182999Smav } 4532182999Smav} 4533182999Smav 4534182999Smav/* 4535182999Smav * Trace path from DAC to pin. 4536182999Smav */ 4537182999Smavstatic nid_t 4538182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4539182999Smav int dupseq, int min, int only, int depth) 4540182999Smav{ 4541182999Smav struct hdac_widget *w; 4542182999Smav int i, im = -1; 4543182999Smav nid_t m = 0, ret; 4544182999Smav 4545182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4546182999Smav return (0); 4547182999Smav w = hdac_widget_get(devinfo, nid); 4548182999Smav if (w == NULL || w->enable == 0) 4549182999Smav return (0); 4550183097Smav HDA_BOOTHVERBOSE( 4551182999Smav if (!only) { 4552182999Smav device_printf(devinfo->codec->sc->dev, 4553182999Smav " %*stracing via nid %d\n", 4554182999Smav depth + 1, "", w->nid); 4555169277Sariff } 4556182999Smav ); 4557182999Smav /* Use only unused widgets */ 4558182999Smav if (w->bindas >= 0 && w->bindas != as) { 4559183097Smav HDA_BOOTHVERBOSE( 4560182999Smav if (!only) { 4561182999Smav device_printf(devinfo->codec->sc->dev, 4562182999Smav " %*snid %d busy by association %d\n", 4563182999Smav depth + 1, "", w->nid, w->bindas); 4564182999Smav } 4565182999Smav ); 4566182999Smav return (0); 4567182999Smav } 4568182999Smav if (dupseq < 0) { 4569182999Smav if (w->bindseqmask != 0) { 4570183097Smav HDA_BOOTHVERBOSE( 4571182999Smav if (!only) { 4572182999Smav device_printf(devinfo->codec->sc->dev, 4573182999Smav " %*snid %d busy by seqmask %x\n", 4574182999Smav depth + 1, "", w->nid, w->bindseqmask); 4575182999Smav } 4576182999Smav ); 4577182999Smav return (0); 4578169277Sariff } 4579182999Smav } else { 4580182999Smav /* If this is headphones - allow duplicate first pin. */ 4581182999Smav if (w->bindseqmask != 0 && 4582182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4583183097Smav HDA_BOOTHVERBOSE( 4584182999Smav device_printf(devinfo->codec->sc->dev, 4585182999Smav " %*snid %d busy by seqmask %x\n", 4586182999Smav depth + 1, "", w->nid, w->bindseqmask); 4587182999Smav ); 4588182999Smav return (0); 4589169277Sariff } 4590182999Smav } 4591182999Smav 4592182999Smav switch (w->type) { 4593182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4594182999Smav /* Do not traverse input. AD1988 has digital monitor 4595182999Smav for which we are not ready. */ 4596169277Sariff break; 4597182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4598182999Smav /* If we are tracing HP take only dac of first pin. */ 4599182999Smav if ((only == 0 || only == w->nid) && 4600182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4601182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4602182999Smav m = w->nid; 4603178155Sariff break; 4604182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4605182999Smav if (depth > 0) 4606169277Sariff break; 4607182999Smav /* Fall */ 4608182999Smav default: 4609182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4610182999Smav for (i = 0; i < w->nconns; i++) { 4611182999Smav if (w->connsenable[i] == 0) 4612162922Sariff continue; 4613182999Smav if (w->selconn != -1 && w->selconn != i) 4614162922Sariff continue; 4615182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4616182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4617182999Smav if (m == 0 || ret < m) { 4618182999Smav m = ret; 4619182999Smav im = i; 4620182999Smav } 4621182999Smav if (only || dupseq >= 0) 4622182999Smav break; 4623182999Smav } 4624162922Sariff } 4625182999Smav if (m && only && ((w->nconns > 1 && 4626182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4627182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4628182999Smav w->selconn = im; 4629162922Sariff break; 4630182999Smav } 4631182999Smav if (m && only) { 4632182999Smav w->bindas = as; 4633182999Smav w->bindseqmask |= (1 << seq); 4634182999Smav } 4635183097Smav HDA_BOOTHVERBOSE( 4636182999Smav if (!only) { 4637182999Smav device_printf(devinfo->codec->sc->dev, 4638182999Smav " %*snid %d returned %d\n", 4639182999Smav depth + 1, "", w->nid, m); 4640182999Smav } 4641182999Smav ); 4642182999Smav return (m); 4643182999Smav} 4644162922Sariff 4645182999Smav/* 4646182999Smav * Trace path from widget to ADC. 4647182999Smav */ 4648182999Smavstatic nid_t 4649182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4650182999Smav int only, int depth) 4651182999Smav{ 4652182999Smav struct hdac_widget *w, *wc; 4653182999Smav int i, j; 4654182999Smav nid_t res = 0; 4655182999Smav 4656182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4657182999Smav return (0); 4658182999Smav w = hdac_widget_get(devinfo, nid); 4659182999Smav if (w == NULL || w->enable == 0) 4660182999Smav return (0); 4661183097Smav HDA_BOOTHVERBOSE( 4662182999Smav device_printf(devinfo->codec->sc->dev, 4663182999Smav " %*stracing via nid %d\n", 4664182999Smav depth + 1, "", w->nid); 4665182999Smav ); 4666182999Smav /* Use only unused widgets */ 4667182999Smav if (w->bindas >= 0 && w->bindas != as) { 4668183097Smav HDA_BOOTHVERBOSE( 4669182999Smav device_printf(devinfo->codec->sc->dev, 4670182999Smav " %*snid %d busy by association %d\n", 4671182999Smav depth + 1, "", w->nid, w->bindas); 4672182999Smav ); 4673182999Smav return (0); 4674182999Smav } 4675182999Smav 4676182999Smav switch (w->type) { 4677182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4678182999Smav /* If we are tracing HP take only dac of first pin. */ 4679182999Smav if (only == w->nid) 4680182999Smav res = 1; 4681162922Sariff break; 4682182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4683182999Smav if (depth > 0) 4684182999Smav break; 4685182999Smav /* Fall */ 4686182999Smav default: 4687182999Smav /* Try to find reachable ADCs with specified nid. */ 4688182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4689182999Smav wc = hdac_widget_get(devinfo, j); 4690182999Smav if (wc == NULL || wc->enable == 0) 4691182999Smav continue; 4692182999Smav for (i = 0; i < wc->nconns; i++) { 4693182999Smav if (wc->connsenable[i] == 0) 4694182999Smav continue; 4695182999Smav if (wc->conns[i] != nid) 4696182999Smav continue; 4697182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 4698182999Smav j, only, depth + 1) != 0) { 4699182999Smav res = 1; 4700182999Smav if (((wc->nconns > 1 && 4701182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 4702182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 4703182999Smav wc->selconn == -1) 4704182999Smav wc->selconn = i; 4705182999Smav } 4706182999Smav } 4707169277Sariff } 4708169277Sariff break; 4709162922Sariff } 4710182999Smav if (res) { 4711182999Smav w->bindas = as; 4712182999Smav w->bindseqmask |= (1 << seq); 4713182999Smav } 4714183097Smav HDA_BOOTHVERBOSE( 4715182999Smav device_printf(devinfo->codec->sc->dev, 4716182999Smav " %*snid %d returned %d\n", 4717182999Smav depth + 1, "", w->nid, res); 4718182999Smav ); 4719182999Smav return (res); 4720162922Sariff} 4721162922Sariff 4722182999Smav/* 4723182999Smav * Erase trace path of the specified association. 4724182999Smav */ 4725182999Smavstatic void 4726182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 4727182999Smav{ 4728182999Smav struct hdac_widget *w; 4729182999Smav int i; 4730182999Smav 4731182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4732182999Smav w = hdac_widget_get(devinfo, i); 4733182999Smav if (w == NULL || w->enable == 0) 4734182999Smav continue; 4735182999Smav if (w->bindas == as) { 4736182999Smav if (seq >= 0) { 4737182999Smav w->bindseqmask &= ~(1 << seq); 4738182999Smav if (w->bindseqmask == 0) { 4739182999Smav w->bindas = -1; 4740182999Smav w->selconn = -1; 4741182999Smav } 4742182999Smav } else { 4743182999Smav w->bindas = -1; 4744182999Smav w->bindseqmask = 0; 4745182999Smav w->selconn = -1; 4746182999Smav } 4747182999Smav } 4748182999Smav } 4749182999Smav} 4750182999Smav 4751182999Smav/* 4752182999Smav * Trace association path from DAC to output 4753182999Smav */ 4754162922Sariffstatic int 4755182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 4756162922Sariff{ 4757182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4758182999Smav int i, hpredir; 4759182999Smav nid_t min, res; 4760162922Sariff 4761182999Smav /* Find next pin */ 4762182999Smav for (i = seq; ases[as].pins[i] == 0 && i < 16; i++) 4763182999Smav ; 4764182999Smav /* Check if there is no any left. If so - we succeded. */ 4765182999Smav if (i == 16) 4766182999Smav return (1); 4767182999Smav 4768182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 4769182999Smav min = 0; 4770182999Smav res = 0; 4771182999Smav do { 4772183097Smav HDA_BOOTHVERBOSE( 4773182999Smav device_printf(devinfo->codec->sc->dev, 4774182999Smav " Tracing pin %d with min nid %d", 4775182999Smav ases[as].pins[i], min); 4776182999Smav if (hpredir >= 0) 4777183097Smav printf(" and hpredir %d", hpredir); 4778183097Smav printf("\n"); 4779182999Smav ); 4780182999Smav /* Trace this pin taking min nid into account. */ 4781182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 4782182999Smav ases[as].pins[i], hpredir, min, 0, 0); 4783182999Smav if (res == 0) { 4784182999Smav /* If we failed - return to previous and redo it. */ 4785182999Smav HDA_BOOTVERBOSE( 4786182999Smav device_printf(devinfo->codec->sc->dev, 4787182999Smav " Unable to trace pin %d seq %d with min " 4788183097Smav "nid %d", 4789183097Smav ases[as].pins[i], i, min); 4790183097Smav if (hpredir >= 0) 4791183097Smav printf(" and hpredir %d", hpredir); 4792183097Smav printf("\n"); 4793182999Smav ); 4794182999Smav return (0); 4795162922Sariff } 4796182999Smav HDA_BOOTVERBOSE( 4797182999Smav device_printf(devinfo->codec->sc->dev, 4798183097Smav " Pin %d traced to DAC %d", 4799183097Smav ases[as].pins[i], res); 4800183097Smav if (hpredir >= 0) 4801183097Smav printf(" and hpredir %d", hpredir); 4802183097Smav if (ases[as].fakeredir) 4803183097Smav printf(" with fake redirection"); 4804183097Smav printf("\n"); 4805182999Smav ); 4806182999Smav /* Trace again to mark the path */ 4807182999Smav hdac_audio_trace_dac(devinfo, as, i, 4808182999Smav ases[as].pins[i], hpredir, min, res, 0); 4809182999Smav ases[as].dacs[i] = res; 4810182999Smav /* We succeded, so call next. */ 4811182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 4812182999Smav return (1); 4813182999Smav /* If next failed, we should retry with next min */ 4814182999Smav hdac_audio_undo_trace(devinfo, as, i); 4815182999Smav ases[as].dacs[i] = 0; 4816182999Smav min = res + 1; 4817182999Smav } while (1); 4818162922Sariff} 4819162922Sariff 4820182999Smav/* 4821182999Smav * Trace association path from input to ADC 4822182999Smav */ 4823162922Sariffstatic int 4824182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 4825162922Sariff{ 4826182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4827162922Sariff struct hdac_widget *w; 4828182999Smav int i, j, k; 4829162922Sariff 4830182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4831182999Smav w = hdac_widget_get(devinfo, j); 4832182999Smav if (w == NULL || w->enable == 0) 4833182999Smav continue; 4834182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4835182999Smav continue; 4836182999Smav if (w->bindas >= 0 && w->bindas != as) 4837182999Smav continue; 4838182999Smav 4839182999Smav /* Find next pin */ 4840182999Smav for (i = 0; i < 16; i++) { 4841182999Smav if (ases[as].pins[i] == 0) 4842182999Smav continue; 4843182999Smav 4844183097Smav HDA_BOOTHVERBOSE( 4845182999Smav device_printf(devinfo->codec->sc->dev, 4846182999Smav " Tracing pin %d to ADC %d\n", 4847182999Smav ases[as].pins[i], j); 4848182999Smav ); 4849182999Smav /* Trace this pin taking goal into account. */ 4850182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 4851182999Smav ases[as].pins[i], j, 0) == 0) { 4852182999Smav /* If we failed - return to previous and redo it. */ 4853182999Smav HDA_BOOTVERBOSE( 4854182999Smav device_printf(devinfo->codec->sc->dev, 4855183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 4856182999Smav ases[as].pins[i], j); 4857182999Smav ); 4858182999Smav hdac_audio_undo_trace(devinfo, as, -1); 4859182999Smav for (k = 0; k < 16; k++) 4860182999Smav ases[as].dacs[k] = 0; 4861182999Smav break; 4862162922Sariff } 4863182999Smav HDA_BOOTVERBOSE( 4864182999Smav device_printf(devinfo->codec->sc->dev, 4865183097Smav " Pin %d traced to ADC %d\n", 4866183097Smav ases[as].pins[i], j); 4867182999Smav ); 4868182999Smav ases[as].dacs[i] = j; 4869162922Sariff } 4870182999Smav if (i == 16) 4871182999Smav return (1); 4872162922Sariff } 4873182999Smav return (0); 4874162922Sariff} 4875162922Sariff 4876182999Smav/* 4877182999Smav * Trace input monitor path from mixer to output association. 4878182999Smav */ 4879183097Smavstatic int 4880182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4881162922Sariff{ 4882182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 4883182999Smav struct hdac_widget *w, *wc; 4884182999Smav int i, j; 4885182999Smav nid_t res = 0; 4886162922Sariff 4887162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4888162922Sariff return (0); 4889162922Sariff w = hdac_widget_get(devinfo, nid); 4890162922Sariff if (w == NULL || w->enable == 0) 4891162922Sariff return (0); 4892183097Smav HDA_BOOTHVERBOSE( 4893182999Smav device_printf(devinfo->codec->sc->dev, 4894182999Smav " %*stracing via nid %d\n", 4895182999Smav depth + 1, "", w->nid); 4896182999Smav ); 4897182999Smav /* Use only unused widgets */ 4898182999Smav if (depth > 0 && w->bindas != -1) { 4899182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 4900183097Smav HDA_BOOTHVERBOSE( 4901182999Smav device_printf(devinfo->codec->sc->dev, 4902182999Smav " %*snid %d found output association %d\n", 4903182999Smav depth + 1, "", w->nid, w->bindas); 4904182999Smav ); 4905182999Smav return (1); 4906182999Smav } else { 4907183097Smav HDA_BOOTHVERBOSE( 4908182999Smav device_printf(devinfo->codec->sc->dev, 4909182999Smav " %*snid %d busy by input association %d\n", 4910182999Smav depth + 1, "", w->nid, w->bindas); 4911182999Smav ); 4912182999Smav return (0); 4913182999Smav } 4914182999Smav } 4915182999Smav 4916162922Sariff switch (w->type) { 4917162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4918182999Smav /* Do not traverse input. AD1988 has digital monitor 4919182999Smav for which we are not ready. */ 4920162922Sariff break; 4921162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4922182999Smav if (depth > 0) 4923182999Smav break; 4924182999Smav /* Fall */ 4925182999Smav default: 4926182999Smav /* Try to find reachable ADCs with specified nid. */ 4927182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4928182999Smav wc = hdac_widget_get(devinfo, j); 4929182999Smav if (wc == NULL || wc->enable == 0) 4930182999Smav continue; 4931182999Smav for (i = 0; i < wc->nconns; i++) { 4932182999Smav if (wc->connsenable[i] == 0) 4933182999Smav continue; 4934182999Smav if (wc->conns[i] != nid) 4935182999Smav continue; 4936182999Smav if (hdac_audio_trace_to_out(devinfo, 4937182999Smav j, depth + 1) != 0) { 4938182999Smav res = 1; 4939182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4940182999Smav wc->selconn == -1) 4941182999Smav wc->selconn = i; 4942182999Smav } 4943182999Smav } 4944162922Sariff } 4945162922Sariff break; 4946182999Smav } 4947182999Smav if (res) 4948182999Smav w->bindas = -2; 4949182999Smav 4950183097Smav HDA_BOOTHVERBOSE( 4951182999Smav device_printf(devinfo->codec->sc->dev, 4952182999Smav " %*snid %d returned %d\n", 4953182999Smav depth + 1, "", w->nid, res); 4954182999Smav ); 4955182999Smav return (res); 4956182999Smav} 4957182999Smav 4958182999Smav/* 4959182999Smav * Trace extra associations (beeper, monitor) 4960182999Smav */ 4961182999Smavstatic void 4962182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 4963182999Smav{ 4964182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 4965182999Smav struct hdac_widget *w; 4966182999Smav int j; 4967182999Smav 4968182999Smav /* Input monitor */ 4969182999Smav /* Find mixer associated with input, but supplying signal 4970182999Smav for output associations. Hope it will be input monitor. */ 4971182999Smav HDA_BOOTVERBOSE( 4972182999Smav device_printf(devinfo->codec->sc->dev, 4973182999Smav "Tracing input monitor\n"); 4974182999Smav ); 4975182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 4976182999Smav w = hdac_widget_get(devinfo, j); 4977182999Smav if (w == NULL || w->enable == 0) 4978182999Smav continue; 4979182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 4980182999Smav continue; 4981182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 4982182999Smav continue; 4983182999Smav HDA_BOOTVERBOSE( 4984182999Smav device_printf(devinfo->codec->sc->dev, 4985182999Smav " Tracing nid %d to out\n", 4986182999Smav j); 4987182999Smav ); 4988182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 4989182999Smav HDA_BOOTVERBOSE( 4990182999Smav device_printf(devinfo->codec->sc->dev, 4991182999Smav " nid %d is input monitor\n", 4992182999Smav w->nid); 4993182999Smav ); 4994182999Smav w->pflags |= HDA_ADC_MONITOR; 4995182999Smav w->ossdev = SOUND_MIXER_IMIX; 4996162922Sariff } 4997162922Sariff } 4998182999Smav 4999182999Smav /* Beeper */ 5000182999Smav HDA_BOOTVERBOSE( 5001182999Smav device_printf(devinfo->codec->sc->dev, 5002182999Smav "Tracing beeper\n"); 5003182999Smav ); 5004182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5005182999Smav w = hdac_widget_get(devinfo, j); 5006182999Smav if (w == NULL || w->enable == 0) 5007182999Smav continue; 5008182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5009182999Smav continue; 5010183097Smav HDA_BOOTHVERBOSE( 5011182999Smav device_printf(devinfo->codec->sc->dev, 5012182999Smav " Tracing nid %d to out\n", 5013182999Smav j); 5014182999Smav ); 5015183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5016183097Smav HDA_BOOTVERBOSE( 5017183097Smav device_printf(devinfo->codec->sc->dev, 5018183097Smav " nid %d traced to out\n", 5019183097Smav j); 5020183097Smav ); 5021183097Smav } 5022182999Smav w->bindas = -2; 5023182999Smav } 5024162922Sariff} 5025162922Sariff 5026182999Smav/* 5027182999Smav * Bind assotiations to PCM channels 5028182999Smav */ 5029182999Smavstatic void 5030182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5031162922Sariff{ 5032182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5033182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5034182999Smav int j, cnt = 0, free; 5035162922Sariff 5036182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5037182999Smav if (as[j].enable) 5038182999Smav cnt++; 5039182999Smav } 5040182999Smav if (sc->num_chans == 0) { 5041182999Smav sc->chans = (struct hdac_chan *)malloc( 5042182999Smav sizeof(struct hdac_chan) * cnt, 5043182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5044182999Smav if (sc->chans == NULL) { 5045182999Smav device_printf(devinfo->codec->sc->dev, 5046182999Smav "Channels memory allocation failed!\n"); 5047182999Smav return; 5048182999Smav } 5049182999Smav } else { 5050182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5051183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5052182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5053182999Smav if (sc->chans == NULL) { 5054182999Smav sc->num_chans = 0; 5055182999Smav device_printf(devinfo->codec->sc->dev, 5056182999Smav "Channels memory allocation failed!\n"); 5057182999Smav return; 5058182999Smav } 5059182999Smav } 5060182999Smav free = sc->num_chans; 5061182999Smav sc->num_chans += cnt; 5062162922Sariff 5063182999Smav for (j = free; j < free + cnt; j++) { 5064182999Smav devinfo->codec->sc->chans[j].devinfo = devinfo; 5065182999Smav devinfo->codec->sc->chans[j].as = -1; 5066182999Smav } 5067162922Sariff 5068182999Smav /* Assign associations in order of their numbers, */ 5069182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5070182999Smav if (as[j].enable == 0) 5071182999Smav continue; 5072182999Smav 5073182999Smav as[j].chan = free; 5074182999Smav devinfo->codec->sc->chans[free].as = j; 5075182999Smav if (as[j].dir == HDA_CTL_IN) { 5076182999Smav devinfo->codec->sc->chans[free].dir = PCMDIR_REC; 5077182999Smav devinfo->function.audio.reccnt++; 5078182999Smav } else { 5079182999Smav devinfo->codec->sc->chans[free].dir = PCMDIR_PLAY; 5080182999Smav devinfo->function.audio.playcnt++; 5081182999Smav } 5082182999Smav hdac_pcmchannel_setup(&devinfo->codec->sc->chans[free]); 5083182999Smav free++; 5084182999Smav } 5085182999Smav} 5086162922Sariff 5087182999Smavstatic void 5088182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5089182999Smav{ 5090182999Smav struct hdac_widget *w; 5091182999Smav int i; 5092182999Smav 5093182999Smav /* Disable power and volume widgets. */ 5094182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5095182999Smav w = hdac_widget_get(devinfo, i); 5096182999Smav if (w == NULL || w->enable == 0) 5097182999Smav continue; 5098182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5099182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5100182999Smav w->enable = 0; 5101183097Smav HDA_BOOTHVERBOSE( 5102182999Smav device_printf(devinfo->codec->sc->dev, 5103182999Smav " Disabling nid %d due to it's" 5104182999Smav " non-audio type.\n", 5105182999Smav w->nid); 5106182999Smav ); 5107162922Sariff } 5108182999Smav } 5109182999Smav} 5110182999Smav 5111182999Smavstatic void 5112182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5113182999Smav{ 5114182999Smav struct hdac_widget *w, *cw; 5115182999Smav struct hdac_audio_ctl *ctl; 5116182999Smav int done, found, i, j, k; 5117182999Smav 5118182999Smav /* Disable useless pins. */ 5119182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5120182999Smav w = hdac_widget_get(devinfo, i); 5121182999Smav if (w == NULL || w->enable == 0) 5122182999Smav continue; 5123182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5124182999Smav (w->wclass.pin.config & 5125182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5126182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5127182999Smav w->enable = 0; 5128183097Smav HDA_BOOTHVERBOSE( 5129182999Smav device_printf(devinfo->codec->sc->dev, 5130182999Smav " Disabling pin nid %d due" 5131182999Smav " to None connectivity.\n", 5132182999Smav w->nid); 5133182999Smav ); 5134182999Smav } 5135182999Smav } 5136182999Smav do { 5137182999Smav done = 1; 5138182999Smav /* Disable and mute controls for disabled widgets. */ 5139162922Sariff i = 0; 5140162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5141182999Smav if (ctl->enable == 0) 5142162922Sariff continue; 5143182999Smav if (ctl->widget->enable == 0 || 5144182999Smav (ctl->childwidget != NULL && 5145182999Smav ctl->childwidget->enable == 0)) { 5146182999Smav ctl->forcemute = 1; 5147182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5148182999Smav ctl->left = 0; 5149182999Smav ctl->right = 0; 5150182999Smav ctl->enable = 0; 5151182999Smav if (ctl->ndir == HDA_CTL_IN) 5152182999Smav ctl->widget->connsenable[ctl->index] = 0; 5153182999Smav done = 0; 5154183097Smav HDA_BOOTHVERBOSE( 5155182999Smav device_printf(devinfo->codec->sc->dev, 5156182999Smav " Disabling ctl %d nid %d cnid %d due" 5157182999Smav " to disabled widget.\n", i, 5158182999Smav ctl->widget->nid, 5159182999Smav (ctl->childwidget != NULL)? 5160182999Smav ctl->childwidget->nid:-1); 5161182999Smav ); 5162182999Smav } 5163182999Smav } 5164182999Smav /* Disable useless widgets. */ 5165182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5166182999Smav w = hdac_widget_get(devinfo, i); 5167182999Smav if (w == NULL || w->enable == 0) 5168182999Smav continue; 5169182999Smav /* Disable inputs with disabled child widgets. */ 5170182999Smav for (j = 0; j < w->nconns; j++) { 5171182999Smav if (w->connsenable[j]) { 5172182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5173182999Smav if (cw == NULL || cw->enable == 0) { 5174182999Smav w->connsenable[j] = 0; 5175183097Smav HDA_BOOTHVERBOSE( 5176182999Smav device_printf(devinfo->codec->sc->dev, 5177182999Smav " Disabling nid %d connection %d due" 5178182999Smav " to disabled child widget.\n", 5179182999Smav i, j); 5180182999Smav ); 5181163057Sariff } 5182163057Sariff } 5183162922Sariff } 5184182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5185182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5186162922Sariff continue; 5187182999Smav /* Disable mixers and selectors without inputs. */ 5188182999Smav found = 0; 5189182999Smav for (j = 0; j < w->nconns; j++) { 5190182999Smav if (w->connsenable[j]) { 5191182999Smav found = 1; 5192162922Sariff break; 5193162922Sariff } 5194182999Smav } 5195182999Smav if (found == 0) { 5196182999Smav w->enable = 0; 5197182999Smav done = 0; 5198183097Smav HDA_BOOTHVERBOSE( 5199182999Smav device_printf(devinfo->codec->sc->dev, 5200182999Smav " Disabling nid %d due to all it's" 5201182999Smav " inputs disabled.\n", w->nid); 5202182999Smav ); 5203182999Smav } 5204182999Smav /* Disable nodes without consumers. */ 5205182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5206182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5207182999Smav continue; 5208182999Smav found = 0; 5209182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5210182999Smav cw = hdac_widget_get(devinfo, k); 5211182999Smav if (cw == NULL || cw->enable == 0) 5212182999Smav continue; 5213182999Smav for (j = 0; j < cw->nconns; j++) { 5214182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5215182999Smav found = 1; 5216182999Smav break; 5217182999Smav } 5218162922Sariff } 5219162922Sariff } 5220182999Smav if (found == 0) { 5221182999Smav w->enable = 0; 5222182999Smav done = 0; 5223183097Smav HDA_BOOTHVERBOSE( 5224182999Smav device_printf(devinfo->codec->sc->dev, 5225182999Smav " Disabling nid %d due to all it's" 5226182999Smav " consumers disabled.\n", w->nid); 5227182999Smav ); 5228182999Smav } 5229162922Sariff } 5230182999Smav } while (done == 0); 5231182999Smav 5232182999Smav} 5233182999Smav 5234182999Smavstatic void 5235182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5236182999Smav{ 5237182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5238182999Smav struct hdac_widget *w, *cw; 5239182999Smav struct hdac_audio_ctl *ctl; 5240182999Smav int i, j, k; 5241182999Smav 5242182999Smav /* Disable unassosiated widgets. */ 5243182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5244182999Smav w = hdac_widget_get(devinfo, i); 5245182999Smav if (w == NULL || w->enable == 0) 5246182999Smav continue; 5247182999Smav if (w->bindas == -1) { 5248182999Smav w->enable = 0; 5249183097Smav HDA_BOOTHVERBOSE( 5250182999Smav device_printf(devinfo->codec->sc->dev, 5251182999Smav " Disabling unassociated nid %d.\n", 5252182999Smav w->nid); 5253182999Smav ); 5254182999Smav } 5255182999Smav } 5256182999Smav /* Disable input connections on input pin and 5257182999Smav * output on output. */ 5258182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5259182999Smav w = hdac_widget_get(devinfo, i); 5260182999Smav if (w == NULL || w->enable == 0) 5261182999Smav continue; 5262182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5263182999Smav continue; 5264182999Smav if (w->bindas < 0) 5265182999Smav continue; 5266182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5267182999Smav for (j = 0; j < w->nconns; j++) { 5268182999Smav if (w->connsenable[j] == 0) 5269182999Smav continue; 5270182999Smav w->connsenable[j] = 0; 5271183097Smav HDA_BOOTHVERBOSE( 5272182999Smav device_printf(devinfo->codec->sc->dev, 5273182999Smav " Disabling connection to input pin " 5274182999Smav "nid %d conn %d.\n", 5275182999Smav i, j); 5276182999Smav ); 5277162922Sariff } 5278182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5279182999Smav HDA_CTL_IN, -1, 1); 5280182999Smav if (ctl && ctl->enable) { 5281182999Smav ctl->forcemute = 1; 5282182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5283182999Smav ctl->left = 0; 5284182999Smav ctl->right = 0; 5285182999Smav ctl->enable = 0; 5286182999Smav } 5287182999Smav } else { 5288182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5289182999Smav HDA_CTL_OUT, -1, 1); 5290182999Smav if (ctl && ctl->enable) { 5291182999Smav ctl->forcemute = 1; 5292182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5293182999Smav ctl->left = 0; 5294182999Smav ctl->right = 0; 5295182999Smav ctl->enable = 0; 5296182999Smav } 5297182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5298182999Smav cw = hdac_widget_get(devinfo, k); 5299182999Smav if (cw == NULL || cw->enable == 0) 5300182999Smav continue; 5301182999Smav for (j = 0; j < cw->nconns; j++) { 5302182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5303182999Smav cw->connsenable[j] = 0; 5304183097Smav HDA_BOOTHVERBOSE( 5305182999Smav device_printf(devinfo->codec->sc->dev, 5306182999Smav " Disabling connection from output pin " 5307182999Smav "nid %d conn %d cnid %d.\n", 5308182999Smav k, j, i); 5309182999Smav ); 5310182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5311182999Smav cw->nconns > 1) 5312182999Smav continue; 5313182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5314182999Smav HDA_CTL_IN, j, 1); 5315182999Smav if (ctl && ctl->enable) { 5316182999Smav ctl->forcemute = 1; 5317182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5318182999Smav ctl->left = 0; 5319182999Smav ctl->right = 0; 5320182999Smav ctl->enable = 0; 5321182999Smav } 5322182999Smav } 5323182999Smav } 5324182999Smav } 5325162922Sariff } 5326162922Sariff } 5327162922Sariff} 5328162922Sariff 5329182999Smavstatic void 5330182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5331162922Sariff{ 5332182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5333182999Smav struct hdac_widget *w; 5334182999Smav int i, j; 5335182999Smav 5336182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5337182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5338182999Smav w = hdac_widget_get(devinfo, i); 5339182999Smav if (w == NULL || w->enable == 0) 5340182999Smav continue; 5341182999Smav if (w->nconns <= 1) 5342182999Smav continue; 5343182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5344182999Smav continue; 5345182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5346182999Smav continue; 5347182999Smav for (j = 0; j < w->nconns; j++) { 5348182999Smav if (w->connsenable[j] == 0) 5349182999Smav continue; 5350182999Smav if (w->selconn < 0 || w->selconn == j) 5351182999Smav continue; 5352182999Smav w->connsenable[j] = 0; 5353183097Smav HDA_BOOTHVERBOSE( 5354182999Smav device_printf(devinfo->codec->sc->dev, 5355182999Smav " Disabling unselected connection " 5356182999Smav "nid %d conn %d.\n", 5357182999Smav i, j); 5358182999Smav ); 5359182999Smav } 5360182999Smav } 5361182999Smav} 5362182999Smav 5363182999Smavstatic void 5364182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5365182999Smav{ 5366162922Sariff struct hdac_widget *w, *cw; 5367162922Sariff struct hdac_audio_ctl *ctl; 5368182999Smav int i, j; 5369162922Sariff 5370182999Smav /* Disable crossassociatement connections. */ 5371182999Smav /* ... using selectors */ 5372182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5373182999Smav w = hdac_widget_get(devinfo, i); 5374182999Smav if (w == NULL || w->enable == 0) 5375182999Smav continue; 5376182999Smav if (w->nconns <= 1) 5377182999Smav continue; 5378182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5379182999Smav continue; 5380182999Smav if (w->bindas == -2) 5381182999Smav continue; 5382182999Smav for (j = 0; j < w->nconns; j++) { 5383182999Smav if (w->connsenable[j] == 0) 5384182999Smav continue; 5385182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5386182999Smav if (cw == NULL || w->enable == 0) 5387182999Smav continue; 5388182999Smav if (w->bindas == cw->bindas || cw->bindas == -2) 5389182999Smav continue; 5390182999Smav w->connsenable[j] = 0; 5391183097Smav HDA_BOOTHVERBOSE( 5392182999Smav device_printf(devinfo->codec->sc->dev, 5393182999Smav " Disabling crossassociatement connection " 5394182999Smav "nid %d conn %d cnid %d.\n", 5395182999Smav i, j, cw->nid); 5396182999Smav ); 5397182999Smav } 5398182999Smav } 5399182999Smav /* ... using controls */ 5400182999Smav i = 0; 5401182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5402182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5403182999Smav continue; 5404182999Smav if (ctl->widget->bindas == -2 || 5405182999Smav ctl->childwidget->bindas == -2) 5406182999Smav continue; 5407182999Smav if (ctl->widget->bindas != ctl->childwidget->bindas) { 5408182999Smav ctl->forcemute = 1; 5409182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5410182999Smav ctl->left = 0; 5411182999Smav ctl->right = 0; 5412182999Smav ctl->enable = 0; 5413182999Smav if (ctl->ndir == HDA_CTL_IN) 5414182999Smav ctl->widget->connsenable[ctl->index] = 0; 5415183097Smav HDA_BOOTHVERBOSE( 5416182999Smav device_printf(devinfo->codec->sc->dev, 5417182999Smav " Disabling crossassociatement connection " 5418182999Smav "ctl %d nid %d cnid %d.\n", i, 5419182999Smav ctl->widget->nid, 5420182999Smav ctl->childwidget->nid); 5421182999Smav ); 5422182999Smav } 5423182999Smav } 5424182999Smav 5425182999Smav} 5426182999Smav 5427182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5428182999Smav 5429182999Smav/* 5430182999Smav * Find controls to control amplification for source. 5431182999Smav */ 5432182999Smavstatic int 5433182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5434182999Smav int ossdev, int ctlable, int depth, int need) 5435182999Smav{ 5436182999Smav struct hdac_widget *w, *wc; 5437182999Smav struct hdac_audio_ctl *ctl; 5438182999Smav int i, j, conns = 0, rneed; 5439182999Smav 5440162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5441182999Smav return (need); 5442162922Sariff 5443162922Sariff w = hdac_widget_get(devinfo, nid); 5444162922Sariff if (w == NULL || w->enable == 0) 5445182999Smav return (need); 5446182999Smav 5447182999Smav /* Count number of active inputs. */ 5448182999Smav if (depth > 0) { 5449182999Smav for (j = 0; j < w->nconns; j++) { 5450182999Smav if (w->connsenable[j]) 5451182999Smav conns++; 5452162922Sariff } 5453162922Sariff } 5454182999Smav 5455182999Smav /* If this is not a first step - use input mixer. 5456182999Smav Pins have common input ctl so care must be taken. */ 5457182999Smav if (depth > 0 && ctlable && (conns == 1 || 5458182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5459182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5460182999Smav index, 1); 5461182999Smav if (ctl) { 5462182999Smav if (HDA_CTL_GIVE(ctl) & need) 5463182999Smav ctl->ossmask |= (1 << ossdev); 5464182999Smav else 5465182999Smav ctl->possmask |= (1 << ossdev); 5466182999Smav need &= ~HDA_CTL_GIVE(ctl); 5467182999Smav } 5468182999Smav } 5469182999Smav 5470182999Smav /* If widget has own ossdev - not traverse it. 5471182999Smav It will be traversed on it's own. */ 5472182999Smav if (w->ossdev >= 0 && depth > 0) 5473182999Smav return (need); 5474182999Smav 5475182999Smav /* We must not traverse pin */ 5476182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5477182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5478182999Smav depth > 0) 5479182999Smav return (need); 5480182999Smav 5481182999Smav /* record that this widget exports such signal, */ 5482182999Smav w->ossmask |= (1 << ossdev); 5483182999Smav 5484182999Smav /* If signals mixed, we can't assign controls farther. 5485182999Smav * Ignore this on depth zero. Caller must knows why. 5486182999Smav * Ignore this for static selectors if this input selected. 5487182999Smav */ 5488182999Smav if (conns > 1) 5489182999Smav ctlable = 0; 5490182999Smav 5491182999Smav if (ctlable) { 5492182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5493182999Smav if (ctl) { 5494182999Smav if (HDA_CTL_GIVE(ctl) & need) 5495182999Smav ctl->ossmask |= (1 << ossdev); 5496182999Smav else 5497182999Smav ctl->possmask |= (1 << ossdev); 5498182999Smav need &= ~HDA_CTL_GIVE(ctl); 5499182999Smav } 5500182999Smav } 5501182999Smav 5502182999Smav rneed = 0; 5503182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5504182999Smav wc = hdac_widget_get(devinfo, i); 5505182999Smav if (wc == NULL || wc->enable == 0) 5506162922Sariff continue; 5507182999Smav for (j = 0; j < wc->nconns; j++) { 5508182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5509182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5510182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5511182999Smav } 5512162922Sariff } 5513162922Sariff } 5514182999Smav rneed &= need; 5515182999Smav 5516182999Smav return (rneed); 5517162922Sariff} 5518162922Sariff 5519182999Smav/* 5520182999Smav * Find controls to control amplification for destination. 5521182999Smav */ 5522182999Smavstatic void 5523182999Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, 5524182999Smav int ossdev, int depth, int need) 5525162922Sariff{ 5526182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5527182999Smav struct hdac_widget *w, *wc; 5528182999Smav struct hdac_audio_ctl *ctl; 5529182999Smav int i, j, consumers; 5530182999Smav 5531162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5532182999Smav return; 5533162922Sariff 5534162922Sariff w = hdac_widget_get(devinfo, nid); 5535162922Sariff if (w == NULL || w->enable == 0) 5536182999Smav return; 5537182999Smav 5538182999Smav if (depth > 0) { 5539182999Smav /* If this node produce output for several consumers, 5540182999Smav we can't touch it. */ 5541182999Smav consumers = 0; 5542182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5543182999Smav wc = hdac_widget_get(devinfo, i); 5544182999Smav if (wc == NULL || wc->enable == 0) 5545182999Smav continue; 5546182999Smav for (j = 0; j < wc->nconns; j++) { 5547182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5548182999Smav consumers++; 5549182999Smav } 5550182999Smav } 5551182999Smav /* The only exception is if real HP redirection is configured 5552182999Smav and this is a duplication point. 5553182999Smav XXX: Actually exception is not completely correct. 5554182999Smav XXX: Duplication point check is not perfect. */ 5555182999Smav if ((consumers == 2 && (w->bindas < 0 || 5556182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5557182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5558182999Smav consumers > 2) 5559182999Smav return; 5560182999Smav 5561182999Smav /* Else use it's output mixer. */ 5562182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5563182999Smav HDA_CTL_OUT, -1, 1); 5564182999Smav if (ctl) { 5565182999Smav if (HDA_CTL_GIVE(ctl) & need) 5566182999Smav ctl->ossmask |= (1 << ossdev); 5567182999Smav else 5568182999Smav ctl->possmask |= (1 << ossdev); 5569182999Smav need &= ~HDA_CTL_GIVE(ctl); 5570182999Smav } 5571182999Smav } 5572182999Smav 5573182999Smav /* We must not traverse pin */ 5574182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5575182999Smav depth > 0) 5576182999Smav return; 5577182999Smav 5578162922Sariff for (i = 0; i < w->nconns; i++) { 5579182999Smav int tneed = need; 5580182999Smav if (w->connsenable[i] == 0) 5581162922Sariff continue; 5582182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5583182999Smav HDA_CTL_IN, i, 1); 5584182999Smav if (ctl) { 5585182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 5586182999Smav ctl->ossmask |= (1 << ossdev); 5587182999Smav else 5588182999Smav ctl->possmask |= (1 << ossdev); 5589182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 5590162922Sariff } 5591182999Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev, 5592182999Smav depth + 1, tneed); 5593162922Sariff } 5594162922Sariff} 5595162922Sariff 5596182999Smav/* 5597182999Smav * Assign OSS names to sound sources 5598182999Smav */ 5599182999Smavstatic void 5600182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 5601162922Sariff{ 5602182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5603182999Smav struct hdac_widget *w; 5604182999Smav int i, j; 5605182999Smav int type = -1, use, used = 0; 5606182999Smav static const int types[7][13] = { 5607182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5608182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 5609182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 5610182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 5611182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 5612182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 5613182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 5614182999Smav -1 }, /* digital */ 5615182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 5616182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 5617182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 5618182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 5619182999Smav -1 } /* others */ 5620182999Smav }; 5621162922Sariff 5622182999Smav /* Surely known names */ 5623162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5624162922Sariff w = hdac_widget_get(devinfo, i); 5625162922Sariff if (w == NULL || w->enable == 0) 5626162922Sariff continue; 5627182999Smav if (w->bindas == -1) 5628182999Smav continue; 5629182999Smav use = -1; 5630182999Smav switch (w->type) { 5631182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5632182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5633182999Smav break; 5634182999Smav type = -1; 5635182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5636182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 5637182999Smav type = 0; 5638182999Smav break; 5639182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5640182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 5641182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 5642182999Smav break; 5643182999Smav type = 1; 5644182999Smav break; 5645182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 5646182999Smav type = 3; 5647182999Smav break; 5648182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5649182999Smav type = 4; 5650182999Smav break; 5651182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 5652182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 5653182999Smav type = 5; 5654182999Smav break; 5655182999Smav } 5656182999Smav if (type == -1) 5657182999Smav break; 5658182999Smav j = 0; 5659182999Smav while (types[type][j] >= 0 && 5660182999Smav (used & (1 << types[type][j])) != 0) { 5661182999Smav j++; 5662182999Smav } 5663182999Smav if (types[type][j] >= 0) 5664182999Smav use = types[type][j]; 5665182999Smav break; 5666182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 5667182999Smav use = SOUND_MIXER_PCM; 5668182999Smav break; 5669182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 5670182999Smav use = SOUND_MIXER_SPEAKER; 5671182999Smav break; 5672182999Smav default: 5673182999Smav break; 5674182999Smav } 5675182999Smav if (use >= 0) { 5676182999Smav w->ossdev = use; 5677182999Smav used |= (1 << use); 5678182999Smav } 5679182999Smav } 5680182999Smav /* Semi-known names */ 5681182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5682182999Smav w = hdac_widget_get(devinfo, i); 5683182999Smav if (w == NULL || w->enable == 0) 5684182999Smav continue; 5685182999Smav if (w->ossdev >= 0) 5686182999Smav continue; 5687182999Smav if (w->bindas == -1) 5688182999Smav continue; 5689162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5690162922Sariff continue; 5691182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5692162922Sariff continue; 5693182999Smav type = -1; 5694182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 5695182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 5696182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 5697182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 5698182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 5699182999Smav type = 0; 5700182999Smav break; 5701182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 5702182999Smav type = 2; 5703182999Smav break; 5704182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 5705182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 5706182999Smav type = 5; 5707182999Smav break; 5708182999Smav } 5709182999Smav if (type == -1) 5710182999Smav break; 5711182999Smav j = 0; 5712182999Smav while (types[type][j] >= 0 && 5713182999Smav (used & (1 << types[type][j])) != 0) { 5714182999Smav j++; 5715182999Smav } 5716182999Smav if (types[type][j] >= 0) { 5717182999Smav w->ossdev = types[type][j]; 5718182999Smav used |= (1 << types[type][j]); 5719182999Smav } 5720182999Smav } 5721182999Smav /* Others */ 5722182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5723182999Smav w = hdac_widget_get(devinfo, i); 5724182999Smav if (w == NULL || w->enable == 0) 5725162922Sariff continue; 5726182999Smav if (w->ossdev >= 0) 5727182999Smav continue; 5728182999Smav if (w->bindas == -1) 5729182999Smav continue; 5730182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5731182999Smav continue; 5732182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 5733182999Smav continue; 5734182999Smav j = 0; 5735182999Smav while (types[6][j] >= 0 && 5736182999Smav (used & (1 << types[6][j])) != 0) { 5737182999Smav j++; 5738162922Sariff } 5739182999Smav if (types[6][j] >= 0) { 5740182999Smav w->ossdev = types[6][j]; 5741182999Smav used |= (1 << types[6][j]); 5742182999Smav } 5743162922Sariff } 5744162922Sariff} 5745162922Sariff 5746162922Sariffstatic void 5747162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5748162922Sariff{ 5749182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5750182999Smav int j, res; 5751162922Sariff 5752182999Smav /* Trace all associations in order of their numbers, */ 5753182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5754182999Smav if (as[j].enable == 0) 5755182999Smav continue; 5756163057Sariff HDA_BOOTVERBOSE( 5757162922Sariff device_printf(devinfo->codec->sc->dev, 5758182999Smav "Tracing association %d (%d)\n", j, as[j].index); 5759162922Sariff ); 5760182999Smav if (as[j].dir == HDA_CTL_OUT) { 5761182999Smavretry: 5762182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 5763182999Smav if (res == 0 && as[j].hpredir >= 0 && 5764182999Smav as[j].fakeredir == 0) { 5765182999Smav /* If codec can't do analog HP redirection 5766182999Smav try to make it using one more DAC. */ 5767182999Smav as[j].fakeredir = 1; 5768182999Smav goto retry; 5769182999Smav } 5770182999Smav } else { 5771182999Smav res = hdac_audio_trace_as_in(devinfo, j); 5772182999Smav } 5773182999Smav if (res) { 5774182999Smav HDA_BOOTVERBOSE( 5775182999Smav device_printf(devinfo->codec->sc->dev, 5776182999Smav "Association %d (%d) trace succeded\n", 5777182999Smav j, as[j].index); 5778182999Smav ); 5779182999Smav } else { 5780182999Smav HDA_BOOTVERBOSE( 5781182999Smav device_printf(devinfo->codec->sc->dev, 5782182999Smav "Association %d (%d) trace failed\n", 5783182999Smav j, as[j].index); 5784182999Smav ); 5785182999Smav as[j].enable = 0; 5786182999Smav } 5787162922Sariff } 5788162922Sariff 5789182999Smav /* Trace mixer and beeper pseudo associations. */ 5790182999Smav hdac_audio_trace_as_extra(devinfo); 5791182999Smav} 5792162922Sariff 5793182999Smavstatic void 5794182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 5795182999Smav{ 5796182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5797182999Smav struct hdac_audio_ctl *ctl; 5798182999Smav struct hdac_widget *w; 5799182999Smav int i; 5800162922Sariff 5801182999Smav /* Assign mixers to the tree. */ 5802162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5803162922Sariff w = hdac_widget_get(devinfo, i); 5804162922Sariff if (w == NULL || w->enable == 0) 5805162922Sariff continue; 5806182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 5807182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 5808182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5809182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 5810182999Smav if (w->ossdev < 0) 5811182999Smav continue; 5812182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 5813182999Smav w->ossdev, 1, 0, 1); 5814182999Smav } else if ((w->pflags & HDA_ADC_MONITOR) != 0) { 5815182999Smav if (w->ossdev < 0) 5816182999Smav continue; 5817182999Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 5818182999Smav w->ossdev, 1, 0, 1)) { 5819182999Smav /* If we are unable to control input monitor 5820182999Smav as source - try to control it as destination. */ 5821182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5822182999Smav w->ossdev, 0, 1); 5823162922Sariff } 5824182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 5825182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5826182999Smav SOUND_MIXER_RECLEV, 0, 1); 5827182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5828182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 5829182999Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, 5830182999Smav SOUND_MIXER_VOLUME, 0, 1); 5831162922Sariff } 5832162922Sariff } 5833182999Smav /* Treat unrequired as possible. */ 5834182999Smav i = 0; 5835182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5836182999Smav if (ctl->ossmask == 0) 5837182999Smav ctl->ossmask = ctl->possmask; 5838182999Smav } 5839182999Smav} 5840162922Sariff 5841182999Smavstatic void 5842182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 5843182999Smav{ 5844182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5845182999Smav struct hdac_widget *w; 5846182999Smav uint32_t pincap; 5847182999Smav int i; 5848182999Smav 5849182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 5850182999Smav w = &devinfo->widget[i]; 5851182999Smav if (w == NULL) 5852162922Sariff continue; 5853182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5854162922Sariff continue; 5855182999Smav 5856182999Smav pincap = w->wclass.pin.cap; 5857182999Smav 5858182999Smav /* Disable everything. */ 5859182999Smav w->wclass.pin.ctrl &= ~( 5860182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 5861182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 5862182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 5863182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 5864182999Smav 5865182999Smav if (w->enable == 0 || 5866182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 5867182999Smav /* Pin is unused so left it disabled. */ 5868182999Smav continue; 5869182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 5870182999Smav /* Input pin, configure for input. */ 5871182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 5872182999Smav w->wclass.pin.ctrl |= 5873182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 5874182999Smav 5875182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 5876182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5877182999Smav w->wclass.pin.ctrl |= 5878182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5879182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5880182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 5881182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5882182999Smav w->wclass.pin.ctrl |= 5883182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5884182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5885182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 5886182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5887182999Smav w->wclass.pin.ctrl |= 5888182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5889182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5890182999Smav } else { 5891182999Smav /* Output pin, configure for output. */ 5892182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 5893182999Smav w->wclass.pin.ctrl |= 5894182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 5895182999Smav 5896182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 5897182999Smav (w->wclass.pin.config & 5898182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 5899182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 5900182999Smav w->wclass.pin.ctrl |= 5901182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 5902182999Smav 5903182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 5904182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5905182999Smav w->wclass.pin.ctrl |= 5906182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5907182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5908182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 5909182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5910182999Smav w->wclass.pin.ctrl |= 5911182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5912182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5913182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 5914182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5915182999Smav w->wclass.pin.ctrl |= 5916182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5917182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5918182999Smav } 5919162922Sariff } 5920162922Sariff} 5921162922Sariff 5922162922Sariffstatic void 5923182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 5924162922Sariff{ 5925162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5926162922Sariff struct hdac_widget *w; 5927164750Sariff nid_t cad; 5928182999Smav uint32_t gdata, gmask, gdir; 5929182999Smav int commitgpio, numgpio; 5930164750Sariff int i; 5931162922Sariff 5932162922Sariff cad = devinfo->codec->cad; 5933162922Sariff 5934182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 5935182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 5936182999Smav 0x7e7, 0), cad); 5937169277Sariff 5938182999Smav gdata = 0; 5939182999Smav gmask = 0; 5940182999Smav gdir = 0; 5941182999Smav commitgpio = 0; 5942164828Sariff 5943182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 5944182999Smav devinfo->function.audio.gpio); 5945166796Sariff 5946182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 5947182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 5948182999Smav else { 5949182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 5950182999Smav if (!(devinfo->function.audio.quirks & 5951182999Smav (1 << i))) 5952182999Smav continue; 5953182999Smav if (commitgpio == 0) { 5954182999Smav commitgpio = 1; 5955182999Smav HDA_BOOTVERBOSE( 5956182999Smav gdata = hdac_command(sc, 5957182999Smav HDA_CMD_GET_GPIO_DATA(cad, 5958182999Smav devinfo->nid), cad); 5959182999Smav gmask = hdac_command(sc, 5960182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 5961182999Smav devinfo->nid), cad); 5962182999Smav gdir = hdac_command(sc, 5963182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 5964182999Smav devinfo->nid), cad); 5965182999Smav device_printf(sc->dev, 5966182999Smav "GPIO init: data=0x%08x " 5967182999Smav "mask=0x%08x dir=0x%08x\n", 5968182999Smav gdata, gmask, gdir); 5969182999Smav gdata = 0; 5970182999Smav gmask = 0; 5971182999Smav gdir = 0; 5972182999Smav ); 5973165039Sariff } 5974182999Smav gdata |= 1 << i; 5975182999Smav gmask |= 1 << i; 5976182999Smav gdir |= 1 << i; 5977165039Sariff } 5978182999Smav } 5979165039Sariff 5980182999Smav if (commitgpio != 0) { 5981182999Smav HDA_BOOTVERBOSE( 5982182999Smav device_printf(sc->dev, 5983182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 5984182999Smav "dir=0x%08x\n", 5985182999Smav gdata, gmask, gdir); 5986182999Smav ); 5987182999Smav hdac_command(sc, 5988182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 5989182999Smav gmask), cad); 5990182999Smav hdac_command(sc, 5991182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 5992182999Smav gdir), cad); 5993182999Smav hdac_command(sc, 5994182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 5995182999Smav gdata), cad); 5996162922Sariff } 5997162922Sariff 5998162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 5999162922Sariff w = &devinfo->widget[i]; 6000182999Smav if (w == NULL) 6001162922Sariff continue; 6002182999Smav if (w->selconn == -1) 6003182999Smav w->selconn = 0; 6004182999Smav if (w->nconns > 0) 6005182999Smav hdac_widget_connection_select(w, w->selconn); 6006182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6007162922Sariff hdac_command(sc, 6008162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6009162922Sariff w->wclass.pin.ctrl), cad); 6010162922Sariff } 6011182999Smav if (w->param.eapdbtl != HDAC_INVALID) { 6012163432Sariff uint32_t val; 6013163432Sariff 6014163432Sariff val = w->param.eapdbtl; 6015163276Sariff if (devinfo->function.audio.quirks & 6016163432Sariff HDA_QUIRK_EAPDINV) 6017163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6018162922Sariff hdac_command(sc, 6019162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6020163432Sariff val), cad); 6021162922Sariff 6022163276Sariff } 6023162922Sariff DELAY(1000); 6024162922Sariff } 6025162922Sariff} 6026162922Sariff 6027162922Sariffstatic void 6028162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6029162922Sariff{ 6030162922Sariff struct hdac_audio_ctl *ctl; 6031182999Smav int i, z; 6032162922Sariff 6033162922Sariff i = 0; 6034162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6035182999Smav if (ctl->enable == 0) { 6036182999Smav /* Mute disabled controls. */ 6037182999Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6038162922Sariff continue; 6039162922Sariff } 6040182999Smav /* Init controls to 0dB amplification. */ 6041182999Smav z = ctl->offset; 6042182999Smav if (z > ctl->step) 6043182999Smav z = ctl->step; 6044182999Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6045162922Sariff } 6046162922Sariff} 6047162922Sariff 6048182999Smavstatic void 6049182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6050182999Smav{ 6051182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6052182999Smav nid_t cad = devinfo->codec->cad; 6053182999Smav int i; 6054182999Smav 6055182999Smav hdac_command(sc, 6056182999Smav HDA_CMD_SET_POWER_STATE(cad, 6057182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6058182999Smav cad); 6059182999Smav DELAY(100); 6060182999Smav 6061182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6062182999Smav hdac_command(sc, 6063182999Smav HDA_CMD_SET_POWER_STATE(cad, 6064182999Smav i, HDA_CMD_POWER_STATE_D0), 6065182999Smav cad); 6066182999Smav } 6067182999Smav DELAY(1000); 6068182999Smav} 6069182999Smav 6070162922Sariffstatic int 6071182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6072162922Sariff{ 6073182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6074182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6075162922Sariff struct hdac_widget *w; 6076182999Smav uint32_t cap, fmtcap, pcmcap; 6077182999Smav int i, j, ret, max; 6078162922Sariff 6079162922Sariff ch->caps = hdac_caps; 6080162922Sariff ch->caps.fmtlist = ch->fmtlist; 6081162922Sariff ch->bit16 = 1; 6082162922Sariff ch->bit32 = 0; 6083162922Sariff ch->pcmrates[0] = 48000; 6084162922Sariff ch->pcmrates[1] = 0; 6085162922Sariff 6086162922Sariff ret = 0; 6087162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6088162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6089162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 6090162922Sariff 6091182999Smav for (i = 0; i < 16 && ret < max; i++) { 6092182999Smav /* Check as is correct */ 6093182999Smav if (ch->as < 0) 6094182999Smav break; 6095182999Smav /* Cound only present DACs */ 6096182999Smav if (as[ch->as].dacs[i] <= 0) 6097162922Sariff continue; 6098182999Smav /* Ignore duplicates */ 6099182999Smav for (j = 0; j < ret; j++) { 6100182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6101182999Smav break; 6102182999Smav } 6103182999Smav if (j < ret) 6104162922Sariff continue; 6105182999Smav 6106182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6107182999Smav if (w == NULL || w->enable == 0) 6108182999Smav continue; 6109182999Smav if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6110182999Smav continue; 6111162922Sariff cap = w->param.supp_stream_formats; 6112182999Smav /*if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 6113162922Sariff }*/ 6114182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6115182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6116162922Sariff continue; 6117182999Smav /* Many codec does not declare AC3 support on SPDIF. 6118182999Smav I don't beleave that they doesn't support it! */ 6119182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6120182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6121164614Sariff if (ret == 0) { 6122182999Smav fmtcap = cap; 6123164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6124164614Sariff } else { 6125182999Smav fmtcap &= cap; 6126164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6127164614Sariff } 6128182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6129162922Sariff } 6130162922Sariff ch->io[ret] = -1; 6131162922Sariff 6132162922Sariff ch->supp_stream_formats = fmtcap; 6133162922Sariff ch->supp_pcm_size_rate = pcmcap; 6134162922Sariff 6135162922Sariff /* 6136162922Sariff * 8bit = 0 6137162922Sariff * 16bit = 1 6138162922Sariff * 20bit = 2 6139162922Sariff * 24bit = 3 6140162922Sariff * 32bit = 4 6141162922Sariff */ 6142162922Sariff if (ret > 0) { 6143162922Sariff i = 0; 6144182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6145182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6146182999Smav ch->bit16 = 1; 6147182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6148182999Smav ch->bit16 = 0; 6149182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6150182999Smav ch->bit32 = 4; 6151182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6152182999Smav ch->bit32 = 3; 6153182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6154182999Smav ch->bit32 = 2; 6155182999Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 6156182999Smav ch->fmtlist[i++] = AFMT_S16_LE; 6157182999Smav ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 6158182999Smav if (ch->bit32 > 0) { 6159182999Smav if (!(devinfo->function.audio.quirks & 6160182999Smav HDA_QUIRK_FORCESTEREO)) 6161182999Smav ch->fmtlist[i++] = AFMT_S32_LE; 6162182999Smav ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 6163182999Smav } 6164162922Sariff } 6165182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6166182999Smav ch->fmtlist[i++] = AFMT_AC3; 6167182999Smav } 6168162922Sariff ch->fmtlist[i] = 0; 6169162922Sariff i = 0; 6170182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6171162922Sariff ch->pcmrates[i++] = 8000; 6172182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6173162922Sariff ch->pcmrates[i++] = 11025; 6174182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6175162922Sariff ch->pcmrates[i++] = 16000; 6176182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6177162922Sariff ch->pcmrates[i++] = 22050; 6178182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6179162922Sariff ch->pcmrates[i++] = 32000; 6180182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6181162922Sariff ch->pcmrates[i++] = 44100; 6182182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6183162922Sariff ch->pcmrates[i++] = 48000; 6184182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6185162922Sariff ch->pcmrates[i++] = 88200; 6186182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6187162922Sariff ch->pcmrates[i++] = 96000; 6188182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6189162922Sariff ch->pcmrates[i++] = 176400; 6190182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6191162922Sariff ch->pcmrates[i++] = 192000; 6192182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6193162922Sariff ch->pcmrates[i] = 0; 6194162922Sariff if (i > 0) { 6195162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6196162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6197162922Sariff } 6198162922Sariff } 6199162922Sariff 6200162922Sariff return (ret); 6201162922Sariff} 6202162922Sariff 6203162922Sariffstatic void 6204182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6205162922Sariff{ 6206182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6207162922Sariff struct hdac_audio_ctl *ctl; 6208162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6209182999Smav char buf[64]; 6210182999Smav int i, j, printed; 6211162922Sariff 6212162922Sariff if (flag == 0) { 6213182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6214162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6215182999Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN | 6216182999Smav SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6217162922Sariff } 6218162922Sariff 6219182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6220182999Smav if ((flag & (1 << j)) == 0) 6221162922Sariff continue; 6222182999Smav i = 0; 6223182999Smav printed = 0; 6224182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6225182999Smav if (ctl->enable == 0 || 6226182999Smav ctl->widget->enable == 0) 6227182999Smav continue; 6228182999Smav if (!((pdevinfo->play >= 0 && 6229182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6230182999Smav (pdevinfo->rec >= 0 && 6231182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6232182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6233182999Smav continue; 6234182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6235182999Smav continue; 6236182999Smav 6237182999Smav if (printed == 0) { 6238182999Smav device_printf(pdevinfo->dev, "\n"); 6239182999Smav if (banner != NULL) { 6240182999Smav device_printf(pdevinfo->dev, "%s", banner); 6241182999Smav } else { 6242182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6243182999Smav } 6244182999Smav printf(" (OSS: %s)\n", 6245182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6246182999Smav buf, sizeof(buf))); 6247182999Smav device_printf(pdevinfo->dev, " |\n"); 6248182999Smav printed = 1; 6249162922Sariff } 6250182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6251182999Smav ctl->widget->nid, 6252182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6253182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6254182999Smav printf(" %2d): ", ctl->index); 6255182999Smav else 6256182999Smav printf("): "); 6257182999Smav if (ctl->step > 0) { 6258182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6259182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6260182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6261182999Smav ctl->step + 1, 6262182999Smav ctl->mute?" + mute":""); 6263182999Smav } else 6264182999Smav printf("%s\n", ctl->mute?"mute":""); 6265162922Sariff } 6266162922Sariff } 6267162922Sariff} 6268162922Sariff 6269162922Sariffstatic void 6270182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6271162922Sariff{ 6272162922Sariff uint32_t cap; 6273162922Sariff 6274162922Sariff cap = fcap; 6275162922Sariff if (cap != 0) { 6276182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6277183097Smav device_printf(dev, " "); 6278162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6279162922Sariff printf(" AC3"); 6280162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6281162922Sariff printf(" FLOAT32"); 6282162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6283162922Sariff printf(" PCM"); 6284162922Sariff printf("\n"); 6285162922Sariff } 6286162922Sariff cap = pcmcap; 6287162922Sariff if (cap != 0) { 6288182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6289183097Smav device_printf(dev, " "); 6290162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6291162922Sariff printf(" 8"); 6292162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6293162922Sariff printf(" 16"); 6294162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6295162922Sariff printf(" 20"); 6296162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6297162922Sariff printf(" 24"); 6298162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6299162922Sariff printf(" 32"); 6300183097Smav printf(" bits,"); 6301162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6302162922Sariff printf(" 8"); 6303162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6304162922Sariff printf(" 11"); 6305162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6306162922Sariff printf(" 16"); 6307162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6308162922Sariff printf(" 22"); 6309162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6310162922Sariff printf(" 32"); 6311162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6312162922Sariff printf(" 44"); 6313162922Sariff printf(" 48"); 6314162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6315162922Sariff printf(" 88"); 6316162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6317162922Sariff printf(" 96"); 6318162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6319162922Sariff printf(" 176"); 6320162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6321162922Sariff printf(" 192"); 6322183097Smav printf(" KHz\n"); 6323162922Sariff } 6324162922Sariff} 6325162922Sariff 6326162922Sariffstatic void 6327162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6328162922Sariff{ 6329183097Smav uint32_t pincap; 6330162922Sariff 6331162922Sariff pincap = w->wclass.pin.cap; 6332162922Sariff 6333162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6334162922Sariff device_printf(sc->dev, " "); 6335162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6336162922Sariff printf(" ISC"); 6337162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6338162922Sariff printf(" TRQD"); 6339162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6340162922Sariff printf(" PDC"); 6341162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6342162922Sariff printf(" HP"); 6343162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6344162922Sariff printf(" OUT"); 6345162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6346162922Sariff printf(" IN"); 6347162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6348162922Sariff printf(" BAL"); 6349165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6350165069Sariff printf(" VREF["); 6351165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6352165069Sariff printf(" 50"); 6353165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6354165069Sariff printf(" 80"); 6355165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6356165069Sariff printf(" 100"); 6357165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6358165069Sariff printf(" GROUND"); 6359165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6360165069Sariff printf(" HIZ"); 6361165069Sariff printf(" ]"); 6362165069Sariff } 6363162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6364162922Sariff printf(" EAPD"); 6365162922Sariff printf("\n"); 6366162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6367162922Sariff w->wclass.pin.config); 6368162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6369162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6370162922Sariff printf(" HP"); 6371162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6372162922Sariff printf(" IN"); 6373162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6374162922Sariff printf(" OUT"); 6375182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6376182999Smav printf(" VREFs"); 6377162922Sariff printf("\n"); 6378162922Sariff} 6379162922Sariff 6380162922Sariffstatic void 6381182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6382182999Smav{ 6383182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6384182999Smav 6385183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6386182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6387182999Smav w->nid, conf, 6388182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6389182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6390182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6391182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6392182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6393182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6394182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6395182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6396182999Smav (w->enable == 0)?" [DISABLED]":""); 6397182999Smav} 6398182999Smav 6399182999Smavstatic void 6400182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6401182999Smav{ 6402182999Smav struct hdac_widget *w; 6403182999Smav int i; 6404182999Smav 6405182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6406182999Smav w = hdac_widget_get(devinfo, i); 6407182999Smav if (w == NULL) 6408182999Smav continue; 6409182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6410182999Smav continue; 6411182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6412182999Smav } 6413182999Smav} 6414182999Smav 6415182999Smavstatic void 6416162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6417162922Sariff{ 6418163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6419162922Sariff device_printf(sc->dev, " " 6420162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6421162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6422162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6423162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6424162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6425162922Sariff} 6426162922Sariff 6427162922Sariffstatic void 6428162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6429162922Sariff{ 6430162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6431182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6432162922Sariff struct hdac_widget *w, *cw; 6433182999Smav char buf[64]; 6434162922Sariff int i, j; 6435162922Sariff 6436162922Sariff device_printf(sc->dev, "\n"); 6437162922Sariff device_printf(sc->dev, "Default Parameter\n"); 6438162922Sariff device_printf(sc->dev, "-----------------\n"); 6439182999Smav hdac_dump_audio_formats(sc->dev, 6440162922Sariff devinfo->function.audio.supp_stream_formats, 6441162922Sariff devinfo->function.audio.supp_pcm_size_rate); 6442162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 6443162922Sariff devinfo->function.audio.inamp_cap); 6444162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 6445162922Sariff devinfo->function.audio.outamp_cap); 6446162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6447162922Sariff w = hdac_widget_get(devinfo, i); 6448162922Sariff if (w == NULL) { 6449162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 6450162922Sariff continue; 6451162922Sariff } 6452162922Sariff device_printf(sc->dev, "\n"); 6453183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 6454162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 6455183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 6456183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 6457162922Sariff w->param.widget_cap); 6458183097Smav if (w->param.widget_cap & 0x0ee1) { 6459183097Smav device_printf(sc->dev, " "); 6460183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 6461183097Smav printf(" LRSWAP"); 6462183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 6463183097Smav printf(" PWR"); 6464183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6465183097Smav printf(" DIGITAL"); 6466183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 6467183097Smav printf(" UNSOL"); 6468183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 6469183097Smav printf(" PROC"); 6470183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 6471183097Smav printf(" STRIPE"); 6472183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap)) 6473183097Smav printf(" STEREO"); 6474183097Smav printf("\n"); 6475183097Smav } 6476183097Smav if (w->bindas != -1) { 6477183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 6478183097Smav w->bindas, w->bindseqmask); 6479183097Smav } 6480183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 6481183097Smav device_printf(sc->dev, " OSS: %s", 6482183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 6483183097Smav if (w->ossdev >= 0) 6484183097Smav printf(" (%s)", ossname[w->ossdev]); 6485183097Smav printf("\n"); 6486183097Smav } 6487162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6488162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6489182999Smav hdac_dump_audio_formats(sc->dev, 6490162922Sariff w->param.supp_stream_formats, 6491162922Sariff w->param.supp_pcm_size_rate); 6492162922Sariff } else if (w->type == 6493162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6494162922Sariff hdac_dump_pin(sc, w); 6495162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 6496162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 6497162922Sariff w->param.eapdbtl); 6498163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 6499163057Sariff w->param.outamp_cap != 0) 6500162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 6501163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 6502163057Sariff w->param.inamp_cap != 0) 6503162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 6504183097Smav if (w->nconns > 0) { 6505183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 6506182999Smav device_printf(sc->dev, " |\n"); 6507183097Smav } 6508162922Sariff for (j = 0; j < w->nconns; j++) { 6509162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 6510182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 6511182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 6512162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 6513162922Sariff if (cw == NULL) 6514162922Sariff printf(" [UNKNOWN]"); 6515162922Sariff else if (cw->enable == 0) 6516162922Sariff printf(" [DISABLED]"); 6517162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 6518162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 6519162922Sariff printf(" (selected)"); 6520162922Sariff printf("\n"); 6521162922Sariff } 6522162922Sariff } 6523162922Sariff 6524162922Sariff} 6525162922Sariff 6526182999Smavstatic void 6527182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 6528163057Sariff{ 6529182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6530163057Sariff struct hdac_widget *w, *cw; 6531182999Smav char buf[64]; 6532182999Smav int i, printed = 0; 6533163057Sariff 6534163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 6535182999Smav return; 6536163057Sariff 6537163057Sariff w = hdac_widget_get(devinfo, nid); 6538182999Smav if (w == NULL || w->enable == 0) 6539182999Smav return; 6540163057Sariff 6541182999Smav if (depth == 0) 6542182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 6543182999Smav else 6544182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 6545182999Smav printf("nid=%d [%s]", w->nid, w->name); 6546163057Sariff 6547182999Smav if (depth > 0) { 6548182999Smav if (w->ossmask == 0) { 6549182999Smav printf("\n"); 6550182999Smav return; 6551163057Sariff } 6552182999Smav printf(" [src: %s]", 6553182999Smav hdac_audio_ctl_ossmixer_mask2allname( 6554182999Smav w->ossmask, buf, sizeof(buf))); 6555182999Smav if (w->ossdev >= 0) { 6556182999Smav printf("\n"); 6557182999Smav return; 6558182999Smav } 6559163057Sariff } 6560182999Smav printf("\n"); 6561182999Smav 6562182999Smav for (i = 0; i < w->nconns; i++) { 6563182999Smav if (w->connsenable[i] == 0) 6564182999Smav continue; 6565182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 6566182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 6567182999Smav continue; 6568182999Smav if (printed == 0) { 6569182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 6570182999Smav printed = 1; 6571182999Smav } 6572182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 6573182999Smav } 6574163057Sariff 6575163057Sariff} 6576163057Sariff 6577162922Sariffstatic void 6578182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 6579162922Sariff{ 6580182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6581182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6582163057Sariff struct hdac_widget *w; 6583163057Sariff int i, printed = 0; 6584163057Sariff 6585182999Smav if (pdevinfo->play < 0) 6586182999Smav return; 6587182999Smav 6588163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6589163057Sariff w = hdac_widget_get(devinfo, i); 6590163057Sariff if (w == NULL || w->enable == 0) 6591163057Sariff continue; 6592182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6593163057Sariff continue; 6594182999Smav if (w->bindas != sc->chans[pdevinfo->play].as) 6595182999Smav continue; 6596163057Sariff if (printed == 0) { 6597163057Sariff printed = 1; 6598182999Smav device_printf(pdevinfo->dev, "\n"); 6599182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6600163057Sariff } 6601182999Smav device_printf(pdevinfo->dev, "\n"); 6602182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6603163057Sariff } 6604162922Sariff} 6605162922Sariff 6606162922Sariffstatic void 6607182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 6608162922Sariff{ 6609182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6610162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6611182999Smav struct hdac_widget *w; 6612182999Smav int i; 6613162922Sariff int printed = 0; 6614162922Sariff 6615182999Smav if (pdevinfo->rec < 0) 6616182999Smav return; 6617182999Smav 6618162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6619162922Sariff w = hdac_widget_get(devinfo, i); 6620162922Sariff if (w == NULL || w->enable == 0) 6621162922Sariff continue; 6622182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 6623162922Sariff continue; 6624182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 6625182999Smav continue; 6626162922Sariff if (printed == 0) { 6627162922Sariff printed = 1; 6628182999Smav device_printf(pdevinfo->dev, "\n"); 6629182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6630162922Sariff } 6631182999Smav device_printf(pdevinfo->dev, "\n"); 6632182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6633182999Smav } 6634182999Smav} 6635182999Smav 6636182999Smavstatic void 6637182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 6638182999Smav{ 6639182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6640182999Smav struct hdac_widget *w; 6641182999Smav int i; 6642182999Smav int printed = 0; 6643182999Smav 6644182999Smav if (pdevinfo->index != 0) 6645182999Smav return; 6646182999Smav 6647182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6648182999Smav w = hdac_widget_get(devinfo, i); 6649182999Smav if (w == NULL || w->enable == 0) 6650182999Smav continue; 6651182999Smav if ((w->pflags & HDA_ADC_MONITOR) == 0) 6652182999Smav continue; 6653182999Smav if (printed == 0) { 6654182999Smav printed = 1; 6655182999Smav device_printf(pdevinfo->dev, "\n"); 6656182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 6657162922Sariff } 6658182999Smav device_printf(pdevinfo->dev, "\n"); 6659182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 6660162922Sariff } 6661162922Sariff} 6662162922Sariff 6663162922Sariffstatic void 6664182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 6665162922Sariff{ 6666182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 6667162922Sariff nid_t *nids; 6668182999Smav int i; 6669162922Sariff 6670182999Smav if (pdevinfo->play >= 0) { 6671182999Smav i = pdevinfo->play; 6672182999Smav device_printf(pdevinfo->dev, "\n"); 6673182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 6674182999Smav device_printf(pdevinfo->dev, "\n"); 6675182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 6676182999Smav sc->chans[i].supp_pcm_size_rate); 6677182999Smav device_printf(pdevinfo->dev, " DAC:"); 6678182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 6679162922Sariff printf(" %d", *nids); 6680162922Sariff printf("\n"); 6681162922Sariff } 6682182999Smav if (pdevinfo->rec >= 0) { 6683182999Smav i = pdevinfo->rec; 6684182999Smav device_printf(pdevinfo->dev, "\n"); 6685182999Smav device_printf(pdevinfo->dev, "Record:\n"); 6686182999Smav device_printf(pdevinfo->dev, "\n"); 6687182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 6688182999Smav sc->chans[i].supp_pcm_size_rate); 6689182999Smav device_printf(pdevinfo->dev, " ADC:"); 6690182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 6691162922Sariff printf(" %d", *nids); 6692162922Sariff printf("\n"); 6693162922Sariff } 6694162922Sariff} 6695162922Sariff 6696162922Sariffstatic void 6697163057Sariffhdac_release_resources(struct hdac_softc *sc) 6698163057Sariff{ 6699182999Smav int i, j; 6700163057Sariff 6701163057Sariff if (sc == NULL) 6702163057Sariff return; 6703163057Sariff 6704163057Sariff hdac_lock(sc); 6705169277Sariff sc->polling = 0; 6706169277Sariff sc->poll_ival = 0; 6707170721Sariff callout_stop(&sc->poll_hda); 6708169277Sariff callout_stop(&sc->poll_hdac); 6709169277Sariff callout_stop(&sc->poll_jack); 6710182999Smav hdac_reset(sc, 0); 6711163057Sariff hdac_unlock(sc); 6712171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 6713170721Sariff callout_drain(&sc->poll_hda); 6714169277Sariff callout_drain(&sc->poll_hdac); 6715169277Sariff callout_drain(&sc->poll_jack); 6716163057Sariff 6717169277Sariff hdac_irq_free(sc); 6718169277Sariff 6719182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 6720182999Smav if (sc->codecs[i] == NULL) 6721163057Sariff continue; 6722182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 6723182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 6724182999Smav if (sc->codecs[i]->fgs[j].node_type == 6725182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 6726182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 6727182999Smav M_HDAC); 6728182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 6729182999Smav M_HDAC); 6730182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 6731182999Smav M_HDAC); 6732182999Smav } 6733182999Smav } 6734182999Smav free(sc->codecs[i]->fgs, M_HDAC); 6735182999Smav free(sc->codecs[i], M_HDAC); 6736163057Sariff sc->codecs[i] = NULL; 6737163057Sariff } 6738163057Sariff 6739169277Sariff hdac_dma_free(sc, &sc->pos_dma); 6740169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 6741169277Sariff hdac_dma_free(sc, &sc->corb_dma); 6742182999Smav for (i = 0; i < sc->num_chans; i++) { 6743182999Smav if (sc->chans[i].blkcnt > 0) 6744182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 6745182999Smav } 6746182999Smav free(sc->chans, M_HDAC); 6747167702Sariff if (sc->chan_dmat != NULL) { 6748167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 6749167702Sariff sc->chan_dmat = NULL; 6750167702Sariff } 6751163057Sariff hdac_mem_free(sc); 6752169277Sariff snd_mtxfree(sc->lock); 6753163057Sariff} 6754163057Sariff 6755163057Sariff/* This function surely going to make its way into upper level someday. */ 6756163057Sariffstatic void 6757163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 6758163057Sariff{ 6759163057Sariff const char *res = NULL; 6760163057Sariff int i = 0, j, k, len, inv; 6761163057Sariff 6762163057Sariff if (on != NULL) 6763163057Sariff *on = 0; 6764163057Sariff if (off != NULL) 6765163057Sariff *off = 0; 6766163057Sariff if (sc == NULL) 6767163057Sariff return; 6768163057Sariff if (resource_string_value(device_get_name(sc->dev), 6769163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 6770163057Sariff return; 6771163057Sariff if (!(res != NULL && strlen(res) > 0)) 6772163057Sariff return; 6773163057Sariff HDA_BOOTVERBOSE( 6774182999Smav device_printf(sc->dev, "HDA Config:"); 6775163057Sariff ); 6776163057Sariff for (;;) { 6777163057Sariff while (res[i] != '\0' && 6778163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 6779163057Sariff i++; 6780163057Sariff if (res[i] == '\0') { 6781163057Sariff HDA_BOOTVERBOSE( 6782163057Sariff printf("\n"); 6783163057Sariff ); 6784163057Sariff return; 6785163057Sariff } 6786163057Sariff j = i; 6787163057Sariff while (res[j] != '\0' && 6788163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 6789163057Sariff j++; 6790163057Sariff len = j - i; 6791163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 6792163057Sariff inv = 2; 6793163057Sariff else 6794163057Sariff inv = 0; 6795163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 6796163057Sariff if (strncmp(res + i + inv, 6797163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 6798163057Sariff continue; 6799163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 6800163057Sariff break; 6801163057Sariff HDA_BOOTVERBOSE( 6802163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 6803163057Sariff hdac_quirks_tab[k].key); 6804163057Sariff ); 6805163057Sariff if (inv == 0 && on != NULL) 6806163057Sariff *on |= hdac_quirks_tab[k].value; 6807163057Sariff else if (inv != 0 && off != NULL) 6808163057Sariff *off |= hdac_quirks_tab[k].value; 6809163057Sariff break; 6810163057Sariff } 6811163057Sariff i = j; 6812163057Sariff } 6813163057Sariff} 6814163057Sariff 6815164614Sariff#ifdef SND_DYNSYSCTL 6816164614Sariffstatic int 6817164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 6818164614Sariff{ 6819164614Sariff struct hdac_softc *sc; 6820164614Sariff device_t dev; 6821164614Sariff uint32_t ctl; 6822164614Sariff int err, val; 6823164614Sariff 6824164614Sariff dev = oidp->oid_arg1; 6825182999Smav sc = device_get_softc(dev); 6826182999Smav if (sc == NULL) 6827164614Sariff return (EINVAL); 6828164614Sariff hdac_lock(sc); 6829164614Sariff val = sc->polling; 6830164614Sariff hdac_unlock(sc); 6831170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6832164614Sariff 6833169277Sariff if (err != 0 || req->newptr == NULL) 6834164614Sariff return (err); 6835164614Sariff if (val < 0 || val > 1) 6836164614Sariff return (EINVAL); 6837164614Sariff 6838164614Sariff hdac_lock(sc); 6839164614Sariff if (val != sc->polling) { 6840182999Smav if (val == 0) { 6841182999Smav callout_stop(&sc->poll_hda); 6842164614Sariff callout_stop(&sc->poll_hdac); 6843169277Sariff hdac_unlock(sc); 6844182999Smav callout_drain(&sc->poll_hda); 6845169277Sariff callout_drain(&sc->poll_hdac); 6846169277Sariff hdac_lock(sc); 6847164614Sariff sc->polling = 0; 6848182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 6849182999Smav ctl |= HDAC_INTCTL_GIE; 6850182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 6851164614Sariff } else { 6852182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 6853182999Smav ctl &= ~HDAC_INTCTL_GIE; 6854182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 6855171141Sariff hdac_unlock(sc); 6856171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 6857171141Sariff hdac_lock(sc); 6858164614Sariff sc->polling = 1; 6859182999Smav hdac_poll_reinit(sc); 6860182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 6861164614Sariff } 6862164614Sariff } 6863164614Sariff hdac_unlock(sc); 6864164614Sariff 6865164614Sariff return (err); 6866164614Sariff} 6867169277Sariff 6868169277Sariffstatic int 6869169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 6870169277Sariff{ 6871169277Sariff struct hdac_softc *sc; 6872169277Sariff device_t dev; 6873169277Sariff int err, val; 6874169277Sariff 6875169277Sariff dev = oidp->oid_arg1; 6876182999Smav sc = device_get_softc(dev); 6877182999Smav if (sc == NULL) 6878169277Sariff return (EINVAL); 6879169277Sariff hdac_lock(sc); 6880169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 6881169277Sariff hdac_unlock(sc); 6882170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6883169277Sariff 6884169277Sariff if (err != 0 || req->newptr == NULL) 6885169277Sariff return (err); 6886169277Sariff 6887169277Sariff if (val < 1) 6888169277Sariff val = 1; 6889169277Sariff if (val > 5000) 6890169277Sariff val = 5000; 6891169277Sariff val = ((uint64_t)val * hz) / 1000; 6892169277Sariff if (val < 1) 6893169277Sariff val = 1; 6894169277Sariff if (val > (hz * 5)) 6895169277Sariff val = hz * 5; 6896169277Sariff 6897169277Sariff hdac_lock(sc); 6898169277Sariff sc->poll_ival = val; 6899169277Sariff hdac_unlock(sc); 6900169277Sariff 6901169277Sariff return (err); 6902169277Sariff} 6903169277Sariff 6904169277Sariffstatic int 6905171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 6906169277Sariff{ 6907169277Sariff struct hdac_softc *sc; 6908182999Smav struct hdac_codec *codec; 6909169277Sariff struct hdac_devinfo *devinfo; 6910169277Sariff struct hdac_widget *w; 6911169277Sariff device_t dev; 6912182999Smav uint32_t res, pincap, delay; 6913182999Smav int codec_index, fg_index; 6914169277Sariff int i, err, val; 6915169277Sariff nid_t cad; 6916169277Sariff 6917169277Sariff dev = oidp->oid_arg1; 6918182999Smav sc = device_get_softc(dev); 6919182999Smav if (sc == NULL) 6920169277Sariff return (EINVAL); 6921169277Sariff val = 0; 6922170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6923169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 6924169277Sariff return (err); 6925182999Smav 6926182999Smav /* XXX: Temporary. For debugging. */ 6927182999Smav if (val == 100) { 6928182999Smav hdac_suspend(dev); 6929182999Smav return (0); 6930182999Smav } else if (val == 101) { 6931182999Smav hdac_resume(dev); 6932182999Smav return (0); 6933182999Smav } 6934182999Smav 6935169277Sariff hdac_lock(sc); 6936182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 6937182999Smav codec = sc->codecs[codec_index]; 6938182999Smav if (codec == NULL) 6939169277Sariff continue; 6940182999Smav cad = codec->cad; 6941182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 6942182999Smav devinfo = &codec->fgs[fg_index]; 6943182999Smav if (devinfo->node_type != 6944182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 6945182999Smav continue; 6946182999Smav 6947182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 6948182999Smav codec_index, devinfo->nid); 6949182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6950182999Smav w = hdac_widget_get(devinfo, i); 6951182999Smav if (w == NULL || w->type != 6952182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6953182999Smav continue; 6954182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6955182999Smav pincap = w->wclass.pin.cap; 6956182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 6957182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 6958182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 6959182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 6960182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 6961182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 6962182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 6963182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 6964182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 6965182999Smav delay = 0; 6966182999Smav hdac_command(sc, 6967182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 6968182999Smav do { 6969182999Smav res = hdac_command(sc, 6970182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 6971182999Smav if (res != 0x7fffffff && res != 0xffffffff) 6972182999Smav break; 6973182999Smav DELAY(10); 6974182999Smav } while (++delay < 10000); 6975182999Smav } else { 6976182999Smav delay = 0; 6977182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 6978182999Smav w->nid), cad); 6979182999Smav } 6980182999Smav printf(" Sense: 0x%08x", res); 6981182999Smav if (delay > 0) 6982182999Smav printf(" delay %dus", delay * 10); 6983182999Smav } 6984182999Smav printf("\n"); 6985182999Smav } 6986182999Smav device_printf(dev, 6987182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 6988182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 6989182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 6990182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 6991182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 6992182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 6993182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 6994182999Smav device_printf(dev, " GPI:"); 6995171141Sariff res = hdac_command(sc, 6996182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 6997182999Smav printf(" data=0x%08x", res); 6998182999Smav res = hdac_command(sc, 6999182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7000182999Smav cad); 7001182999Smav printf(" wake=0x%08x", res); 7002182999Smav res = hdac_command(sc, 7003182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7004182999Smav cad); 7005182999Smav printf(" unsol=0x%08x", res); 7006182999Smav res = hdac_command(sc, 7007182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7008182999Smav printf(" sticky=0x%08x\n", res); 7009182999Smav } 7010182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7011182999Smav device_printf(dev, " GPO:"); 7012182999Smav res = hdac_command(sc, 7013182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7014182999Smav printf(" data=0x%08x\n", res); 7015182999Smav } 7016182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7017182999Smav device_printf(dev, "GPIO:"); 7018182999Smav res = hdac_command(sc, 7019182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7020182999Smav printf(" data=0x%08x", res); 7021182999Smav res = hdac_command(sc, 7022182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7023182999Smav printf(" enable=0x%08x", res); 7024182999Smav res = hdac_command(sc, 7025182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7026182999Smav printf(" direction=0x%08x\n", res); 7027182999Smav res = hdac_command(sc, 7028182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7029182999Smav device_printf(dev, " wake=0x%08x", res); 7030182999Smav res = hdac_command(sc, 7031182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7032182999Smav cad); 7033182999Smav printf(" unsol=0x%08x", res); 7034182999Smav res = hdac_command(sc, 7035182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7036182999Smav printf(" sticky=0x%08x\n", res); 7037182999Smav } 7038171141Sariff } 7039169277Sariff } 7040169277Sariff hdac_unlock(sc); 7041169277Sariff return (0); 7042169277Sariff} 7043164614Sariff#endif 7044164614Sariff 7045163057Sariffstatic void 7046162922Sariffhdac_attach2(void *arg) 7047162922Sariff{ 7048182999Smav struct hdac_codec *codec; 7049162922Sariff struct hdac_softc *sc; 7050162922Sariff struct hdac_audio_ctl *ctl; 7051163057Sariff uint32_t quirks_on, quirks_off; 7052182999Smav int codec_index, fg_index; 7053182999Smav int i, pdev, rdev, dmaalloc = 0; 7054182999Smav struct hdac_devinfo *devinfo; 7055162922Sariff 7056162922Sariff sc = (struct hdac_softc *)arg; 7057162922Sariff 7058163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7059162922Sariff 7060183097Smav HDA_BOOTHVERBOSE( 7061182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7062163057Sariff quirks_on, quirks_off); 7063163057Sariff ); 7064163057Sariff 7065162922Sariff hdac_lock(sc); 7066162922Sariff 7067162922Sariff /* Remove ourselves from the config hooks */ 7068162922Sariff if (sc->intrhook.ich_func != NULL) { 7069162922Sariff config_intrhook_disestablish(&sc->intrhook); 7070162922Sariff sc->intrhook.ich_func = NULL; 7071162922Sariff } 7072162922Sariff 7073162922Sariff /* Start the corb and rirb engines */ 7074183097Smav HDA_BOOTHVERBOSE( 7075182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7076162922Sariff ); 7077162922Sariff hdac_corb_start(sc); 7078183097Smav HDA_BOOTHVERBOSE( 7079182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7080162922Sariff ); 7081162922Sariff hdac_rirb_start(sc); 7082162922Sariff 7083183097Smav HDA_BOOTHVERBOSE( 7084162922Sariff device_printf(sc->dev, 7085182999Smav "Enabling controller interrupt...\n"); 7086162922Sariff ); 7087182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7088182999Smav HDAC_GCTL_UNSOL); 7089182999Smav if (sc->polling == 0) { 7090164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7091164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7092182999Smav } else { 7093182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7094182999Smav } 7095162922Sariff DELAY(1000); 7096162922Sariff 7097183097Smav HDA_BOOTHVERBOSE( 7098172811Sariff device_printf(sc->dev, 7099182999Smav "Scanning HDA codecs ...\n"); 7100162922Sariff ); 7101182999Smav hdac_scan_codecs(sc); 7102182999Smav 7103182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7104182999Smav codec = sc->codecs[codec_index]; 7105182999Smav if (codec == NULL) 7106182999Smav continue; 7107182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7108182999Smav devinfo = &codec->fgs[fg_index]; 7109183019Smav HDA_BOOTVERBOSE( 7110183019Smav device_printf(sc->dev, "\n"); 7111183097Smav device_printf(sc->dev, 7112183097Smav "Processing %s FG cad=%d nid=%d...\n", 7113183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7114183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7115183097Smav "unknown", 7116183097Smav devinfo->codec->cad, devinfo->nid); 7117183019Smav ); 7118182999Smav if (devinfo->node_type != 7119182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7120183097Smav HDA_BOOTHVERBOSE( 7121182999Smav device_printf(sc->dev, 7122183097Smav "Powering down...\n"); 7123182999Smav ); 7124182999Smav hdac_command(sc, 7125182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7126182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7127182999Smav codec->cad); 7128182999Smav continue; 7129182999Smav } 7130162922Sariff 7131183097Smav HDA_BOOTHVERBOSE( 7132183097Smav device_printf(sc->dev, "Powering up...\n"); 7133182999Smav ); 7134182999Smav hdac_powerup(devinfo); 7135183097Smav HDA_BOOTHVERBOSE( 7136182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7137182999Smav ); 7138182999Smav hdac_audio_parse(devinfo); 7139183097Smav HDA_BOOTHVERBOSE( 7140182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7141182999Smav ); 7142182999Smav hdac_audio_ctl_parse(devinfo); 7143183097Smav HDA_BOOTHVERBOSE( 7144182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7145182999Smav ); 7146182999Smav hdac_vendor_patch_parse(devinfo); 7147182999Smav devinfo->function.audio.quirks |= quirks_on; 7148182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7149162922Sariff 7150183097Smav HDA_BOOTHVERBOSE( 7151182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7152182999Smav ); 7153182999Smav hdac_audio_disable_nonaudio(devinfo); 7154183097Smav HDA_BOOTHVERBOSE( 7155182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7156182999Smav ); 7157182999Smav hdac_audio_disable_useless(devinfo); 7158182999Smav HDA_BOOTVERBOSE( 7159182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7160182999Smav hdac_dump_pin_configs(devinfo); 7161183097Smav ); 7162183097Smav HDA_BOOTHVERBOSE( 7163182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7164182999Smav ); 7165182999Smav hdac_audio_as_parse(devinfo); 7166183097Smav HDA_BOOTHVERBOSE( 7167182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7168182999Smav ); 7169182999Smav hdac_audio_build_tree(devinfo); 7170183097Smav HDA_BOOTHVERBOSE( 7171182999Smav device_printf(sc->dev, "Disabling unassociated " 7172182999Smav "widgets...\n"); 7173182999Smav ); 7174182999Smav hdac_audio_disable_unas(devinfo); 7175183097Smav HDA_BOOTHVERBOSE( 7176182999Smav device_printf(sc->dev, "Disabling nonselected " 7177182999Smav "inputs...\n"); 7178182999Smav ); 7179182999Smav hdac_audio_disable_notselected(devinfo); 7180183097Smav HDA_BOOTHVERBOSE( 7181182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7182182999Smav ); 7183182999Smav hdac_audio_disable_useless(devinfo); 7184183097Smav HDA_BOOTHVERBOSE( 7185182999Smav device_printf(sc->dev, "Disabling " 7186182999Smav "crossassociatement connections...\n"); 7187182999Smav ); 7188182999Smav hdac_audio_disable_crossas(devinfo); 7189183097Smav HDA_BOOTHVERBOSE( 7190182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7191182999Smav ); 7192182999Smav hdac_audio_disable_useless(devinfo); 7193183097Smav HDA_BOOTHVERBOSE( 7194182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7195182999Smav ); 7196182999Smav hdac_audio_bind_as(devinfo); 7197183097Smav HDA_BOOTHVERBOSE( 7198182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7199182999Smav ); 7200182999Smav hdac_audio_assign_names(devinfo); 7201183097Smav HDA_BOOTHVERBOSE( 7202182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7203182999Smav ); 7204182999Smav hdac_audio_assign_mixers(devinfo); 7205183097Smav HDA_BOOTHVERBOSE( 7206182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7207182999Smav ); 7208182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7209183097Smav HDA_BOOTHVERBOSE( 7210182999Smav device_printf(sc->dev, "AFG commit...\n"); 7211182999Smav ); 7212182999Smav hdac_audio_commit(devinfo); 7213183097Smav HDA_BOOTHVERBOSE( 7214182999Smav device_printf(sc->dev, "Ctls commit...\n"); 7215182999Smav ); 7216182999Smav hdac_audio_ctl_commit(devinfo); 7217183097Smav HDA_BOOTHVERBOSE( 7218182999Smav device_printf(sc->dev, "HP switch init...\n"); 7219182999Smav ); 7220182999Smav hdac_hp_switch_init(devinfo); 7221182999Smav 7222182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7223182999Smav dmaalloc == 0) { 7224182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7225182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7226182999Smav HDA_BOOTVERBOSE( 7227182999Smav device_printf(sc->dev, "Failed to " 7228182999Smav "allocate DMA pos buffer " 7229182999Smav "(non-fatal)\n"); 7230182999Smav ); 7231182999Smav } else 7232182999Smav dmaalloc = 1; 7233182999Smav } 7234182999Smav 7235182999Smav i = devinfo->function.audio.playcnt; 7236182999Smav if (devinfo->function.audio.reccnt > i) 7237182999Smav i = devinfo->function.audio.reccnt; 7238182999Smav devinfo->function.audio.devs = 7239182999Smav (struct hdac_pcm_devinfo *)malloc( 7240182999Smav sizeof(struct hdac_pcm_devinfo) * i, 7241182999Smav M_HDAC, M_ZERO | M_NOWAIT); 7242182999Smav if (devinfo->function.audio.devs == NULL) { 7243182999Smav device_printf(sc->dev, 7244182999Smav "Unable to allocate memory for devices\n"); 7245182999Smav continue; 7246182999Smav } 7247182999Smav devinfo->function.audio.num_devs = i; 7248182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7249182999Smav devinfo->function.audio.devs[i].index = i; 7250182999Smav devinfo->function.audio.devs[i].devinfo = devinfo; 7251182999Smav devinfo->function.audio.devs[i].play = -1; 7252182999Smav devinfo->function.audio.devs[i].rec = -1; 7253182999Smav } 7254182999Smav pdev = 0; 7255182999Smav rdev = 0; 7256182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 7257182999Smav if (devinfo->function.audio.as[i].enable == 0) 7258182999Smav continue; 7259182999Smav if (devinfo->function.audio.as[i].dir == 7260182999Smav HDA_CTL_IN) { 7261182999Smav devinfo->function.audio.devs[rdev].rec 7262182999Smav = devinfo->function.audio.as[i].chan; 7263182999Smav sc->chans[devinfo->function.audio.as[i].chan].pdevinfo = 7264182999Smav &devinfo->function.audio.devs[rdev]; 7265182999Smav rdev++; 7266182999Smav } else { 7267182999Smav devinfo->function.audio.devs[pdev].play 7268182999Smav = devinfo->function.audio.as[i].chan; 7269182999Smav sc->chans[devinfo->function.audio.as[i].chan].pdevinfo = 7270182999Smav &devinfo->function.audio.devs[pdev]; 7271182999Smav pdev++; 7272182999Smav } 7273182999Smav } 7274182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7275182999Smav struct hdac_pcm_devinfo *pdevinfo = 7276182999Smav &devinfo->function.audio.devs[i]; 7277182999Smav pdevinfo->dev = 7278182999Smav device_add_child(sc->dev, "pcm", -1); 7279182999Smav device_set_ivars(pdevinfo->dev, 7280182999Smav (void *)pdevinfo); 7281182999Smav } 7282182999Smav 7283182999Smav HDA_BOOTVERBOSE( 7284182999Smav if (devinfo->function.audio.quirks != 0) { 7285183097Smav device_printf(sc->dev, "FG config/quirks:"); 7286182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7287182999Smav if ((devinfo->function.audio.quirks & 7288182999Smav hdac_quirks_tab[i].value) == 7289182999Smav hdac_quirks_tab[i].value) 7290182999Smav printf(" %s", hdac_quirks_tab[i].key); 7291182999Smav } 7292182999Smav printf("\n"); 7293182999Smav } 7294182999Smav 7295182999Smav device_printf(sc->dev, "\n"); 7296182999Smav device_printf(sc->dev, "+-------------------+\n"); 7297182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7298182999Smav device_printf(sc->dev, "+-------------------+\n"); 7299182999Smav hdac_dump_nodes(devinfo); 7300183097Smav ); 7301182999Smav 7302183097Smav HDA_BOOTHVERBOSE( 7303182999Smav device_printf(sc->dev, "\n"); 7304182999Smav device_printf(sc->dev, "+------------------------+\n"); 7305182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7306182999Smav device_printf(sc->dev, "+------------------------+\n"); 7307182999Smav device_printf(sc->dev, "\n"); 7308182999Smav i = 0; 7309182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7310182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7311182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7312182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7313182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7314182999Smav ctl->index); 7315182999Smav if (ctl->childwidget != NULL) 7316182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7317182999Smav else 7318182999Smav printf(" "); 7319182999Smav printf(" ossmask=0x%08x\n", 7320182999Smav ctl->ossmask); 7321182999Smav device_printf(sc->dev, 7322182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7323182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7324182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7325182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7326182999Smav } 7327182999Smav ); 7328182999Smav } 7329162922Sariff } 7330182999Smav hdac_unlock(sc); 7331162922Sariff 7332163057Sariff HDA_BOOTVERBOSE( 7333182999Smav device_printf(sc->dev, "\n"); 7334162922Sariff ); 7335182999Smav 7336182999Smav bus_generic_attach(sc->dev); 7337182999Smav 7338182999Smav#ifdef SND_DYNSYSCTL 7339182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7340182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7341182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7342182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7343182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7344182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7345182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7346182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7347182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7348182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7349182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7350182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7351182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7352182999Smav#endif 7353182999Smav} 7354182999Smav 7355182999Smav/**************************************************************************** 7356182999Smav * int hdac_suspend(device_t) 7357182999Smav * 7358182999Smav * Suspend and power down HDA bus and codecs. 7359182999Smav ****************************************************************************/ 7360182999Smavstatic int 7361182999Smavhdac_suspend(device_t dev) 7362182999Smav{ 7363182999Smav struct hdac_softc *sc; 7364182999Smav struct hdac_codec *codec; 7365182999Smav struct hdac_devinfo *devinfo; 7366182999Smav int codec_index, fg_index, i; 7367182999Smav 7368183097Smav HDA_BOOTHVERBOSE( 7369182999Smav device_printf(dev, "Suspend...\n"); 7370162922Sariff ); 7371182999Smav 7372182999Smav sc = device_get_softc(dev); 7373182999Smav hdac_lock(sc); 7374182999Smav 7375183097Smav HDA_BOOTHVERBOSE( 7376182999Smav device_printf(dev, "Stop streams...\n"); 7377162922Sariff ); 7378182999Smav for (i = 0; i < sc->num_chans; i++) { 7379182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7380182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7381182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7382182999Smav } 7383182999Smav } 7384162922Sariff 7385182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7386182999Smav codec = sc->codecs[codec_index]; 7387182999Smav if (codec == NULL) 7388162922Sariff continue; 7389182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7390182999Smav devinfo = &codec->fgs[fg_index]; 7391183097Smav HDA_BOOTHVERBOSE( 7392182999Smav device_printf(dev, 7393182999Smav "Power down FG" 7394182999Smav " cad=%d nid=%d to the D3 state...\n", 7395182999Smav codec->cad, devinfo->nid); 7396182999Smav ); 7397182999Smav hdac_command(sc, 7398182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7399182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7400182999Smav codec->cad); 7401162922Sariff } 7402162922Sariff } 7403162922Sariff 7404183097Smav HDA_BOOTHVERBOSE( 7405182999Smav device_printf(dev, "Reset controller...\n"); 7406162922Sariff ); 7407182999Smav callout_stop(&sc->poll_hda); 7408182999Smav callout_stop(&sc->poll_hdac); 7409182999Smav callout_stop(&sc->poll_jack); 7410182999Smav hdac_reset(sc, 0); 7411182999Smav hdac_unlock(sc); 7412182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7413182999Smav callout_drain(&sc->poll_hda); 7414182999Smav callout_drain(&sc->poll_hdac); 7415182999Smav callout_drain(&sc->poll_jack); 7416162922Sariff 7417183097Smav HDA_BOOTHVERBOSE( 7418182999Smav device_printf(dev, "Suspend done\n"); 7419162922Sariff ); 7420182999Smav 7421182999Smav return (0); 7422182999Smav} 7423182999Smav 7424182999Smav/**************************************************************************** 7425182999Smav * int hdac_resume(device_t) 7426182999Smav * 7427182999Smav * Powerup and restore HDA bus and codecs state. 7428182999Smav ****************************************************************************/ 7429182999Smavstatic int 7430182999Smavhdac_resume(device_t dev) 7431182999Smav{ 7432182999Smav struct hdac_softc *sc; 7433182999Smav struct hdac_codec *codec; 7434182999Smav struct hdac_devinfo *devinfo; 7435182999Smav int codec_index, fg_index, i; 7436182999Smav 7437183097Smav HDA_BOOTHVERBOSE( 7438182999Smav device_printf(dev, "Resume...\n"); 7439162922Sariff ); 7440162922Sariff 7441182999Smav sc = device_get_softc(dev); 7442182999Smav hdac_lock(sc); 7443182999Smav 7444182999Smav /* Quiesce everything */ 7445183097Smav HDA_BOOTHVERBOSE( 7446182999Smav device_printf(dev, "Reset controller...\n"); 7447162922Sariff ); 7448182999Smav hdac_reset(sc, 1); 7449182999Smav 7450182999Smav /* Initialize the CORB and RIRB */ 7451182999Smav hdac_corb_init(sc); 7452182999Smav hdac_rirb_init(sc); 7453182999Smav 7454182999Smav /* Start the corb and rirb engines */ 7455183097Smav HDA_BOOTHVERBOSE( 7456182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7457162922Sariff ); 7458182999Smav hdac_corb_start(sc); 7459183097Smav HDA_BOOTHVERBOSE( 7460182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7461162922Sariff ); 7462182999Smav hdac_rirb_start(sc); 7463163057Sariff 7464183097Smav HDA_BOOTHVERBOSE( 7465182999Smav device_printf(dev, 7466182999Smav "Enabling controller interrupt...\n"); 7467162922Sariff ); 7468182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7469182999Smav HDAC_GCTL_UNSOL); 7470182999Smav if (sc->polling == 0) { 7471182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7472182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7473182999Smav } else { 7474182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7475182999Smav } 7476182999Smav DELAY(1000); 7477162922Sariff 7478182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7479182999Smav codec = sc->codecs[codec_index]; 7480182999Smav if (codec == NULL) 7481182999Smav continue; 7482182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7483182999Smav devinfo = &codec->fgs[fg_index]; 7484182999Smav if (devinfo->node_type != 7485182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7486183097Smav HDA_BOOTHVERBOSE( 7487182999Smav device_printf(dev, 7488182999Smav "Power down unsupported non-audio FG" 7489182999Smav " cad=%d nid=%d to the D3 state...\n", 7490182999Smav codec->cad, devinfo->nid); 7491182999Smav ); 7492182999Smav hdac_command(sc, 7493182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7494182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7495182999Smav codec->cad); 7496182999Smav continue; 7497182999Smav } 7498162922Sariff 7499183097Smav HDA_BOOTHVERBOSE( 7500182999Smav device_printf(dev, 7501182999Smav "Power up audio FG cad=%d nid=%d...\n", 7502182999Smav devinfo->codec->cad, devinfo->nid); 7503182999Smav ); 7504182999Smav hdac_powerup(devinfo); 7505183097Smav HDA_BOOTHVERBOSE( 7506182999Smav device_printf(dev, "AFG commit...\n"); 7507182999Smav ); 7508182999Smav hdac_audio_commit(devinfo); 7509183097Smav HDA_BOOTHVERBOSE( 7510182999Smav device_printf(dev, "Ctls commit...\n"); 7511182999Smav ); 7512182999Smav hdac_audio_ctl_commit(devinfo); 7513183097Smav HDA_BOOTHVERBOSE( 7514182999Smav device_printf(dev, "HP switch init...\n"); 7515182999Smav ); 7516182999Smav hdac_hp_switch_init(devinfo); 7517182999Smav 7518182999Smav hdac_unlock(sc); 7519182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 7520182999Smav struct hdac_pcm_devinfo *pdevinfo = 7521182999Smav &devinfo->function.audio.devs[i]; 7522183097Smav HDA_BOOTHVERBOSE( 7523182999Smav device_printf(pdevinfo->dev, 7524182999Smav "OSS mixer reinitialization...\n"); 7525182999Smav ); 7526182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 7527182999Smav device_printf(pdevinfo->dev, 7528182999Smav "unable to reinitialize the mixer\n"); 7529182999Smav } 7530182999Smav hdac_lock(sc); 7531182999Smav } 7532169277Sariff } 7533169277Sariff 7534183097Smav HDA_BOOTHVERBOSE( 7535182999Smav device_printf(dev, "Start streams...\n"); 7536163057Sariff ); 7537182999Smav for (i = 0; i < sc->num_chans; i++) { 7538182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 7539182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 7540182999Smav hdac_channel_start(sc, &sc->chans[i]); 7541182999Smav } 7542182999Smav } 7543162922Sariff 7544182999Smav hdac_unlock(sc); 7545182999Smav 7546183097Smav HDA_BOOTHVERBOSE( 7547182999Smav device_printf(dev, "Resume done\n"); 7548162922Sariff ); 7549164614Sariff 7550182999Smav return (0); 7551162922Sariff} 7552162922Sariff/**************************************************************************** 7553162922Sariff * int hdac_detach(device_t) 7554162922Sariff * 7555162922Sariff * Detach and free up resources utilized by the hdac device. 7556162922Sariff ****************************************************************************/ 7557162922Sariffstatic int 7558162922Sariffhdac_detach(device_t dev) 7559162922Sariff{ 7560182999Smav struct hdac_softc *sc; 7561182999Smav device_t *devlist = NULL; 7562182999Smav int i, devcount; 7563162922Sariff 7564182999Smav sc = device_get_softc(dev); 7565162922Sariff 7566182999Smav device_get_children(dev, &devlist, &devcount); 7567182999Smav for (i = 0; devlist != NULL && i < devcount; i++) 7568182999Smav device_delete_child(dev, devlist[i]); 7569182999Smav if (devlist != NULL) 7570182999Smav free(devlist, M_TEMP); 7571162922Sariff 7572163057Sariff hdac_release_resources(sc); 7573162922Sariff 7574162922Sariff return (0); 7575162922Sariff} 7576162922Sariff 7577184095Smavstatic int 7578184095Smavhdac_print_child(device_t dev, device_t child) 7579184095Smav{ 7580184095Smav struct hdac_pcm_devinfo *pdevinfo = 7581184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 7582184095Smav int retval; 7583184095Smav 7584184095Smav retval = bus_print_child_header(dev, child); 7585184095Smav retval += printf(" at cad %d nid %d", 7586184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 7587184095Smav retval += bus_print_child_footer(dev, child); 7588184095Smav 7589184095Smav return (retval); 7590184095Smav} 7591184095Smav 7592162922Sariffstatic device_method_t hdac_methods[] = { 7593162922Sariff /* device interface */ 7594162922Sariff DEVMETHOD(device_probe, hdac_probe), 7595162922Sariff DEVMETHOD(device_attach, hdac_attach), 7596162922Sariff DEVMETHOD(device_detach, hdac_detach), 7597182999Smav DEVMETHOD(device_suspend, hdac_suspend), 7598182999Smav DEVMETHOD(device_resume, hdac_resume), 7599184095Smav /* Bus interface */ 7600184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 7601162922Sariff { 0, 0 } 7602162922Sariff}; 7603162922Sariff 7604162922Sariffstatic driver_t hdac_driver = { 7605182999Smav "hdac", 7606162922Sariff hdac_methods, 7607182999Smav sizeof(struct hdac_softc), 7608162922Sariff}; 7609162922Sariff 7610182999Smavstatic devclass_t hdac_devclass; 7611182999Smav 7612182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 7613162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 7614162922SariffMODULE_VERSION(snd_hda, 1); 7615182999Smav 7616182999Smavstatic int 7617182999Smavhdac_pcm_probe(device_t dev) 7618182999Smav{ 7619182999Smav struct hdac_pcm_devinfo *pdevinfo = 7620182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7621182999Smav char buf[128]; 7622182999Smav 7623184095Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d", 7624182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 7625182999Smav pdevinfo->index); 7626182999Smav device_set_desc_copy(dev, buf); 7627182999Smav return (0); 7628182999Smav} 7629182999Smav 7630182999Smavstatic int 7631182999Smavhdac_pcm_attach(device_t dev) 7632182999Smav{ 7633182999Smav struct hdac_pcm_devinfo *pdevinfo = 7634182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7635182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7636182999Smav char status[SND_STATUSLEN]; 7637182999Smav int i; 7638182999Smav 7639182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 7640182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 7641182999Smav 7642182999Smav HDA_BOOTVERBOSE( 7643182999Smav device_printf(dev, "+--------------------------------------+\n"); 7644182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 7645182999Smav device_printf(dev, "+--------------------------------------+\n"); 7646182999Smav hdac_dump_pcmchannels(pdevinfo); 7647182999Smav device_printf(dev, "\n"); 7648182999Smav device_printf(dev, "+--------------------------------+\n"); 7649182999Smav device_printf(dev, "| DUMPING Playback/Record Pathes |\n"); 7650182999Smav device_printf(dev, "+--------------------------------+\n"); 7651182999Smav hdac_dump_dac(pdevinfo); 7652182999Smav hdac_dump_adc(pdevinfo); 7653182999Smav hdac_dump_mix(pdevinfo); 7654182999Smav device_printf(dev, "\n"); 7655182999Smav device_printf(dev, "+-------------------------+\n"); 7656182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 7657182999Smav device_printf(dev, "+-------------------------+\n"); 7658182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 7659182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 7660182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 7661182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 7662182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 7663182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 7664182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 7665182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 7666182999Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 7667182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 7668182999Smav device_printf(dev, "\n"); 7669182999Smav ); 7670182999Smav 7671182999Smav if (resource_int_value(device_get_name(dev), 7672182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 7673182999Smav i &= HDA_BLK_ALIGN; 7674182999Smav if (i < HDA_BLK_MIN) 7675182999Smav i = HDA_BLK_MIN; 7676182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 7677182999Smav i = 0; 7678182999Smav while (pdevinfo->chan_blkcnt >> i) 7679182999Smav i++; 7680182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 7681182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 7682182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 7683182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 7684182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 7685182999Smav } else 7686182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 7687182999Smav 7688182999Smav /* 7689182999Smav * We don't register interrupt handler with snd_setup_intr 7690182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 7691182999Smav */ 7692182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 7693182999Smav 7694183097Smav HDA_BOOTHVERBOSE( 7695182999Smav device_printf(dev, "OSS mixer initialization...\n"); 7696182999Smav ); 7697182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 7698182999Smav device_printf(dev, "Can't register mixer\n"); 7699182999Smav 7700183097Smav HDA_BOOTHVERBOSE( 7701182999Smav device_printf(dev, "Registering PCM channels...\n"); 7702182999Smav ); 7703182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 7704182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 7705182999Smav device_printf(dev, "Can't register PCM\n"); 7706182999Smav 7707182999Smav pdevinfo->registered++; 7708182999Smav 7709182999Smav if (pdevinfo->play >= 0) 7710182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 7711182999Smav if (pdevinfo->rec >= 0) 7712182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 7713182999Smav 7714184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 7715184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 7716184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 7717182999Smav pcm_setstatus(dev, status); 7718182999Smav 7719182999Smav return (0); 7720182999Smav} 7721182999Smav 7722182999Smavstatic int 7723182999Smavhdac_pcm_detach(device_t dev) 7724182999Smav{ 7725182999Smav struct hdac_pcm_devinfo *pdevinfo = 7726182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 7727182999Smav int err; 7728182999Smav 7729182999Smav if (pdevinfo->registered > 0) { 7730182999Smav err = pcm_unregister(dev); 7731182999Smav if (err != 0) 7732182999Smav return (err); 7733182999Smav } 7734182999Smav 7735182999Smav return (0); 7736182999Smav} 7737182999Smav 7738182999Smavstatic device_method_t hdac_pcm_methods[] = { 7739182999Smav /* device interface */ 7740182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 7741182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 7742182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 7743182999Smav { 0, 0 } 7744182999Smav}; 7745182999Smav 7746182999Smavstatic driver_t hdac_pcm_driver = { 7747182999Smav "pcm", 7748182999Smav hdac_pcm_methods, 7749182999Smav PCM_SOFTC_SIZE, 7750182999Smav}; 7751182999Smav 7752182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 7753182999Smav 7754