hdac.c revision 211910
1162922Sariff/*- 2162922Sariff * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3162922Sariff * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4182999Smav * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org> 5162922Sariff * All rights reserved. 6162922Sariff * 7162922Sariff * Redistribution and use in source and binary forms, with or without 8162922Sariff * modification, are permitted provided that the following conditions 9162922Sariff * are met: 10162922Sariff * 1. Redistributions of source code must retain the above copyright 11162922Sariff * notice, this list of conditions and the following disclaimer. 12162922Sariff * 2. Redistributions in binary form must reproduce the above copyright 13162922Sariff * notice, this list of conditions and the following disclaimer in the 14162922Sariff * documentation and/or other materials provided with the distribution. 15162922Sariff * 16162922Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19162922Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26162922Sariff * SUCH DAMAGE. 27162922Sariff */ 28162922Sariff 29162922Sariff/* 30162922Sariff * Intel High Definition Audio (Controller) driver for FreeBSD. Be advised 31162922Sariff * that this driver still in its early stage, and possible of rewrite are 32162922Sariff * pretty much guaranteed. There are supposedly several distinct parent/child 33162922Sariff * busses to make this "perfect", but as for now and for the sake of 34162922Sariff * simplicity, everything is gobble up within single source. 35162922Sariff * 36162922Sariff * List of subsys: 37162922Sariff * 1) HDA Controller support 38162922Sariff * 2) HDA Codecs support, which may include 39162922Sariff * - HDA 40162922Sariff * - Modem 41162922Sariff * 3) Widget parser - the real magic of why this driver works on so 42162922Sariff * many hardwares with minimal vendor specific quirk. The original 43162922Sariff * parser was written using Ruby and can be found at 44162922Sariff * http://people.freebsd.org/~ariff/HDA/parser.rb . This crude 45162922Sariff * ruby parser take the verbose dmesg dump as its input. Refer to 46162922Sariff * http://www.microsoft.com/whdc/device/audio/default.mspx for various 47164614Sariff * interesting documents, especially UAA (Universal Audio Architecture). 48162922Sariff * 4) Possible vendor specific support. 49162922Sariff * (snd_hda_intel, snd_hda_ati, etc..) 50162922Sariff * 51162922Sariff * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the 52162922Sariff * Compaq V3000 with Conexant HDA. 53162922Sariff * 54162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 55162922Sariff * * * 56162922Sariff * * This driver is a collaborative effort made by: * 57162922Sariff * * * 58162922Sariff * * Stephane E. Potvin <sepotvin@videotron.ca> * 59162922Sariff * * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * 60162922Sariff * * Wesley Morgan <morganw@chemikals.org> * 61162922Sariff * * Daniel Eischen <deischen@FreeBSD.org> * 62162922Sariff * * Maxime Guillaud <bsd-ports@mguillaud.net> * 63162922Sariff * * Ariff Abdullah <ariff@FreeBSD.org> * 64182999Smav * * Alexander Motin <mav@FreeBSD.org> * 65162922Sariff * * * 66162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 67162922Sariff * * * 68162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 69162922Sariff */ 70162922Sariff 71193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 72193640Sariff#include "opt_snd.h" 73193640Sariff#endif 74193640Sariff 75162922Sariff#include <dev/sound/pcm/sound.h> 76162922Sariff#include <dev/pci/pcireg.h> 77162922Sariff#include <dev/pci/pcivar.h> 78162922Sariff 79171141Sariff#include <sys/ctype.h> 80171141Sariff#include <sys/taskqueue.h> 81171141Sariff 82162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 83162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 84162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 85162922Sariff#include <dev/sound/pci/hda/hdac.h> 86162922Sariff 87162922Sariff#include "mixer_if.h" 88162922Sariff 89204351Smav#define HDA_DRV_TEST_REV "20100226_0142" 90162922Sariff 91162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 211910 2010-08-28 00:23:13Z jfv $"); 92162922Sariff 93169277Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 94169277Sariff if (bootverbose != 0 || snd_verbose > 3) { \ 95169277Sariff stmt \ 96169277Sariff } \ 97193640Sariff} while (0) 98162922Sariff 99183097Smav#define HDA_BOOTHVERBOSE(stmt) do { \ 100183097Smav if (snd_verbose > 3) { \ 101183097Smav stmt \ 102183097Smav } \ 103193640Sariff} while (0) 104183097Smav 105162965Sariff#if 1 106162922Sariff#undef HDAC_INTR_EXTRA 107162922Sariff#define HDAC_INTR_EXTRA 1 108162922Sariff#endif 109162922Sariff 110162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 111162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 112163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 113163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 114162922Sariff 115162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 116163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 117163257Sariff (fl) == 0xffffffff || \ 118163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 119163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 120163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 121163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 122162965Sariff#define HDA_MATCH_ALL 0xffffffff 123162965Sariff#define HDAC_INVALID 0xffffffff 124162965Sariff 125169277Sariff/* Default controller / jack sense poll: 250ms */ 126169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 127169277Sariff 128171141Sariff/* 129171141Sariff * Make room for possible 4096 playback/record channels, in 100 years to come. 130171141Sariff */ 131171141Sariff#define HDAC_TRIGGER_NONE 0x00000000 132171141Sariff#define HDAC_TRIGGER_PLAY 0x00000fff 133171141Sariff#define HDAC_TRIGGER_REC 0x00fff000 134171141Sariff#define HDAC_TRIGGER_UNSOL 0x80000000 135171141Sariff 136162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 137162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 138162922Sariff 139162922Sariff/* Controller models */ 140162922Sariff 141162922Sariff/* Intel */ 142162922Sariff#define INTEL_VENDORID 0x8086 143211910Sjfv#define HDA_INTEL_CPT HDA_MODEL_CONSTRUCT(INTEL, 0x1c20) 144162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 145171330Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 146162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 147163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 148171330Sariff#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e) 149197017Smav#define HDA_INTEL_82801JI HDA_MODEL_CONSTRUCT(INTEL, 0x3a3e) 150197017Smav#define HDA_INTEL_82801JD HDA_MODEL_CONSTRUCT(INTEL, 0x3a6e) 151187020Smav#define HDA_INTEL_PCH HDA_MODEL_CONSTRUCT(INTEL, 0x3b56) 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) 165186511Smav#define HDA_NVIDIA_MCP78_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0774) 166186511Smav#define HDA_NVIDIA_MCP78_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0775) 167186511Smav#define HDA_NVIDIA_MCP78_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0776) 168186511Smav#define HDA_NVIDIA_MCP78_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0777) 169186511Smav#define HDA_NVIDIA_MCP73_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fc) 170186511Smav#define HDA_NVIDIA_MCP73_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x07fd) 171186511Smav#define HDA_NVIDIA_MCP79_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac0) 172186511Smav#define HDA_NVIDIA_MCP79_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac1) 173186511Smav#define HDA_NVIDIA_MCP79_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac2) 174186511Smav#define HDA_NVIDIA_MCP79_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac3) 175197018Smav#define HDA_NVIDIA_MCP89_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d94) 176197018Smav#define HDA_NVIDIA_MCP89_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d95) 177197018Smav#define HDA_NVIDIA_MCP89_3 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d96) 178197018Smav#define HDA_NVIDIA_MCP89_4 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d97) 179162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 180162922Sariff 181162922Sariff/* ATI */ 182162922Sariff#define ATI_VENDORID 0x1002 183162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 184163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 185187020Smav#define HDA_ATI_RS600 HDA_MODEL_CONSTRUCT(ATI, 0x793b) 186187020Smav#define HDA_ATI_RS690 HDA_MODEL_CONSTRUCT(ATI, 0x7919) 187187020Smav#define HDA_ATI_RS780 HDA_MODEL_CONSTRUCT(ATI, 0x960f) 188187020Smav#define HDA_ATI_R600 HDA_MODEL_CONSTRUCT(ATI, 0xaa00) 189187020Smav#define HDA_ATI_RV630 HDA_MODEL_CONSTRUCT(ATI, 0xaa08) 190187020Smav#define HDA_ATI_RV610 HDA_MODEL_CONSTRUCT(ATI, 0xaa10) 191187020Smav#define HDA_ATI_RV670 HDA_MODEL_CONSTRUCT(ATI, 0xaa18) 192187020Smav#define HDA_ATI_RV635 HDA_MODEL_CONSTRUCT(ATI, 0xaa20) 193187020Smav#define HDA_ATI_RV620 HDA_MODEL_CONSTRUCT(ATI, 0xaa28) 194187020Smav#define HDA_ATI_RV770 HDA_MODEL_CONSTRUCT(ATI, 0xaa30) 195187020Smav#define HDA_ATI_RV730 HDA_MODEL_CONSTRUCT(ATI, 0xaa38) 196187020Smav#define HDA_ATI_RV710 HDA_MODEL_CONSTRUCT(ATI, 0xaa40) 197187020Smav#define HDA_ATI_RV740 HDA_MODEL_CONSTRUCT(ATI, 0xaa48) 198162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 199162922Sariff 200163136Sariff/* VIA */ 201163136Sariff#define VIA_VENDORID 0x1106 202163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 203163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 204163136Sariff 205163136Sariff/* SiS */ 206163136Sariff#define SIS_VENDORID 0x1039 207163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 208163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 209163136Sariff 210186301Smav/* ULI */ 211186301Smav#define ULI_VENDORID 0x10b9 212186301Smav#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461) 213186301Smav#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff) 214186301Smav 215162922Sariff/* OEM/subvendors */ 216162922Sariff 217165466Sariff/* Intel */ 218165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 219165466Sariff 220162922Sariff/* HP/Compaq */ 221162922Sariff#define HP_VENDORID 0x103c 222162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 223162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 224162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 225165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 226166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 227169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 228169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 229174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 230172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 231162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 232165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 233165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 234162922Sariff 235162922Sariff/* Dell */ 236162922Sariff#define DELL_VENDORID 0x1028 237180532Sdelphij#define DELL_D630_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01f9) 238162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 239184483Smav#define DELL_V1400_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0227) 240178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 241162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 242169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 243169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 244162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 245162922Sariff 246162922Sariff/* Clevo */ 247162922Sariff#define CLEVO_VENDORID 0x1558 248162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 249162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 250162922Sariff 251162922Sariff/* Acer */ 252162922Sariff#define ACER_VENDORID 0x1025 253165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 254173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 255174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 256182854Sjoel#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133) 257169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 258182999Smav#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b) 259189879Smav#define ACER_T5320_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011f) 260162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 261162922Sariff 262162965Sariff/* Asus */ 263162965Sariff#define ASUS_VENDORID 0x1043 264178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 265163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 266178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 267165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 268178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 269178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 270167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 271169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 272178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 273190630Smav#define ASUS_P5PL2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x817f) 274178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 275178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 276170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 277178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 278169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 279171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 280162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 281162922Sariff 282163257Sariff/* IBM / Lenovo */ 283163257Sariff#define IBM_VENDORID 0x1014 284163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 285163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 286162965Sariff 287164614Sariff/* Lenovo */ 288164657Sariff#define LENOVO_VENDORID 0x17aa 289164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 290182854Sjoel#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e) 291172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 292164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 293163257Sariff 294164657Sariff/* Samsung */ 295164657Sariff#define SAMSUNG_VENDORID 0x144d 296164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 297164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 298164614Sariff 299164750Sariff/* Medion ? */ 300164750Sariff#define MEDION_VENDORID 0x161f 301164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 302164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 303164750Sariff 304173817Sariff/* Apple Computer Inc. */ 305173817Sariff#define APPLE_VENDORID 0x106b 306173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 307173817Sariff 308182999Smav/* Sony */ 309182999Smav#define SONY_VENDORID 0x104d 310182999Smav#define SONY_S5_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0x81cc) 311182999Smav#define SONY_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SONY, 0xffff) 312182999Smav 313164828Sariff/* 314164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 315164828Sariff * instead of their own, which is beyond my comprehension 316164828Sariff * (see HDA_CODEC_STAC9221 below). 317164828Sariff */ 318164828Sariff#define APPLE_INTEL_MAC 0x76808384 319199846Smav#define APPLE_MACBOOKPRO55 0xcb7910de 320164828Sariff 321165281Sariff/* LG Electronics */ 322165281Sariff#define LG_VENDORID 0x1854 323165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 324165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 325165281Sariff 326165351Sariff/* Fujitsu Siemens */ 327165351Sariff#define FS_VENDORID 0x1734 328165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 329172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 330165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 331165351Sariff 332172811Sariff/* Fujitsu Limited */ 333172811Sariff#define FL_VENDORID 0x10cf 334172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 335182854Sjoel#define FL_U1010_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x142d) 336172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 337172811Sariff 338165770Sariff/* Toshiba */ 339165770Sariff#define TOSHIBA_VENDORID 0x1179 340165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 341173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 342165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 343165770Sariff 344165992Sariff/* Micro-Star International (MSI) */ 345165992Sariff#define MSI_VENDORID 0x1462 346165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 347172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 348165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 349165992Sariff 350172811Sariff/* Giga-Byte Technology */ 351172811Sariff#define GB_VENDORID 0x1458 352172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 353172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 354172811Sariff 355169277Sariff/* Uniwill ? */ 356169277Sariff#define UNIWILL_VENDORID 0x1584 357169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 358170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 359169277Sariff 360169277Sariff 361162922Sariff/* Misc constants.. */ 362182999Smav#define HDA_AMP_VOL_DEFAULT (-1) 363162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 364162922Sariff#define HDA_AMP_MUTE_NONE (0) 365162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 366162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 367162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 368162922Sariff 369162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 370162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 371162922Sariff 372182999Smav#define HDA_ADC_MONITOR (1 << 0) 373162922Sariff 374182999Smav#define HDA_CTL_OUT 1 375182999Smav#define HDA_CTL_IN 2 376169277Sariff 377169277Sariff#define HDA_GPIO_MAX 8 378169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 379163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 380163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 381163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 382169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 383169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 384169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 385169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 386169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 387169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 388162922Sariff 389169277Sariff/* 9 - 25 = anything else */ 390169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 391169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 392169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 393169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 394169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 395182999Smav#define HDA_QUIRK_SENSEINV (1 << 14) 396169277Sariff 397169277Sariff/* 26 - 31 = vrefs */ 398169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 399169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 400169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 401169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 402169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 403169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 404169277Sariff 405169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 406169277Sariff HDA_QUIRK_IVREF100) 407169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 408169277Sariff HDA_QUIRK_OVREF100) 409169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 410169277Sariff 411171141Sariff#if __FreeBSD_version < 600000 412171141Sariff#define taskqueue_drain(...) 413171141Sariff#endif 414171141Sariff 415163057Sariffstatic const struct { 416163057Sariff char *key; 417163057Sariff uint32_t value; 418163057Sariff} hdac_quirks_tab[] = { 419163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 420163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 421163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 422169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 423169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 424169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 425169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 426169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 427165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 428163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 429163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 430163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 431163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 432169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 433182999Smav { "senseinv", HDA_QUIRK_SENSEINV }, 434169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 435169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 436169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 437169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 438169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 439169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 440169277Sariff { "ivref", HDA_QUIRK_IVREF }, 441169277Sariff { "ovref", HDA_QUIRK_OVREF }, 442165069Sariff { "vref", HDA_QUIRK_VREF }, 443163057Sariff}; 444163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 445163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 446163057Sariff 447162922Sariff#define HDA_BDL_MIN 2 448162922Sariff#define HDA_BDL_MAX 256 449162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 450162922Sariff 451169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 452167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 453167648Sariff 454162922Sariff#define HDA_BUFSZ_MIN 4096 455162922Sariff#define HDA_BUFSZ_MAX 65536 456162922Sariff#define HDA_BUFSZ_DEFAULT 16384 457162922Sariff 458162922Sariff#define HDA_PARSE_MAXDEPTH 10 459162922Sariff 460169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 461162922Sariff 462165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 463162922Sariff 464182999Smavconst char *HDA_COLORS[16] = {"Unknown", "Black", "Grey", "Blue", "Green", "Red", 465182999Smav "Orange", "Yellow", "Purple", "Pink", "Res.A", "Res.B", "Res.C", "Res.D", 466182999Smav "White", "Other"}; 467162922Sariff 468182999Smavconst char *HDA_DEVS[16] = {"Line-out", "Speaker", "Headphones", "CD", 469182999Smav "SPDIF-out", "Digital-out", "Modem-line", "Modem-handset", "Line-in", 470182999Smav "AUX", "Mic", "Telephony", "SPDIF-in", "Digital-in", "Res.E", "Other"}; 471182999Smav 472182999Smavconst char *HDA_CONNS[4] = {"Jack", "None", "Fixed", "Both"}; 473182999Smav 474162922Sariff/* Default */ 475162922Sariffstatic uint32_t hdac_fmt[] = { 476193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 477162922Sariff 0 478162922Sariff}; 479162922Sariff 480162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 481162922Sariff 482189086Smav#define HDAC_NO_MSI 1 483194861Smav#define HDAC_NO_64BIT 2 484189086Smav 485162922Sariffstatic const struct { 486162922Sariff uint32_t model; 487162922Sariff char *desc; 488189086Smav char flags; 489162922Sariff} hdac_devices[] = { 490211910Sjfv { HDA_INTEL_CPT, "Intel Cougar Point", 0 }, 491189086Smav { HDA_INTEL_82801F, "Intel 82801F", 0 }, 492189086Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, 493189086Smav { HDA_INTEL_82801G, "Intel 82801G", 0 }, 494189086Smav { HDA_INTEL_82801H, "Intel 82801H", 0 }, 495189086Smav { HDA_INTEL_82801I, "Intel 82801I", 0 }, 496197017Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0 }, 497197017Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0 }, 498189086Smav { HDA_INTEL_PCH, "Intel PCH", 0 }, 499189086Smav { HDA_INTEL_SCH, "Intel SCH", 0 }, 500189086Smav { HDA_NVIDIA_MCP51, "NVidia MCP51", HDAC_NO_MSI }, 501195690Smav { HDA_NVIDIA_MCP55, "NVidia MCP55", HDAC_NO_MSI }, 502189086Smav { HDA_NVIDIA_MCP61_1, "NVidia MCP61", 0 }, 503189086Smav { HDA_NVIDIA_MCP61_2, "NVidia MCP61", 0 }, 504189086Smav { HDA_NVIDIA_MCP65_1, "NVidia MCP65", 0 }, 505189086Smav { HDA_NVIDIA_MCP65_2, "NVidia MCP65", 0 }, 506189086Smav { HDA_NVIDIA_MCP67_1, "NVidia MCP67", 0 }, 507189086Smav { HDA_NVIDIA_MCP67_2, "NVidia MCP67", 0 }, 508189086Smav { HDA_NVIDIA_MCP73_1, "NVidia MCP73", 0 }, 509189086Smav { HDA_NVIDIA_MCP73_2, "NVidia MCP73", 0 }, 510194861Smav { HDA_NVIDIA_MCP78_1, "NVidia MCP78", HDAC_NO_64BIT }, 511194861Smav { HDA_NVIDIA_MCP78_2, "NVidia MCP78", HDAC_NO_64BIT }, 512194861Smav { HDA_NVIDIA_MCP78_3, "NVidia MCP78", HDAC_NO_64BIT }, 513194861Smav { HDA_NVIDIA_MCP78_4, "NVidia MCP78", HDAC_NO_64BIT }, 514189086Smav { HDA_NVIDIA_MCP79_1, "NVidia MCP79", 0 }, 515189086Smav { HDA_NVIDIA_MCP79_2, "NVidia MCP79", 0 }, 516189086Smav { HDA_NVIDIA_MCP79_3, "NVidia MCP79", 0 }, 517189086Smav { HDA_NVIDIA_MCP79_4, "NVidia MCP79", 0 }, 518197018Smav { HDA_NVIDIA_MCP89_1, "NVidia MCP89", 0 }, 519197018Smav { HDA_NVIDIA_MCP89_2, "NVidia MCP89", 0 }, 520197018Smav { HDA_NVIDIA_MCP89_3, "NVidia MCP89", 0 }, 521197018Smav { HDA_NVIDIA_MCP89_4, "NVidia MCP89", 0 }, 522189086Smav { HDA_ATI_SB450, "ATI SB450", 0 }, 523189086Smav { HDA_ATI_SB600, "ATI SB600", 0 }, 524189086Smav { HDA_ATI_RS600, "ATI RS600", 0 }, 525189086Smav { HDA_ATI_RS690, "ATI RS690", 0 }, 526189086Smav { HDA_ATI_RS780, "ATI RS780", 0 }, 527189086Smav { HDA_ATI_R600, "ATI R600", 0 }, 528189086Smav { HDA_ATI_RV610, "ATI RV610", 0 }, 529189086Smav { HDA_ATI_RV620, "ATI RV620", 0 }, 530189086Smav { HDA_ATI_RV630, "ATI RV630", 0 }, 531189086Smav { HDA_ATI_RV635, "ATI RV635", 0 }, 532189086Smav { HDA_ATI_RV710, "ATI RV710", 0 }, 533189086Smav { HDA_ATI_RV730, "ATI RV730", 0 }, 534189086Smav { HDA_ATI_RV740, "ATI RV740", 0 }, 535189086Smav { HDA_ATI_RV770, "ATI RV770", 0 }, 536189086Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0 }, 537189086Smav { HDA_SIS_966, "SiS 966", 0 }, 538189086Smav { HDA_ULI_M5461, "ULI M5461", 0 }, 539162922Sariff /* Unknown */ 540162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 541162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 542162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 543163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 544163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 545186301Smav { HDA_ULI_ALL, "ULI (Unknown)" }, 546162922Sariff}; 547162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 548162922Sariff 549162922Sariffstatic const struct { 550169277Sariff uint16_t vendor; 551169277Sariff uint8_t reg; 552169277Sariff uint8_t mask; 553169277Sariff uint8_t enable; 554169277Sariff} hdac_pcie_snoop[] = { 555169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 556169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 557169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 558169277Sariff}; 559169277Sariff#define HDAC_PCIESNOOP_LEN \ 560169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 561169277Sariff 562169277Sariffstatic const struct { 563162922Sariff uint32_t rate; 564162922Sariff int valid; 565162922Sariff uint16_t base; 566162922Sariff uint16_t mul; 567162922Sariff uint16_t div; 568162922Sariff} hda_rate_tab[] = { 569162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 570162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 571162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 572162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 573162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 574162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 575162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 576162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 577162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 578162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 579162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 580162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 581162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 582162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 583162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 584162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 585162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 586162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 587162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 588162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 589162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 590162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 591162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 592162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 593162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 594162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 595162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 596162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 597162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 598162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 599162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 600162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 601162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 602162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 603162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 604162922Sariff}; 605162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 606162922Sariff 607162922Sariff/* All codecs you can eat... */ 608162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 609162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 610162922Sariff 611199846Smav/* Cirrus Logic */ 612199846Smav#define CIRRUSLOGIC_VENDORID 0x1013 613199846Smav#define HDA_CODEC_CS4206 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4206) 614199846Smav#define HDA_CODEC_CS4207 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4207) 615200375Smav#define HDA_CODEC_CSXXXX HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0xffff) 616199846Smav 617162922Sariff/* Realtek */ 618162922Sariff#define REALTEK_VENDORID 0x10ec 619162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 620169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 621183024Smav#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) 622171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 623183024Smav#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) 624205413Smav#define HDA_CODEC_ALC270 HDA_CODEC_CONSTRUCT(REALTEK, 0x0270) 625183024Smav#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) 626205413Smav#define HDA_CODEC_ALC273 HDA_CODEC_CONSTRUCT(REALTEK, 0x0273) 627205413Smav#define HDA_CODEC_ALC275 HDA_CODEC_CONSTRUCT(REALTEK, 0x0275) 628170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 629183024Smav#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) 630183025Smav#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) 631205413Smav#define HDA_CODEC_ALC665 HDA_CODEC_CONSTRUCT(REALTEK, 0x0665) 632162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 633169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 634162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 635163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 636163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 637169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 638197640Smav#define HDA_CODEC_ALC887 HDA_CODEC_CONSTRUCT(REALTEK, 0x0887) 639165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 640182999Smav#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) 641205413Smav#define HDA_CODEC_ALC892 HDA_CODEC_CONSTRUCT(REALTEK, 0x0892) 642162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 643162922Sariff 644169277Sariff/* Analog Devices */ 645169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 646186403Smav#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) 647186403Smav#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) 648186403Smav#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) 649186403Smav#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) 650186403Smav#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) 651186403Smav#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) 652169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 653169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 654174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 655169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 656186403Smav#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) 657169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 658170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 659186403Smav#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) 660186403Smav#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) 661169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 662162922Sariff 663162922Sariff/* CMedia */ 664162922Sariff#define CMEDIA_VENDORID 0x434d 665162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 666162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 667162922Sariff 668162922Sariff/* Sigmatel */ 669162922Sariff#define SIGMATEL_VENDORID 0x8384 670182999Smav#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) 671182999Smav#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) 672182999Smav#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) 673182999Smav#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) 674182999Smav#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) 675182999Smav#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) 676182999Smav#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 677182999Smav#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) 678183894Smav#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) 679183894Smav#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) 680183894Smav#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) 681183894Smav#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) 682183894Smav#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) 683183894Smav#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) 684183894Smav#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) 685182999Smav#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 686183894Smav#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) 687183894Smav#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) 688183894Smav#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) 689183894Smav#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) 690183894Smav#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) 691183894Smav#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) 692183894Smav#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) 693183894Smav#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) 694200375Smav#define HDA_CODEC_CXD9872RDK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7661) 695182999Smav#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) 696200375Smav#define HDA_CODEC_CXD9872AKD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7664) 697162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 698182999Smav#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 699183894Smav#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) 700162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 701162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 702183894Smav#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) 703183894Smav#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) 704183894Smav#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) 705183894Smav#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 706183894Smav#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) 707183894Smav#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) 708183894Smav#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) 709183894Smav#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) 710183894Smav#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) 711162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 712162922Sariff 713183894Smav/* IDT */ 714183894Smav#define IDT_VENDORID 0x111d 715183894Smav#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) 716183894Smav#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) 717183894Smav#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) 718183894Smav#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) 719183894Smav#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) 720183894Smav#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) 721183894Smav#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) 722183894Smav#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) 723183894Smav#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) 724183894Smav#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) 725183894Smav#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) 726183894Smav#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) 727183894Smav#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) 728183894Smav 729182999Smav/* Silicon Image */ 730182999Smav#define SII_VENDORID 0x1095 731187020Smav#define HDA_CODEC_SII1390 HDA_CODEC_CONSTRUCT(SII, 0x1390) 732186146Smav#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) 733182999Smav#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) 734182999Smav 735182999Smav/* Lucent/Agere */ 736182999Smav#define AGERE_VENDORID 0x11c1 737182999Smav#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) 738182999Smav 739186430Smav/* Conexant */ 740162922Sariff#define CONEXANT_VENDORID 0x14f1 741186430Smav#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 742186430Smav#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 743186430Smav#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) 744200375Smav#define HDA_CODEC_CX20582 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5066) 745205413Smav#define HDA_CODEC_CX20583 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5067) 746208934Smav#define HDA_CODEC_CX20585 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5069) 747162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 748162922Sariff 749169277Sariff/* VIA */ 750169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 751169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 752169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 753169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 754169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 755169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 756169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 757169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 758169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 759169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 760169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 761169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 762186145Smav#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) 763186145Smav#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) 764186145Smav#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) 765186145Smav#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) 766186145Smav#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) 767186145Smav#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) 768186145Smav#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) 769186145Smav#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) 770187020Smav#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) 771187020Smav#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) 772187020Smav#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) 773187020Smav#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) 774187020Smav#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) 775187020Smav#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) 776187020Smav#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) 777187020Smav#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) 778187020Smav#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) 779187020Smav#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) 780187020Smav#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) 781187020Smav#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) 782187020Smav#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) 783187020Smav#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) 784187020Smav#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) 785187020Smav#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) 786199258Smav#define HDA_CODEC_VT1716S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0433) 787199258Smav#define HDA_CODEC_VT1716S_1 HDA_CODEC_CONSTRUCT(VIA, 0xa721) 788199258Smav#define HDA_CODEC_VT1718S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0428) 789199258Smav#define HDA_CODEC_VT1718S_1 HDA_CODEC_CONSTRUCT(VIA, 0x4428) 790199258Smav#define HDA_CODEC_VT1812 HDA_CODEC_CONSTRUCT(VIA, 0x0448) 791199258Smav#define HDA_CODEC_VT1818S HDA_CODEC_CONSTRUCT(VIA, 0x0440) 792199258Smav#define HDA_CODEC_VT1828S HDA_CODEC_CONSTRUCT(VIA, 0x4441) 793199258Smav#define HDA_CODEC_VT2002P_0 HDA_CODEC_CONSTRUCT(VIA, 0x0438) 794199258Smav#define HDA_CODEC_VT2002P_1 HDA_CODEC_CONSTRUCT(VIA, 0x4438) 795199258Smav#define HDA_CODEC_VT2020 HDA_CODEC_CONSTRUCT(VIA, 0x0441) 796169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 797162922Sariff 798182999Smav/* ATI */ 799186146Smav#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) 800186146Smav#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) 801186146Smav#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) 802186146Smav#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) 803182999Smav#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) 804169277Sariff 805182999Smav/* NVIDIA */ 806187020Smav#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) 807187445Smav#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) 808187020Smav#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) 809208934Smav#define HDA_CODEC_NVIDIAGT220 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000a) 810208934Smav#define HDA_CODEC_NVIDIAGT21X HDA_CODEC_CONSTRUCT(NVIDIA, 0x000b) 811208934Smav#define HDA_CODEC_NVIDIAMCP89 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000c) 812208934Smav#define HDA_CODEC_NVIDIAGT240 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000d) 813187020Smav#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) 814187445Smav#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) 815182999Smav#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) 816182999Smav 817183894Smav/* INTEL */ 818187020Smav#define HDA_CODEC_INTELG45_1 HDA_CODEC_CONSTRUCT(INTEL, 0x2801) 819187020Smav#define HDA_CODEC_INTELG45_2 HDA_CODEC_CONSTRUCT(INTEL, 0x2802) 820187020Smav#define HDA_CODEC_INTELG45_3 HDA_CODEC_CONSTRUCT(INTEL, 0x2803) 821205413Smav#define HDA_CODEC_INTELG45_4 HDA_CODEC_CONSTRUCT(INTEL, 0x2804) 822205413Smav#define HDA_CODEC_INTELG45_5 HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) 823199258Smav#define HDA_CODEC_INTELQ57 HDA_CODEC_CONSTRUCT(INTEL, 0x0054) 824183894Smav#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) 825183894Smav 826162922Sariff/* Codecs */ 827162922Sariffstatic const struct { 828162922Sariff uint32_t id; 829162922Sariff char *name; 830162922Sariff} hdac_codecs[] = { 831199846Smav { HDA_CODEC_CS4206, "Cirrus Logic CS4206" }, 832199846Smav { HDA_CODEC_CS4207, "Cirrus Logic CS4207" }, 833162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 834169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 835183024Smav { HDA_CODEC_ALC267, "Realtek ALC267" }, 836171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 837183024Smav { HDA_CODEC_ALC269, "Realtek ALC269" }, 838205413Smav { HDA_CODEC_ALC270, "Realtek ALC270" }, 839183024Smav { HDA_CODEC_ALC272, "Realtek ALC272" }, 840205413Smav { HDA_CODEC_ALC273, "Realtek ALC273" }, 841205413Smav { HDA_CODEC_ALC275, "Realtek ALC275" }, 842170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 843183024Smav { HDA_CODEC_ALC662, "Realtek ALC662" }, 844183024Smav { HDA_CODEC_ALC663, "Realtek ALC663" }, 845205413Smav { HDA_CODEC_ALC665, "Realtek ALC665" }, 846162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 847169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 848162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 849162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 850163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 851169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 852197640Smav { HDA_CODEC_ALC887, "Realtek ALC887" }, 853165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 854182999Smav { HDA_CODEC_ALC889, "Realtek ALC889" }, 855205413Smav { HDA_CODEC_ALC892, "Realtek ALC892" }, 856186403Smav { HDA_CODEC_AD1882, "Analog Devices AD1882" }, 857186403Smav { HDA_CODEC_AD1882A, "Analog Devices AD1882A" }, 858186403Smav { HDA_CODEC_AD1883, "Analog Devices AD1883" }, 859186403Smav { HDA_CODEC_AD1884, "Analog Devices AD1884" }, 860186403Smav { HDA_CODEC_AD1884A, "Analog Devices AD1884A" }, 861169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 862169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 863174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 864186403Smav { HDA_CODEC_AD1984A, "Analog Devices AD1984A" }, 865186403Smav { HDA_CODEC_AD1984B, "Analog Devices AD1984B" }, 866169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 867186403Smav { HDA_CODEC_AD1987, "Analog Devices AD1987" }, 868186403Smav { HDA_CODEC_AD1988, "Analog Devices AD1988A" }, 869170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 870186403Smav { HDA_CODEC_AD1989B, "Analog Devices AD1989B" }, 871162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 872200375Smav { HDA_CODEC_CXD9872RDK, "Sigmatel CXD9872RD/K" }, 873200375Smav { HDA_CODEC_CXD9872AKD, "Sigmatel CXD9872AKD" }, 874183894Smav { HDA_CODEC_STAC9200D, "Sigmatel STAC9200D" }, 875183894Smav { HDA_CODEC_STAC9204X, "Sigmatel STAC9204X" }, 876183894Smav { HDA_CODEC_STAC9204D, "Sigmatel STAC9204D" }, 877183894Smav { HDA_CODEC_STAC9205X, "Sigmatel STAC9205X" }, 878183894Smav { HDA_CODEC_STAC9205D, "Sigmatel STAC9205D" }, 879183894Smav { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 880183894Smav { HDA_CODEC_STAC9220_A1, "Sigmatel STAC9220_A1" }, 881183894Smav { HDA_CODEC_STAC9220_A2, "Sigmatel STAC9220_A2" }, 882162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 883183894Smav { HDA_CODEC_STAC9221_A2, "Sigmatel STAC9221_A2" }, 884162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 885162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 886183894Smav { HDA_CODEC_STAC9227X, "Sigmatel STAC9227X" }, 887183894Smav { HDA_CODEC_STAC9227D, "Sigmatel STAC9227D" }, 888183894Smav { HDA_CODEC_STAC9228X, "Sigmatel STAC9228X" }, 889183894Smav { HDA_CODEC_STAC9228D, "Sigmatel STAC9228D" }, 890183894Smav { HDA_CODEC_STAC9229X, "Sigmatel STAC9229X" }, 891183894Smav { HDA_CODEC_STAC9229D, "Sigmatel STAC9229D" }, 892182999Smav { HDA_CODEC_STAC9230X, "Sigmatel STAC9230X" }, 893182999Smav { HDA_CODEC_STAC9230D, "Sigmatel STAC9230D" }, 894183894Smav { HDA_CODEC_STAC9250, "Sigmatel STAC9250" }, 895183894Smav { HDA_CODEC_STAC9251, "Sigmatel STAC9251" }, 896183894Smav { HDA_CODEC_STAC9271X, "Sigmatel STAC9271X" }, 897166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 898183894Smav { HDA_CODEC_STAC9272X, "Sigmatel STAC9272X" }, 899183894Smav { HDA_CODEC_STAC9272D, "Sigmatel STAC9272D" }, 900183894Smav { HDA_CODEC_STAC9273X, "Sigmatel STAC9273X" }, 901183894Smav { HDA_CODEC_STAC9273D, "Sigmatel STAC9273D" }, 902183894Smav { HDA_CODEC_STAC9274, "Sigmatel STAC9274" }, 903183894Smav { HDA_CODEC_STAC9274D, "Sigmatel STAC9274D" }, 904183894Smav { HDA_CODEC_STAC9274X5NH, "Sigmatel STAC9274X5NH" }, 905183894Smav { HDA_CODEC_STAC9274D5NH, "Sigmatel STAC9274D5NH" }, 906183894Smav { HDA_CODEC_STAC9872AK, "Sigmatel STAC9872AK" }, 907183894Smav { HDA_CODEC_IDT92HD005, "IDT 92HD005" }, 908183894Smav { HDA_CODEC_IDT92HD005D, "IDT 92HD005D" }, 909183894Smav { HDA_CODEC_IDT92HD206X, "IDT 92HD206X" }, 910183894Smav { HDA_CODEC_IDT92HD206D, "IDT 92HD206D" }, 911183894Smav { HDA_CODEC_IDT92HD700X, "IDT 92HD700X" }, 912183894Smav { HDA_CODEC_IDT92HD700D, "IDT 92HD700D" }, 913183894Smav { HDA_CODEC_IDT92HD71B5, "IDT 92HD71B5" }, 914183894Smav { HDA_CODEC_IDT92HD71B7, "IDT 92HD71B7" }, 915183894Smav { HDA_CODEC_IDT92HD71B8, "IDT 92HD71B8" }, 916183894Smav { HDA_CODEC_IDT92HD73C1, "IDT 92HD73C1" }, 917183894Smav { HDA_CODEC_IDT92HD73D1, "IDT 92HD73D1" }, 918183894Smav { HDA_CODEC_IDT92HD73E1, "IDT 92HD73E1" }, 919183894Smav { HDA_CODEC_IDT92HD75B3, "IDT 92HD75B3" }, 920183894Smav { HDA_CODEC_IDT92HD75BX, "IDT 92HD75BX" }, 921183894Smav { HDA_CODEC_IDT92HD81B1C, "IDT 92HD81B1C" }, 922183894Smav { HDA_CODEC_IDT92HD81B1X, "IDT 92HD81B1X" }, 923183894Smav { HDA_CODEC_IDT92HD83C1C, "IDT 92HD83C1C" }, 924183894Smav { HDA_CODEC_IDT92HD83C1X, "IDT 92HD83C1X" }, 925186430Smav { HDA_CODEC_CX20549, "Conexant CX20549 (Venice)" }, 926186430Smav { HDA_CODEC_CX20551, "Conexant CX20551 (Waikiki)" }, 927186430Smav { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, 928200375Smav { HDA_CODEC_CX20582, "Conexant CX20582 (Pebble)" }, 929205413Smav { HDA_CODEC_CX20583, "Conexant CX20583 (Pebble HSF)" }, 930208934Smav { HDA_CODEC_CX20585, "Conexant CX20585" }, 931169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 932169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 933169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 934169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 935169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 936169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 937169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 938169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 939169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 940169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 941169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 942169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 943186145Smav { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" }, 944186145Smav { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" }, 945186145Smav { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" }, 946186145Smav { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" }, 947186145Smav { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" }, 948186145Smav { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" }, 949186145Smav { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" }, 950186145Smav { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" }, 951187020Smav { HDA_CODEC_VT1708S_0, "VIA VT1708S_0" }, 952187020Smav { HDA_CODEC_VT1708S_1, "VIA VT1708S_1" }, 953187020Smav { HDA_CODEC_VT1708S_2, "VIA VT1708S_2" }, 954187020Smav { HDA_CODEC_VT1708S_3, "VIA VT1708S_3" }, 955187020Smav { HDA_CODEC_VT1708S_4, "VIA VT1708S_4" }, 956187020Smav { HDA_CODEC_VT1708S_5, "VIA VT1708S_5" }, 957187020Smav { HDA_CODEC_VT1708S_6, "VIA VT1708S_6" }, 958187020Smav { HDA_CODEC_VT1708S_7, "VIA VT1708S_7" }, 959187020Smav { HDA_CODEC_VT1702_0, "VIA VT1702_0" }, 960187020Smav { HDA_CODEC_VT1702_1, "VIA VT1702_1" }, 961187020Smav { HDA_CODEC_VT1702_2, "VIA VT1702_2" }, 962187020Smav { HDA_CODEC_VT1702_3, "VIA VT1702_3" }, 963187020Smav { HDA_CODEC_VT1702_4, "VIA VT1702_4" }, 964187020Smav { HDA_CODEC_VT1702_5, "VIA VT1702_5" }, 965187020Smav { HDA_CODEC_VT1702_6, "VIA VT1702_6" }, 966187020Smav { HDA_CODEC_VT1702_7, "VIA VT1702_7" }, 967199258Smav { HDA_CODEC_VT1716S_0, "VIA VT1716S_0" }, 968199258Smav { HDA_CODEC_VT1716S_1, "VIA VT1716S_1" }, 969199258Smav { HDA_CODEC_VT1718S_0, "VIA VT1718S_0" }, 970199258Smav { HDA_CODEC_VT1718S_1, "VIA VT1718S_1" }, 971199258Smav { HDA_CODEC_VT1812, "VIA VT1812" }, 972199258Smav { HDA_CODEC_VT1818S, "VIA VT1818S" }, 973199258Smav { HDA_CODEC_VT1828S, "VIA VT1828S" }, 974199258Smav { HDA_CODEC_VT2002P_0, "VIA VT2002P_0" }, 975199258Smav { HDA_CODEC_VT2002P_1, "VIA VT2002P_1" }, 976199258Smav { HDA_CODEC_VT2020, "VIA VT2020" }, 977186146Smav { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" }, 978186146Smav { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" }, 979186146Smav { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, 980186146Smav { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, 981187020Smav { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, 982187445Smav { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, 983187020Smav { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, 984187445Smav { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, 985187020Smav { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, 986208934Smav { HDA_CODEC_NVIDIAGT220, "NVidia GT220 HDMI" }, 987208934Smav { HDA_CODEC_NVIDIAGT21X, "NVidia GT21x HDMI" }, 988208934Smav { HDA_CODEC_NVIDIAMCP89, "NVidia MCP89 HDMI" }, 989208934Smav { HDA_CODEC_NVIDIAGT240, "NVidia GT240 HDMI" }, 990187020Smav { HDA_CODEC_INTELG45_1, "Intel G45 HDMI" }, 991187020Smav { HDA_CODEC_INTELG45_2, "Intel G45 HDMI" }, 992187020Smav { HDA_CODEC_INTELG45_3, "Intel G45 HDMI" }, 993187020Smav { HDA_CODEC_INTELG45_4, "Intel G45 HDMI" }, 994205413Smav { HDA_CODEC_INTELG45_5, "Intel G45 HDMI" }, 995199258Smav { HDA_CODEC_INTELQ57, "Intel Q57 HDMI" }, 996187020Smav { HDA_CODEC_SII1390, "Silicon Image SiI1390 HDMI" }, 997186146Smav { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" }, 998162922Sariff /* Unknown codec */ 999162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 1000169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 1001200375Smav { HDA_CODEC_CSXXXX, "Cirrus Logic (Unknown)" }, 1002162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 1003162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 1004182999Smav { HDA_CODEC_SIIXXXX, "Silicon Image (Unknown)" }, 1005182999Smav { HDA_CODEC_AGEREXXXX, "Lucent/Agere Systems (Unknown)" }, 1006162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 1007169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 1008182999Smav { HDA_CODEC_ATIXXXX, "ATI (Unknown)" }, 1009182999Smav { HDA_CODEC_NVIDIAXXXX,"NVidia (Unknown)" }, 1010183894Smav { HDA_CODEC_INTELXXXX, "Intel (Unknown)" }, 1011183894Smav { HDA_CODEC_IDTXXXX, "IDT (Unknown)" }, 1012162922Sariff}; 1013162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 1014162922Sariff 1015162922Sariff 1016162922Sariff/**************************************************************************** 1017162922Sariff * Function prototypes 1018162922Sariff ****************************************************************************/ 1019162922Sariffstatic void hdac_intr_handler(void *); 1020182999Smavstatic int hdac_reset(struct hdac_softc *, int); 1021162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 1022162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 1023162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 1024162922Sariff struct hdac_dma *, bus_size_t); 1025169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 1026162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 1027162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 1028162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 1029162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 1030162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 1031162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 1032162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 1033162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 1034182999Smavstatic void hdac_scan_codecs(struct hdac_softc *); 1035182999Smavstatic void hdac_probe_codec(struct hdac_codec *); 1036182999Smavstatic void hdac_probe_function(struct hdac_codec *, nid_t); 1037182999Smavstatic int hdac_pcmchannel_setup(struct hdac_chan *); 1038162922Sariff 1039162922Sariffstatic void hdac_attach2(void *); 1040162922Sariff 1041162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 1042162922Sariff uint32_t, int); 1043162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 1044162922Sariff struct hdac_command_list *, int); 1045162922Sariff 1046162922Sariffstatic int hdac_probe(device_t); 1047162922Sariffstatic int hdac_attach(device_t); 1048162922Sariffstatic int hdac_detach(device_t); 1049182999Smavstatic int hdac_suspend(device_t); 1050182999Smavstatic int hdac_resume(device_t); 1051162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 1052162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 1053162922Sariff uint32_t, int, int); 1054162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 1055182999Smav nid_t, int, int, int); 1056162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 1057162922Sariff nid_t, nid_t, int, int, int, int, int, int); 1058162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 1059162922Sariff 1060164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 1061164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 1062164614Sariff 1063182999Smavstatic void hdac_dump_pin_config(struct hdac_widget *w, uint32_t conf); 1064182999Smav 1065162922Sariff#define hdac_command(a1, a2, a3) \ 1066162922Sariff hdac_command_sendone_internal(a1, a2, a3) 1067162922Sariff 1068182999Smav#define hdac_codec_id(c) \ 1069182999Smav ((uint32_t)((c == NULL) ? 0x00000000 : \ 1070182999Smav ((((uint32_t)(c)->vendor_id & 0x0000ffff) << 16) | \ 1071182999Smav ((uint32_t)(c)->device_id & 0x0000ffff)))) 1072162922Sariff 1073162922Sariffstatic char * 1074182999Smavhdac_codec_name(struct hdac_codec *codec) 1075162922Sariff{ 1076162922Sariff uint32_t id; 1077162922Sariff int i; 1078162922Sariff 1079182999Smav id = hdac_codec_id(codec); 1080162922Sariff 1081162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 1082163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 1083162922Sariff return (hdac_codecs[i].name); 1084162922Sariff } 1085162922Sariff 1086162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 1087162922Sariff} 1088162922Sariff 1089162922Sariffstatic char * 1090162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 1091162922Sariff{ 1092162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 1093162922Sariff int i, first = 1; 1094162922Sariff 1095162922Sariff bzero(buf, len); 1096162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 1097162922Sariff if (mask & (1 << i)) { 1098162922Sariff if (first == 0) 1099162922Sariff strlcat(buf, ", ", len); 1100162922Sariff strlcat(buf, ossname[i], len); 1101162922Sariff first = 0; 1102162922Sariff } 1103162922Sariff } 1104182999Smav return (buf); 1105162922Sariff} 1106162922Sariff 1107162922Sariffstatic struct hdac_audio_ctl * 1108162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 1109162922Sariff{ 1110162922Sariff if (devinfo == NULL || 1111162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 1112162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 1113162922Sariff devinfo->function.audio.ctlcnt < 1 || 1114162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 1115162922Sariff return (NULL); 1116162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 1117162922Sariff} 1118162922Sariff 1119162922Sariffstatic struct hdac_audio_ctl * 1120182999Smavhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, int dir, 1121162922Sariff int index, int cnt) 1122162922Sariff{ 1123182999Smav struct hdac_audio_ctl *ctl; 1124182999Smav int i, found = 0; 1125162922Sariff 1126162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 1127162922Sariff return (NULL); 1128162922Sariff 1129162922Sariff i = 0; 1130162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 1131182999Smav if (ctl->enable == 0) 1132162922Sariff continue; 1133182999Smav if (ctl->widget->nid != nid) 1134162922Sariff continue; 1135182999Smav if (dir && ctl->ndir != dir) 1136182999Smav continue; 1137182999Smav if (index >= 0 && ctl->ndir == HDA_CTL_IN && 1138182999Smav ctl->dir == ctl->ndir && ctl->index != index) 1139182999Smav continue; 1140162922Sariff found++; 1141182999Smav if (found == cnt || cnt <= 0) 1142162922Sariff return (ctl); 1143162922Sariff } 1144162922Sariff 1145182999Smav return (NULL); 1146162922Sariff} 1147162922Sariff 1148182999Smav/* 1149182999Smav * Jack detection (Speaker/HP redirection) event handler. 1150182999Smav */ 1151162922Sariffstatic void 1152162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 1153162922Sariff{ 1154182999Smav struct hdac_audio_as *as; 1155162922Sariff struct hdac_softc *sc; 1156162922Sariff struct hdac_widget *w; 1157162922Sariff struct hdac_audio_ctl *ctl; 1158182999Smav uint32_t val, res; 1159182999Smav int i, j; 1160162922Sariff nid_t cad; 1161162922Sariff 1162162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 1163162922Sariff devinfo->codec->sc == NULL) 1164162922Sariff return; 1165162922Sariff 1166162922Sariff sc = devinfo->codec->sc; 1167162922Sariff cad = devinfo->codec->cad; 1168182999Smav as = devinfo->function.audio.as; 1169182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1170182999Smav if (as[i].hpredir < 0) 1171182999Smav continue; 1172182999Smav 1173182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1174182999Smav if (w == NULL || w->enable == 0 || w->type != 1175182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1176182999Smav continue; 1177162922Sariff 1178171141Sariff res = hdac_command(sc, 1179182999Smav HDA_CMD_GET_PIN_SENSE(cad, as[i].pins[15]), cad); 1180171141Sariff 1181182999Smav HDA_BOOTVERBOSE( 1182182999Smav device_printf(sc->dev, 1183182999Smav "Pin sense: nid=%d res=0x%08x\n", 1184182999Smav as[i].pins[15], res); 1185182999Smav ); 1186171141Sariff 1187182999Smav res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 1188182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_SENSEINV) 1189182999Smav res ^= 1; 1190162922Sariff 1191182999Smav /* (Un)Mute headphone pin. */ 1192162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 1193182999Smav as[i].pins[15], HDA_CTL_IN, -1, 1); 1194182999Smav if (ctl != NULL && ctl->mute) { 1195182999Smav /* If pin has muter - use it. */ 1196182999Smav val = (res != 0) ? 0 : 1; 1197182999Smav if (val != ctl->forcemute) { 1198182999Smav ctl->forcemute = val; 1199162922Sariff hdac_audio_ctl_amp_set(ctl, 1200182999Smav HDA_AMP_MUTE_DEFAULT, 1201182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1202162922Sariff } 1203182999Smav } else { 1204182999Smav /* If there is no muter - disable pin output. */ 1205182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1206163057Sariff if (w != NULL && w->type == 1207163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1208182999Smav if (res != 0) 1209169277Sariff val = w->wclass.pin.ctrl | 1210162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1211162922Sariff else 1212169277Sariff val = w->wclass.pin.ctrl & 1213162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1214169277Sariff if (val != w->wclass.pin.ctrl) { 1215169277Sariff w->wclass.pin.ctrl = val; 1216169277Sariff hdac_command(sc, 1217169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1218169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1219169277Sariff } 1220162922Sariff } 1221182999Smav } 1222182999Smav /* (Un)Mute other pins. */ 1223182999Smav for (j = 0; j < 15; j++) { 1224182999Smav if (as[i].pins[j] <= 0) 1225182999Smav continue; 1226182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 1227182999Smav as[i].pins[j], HDA_CTL_IN, -1, 1); 1228182999Smav if (ctl != NULL && ctl->mute) { 1229182999Smav /* If pin has muter - use it. */ 1230182999Smav val = (res != 0) ? 1 : 0; 1231182999Smav if (val == ctl->forcemute) 1232169277Sariff continue; 1233182999Smav ctl->forcemute = val; 1234182999Smav hdac_audio_ctl_amp_set(ctl, 1235182999Smav HDA_AMP_MUTE_DEFAULT, 1236182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 1237182999Smav continue; 1238162922Sariff } 1239182999Smav /* If there is no muter - disable pin output. */ 1240182999Smav w = hdac_widget_get(devinfo, as[i].pins[j]); 1241163057Sariff if (w != NULL && w->type == 1242163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1243182999Smav if (res != 0) 1244182999Smav val = w->wclass.pin.ctrl & 1245182999Smav ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1246182999Smav else 1247182999Smav val = w->wclass.pin.ctrl | 1248182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1249169277Sariff if (val != w->wclass.pin.ctrl) { 1250169277Sariff w->wclass.pin.ctrl = val; 1251169277Sariff hdac_command(sc, 1252169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1253169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1254169277Sariff } 1255162922Sariff } 1256162922Sariff } 1257182999Smav } 1258182999Smav} 1259182999Smav 1260182999Smav/* 1261182999Smav * Callback for poll based jack detection. 1262182999Smav */ 1263182999Smavstatic void 1264182999Smavhdac_jack_poll_callback(void *arg) 1265182999Smav{ 1266182999Smav struct hdac_devinfo *devinfo = arg; 1267182999Smav struct hdac_softc *sc; 1268182999Smav 1269182999Smav if (devinfo == NULL || devinfo->codec == NULL || 1270182999Smav devinfo->codec->sc == NULL) 1271182999Smav return; 1272182999Smav sc = devinfo->codec->sc; 1273182999Smav hdac_lock(sc); 1274182999Smav if (sc->poll_ival == 0) { 1275182999Smav hdac_unlock(sc); 1276182999Smav return; 1277182999Smav } 1278182999Smav hdac_hp_switch_handler(devinfo); 1279182999Smav callout_reset(&sc->poll_jack, sc->poll_ival, 1280182999Smav hdac_jack_poll_callback, devinfo); 1281182999Smav hdac_unlock(sc); 1282182999Smav} 1283182999Smav 1284182999Smav/* 1285182999Smav * Jack detection initializer. 1286182999Smav */ 1287182999Smavstatic void 1288182999Smavhdac_hp_switch_init(struct hdac_devinfo *devinfo) 1289182999Smav{ 1290182999Smav struct hdac_softc *sc = devinfo->codec->sc; 1291182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 1292182999Smav struct hdac_widget *w; 1293182999Smav uint32_t id; 1294182999Smav int i, enable = 0, poll = 0; 1295182999Smav nid_t cad; 1296182999Smav 1297182999Smav id = hdac_codec_id(devinfo->codec); 1298182999Smav cad = devinfo->codec->cad; 1299182999Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 1300182999Smav if (as[i].hpredir < 0) 1301182999Smav continue; 1302182999Smav 1303182999Smav w = hdac_widget_get(devinfo, as[i].pins[15]); 1304182999Smav if (w == NULL || w->enable == 0 || w->type != 1305182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1306182999Smav continue; 1307182999Smav if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 || 1308182999Smav (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) { 1309182999Smav device_printf(sc->dev, 1310182999Smav "No jack detection support at pin %d\n", 1311182999Smav as[i].pins[15]); 1312182999Smav continue; 1313182999Smav } 1314182999Smav enable = 1; 1315182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 1316169277Sariff hdac_command(sc, 1317182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 1318182999Smav HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 1319182999Smav HDAC_UNSOLTAG_EVENT_HP), cad); 1320182999Smav } else 1321182999Smav poll = 1; 1322182999Smav HDA_BOOTVERBOSE( 1323169277Sariff device_printf(sc->dev, 1324182999Smav "Enabling headphone/speaker " 1325182999Smav "audio routing switching:\n"); 1326182999Smav device_printf(sc->dev, "\tas=%d sense nid=%d [%s]\n", 1327182999Smav i, w->nid, (poll != 0) ? "POLL" : "UNSOL"); 1328182999Smav ); 1329182999Smav } 1330182999Smav if (enable) { 1331182999Smav hdac_hp_switch_handler(devinfo); 1332182999Smav if (poll) { 1333182999Smav callout_reset(&sc->poll_jack, 1, 1334182999Smav hdac_jack_poll_callback, devinfo); 1335169277Sariff } 1336162922Sariff } 1337162922Sariff} 1338162922Sariff 1339182999Smav/* 1340182999Smav * Unsolicited messages handler. 1341182999Smav */ 1342162922Sariffstatic void 1343162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1344162922Sariff{ 1345162922Sariff struct hdac_softc *sc; 1346162922Sariff struct hdac_devinfo *devinfo = NULL; 1347182999Smav int i; 1348162922Sariff 1349162922Sariff if (codec == NULL || codec->sc == NULL) 1350162922Sariff return; 1351162922Sariff 1352162922Sariff sc = codec->sc; 1353162922Sariff 1354163057Sariff HDA_BOOTVERBOSE( 1355182999Smav device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 1356162922Sariff ); 1357162922Sariff 1358182999Smav for (i = 0; i < codec->num_fgs; i++) { 1359182999Smav if (codec->fgs[i].node_type == 1360182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 1361182999Smav devinfo = &codec->fgs[i]; 1362162965Sariff break; 1363182999Smav } 1364162922Sariff } 1365162965Sariff 1366162922Sariff if (devinfo == NULL) 1367162922Sariff return; 1368162922Sariff 1369162922Sariff switch (tag) { 1370162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1371162922Sariff hdac_hp_switch_handler(devinfo); 1372162922Sariff break; 1373162922Sariff default: 1374182999Smav device_printf(sc->dev, "Unknown unsol tag: 0x%08x!\n", tag); 1375162922Sariff break; 1376162922Sariff } 1377162922Sariff} 1378162922Sariff 1379164614Sariffstatic int 1380162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1381162922Sariff{ 1382162922Sariff /* XXX to be removed */ 1383162922Sariff#ifdef HDAC_INTR_EXTRA 1384162922Sariff uint32_t res; 1385162922Sariff#endif 1386162922Sariff 1387171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1388164614Sariff return (0); 1389162922Sariff 1390162922Sariff /* XXX to be removed */ 1391162922Sariff#ifdef HDAC_INTR_EXTRA 1392162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1393162922Sariff#endif 1394162922Sariff 1395162922Sariff /* XXX to be removed */ 1396162922Sariff#ifdef HDAC_INTR_EXTRA 1397163057Sariff HDA_BOOTVERBOSE( 1398163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1399182999Smav device_printf(ch->pdevinfo->dev, 1400163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1401163057Sariff "%08x\n", 1402163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1403163057Sariff ); 1404162922Sariff#endif 1405162922Sariff 1406162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1407163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1408162922Sariff 1409162922Sariff /* XXX to be removed */ 1410162922Sariff#ifdef HDAC_INTR_EXTRA 1411162922Sariff if (res & HDAC_SDSTS_BCIS) { 1412162922Sariff#endif 1413164614Sariff return (1); 1414162922Sariff /* XXX to be removed */ 1415162922Sariff#ifdef HDAC_INTR_EXTRA 1416162922Sariff } 1417162922Sariff#endif 1418164614Sariff 1419164614Sariff return (0); 1420162922Sariff} 1421162922Sariff 1422162922Sariff/**************************************************************************** 1423162922Sariff * void hdac_intr_handler(void *) 1424162922Sariff * 1425162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1426162922Sariff ****************************************************************************/ 1427162922Sariffstatic void 1428162922Sariffhdac_intr_handler(void *context) 1429162922Sariff{ 1430162922Sariff struct hdac_softc *sc; 1431162922Sariff uint32_t intsts; 1432162922Sariff uint8_t rirbsts; 1433164614Sariff struct hdac_rirb *rirb_base; 1434171141Sariff uint32_t trigger; 1435182999Smav int i; 1436162922Sariff 1437162922Sariff sc = (struct hdac_softc *)context; 1438162922Sariff 1439162922Sariff hdac_lock(sc); 1440164614Sariff if (sc->polling != 0) { 1441164614Sariff hdac_unlock(sc); 1442164614Sariff return; 1443164614Sariff } 1444171141Sariff 1445162922Sariff /* Do we have anything to do? */ 1446162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1447163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1448162922Sariff hdac_unlock(sc); 1449162922Sariff return; 1450162922Sariff } 1451162922Sariff 1452171141Sariff trigger = 0; 1453171141Sariff 1454162922Sariff /* Was this a controller interrupt? */ 1455163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1456162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1457162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1458162922Sariff /* Get as many responses that we can */ 1459163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1460164614Sariff HDAC_WRITE_1(&sc->mem, 1461164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1462171141Sariff if (hdac_rirb_flush(sc) != 0) 1463171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1464162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1465162922Sariff } 1466162922Sariff /* XXX to be removed */ 1467162922Sariff /* Clear interrupt and exit */ 1468162922Sariff#ifdef HDAC_INTR_EXTRA 1469162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1470162922Sariff#endif 1471162922Sariff } 1472164614Sariff 1473163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1474182999Smav for (i = 0; i < sc->num_chans; i++) { 1475182999Smav if ((intsts & (1 << (sc->chans[i].off >> 5))) && 1476182999Smav hdac_stream_intr(sc, &sc->chans[i]) != 0) 1477182999Smav trigger |= (1 << i); 1478182999Smav } 1479162922Sariff /* XXX to be removed */ 1480162922Sariff#ifdef HDAC_INTR_EXTRA 1481164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1482164614Sariff HDAC_INTSTS_SIS_MASK); 1483162922Sariff#endif 1484162922Sariff } 1485162922Sariff 1486164614Sariff hdac_unlock(sc); 1487162922Sariff 1488182999Smav for (i = 0; i < sc->num_chans; i++) { 1489182999Smav if (trigger & (1 << i)) 1490182999Smav chn_intr(sc->chans[i].c); 1491182999Smav } 1492171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1493171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1494162922Sariff} 1495162922Sariff 1496162922Sariff/**************************************************************************** 1497182999Smav * int hdac_reset(hdac_softc *, int) 1498162922Sariff * 1499162922Sariff * Reset the hdac to a quiescent and known state. 1500162922Sariff ****************************************************************************/ 1501162922Sariffstatic int 1502182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 1503162922Sariff{ 1504162922Sariff uint32_t gctl; 1505162922Sariff int count, i; 1506162922Sariff 1507162922Sariff /* 1508162922Sariff * Stop all Streams DMA engine 1509162922Sariff */ 1510162922Sariff for (i = 0; i < sc->num_iss; i++) 1511162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1512162922Sariff for (i = 0; i < sc->num_oss; i++) 1513162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1514162922Sariff for (i = 0; i < sc->num_bss; i++) 1515162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1516162922Sariff 1517162922Sariff /* 1518169277Sariff * Stop Control DMA engines. 1519162922Sariff */ 1520162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1521162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1522162922Sariff 1523162922Sariff /* 1524169277Sariff * Reset DMA position buffer. 1525169277Sariff */ 1526169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1527169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1528169277Sariff 1529169277Sariff /* 1530162922Sariff * Reset the controller. The reset must remain asserted for 1531162922Sariff * a minimum of 100us. 1532162922Sariff */ 1533162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1534162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1535162922Sariff count = 10000; 1536162922Sariff do { 1537162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1538162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1539162922Sariff break; 1540162922Sariff DELAY(10); 1541162922Sariff } while (--count); 1542162922Sariff if (gctl & HDAC_GCTL_CRST) { 1543162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1544162922Sariff return (ENXIO); 1545162922Sariff } 1546182999Smav 1547182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 1548182999Smav if (!wakeup) 1549182999Smav return (0); 1550182999Smav 1551162922Sariff DELAY(100); 1552162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1553162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1554162922Sariff count = 10000; 1555162922Sariff do { 1556162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1557163057Sariff if (gctl & HDAC_GCTL_CRST) 1558162922Sariff break; 1559162922Sariff DELAY(10); 1560162922Sariff } while (--count); 1561162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1562162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1563162922Sariff return (ENXIO); 1564162922Sariff } 1565162922Sariff 1566162922Sariff /* 1567162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1568162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1569162922Sariff * computer. Let's use twice as much as necessary to make sure that 1570162922Sariff * it's reset properly. 1571162922Sariff */ 1572162922Sariff DELAY(1000); 1573162922Sariff 1574162922Sariff return (0); 1575162922Sariff} 1576162922Sariff 1577162922Sariff 1578162922Sariff/**************************************************************************** 1579162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1580162922Sariff * 1581162922Sariff * Retreive the general capabilities of the hdac; 1582162922Sariff * Number of Input Streams 1583162922Sariff * Number of Output Streams 1584162922Sariff * Number of bidirectional Streams 1585162922Sariff * 64bit ready 1586162922Sariff * CORB and RIRB sizes 1587162922Sariff ****************************************************************************/ 1588162922Sariffstatic int 1589162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1590162922Sariff{ 1591162922Sariff uint16_t gcap; 1592162922Sariff uint8_t corbsize, rirbsize; 1593162922Sariff 1594162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1595162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1596162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1597162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1598196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 1599163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1600162922Sariff 1601162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1602162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1603162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1604162922Sariff sc->corb_size = 256; 1605162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1606162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1607162922Sariff sc->corb_size = 16; 1608162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1609162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1610162922Sariff sc->corb_size = 2; 1611162922Sariff else { 1612162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1613162922Sariff __func__, corbsize); 1614162922Sariff return (ENXIO); 1615162922Sariff } 1616162922Sariff 1617162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1618162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1619162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1620162922Sariff sc->rirb_size = 256; 1621162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1622162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1623162922Sariff sc->rirb_size = 16; 1624162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1625162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1626162922Sariff sc->rirb_size = 2; 1627162922Sariff else { 1628162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1629162922Sariff __func__, rirbsize); 1630162922Sariff return (ENXIO); 1631162922Sariff } 1632162922Sariff 1633196762Smav HDA_BOOTVERBOSE( 1634196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 1635196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 1636196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 1637196762Smav sc->support_64bit ? ", 64bit" : "", 1638196762Smav sc->corb_size, sc->rirb_size); 1639182999Smav ); 1640182999Smav 1641162922Sariff return (0); 1642162922Sariff} 1643162922Sariff 1644162922Sariff 1645162922Sariff/**************************************************************************** 1646162922Sariff * void hdac_dma_cb 1647162922Sariff * 1648162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1649162922Sariff * established. We just record the physical address of the mapping into 1650162922Sariff * the struct hdac_dma passed in. 1651162922Sariff ****************************************************************************/ 1652162922Sariffstatic void 1653162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1654162922Sariff{ 1655162922Sariff struct hdac_dma *dma; 1656162922Sariff 1657162922Sariff if (error == 0) { 1658162922Sariff dma = (struct hdac_dma *)callback_arg; 1659162922Sariff dma->dma_paddr = segs[0].ds_addr; 1660162922Sariff } 1661162922Sariff} 1662162922Sariff 1663162922Sariff 1664162922Sariff/**************************************************************************** 1665162922Sariff * int hdac_dma_alloc 1666162922Sariff * 1667162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1668162922Sariff * It must be freed by a corresponding hdac_dma_free. 1669162922Sariff ****************************************************************************/ 1670162922Sariffstatic int 1671162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1672162922Sariff{ 1673169277Sariff bus_size_t roundsz; 1674162922Sariff int result; 1675162922Sariff 1676169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1677162922Sariff bzero(dma, sizeof(*dma)); 1678162922Sariff 1679162922Sariff /* 1680162922Sariff * Create a DMA tag 1681162922Sariff */ 1682194861Smav result = bus_dma_tag_create( 1683194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1684162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1685162922Sariff 0, /* boundary */ 1686194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1687194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1688162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1689162922Sariff NULL, /* filtfunc */ 1690162922Sariff NULL, /* fistfuncarg */ 1691169277Sariff roundsz, /* maxsize */ 1692162922Sariff 1, /* nsegments */ 1693169277Sariff roundsz, /* maxsegsz */ 1694162922Sariff 0, /* flags */ 1695162922Sariff NULL, /* lockfunc */ 1696162922Sariff NULL, /* lockfuncarg */ 1697162922Sariff &dma->dma_tag); /* dmat */ 1698162922Sariff if (result != 0) { 1699162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1700162922Sariff __func__, result); 1701167773Sariff goto hdac_dma_alloc_fail; 1702162922Sariff } 1703162922Sariff 1704162922Sariff /* 1705162922Sariff * Allocate DMA memory 1706162922Sariff */ 1707162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1708169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1709171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1710171330Sariff &dma->dma_map); 1711162922Sariff if (result != 0) { 1712162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1713162922Sariff __func__, result); 1714167773Sariff goto hdac_dma_alloc_fail; 1715162922Sariff } 1716162922Sariff 1717169277Sariff dma->dma_size = roundsz; 1718169277Sariff 1719162922Sariff /* 1720162922Sariff * Map the memory 1721162922Sariff */ 1722162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1723169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1724162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1725167773Sariff if (result == 0) 1726167773Sariff result = ENOMEM; 1727162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1728162922Sariff __func__, result); 1729167773Sariff goto hdac_dma_alloc_fail; 1730162922Sariff } 1731162922Sariff 1732183097Smav HDA_BOOTHVERBOSE( 1733169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1734169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1735169277Sariff ); 1736169277Sariff 1737162922Sariff return (0); 1738169277Sariff 1739167773Sariffhdac_dma_alloc_fail: 1740169277Sariff hdac_dma_free(sc, dma); 1741167773Sariff 1742162922Sariff return (result); 1743162922Sariff} 1744162922Sariff 1745162922Sariff 1746162922Sariff/**************************************************************************** 1747169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1748162922Sariff * 1749162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1750162922Sariff * hdac_dma_alloc function. 1751162922Sariff ****************************************************************************/ 1752162922Sariffstatic void 1753169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1754162922Sariff{ 1755167773Sariff if (dma->dma_map != NULL) { 1756169277Sariff#if 0 1757162922Sariff /* Flush caches */ 1758162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1759162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1760169277Sariff#endif 1761162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1762167773Sariff } 1763167773Sariff if (dma->dma_vaddr != NULL) { 1764162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1765167773Sariff dma->dma_vaddr = NULL; 1766167773Sariff } 1767167773Sariff dma->dma_map = NULL; 1768167773Sariff if (dma->dma_tag != NULL) { 1769162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1770167773Sariff dma->dma_tag = NULL; 1771162922Sariff } 1772167773Sariff dma->dma_size = 0; 1773162922Sariff} 1774162922Sariff 1775162922Sariff/**************************************************************************** 1776162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1777162922Sariff * 1778162922Sariff * Allocate all the bus resources necessary to speak with the physical 1779162922Sariff * controller. 1780162922Sariff ****************************************************************************/ 1781162922Sariffstatic int 1782162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1783162922Sariff{ 1784162922Sariff struct hdac_mem *mem; 1785162922Sariff 1786162922Sariff mem = &sc->mem; 1787162922Sariff mem->mem_rid = PCIR_BAR(0); 1788162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1789162922Sariff &mem->mem_rid, RF_ACTIVE); 1790162922Sariff if (mem->mem_res == NULL) { 1791162922Sariff device_printf(sc->dev, 1792162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1793162922Sariff return (ENOMEM); 1794162922Sariff } 1795162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1796162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1797162922Sariff 1798162922Sariff return (0); 1799162922Sariff} 1800162922Sariff 1801162922Sariff/**************************************************************************** 1802162922Sariff * void hdac_mem_free(struct hdac_softc *) 1803162922Sariff * 1804162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1805162922Sariff ****************************************************************************/ 1806162922Sariffstatic void 1807162922Sariffhdac_mem_free(struct hdac_softc *sc) 1808162922Sariff{ 1809162922Sariff struct hdac_mem *mem; 1810162922Sariff 1811162922Sariff mem = &sc->mem; 1812162922Sariff if (mem->mem_res != NULL) 1813162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1814162922Sariff mem->mem_res); 1815164614Sariff mem->mem_res = NULL; 1816162922Sariff} 1817162922Sariff 1818162922Sariff/**************************************************************************** 1819162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1820162922Sariff * 1821162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1822162922Sariff ****************************************************************************/ 1823162922Sariffstatic int 1824162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1825162922Sariff{ 1826162922Sariff struct hdac_irq *irq; 1827162922Sariff int result; 1828162922Sariff 1829162922Sariff irq = &sc->irq; 1830162922Sariff irq->irq_rid = 0x0; 1831171330Sariff 1832171330Sariff if ((sc->flags & HDAC_F_MSI) && 1833171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1834171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1835171330Sariff irq->irq_rid = 0x1; 1836171330Sariff else 1837171330Sariff sc->flags &= ~HDAC_F_MSI; 1838171330Sariff 1839162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1840162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1841162922Sariff if (irq->irq_res == NULL) { 1842162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1843162922Sariff __func__); 1844167773Sariff goto hdac_irq_alloc_fail; 1845162922Sariff } 1846182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 1847182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 1848162922Sariff if (result != 0) { 1849162922Sariff device_printf(sc->dev, 1850162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1851162922Sariff __func__, result); 1852167773Sariff goto hdac_irq_alloc_fail; 1853162922Sariff } 1854162922Sariff 1855162922Sariff return (0); 1856162922Sariff 1857167773Sariffhdac_irq_alloc_fail: 1858164614Sariff hdac_irq_free(sc); 1859164614Sariff 1860162922Sariff return (ENXIO); 1861162922Sariff} 1862162922Sariff 1863162922Sariff/**************************************************************************** 1864162922Sariff * void hdac_irq_free(struct hdac_softc *) 1865162922Sariff * 1866162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1867162922Sariff ****************************************************************************/ 1868162922Sariffstatic void 1869162922Sariffhdac_irq_free(struct hdac_softc *sc) 1870162922Sariff{ 1871162922Sariff struct hdac_irq *irq; 1872162922Sariff 1873162922Sariff irq = &sc->irq; 1874164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1875162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1876162922Sariff if (irq->irq_res != NULL) 1877162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1878162922Sariff irq->irq_res); 1879188656Smav if (irq->irq_rid == 0x1) 1880171330Sariff pci_release_msi(sc->dev); 1881164614Sariff irq->irq_handle = NULL; 1882164614Sariff irq->irq_res = NULL; 1883171330Sariff irq->irq_rid = 0x0; 1884162922Sariff} 1885162922Sariff 1886162922Sariff/**************************************************************************** 1887162922Sariff * void hdac_corb_init(struct hdac_softc *) 1888162922Sariff * 1889162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1890162922Sariff * The CORB engine must not be running when this function is called. 1891162922Sariff ****************************************************************************/ 1892162922Sariffstatic void 1893162922Sariffhdac_corb_init(struct hdac_softc *sc) 1894162922Sariff{ 1895162922Sariff uint8_t corbsize; 1896162922Sariff uint64_t corbpaddr; 1897162922Sariff 1898162922Sariff /* Setup the CORB size. */ 1899162922Sariff switch (sc->corb_size) { 1900162922Sariff case 256: 1901162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1902162922Sariff break; 1903162922Sariff case 16: 1904162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1905162922Sariff break; 1906162922Sariff case 2: 1907162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1908162922Sariff break; 1909162922Sariff default: 1910162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1911162922Sariff } 1912162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1913162922Sariff 1914162922Sariff /* Setup the CORB Address in the hdac */ 1915162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1916162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1917162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1918162922Sariff 1919162922Sariff /* Set the WP and RP */ 1920162922Sariff sc->corb_wp = 0; 1921162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1922162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1923162922Sariff /* 1924162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1925162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1926162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1927162922Sariff * manually reset the bit to zero before continuing. 1928162922Sariff */ 1929162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1930162922Sariff 1931162922Sariff /* Enable CORB error reporting */ 1932162922Sariff#if 0 1933162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1934162922Sariff#endif 1935162922Sariff} 1936162922Sariff 1937162922Sariff/**************************************************************************** 1938162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1939162922Sariff * 1940162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1941162922Sariff * The RIRB engine must not be running when this function is called. 1942162922Sariff ****************************************************************************/ 1943162922Sariffstatic void 1944162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1945162922Sariff{ 1946162922Sariff uint8_t rirbsize; 1947162922Sariff uint64_t rirbpaddr; 1948162922Sariff 1949162922Sariff /* Setup the RIRB size. */ 1950162922Sariff switch (sc->rirb_size) { 1951162922Sariff case 256: 1952162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1953162922Sariff break; 1954162922Sariff case 16: 1955162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1956162922Sariff break; 1957162922Sariff case 2: 1958162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1959162922Sariff break; 1960162922Sariff default: 1961162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1962162922Sariff } 1963162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1964162922Sariff 1965162922Sariff /* Setup the RIRB Address in the hdac */ 1966162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1967162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1968162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1969162922Sariff 1970162922Sariff /* Setup the WP and RP */ 1971162922Sariff sc->rirb_rp = 0; 1972162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1973162922Sariff 1974182999Smav /* Setup the interrupt threshold */ 1975182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1976162922Sariff 1977182999Smav /* Enable Overrun and response received reporting */ 1978162922Sariff#if 0 1979182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1980182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1981162922Sariff#else 1982182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1983162922Sariff#endif 1984162922Sariff 1985169277Sariff#if 0 1986162922Sariff /* 1987162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1988162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1989162922Sariff * should be sufficient to do this only once as the rirb is purely 1990162922Sariff * read-only from now on. 1991162922Sariff */ 1992162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1993162922Sariff BUS_DMASYNC_PREREAD); 1994169277Sariff#endif 1995162922Sariff} 1996162922Sariff 1997162922Sariff/**************************************************************************** 1998162922Sariff * void hdac_corb_start(hdac_softc *) 1999162922Sariff * 2000162922Sariff * Startup the corb DMA engine 2001162922Sariff ****************************************************************************/ 2002162922Sariffstatic void 2003162922Sariffhdac_corb_start(struct hdac_softc *sc) 2004162922Sariff{ 2005162922Sariff uint32_t corbctl; 2006162922Sariff 2007162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 2008162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 2009162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 2010162922Sariff} 2011162922Sariff 2012162922Sariff/**************************************************************************** 2013162922Sariff * void hdac_rirb_start(hdac_softc *) 2014162922Sariff * 2015162922Sariff * Startup the rirb DMA engine 2016162922Sariff ****************************************************************************/ 2017162922Sariffstatic void 2018162922Sariffhdac_rirb_start(struct hdac_softc *sc) 2019162922Sariff{ 2020162922Sariff uint32_t rirbctl; 2021162922Sariff 2022162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 2023162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 2024162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 2025162922Sariff} 2026162922Sariff 2027162922Sariff 2028162922Sariff/**************************************************************************** 2029172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 2030162922Sariff * 2031172811Sariff * Scan the bus for available codecs, starting with num. 2032162922Sariff ****************************************************************************/ 2033162922Sariffstatic void 2034182999Smavhdac_scan_codecs(struct hdac_softc *sc) 2035162922Sariff{ 2036162922Sariff struct hdac_codec *codec; 2037162922Sariff int i; 2038162922Sariff uint16_t statests; 2039162922Sariff 2040162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 2041182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 2042162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 2043162922Sariff /* We have found a codec. */ 2044162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 2045162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 2046162922Sariff if (codec == NULL) { 2047162922Sariff device_printf(sc->dev, 2048162922Sariff "Unable to allocate memory for codec\n"); 2049162922Sariff continue; 2050162922Sariff } 2051164614Sariff codec->commands = NULL; 2052164614Sariff codec->responses_received = 0; 2053162922Sariff codec->verbs_sent = 0; 2054162922Sariff codec->sc = sc; 2055162922Sariff codec->cad = i; 2056162922Sariff sc->codecs[i] = codec; 2057182999Smav hdac_probe_codec(codec); 2058162922Sariff } 2059162922Sariff } 2060162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 2061163057Sariff /* bus_generic_attach(sc->dev); */ 2062162922Sariff} 2063162922Sariff 2064162922Sariff/**************************************************************************** 2065162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 2066162922Sariff * 2067162922Sariff * Probe a the given codec_id for available function groups. 2068162922Sariff ****************************************************************************/ 2069182999Smavstatic void 2070162922Sariffhdac_probe_codec(struct hdac_codec *codec) 2071162922Sariff{ 2072162922Sariff struct hdac_softc *sc = codec->sc; 2073162922Sariff uint32_t vendorid, revisionid, subnode; 2074162922Sariff int startnode; 2075162922Sariff int endnode; 2076162922Sariff int i; 2077162922Sariff nid_t cad = codec->cad; 2078162922Sariff 2079163057Sariff HDA_BOOTVERBOSE( 2080184089Smav device_printf(sc->dev, "Probing codec #%d...\n", cad); 2081162922Sariff ); 2082162922Sariff vendorid = hdac_command(sc, 2083162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 2084162922Sariff cad); 2085162922Sariff revisionid = hdac_command(sc, 2086162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 2087162922Sariff cad); 2088182999Smav codec->vendor_id = HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 2089182999Smav codec->device_id = HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 2090182999Smav codec->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 2091182999Smav codec->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 2092182999Smav 2093182999Smav if (vendorid == HDAC_INVALID && revisionid == HDAC_INVALID) { 2094182999Smav device_printf(sc->dev, "Codec #%d is not responding!" 2095182999Smav " Probing aborted.\n", cad); 2096182999Smav return; 2097182999Smav } 2098182999Smav 2099184089Smav device_printf(sc->dev, "HDA Codec #%d: %s\n", 2100182999Smav cad, hdac_codec_name(codec)); 2101182999Smav HDA_BOOTVERBOSE( 2102184089Smav device_printf(sc->dev, " HDA Codec ID: 0x%08x\n", 2103182999Smav hdac_codec_id(codec)); 2104182999Smav device_printf(sc->dev, " Vendor: 0x%04x\n", 2105182999Smav codec->vendor_id); 2106182999Smav device_printf(sc->dev, " Device: 0x%04x\n", 2107182999Smav codec->device_id); 2108182999Smav device_printf(sc->dev, " Revision: 0x%02x\n", 2109182999Smav codec->revision_id); 2110182999Smav device_printf(sc->dev, " Stepping: 0x%02x\n", 2111182999Smav codec->stepping_id); 2112182999Smav device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2113182999Smav sc->pci_subvendor); 2114182999Smav ); 2115162922Sariff subnode = hdac_command(sc, 2116162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 2117162922Sariff cad); 2118162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 2119162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 2120162922Sariff 2121183097Smav HDA_BOOTHVERBOSE( 2122182999Smav device_printf(sc->dev, "\tstartnode=%d endnode=%d\n", 2123163057Sariff startnode, endnode); 2124162922Sariff ); 2125182999Smav 2126182999Smav codec->fgs = (struct hdac_devinfo *)malloc(sizeof(struct hdac_devinfo) * 2127182999Smav (endnode - startnode), M_HDAC, M_NOWAIT | M_ZERO); 2128182999Smav if (codec->fgs == NULL) { 2129183024Smav device_printf(sc->dev, "%s: Unable to allocate function groups\n", 2130182999Smav __func__); 2131182999Smav return; 2132162922Sariff } 2133162922Sariff 2134182999Smav for (i = startnode; i < endnode; i++) 2135182999Smav hdac_probe_function(codec, i); 2136182999Smav return; 2137162922Sariff} 2138162922Sariff 2139182999Smav/* 2140182999Smav * Probe codec function and add it to the list. 2141182999Smav */ 2142182999Smavstatic void 2143162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 2144162922Sariff{ 2145162922Sariff struct hdac_softc *sc = codec->sc; 2146182999Smav struct hdac_devinfo *devinfo = &codec->fgs[codec->num_fgs]; 2147162922Sariff uint32_t fctgrptype; 2148182999Smav uint32_t res; 2149162922Sariff nid_t cad = codec->cad; 2150162922Sariff 2151162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 2152162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 2153162922Sariff 2154162922Sariff devinfo->nid = nid; 2155162965Sariff devinfo->node_type = fctgrptype; 2156162922Sariff devinfo->codec = codec; 2157162922Sariff 2158182999Smav res = hdac_command(sc, 2159182999Smav HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2160162922Sariff 2161182999Smav devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2162182999Smav devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2163182999Smav devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2164162922Sariff 2165182999Smav HDA_BOOTVERBOSE( 2166182999Smav device_printf(sc->dev, 2167182999Smav "\tFound %s FG nid=%d startnode=%d endnode=%d total=%d\n", 2168182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 2169182999Smav (fctgrptype == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 2170182999Smav "unknown", nid, devinfo->startnode, devinfo->endnode, 2171182999Smav devinfo->nodecnt); 2172182999Smav ); 2173182999Smav 2174182999Smav if (devinfo->nodecnt > 0) 2175182999Smav devinfo->widget = (struct hdac_widget *)malloc( 2176182999Smav sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2177182999Smav M_NOWAIT | M_ZERO); 2178182999Smav else 2179182999Smav devinfo->widget = NULL; 2180182999Smav 2181182999Smav if (devinfo->widget == NULL) { 2182182999Smav device_printf(sc->dev, "unable to allocate widgets!\n"); 2183182999Smav devinfo->endnode = devinfo->startnode; 2184182999Smav devinfo->nodecnt = 0; 2185182999Smav return; 2186182999Smav } 2187182999Smav 2188182999Smav codec->num_fgs++; 2189162922Sariff} 2190162922Sariff 2191162922Sariffstatic void 2192162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 2193162922Sariff{ 2194162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2195162922Sariff uint32_t res; 2196169277Sariff int i, j, max, ents, entnum; 2197162922Sariff nid_t cad = w->devinfo->codec->cad; 2198162922Sariff nid_t nid = w->nid; 2199169277Sariff nid_t cnid, addcnid, prevcnid; 2200162922Sariff 2201169277Sariff w->nconns = 0; 2202169277Sariff 2203162922Sariff res = hdac_command(sc, 2204162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 2205162922Sariff 2206169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 2207162922Sariff 2208169277Sariff if (ents < 1) 2209162922Sariff return; 2210162922Sariff 2211162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 2212162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 2213169277Sariff prevcnid = 0; 2214162922Sariff 2215169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 2216169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 2217169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 2218169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 2219169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 2220169277Sariff 2221169277Sariff for (i = 0; i < ents; i += entnum) { 2222162922Sariff res = hdac_command(sc, 2223162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 2224162922Sariff for (j = 0; j < entnum; j++) { 2225169277Sariff cnid = CONN_CNID(res, entnum, j); 2226169277Sariff if (cnid == 0) { 2227169277Sariff if (w->nconns < ents) 2228169277Sariff device_printf(sc->dev, 2229169277Sariff "%s: nid=%d WARNING: zero cnid " 2230169277Sariff "entnum=%d j=%d index=%d " 2231169277Sariff "entries=%d found=%d res=0x%08x\n", 2232169277Sariff __func__, nid, entnum, j, i, 2233169277Sariff ents, w->nconns, res); 2234169277Sariff else 2235169277Sariff goto getconns_out; 2236169277Sariff } 2237169277Sariff if (cnid < w->devinfo->startnode || 2238169277Sariff cnid >= w->devinfo->endnode) { 2239169277Sariff HDA_BOOTVERBOSE( 2240169277Sariff device_printf(sc->dev, 2241182999Smav "GHOST: nid=%d j=%d " 2242169277Sariff "entnum=%d index=%d res=0x%08x\n", 2243182999Smav nid, j, entnum, i, res); 2244169277Sariff ); 2245169277Sariff } 2246169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 2247169277Sariff addcnid = cnid; 2248169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 2249162922Sariff device_printf(sc->dev, 2250169277Sariff "%s: WARNING: Invalid child range " 2251169277Sariff "nid=%d index=%d j=%d entnum=%d " 2252169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 2253169277Sariff __func__, nid, i, j, entnum, prevcnid, 2254169277Sariff cnid, res); 2255169277Sariff addcnid = cnid; 2256169277Sariff } else 2257169277Sariff addcnid = prevcnid + 1; 2258169277Sariff while (addcnid <= cnid) { 2259169277Sariff if (w->nconns > max) { 2260169277Sariff device_printf(sc->dev, 2261182999Smav "Adding %d (nid=%d): " 2262169277Sariff "Max connection reached! max=%d\n", 2263182999Smav addcnid, nid, max + 1); 2264169277Sariff goto getconns_out; 2265169277Sariff } 2266182999Smav w->connsenable[w->nconns] = 1; 2267169277Sariff w->conns[w->nconns++] = addcnid++; 2268162922Sariff } 2269169277Sariff prevcnid = cnid; 2270162922Sariff } 2271162922Sariff } 2272162922Sariff 2273169277Sariffgetconns_out: 2274169277Sariff return; 2275162922Sariff} 2276162922Sariff 2277162922Sariffstatic uint32_t 2278182999Smavhdac_widget_pin_patch(uint32_t config, const char *str) 2279182999Smav{ 2280182999Smav char buf[256]; 2281182999Smav char *key, *value, *rest, *bad; 2282182999Smav int ival, i; 2283182999Smav 2284182999Smav strlcpy(buf, str, sizeof(buf)); 2285182999Smav rest = buf; 2286182999Smav while ((key = strsep(&rest, "=")) != NULL) { 2287182999Smav value = strsep(&rest, " \t"); 2288182999Smav if (value == NULL) 2289182999Smav break; 2290182999Smav ival = strtol(value, &bad, 10); 2291182999Smav if (strcmp(key, "seq") == 0) { 2292182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK; 2293182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT) & 2294182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK); 2295182999Smav } else if (strcmp(key, "as") == 0) { 2296182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK; 2297182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT) & 2298182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK); 2299182999Smav } else if (strcmp(key, "misc") == 0) { 2300182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_MISC_MASK; 2301182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_MISC_SHIFT) & 2302182999Smav HDA_CONFIG_DEFAULTCONF_MISC_MASK); 2303182999Smav } else if (strcmp(key, "color") == 0) { 2304182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_COLOR_MASK; 2305182999Smav if (bad[0] == 0) { 2306182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT) & 2307182999Smav HDA_CONFIG_DEFAULTCONF_COLOR_MASK); 2308182999Smav }; 2309182999Smav for (i = 0; i < 16; i++) { 2310182999Smav if (strcasecmp(HDA_COLORS[i], value) == 0) { 2311182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT); 2312182999Smav break; 2313182999Smav } 2314182999Smav } 2315182999Smav } else if (strcmp(key, "ctype") == 0) { 2316182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK; 2317182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT) & 2318182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK); 2319182999Smav } else if (strcmp(key, "device") == 0) { 2320182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2321182999Smav if (bad[0] == 0) { 2322182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT) & 2323182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK); 2324182999Smav continue; 2325182999Smav }; 2326182999Smav for (i = 0; i < 16; i++) { 2327182999Smav if (strcasecmp(HDA_DEVS[i], value) == 0) { 2328182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT); 2329182999Smav break; 2330182999Smav } 2331182999Smav } 2332182999Smav } else if (strcmp(key, "loc") == 0) { 2333182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_LOCATION_MASK; 2334182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT) & 2335182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION_MASK); 2336182999Smav } else if (strcmp(key, "conn") == 0) { 2337182999Smav config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2338182999Smav if (bad[0] == 0) { 2339182999Smav config |= ((ival << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT) & 2340182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2341182999Smav continue; 2342182999Smav }; 2343182999Smav for (i = 0; i < 4; i++) { 2344182999Smav if (strcasecmp(HDA_CONNS[i], value) == 0) { 2345182999Smav config |= (i << HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT); 2346182999Smav break; 2347182999Smav } 2348182999Smav } 2349182999Smav } 2350182999Smav } 2351182999Smav return (config); 2352182999Smav} 2353182999Smav 2354182999Smavstatic uint32_t 2355162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2356162922Sariff{ 2357162922Sariff struct hdac_softc *sc; 2358166965Sariff uint32_t config, orig, id; 2359162922Sariff nid_t cad, nid; 2360182999Smav char buf[32]; 2361182999Smav const char *res = NULL, *patch = NULL; 2362162922Sariff 2363162922Sariff sc = w->devinfo->codec->sc; 2364162922Sariff cad = w->devinfo->codec->cad; 2365162922Sariff nid = w->nid; 2366182999Smav id = hdac_codec_id(w->devinfo->codec); 2367162922Sariff 2368162922Sariff config = hdac_command(sc, 2369162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2370162922Sariff cad); 2371166965Sariff orig = config; 2372166965Sariff 2373182999Smav HDA_BOOTVERBOSE( 2374182999Smav hdac_dump_pin_config(w, orig); 2375182999Smav ); 2376182999Smav 2377182999Smav /* XXX: Old patches require complete review. 2378182999Smav * Now they may create more problem then solve due to 2379182999Smav * incorrect associations. 2380162965Sariff */ 2381165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2382165281Sariff switch (nid) { 2383165281Sariff case 26: 2384165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2385165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2386165281Sariff break; 2387165281Sariff case 27: 2388165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2389165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2390165281Sariff break; 2391167610Sariff default: 2392167610Sariff break; 2393165281Sariff } 2394165281Sariff } else if (id == HDA_CODEC_ALC880 && 2395162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2396162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2397162922Sariff /* 2398162965Sariff * Super broken BIOS 2399162922Sariff */ 2400162922Sariff switch (nid) { 2401162922Sariff case 24: /* MIC1 */ 2402162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2403162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2404162922Sariff break; 2405162922Sariff case 25: /* XXX MIC2 */ 2406162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2407162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2408162922Sariff break; 2409162922Sariff case 26: /* LINE1 */ 2410162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2411162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2412162922Sariff break; 2413162922Sariff case 27: /* XXX LINE2 */ 2414162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2415162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2416162922Sariff break; 2417162922Sariff case 28: /* CD */ 2418162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2419162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2420162922Sariff break; 2421162922Sariff } 2422166965Sariff } else if (id == HDA_CODEC_ALC883 && 2423172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2424172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2425166965Sariff switch (nid) { 2426166965Sariff case 25: 2427166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2428166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2429166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2430166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2431166965Sariff break; 2432169277Sariff case 28: 2433169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2434169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2435169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2436169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2437169277Sariff break; 2438166965Sariff } 2439186430Smav } else if (id == HDA_CODEC_CX20549 && sc->pci_subvendor == 2440166965Sariff HP_V3000_SUBVENDOR) { 2441166965Sariff switch (nid) { 2442166965Sariff case 18: 2443166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2444166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2445166965Sariff break; 2446166965Sariff case 20: 2447166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2448166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2449166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2450166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2451166965Sariff break; 2452167454Sariff case 21: 2453167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2454167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2455167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2456167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2457167454Sariff break; 2458166965Sariff } 2459186430Smav } else if (id == HDA_CODEC_CX20551 && sc->pci_subvendor == 2460169277Sariff HP_DV5000_SUBVENDOR) { 2461169277Sariff switch (nid) { 2462169277Sariff case 20: 2463169277Sariff case 21: 2464169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2465169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2466169277Sariff break; 2467169277Sariff } 2468169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2469169277Sariff ASUS_W6F_SUBVENDOR) { 2470169277Sariff switch (nid) { 2471169277Sariff case 11: 2472169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2473169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2474169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2475169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2476169277Sariff break; 2477178324Sariff case 12: 2478178324Sariff case 14: 2479178324Sariff case 16: 2480178324Sariff case 31: 2481178324Sariff case 32: 2482178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2483178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2484178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2485178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2486178324Sariff break; 2487169277Sariff case 15: 2488169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2489169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2490169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2491169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2492169277Sariff break; 2493169277Sariff } 2494169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2495169277Sariff UNIWILL_9075_SUBVENDOR) { 2496169277Sariff switch (nid) { 2497169277Sariff case 15: 2498169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2499169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2500169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2501169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2502169277Sariff break; 2503169277Sariff } 2504182999Smav } 2505182999Smav 2506182999Smav /* New patches */ 2507182999Smav if (id == HDA_CODEC_AD1986A && 2508171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2509190630Smav sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR || 2510190630Smav sc->pci_subvendor == ASUS_P5PL2_SUBVENDOR)) { 2511169277Sariff switch (nid) { 2512190630Smav case 26: /* Headphones with redirection */ 2513190630Smav patch = "as=1 seq=15"; 2514190630Smav break; 2515190630Smav case 28: /* 5.1 out => 2.0 out + 1 input */ 2516182999Smav patch = "device=Line-in as=8 seq=1"; 2517169277Sariff break; 2518190630Smav case 29: /* Can't use this as input, as the only available mic 2519190630Smav * preamplifier is busy by front panel mic (nid 31). 2520190630Smav * If you want to use this rear connector as mic input, 2521190630Smav * you have to disable the front panel one. */ 2522190630Smav patch = "as=0"; 2523169277Sariff break; 2524182999Smav case 31: /* Lot of inputs configured with as=15 and unusable */ 2525182999Smav patch = "as=8 seq=3"; 2526169277Sariff break; 2527182999Smav case 32: 2528182999Smav patch = "as=8 seq=4"; 2529182999Smav break; 2530182999Smav case 34: 2531182999Smav patch = "as=8 seq=5"; 2532182999Smav break; 2533182999Smav case 36: 2534182999Smav patch = "as=8 seq=6"; 2535182999Smav break; 2536169277Sariff } 2537182999Smav } else if (id == HDA_CODEC_ALC260 && 2538182999Smav HDA_DEV_MATCH(SONY_S5_SUBVENDOR, sc->pci_subvendor)) { 2539182999Smav switch (nid) { 2540182999Smav case 16: 2541182999Smav patch = "seq=15 device=Headphones"; 2542182999Smav break; 2543182999Smav } 2544189879Smav } else if (id == HDA_CODEC_ALC268) { 2545189879Smav if (sc->pci_subvendor == ACER_T5320_SUBVENDOR) { 2546174578Sariff switch (nid) { 2547189879Smav case 20: /* Headphones Jack */ 2548189879Smav patch = "as=1 seq=15"; 2549174578Sariff break; 2550174578Sariff } 2551189879Smav } 2552162922Sariff } 2553162922Sariff 2554182999Smav if (patch != NULL) 2555182999Smav config = hdac_widget_pin_patch(config, patch); 2556182999Smav 2557182999Smav snprintf(buf, sizeof(buf), "cad%u.nid%u.config", cad, nid); 2558182999Smav if (resource_string_value(device_get_name(sc->dev), 2559182999Smav device_get_unit(sc->dev), buf, &res) == 0) { 2560182999Smav if (strncmp(res, "0x", 2) == 0) { 2561182999Smav config = strtol(res + 2, NULL, 16); 2562182999Smav } else { 2563182999Smav config = hdac_widget_pin_patch(config, res); 2564182999Smav } 2565182999Smav } 2566182999Smav 2567166965Sariff HDA_BOOTVERBOSE( 2568166965Sariff if (config != orig) 2569166965Sariff device_printf(sc->dev, 2570182999Smav "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 2571166965Sariff nid, orig, config); 2572166965Sariff ); 2573166965Sariff 2574162922Sariff return (config); 2575162922Sariff} 2576162922Sariff 2577166965Sariffstatic uint32_t 2578166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2579166965Sariff{ 2580166965Sariff struct hdac_softc *sc; 2581166965Sariff uint32_t caps, orig, id; 2582166965Sariff nid_t cad, nid; 2583166965Sariff 2584166965Sariff sc = w->devinfo->codec->sc; 2585166965Sariff cad = w->devinfo->codec->cad; 2586166965Sariff nid = w->nid; 2587182999Smav id = hdac_codec_id(w->devinfo->codec); 2588166965Sariff 2589166965Sariff caps = hdac_command(sc, 2590166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2591166965Sariff orig = caps; 2592166965Sariff 2593166965Sariff HDA_BOOTVERBOSE( 2594166965Sariff if (caps != orig) 2595166965Sariff device_printf(sc->dev, 2596182999Smav "Patching pin caps nid=%u 0x%08x -> 0x%08x\n", 2597166965Sariff nid, orig, caps); 2598166965Sariff ); 2599166965Sariff 2600166965Sariff return (caps); 2601166965Sariff} 2602166965Sariff 2603162922Sariffstatic void 2604162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2605162922Sariff{ 2606162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2607162922Sariff uint32_t config, pincap; 2608186912Smav const char *devstr; 2609162922Sariff nid_t cad = w->devinfo->codec->cad; 2610162922Sariff nid_t nid = w->nid; 2611186912Smav int conn, color; 2612162922Sariff 2613162922Sariff config = hdac_widget_pin_getconfig(w); 2614162922Sariff w->wclass.pin.config = config; 2615162922Sariff 2616166965Sariff pincap = hdac_widget_pin_getcaps(w); 2617162922Sariff w->wclass.pin.cap = pincap; 2618162922Sariff 2619162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2620182999Smav HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad); 2621162922Sariff 2622162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2623162922Sariff w->param.eapdbtl = hdac_command(sc, 2624162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2625162922Sariff w->param.eapdbtl &= 0x7; 2626162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2627162922Sariff } else 2628162965Sariff w->param.eapdbtl = HDAC_INVALID; 2629162922Sariff 2630182999Smav devstr = HDA_DEVS[(config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> 2631182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT]; 2632162922Sariff 2633186912Smav conn = (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> 2634186912Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT; 2635186912Smav color = (config & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> 2636186912Smav HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT; 2637162922Sariff 2638162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2639162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2640162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2641186912Smav if (conn == 0 && color != 0 && color != 15) { 2642186912Smav strlcat(w->name, HDA_COLORS[color], sizeof(w->name)); 2643186912Smav strlcat(w->name, " ", sizeof(w->name)); 2644186912Smav } 2645186912Smav strlcat(w->name, HDA_CONNS[conn], sizeof(w->name)); 2646162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2647162922Sariff} 2648162922Sariff 2649182999Smavstatic uint32_t 2650182999Smavhdac_widget_getcaps(struct hdac_widget *w, int *waspin) 2651182999Smav{ 2652182999Smav struct hdac_softc *sc; 2653182999Smav uint32_t caps, orig, id; 2654182999Smav nid_t cad, nid, beeper = -1; 2655182999Smav 2656182999Smav sc = w->devinfo->codec->sc; 2657182999Smav cad = w->devinfo->codec->cad; 2658182999Smav nid = w->nid; 2659182999Smav id = hdac_codec_id(w->devinfo->codec); 2660182999Smav 2661182999Smav caps = hdac_command(sc, 2662182999Smav HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2663182999Smav cad); 2664182999Smav orig = caps; 2665182999Smav 2666182999Smav /* On some codecs beeper is an input pin, but it is not recordable 2667182999Smav alone. Also most of BIOSes does not declare beeper pin. 2668182999Smav Change beeper pin node type to beeper to help parser. */ 2669182999Smav *waspin = 0; 2670182999Smav switch (id) { 2671187721Smav case HDA_CODEC_AD1882: 2672187721Smav case HDA_CODEC_AD1883: 2673187721Smav case HDA_CODEC_AD1984: 2674187721Smav case HDA_CODEC_AD1984A: 2675187721Smav case HDA_CODEC_AD1984B: 2676187721Smav case HDA_CODEC_AD1987: 2677182999Smav case HDA_CODEC_AD1988: 2678182999Smav case HDA_CODEC_AD1988B: 2679187721Smav case HDA_CODEC_AD1989B: 2680182999Smav beeper = 26; 2681182999Smav break; 2682182999Smav case HDA_CODEC_ALC260: 2683182999Smav beeper = 23; 2684182999Smav break; 2685182999Smav case HDA_CODEC_ALC262: 2686182999Smav case HDA_CODEC_ALC268: 2687182999Smav case HDA_CODEC_ALC880: 2688182999Smav case HDA_CODEC_ALC882: 2689182999Smav case HDA_CODEC_ALC883: 2690182999Smav case HDA_CODEC_ALC885: 2691182999Smav case HDA_CODEC_ALC888: 2692182999Smav case HDA_CODEC_ALC889: 2693182999Smav beeper = 29; 2694182999Smav break; 2695182999Smav } 2696182999Smav if (nid == beeper) { 2697182999Smav caps &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 2698182999Smav caps |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 2699182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 2700182999Smav *waspin = 1; 2701182999Smav } 2702182999Smav 2703182999Smav HDA_BOOTVERBOSE( 2704182999Smav if (caps != orig) { 2705182999Smav device_printf(sc->dev, 2706182999Smav "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 2707182999Smav nid, orig, caps); 2708182999Smav } 2709182999Smav ); 2710182999Smav 2711182999Smav return (caps); 2712182999Smav} 2713182999Smav 2714162922Sariffstatic void 2715162922Sariffhdac_widget_parse(struct hdac_widget *w) 2716162922Sariff{ 2717162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2718162922Sariff uint32_t wcap, cap; 2719162922Sariff char *typestr; 2720162922Sariff nid_t cad = w->devinfo->codec->cad; 2721162922Sariff nid_t nid = w->nid; 2722162922Sariff 2723182999Smav wcap = hdac_widget_getcaps(w, &w->waspin); 2724182999Smav 2725162922Sariff w->param.widget_cap = wcap; 2726162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2727162922Sariff 2728162922Sariff switch (w->type) { 2729162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2730162922Sariff typestr = "audio output"; 2731162922Sariff break; 2732162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2733162922Sariff typestr = "audio input"; 2734162922Sariff break; 2735162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2736162922Sariff typestr = "audio mixer"; 2737162922Sariff break; 2738162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2739162922Sariff typestr = "audio selector"; 2740162922Sariff break; 2741162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2742162922Sariff typestr = "pin"; 2743162922Sariff break; 2744162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2745162922Sariff typestr = "power widget"; 2746162922Sariff break; 2747162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2748162922Sariff typestr = "volume widget"; 2749162922Sariff break; 2750162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2751162922Sariff typestr = "beep widget"; 2752162922Sariff break; 2753162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2754162922Sariff typestr = "vendor widget"; 2755162922Sariff break; 2756162922Sariff default: 2757162922Sariff typestr = "unknown type"; 2758162922Sariff break; 2759162922Sariff } 2760162922Sariff 2761162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2762162922Sariff 2763162922Sariff hdac_widget_connection_parse(w); 2764162922Sariff 2765162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2766162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2767162922Sariff w->param.outamp_cap = 2768162922Sariff hdac_command(sc, 2769162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2770162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2771162922Sariff else 2772162922Sariff w->param.outamp_cap = 2773162922Sariff w->devinfo->function.audio.outamp_cap; 2774162922Sariff } else 2775162922Sariff w->param.outamp_cap = 0; 2776162922Sariff 2777162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2778162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2779162922Sariff w->param.inamp_cap = 2780162922Sariff hdac_command(sc, 2781162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2782162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2783162922Sariff else 2784162922Sariff w->param.inamp_cap = 2785162922Sariff w->devinfo->function.audio.inamp_cap; 2786162922Sariff } else 2787162922Sariff w->param.inamp_cap = 0; 2788162922Sariff 2789162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2790162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2791162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2792162922Sariff cap = hdac_command(sc, 2793162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2794162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2795162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2796162922Sariff w->devinfo->function.audio.supp_stream_formats; 2797162922Sariff cap = hdac_command(sc, 2798162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2799162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2800162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2801162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2802162922Sariff } else { 2803162922Sariff w->param.supp_stream_formats = 2804162922Sariff w->devinfo->function.audio.supp_stream_formats; 2805162922Sariff w->param.supp_pcm_size_rate = 2806162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2807162922Sariff } 2808162922Sariff } else { 2809162922Sariff w->param.supp_stream_formats = 0; 2810162922Sariff w->param.supp_pcm_size_rate = 0; 2811162922Sariff } 2812162922Sariff 2813162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2814162922Sariff hdac_widget_pin_parse(w); 2815162922Sariff} 2816162922Sariff 2817162922Sariffstatic struct hdac_widget * 2818162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2819162922Sariff{ 2820162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2821162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2822162922Sariff return (NULL); 2823162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2824162922Sariff} 2825162922Sariff 2826164614Sariffstatic __inline int 2827164614Sariffhda_poll_channel(struct hdac_chan *ch) 2828164614Sariff{ 2829164614Sariff uint32_t sz, delta; 2830164614Sariff volatile uint32_t ptr; 2831164614Sariff 2832171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2833164614Sariff return (0); 2834164614Sariff 2835164614Sariff sz = ch->blksz * ch->blkcnt; 2836169277Sariff if (ch->dmapos != NULL) 2837169277Sariff ptr = *(ch->dmapos); 2838169277Sariff else 2839169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2840169277Sariff ch->off + HDAC_SDLPIB); 2841164614Sariff ch->ptr = ptr; 2842164614Sariff ptr %= sz; 2843164614Sariff ptr &= ~(ch->blksz - 1); 2844164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2845164614Sariff 2846164614Sariff if (delta < ch->blksz) 2847164614Sariff return (0); 2848164614Sariff 2849164614Sariff ch->prevptr = ptr; 2850164614Sariff 2851164614Sariff return (1); 2852164614Sariff} 2853164614Sariff 2854162922Sariffstatic void 2855164614Sariffhda_poll_callback(void *arg) 2856164614Sariff{ 2857164614Sariff struct hdac_softc *sc = arg; 2858171141Sariff uint32_t trigger; 2859182999Smav int i, active = 0; 2860164614Sariff 2861164614Sariff if (sc == NULL) 2862164614Sariff return; 2863164614Sariff 2864164614Sariff hdac_lock(sc); 2865182999Smav if (sc->polling == 0) { 2866164614Sariff hdac_unlock(sc); 2867164614Sariff return; 2868164614Sariff } 2869164614Sariff 2870171141Sariff trigger = 0; 2871182999Smav for (i = 0; i < sc->num_chans; i++) { 2872182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2873182999Smav continue; 2874182999Smav active = 1; 2875182999Smav if (hda_poll_channel(&sc->chans[i])) 2876182999Smav trigger |= (1 << i); 2877182999Smav } 2878164614Sariff 2879164614Sariff /* XXX */ 2880182999Smav if (active) 2881182999Smav callout_reset(&sc->poll_hda, sc->poll_ticks, 2882182999Smav hda_poll_callback, sc); 2883164614Sariff 2884164614Sariff hdac_unlock(sc); 2885164614Sariff 2886182999Smav for (i = 0; i < sc->num_chans; i++) { 2887182999Smav if (trigger & (1 << i)) 2888182999Smav chn_intr(sc->chans[i].c); 2889182999Smav } 2890164614Sariff} 2891164614Sariff 2892164614Sariffstatic int 2893164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2894164614Sariff{ 2895164614Sariff struct hdac_rirb *rirb_base, *rirb; 2896164614Sariff struct hdac_codec *codec; 2897164614Sariff struct hdac_command_list *commands; 2898164614Sariff nid_t cad; 2899164614Sariff uint32_t resp; 2900164614Sariff uint8_t rirbwp; 2901171141Sariff int ret; 2902164614Sariff 2903164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2904164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2905169277Sariff#if 0 2906164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2907164614Sariff BUS_DMASYNC_POSTREAD); 2908169277Sariff#endif 2909164614Sariff 2910171141Sariff ret = 0; 2911171141Sariff 2912164614Sariff while (sc->rirb_rp != rirbwp) { 2913164614Sariff sc->rirb_rp++; 2914164614Sariff sc->rirb_rp %= sc->rirb_size; 2915164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2916164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2917164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2918164614Sariff sc->codecs[cad] == NULL) 2919164614Sariff continue; 2920164614Sariff resp = rirb->response; 2921164614Sariff codec = sc->codecs[cad]; 2922164614Sariff commands = codec->commands; 2923164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2924164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2925164614Sariff ((resp >> 26) & 0xffff); 2926164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2927164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2928164614Sariff codec->responses_received < commands->num_commands) 2929164614Sariff commands->responses[codec->responses_received++] = 2930164614Sariff resp; 2931164614Sariff ret++; 2932164614Sariff } 2933164614Sariff 2934164614Sariff return (ret); 2935164614Sariff} 2936164614Sariff 2937164614Sariffstatic int 2938164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2939164614Sariff{ 2940164614Sariff nid_t cad; 2941164614Sariff uint32_t tag; 2942164614Sariff int ret = 0; 2943164614Sariff 2944164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2945164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2946164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2947164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2948164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2949164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2950164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2951164614Sariff ret++; 2952164614Sariff } 2953164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2954164614Sariff } 2955164614Sariff 2956164614Sariff return (ret); 2957164614Sariff} 2958164614Sariff 2959164614Sariffstatic void 2960164614Sariffhdac_poll_callback(void *arg) 2961164614Sariff{ 2962164614Sariff struct hdac_softc *sc = arg; 2963164614Sariff if (sc == NULL) 2964164614Sariff return; 2965166796Sariff 2966164614Sariff hdac_lock(sc); 2967169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2968164614Sariff hdac_unlock(sc); 2969164614Sariff return; 2970164614Sariff } 2971171141Sariff if (hdac_rirb_flush(sc) != 0) 2972171141Sariff hdac_unsolq_flush(sc); 2973169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2974164614Sariff hdac_unlock(sc); 2975164614Sariff} 2976164614Sariff 2977164614Sariffstatic void 2978182999Smavhdac_poll_reinit(struct hdac_softc *sc) 2979182999Smav{ 2980182999Smav int i, pollticks, min = 1000000; 2981182999Smav struct hdac_chan *ch; 2982182999Smav 2983182999Smav for (i = 0; i < sc->num_chans; i++) { 2984182999Smav if ((sc->chans[i].flags & HDAC_CHN_RUNNING) == 0) 2985182999Smav continue; 2986182999Smav ch = &sc->chans[i]; 2987182999Smav pollticks = ((uint64_t)hz * ch->blksz) / 2988193640Sariff ((uint64_t)sndbuf_getalign(ch->b) * sndbuf_getspd(ch->b)); 2989182999Smav pollticks >>= 1; 2990182999Smav if (pollticks > hz) 2991182999Smav pollticks = hz; 2992182999Smav if (pollticks < 1) { 2993182999Smav HDA_BOOTVERBOSE( 2994182999Smav device_printf(sc->dev, 2995182999Smav "%s: pollticks=%d < 1 !\n", 2996182999Smav __func__, pollticks); 2997182999Smav ); 2998182999Smav pollticks = 1; 2999182999Smav } 3000182999Smav if (min > pollticks) 3001182999Smav min = pollticks; 3002182999Smav } 3003182999Smav HDA_BOOTVERBOSE( 3004182999Smav device_printf(sc->dev, 3005182999Smav "%s: pollticks %d -> %d\n", 3006182999Smav __func__, sc->poll_ticks, min); 3007182999Smav ); 3008182999Smav sc->poll_ticks = min; 3009182999Smav if (min == 1000000) 3010182999Smav callout_stop(&sc->poll_hda); 3011182999Smav else 3012182999Smav callout_reset(&sc->poll_hda, 1, hda_poll_callback, sc); 3013182999Smav} 3014182999Smav 3015182999Smavstatic void 3016162922Sariffhdac_stream_stop(struct hdac_chan *ch) 3017162922Sariff{ 3018162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3019162922Sariff uint32_t ctl; 3020162922Sariff 3021162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3022162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3023162922Sariff HDAC_SDCTL_RUN); 3024162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3025162922Sariff 3026171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 3027164614Sariff 3028182999Smav if (sc->polling != 0) 3029182999Smav hdac_poll_reinit(sc); 3030164614Sariff 3031182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3032182999Smav ctl &= ~(1 << (ch->off >> 5)); 3033182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3034162922Sariff} 3035162922Sariff 3036162922Sariffstatic void 3037162922Sariffhdac_stream_start(struct hdac_chan *ch) 3038162922Sariff{ 3039162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3040162922Sariff uint32_t ctl; 3041162922Sariff 3042182999Smav ch->flags |= HDAC_CHN_RUNNING; 3043162922Sariff 3044182999Smav if (sc->polling != 0) 3045182999Smav hdac_poll_reinit(sc); 3046182999Smav 3047182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 3048182999Smav ctl |= 1 << (ch->off >> 5); 3049182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 3050182999Smav 3051182999Smav ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3052182999Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 3053182999Smav HDAC_SDCTL_RUN; 3054162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3055162922Sariff} 3056162922Sariff 3057162922Sariffstatic void 3058162922Sariffhdac_stream_reset(struct hdac_chan *ch) 3059162922Sariff{ 3060162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3061162922Sariff int timeout = 1000; 3062162922Sariff int to = timeout; 3063162922Sariff uint32_t ctl; 3064162922Sariff 3065162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3066162922Sariff ctl |= HDAC_SDCTL_SRST; 3067162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3068162922Sariff do { 3069162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3070162922Sariff if (ctl & HDAC_SDCTL_SRST) 3071162922Sariff break; 3072162922Sariff DELAY(10); 3073162922Sariff } while (--to); 3074162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 3075162922Sariff device_printf(sc->dev, "timeout in reset\n"); 3076162922Sariff } 3077162922Sariff ctl &= ~HDAC_SDCTL_SRST; 3078162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 3079162922Sariff to = timeout; 3080162922Sariff do { 3081162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 3082162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 3083162922Sariff break; 3084162922Sariff DELAY(10); 3085162922Sariff } while (--to); 3086163057Sariff if (ctl & HDAC_SDCTL_SRST) 3087162922Sariff device_printf(sc->dev, "can't reset!\n"); 3088162922Sariff} 3089162922Sariff 3090162922Sariffstatic void 3091162922Sariffhdac_stream_setid(struct hdac_chan *ch) 3092162922Sariff{ 3093162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3094162922Sariff uint32_t ctl; 3095162922Sariff 3096162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 3097162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 3098162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 3099162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 3100162922Sariff} 3101162922Sariff 3102162922Sariffstatic void 3103162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 3104162922Sariff{ 3105162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3106164614Sariff struct hdac_bdle *bdle; 3107162922Sariff uint64_t addr; 3108164614Sariff uint32_t blksz, blkcnt; 3109162922Sariff int i; 3110162922Sariff 3111162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 3112164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 3113162922Sariff 3114182999Smav blksz = ch->blksz; 3115182999Smav blkcnt = ch->blkcnt; 3116164614Sariff 3117164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 3118162922Sariff bdle->addrl = (uint32_t)addr; 3119162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 3120164614Sariff bdle->len = blksz; 3121182999Smav bdle->ioc = 1; 3122164614Sariff addr += blksz; 3123162922Sariff } 3124162922Sariff 3125164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 3126164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 3127162922Sariff addr = ch->bdl_dma.dma_paddr; 3128162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 3129162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 3130169277Sariff if (ch->dmapos != NULL && 3131169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 3132169277Sariff addr = sc->pos_dma.dma_paddr; 3133169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 3134169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 3135169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 3136169277Sariff } 3137162922Sariff} 3138162922Sariff 3139162922Sariffstatic int 3140162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 3141162922Sariff{ 3142162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3143162922Sariff int rc; 3144162922Sariff 3145162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 3146162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 3147162922Sariff if (rc) { 3148162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 3149162922Sariff return (rc); 3150162922Sariff } 3151162922Sariff 3152162922Sariff return (0); 3153162922Sariff} 3154162922Sariff 3155162922Sariffstatic void 3156162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 3157162922Sariff int index, int lmute, int rmute, 3158162922Sariff int left, int right, int dir) 3159162922Sariff{ 3160162922Sariff uint16_t v = 0; 3161162922Sariff 3162162922Sariff if (sc == NULL) 3163162922Sariff return; 3164162922Sariff 3165162922Sariff if (left != right || lmute != rmute) { 3166162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 3167162922Sariff (lmute << 7) | left; 3168162922Sariff hdac_command(sc, 3169164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3170162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 3171162922Sariff (rmute << 7) | right; 3172162922Sariff } else 3173162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 3174162922Sariff (lmute << 7) | left; 3175162922Sariff 3176162922Sariff hdac_command(sc, 3177162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 3178162922Sariff} 3179162922Sariff 3180162922Sariffstatic void 3181162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 3182162922Sariff int left, int right) 3183162922Sariff{ 3184162922Sariff struct hdac_softc *sc; 3185162922Sariff nid_t nid, cad; 3186162922Sariff int lmute, rmute; 3187162922Sariff 3188162922Sariff sc = ctl->widget->devinfo->codec->sc; 3189162922Sariff cad = ctl->widget->devinfo->codec->cad; 3190162922Sariff nid = ctl->widget->nid; 3191162922Sariff 3192182999Smav /* Save new values if valid. */ 3193182999Smav if (mute != HDA_AMP_MUTE_DEFAULT) 3194182999Smav ctl->muted = mute; 3195182999Smav if (left != HDA_AMP_VOL_DEFAULT) 3196182999Smav ctl->left = left; 3197182999Smav if (right != HDA_AMP_VOL_DEFAULT) 3198182999Smav ctl->right = right; 3199182999Smav /* Prepare effective values */ 3200182999Smav if (ctl->forcemute) { 3201182999Smav lmute = 1; 3202182999Smav rmute = 1; 3203182999Smav left = 0; 3204182999Smav right = 0; 3205182999Smav } else { 3206162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 3207162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 3208182999Smav left = ctl->left; 3209182999Smav right = ctl->right; 3210162922Sariff } 3211182999Smav /* Apply effective values */ 3212162922Sariff if (ctl->dir & HDA_CTL_OUT) 3213162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3214162922Sariff lmute, rmute, left, right, 0); 3215162922Sariff if (ctl->dir & HDA_CTL_IN) 3216182999Smav hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 3217162922Sariff lmute, rmute, left, right, 1); 3218162922Sariff} 3219162922Sariff 3220162922Sariffstatic void 3221162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 3222162922Sariff{ 3223162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 3224162922Sariff return; 3225162922Sariff hdac_command(w->devinfo->codec->sc, 3226162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 3227162922Sariff w->nid, index), w->devinfo->codec->cad); 3228162922Sariff w->selconn = index; 3229162922Sariff} 3230162922Sariff 3231162922Sariff 3232162922Sariff/**************************************************************************** 3233162922Sariff * uint32_t hdac_command_sendone_internal 3234162922Sariff * 3235162922Sariff * Wrapper function that sends only one command to a given codec 3236162922Sariff ****************************************************************************/ 3237162922Sariffstatic uint32_t 3238162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 3239162922Sariff{ 3240162922Sariff struct hdac_command_list cl; 3241162965Sariff uint32_t response = HDAC_INVALID; 3242162922Sariff 3243163057Sariff if (!hdac_lockowned(sc)) 3244162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 3245162922Sariff cl.num_commands = 1; 3246162922Sariff cl.verbs = &verb; 3247162922Sariff cl.responses = &response; 3248162922Sariff 3249162922Sariff hdac_command_send_internal(sc, &cl, cad); 3250162922Sariff 3251162922Sariff return (response); 3252162922Sariff} 3253162922Sariff 3254162922Sariff/**************************************************************************** 3255162922Sariff * hdac_command_send_internal 3256162922Sariff * 3257162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 3258162922Sariff * we can and msleep on the codec. When the interrupt get the responses 3259162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 3260162922Sariff * if any. 3261162922Sariff ****************************************************************************/ 3262162922Sariffstatic void 3263162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 3264162922Sariff struct hdac_command_list *commands, nid_t cad) 3265162922Sariff{ 3266162922Sariff struct hdac_codec *codec; 3267162922Sariff int corbrp; 3268162922Sariff uint32_t *corb; 3269162922Sariff int timeout; 3270162922Sariff int retry = 10; 3271164614Sariff struct hdac_rirb *rirb_base; 3272162922Sariff 3273164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 3274164614Sariff commands->num_commands < 1) 3275162922Sariff return; 3276162922Sariff 3277162922Sariff codec = sc->codecs[cad]; 3278162922Sariff codec->commands = commands; 3279162922Sariff codec->responses_received = 0; 3280162922Sariff codec->verbs_sent = 0; 3281162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 3282162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 3283162922Sariff 3284162922Sariff do { 3285162922Sariff if (codec->verbs_sent != commands->num_commands) { 3286162922Sariff /* Queue as many verbs as possible */ 3287162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 3288169277Sariff#if 0 3289162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3290162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 3291169277Sariff#endif 3292162922Sariff while (codec->verbs_sent != commands->num_commands && 3293162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 3294162922Sariff sc->corb_wp++; 3295162922Sariff sc->corb_wp %= sc->corb_size; 3296162922Sariff corb[sc->corb_wp] = 3297162922Sariff commands->verbs[codec->verbs_sent++]; 3298162922Sariff } 3299162922Sariff 3300162922Sariff /* Send the verbs to the codecs */ 3301169277Sariff#if 0 3302162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 3303162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 3304169277Sariff#endif 3305162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 3306162922Sariff } 3307162922Sariff 3308162922Sariff timeout = 1000; 3309164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 3310162922Sariff DELAY(10); 3311162922Sariff } while ((codec->verbs_sent != commands->num_commands || 3312164614Sariff codec->responses_received != commands->num_commands) && --retry); 3313162922Sariff 3314162922Sariff if (retry == 0) 3315162922Sariff device_printf(sc->dev, 3316164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 3317164614Sariff __func__, commands->num_commands, codec->verbs_sent, 3318164614Sariff codec->responses_received); 3319162922Sariff 3320164614Sariff codec->commands = NULL; 3321164614Sariff codec->responses_received = 0; 3322162922Sariff codec->verbs_sent = 0; 3323162922Sariff 3324164614Sariff hdac_unsolq_flush(sc); 3325162922Sariff} 3326162922Sariff 3327162922Sariff 3328162922Sariff/**************************************************************************** 3329162922Sariff * Device Methods 3330162922Sariff ****************************************************************************/ 3331162922Sariff 3332162922Sariff/**************************************************************************** 3333162922Sariff * int hdac_probe(device_t) 3334162922Sariff * 3335162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3336162922Sariff * match using the subclass of the device. 3337162922Sariff ****************************************************************************/ 3338162922Sariffstatic int 3339162922Sariffhdac_probe(device_t dev) 3340162922Sariff{ 3341162922Sariff int i, result; 3342163257Sariff uint32_t model; 3343163257Sariff uint16_t class, subclass; 3344162922Sariff char desc[64]; 3345162922Sariff 3346162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3347162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3348162922Sariff class = pci_get_class(dev); 3349162922Sariff subclass = pci_get_subclass(dev); 3350162922Sariff 3351162922Sariff bzero(desc, sizeof(desc)); 3352162922Sariff result = ENXIO; 3353162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3354162922Sariff if (hdac_devices[i].model == model) { 3355162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3356162922Sariff result = BUS_PROBE_DEFAULT; 3357162922Sariff break; 3358162922Sariff } 3359163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3360162922Sariff class == PCIC_MULTIMEDIA && 3361162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3362162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3363162922Sariff result = BUS_PROBE_GENERIC; 3364162922Sariff break; 3365162922Sariff } 3366162922Sariff } 3367162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3368162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3369162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3370162922Sariff result = BUS_PROBE_GENERIC; 3371162922Sariff } 3372162922Sariff if (result != ENXIO) { 3373162922Sariff strlcat(desc, " High Definition Audio Controller", 3374162922Sariff sizeof(desc)); 3375162922Sariff device_set_desc_copy(dev, desc); 3376162922Sariff } 3377162922Sariff 3378162922Sariff return (result); 3379162922Sariff} 3380162922Sariff 3381162922Sariffstatic void * 3382162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3383162922Sariff struct pcm_channel *c, int dir) 3384162922Sariff{ 3385182999Smav struct hdac_pcm_devinfo *pdevinfo = data; 3386182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3387162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3388162922Sariff struct hdac_chan *ch; 3389182999Smav int i, ord = 0, chid; 3390162922Sariff 3391162922Sariff hdac_lock(sc); 3392182999Smav 3393182999Smav chid = (dir == PCMDIR_PLAY)?pdevinfo->play:pdevinfo->rec; 3394182999Smav ch = &sc->chans[chid]; 3395182999Smav for (i = 0; i < sc->num_chans && i < chid; i++) { 3396182999Smav if (ch->dir == sc->chans[i].dir) 3397182999Smav ord++; 3398182999Smav } 3399162922Sariff if (dir == PCMDIR_PLAY) { 3400182999Smav ch->off = (sc->num_iss + ord) << 5; 3401162922Sariff } else { 3402182999Smav ch->off = ord << 5; 3403162922Sariff } 3404182999Smav 3405162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3406162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3407162922Sariff ch->pcmrates[0] = 48000; 3408162922Sariff ch->pcmrates[1] = 0; 3409162922Sariff } 3410169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3411169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3412169277Sariff (sc->streamcnt * 8)); 3413169277Sariff else 3414169277Sariff ch->dmapos = NULL; 3415169277Sariff ch->sid = ++sc->streamcnt; 3416169277Sariff ch->dir = dir; 3417162922Sariff ch->b = b; 3418162922Sariff ch->c = c; 3419182999Smav ch->blksz = pdevinfo->chan_size / pdevinfo->chan_blkcnt; 3420182999Smav ch->blkcnt = pdevinfo->chan_blkcnt; 3421162922Sariff hdac_unlock(sc); 3422162922Sariff 3423162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3424162922Sariff ch->blkcnt = 0; 3425162922Sariff return (NULL); 3426162922Sariff } 3427162922Sariff 3428169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3429171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3430182999Smav pdevinfo->chan_size) != 0) 3431162922Sariff return (NULL); 3432162922Sariff 3433162922Sariff return (ch); 3434162922Sariff} 3435162922Sariff 3436162922Sariffstatic int 3437162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3438162922Sariff{ 3439162922Sariff struct hdac_chan *ch = data; 3440162922Sariff int i; 3441162922Sariff 3442162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3443162922Sariff if (format == ch->caps.fmtlist[i]) { 3444162922Sariff ch->fmt = format; 3445162922Sariff return (0); 3446162922Sariff } 3447162922Sariff } 3448162922Sariff 3449162922Sariff return (EINVAL); 3450162922Sariff} 3451162922Sariff 3452193640Sariffstatic uint32_t 3453162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3454162922Sariff{ 3455162922Sariff struct hdac_chan *ch = data; 3456164614Sariff uint32_t spd = 0, threshold; 3457162922Sariff int i; 3458162922Sariff 3459162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3460162922Sariff spd = ch->pcmrates[i]; 3461164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3462164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3463164614Sariff if (speed < threshold) 3464162922Sariff break; 3465162922Sariff } 3466162922Sariff 3467164614Sariff if (spd == 0) /* impossible */ 3468162922Sariff ch->spd = 48000; 3469162922Sariff else 3470162922Sariff ch->spd = spd; 3471162922Sariff 3472162922Sariff return (ch->spd); 3473162922Sariff} 3474162922Sariff 3475162922Sariffstatic void 3476162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3477162922Sariff{ 3478162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3479182999Smav struct hdac_audio_as *as = &ch->devinfo->function.audio.as[ch->as]; 3480173817Sariff struct hdac_widget *w; 3481182999Smav int i, chn, totalchn, c; 3482162922Sariff nid_t cad = ch->devinfo->codec->cad; 3483182999Smav uint16_t fmt, dfmt; 3484202127Smav uint16_t chmap[2][5] = {{ 0x0010, 0x0001, 0x0201, 0x0231, 0x0231 }, /* 5.1 */ 3485202127Smav { 0x0010, 0x0001, 0x2001, 0x2031, 0x2431 }};/* 7.1 */ 3486202127Smav int map = -1; 3487162922Sariff 3488202127Smav totalchn = AFMT_CHANNEL(ch->fmt); 3489183097Smav HDA_BOOTHVERBOSE( 3490182999Smav device_printf(ch->pdevinfo->dev, 3491182999Smav "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n", 3492182999Smav (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3493182999Smav ch->fmt, ch->spd); 3494182999Smav ); 3495162922Sariff fmt = 0; 3496162922Sariff if (ch->fmt & AFMT_S16_LE) 3497162922Sariff fmt |= ch->bit16 << 4; 3498162922Sariff else if (ch->fmt & AFMT_S32_LE) 3499162922Sariff fmt |= ch->bit32 << 4; 3500162922Sariff else 3501162922Sariff fmt |= 1 << 4; 3502162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3503162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3504162922Sariff fmt |= hda_rate_tab[i].base; 3505162922Sariff fmt |= hda_rate_tab[i].mul; 3506162922Sariff fmt |= hda_rate_tab[i].div; 3507162922Sariff break; 3508162922Sariff } 3509162922Sariff } 3510202127Smav fmt |= (totalchn - 1); 3511162922Sariff 3512202127Smav /* Set channel mapping for known speaker setups. */ 3513202127Smav if (as->pinset == 0x0007 || as->pinset == 0x0013) /* Standard 5.1 */ 3514202127Smav map = 0; 3515202127Smav else if (as->pinset == 0x0017) /* Standard 7.1 */ 3516202127Smav map = 1; 3517162922Sariff 3518162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3519182999Smav 3520182999Smav dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN; 3521182999Smav if (ch->fmt & AFMT_AC3) 3522182999Smav dfmt |= HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO; 3523162922Sariff 3524173817Sariff chn = 0; 3525162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3526173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3527173817Sariff if (w == NULL) 3528173817Sariff continue; 3529182999Smav 3530202127Smav /* If HP redirection is enabled, but failed to use same 3531202127Smav DAC, make last DAC to duplicate first one. */ 3532204351Smav if (as->fakeredir && i == (as->pincnt - 1)) { 3533202127Smav c = (ch->sid << 4); 3534202127Smav } else { 3535202127Smav if (map >= 0) /* Map known speaker setups. */ 3536202127Smav chn = (((chmap[map][totalchn / 2] >> i * 4) & 3537202127Smav 0xf) - 1) * 2; 3538202127Smav if (chn < 0 || chn >= totalchn) { 3539202127Smav c = 0; 3540202127Smav } else { 3541202127Smav c = (ch->sid << 4) | chn; 3542202127Smav } 3543202127Smav } 3544183097Smav HDA_BOOTHVERBOSE( 3545182999Smav device_printf(ch->pdevinfo->dev, 3546182999Smav "PCMDIR_%s: Stream setup nid=%d: " 3547202127Smav "fmt=0x%04x, dfmt=0x%04x, chan=0x%04x\n", 3548162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3549202127Smav ch->io[i], fmt, dfmt, c); 3550162922Sariff ); 3551162922Sariff hdac_command(sc, 3552162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3553182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3554174025Sariff hdac_command(sc, 3555182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], dfmt), 3556174025Sariff cad); 3557182999Smav } 3558182999Smav hdac_command(sc, 3559182999Smav HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], c), cad); 3560197611Smav#if 0 3561197611Smav hdac_command(sc, 3562197611Smav HDA_CMD_SET_CONV_CHAN_COUNT(cad, ch->io[i], 1), cad); 3563197611Smav hdac_command(sc, 3564197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x00), cad); 3565197611Smav hdac_command(sc, 3566197611Smav HDA_CMD_SET_HDMI_CHAN_SLOT(cad, ch->io[i], 0x11), cad); 3567197611Smav#endif 3568202127Smav chn += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 3569162922Sariff } 3570162922Sariff} 3571162922Sariff 3572202156Smav/* 3573202156Smav * Greatest Common Divisor. 3574202156Smav */ 3575202156Smavstatic unsigned 3576202156Smavgcd(unsigned a, unsigned b) 3577202156Smav{ 3578202156Smav u_int c; 3579202156Smav 3580202156Smav while (b != 0) { 3581202156Smav c = a; 3582202156Smav a = b; 3583202156Smav b = (c % b); 3584202156Smav } 3585202156Smav return (a); 3586202156Smav} 3587202156Smav 3588202156Smav/* 3589202156Smav * Least Common Multiple. 3590202156Smav */ 3591202156Smavstatic unsigned 3592202156Smavlcm(unsigned a, unsigned b) 3593202156Smav{ 3594202156Smav 3595202156Smav return ((a * b) / gcd(a, b)); 3596202156Smav} 3597202156Smav 3598162922Sariffstatic int 3599167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3600167648Sariff uint32_t blksz, uint32_t blkcnt) 3601162922Sariff{ 3602162922Sariff struct hdac_chan *ch = data; 3603164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3604162922Sariff 3605202156Smav blksz -= blksz % lcm(HDAC_DMA_ALIGNMENT, sndbuf_getalign(ch->b)); 3606162922Sariff 3607167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3608167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3609167648Sariff if (blksz < HDA_BLK_MIN) 3610167648Sariff blksz = HDA_BLK_MIN; 3611167648Sariff if (blkcnt > HDA_BDL_MAX) 3612167648Sariff blkcnt = HDA_BDL_MAX; 3613167648Sariff if (blkcnt < HDA_BDL_MIN) 3614167648Sariff blkcnt = HDA_BDL_MIN; 3615164614Sariff 3616167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3617167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3618167648Sariff blkcnt >>= 1; 3619167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3620167648Sariff blksz >>= 1; 3621167648Sariff else 3622167648Sariff break; 3623167648Sariff } 3624167648Sariff 3625164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3626167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3627167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3628164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3629167648Sariff __func__, blksz, blkcnt); 3630164614Sariff 3631164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3632167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3633164614Sariff 3634193640Sariff return (0); 3635167648Sariff} 3636167648Sariff 3637193640Sariffstatic uint32_t 3638167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3639167648Sariff{ 3640167648Sariff struct hdac_chan *ch = data; 3641167648Sariff 3642182999Smav hdac_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt); 3643167648Sariff 3644162922Sariff return (ch->blksz); 3645162922Sariff} 3646162922Sariff 3647162922Sariffstatic void 3648162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3649162922Sariff{ 3650162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3651182999Smav struct hdac_widget *w; 3652162922Sariff nid_t cad = devinfo->codec->cad; 3653162922Sariff int i; 3654162922Sariff 3655162922Sariff hdac_stream_stop(ch); 3656162922Sariff 3657162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3658182999Smav w = hdac_widget_get(ch->devinfo, ch->io[i]); 3659182999Smav if (w == NULL) 3660182999Smav continue; 3661182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 3662182999Smav hdac_command(sc, 3663182999Smav HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, ch->io[i], 0), 3664182999Smav cad); 3665182999Smav } 3666162922Sariff hdac_command(sc, 3667162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3668162922Sariff 0), cad); 3669162922Sariff } 3670162922Sariff} 3671162922Sariff 3672162922Sariffstatic void 3673162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3674162922Sariff{ 3675162922Sariff ch->ptr = 0; 3676162922Sariff ch->prevptr = 0; 3677162922Sariff hdac_stream_stop(ch); 3678162922Sariff hdac_stream_reset(ch); 3679162922Sariff hdac_bdl_setup(ch); 3680162922Sariff hdac_stream_setid(ch); 3681162922Sariff hdac_stream_setup(ch); 3682162922Sariff hdac_stream_start(ch); 3683162922Sariff} 3684162922Sariff 3685162922Sariffstatic int 3686162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3687162922Sariff{ 3688162922Sariff struct hdac_chan *ch = data; 3689162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3690162922Sariff 3691170521Sariff if (!PCMTRIG_COMMON(go)) 3692170521Sariff return (0); 3693170521Sariff 3694162922Sariff hdac_lock(sc); 3695162922Sariff switch (go) { 3696162922Sariff case PCMTRIG_START: 3697162922Sariff hdac_channel_start(sc, ch); 3698162922Sariff break; 3699162922Sariff case PCMTRIG_STOP: 3700162922Sariff case PCMTRIG_ABORT: 3701162922Sariff hdac_channel_stop(sc, ch); 3702162922Sariff break; 3703167610Sariff default: 3704167610Sariff break; 3705162922Sariff } 3706162922Sariff hdac_unlock(sc); 3707162922Sariff 3708162922Sariff return (0); 3709162922Sariff} 3710162922Sariff 3711193640Sariffstatic uint32_t 3712162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3713162922Sariff{ 3714162922Sariff struct hdac_chan *ch = data; 3715162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3716162922Sariff uint32_t ptr; 3717162922Sariff 3718162922Sariff hdac_lock(sc); 3719164614Sariff if (sc->polling != 0) 3720164614Sariff ptr = ch->ptr; 3721169277Sariff else if (ch->dmapos != NULL) 3722169277Sariff ptr = *(ch->dmapos); 3723164614Sariff else 3724164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3725162922Sariff hdac_unlock(sc); 3726162922Sariff 3727164614Sariff /* 3728164614Sariff * Round to available space and force 128 bytes aligment. 3729164614Sariff */ 3730164614Sariff ptr %= ch->blksz * ch->blkcnt; 3731167648Sariff ptr &= HDA_BLK_ALIGN; 3732162922Sariff 3733162922Sariff return (ptr); 3734162922Sariff} 3735162922Sariff 3736162922Sariffstatic struct pcmchan_caps * 3737162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3738162922Sariff{ 3739162922Sariff return (&((struct hdac_chan *)data)->caps); 3740162922Sariff} 3741162922Sariff 3742162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3743162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3744162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3745162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3746162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3747167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3748162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3749162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3750162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3751193640Sariff KOBJMETHOD_END 3752162922Sariff}; 3753162922SariffCHANNEL_DECLARE(hdac_channel); 3754162922Sariff 3755162922Sariffstatic int 3756162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3757162922Sariff{ 3758182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3759182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3760162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3761162922Sariff struct hdac_widget *w, *cw; 3762162922Sariff struct hdac_audio_ctl *ctl; 3763162922Sariff uint32_t mask, recmask, id; 3764162922Sariff int i, j, softpcmvol; 3765162922Sariff 3766162922Sariff hdac_lock(sc); 3767162922Sariff 3768182999Smav /* Make sure that in case of soft volume it won't stay muted. */ 3769182999Smav for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3770182999Smav pdevinfo->left[i] = 100; 3771182999Smav pdevinfo->right[i] = 100; 3772182999Smav } 3773182999Smav 3774162922Sariff mask = 0; 3775162922Sariff recmask = 0; 3776182999Smav id = hdac_codec_id(devinfo->codec); 3777162922Sariff 3778182999Smav /* Declate EAPD as ogain control. */ 3779182999Smav if (pdevinfo->play >= 0) { 3780182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3781182999Smav w = hdac_widget_get(devinfo, i); 3782182999Smav if (w == NULL || w->enable == 0) 3783182999Smav continue; 3784182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3785182999Smav w->param.eapdbtl == HDAC_INVALID || 3786182999Smav w->bindas != sc->chans[pdevinfo->play].as) 3787182999Smav continue; 3788182999Smav mask |= SOUND_MASK_OGAIN; 3789162922Sariff break; 3790162922Sariff } 3791162922Sariff } 3792162922Sariff 3793182999Smav /* Declare volume controls assigned to this association. */ 3794162922Sariff i = 0; 3795162922Sariff ctl = NULL; 3796162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3797182999Smav if (ctl->enable == 0) 3798162922Sariff continue; 3799182999Smav if ((pdevinfo->play >= 0 && 3800182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3801182999Smav (pdevinfo->rec >= 0 && 3802182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3803182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0)) 3804182999Smav mask |= ctl->ossmask; 3805162922Sariff } 3806162922Sariff 3807182999Smav /* Declare record sources available to this association. */ 3808182999Smav if (pdevinfo->rec >= 0) { 3809182999Smav struct hdac_chan *ch = &sc->chans[pdevinfo->rec]; 3810182999Smav for (i = 0; ch->io[i] != -1; i++) { 3811182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 3812182999Smav if (w == NULL || w->enable == 0) 3813182999Smav continue; 3814182999Smav for (j = 0; j < w->nconns; j++) { 3815182999Smav if (w->connsenable[j] == 0) 3816162922Sariff continue; 3817182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 3818182999Smav if (cw == NULL || cw->enable == 0) 3819165992Sariff continue; 3820182999Smav if (cw->bindas != sc->chans[pdevinfo->rec].as && 3821182999Smav cw->bindas != -2) 3822165992Sariff continue; 3823182999Smav recmask |= cw->ossmask; 3824165992Sariff } 3825182999Smav } 3826182999Smav } 3827182999Smav 3828185230Smav /* Declare soft PCM volume if needed. */ 3829193640Sariff if (pdevinfo->play >= 0) { 3830182999Smav ctl = NULL; 3831182999Smav if ((mask & SOUND_MASK_PCM) == 0 || 3832182999Smav (devinfo->function.audio.quirks & HDA_QUIRK_SOFTPCMVOL)) { 3833182999Smav softpcmvol = 1; 3834182999Smav mask |= SOUND_MASK_PCM; 3835162922Sariff } else { 3836182999Smav softpcmvol = 0; 3837182999Smav i = 0; 3838182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3839182999Smav if (ctl->enable == 0) 3840162922Sariff continue; 3841182999Smav if (ctl->widget->bindas != sc->chans[pdevinfo->play].as && 3842182999Smav (ctl->widget->bindas != -2 || pdevinfo->index != 0)) 3843162922Sariff continue; 3844182999Smav if (!(ctl->ossmask & SOUND_MASK_PCM)) 3845182999Smav continue; 3846182999Smav if (ctl->step > 0) 3847182999Smav break; 3848162922Sariff } 3849162922Sariff } 3850182999Smav 3851182999Smav if (softpcmvol == 1 || ctl == NULL) { 3852182999Smav pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL); 3853182999Smav HDA_BOOTVERBOSE( 3854182999Smav device_printf(pdevinfo->dev, 3855182999Smav "%s Soft PCM volume\n", 3856182999Smav (softpcmvol == 1) ? "Forcing" : "Enabling"); 3857182999Smav ); 3858182999Smav } 3859185230Smav } 3860182999Smav 3861185230Smav /* Declare master volume if needed. */ 3862185230Smav if (pdevinfo->play >= 0) { 3863185230Smav if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) == 3864185230Smav SOUND_MASK_PCM) { 3865182999Smav mask |= SOUND_MASK_VOLUME; 3866182999Smav mix_setparentchild(m, SOUND_MIXER_VOLUME, 3867182999Smav SOUND_MASK_PCM); 3868182999Smav mix_setrealdev(m, SOUND_MIXER_VOLUME, 3869182999Smav SOUND_MIXER_NONE); 3870182999Smav HDA_BOOTVERBOSE( 3871182999Smav device_printf(pdevinfo->dev, 3872182999Smav "Forcing master volume with PCM\n"); 3873182999Smav ); 3874182999Smav } 3875162922Sariff } 3876162922Sariff 3877169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3878169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3879162922Sariff 3880162922Sariff mix_setrecdevs(m, recmask); 3881162922Sariff mix_setdevs(m, mask); 3882162922Sariff 3883162922Sariff hdac_unlock(sc); 3884162922Sariff 3885162922Sariff return (0); 3886162922Sariff} 3887162922Sariff 3888162922Sariffstatic int 3889162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3890162922Sariff unsigned left, unsigned right) 3891162922Sariff{ 3892182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 3893182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3894162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3895162922Sariff struct hdac_widget *w; 3896162922Sariff struct hdac_audio_ctl *ctl; 3897182999Smav uint32_t mute; 3898182999Smav int lvol, rvol; 3899182999Smav int i, j; 3900162922Sariff 3901162922Sariff hdac_lock(sc); 3902182999Smav /* Save new values. */ 3903182999Smav pdevinfo->left[dev] = left; 3904182999Smav pdevinfo->right[dev] = right; 3905182999Smav 3906182999Smav /* 'ogain' is the special case implemented with EAPD. */ 3907162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3908163257Sariff uint32_t orig; 3909182999Smav w = NULL; 3910182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3911182999Smav w = hdac_widget_get(devinfo, i); 3912182999Smav if (w == NULL || w->enable == 0) 3913182999Smav continue; 3914182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3915182999Smav w->param.eapdbtl == HDAC_INVALID) 3916182999Smav continue; 3917182999Smav break; 3918162922Sariff } 3919182999Smav if (i >= devinfo->endnode) { 3920162922Sariff hdac_unlock(sc); 3921162922Sariff return (-1); 3922162922Sariff } 3923163257Sariff orig = w->param.eapdbtl; 3924163432Sariff if (left == 0) 3925162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3926162922Sariff else 3927162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3928163257Sariff if (orig != w->param.eapdbtl) { 3929163432Sariff uint32_t val; 3930163432Sariff 3931163432Sariff val = w->param.eapdbtl; 3932163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3933163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3934163257Sariff hdac_command(sc, 3935163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3936163432Sariff w->nid, val), devinfo->codec->cad); 3937163257Sariff } 3938162922Sariff hdac_unlock(sc); 3939162922Sariff return (left | (left << 8)); 3940162922Sariff } 3941162922Sariff 3942182999Smav /* Recalculate all controls related to this OSS device. */ 3943162922Sariff i = 0; 3944162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3945182999Smav if (ctl->enable == 0 || 3946162922Sariff !(ctl->ossmask & (1 << dev))) 3947162922Sariff continue; 3948182999Smav if (!((pdevinfo->play >= 0 && 3949182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 3950182999Smav (pdevinfo->rec >= 0 && 3951182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 3952182999Smav ctl->widget->bindas == -2)) 3953182999Smav continue; 3954182999Smav 3955182999Smav lvol = 100; 3956182999Smav rvol = 100; 3957182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 3958182999Smav if (ctl->ossmask & (1 << j)) { 3959182999Smav lvol = lvol * pdevinfo->left[j] / 100; 3960182999Smav rvol = rvol * pdevinfo->right[j] / 100; 3961162922Sariff } 3962162922Sariff } 3963202789Smav mute = (lvol == 0) ? HDA_AMP_MUTE_LEFT : 0; 3964202789Smav mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 0; 3965182999Smav lvol = (lvol * ctl->step + 50) / 100; 3966182999Smav rvol = (rvol * ctl->step + 50) / 100; 3967162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3968162922Sariff } 3969162922Sariff hdac_unlock(sc); 3970162922Sariff 3971162922Sariff return (left | (right << 8)); 3972162922Sariff} 3973162922Sariff 3974182999Smav/* 3975182999Smav * Commutate specified record source. 3976182999Smav */ 3977182999Smavstatic uint32_t 3978182999Smavhdac_audio_ctl_recsel_comm(struct hdac_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth) 3979162922Sariff{ 3980182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 3981162922Sariff struct hdac_widget *w, *cw; 3982182999Smav struct hdac_audio_ctl *ctl; 3983182999Smav char buf[64]; 3984182999Smav int i, muted; 3985182999Smav uint32_t res = 0; 3986162922Sariff 3987182999Smav if (depth > HDA_PARSE_MAXDEPTH) 3988182999Smav return (0); 3989182999Smav 3990182999Smav w = hdac_widget_get(devinfo, nid); 3991182999Smav if (w == NULL || w->enable == 0) 3992182999Smav return (0); 3993182999Smav 3994182999Smav for (i = 0; i < w->nconns; i++) { 3995182999Smav if (w->connsenable[i] == 0) 3996182999Smav continue; 3997182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 3998182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 3999182999Smav continue; 4000182999Smav /* Call recursively to trace signal to it's source if needed. */ 4001182999Smav if ((src & cw->ossmask) != 0) { 4002182999Smav if (cw->ossdev < 0) { 4003182999Smav res |= hdac_audio_ctl_recsel_comm(pdevinfo, src, 4004182999Smav w->conns[i], depth + 1); 4005182999Smav } else { 4006182999Smav res |= cw->ossmask; 4007182999Smav } 4008182999Smav } 4009182999Smav /* We have two special cases: mixers and others (selectors). */ 4010182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 4011182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, 4012182999Smav w->nid, HDA_CTL_IN, i, 1); 4013182999Smav if (ctl == NULL) 4014182999Smav continue; 4015182999Smav /* If we have input control on this node mute them 4016182999Smav * according to requested sources. */ 4017182999Smav muted = (src & cw->ossmask) ? 0 : 1; 4018182999Smav if (muted != ctl->forcemute) { 4019182999Smav ctl->forcemute = muted; 4020182999Smav hdac_audio_ctl_amp_set(ctl, 4021182999Smav HDA_AMP_MUTE_DEFAULT, 4022182999Smav HDA_AMP_VOL_DEFAULT, HDA_AMP_VOL_DEFAULT); 4023182999Smav } 4024183097Smav HDA_BOOTHVERBOSE( 4025182999Smav device_printf(pdevinfo->dev, 4026182999Smav "Recsel (%s): nid %d source %d %s\n", 4027182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4028182999Smav src, buf, sizeof(buf)), 4029182999Smav nid, i, muted?"mute":"unmute"); 4030182999Smav ); 4031182999Smav } else { 4032182999Smav if (w->nconns == 1) 4033182999Smav break; 4034182999Smav if ((src & cw->ossmask) == 0) 4035182999Smav continue; 4036182999Smav /* If we found requested source - select it and exit. */ 4037182999Smav hdac_widget_connection_select(w, i); 4038183097Smav HDA_BOOTHVERBOSE( 4039182999Smav device_printf(pdevinfo->dev, 4040182999Smav "Recsel (%s): nid %d source %d select\n", 4041182999Smav hdac_audio_ctl_ossmixer_mask2allname( 4042182999Smav src, buf, sizeof(buf)), 4043182999Smav nid, i); 4044182999Smav ); 4045162922Sariff break; 4046162922Sariff } 4047162922Sariff } 4048182999Smav return (res); 4049182999Smav} 4050162922Sariff 4051182999Smavstatic uint32_t 4052182999Smavhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 4053182999Smav{ 4054182999Smav struct hdac_pcm_devinfo *pdevinfo = mix_getdevinfo(m); 4055182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 4056182999Smav struct hdac_widget *w; 4057182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4058182999Smav struct hdac_chan *ch; 4059182999Smav int i; 4060182999Smav uint32_t ret = 0xffffffff; 4061182999Smav 4062162922Sariff hdac_lock(sc); 4063162922Sariff 4064182999Smav /* Commutate requested recsrc for each ADC. */ 4065182999Smav ch = &sc->chans[pdevinfo->rec]; 4066182999Smav for (i = 0; ch->io[i] != -1; i++) { 4067182999Smav w = hdac_widget_get(devinfo, ch->io[i]); 4068162965Sariff if (w == NULL || w->enable == 0) 4069162922Sariff continue; 4070182999Smav ret &= hdac_audio_ctl_recsel_comm(pdevinfo, src, ch->io[i], 0); 4071162922Sariff } 4072162922Sariff 4073162922Sariff hdac_unlock(sc); 4074162922Sariff 4075182999Smav return ((ret == 0xffffffff)? 0 : ret); 4076162922Sariff} 4077162922Sariff 4078162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 4079162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 4080162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 4081162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 4082193640Sariff KOBJMETHOD_END 4083162922Sariff}; 4084162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 4085162922Sariff 4086171141Sariffstatic void 4087171141Sariffhdac_unsolq_task(void *context, int pending) 4088171141Sariff{ 4089171141Sariff struct hdac_softc *sc; 4090171141Sariff 4091171141Sariff sc = (struct hdac_softc *)context; 4092171141Sariff 4093171141Sariff hdac_lock(sc); 4094171141Sariff hdac_unsolq_flush(sc); 4095171141Sariff hdac_unlock(sc); 4096171141Sariff} 4097171141Sariff 4098162922Sariff/**************************************************************************** 4099162922Sariff * int hdac_attach(device_t) 4100162922Sariff * 4101162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 4102162922Sariff * when this function is called. Setup everything that doesn't require 4103162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 4104162922Sariff ****************************************************************************/ 4105162922Sariffstatic int 4106162922Sariffhdac_attach(device_t dev) 4107162922Sariff{ 4108162922Sariff struct hdac_softc *sc; 4109162922Sariff int result; 4110189086Smav int i, devid = -1; 4111189086Smav uint32_t model; 4112189086Smav uint16_t class, subclass; 4113169277Sariff uint16_t vendor; 4114169277Sariff uint8_t v; 4115162922Sariff 4116184089Smav device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV); 4117182999Smav 4118189086Smav model = (uint32_t)pci_get_device(dev) << 16; 4119189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 4120189086Smav class = pci_get_class(dev); 4121189086Smav subclass = pci_get_subclass(dev); 4122189086Smav 4123189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 4124189086Smav if (hdac_devices[i].model == model) { 4125189086Smav devid = i; 4126189086Smav break; 4127189086Smav } 4128189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 4129189086Smav class == PCIC_MULTIMEDIA && 4130189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 4131189086Smav devid = i; 4132189086Smav break; 4133189086Smav } 4134189086Smav } 4135189086Smav 4136182999Smav sc = device_get_softc(dev); 4137163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 4138162922Sariff sc->dev = dev; 4139163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 4140163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 4141169277Sariff vendor = pci_get_vendor(dev); 4142162922Sariff 4143165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 4144165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 4145165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 4146165281Sariff } 4147165281Sariff 4148164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 4149164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 4150169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 4151164614Sariff 4152171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 4153171141Sariff 4154182999Smav sc->poll_ticks = 1000000; 4155169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 4156169277Sariff if (resource_int_value(device_get_name(dev), 4157169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 4158164614Sariff sc->polling = 1; 4159164614Sariff else 4160164614Sariff sc->polling = 0; 4161164614Sariff 4162162922Sariff sc->hdabus = NULL; 4163162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 4164162922Sariff sc->codecs[i] = NULL; 4165162922Sariff 4166162922Sariff pci_enable_busmaster(dev); 4167162922Sariff 4168169277Sariff if (vendor == INTEL_VENDORID) { 4169169277Sariff /* TCSEL -> TC0 */ 4170169277Sariff v = pci_read_config(dev, 0x44, 1); 4171169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 4172183097Smav HDA_BOOTHVERBOSE( 4173169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 4174169277Sariff pci_read_config(dev, 0x44, 1)); 4175169277Sariff ); 4176169277Sariff } 4177169277Sariff 4178189127Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_MSI)) 4179188656Smav sc->flags &= ~HDAC_F_MSI; 4180188656Smav else 4181171330Sariff sc->flags |= HDAC_F_MSI; 4182189086Smav if (resource_int_value(device_get_name(dev), 4183189086Smav device_get_unit(dev), "msi", &i) == 0) { 4184189086Smav if (i == 0) 4185189086Smav sc->flags &= ~HDAC_F_MSI; 4186189086Smav else 4187189086Smav sc->flags |= HDAC_F_MSI; 4188189086Smav } 4189171330Sariff 4190169277Sariff#if defined(__i386__) || defined(__amd64__) 4191171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4192169277Sariff 4193169277Sariff if (resource_int_value(device_get_name(dev), 4194169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 4195169277Sariff#else 4196171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4197169277Sariff#endif 4198169277Sariff /* 4199169277Sariff * Try to enable PCIe snoop to avoid messing around with 4200169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 4201169277Sariff * config is pretty much vendor specific, there are no 4202169277Sariff * general solutions on how to enable it, forcing us (even 4203169277Sariff * Microsoft) to enable uncacheable or write combined DMA 4204169277Sariff * by default. 4205169277Sariff * 4206169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 4207169277Sariff */ 4208169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 4209169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 4210169277Sariff continue; 4211171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 4212169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 4213169277Sariff break; 4214169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4215169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 4216169277Sariff hdac_pcie_snoop[i].enable) 4217169277Sariff break; 4218169277Sariff v &= hdac_pcie_snoop[i].mask; 4219169277Sariff v |= hdac_pcie_snoop[i].enable; 4220169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 4221169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 4222169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 4223169277Sariff hdac_pcie_snoop[i].enable) { 4224169277Sariff HDA_BOOTVERBOSE( 4225169277Sariff device_printf(dev, 4226169277Sariff "WARNING: Failed to enable PCIe " 4227169277Sariff "snoop!\n"); 4228169277Sariff ); 4229169277Sariff#if defined(__i386__) || defined(__amd64__) 4230171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 4231169277Sariff#endif 4232169277Sariff } 4233169277Sariff break; 4234169277Sariff } 4235169277Sariff#if defined(__i386__) || defined(__amd64__) 4236169277Sariff } 4237169277Sariff#endif 4238169277Sariff 4239183097Smav HDA_BOOTHVERBOSE( 4240169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 4241171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 4242171330Sariff "Uncacheable" : "PCIe snoop", vendor); 4243169277Sariff ); 4244169277Sariff 4245162922Sariff /* Allocate resources */ 4246162922Sariff result = hdac_mem_alloc(sc); 4247162922Sariff if (result != 0) 4248163057Sariff goto hdac_attach_fail; 4249162922Sariff result = hdac_irq_alloc(sc); 4250162922Sariff if (result != 0) 4251163057Sariff goto hdac_attach_fail; 4252162922Sariff 4253162922Sariff /* Get Capabilities */ 4254162922Sariff result = hdac_get_capabilities(sc); 4255162922Sariff if (result != 0) 4256163057Sariff goto hdac_attach_fail; 4257162922Sariff 4258194861Smav if (devid >= 0 && (hdac_devices[devid].flags & HDAC_NO_64BIT)) 4259194861Smav sc->support_64bit = 0; 4260194861Smav 4261162922Sariff /* Allocate CORB and RIRB dma memory */ 4262162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 4263162922Sariff sc->corb_size * sizeof(uint32_t)); 4264162922Sariff if (result != 0) 4265163057Sariff goto hdac_attach_fail; 4266162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 4267162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 4268162922Sariff if (result != 0) 4269163057Sariff goto hdac_attach_fail; 4270162922Sariff 4271194861Smav result = bus_dma_tag_create( 4272194861Smav bus_get_dma_tag(sc->dev), /* parent */ 4273194861Smav HDAC_DMA_ALIGNMENT, /* alignment */ 4274194861Smav 0, /* boundary */ 4275194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 4276194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 4277194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 4278194861Smav NULL, /* filtfunc */ 4279194861Smav NULL, /* fistfuncarg */ 4280194861Smav HDA_BUFSZ_MAX, /* maxsize */ 4281194861Smav 1, /* nsegments */ 4282194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 4283194861Smav 0, /* flags */ 4284194861Smav NULL, /* lockfunc */ 4285194861Smav NULL, /* lockfuncarg */ 4286194861Smav &sc->chan_dmat); /* dmat */ 4287194861Smav if (result != 0) { 4288194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 4289194861Smav __func__, result); 4290194861Smav goto hdac_attach_fail; 4291194861Smav } 4292194861Smav 4293162922Sariff /* Quiesce everything */ 4294183097Smav HDA_BOOTHVERBOSE( 4295182999Smav device_printf(dev, "Reset controller...\n"); 4296182999Smav ); 4297182999Smav hdac_reset(sc, 1); 4298162922Sariff 4299162922Sariff /* Initialize the CORB and RIRB */ 4300162922Sariff hdac_corb_init(sc); 4301162922Sariff hdac_rirb_init(sc); 4302162922Sariff 4303162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 4304162922Sariff sc->intrhook.ich_func = hdac_attach2; 4305162922Sariff sc->intrhook.ich_arg = (void *)sc; 4306162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 4307162922Sariff sc->intrhook.ich_func = NULL; 4308162922Sariff hdac_attach2((void *)sc); 4309162922Sariff } 4310162922Sariff 4311163057Sariff return (0); 4312162922Sariff 4313163057Sariffhdac_attach_fail: 4314162922Sariff hdac_irq_free(sc); 4315169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 4316169277Sariff hdac_dma_free(sc, &sc->corb_dma); 4317162922Sariff hdac_mem_free(sc); 4318162922Sariff snd_mtxfree(sc->lock); 4319162922Sariff 4320163057Sariff return (ENXIO); 4321162922Sariff} 4322162922Sariff 4323162922Sariffstatic void 4324162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 4325162922Sariff{ 4326182999Smav struct hdac_codec *codec = devinfo->codec; 4327182999Smav struct hdac_softc *sc = codec->sc; 4328162922Sariff struct hdac_widget *w; 4329162922Sariff uint32_t res; 4330162922Sariff int i; 4331162922Sariff nid_t cad, nid; 4332162922Sariff 4333162922Sariff cad = devinfo->codec->cad; 4334162922Sariff nid = devinfo->nid; 4335162922Sariff 4336162922Sariff res = hdac_command(sc, 4337169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 4338169277Sariff devinfo->function.audio.gpio = res; 4339169277Sariff 4340163057Sariff HDA_BOOTVERBOSE( 4341183097Smav device_printf(sc->dev, "GPIO: 0x%08x " 4342183097Smav "NumGPIO=%d NumGPO=%d " 4343169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4344183097Smav devinfo->function.audio.gpio, 4345169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4346169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4347169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4348169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4349169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4350162922Sariff ); 4351162922Sariff 4352162922Sariff res = hdac_command(sc, 4353162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4354162922Sariff cad); 4355162922Sariff devinfo->function.audio.supp_stream_formats = res; 4356162922Sariff 4357162922Sariff res = hdac_command(sc, 4358162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4359162922Sariff cad); 4360162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4361162922Sariff 4362162922Sariff res = hdac_command(sc, 4363162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4364162922Sariff cad); 4365162922Sariff devinfo->function.audio.outamp_cap = res; 4366162922Sariff 4367162922Sariff res = hdac_command(sc, 4368162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4369162922Sariff cad); 4370162922Sariff devinfo->function.audio.inamp_cap = res; 4371162922Sariff 4372162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4373162922Sariff w = hdac_widget_get(devinfo, i); 4374162922Sariff if (w == NULL) 4375162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4376162922Sariff else { 4377162922Sariff w->devinfo = devinfo; 4378162922Sariff w->nid = i; 4379162922Sariff w->enable = 1; 4380162922Sariff w->selconn = -1; 4381162922Sariff w->pflags = 0; 4382182999Smav w->ossdev = -1; 4383182999Smav w->bindas = -1; 4384162965Sariff w->param.eapdbtl = HDAC_INVALID; 4385162922Sariff hdac_widget_parse(w); 4386162922Sariff } 4387162922Sariff } 4388162922Sariff} 4389162922Sariff 4390162922Sariffstatic void 4391162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4392162922Sariff{ 4393162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4394162922Sariff struct hdac_audio_ctl *ctls; 4395162922Sariff struct hdac_widget *w, *cw; 4396162922Sariff int i, j, cnt, max, ocap, icap; 4397163057Sariff int mute, offset, step, size; 4398162922Sariff 4399162922Sariff /* XXX This is redundant */ 4400162922Sariff max = 0; 4401162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4402162922Sariff w = hdac_widget_get(devinfo, i); 4403162922Sariff if (w == NULL || w->enable == 0) 4404162922Sariff continue; 4405162922Sariff if (w->param.outamp_cap != 0) 4406162922Sariff max++; 4407162922Sariff if (w->param.inamp_cap != 0) { 4408162922Sariff switch (w->type) { 4409162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4410162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4411162922Sariff for (j = 0; j < w->nconns; j++) { 4412162922Sariff cw = hdac_widget_get(devinfo, 4413162922Sariff w->conns[j]); 4414162922Sariff if (cw == NULL || cw->enable == 0) 4415162922Sariff continue; 4416162922Sariff max++; 4417162922Sariff } 4418162922Sariff break; 4419162922Sariff default: 4420162922Sariff max++; 4421162922Sariff break; 4422162922Sariff } 4423162922Sariff } 4424162922Sariff } 4425162922Sariff 4426162922Sariff devinfo->function.audio.ctlcnt = max; 4427162922Sariff 4428162922Sariff if (max < 1) 4429162922Sariff return; 4430162922Sariff 4431162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4432162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4433162922Sariff 4434162922Sariff if (ctls == NULL) { 4435162922Sariff /* Blekh! */ 4436162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4437162922Sariff devinfo->function.audio.ctlcnt = 0; 4438162922Sariff return; 4439162922Sariff } 4440162922Sariff 4441162922Sariff cnt = 0; 4442162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4443162922Sariff if (cnt >= max) { 4444162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4445162922Sariff __func__); 4446162922Sariff break; 4447162922Sariff } 4448162922Sariff w = hdac_widget_get(devinfo, i); 4449162922Sariff if (w == NULL || w->enable == 0) 4450162922Sariff continue; 4451162922Sariff ocap = w->param.outamp_cap; 4452162922Sariff icap = w->param.inamp_cap; 4453162922Sariff if (ocap != 0) { 4454163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4455163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4456163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4457163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4458163057Sariff /*if (offset > step) { 4459163057Sariff HDA_BOOTVERBOSE( 4460163057Sariff device_printf(sc->dev, 4461182999Smav "BUGGY outamp: nid=%d " 4462163057Sariff "[offset=%d > step=%d]\n", 4463163057Sariff w->nid, offset, step); 4464163057Sariff ); 4465163057Sariff offset = step; 4466163057Sariff }*/ 4467162922Sariff ctls[cnt].enable = 1; 4468162922Sariff ctls[cnt].widget = w; 4469163057Sariff ctls[cnt].mute = mute; 4470163057Sariff ctls[cnt].step = step; 4471163057Sariff ctls[cnt].size = size; 4472163057Sariff ctls[cnt].offset = offset; 4473163057Sariff ctls[cnt].left = offset; 4474163057Sariff ctls[cnt].right = offset; 4475182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4476182999Smav w->waspin) 4477182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4478182999Smav else 4479182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4480162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4481162922Sariff } 4482162922Sariff 4483162922Sariff if (icap != 0) { 4484163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4485163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4486163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4487163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4488163057Sariff /*if (offset > step) { 4489163057Sariff HDA_BOOTVERBOSE( 4490163057Sariff device_printf(sc->dev, 4491182999Smav "BUGGY inamp: nid=%d " 4492163057Sariff "[offset=%d > step=%d]\n", 4493163057Sariff w->nid, offset, step); 4494163057Sariff ); 4495163057Sariff offset = step; 4496163057Sariff }*/ 4497162922Sariff switch (w->type) { 4498162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4499162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4500162922Sariff for (j = 0; j < w->nconns; j++) { 4501162922Sariff if (cnt >= max) { 4502162922Sariff device_printf(sc->dev, 4503162922Sariff "%s: Ctl overflow!\n", 4504162922Sariff __func__); 4505162922Sariff break; 4506162922Sariff } 4507162922Sariff cw = hdac_widget_get(devinfo, 4508162922Sariff w->conns[j]); 4509162922Sariff if (cw == NULL || cw->enable == 0) 4510162922Sariff continue; 4511162922Sariff ctls[cnt].enable = 1; 4512162922Sariff ctls[cnt].widget = w; 4513162922Sariff ctls[cnt].childwidget = cw; 4514162922Sariff ctls[cnt].index = j; 4515163057Sariff ctls[cnt].mute = mute; 4516163057Sariff ctls[cnt].step = step; 4517163057Sariff ctls[cnt].size = size; 4518163057Sariff ctls[cnt].offset = offset; 4519163057Sariff ctls[cnt].left = offset; 4520163057Sariff ctls[cnt].right = offset; 4521182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4522162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4523162922Sariff } 4524162922Sariff break; 4525162922Sariff default: 4526162922Sariff if (cnt >= max) { 4527162922Sariff device_printf(sc->dev, 4528162922Sariff "%s: Ctl overflow!\n", 4529162922Sariff __func__); 4530162922Sariff break; 4531162922Sariff } 4532162922Sariff ctls[cnt].enable = 1; 4533162922Sariff ctls[cnt].widget = w; 4534163057Sariff ctls[cnt].mute = mute; 4535163057Sariff ctls[cnt].step = step; 4536163057Sariff ctls[cnt].size = size; 4537163057Sariff ctls[cnt].offset = offset; 4538163057Sariff ctls[cnt].left = offset; 4539163057Sariff ctls[cnt].right = offset; 4540182999Smav if (w->type == 4541182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4542182999Smav ctls[cnt].ndir = HDA_CTL_OUT; 4543182999Smav else 4544182999Smav ctls[cnt].ndir = HDA_CTL_IN; 4545162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4546162922Sariff break; 4547162922Sariff } 4548162922Sariff } 4549162922Sariff } 4550162922Sariff 4551162922Sariff devinfo->function.audio.ctl = ctls; 4552162922Sariff} 4553162922Sariff 4554182999Smavstatic void 4555182999Smavhdac_audio_as_parse(struct hdac_devinfo *devinfo) 4556182999Smav{ 4557182999Smav struct hdac_softc *sc = devinfo->codec->sc; 4558182999Smav struct hdac_audio_as *as; 4559182999Smav struct hdac_widget *w; 4560182999Smav int i, j, cnt, max, type, dir, assoc, seq, first, hpredir; 4561182999Smav 4562184991Smav /* Count present associations */ 4563182999Smav max = 0; 4564184991Smav for (j = 1; j < 16; j++) { 4565182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4566182999Smav w = hdac_widget_get(devinfo, i); 4567182999Smav if (w == NULL || w->enable == 0) 4568182999Smav continue; 4569182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4570182999Smav continue; 4571182999Smav if (HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config) 4572182999Smav != j) 4573182999Smav continue; 4574182999Smav max++; 4575182999Smav if (j != 15) /* There could be many 1-pin assocs #15 */ 4576182999Smav break; 4577182999Smav } 4578182999Smav } 4579182999Smav 4580182999Smav devinfo->function.audio.ascnt = max; 4581182999Smav 4582182999Smav if (max < 1) 4583182999Smav return; 4584182999Smav 4585182999Smav as = (struct hdac_audio_as *)malloc( 4586182999Smav sizeof(*as) * max, M_HDAC, M_ZERO | M_NOWAIT); 4587182999Smav 4588182999Smav if (as == NULL) { 4589182999Smav /* Blekh! */ 4590182999Smav device_printf(sc->dev, "unable to allocate assocs!\n"); 4591182999Smav devinfo->function.audio.ascnt = 0; 4592182999Smav return; 4593182999Smav } 4594182999Smav 4595182999Smav for (i = 0; i < max; i++) { 4596182999Smav as[i].hpredir = -1; 4597182999Smav as[i].chan = -1; 4598197611Smav as[i].digital = 0; 4599182999Smav } 4600182999Smav 4601182999Smav /* Scan associations skipping as=0. */ 4602182999Smav cnt = 0; 4603182999Smav for (j = 1; j < 16; j++) { 4604182999Smav first = 16; 4605182999Smav hpredir = 0; 4606182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4607182999Smav w = hdac_widget_get(devinfo, i); 4608182999Smav if (w == NULL || w->enable == 0) 4609182999Smav continue; 4610182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4611182999Smav continue; 4612182999Smav assoc = HDA_CONFIG_DEFAULTCONF_ASSOCIATION(w->wclass.pin.config); 4613182999Smav seq = HDA_CONFIG_DEFAULTCONF_SEQUENCE(w->wclass.pin.config); 4614182999Smav if (assoc != j) { 4615182999Smav continue; 4616182999Smav } 4617182999Smav KASSERT(cnt < max, 4618182999Smav ("%s: Associations owerflow (%d of %d)", 4619182999Smav __func__, cnt, max)); 4620182999Smav type = w->wclass.pin.config & 4621182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4622182999Smav /* Get pin direction. */ 4623182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT || 4624182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4625182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4626182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT || 4627182999Smav type == HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT) 4628182999Smav dir = HDA_CTL_OUT; 4629182999Smav else 4630182999Smav dir = HDA_CTL_IN; 4631182999Smav /* If this is a first pin - create new association. */ 4632182999Smav if (as[cnt].pincnt == 0) { 4633182999Smav as[cnt].enable = 1; 4634182999Smav as[cnt].index = j; 4635182999Smav as[cnt].dir = dir; 4636182999Smav } 4637182999Smav if (seq < first) 4638182999Smav first = seq; 4639182999Smav /* Check association correctness. */ 4640182999Smav if (as[cnt].pins[seq] != 0) { 4641182999Smav device_printf(sc->dev, "%s: Duplicate pin %d (%d) " 4642182999Smav "in association %d! Disabling association.\n", 4643182999Smav __func__, seq, w->nid, j); 4644182999Smav as[cnt].enable = 0; 4645182999Smav } 4646182999Smav if (dir != as[cnt].dir) { 4647182999Smav device_printf(sc->dev, "%s: Pin %d has wrong " 4648182999Smav "direction for association %d! Disabling " 4649182999Smav "association.\n", 4650182999Smav __func__, w->nid, j); 4651182999Smav as[cnt].enable = 0; 4652182999Smav } 4653197611Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 4654197611Smav if (HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap)) 4655197611Smav as[cnt].digital = 3; 4656197611Smav else if (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap)) 4657197611Smav as[cnt].digital = 2; 4658197611Smav else 4659197611Smav as[cnt].digital = 1; 4660197611Smav } 4661182999Smav /* Headphones with seq=15 may mean redirection. */ 4662182999Smav if (type == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT && 4663182999Smav seq == 15) 4664182999Smav hpredir = 1; 4665182999Smav as[cnt].pins[seq] = w->nid; 4666182999Smav as[cnt].pincnt++; 4667182999Smav /* Association 15 is a multiple unassociated pins. */ 4668182999Smav if (j == 15) 4669182999Smav cnt++; 4670182999Smav } 4671182999Smav if (j != 15 && as[cnt].pincnt > 0) { 4672182999Smav if (hpredir && as[cnt].pincnt > 1) 4673182999Smav as[cnt].hpredir = first; 4674182999Smav cnt++; 4675182999Smav } 4676182999Smav } 4677182999Smav HDA_BOOTVERBOSE( 4678182999Smav device_printf(sc->dev, 4679183097Smav "%d associations found:\n", max); 4680182999Smav for (i = 0; i < max; i++) { 4681182999Smav device_printf(sc->dev, 4682182999Smav "Association %d (%d) %s%s:\n", 4683182999Smav i, as[i].index, (as[i].dir == HDA_CTL_IN)?"in":"out", 4684182999Smav as[i].enable?"":" (disabled)"); 4685182999Smav for (j = 0; j < 16; j++) { 4686182999Smav if (as[i].pins[j] == 0) 4687182999Smav continue; 4688182999Smav device_printf(sc->dev, 4689183097Smav " Pin nid=%d seq=%d\n", 4690182999Smav as[i].pins[j], j); 4691182999Smav } 4692182999Smav } 4693182999Smav ); 4694182999Smav 4695182999Smav devinfo->function.audio.as = as; 4696182999Smav} 4697182999Smav 4698162965Sariffstatic const struct { 4699162965Sariff uint32_t model; 4700162965Sariff uint32_t id; 4701162965Sariff uint32_t set, unset; 4702162965Sariff} hdac_quirks[] = { 4703163057Sariff /* 4704163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4705163057Sariff * on few codecs (especially ALC880) seems broken or 4706163057Sariff * perhaps unsupported. 4707163057Sariff */ 4708163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4709169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4710162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4711165039Sariff HDA_QUIRK_GPIO0, 0 }, 4712178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4713178155Sariff HDA_QUIRK_GPIO0, 0 }, 4714162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4715165039Sariff HDA_QUIRK_GPIO0, 0 }, 4716165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4717165281Sariff HDA_QUIRK_GPIO0, 0 }, 4718167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4719167623Sariff HDA_QUIRK_GPIO0, 0 }, 4720169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4721169277Sariff HDA_QUIRK_GPIO0, 0 }, 4722163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4723163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4724178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4725163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4726169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4727169277Sariff HDA_QUIRK_OVREF, 0 }, 4728169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4729169277Sariff HDA_QUIRK_OVREF, 0 }, 4730169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4731169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4732165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4733165281Sariff HDA_QUIRK_GPIO1, 0 }, 4734164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4735182999Smav HDA_QUIRK_EAPDINV | HDA_QUIRK_SENSEINV, 0 }, 4736164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4737164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4738173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4739173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4740165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4741165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4742199846Smav { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, 4743199846Smav HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 }, 4744183894Smav { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, 4745180532Sdelphij HDA_QUIRK_GPIO0, 0 }, 4746184483Smav { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, 4747184483Smav HDA_QUIRK_GPIO2, 0 }, 4748183894Smav { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, 4749178155Sariff HDA_QUIRK_GPIO0, 0 }, 4750169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4751169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4752170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4753170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4754186430Smav { HDA_MATCH_ALL, HDA_CODEC_CX20549, 4755182999Smav 0, HDA_QUIRK_FORCESTEREO } 4756162965Sariff}; 4757162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4758162965Sariff 4759162922Sariffstatic void 4760162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4761162922Sariff{ 4762162922Sariff struct hdac_widget *w; 4763162965Sariff uint32_t id, subvendor; 4764162922Sariff int i; 4765162922Sariff 4766182999Smav id = hdac_codec_id(devinfo->codec); 4767163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4768163057Sariff 4769162922Sariff /* 4770163057Sariff * Quirks 4771162922Sariff */ 4772163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4773163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4774163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4775163057Sariff continue; 4776163057Sariff if (hdac_quirks[i].set != 0) 4777163057Sariff devinfo->function.audio.quirks |= 4778163057Sariff hdac_quirks[i].set; 4779163057Sariff if (hdac_quirks[i].unset != 0) 4780163057Sariff devinfo->function.audio.quirks &= 4781163057Sariff ~(hdac_quirks[i].unset); 4782163057Sariff } 4783163057Sariff 4784162922Sariff switch (id) { 4785187196Smav case HDA_CODEC_AD1983: 4786187196Smav /* 4787187202Smav * This codec has several possible usages, but none 4788187202Smav * fit the parser best. Help parser to choose better. 4789187196Smav */ 4790187196Smav /* Disable direct unmixed playback to get pcm volume. */ 4791187196Smav w = hdac_widget_get(devinfo, 5); 4792187196Smav if (w != NULL) 4793187196Smav w->connsenable[0] = 0; 4794187196Smav w = hdac_widget_get(devinfo, 6); 4795187196Smav if (w != NULL) 4796187196Smav w->connsenable[0] = 0; 4797187196Smav w = hdac_widget_get(devinfo, 11); 4798187196Smav if (w != NULL) 4799187196Smav w->connsenable[0] = 0; 4800187196Smav /* Disable mic and line selectors. */ 4801187196Smav w = hdac_widget_get(devinfo, 12); 4802187196Smav if (w != NULL) 4803187196Smav w->connsenable[1] = 0; 4804187196Smav w = hdac_widget_get(devinfo, 13); 4805187196Smav if (w != NULL) 4806187196Smav w->connsenable[1] = 0; 4807187196Smav /* Disable recording from mono playback mix. */ 4808187196Smav w = hdac_widget_get(devinfo, 20); 4809187196Smav if (w != NULL) 4810187196Smav w->connsenable[3] = 0; 4811187196Smav break; 4812162922Sariff case HDA_CODEC_AD1986A: 4813186503Smav /* 4814186503Smav * This codec has overcomplicated input mixing. 4815186503Smav * Make some cleaning there. 4816186503Smav */ 4817186503Smav /* Disable input mono mixer. Not needed and not supported. */ 4818186503Smav w = hdac_widget_get(devinfo, 43); 4819186503Smav if (w != NULL) 4820186503Smav w->enable = 0; 4821186503Smav /* Disable any with any input mixing mesh. Use separately. */ 4822186503Smav w = hdac_widget_get(devinfo, 39); 4823186503Smav if (w != NULL) 4824186503Smav w->enable = 0; 4825186503Smav w = hdac_widget_get(devinfo, 40); 4826186503Smav if (w != NULL) 4827186503Smav w->enable = 0; 4828186503Smav w = hdac_widget_get(devinfo, 41); 4829186503Smav if (w != NULL) 4830186503Smav w->enable = 0; 4831186503Smav w = hdac_widget_get(devinfo, 42); 4832186503Smav if (w != NULL) 4833186503Smav w->enable = 0; 4834186503Smav /* Disable duplicate mixer node connector. */ 4835186503Smav w = hdac_widget_get(devinfo, 15); 4836186503Smav if (w != NULL) 4837186503Smav w->connsenable[3] = 0; 4838190630Smav /* There is only one mic preamplifier, use it effectively. */ 4839190630Smav w = hdac_widget_get(devinfo, 31); 4840190630Smav if (w != NULL) { 4841190630Smav if ((w->wclass.pin.config & 4842190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4843190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4844190630Smav w = hdac_widget_get(devinfo, 16); 4845190630Smav if (w != NULL) 4846190630Smav w->connsenable[2] = 0; 4847190630Smav } else { 4848190630Smav w = hdac_widget_get(devinfo, 15); 4849190630Smav if (w != NULL) 4850190630Smav w->connsenable[0] = 0; 4851190630Smav } 4852190630Smav } 4853190630Smav w = hdac_widget_get(devinfo, 32); 4854190630Smav if (w != NULL) { 4855190630Smav if ((w->wclass.pin.config & 4856190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 4857190630Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 4858190630Smav w = hdac_widget_get(devinfo, 16); 4859190630Smav if (w != NULL) 4860190630Smav w->connsenable[0] = 0; 4861190630Smav } else { 4862190630Smav w = hdac_widget_get(devinfo, 15); 4863190630Smav if (w != NULL) 4864190630Smav w->connsenable[1] = 0; 4865190630Smav } 4866190630Smav } 4867186503Smav 4868182999Smav if (subvendor == ASUS_A8X_SUBVENDOR) { 4869178155Sariff /* 4870178155Sariff * This is just plain ridiculous.. There 4871178155Sariff * are several A8 series that share the same 4872178155Sariff * pci id but works differently (EAPD). 4873178155Sariff */ 4874178155Sariff w = hdac_widget_get(devinfo, 26); 4875178155Sariff if (w != NULL && w->type == 4876178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4877178155Sariff (w->wclass.pin.config & 4878178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4879178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4880178155Sariff devinfo->function.audio.quirks &= 4881178155Sariff ~HDA_QUIRK_EAPDINV; 4882169277Sariff } 4883162922Sariff break; 4884184230Smav case HDA_CODEC_AD1981HD: 4885184230Smav /* 4886184230Smav * This codec has very unusual design with several 4887184254Smav * points inappropriate for the present parser. 4888184230Smav */ 4889184230Smav /* Disable recording from mono playback mix. */ 4890184230Smav w = hdac_widget_get(devinfo, 21); 4891184230Smav if (w != NULL) 4892184230Smav w->connsenable[3] = 0; 4893184230Smav /* Disable rear to front mic mixer, use separately. */ 4894184230Smav w = hdac_widget_get(devinfo, 31); 4895184230Smav if (w != NULL) 4896184230Smav w->enable = 0; 4897202789Smav /* Disable direct playback, use mixer. */ 4898202789Smav w = hdac_widget_get(devinfo, 5); 4899184230Smav if (w != NULL) 4900202789Smav w->connsenable[0] = 0; 4901202789Smav w = hdac_widget_get(devinfo, 6); 4902202789Smav if (w != NULL) 4903202789Smav w->connsenable[0] = 0; 4904202789Smav w = hdac_widget_get(devinfo, 9); 4905202789Smav if (w != NULL) 4906202789Smav w->connsenable[0] = 0; 4907202789Smav w = hdac_widget_get(devinfo, 24); 4908202789Smav if (w != NULL) 4909202789Smav w->connsenable[0] = 0; 4910184230Smav break; 4911182999Smav } 4912182999Smav} 4913182999Smav 4914182999Smav/* 4915182999Smav * Trace path from DAC to pin. 4916182999Smav */ 4917182999Smavstatic nid_t 4918182999Smavhdac_audio_trace_dac(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 4919182999Smav int dupseq, int min, int only, int depth) 4920182999Smav{ 4921182999Smav struct hdac_widget *w; 4922182999Smav int i, im = -1; 4923182999Smav nid_t m = 0, ret; 4924182999Smav 4925182999Smav if (depth > HDA_PARSE_MAXDEPTH) 4926182999Smav return (0); 4927182999Smav w = hdac_widget_get(devinfo, nid); 4928182999Smav if (w == NULL || w->enable == 0) 4929182999Smav return (0); 4930183097Smav HDA_BOOTHVERBOSE( 4931182999Smav if (!only) { 4932182999Smav device_printf(devinfo->codec->sc->dev, 4933182999Smav " %*stracing via nid %d\n", 4934182999Smav depth + 1, "", w->nid); 4935169277Sariff } 4936182999Smav ); 4937182999Smav /* Use only unused widgets */ 4938182999Smav if (w->bindas >= 0 && w->bindas != as) { 4939183097Smav HDA_BOOTHVERBOSE( 4940182999Smav if (!only) { 4941182999Smav device_printf(devinfo->codec->sc->dev, 4942182999Smav " %*snid %d busy by association %d\n", 4943182999Smav depth + 1, "", w->nid, w->bindas); 4944182999Smav } 4945182999Smav ); 4946182999Smav return (0); 4947182999Smav } 4948182999Smav if (dupseq < 0) { 4949182999Smav if (w->bindseqmask != 0) { 4950183097Smav HDA_BOOTHVERBOSE( 4951182999Smav if (!only) { 4952182999Smav device_printf(devinfo->codec->sc->dev, 4953182999Smav " %*snid %d busy by seqmask %x\n", 4954182999Smav depth + 1, "", w->nid, w->bindseqmask); 4955182999Smav } 4956182999Smav ); 4957182999Smav return (0); 4958169277Sariff } 4959182999Smav } else { 4960182999Smav /* If this is headphones - allow duplicate first pin. */ 4961182999Smav if (w->bindseqmask != 0 && 4962182999Smav (w->bindseqmask & (1 << dupseq)) == 0) { 4963183097Smav HDA_BOOTHVERBOSE( 4964182999Smav device_printf(devinfo->codec->sc->dev, 4965182999Smav " %*snid %d busy by seqmask %x\n", 4966182999Smav depth + 1, "", w->nid, w->bindseqmask); 4967182999Smav ); 4968182999Smav return (0); 4969169277Sariff } 4970182999Smav } 4971182999Smav 4972182999Smav switch (w->type) { 4973182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4974182999Smav /* Do not traverse input. AD1988 has digital monitor 4975182999Smav for which we are not ready. */ 4976169277Sariff break; 4977182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4978182999Smav /* If we are tracing HP take only dac of first pin. */ 4979182999Smav if ((only == 0 || only == w->nid) && 4980182999Smav (w->nid >= min) && (dupseq < 0 || w->nid == 4981182999Smav devinfo->function.audio.as[as].dacs[dupseq])) 4982182999Smav m = w->nid; 4983178155Sariff break; 4984182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4985182999Smav if (depth > 0) 4986169277Sariff break; 4987182999Smav /* Fall */ 4988182999Smav default: 4989182999Smav /* Find reachable DACs with smallest nid respecting constraints. */ 4990182999Smav for (i = 0; i < w->nconns; i++) { 4991182999Smav if (w->connsenable[i] == 0) 4992162922Sariff continue; 4993182999Smav if (w->selconn != -1 && w->selconn != i) 4994162922Sariff continue; 4995182999Smav if ((ret = hdac_audio_trace_dac(devinfo, as, seq, 4996182999Smav w->conns[i], dupseq, min, only, depth + 1)) != 0) { 4997182999Smav if (m == 0 || ret < m) { 4998182999Smav m = ret; 4999182999Smav im = i; 5000182999Smav } 5001182999Smav if (only || dupseq >= 0) 5002182999Smav break; 5003182999Smav } 5004162922Sariff } 5005182999Smav if (m && only && ((w->nconns > 1 && 5006182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5007182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 5008182999Smav w->selconn = im; 5009162922Sariff break; 5010182999Smav } 5011182999Smav if (m && only) { 5012182999Smav w->bindas = as; 5013182999Smav w->bindseqmask |= (1 << seq); 5014182999Smav } 5015183097Smav HDA_BOOTHVERBOSE( 5016182999Smav if (!only) { 5017182999Smav device_printf(devinfo->codec->sc->dev, 5018182999Smav " %*snid %d returned %d\n", 5019182999Smav depth + 1, "", w->nid, m); 5020182999Smav } 5021182999Smav ); 5022182999Smav return (m); 5023182999Smav} 5024162922Sariff 5025182999Smav/* 5026182999Smav * Trace path from widget to ADC. 5027182999Smav */ 5028182999Smavstatic nid_t 5029182999Smavhdac_audio_trace_adc(struct hdac_devinfo *devinfo, int as, int seq, nid_t nid, 5030182999Smav int only, int depth) 5031182999Smav{ 5032182999Smav struct hdac_widget *w, *wc; 5033182999Smav int i, j; 5034182999Smav nid_t res = 0; 5035182999Smav 5036182999Smav if (depth > HDA_PARSE_MAXDEPTH) 5037182999Smav return (0); 5038182999Smav w = hdac_widget_get(devinfo, nid); 5039182999Smav if (w == NULL || w->enable == 0) 5040182999Smav return (0); 5041183097Smav HDA_BOOTHVERBOSE( 5042182999Smav device_printf(devinfo->codec->sc->dev, 5043182999Smav " %*stracing via nid %d\n", 5044182999Smav depth + 1, "", w->nid); 5045182999Smav ); 5046182999Smav /* Use only unused widgets */ 5047182999Smav if (w->bindas >= 0 && w->bindas != as) { 5048183097Smav HDA_BOOTHVERBOSE( 5049182999Smav device_printf(devinfo->codec->sc->dev, 5050182999Smav " %*snid %d busy by association %d\n", 5051182999Smav depth + 1, "", w->nid, w->bindas); 5052182999Smav ); 5053182999Smav return (0); 5054182999Smav } 5055182999Smav 5056182999Smav switch (w->type) { 5057182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5058182999Smav /* If we are tracing HP take only dac of first pin. */ 5059182999Smav if (only == w->nid) 5060182999Smav res = 1; 5061162922Sariff break; 5062182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5063182999Smav if (depth > 0) 5064182999Smav break; 5065182999Smav /* Fall */ 5066182999Smav default: 5067182999Smav /* Try to find reachable ADCs with specified nid. */ 5068182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5069182999Smav wc = hdac_widget_get(devinfo, j); 5070182999Smav if (wc == NULL || wc->enable == 0) 5071182999Smav continue; 5072182999Smav for (i = 0; i < wc->nconns; i++) { 5073182999Smav if (wc->connsenable[i] == 0) 5074182999Smav continue; 5075182999Smav if (wc->conns[i] != nid) 5076182999Smav continue; 5077182999Smav if (hdac_audio_trace_adc(devinfo, as, seq, 5078182999Smav j, only, depth + 1) != 0) { 5079182999Smav res = 1; 5080182999Smav if (((wc->nconns > 1 && 5081182999Smav wc->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 5082182999Smav wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) && 5083182999Smav wc->selconn == -1) 5084182999Smav wc->selconn = i; 5085182999Smav } 5086182999Smav } 5087169277Sariff } 5088169277Sariff break; 5089162922Sariff } 5090182999Smav if (res) { 5091182999Smav w->bindas = as; 5092182999Smav w->bindseqmask |= (1 << seq); 5093182999Smav } 5094183097Smav HDA_BOOTHVERBOSE( 5095182999Smav device_printf(devinfo->codec->sc->dev, 5096182999Smav " %*snid %d returned %d\n", 5097182999Smav depth + 1, "", w->nid, res); 5098182999Smav ); 5099182999Smav return (res); 5100162922Sariff} 5101162922Sariff 5102182999Smav/* 5103182999Smav * Erase trace path of the specified association. 5104182999Smav */ 5105182999Smavstatic void 5106182999Smavhdac_audio_undo_trace(struct hdac_devinfo *devinfo, int as, int seq) 5107182999Smav{ 5108182999Smav struct hdac_widget *w; 5109182999Smav int i; 5110182999Smav 5111182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5112182999Smav w = hdac_widget_get(devinfo, i); 5113182999Smav if (w == NULL || w->enable == 0) 5114182999Smav continue; 5115182999Smav if (w->bindas == as) { 5116182999Smav if (seq >= 0) { 5117182999Smav w->bindseqmask &= ~(1 << seq); 5118182999Smav if (w->bindseqmask == 0) { 5119182999Smav w->bindas = -1; 5120182999Smav w->selconn = -1; 5121182999Smav } 5122182999Smav } else { 5123182999Smav w->bindas = -1; 5124182999Smav w->bindseqmask = 0; 5125182999Smav w->selconn = -1; 5126182999Smav } 5127182999Smav } 5128182999Smav } 5129182999Smav} 5130182999Smav 5131182999Smav/* 5132182999Smav * Trace association path from DAC to output 5133182999Smav */ 5134162922Sariffstatic int 5135182999Smavhdac_audio_trace_as_out(struct hdac_devinfo *devinfo, int as, int seq) 5136162922Sariff{ 5137182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5138182999Smav int i, hpredir; 5139182999Smav nid_t min, res; 5140162922Sariff 5141182999Smav /* Find next pin */ 5142185176Smav for (i = seq; i < 16 && ases[as].pins[i] == 0; i++) 5143182999Smav ; 5144188510Smav /* Check if there is no any left. If so - we succeeded. */ 5145182999Smav if (i == 16) 5146182999Smav return (1); 5147182999Smav 5148182999Smav hpredir = (i == 15 && ases[as].fakeredir == 0)?ases[as].hpredir:-1; 5149182999Smav min = 0; 5150182999Smav res = 0; 5151182999Smav do { 5152183097Smav HDA_BOOTHVERBOSE( 5153182999Smav device_printf(devinfo->codec->sc->dev, 5154182999Smav " Tracing pin %d with min nid %d", 5155182999Smav ases[as].pins[i], min); 5156182999Smav if (hpredir >= 0) 5157183097Smav printf(" and hpredir %d", hpredir); 5158183097Smav printf("\n"); 5159182999Smav ); 5160182999Smav /* Trace this pin taking min nid into account. */ 5161182999Smav res = hdac_audio_trace_dac(devinfo, as, i, 5162182999Smav ases[as].pins[i], hpredir, min, 0, 0); 5163182999Smav if (res == 0) { 5164182999Smav /* If we failed - return to previous and redo it. */ 5165182999Smav HDA_BOOTVERBOSE( 5166182999Smav device_printf(devinfo->codec->sc->dev, 5167182999Smav " Unable to trace pin %d seq %d with min " 5168183097Smav "nid %d", 5169183097Smav ases[as].pins[i], i, min); 5170183097Smav if (hpredir >= 0) 5171183097Smav printf(" and hpredir %d", hpredir); 5172183097Smav printf("\n"); 5173182999Smav ); 5174182999Smav return (0); 5175162922Sariff } 5176182999Smav HDA_BOOTVERBOSE( 5177182999Smav device_printf(devinfo->codec->sc->dev, 5178183097Smav " Pin %d traced to DAC %d", 5179183097Smav ases[as].pins[i], res); 5180183097Smav if (hpredir >= 0) 5181183097Smav printf(" and hpredir %d", hpredir); 5182183097Smav if (ases[as].fakeredir) 5183183097Smav printf(" with fake redirection"); 5184183097Smav printf("\n"); 5185182999Smav ); 5186182999Smav /* Trace again to mark the path */ 5187182999Smav hdac_audio_trace_dac(devinfo, as, i, 5188182999Smav ases[as].pins[i], hpredir, min, res, 0); 5189182999Smav ases[as].dacs[i] = res; 5190188510Smav /* We succeeded, so call next. */ 5191182999Smav if (hdac_audio_trace_as_out(devinfo, as, i + 1)) 5192182999Smav return (1); 5193182999Smav /* If next failed, we should retry with next min */ 5194182999Smav hdac_audio_undo_trace(devinfo, as, i); 5195182999Smav ases[as].dacs[i] = 0; 5196182999Smav min = res + 1; 5197182999Smav } while (1); 5198162922Sariff} 5199162922Sariff 5200182999Smav/* 5201182999Smav * Trace association path from input to ADC 5202182999Smav */ 5203162922Sariffstatic int 5204182999Smavhdac_audio_trace_as_in(struct hdac_devinfo *devinfo, int as) 5205162922Sariff{ 5206182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5207162922Sariff struct hdac_widget *w; 5208182999Smav int i, j, k; 5209162922Sariff 5210182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5211182999Smav w = hdac_widget_get(devinfo, j); 5212182999Smav if (w == NULL || w->enable == 0) 5213182999Smav continue; 5214182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5215182999Smav continue; 5216182999Smav if (w->bindas >= 0 && w->bindas != as) 5217182999Smav continue; 5218182999Smav 5219182999Smav /* Find next pin */ 5220182999Smav for (i = 0; i < 16; i++) { 5221182999Smav if (ases[as].pins[i] == 0) 5222182999Smav continue; 5223182999Smav 5224183097Smav HDA_BOOTHVERBOSE( 5225182999Smav device_printf(devinfo->codec->sc->dev, 5226182999Smav " Tracing pin %d to ADC %d\n", 5227182999Smav ases[as].pins[i], j); 5228182999Smav ); 5229182999Smav /* Trace this pin taking goal into account. */ 5230182999Smav if (hdac_audio_trace_adc(devinfo, as, i, 5231182999Smav ases[as].pins[i], j, 0) == 0) { 5232182999Smav /* If we failed - return to previous and redo it. */ 5233182999Smav HDA_BOOTVERBOSE( 5234182999Smav device_printf(devinfo->codec->sc->dev, 5235183097Smav " Unable to trace pin %d to ADC %d, undo traces\n", 5236182999Smav ases[as].pins[i], j); 5237182999Smav ); 5238182999Smav hdac_audio_undo_trace(devinfo, as, -1); 5239182999Smav for (k = 0; k < 16; k++) 5240182999Smav ases[as].dacs[k] = 0; 5241182999Smav break; 5242162922Sariff } 5243182999Smav HDA_BOOTVERBOSE( 5244182999Smav device_printf(devinfo->codec->sc->dev, 5245183097Smav " Pin %d traced to ADC %d\n", 5246183097Smav ases[as].pins[i], j); 5247182999Smav ); 5248182999Smav ases[as].dacs[i] = j; 5249162922Sariff } 5250182999Smav if (i == 16) 5251182999Smav return (1); 5252162922Sariff } 5253182999Smav return (0); 5254162922Sariff} 5255162922Sariff 5256182999Smav/* 5257182999Smav * Trace input monitor path from mixer to output association. 5258182999Smav */ 5259183097Smavstatic int 5260182999Smavhdac_audio_trace_to_out(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5261162922Sariff{ 5262182999Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5263182999Smav struct hdac_widget *w, *wc; 5264182999Smav int i, j; 5265182999Smav nid_t res = 0; 5266162922Sariff 5267162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5268162922Sariff return (0); 5269162922Sariff w = hdac_widget_get(devinfo, nid); 5270162922Sariff if (w == NULL || w->enable == 0) 5271162922Sariff return (0); 5272183097Smav HDA_BOOTHVERBOSE( 5273182999Smav device_printf(devinfo->codec->sc->dev, 5274182999Smav " %*stracing via nid %d\n", 5275182999Smav depth + 1, "", w->nid); 5276182999Smav ); 5277182999Smav /* Use only unused widgets */ 5278182999Smav if (depth > 0 && w->bindas != -1) { 5279182999Smav if (w->bindas < 0 || ases[w->bindas].dir == HDA_CTL_OUT) { 5280183097Smav HDA_BOOTHVERBOSE( 5281182999Smav device_printf(devinfo->codec->sc->dev, 5282182999Smav " %*snid %d found output association %d\n", 5283182999Smav depth + 1, "", w->nid, w->bindas); 5284182999Smav ); 5285202789Smav if (w->bindas >= 0) 5286202789Smav w->pflags |= HDA_ADC_MONITOR; 5287182999Smav return (1); 5288182999Smav } else { 5289183097Smav HDA_BOOTHVERBOSE( 5290182999Smav device_printf(devinfo->codec->sc->dev, 5291182999Smav " %*snid %d busy by input association %d\n", 5292182999Smav depth + 1, "", w->nid, w->bindas); 5293182999Smav ); 5294182999Smav return (0); 5295182999Smav } 5296182999Smav } 5297182999Smav 5298162922Sariff switch (w->type) { 5299162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 5300182999Smav /* Do not traverse input. AD1988 has digital monitor 5301182999Smav for which we are not ready. */ 5302162922Sariff break; 5303162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 5304182999Smav if (depth > 0) 5305182999Smav break; 5306182999Smav /* Fall */ 5307182999Smav default: 5308182999Smav /* Try to find reachable ADCs with specified nid. */ 5309182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5310182999Smav wc = hdac_widget_get(devinfo, j); 5311182999Smav if (wc == NULL || wc->enable == 0) 5312182999Smav continue; 5313182999Smav for (i = 0; i < wc->nconns; i++) { 5314182999Smav if (wc->connsenable[i] == 0) 5315182999Smav continue; 5316182999Smav if (wc->conns[i] != nid) 5317182999Smav continue; 5318182999Smav if (hdac_audio_trace_to_out(devinfo, 5319182999Smav j, depth + 1) != 0) { 5320182999Smav res = 1; 5321182999Smav if (wc->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5322182999Smav wc->selconn == -1) 5323182999Smav wc->selconn = i; 5324182999Smav } 5325182999Smav } 5326162922Sariff } 5327162922Sariff break; 5328182999Smav } 5329202789Smav if (res && w->bindas == -1) 5330182999Smav w->bindas = -2; 5331182999Smav 5332183097Smav HDA_BOOTHVERBOSE( 5333182999Smav device_printf(devinfo->codec->sc->dev, 5334182999Smav " %*snid %d returned %d\n", 5335182999Smav depth + 1, "", w->nid, res); 5336182999Smav ); 5337182999Smav return (res); 5338182999Smav} 5339182999Smav 5340182999Smav/* 5341182999Smav * Trace extra associations (beeper, monitor) 5342182999Smav */ 5343182999Smavstatic void 5344182999Smavhdac_audio_trace_as_extra(struct hdac_devinfo *devinfo) 5345182999Smav{ 5346182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5347182999Smav struct hdac_widget *w; 5348182999Smav int j; 5349182999Smav 5350182999Smav /* Input monitor */ 5351182999Smav /* Find mixer associated with input, but supplying signal 5352182999Smav for output associations. Hope it will be input monitor. */ 5353182999Smav HDA_BOOTVERBOSE( 5354182999Smav device_printf(devinfo->codec->sc->dev, 5355182999Smav "Tracing input monitor\n"); 5356182999Smav ); 5357182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5358182999Smav w = hdac_widget_get(devinfo, j); 5359182999Smav if (w == NULL || w->enable == 0) 5360182999Smav continue; 5361182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5362182999Smav continue; 5363182999Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5364182999Smav continue; 5365182999Smav HDA_BOOTVERBOSE( 5366182999Smav device_printf(devinfo->codec->sc->dev, 5367182999Smav " Tracing nid %d to out\n", 5368182999Smav j); 5369182999Smav ); 5370182999Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5371182999Smav HDA_BOOTVERBOSE( 5372182999Smav device_printf(devinfo->codec->sc->dev, 5373182999Smav " nid %d is input monitor\n", 5374182999Smav w->nid); 5375182999Smav ); 5376182999Smav w->ossdev = SOUND_MIXER_IMIX; 5377162922Sariff } 5378162922Sariff } 5379182999Smav 5380202789Smav /* Other inputs monitor */ 5381202789Smav /* Find input pins supplying signal for output associations. 5382202789Smav Hope it will be input monitoring. */ 5383202789Smav HDA_BOOTVERBOSE( 5384202789Smav device_printf(devinfo->codec->sc->dev, 5385202789Smav "Tracing other input monitors\n"); 5386202789Smav ); 5387202789Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5388202789Smav w = hdac_widget_get(devinfo, j); 5389202789Smav if (w == NULL || w->enable == 0) 5390202789Smav continue; 5391202789Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5392202789Smav continue; 5393202789Smav if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN) 5394202789Smav continue; 5395202789Smav HDA_BOOTVERBOSE( 5396202789Smav device_printf(devinfo->codec->sc->dev, 5397202789Smav " Tracing nid %d to out\n", 5398202789Smav j); 5399202789Smav ); 5400202789Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5401202789Smav HDA_BOOTVERBOSE( 5402202789Smav device_printf(devinfo->codec->sc->dev, 5403202789Smav " nid %d is input monitor\n", 5404202789Smav w->nid); 5405202789Smav ); 5406202789Smav } 5407202789Smav } 5408202789Smav 5409182999Smav /* Beeper */ 5410182999Smav HDA_BOOTVERBOSE( 5411182999Smav device_printf(devinfo->codec->sc->dev, 5412182999Smav "Tracing beeper\n"); 5413182999Smav ); 5414182999Smav for (j = devinfo->startnode; j < devinfo->endnode; j++) { 5415182999Smav w = hdac_widget_get(devinfo, j); 5416182999Smav if (w == NULL || w->enable == 0) 5417182999Smav continue; 5418182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) 5419182999Smav continue; 5420183097Smav HDA_BOOTHVERBOSE( 5421182999Smav device_printf(devinfo->codec->sc->dev, 5422182999Smav " Tracing nid %d to out\n", 5423182999Smav j); 5424182999Smav ); 5425183097Smav if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) { 5426183097Smav HDA_BOOTVERBOSE( 5427183097Smav device_printf(devinfo->codec->sc->dev, 5428183097Smav " nid %d traced to out\n", 5429183097Smav j); 5430183097Smav ); 5431183097Smav } 5432182999Smav w->bindas = -2; 5433182999Smav } 5434162922Sariff} 5435162922Sariff 5436182999Smav/* 5437182999Smav * Bind assotiations to PCM channels 5438182999Smav */ 5439182999Smavstatic void 5440182999Smavhdac_audio_bind_as(struct hdac_devinfo *devinfo) 5441162922Sariff{ 5442182999Smav struct hdac_softc *sc = devinfo->codec->sc; 5443182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5444182999Smav int j, cnt = 0, free; 5445162922Sariff 5446182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5447182999Smav if (as[j].enable) 5448182999Smav cnt++; 5449182999Smav } 5450182999Smav if (sc->num_chans == 0) { 5451182999Smav sc->chans = (struct hdac_chan *)malloc( 5452182999Smav sizeof(struct hdac_chan) * cnt, 5453182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5454182999Smav if (sc->chans == NULL) { 5455190519Smav device_printf(sc->dev, 5456182999Smav "Channels memory allocation failed!\n"); 5457182999Smav return; 5458182999Smav } 5459182999Smav } else { 5460182999Smav sc->chans = (struct hdac_chan *)realloc(sc->chans, 5461183810Smav sizeof(struct hdac_chan) * (sc->num_chans + cnt), 5462182999Smav M_HDAC, M_ZERO | M_NOWAIT); 5463182999Smav if (sc->chans == NULL) { 5464182999Smav sc->num_chans = 0; 5465190519Smav device_printf(sc->dev, 5466182999Smav "Channels memory allocation failed!\n"); 5467182999Smav return; 5468182999Smav } 5469190519Smav /* Fixup relative pointers after realloc */ 5470190519Smav for (j = 0; j < sc->num_chans; j++) 5471190519Smav sc->chans[j].caps.fmtlist = sc->chans[j].fmtlist; 5472182999Smav } 5473182999Smav free = sc->num_chans; 5474182999Smav sc->num_chans += cnt; 5475162922Sariff 5476182999Smav for (j = free; j < free + cnt; j++) { 5477190519Smav sc->chans[j].devinfo = devinfo; 5478190519Smav sc->chans[j].as = -1; 5479182999Smav } 5480162922Sariff 5481182999Smav /* Assign associations in order of their numbers, */ 5482182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 5483182999Smav if (as[j].enable == 0) 5484182999Smav continue; 5485182999Smav 5486182999Smav as[j].chan = free; 5487190519Smav sc->chans[free].as = j; 5488190519Smav sc->chans[free].dir = 5489185225Smav (as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY; 5490190519Smav hdac_pcmchannel_setup(&sc->chans[free]); 5491182999Smav free++; 5492182999Smav } 5493182999Smav} 5494162922Sariff 5495182999Smavstatic void 5496182999Smavhdac_audio_disable_nonaudio(struct hdac_devinfo *devinfo) 5497182999Smav{ 5498182999Smav struct hdac_widget *w; 5499182999Smav int i; 5500182999Smav 5501182999Smav /* Disable power and volume widgets. */ 5502182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5503182999Smav w = hdac_widget_get(devinfo, i); 5504182999Smav if (w == NULL || w->enable == 0) 5505182999Smav continue; 5506182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET || 5507182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET) { 5508182999Smav w->enable = 0; 5509183097Smav HDA_BOOTHVERBOSE( 5510182999Smav device_printf(devinfo->codec->sc->dev, 5511182999Smav " Disabling nid %d due to it's" 5512182999Smav " non-audio type.\n", 5513182999Smav w->nid); 5514182999Smav ); 5515162922Sariff } 5516182999Smav } 5517182999Smav} 5518182999Smav 5519182999Smavstatic void 5520182999Smavhdac_audio_disable_useless(struct hdac_devinfo *devinfo) 5521182999Smav{ 5522182999Smav struct hdac_widget *w, *cw; 5523182999Smav struct hdac_audio_ctl *ctl; 5524182999Smav int done, found, i, j, k; 5525182999Smav 5526182999Smav /* Disable useless pins. */ 5527182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5528182999Smav w = hdac_widget_get(devinfo, i); 5529182999Smav if (w == NULL || w->enable == 0) 5530182999Smav continue; 5531184991Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5532184991Smav if ((w->wclass.pin.config & 5533184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5534184991Smav HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) { 5535184991Smav w->enable = 0; 5536184991Smav HDA_BOOTHVERBOSE( 5537184991Smav device_printf(devinfo->codec->sc->dev, 5538184991Smav " Disabling pin nid %d due" 5539184991Smav " to None connectivity.\n", 5540184991Smav w->nid); 5541184991Smav ); 5542184991Smav } else if ((w->wclass.pin.config & 5543184991Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) == 0) { 5544184991Smav w->enable = 0; 5545184991Smav HDA_BOOTHVERBOSE( 5546184991Smav device_printf(devinfo->codec->sc->dev, 5547184991Smav " Disabling unassociated" 5548184991Smav " pin nid %d.\n", 5549184991Smav w->nid); 5550184991Smav ); 5551184991Smav } 5552182999Smav } 5553182999Smav } 5554182999Smav do { 5555182999Smav done = 1; 5556182999Smav /* Disable and mute controls for disabled widgets. */ 5557162922Sariff i = 0; 5558162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5559182999Smav if (ctl->enable == 0) 5560162922Sariff continue; 5561182999Smav if (ctl->widget->enable == 0 || 5562182999Smav (ctl->childwidget != NULL && 5563182999Smav ctl->childwidget->enable == 0)) { 5564182999Smav ctl->forcemute = 1; 5565182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5566182999Smav ctl->left = 0; 5567182999Smav ctl->right = 0; 5568182999Smav ctl->enable = 0; 5569182999Smav if (ctl->ndir == HDA_CTL_IN) 5570182999Smav ctl->widget->connsenable[ctl->index] = 0; 5571182999Smav done = 0; 5572183097Smav HDA_BOOTHVERBOSE( 5573182999Smav device_printf(devinfo->codec->sc->dev, 5574182999Smav " Disabling ctl %d nid %d cnid %d due" 5575182999Smav " to disabled widget.\n", i, 5576182999Smav ctl->widget->nid, 5577182999Smav (ctl->childwidget != NULL)? 5578182999Smav ctl->childwidget->nid:-1); 5579182999Smav ); 5580182999Smav } 5581182999Smav } 5582182999Smav /* Disable useless widgets. */ 5583182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5584182999Smav w = hdac_widget_get(devinfo, i); 5585182999Smav if (w == NULL || w->enable == 0) 5586182999Smav continue; 5587182999Smav /* Disable inputs with disabled child widgets. */ 5588182999Smav for (j = 0; j < w->nconns; j++) { 5589182999Smav if (w->connsenable[j]) { 5590182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5591182999Smav if (cw == NULL || cw->enable == 0) { 5592182999Smav w->connsenable[j] = 0; 5593183097Smav HDA_BOOTHVERBOSE( 5594182999Smav device_printf(devinfo->codec->sc->dev, 5595182999Smav " Disabling nid %d connection %d due" 5596182999Smav " to disabled child widget.\n", 5597182999Smav i, j); 5598182999Smav ); 5599163057Sariff } 5600163057Sariff } 5601162922Sariff } 5602182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5603182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5604162922Sariff continue; 5605182999Smav /* Disable mixers and selectors without inputs. */ 5606182999Smav found = 0; 5607182999Smav for (j = 0; j < w->nconns; j++) { 5608182999Smav if (w->connsenable[j]) { 5609182999Smav found = 1; 5610162922Sariff break; 5611162922Sariff } 5612182999Smav } 5613182999Smav if (found == 0) { 5614182999Smav w->enable = 0; 5615182999Smav done = 0; 5616183097Smav HDA_BOOTHVERBOSE( 5617182999Smav device_printf(devinfo->codec->sc->dev, 5618182999Smav " Disabling nid %d due to all it's" 5619182999Smav " inputs disabled.\n", w->nid); 5620182999Smav ); 5621182999Smav } 5622182999Smav /* Disable nodes without consumers. */ 5623182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 5624182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5625182999Smav continue; 5626182999Smav found = 0; 5627182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5628182999Smav cw = hdac_widget_get(devinfo, k); 5629182999Smav if (cw == NULL || cw->enable == 0) 5630182999Smav continue; 5631182999Smav for (j = 0; j < cw->nconns; j++) { 5632182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5633182999Smav found = 1; 5634182999Smav break; 5635182999Smav } 5636162922Sariff } 5637162922Sariff } 5638182999Smav if (found == 0) { 5639182999Smav w->enable = 0; 5640182999Smav done = 0; 5641183097Smav HDA_BOOTHVERBOSE( 5642182999Smav device_printf(devinfo->codec->sc->dev, 5643182999Smav " Disabling nid %d due to all it's" 5644182999Smav " consumers disabled.\n", w->nid); 5645182999Smav ); 5646182999Smav } 5647162922Sariff } 5648182999Smav } while (done == 0); 5649182999Smav 5650182999Smav} 5651182999Smav 5652182999Smavstatic void 5653182999Smavhdac_audio_disable_unas(struct hdac_devinfo *devinfo) 5654182999Smav{ 5655182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5656182999Smav struct hdac_widget *w, *cw; 5657182999Smav struct hdac_audio_ctl *ctl; 5658182999Smav int i, j, k; 5659182999Smav 5660182999Smav /* Disable unassosiated widgets. */ 5661182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5662182999Smav w = hdac_widget_get(devinfo, i); 5663182999Smav if (w == NULL || w->enable == 0) 5664182999Smav continue; 5665182999Smav if (w->bindas == -1) { 5666182999Smav w->enable = 0; 5667183097Smav HDA_BOOTHVERBOSE( 5668182999Smav device_printf(devinfo->codec->sc->dev, 5669182999Smav " Disabling unassociated nid %d.\n", 5670182999Smav w->nid); 5671182999Smav ); 5672182999Smav } 5673182999Smav } 5674182999Smav /* Disable input connections on input pin and 5675182999Smav * output on output. */ 5676182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5677182999Smav w = hdac_widget_get(devinfo, i); 5678182999Smav if (w == NULL || w->enable == 0) 5679182999Smav continue; 5680182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5681182999Smav continue; 5682182999Smav if (w->bindas < 0) 5683182999Smav continue; 5684182999Smav if (as[w->bindas].dir == HDA_CTL_IN) { 5685182999Smav for (j = 0; j < w->nconns; j++) { 5686182999Smav if (w->connsenable[j] == 0) 5687182999Smav continue; 5688182999Smav w->connsenable[j] = 0; 5689183097Smav HDA_BOOTHVERBOSE( 5690182999Smav device_printf(devinfo->codec->sc->dev, 5691182999Smav " Disabling connection to input pin " 5692182999Smav "nid %d conn %d.\n", 5693182999Smav i, j); 5694182999Smav ); 5695162922Sariff } 5696182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5697182999Smav HDA_CTL_IN, -1, 1); 5698182999Smav if (ctl && ctl->enable) { 5699182999Smav ctl->forcemute = 1; 5700182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5701182999Smav ctl->left = 0; 5702182999Smav ctl->right = 0; 5703182999Smav ctl->enable = 0; 5704182999Smav } 5705182999Smav } else { 5706182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5707182999Smav HDA_CTL_OUT, -1, 1); 5708182999Smav if (ctl && ctl->enable) { 5709182999Smav ctl->forcemute = 1; 5710182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5711182999Smav ctl->left = 0; 5712182999Smav ctl->right = 0; 5713182999Smav ctl->enable = 0; 5714182999Smav } 5715182999Smav for (k = devinfo->startnode; k < devinfo->endnode; k++) { 5716182999Smav cw = hdac_widget_get(devinfo, k); 5717182999Smav if (cw == NULL || cw->enable == 0) 5718182999Smav continue; 5719182999Smav for (j = 0; j < cw->nconns; j++) { 5720182999Smav if (cw->connsenable[j] && cw->conns[j] == i) { 5721182999Smav cw->connsenable[j] = 0; 5722183097Smav HDA_BOOTHVERBOSE( 5723182999Smav device_printf(devinfo->codec->sc->dev, 5724182999Smav " Disabling connection from output pin " 5725182999Smav "nid %d conn %d cnid %d.\n", 5726182999Smav k, j, i); 5727182999Smav ); 5728182999Smav if (cw->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5729182999Smav cw->nconns > 1) 5730182999Smav continue; 5731182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, k, 5732182999Smav HDA_CTL_IN, j, 1); 5733182999Smav if (ctl && ctl->enable) { 5734182999Smav ctl->forcemute = 1; 5735182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5736182999Smav ctl->left = 0; 5737182999Smav ctl->right = 0; 5738182999Smav ctl->enable = 0; 5739182999Smav } 5740182999Smav } 5741182999Smav } 5742182999Smav } 5743162922Sariff } 5744162922Sariff } 5745162922Sariff} 5746162922Sariff 5747182999Smavstatic void 5748182999Smavhdac_audio_disable_notselected(struct hdac_devinfo *devinfo) 5749162922Sariff{ 5750182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5751182999Smav struct hdac_widget *w; 5752182999Smav int i, j; 5753182999Smav 5754182999Smav /* On playback path we can safely disable all unseleted inputs. */ 5755182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5756182999Smav w = hdac_widget_get(devinfo, i); 5757182999Smav if (w == NULL || w->enable == 0) 5758182999Smav continue; 5759182999Smav if (w->nconns <= 1) 5760182999Smav continue; 5761182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5762182999Smav continue; 5763182999Smav if (w->bindas < 0 || as[w->bindas].dir == HDA_CTL_IN) 5764182999Smav continue; 5765182999Smav for (j = 0; j < w->nconns; j++) { 5766182999Smav if (w->connsenable[j] == 0) 5767182999Smav continue; 5768182999Smav if (w->selconn < 0 || w->selconn == j) 5769182999Smav continue; 5770182999Smav w->connsenable[j] = 0; 5771183097Smav HDA_BOOTHVERBOSE( 5772182999Smav device_printf(devinfo->codec->sc->dev, 5773182999Smav " Disabling unselected connection " 5774182999Smav "nid %d conn %d.\n", 5775182999Smav i, j); 5776182999Smav ); 5777182999Smav } 5778182999Smav } 5779182999Smav} 5780182999Smav 5781182999Smavstatic void 5782182999Smavhdac_audio_disable_crossas(struct hdac_devinfo *devinfo) 5783182999Smav{ 5784202789Smav struct hdac_audio_as *ases = devinfo->function.audio.as; 5785162922Sariff struct hdac_widget *w, *cw; 5786162922Sariff struct hdac_audio_ctl *ctl; 5787182999Smav int i, j; 5788162922Sariff 5789187052Smav /* Disable crossassociatement and unwanted crosschannel connections. */ 5790182999Smav /* ... using selectors */ 5791182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5792182999Smav w = hdac_widget_get(devinfo, i); 5793182999Smav if (w == NULL || w->enable == 0) 5794182999Smav continue; 5795182999Smav if (w->nconns <= 1) 5796182999Smav continue; 5797182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5798182999Smav continue; 5799182999Smav if (w->bindas == -2) 5800182999Smav continue; 5801182999Smav for (j = 0; j < w->nconns; j++) { 5802182999Smav if (w->connsenable[j] == 0) 5803182999Smav continue; 5804182999Smav cw = hdac_widget_get(devinfo, w->conns[j]); 5805182999Smav if (cw == NULL || w->enable == 0) 5806182999Smav continue; 5807202789Smav if (cw->bindas == -2 || 5808202789Smav ((w->pflags & HDA_ADC_MONITOR) && 5809202789Smav cw->bindas >= 0 && 5810202789Smav ases[cw->bindas].dir == HDA_CTL_IN)) 5811182999Smav continue; 5812187052Smav if (w->bindas == cw->bindas && 5813187052Smav (w->bindseqmask & cw->bindseqmask) != 0) 5814187052Smav continue; 5815182999Smav w->connsenable[j] = 0; 5816183097Smav HDA_BOOTHVERBOSE( 5817182999Smav device_printf(devinfo->codec->sc->dev, 5818182999Smav " Disabling crossassociatement connection " 5819182999Smav "nid %d conn %d cnid %d.\n", 5820182999Smav i, j, cw->nid); 5821182999Smav ); 5822182999Smav } 5823182999Smav } 5824182999Smav /* ... using controls */ 5825182999Smav i = 0; 5826182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5827182999Smav if (ctl->enable == 0 || ctl->childwidget == NULL) 5828182999Smav continue; 5829202789Smav if (ctl->widget->bindas == -2) 5830182999Smav continue; 5831202789Smav if (ctl->childwidget->bindas == -2 || 5832202789Smav ((ctl->widget->pflags & HDA_ADC_MONITOR) && 5833202789Smav ctl->childwidget->bindas >= 0 && 5834202789Smav ases[ctl->childwidget->bindas].dir == HDA_CTL_IN)) 5835202789Smav continue; 5836187052Smav if (ctl->widget->bindas != ctl->childwidget->bindas || 5837187052Smav (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) == 0) { 5838182999Smav ctl->forcemute = 1; 5839182999Smav ctl->muted = HDA_AMP_MUTE_ALL; 5840182999Smav ctl->left = 0; 5841182999Smav ctl->right = 0; 5842182999Smav ctl->enable = 0; 5843182999Smav if (ctl->ndir == HDA_CTL_IN) 5844182999Smav ctl->widget->connsenable[ctl->index] = 0; 5845183097Smav HDA_BOOTHVERBOSE( 5846182999Smav device_printf(devinfo->codec->sc->dev, 5847182999Smav " Disabling crossassociatement connection " 5848182999Smav "ctl %d nid %d cnid %d.\n", i, 5849182999Smav ctl->widget->nid, 5850182999Smav ctl->childwidget->nid); 5851182999Smav ); 5852182999Smav } 5853182999Smav } 5854182999Smav 5855182999Smav} 5856182999Smav 5857182999Smav#define HDA_CTL_GIVE(ctl) ((ctl)->step?1:0) 5858182999Smav 5859182999Smav/* 5860182999Smav * Find controls to control amplification for source. 5861182999Smav */ 5862182999Smavstatic int 5863182999Smavhdac_audio_ctl_source_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5864182999Smav int ossdev, int ctlable, int depth, int need) 5865182999Smav{ 5866182999Smav struct hdac_widget *w, *wc; 5867182999Smav struct hdac_audio_ctl *ctl; 5868182999Smav int i, j, conns = 0, rneed; 5869182999Smav 5870162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5871182999Smav return (need); 5872162922Sariff 5873162922Sariff w = hdac_widget_get(devinfo, nid); 5874162922Sariff if (w == NULL || w->enable == 0) 5875182999Smav return (need); 5876182999Smav 5877182999Smav /* Count number of active inputs. */ 5878182999Smav if (depth > 0) { 5879182999Smav for (j = 0; j < w->nconns; j++) { 5880182999Smav if (w->connsenable[j]) 5881182999Smav conns++; 5882162922Sariff } 5883162922Sariff } 5884182999Smav 5885182999Smav /* If this is not a first step - use input mixer. 5886182999Smav Pins have common input ctl so care must be taken. */ 5887182999Smav if (depth > 0 && ctlable && (conns == 1 || 5888182999Smav w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) { 5889182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_IN, 5890182999Smav index, 1); 5891182999Smav if (ctl) { 5892182999Smav if (HDA_CTL_GIVE(ctl) & need) 5893182999Smav ctl->ossmask |= (1 << ossdev); 5894182999Smav else 5895182999Smav ctl->possmask |= (1 << ossdev); 5896182999Smav need &= ~HDA_CTL_GIVE(ctl); 5897182999Smav } 5898182999Smav } 5899182999Smav 5900182999Smav /* If widget has own ossdev - not traverse it. 5901182999Smav It will be traversed on it's own. */ 5902182999Smav if (w->ossdev >= 0 && depth > 0) 5903182999Smav return (need); 5904182999Smav 5905182999Smav /* We must not traverse pin */ 5906182999Smav if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 5907182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5908182999Smav depth > 0) 5909182999Smav return (need); 5910182999Smav 5911182999Smav /* record that this widget exports such signal, */ 5912182999Smav w->ossmask |= (1 << ossdev); 5913182999Smav 5914182999Smav /* If signals mixed, we can't assign controls farther. 5915182999Smav * Ignore this on depth zero. Caller must knows why. 5916182999Smav * Ignore this for static selectors if this input selected. 5917182999Smav */ 5918182999Smav if (conns > 1) 5919182999Smav ctlable = 0; 5920182999Smav 5921182999Smav if (ctlable) { 5922182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, HDA_CTL_OUT, -1, 1); 5923182999Smav if (ctl) { 5924182999Smav if (HDA_CTL_GIVE(ctl) & need) 5925182999Smav ctl->ossmask |= (1 << ossdev); 5926182999Smav else 5927182999Smav ctl->possmask |= (1 << ossdev); 5928182999Smav need &= ~HDA_CTL_GIVE(ctl); 5929182999Smav } 5930182999Smav } 5931182999Smav 5932182999Smav rneed = 0; 5933182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5934182999Smav wc = hdac_widget_get(devinfo, i); 5935182999Smav if (wc == NULL || wc->enable == 0) 5936162922Sariff continue; 5937182999Smav for (j = 0; j < wc->nconns; j++) { 5938182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) { 5939182999Smav rneed |= hdac_audio_ctl_source_amp(devinfo, 5940182999Smav wc->nid, j, ossdev, ctlable, depth + 1, need); 5941182999Smav } 5942162922Sariff } 5943162922Sariff } 5944182999Smav rneed &= need; 5945182999Smav 5946182999Smav return (rneed); 5947162922Sariff} 5948162922Sariff 5949182999Smav/* 5950182999Smav * Find controls to control amplification for destination. 5951182999Smav */ 5952182999Smavstatic void 5953202789Smavhdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, int index, 5954182999Smav int ossdev, int depth, int need) 5955162922Sariff{ 5956182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 5957182999Smav struct hdac_widget *w, *wc; 5958182999Smav struct hdac_audio_ctl *ctl; 5959182999Smav int i, j, consumers; 5960182999Smav 5961162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 5962182999Smav return; 5963162922Sariff 5964162922Sariff w = hdac_widget_get(devinfo, nid); 5965162922Sariff if (w == NULL || w->enable == 0) 5966182999Smav return; 5967182999Smav 5968182999Smav if (depth > 0) { 5969182999Smav /* If this node produce output for several consumers, 5970182999Smav we can't touch it. */ 5971182999Smav consumers = 0; 5972182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5973182999Smav wc = hdac_widget_get(devinfo, i); 5974182999Smav if (wc == NULL || wc->enable == 0) 5975182999Smav continue; 5976182999Smav for (j = 0; j < wc->nconns; j++) { 5977182999Smav if (wc->connsenable[j] && wc->conns[j] == nid) 5978182999Smav consumers++; 5979182999Smav } 5980182999Smav } 5981182999Smav /* The only exception is if real HP redirection is configured 5982182999Smav and this is a duplication point. 5983182999Smav XXX: Actually exception is not completely correct. 5984182999Smav XXX: Duplication point check is not perfect. */ 5985182999Smav if ((consumers == 2 && (w->bindas < 0 || 5986182999Smav as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir || 5987182999Smav (w->bindseqmask & (1 << 15)) == 0)) || 5988182999Smav consumers > 2) 5989182999Smav return; 5990182999Smav 5991182999Smav /* Else use it's output mixer. */ 5992182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 5993182999Smav HDA_CTL_OUT, -1, 1); 5994182999Smav if (ctl) { 5995182999Smav if (HDA_CTL_GIVE(ctl) & need) 5996182999Smav ctl->ossmask |= (1 << ossdev); 5997182999Smav else 5998182999Smav ctl->possmask |= (1 << ossdev); 5999182999Smav need &= ~HDA_CTL_GIVE(ctl); 6000182999Smav } 6001182999Smav } 6002182999Smav 6003182999Smav /* We must not traverse pin */ 6004182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6005182999Smav depth > 0) 6006182999Smav return; 6007182999Smav 6008162922Sariff for (i = 0; i < w->nconns; i++) { 6009182999Smav int tneed = need; 6010182999Smav if (w->connsenable[i] == 0) 6011162922Sariff continue; 6012202789Smav if (index >= 0 && i != index) 6013202789Smav continue; 6014182999Smav ctl = hdac_audio_ctl_amp_get(devinfo, w->nid, 6015182999Smav HDA_CTL_IN, i, 1); 6016182999Smav if (ctl) { 6017182999Smav if (HDA_CTL_GIVE(ctl) & tneed) 6018182999Smav ctl->ossmask |= (1 << ossdev); 6019182999Smav else 6020182999Smav ctl->possmask |= (1 << ossdev); 6021182999Smav tneed &= ~HDA_CTL_GIVE(ctl); 6022162922Sariff } 6023202789Smav hdac_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev, 6024182999Smav depth + 1, tneed); 6025162922Sariff } 6026162922Sariff} 6027162922Sariff 6028182999Smav/* 6029182999Smav * Assign OSS names to sound sources 6030182999Smav */ 6031182999Smavstatic void 6032182999Smavhdac_audio_assign_names(struct hdac_devinfo *devinfo) 6033162922Sariff{ 6034182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6035182999Smav struct hdac_widget *w; 6036182999Smav int i, j; 6037182999Smav int type = -1, use, used = 0; 6038182999Smav static const int types[7][13] = { 6039182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6040182999Smav SOUND_MIXER_LINE3, -1 }, /* line */ 6041182999Smav { SOUND_MIXER_MONITOR, SOUND_MIXER_MIC, -1 }, /* int mic */ 6042182999Smav { SOUND_MIXER_MIC, SOUND_MIXER_MONITOR, -1 }, /* ext mic */ 6043182999Smav { SOUND_MIXER_CD, -1 }, /* cd */ 6044182999Smav { SOUND_MIXER_SPEAKER, -1 }, /* speaker */ 6045182999Smav { SOUND_MIXER_DIGITAL1, SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, 6046182999Smav -1 }, /* digital */ 6047182999Smav { SOUND_MIXER_LINE, SOUND_MIXER_LINE1, SOUND_MIXER_LINE2, 6048182999Smav SOUND_MIXER_LINE3, SOUND_MIXER_PHONEIN, SOUND_MIXER_PHONEOUT, 6049182999Smav SOUND_MIXER_VIDEO, SOUND_MIXER_RADIO, SOUND_MIXER_DIGITAL1, 6050182999Smav SOUND_MIXER_DIGITAL2, SOUND_MIXER_DIGITAL3, SOUND_MIXER_MONITOR, 6051182999Smav -1 } /* others */ 6052182999Smav }; 6053162922Sariff 6054182999Smav /* Surely known names */ 6055162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6056162922Sariff w = hdac_widget_get(devinfo, i); 6057162922Sariff if (w == NULL || w->enable == 0) 6058162922Sariff continue; 6059182999Smav if (w->bindas == -1) 6060182999Smav continue; 6061182999Smav use = -1; 6062182999Smav switch (w->type) { 6063182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 6064182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6065182999Smav break; 6066182999Smav type = -1; 6067182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6068182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 6069182999Smav type = 0; 6070182999Smav break; 6071182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6072182999Smav if ((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) 6073182999Smav == HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 6074182999Smav break; 6075182999Smav type = 1; 6076182999Smav break; 6077182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 6078182999Smav type = 3; 6079182999Smav break; 6080182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6081182999Smav type = 4; 6082182999Smav break; 6083182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 6084182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 6085182999Smav type = 5; 6086182999Smav break; 6087182999Smav } 6088182999Smav if (type == -1) 6089182999Smav break; 6090182999Smav j = 0; 6091182999Smav while (types[type][j] >= 0 && 6092182999Smav (used & (1 << types[type][j])) != 0) { 6093182999Smav j++; 6094182999Smav } 6095182999Smav if (types[type][j] >= 0) 6096182999Smav use = types[type][j]; 6097182999Smav break; 6098182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 6099182999Smav use = SOUND_MIXER_PCM; 6100182999Smav break; 6101182999Smav case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 6102182999Smav use = SOUND_MIXER_SPEAKER; 6103182999Smav break; 6104182999Smav default: 6105182999Smav break; 6106182999Smav } 6107182999Smav if (use >= 0) { 6108182999Smav w->ossdev = use; 6109182999Smav used |= (1 << use); 6110182999Smav } 6111182999Smav } 6112182999Smav /* Semi-known names */ 6113182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6114182999Smav w = hdac_widget_get(devinfo, i); 6115182999Smav if (w == NULL || w->enable == 0) 6116182999Smav continue; 6117182999Smav if (w->ossdev >= 0) 6118182999Smav continue; 6119182999Smav if (w->bindas == -1) 6120182999Smav continue; 6121162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6122162922Sariff continue; 6123182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6124162922Sariff continue; 6125182999Smav type = -1; 6126182999Smav switch (w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 6127182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 6128182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 6129182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 6130182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 6131182999Smav type = 0; 6132182999Smav break; 6133182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 6134182999Smav type = 2; 6135182999Smav break; 6136182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 6137182999Smav case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 6138182999Smav type = 5; 6139182999Smav break; 6140182999Smav } 6141182999Smav if (type == -1) 6142182999Smav break; 6143182999Smav j = 0; 6144182999Smav while (types[type][j] >= 0 && 6145182999Smav (used & (1 << types[type][j])) != 0) { 6146182999Smav j++; 6147182999Smav } 6148182999Smav if (types[type][j] >= 0) { 6149182999Smav w->ossdev = types[type][j]; 6150182999Smav used |= (1 << types[type][j]); 6151182999Smav } 6152182999Smav } 6153182999Smav /* Others */ 6154182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6155182999Smav w = hdac_widget_get(devinfo, i); 6156182999Smav if (w == NULL || w->enable == 0) 6157162922Sariff continue; 6158182999Smav if (w->ossdev >= 0) 6159182999Smav continue; 6160182999Smav if (w->bindas == -1) 6161182999Smav continue; 6162182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6163182999Smav continue; 6164182999Smav if (as[w->bindas].dir == HDA_CTL_OUT) 6165182999Smav continue; 6166182999Smav j = 0; 6167182999Smav while (types[6][j] >= 0 && 6168182999Smav (used & (1 << types[6][j])) != 0) { 6169182999Smav j++; 6170162922Sariff } 6171182999Smav if (types[6][j] >= 0) { 6172182999Smav w->ossdev = types[6][j]; 6173182999Smav used |= (1 << types[6][j]); 6174182999Smav } 6175162922Sariff } 6176162922Sariff} 6177162922Sariff 6178162922Sariffstatic void 6179162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 6180162922Sariff{ 6181182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6182182999Smav int j, res; 6183162922Sariff 6184182999Smav /* Trace all associations in order of their numbers, */ 6185182999Smav for (j = 0; j < devinfo->function.audio.ascnt; j++) { 6186182999Smav if (as[j].enable == 0) 6187182999Smav continue; 6188163057Sariff HDA_BOOTVERBOSE( 6189162922Sariff device_printf(devinfo->codec->sc->dev, 6190182999Smav "Tracing association %d (%d)\n", j, as[j].index); 6191162922Sariff ); 6192182999Smav if (as[j].dir == HDA_CTL_OUT) { 6193182999Smavretry: 6194182999Smav res = hdac_audio_trace_as_out(devinfo, j, 0); 6195182999Smav if (res == 0 && as[j].hpredir >= 0 && 6196182999Smav as[j].fakeredir == 0) { 6197182999Smav /* If codec can't do analog HP redirection 6198182999Smav try to make it using one more DAC. */ 6199182999Smav as[j].fakeredir = 1; 6200182999Smav goto retry; 6201182999Smav } 6202182999Smav } else { 6203182999Smav res = hdac_audio_trace_as_in(devinfo, j); 6204182999Smav } 6205182999Smav if (res) { 6206182999Smav HDA_BOOTVERBOSE( 6207182999Smav device_printf(devinfo->codec->sc->dev, 6208188510Smav "Association %d (%d) trace succeeded\n", 6209182999Smav j, as[j].index); 6210182999Smav ); 6211182999Smav } else { 6212182999Smav HDA_BOOTVERBOSE( 6213182999Smav device_printf(devinfo->codec->sc->dev, 6214182999Smav "Association %d (%d) trace failed\n", 6215182999Smav j, as[j].index); 6216182999Smav ); 6217182999Smav as[j].enable = 0; 6218182999Smav } 6219162922Sariff } 6220162922Sariff 6221182999Smav /* Trace mixer and beeper pseudo associations. */ 6222182999Smav hdac_audio_trace_as_extra(devinfo); 6223182999Smav} 6224162922Sariff 6225182999Smavstatic void 6226182999Smavhdac_audio_assign_mixers(struct hdac_devinfo *devinfo) 6227182999Smav{ 6228182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6229182999Smav struct hdac_audio_ctl *ctl; 6230202789Smav struct hdac_widget *w, *cw; 6231202789Smav int i, j; 6232162922Sariff 6233182999Smav /* Assign mixers to the tree. */ 6234162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6235162922Sariff w = hdac_widget_get(devinfo, i); 6236162922Sariff if (w == NULL || w->enable == 0) 6237162922Sariff continue; 6238182999Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 6239182999Smav w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET || 6240182999Smav (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6241182999Smav as[w->bindas].dir == HDA_CTL_IN)) { 6242182999Smav if (w->ossdev < 0) 6243182999Smav continue; 6244182999Smav hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6245182999Smav w->ossdev, 1, 0, 1); 6246182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 6247202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6248182999Smav SOUND_MIXER_RECLEV, 0, 1); 6249182999Smav } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6250182999Smav as[w->bindas].dir == HDA_CTL_OUT) { 6251202789Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6252182999Smav SOUND_MIXER_VOLUME, 0, 1); 6253162922Sariff } 6254202796Smav if (w->ossdev == SOUND_MIXER_IMIX) { 6255202796Smav if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1, 6256202796Smav w->ossdev, 1, 0, 1)) { 6257202796Smav /* If we are unable to control input monitor 6258202796Smav as source - try to control it as destination. */ 6259202796Smav hdac_audio_ctl_dest_amp(devinfo, w->nid, -1, 6260202796Smav w->ossdev, 0, 1); 6261202796Smav } 6262202796Smav } 6263202789Smav if (w->pflags & HDA_ADC_MONITOR) { 6264202789Smav for (j = 0; j < w->nconns; j++) { 6265202789Smav if (!w->connsenable[j]) 6266202789Smav continue; 6267202789Smav cw = hdac_widget_get(devinfo, w->conns[j]); 6268202789Smav if (cw == NULL || cw->enable == 0) 6269202789Smav continue; 6270202789Smav if (cw->bindas == -1) 6271202789Smav continue; 6272202789Smav if (cw->bindas >= 0 && 6273202789Smav as[cw->bindas].dir != HDA_CTL_IN) 6274202789Smav continue; 6275202789Smav hdac_audio_ctl_dest_amp(devinfo, 6276202796Smav w->nid, j, SOUND_MIXER_IGAIN, 0, 1); 6277202789Smav } 6278202789Smav } 6279162922Sariff } 6280182999Smav /* Treat unrequired as possible. */ 6281182999Smav i = 0; 6282182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6283182999Smav if (ctl->ossmask == 0) 6284182999Smav ctl->ossmask = ctl->possmask; 6285182999Smav } 6286182999Smav} 6287162922Sariff 6288182999Smavstatic void 6289182999Smavhdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo) 6290182999Smav{ 6291182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6292182999Smav struct hdac_widget *w; 6293182999Smav uint32_t pincap; 6294182999Smav int i; 6295182999Smav 6296182999Smav for (i = 0; i < devinfo->nodecnt; i++) { 6297182999Smav w = &devinfo->widget[i]; 6298182999Smav if (w == NULL) 6299162922Sariff continue; 6300182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6301162922Sariff continue; 6302182999Smav 6303182999Smav pincap = w->wclass.pin.cap; 6304182999Smav 6305182999Smav /* Disable everything. */ 6306182999Smav w->wclass.pin.ctrl &= ~( 6307182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 6308182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 6309182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 6310182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 6311182999Smav 6312182999Smav if (w->enable == 0 || 6313182999Smav w->bindas < 0 || as[w->bindas].enable == 0) { 6314182999Smav /* Pin is unused so left it disabled. */ 6315182999Smav continue; 6316182999Smav } else if (as[w->bindas].dir == HDA_CTL_IN) { 6317182999Smav /* Input pin, configure for input. */ 6318182999Smav if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6319182999Smav w->wclass.pin.ctrl |= 6320182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 6321182999Smav 6322182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 6323182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6324182999Smav w->wclass.pin.ctrl |= 6325182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6326182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6327182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 6328182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6329182999Smav w->wclass.pin.ctrl |= 6330182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6331182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6332182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 6333182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6334182999Smav w->wclass.pin.ctrl |= 6335182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6336182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6337182999Smav } else { 6338182999Smav /* Output pin, configure for output. */ 6339182999Smav if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6340182999Smav w->wclass.pin.ctrl |= 6341182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 6342182999Smav 6343182999Smav if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap) && 6344182999Smav (w->wclass.pin.config & 6345182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 6346182999Smav HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 6347182999Smav w->wclass.pin.ctrl |= 6348182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 6349182999Smav 6350182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 6351182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6352182999Smav w->wclass.pin.ctrl |= 6353182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6354182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 6355182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 6356182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6357182999Smav w->wclass.pin.ctrl |= 6358182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6359182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 6360182999Smav else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 6361182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6362182999Smav w->wclass.pin.ctrl |= 6363182999Smav HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 6364182999Smav HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 6365182999Smav } 6366162922Sariff } 6367162922Sariff} 6368162922Sariff 6369162922Sariffstatic void 6370187154Smavhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 6371187154Smav{ 6372187154Smav struct hdac_audio_ctl *ctl; 6373187154Smav int i, z; 6374187154Smav 6375187154Smav i = 0; 6376187154Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6377187154Smav if (ctl->enable == 0 || ctl->ossmask != 0) { 6378187154Smav /* Mute disabled and mixer controllable controls. 6379187154Smav * Last will be initialized by mixer_init(). 6380187154Smav * This expected to reduce click on startup. */ 6381187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0); 6382187154Smav continue; 6383187154Smav } 6384187154Smav /* Init fixed controls to 0dB amplification. */ 6385187154Smav z = ctl->offset; 6386187154Smav if (z > ctl->step) 6387187154Smav z = ctl->step; 6388187154Smav hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z); 6389187154Smav } 6390187154Smav} 6391187154Smav 6392187154Smavstatic void 6393182999Smavhdac_audio_commit(struct hdac_devinfo *devinfo) 6394162922Sariff{ 6395162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6396162922Sariff struct hdac_widget *w; 6397164750Sariff nid_t cad; 6398182999Smav uint32_t gdata, gmask, gdir; 6399182999Smav int commitgpio, numgpio; 6400164750Sariff int i; 6401162922Sariff 6402162922Sariff cad = devinfo->codec->cad; 6403162922Sariff 6404182999Smav if (sc->pci_subvendor == APPLE_INTEL_MAC) 6405182999Smav hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 6406182999Smav 0x7e7, 0), cad); 6407169277Sariff 6408187154Smav /* Commit controls. */ 6409187154Smav hdac_audio_ctl_commit(devinfo); 6410187154Smav 6411187154Smav /* Commit selectors, pins and EAPD. */ 6412187154Smav for (i = 0; i < devinfo->nodecnt; i++) { 6413187154Smav w = &devinfo->widget[i]; 6414187154Smav if (w == NULL) 6415187154Smav continue; 6416187154Smav if (w->selconn == -1) 6417187154Smav w->selconn = 0; 6418187154Smav if (w->nconns > 0) 6419187154Smav hdac_widget_connection_select(w, w->selconn); 6420187154Smav if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 6421187154Smav hdac_command(sc, 6422187154Smav HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 6423187154Smav w->wclass.pin.ctrl), cad); 6424187154Smav } 6425187154Smav if (w->param.eapdbtl != HDAC_INVALID) { 6426187154Smav uint32_t val; 6427187154Smav 6428187154Smav val = w->param.eapdbtl; 6429187154Smav if (devinfo->function.audio.quirks & 6430187154Smav HDA_QUIRK_EAPDINV) 6431187154Smav val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 6432187154Smav hdac_command(sc, 6433187154Smav HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 6434187154Smav val), cad); 6435187154Smav } 6436187154Smav } 6437187154Smav 6438187154Smav /* Commit GPIOs. */ 6439182999Smav gdata = 0; 6440182999Smav gmask = 0; 6441182999Smav gdir = 0; 6442182999Smav commitgpio = 0; 6443182999Smav numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 6444182999Smav devinfo->function.audio.gpio); 6445166796Sariff 6446182999Smav if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 6447182999Smav commitgpio = (numgpio > 0) ? 1 : 0; 6448182999Smav else { 6449182999Smav for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 6450182999Smav if (!(devinfo->function.audio.quirks & 6451182999Smav (1 << i))) 6452182999Smav continue; 6453182999Smav if (commitgpio == 0) { 6454182999Smav commitgpio = 1; 6455182999Smav HDA_BOOTVERBOSE( 6456182999Smav gdata = hdac_command(sc, 6457182999Smav HDA_CMD_GET_GPIO_DATA(cad, 6458182999Smav devinfo->nid), cad); 6459182999Smav gmask = hdac_command(sc, 6460182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 6461182999Smav devinfo->nid), cad); 6462182999Smav gdir = hdac_command(sc, 6463182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, 6464182999Smav devinfo->nid), cad); 6465182999Smav device_printf(sc->dev, 6466182999Smav "GPIO init: data=0x%08x " 6467182999Smav "mask=0x%08x dir=0x%08x\n", 6468182999Smav gdata, gmask, gdir); 6469182999Smav gdata = 0; 6470182999Smav gmask = 0; 6471182999Smav gdir = 0; 6472182999Smav ); 6473165039Sariff } 6474182999Smav gdata |= 1 << i; 6475182999Smav gmask |= 1 << i; 6476182999Smav gdir |= 1 << i; 6477165039Sariff } 6478182999Smav } 6479165039Sariff 6480182999Smav if (commitgpio != 0) { 6481182999Smav HDA_BOOTVERBOSE( 6482182999Smav device_printf(sc->dev, 6483182999Smav "GPIO commit: data=0x%08x mask=0x%08x " 6484182999Smav "dir=0x%08x\n", 6485182999Smav gdata, gmask, gdir); 6486182999Smav ); 6487182999Smav hdac_command(sc, 6488182999Smav HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 6489182999Smav gmask), cad); 6490182999Smav hdac_command(sc, 6491182999Smav HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 6492182999Smav gdir), cad); 6493182999Smav hdac_command(sc, 6494182999Smav HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 6495182999Smav gdata), cad); 6496162922Sariff } 6497162922Sariff} 6498162922Sariff 6499162922Sariffstatic void 6500182999Smavhdac_powerup(struct hdac_devinfo *devinfo) 6501182999Smav{ 6502182999Smav struct hdac_softc *sc = devinfo->codec->sc; 6503182999Smav nid_t cad = devinfo->codec->cad; 6504182999Smav int i; 6505182999Smav 6506182999Smav hdac_command(sc, 6507182999Smav HDA_CMD_SET_POWER_STATE(cad, 6508182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D0), 6509182999Smav cad); 6510182999Smav DELAY(100); 6511182999Smav 6512182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6513182999Smav hdac_command(sc, 6514182999Smav HDA_CMD_SET_POWER_STATE(cad, 6515182999Smav i, HDA_CMD_POWER_STATE_D0), 6516182999Smav cad); 6517182999Smav } 6518182999Smav DELAY(1000); 6519182999Smav} 6520182999Smav 6521162922Sariffstatic int 6522182999Smavhdac_pcmchannel_setup(struct hdac_chan *ch) 6523162922Sariff{ 6524182999Smav struct hdac_devinfo *devinfo = ch->devinfo; 6525182999Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6526162922Sariff struct hdac_widget *w; 6527182999Smav uint32_t cap, fmtcap, pcmcap; 6528202127Smav int i, j, ret, channels, onlystereo; 6529202127Smav uint16_t pinset; 6530162922Sariff 6531162922Sariff ch->caps = hdac_caps; 6532162922Sariff ch->caps.fmtlist = ch->fmtlist; 6533162922Sariff ch->bit16 = 1; 6534162922Sariff ch->bit32 = 0; 6535162922Sariff ch->pcmrates[0] = 48000; 6536162922Sariff ch->pcmrates[1] = 0; 6537162922Sariff 6538162922Sariff ret = 0; 6539202127Smav channels = 0; 6540202127Smav onlystereo = 1; 6541202127Smav pinset = 0; 6542162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 6543162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 6544162922Sariff 6545202127Smav for (i = 0; i < 16; i++) { 6546182999Smav /* Check as is correct */ 6547182999Smav if (ch->as < 0) 6548182999Smav break; 6549182999Smav /* Cound only present DACs */ 6550182999Smav if (as[ch->as].dacs[i] <= 0) 6551162922Sariff continue; 6552182999Smav /* Ignore duplicates */ 6553182999Smav for (j = 0; j < ret; j++) { 6554182999Smav if (ch->io[j] == as[ch->as].dacs[i]) 6555182999Smav break; 6556182999Smav } 6557182999Smav if (j < ret) 6558162922Sariff continue; 6559182999Smav 6560182999Smav w = hdac_widget_get(devinfo, as[ch->as].dacs[i]); 6561182999Smav if (w == NULL || w->enable == 0) 6562182999Smav continue; 6563162922Sariff cap = w->param.supp_stream_formats; 6564182999Smav if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap) && 6565182999Smav !HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6566162922Sariff continue; 6567202127Smav /* Many CODECs does not declare AC3 support on SPDIF. 6568182999Smav I don't beleave that they doesn't support it! */ 6569182999Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6570182999Smav cap |= HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK; 6571164614Sariff if (ret == 0) { 6572182999Smav fmtcap = cap; 6573164614Sariff pcmcap = w->param.supp_pcm_size_rate; 6574164614Sariff } else { 6575182999Smav fmtcap &= cap; 6576164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 6577164614Sariff } 6578182999Smav ch->io[ret++] = as[ch->as].dacs[i]; 6579202127Smav /* Do not count redirection pin/dac channels. */ 6580202127Smav if (i == 15 && as[ch->as].hpredir >= 0) 6581202127Smav continue; 6582202127Smav channels += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1; 6583202127Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) != 1) 6584202127Smav onlystereo = 0; 6585202127Smav pinset |= (1 << i); 6586162922Sariff } 6587162922Sariff ch->io[ret] = -1; 6588162922Sariff 6589202127Smav if (as[ch->as].fakeredir) 6590202127Smav ret--; 6591202127Smav /* Standard speaks only about stereo pins and playback, ... */ 6592202127Smav if ((!onlystereo) || as[ch->as].dir != HDA_CTL_OUT) 6593202127Smav pinset = 0; 6594202127Smav /* ..., but there it gives us info about speakers layout. */ 6595202127Smav as[ch->as].pinset = pinset; 6596202127Smav 6597162922Sariff ch->supp_stream_formats = fmtcap; 6598162922Sariff ch->supp_pcm_size_rate = pcmcap; 6599162922Sariff 6600162922Sariff /* 6601162922Sariff * 8bit = 0 6602162922Sariff * 16bit = 1 6603162922Sariff * 20bit = 2 6604162922Sariff * 24bit = 3 6605162922Sariff * 32bit = 4 6606162922Sariff */ 6607162922Sariff if (ret > 0) { 6608162922Sariff i = 0; 6609182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(fmtcap)) { 6610182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(pcmcap)) 6611182999Smav ch->bit16 = 1; 6612182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) 6613182999Smav ch->bit16 = 0; 6614182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) 6615182999Smav ch->bit32 = 4; 6616182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) 6617182999Smav ch->bit32 = 3; 6618182999Smav else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) 6619182999Smav ch->bit32 = 2; 6620202127Smav if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) { 6621202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 1, 0); 6622202127Smav if (ch->bit32) 6623202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 1, 0); 6624182999Smav } 6625202127Smav if (channels >= 2) { 6626202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 2, 0); 6627202127Smav if (ch->bit32) 6628202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 2, 0); 6629202127Smav } 6630202127Smav if (channels == 4 || /* Any 4-channel */ 6631202127Smav pinset == 0x0007 || /* 5.1 */ 6632202127Smav pinset == 0x0013 || /* 5.1 */ 6633202127Smav pinset == 0x0017) { /* 7.1 */ 6634202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 4, 0); 6635202127Smav if (ch->bit32) 6636202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 0); 6637202127Smav } 6638202127Smav if (channels == 6 || /* Any 6-channel */ 6639202127Smav pinset == 0x0017) { /* 7.1 */ 6640202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 1); 6641202127Smav if (ch->bit32) 6642202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 1); 6643202127Smav } 6644202127Smav if (channels == 8) { /* Any 8-channel */ 6645202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 8, 1); 6646202127Smav if (ch->bit32) 6647202127Smav ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 8, 1); 6648202127Smav } 6649162922Sariff } 6650182999Smav if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) { 6651193640Sariff ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 2, 0); 6652182999Smav } 6653162922Sariff ch->fmtlist[i] = 0; 6654162922Sariff i = 0; 6655182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(pcmcap)) 6656162922Sariff ch->pcmrates[i++] = 8000; 6657182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(pcmcap)) 6658162922Sariff ch->pcmrates[i++] = 11025; 6659182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(pcmcap)) 6660162922Sariff ch->pcmrates[i++] = 16000; 6661182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(pcmcap)) 6662162922Sariff ch->pcmrates[i++] = 22050; 6663182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(pcmcap)) 6664162922Sariff ch->pcmrates[i++] = 32000; 6665182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(pcmcap)) 6666162922Sariff ch->pcmrates[i++] = 44100; 6667182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(pcmcap)) */ 6668162922Sariff ch->pcmrates[i++] = 48000; 6669182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(pcmcap)) 6670162922Sariff ch->pcmrates[i++] = 88200; 6671182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(pcmcap)) 6672162922Sariff ch->pcmrates[i++] = 96000; 6673182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(pcmcap)) 6674162922Sariff ch->pcmrates[i++] = 176400; 6675182999Smav if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(pcmcap)) 6676162922Sariff ch->pcmrates[i++] = 192000; 6677182999Smav /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(pcmcap)) */ 6678162922Sariff ch->pcmrates[i] = 0; 6679162922Sariff if (i > 0) { 6680162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 6681162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 6682162922Sariff } 6683162922Sariff } 6684162922Sariff 6685162922Sariff return (ret); 6686162922Sariff} 6687162922Sariff 6688162922Sariffstatic void 6689185225Smavhdac_create_pcms(struct hdac_devinfo *devinfo) 6690185225Smav{ 6691185225Smav struct hdac_softc *sc = devinfo->codec->sc; 6692185225Smav struct hdac_audio_as *as = devinfo->function.audio.as; 6693185225Smav int i, j, apdev = 0, ardev = 0, dpdev = 0, drdev = 0; 6694185225Smav 6695185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6696185225Smav if (as[i].enable == 0) 6697185225Smav continue; 6698185225Smav if (as[i].dir == HDA_CTL_IN) { 6699185225Smav if (as[i].digital) 6700185225Smav drdev++; 6701185225Smav else 6702185225Smav ardev++; 6703185225Smav } else { 6704185225Smav if (as[i].digital) 6705185225Smav dpdev++; 6706185225Smav else 6707185225Smav apdev++; 6708185225Smav } 6709185225Smav } 6710185225Smav devinfo->function.audio.num_devs = 6711185225Smav max(ardev, apdev) + max(drdev, dpdev); 6712185225Smav devinfo->function.audio.devs = 6713185225Smav (struct hdac_pcm_devinfo *)malloc( 6714185225Smav devinfo->function.audio.num_devs * sizeof(struct hdac_pcm_devinfo), 6715185225Smav M_HDAC, M_ZERO | M_NOWAIT); 6716185225Smav if (devinfo->function.audio.devs == NULL) { 6717185225Smav device_printf(sc->dev, 6718185225Smav "Unable to allocate memory for devices\n"); 6719185225Smav return; 6720185225Smav } 6721185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6722185225Smav devinfo->function.audio.devs[i].index = i; 6723185225Smav devinfo->function.audio.devs[i].devinfo = devinfo; 6724185225Smav devinfo->function.audio.devs[i].play = -1; 6725185225Smav devinfo->function.audio.devs[i].rec = -1; 6726197611Smav devinfo->function.audio.devs[i].digital = 255; 6727185225Smav } 6728185225Smav for (i = 0; i < devinfo->function.audio.ascnt; i++) { 6729185225Smav if (as[i].enable == 0) 6730185225Smav continue; 6731185225Smav for (j = 0; j < devinfo->function.audio.num_devs; j++) { 6732197611Smav if (devinfo->function.audio.devs[j].digital != 255 && 6733197640Smav (!devinfo->function.audio.devs[j].digital) != 6734197611Smav (!as[i].digital)) 6735185225Smav continue; 6736185225Smav if (as[i].dir == HDA_CTL_IN) { 6737185225Smav if (devinfo->function.audio.devs[j].rec >= 0) 6738185225Smav continue; 6739185225Smav devinfo->function.audio.devs[j].rec 6740185225Smav = as[i].chan; 6741185225Smav } else { 6742185225Smav if (devinfo->function.audio.devs[j].play >= 0) 6743185225Smav continue; 6744185225Smav devinfo->function.audio.devs[j].play 6745185225Smav = as[i].chan; 6746185225Smav } 6747185225Smav sc->chans[as[i].chan].pdevinfo = 6748185225Smav &devinfo->function.audio.devs[j]; 6749185225Smav devinfo->function.audio.devs[j].digital = 6750185225Smav as[i].digital; 6751185225Smav break; 6752185225Smav } 6753185225Smav } 6754185225Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 6755185225Smav struct hdac_pcm_devinfo *pdevinfo = 6756185225Smav &devinfo->function.audio.devs[i]; 6757185225Smav pdevinfo->dev = 6758185225Smav device_add_child(sc->dev, "pcm", -1); 6759185225Smav device_set_ivars(pdevinfo->dev, 6760185225Smav (void *)pdevinfo); 6761185225Smav } 6762185225Smav} 6763185225Smav 6764185225Smavstatic void 6765182999Smavhdac_dump_ctls(struct hdac_pcm_devinfo *pdevinfo, const char *banner, uint32_t flag) 6766162922Sariff{ 6767182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 6768162922Sariff struct hdac_audio_ctl *ctl; 6769162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6770182999Smav char buf[64]; 6771182999Smav int i, j, printed; 6772162922Sariff 6773162922Sariff if (flag == 0) { 6774182999Smav flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM | 6775162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 6776202796Smav SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IGAIN | 6777202796Smav SOUND_MASK_OGAIN | SOUND_MASK_IMIX | SOUND_MASK_MONITOR); 6778162922Sariff } 6779162922Sariff 6780182999Smav for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { 6781182999Smav if ((flag & (1 << j)) == 0) 6782162922Sariff continue; 6783182999Smav i = 0; 6784182999Smav printed = 0; 6785182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6786182999Smav if (ctl->enable == 0 || 6787182999Smav ctl->widget->enable == 0) 6788182999Smav continue; 6789182999Smav if (!((pdevinfo->play >= 0 && 6790182999Smav ctl->widget->bindas == sc->chans[pdevinfo->play].as) || 6791182999Smav (pdevinfo->rec >= 0 && 6792182999Smav ctl->widget->bindas == sc->chans[pdevinfo->rec].as) || 6793182999Smav (ctl->widget->bindas == -2 && pdevinfo->index == 0))) 6794182999Smav continue; 6795182999Smav if ((ctl->ossmask & (1 << j)) == 0) 6796182999Smav continue; 6797182999Smav 6798182999Smav if (printed == 0) { 6799182999Smav device_printf(pdevinfo->dev, "\n"); 6800182999Smav if (banner != NULL) { 6801182999Smav device_printf(pdevinfo->dev, "%s", banner); 6802182999Smav } else { 6803182999Smav device_printf(pdevinfo->dev, "Unknown Ctl"); 6804182999Smav } 6805182999Smav printf(" (OSS: %s)\n", 6806182999Smav hdac_audio_ctl_ossmixer_mask2allname(1 << j, 6807182999Smav buf, sizeof(buf))); 6808182999Smav device_printf(pdevinfo->dev, " |\n"); 6809182999Smav printed = 1; 6810162922Sariff } 6811182999Smav device_printf(pdevinfo->dev, " +- ctl %2d (nid %3d %s", i, 6812182999Smav ctl->widget->nid, 6813182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out"); 6814182999Smav if (ctl->ndir == HDA_CTL_IN && ctl->ndir == ctl->dir) 6815182999Smav printf(" %2d): ", ctl->index); 6816182999Smav else 6817182999Smav printf("): "); 6818182999Smav if (ctl->step > 0) { 6819182999Smav printf("%+d/%+ddB (%d steps)%s\n", 6820182999Smav (0 - ctl->offset) * (ctl->size + 1) / 4, 6821182999Smav (ctl->step - ctl->offset) * (ctl->size + 1) / 4, 6822182999Smav ctl->step + 1, 6823182999Smav ctl->mute?" + mute":""); 6824182999Smav } else 6825182999Smav printf("%s\n", ctl->mute?"mute":""); 6826162922Sariff } 6827162922Sariff } 6828162922Sariff} 6829162922Sariff 6830162922Sariffstatic void 6831182999Smavhdac_dump_audio_formats(device_t dev, uint32_t fcap, uint32_t pcmcap) 6832162922Sariff{ 6833162922Sariff uint32_t cap; 6834162922Sariff 6835162922Sariff cap = fcap; 6836162922Sariff if (cap != 0) { 6837182999Smav device_printf(dev, " Stream cap: 0x%08x\n", cap); 6838183097Smav device_printf(dev, " "); 6839162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 6840162922Sariff printf(" AC3"); 6841162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 6842162922Sariff printf(" FLOAT32"); 6843162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 6844162922Sariff printf(" PCM"); 6845162922Sariff printf("\n"); 6846162922Sariff } 6847162922Sariff cap = pcmcap; 6848162922Sariff if (cap != 0) { 6849182999Smav device_printf(dev, " PCM cap: 0x%08x\n", cap); 6850183097Smav device_printf(dev, " "); 6851162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 6852162922Sariff printf(" 8"); 6853162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 6854162922Sariff printf(" 16"); 6855162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 6856162922Sariff printf(" 20"); 6857162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 6858162922Sariff printf(" 24"); 6859162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 6860162922Sariff printf(" 32"); 6861183097Smav printf(" bits,"); 6862162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 6863162922Sariff printf(" 8"); 6864162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 6865162922Sariff printf(" 11"); 6866162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 6867162922Sariff printf(" 16"); 6868162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 6869162922Sariff printf(" 22"); 6870162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 6871162922Sariff printf(" 32"); 6872162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 6873162922Sariff printf(" 44"); 6874162922Sariff printf(" 48"); 6875162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 6876162922Sariff printf(" 88"); 6877162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 6878162922Sariff printf(" 96"); 6879162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 6880162922Sariff printf(" 176"); 6881162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 6882162922Sariff printf(" 192"); 6883183097Smav printf(" KHz\n"); 6884162922Sariff } 6885162922Sariff} 6886162922Sariff 6887162922Sariffstatic void 6888162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 6889162922Sariff{ 6890183097Smav uint32_t pincap; 6891162922Sariff 6892162922Sariff pincap = w->wclass.pin.cap; 6893162922Sariff 6894162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 6895162922Sariff device_printf(sc->dev, " "); 6896162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 6897162922Sariff printf(" ISC"); 6898162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 6899162922Sariff printf(" TRQD"); 6900162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 6901162922Sariff printf(" PDC"); 6902162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 6903162922Sariff printf(" HP"); 6904162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 6905162922Sariff printf(" OUT"); 6906162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 6907162922Sariff printf(" IN"); 6908162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 6909162922Sariff printf(" BAL"); 6910197611Smav if (HDA_PARAM_PIN_CAP_HDMI(pincap)) 6911197611Smav printf(" HDMI"); 6912165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 6913165069Sariff printf(" VREF["); 6914165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 6915165069Sariff printf(" 50"); 6916165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 6917165069Sariff printf(" 80"); 6918165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 6919165069Sariff printf(" 100"); 6920165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 6921165069Sariff printf(" GROUND"); 6922165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 6923165069Sariff printf(" HIZ"); 6924165069Sariff printf(" ]"); 6925165069Sariff } 6926162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 6927162922Sariff printf(" EAPD"); 6928197611Smav if (HDA_PARAM_PIN_CAP_DP(pincap)) 6929197611Smav printf(" DP"); 6930197611Smav if (HDA_PARAM_PIN_CAP_HBR(pincap)) 6931197611Smav printf(" HBR"); 6932162922Sariff printf("\n"); 6933162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 6934162922Sariff w->wclass.pin.config); 6935162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 6936162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 6937162922Sariff printf(" HP"); 6938162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 6939162922Sariff printf(" IN"); 6940162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 6941162922Sariff printf(" OUT"); 6942182999Smav if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) 6943182999Smav printf(" VREFs"); 6944162922Sariff printf("\n"); 6945162922Sariff} 6946162922Sariff 6947162922Sariffstatic void 6948182999Smavhdac_dump_pin_config(struct hdac_widget *w, uint32_t conf) 6949182999Smav{ 6950182999Smav struct hdac_softc *sc = w->devinfo->codec->sc; 6951182999Smav 6952183097Smav device_printf(sc->dev, " nid %d 0x%08x as %2d seq %2d %13s %5s " 6953182999Smav "jack %2d loc %2d color %7s misc %d%s\n", 6954182999Smav w->nid, conf, 6955182999Smav HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf), 6956182999Smav HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf), 6957182999Smav HDA_DEVS[HDA_CONFIG_DEFAULTCONF_DEVICE(conf)], 6958182999Smav HDA_CONNS[HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf)], 6959182999Smav HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf), 6960182999Smav HDA_CONFIG_DEFAULTCONF_LOCATION(conf), 6961182999Smav HDA_COLORS[HDA_CONFIG_DEFAULTCONF_COLOR(conf)], 6962182999Smav HDA_CONFIG_DEFAULTCONF_MISC(conf), 6963182999Smav (w->enable == 0)?" [DISABLED]":""); 6964182999Smav} 6965182999Smav 6966182999Smavstatic void 6967182999Smavhdac_dump_pin_configs(struct hdac_devinfo *devinfo) 6968182999Smav{ 6969182999Smav struct hdac_widget *w; 6970182999Smav int i; 6971182999Smav 6972182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6973182999Smav w = hdac_widget_get(devinfo, i); 6974182999Smav if (w == NULL) 6975182999Smav continue; 6976182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6977182999Smav continue; 6978182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 6979182999Smav } 6980182999Smav} 6981182999Smav 6982182999Smavstatic void 6983162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 6984162922Sariff{ 6985163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 6986162922Sariff device_printf(sc->dev, " " 6987162922Sariff "mute=%d step=%d size=%d offset=%d\n", 6988162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 6989162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 6990162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 6991162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 6992162922Sariff} 6993162922Sariff 6994162922Sariffstatic void 6995162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 6996162922Sariff{ 6997162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 6998182999Smav static char *ossname[] = SOUND_DEVICE_NAMES; 6999162922Sariff struct hdac_widget *w, *cw; 7000182999Smav char buf[64]; 7001162922Sariff int i, j; 7002162922Sariff 7003162922Sariff device_printf(sc->dev, "\n"); 7004162922Sariff device_printf(sc->dev, "Default Parameter\n"); 7005162922Sariff device_printf(sc->dev, "-----------------\n"); 7006182999Smav hdac_dump_audio_formats(sc->dev, 7007162922Sariff devinfo->function.audio.supp_stream_formats, 7008162922Sariff devinfo->function.audio.supp_pcm_size_rate); 7009162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 7010162922Sariff devinfo->function.audio.inamp_cap); 7011162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 7012162922Sariff devinfo->function.audio.outamp_cap); 7013162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7014162922Sariff w = hdac_widget_get(devinfo, i); 7015162922Sariff if (w == NULL) { 7016162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 7017162922Sariff continue; 7018162922Sariff } 7019162922Sariff device_printf(sc->dev, "\n"); 7020183097Smav device_printf(sc->dev, " nid: %d%s\n", w->nid, 7021162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 7022183097Smav device_printf(sc->dev, " Name: %s\n", w->name); 7023183097Smav device_printf(sc->dev, " Widget cap: 0x%08x\n", 7024162922Sariff w->param.widget_cap); 7025183097Smav if (w->param.widget_cap & 0x0ee1) { 7026183097Smav device_printf(sc->dev, " "); 7027183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(w->param.widget_cap)) 7028183097Smav printf(" LRSWAP"); 7029183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(w->param.widget_cap)) 7030183097Smav printf(" PWR"); 7031183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 7032183097Smav printf(" DIGITAL"); 7033183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 7034183097Smav printf(" UNSOL"); 7035183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap)) 7036183097Smav printf(" PROC"); 7037183097Smav if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) 7038183097Smav printf(" STRIPE"); 7039197611Smav j = HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap); 7040197611Smav if (j == 1) 7041183097Smav printf(" STEREO"); 7042197611Smav else if (j > 1) 7043197611Smav printf(" %dCH", j + 1); 7044183097Smav printf("\n"); 7045183097Smav } 7046183097Smav if (w->bindas != -1) { 7047183097Smav device_printf(sc->dev, " Association: %d (0x%08x)\n", 7048183097Smav w->bindas, w->bindseqmask); 7049183097Smav } 7050183097Smav if (w->ossmask != 0 || w->ossdev >= 0) { 7051183097Smav device_printf(sc->dev, " OSS: %s", 7052183097Smav hdac_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf))); 7053183097Smav if (w->ossdev >= 0) 7054183097Smav printf(" (%s)", ossname[w->ossdev]); 7055183097Smav printf("\n"); 7056183097Smav } 7057162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 7058162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 7059182999Smav hdac_dump_audio_formats(sc->dev, 7060162922Sariff w->param.supp_stream_formats, 7061162922Sariff w->param.supp_pcm_size_rate); 7062162922Sariff } else if (w->type == 7063162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7064162922Sariff hdac_dump_pin(sc, w); 7065162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 7066162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 7067162922Sariff w->param.eapdbtl); 7068163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 7069163057Sariff w->param.outamp_cap != 0) 7070162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 7071163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 7072163057Sariff w->param.inamp_cap != 0) 7073162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 7074183097Smav if (w->nconns > 0) { 7075183097Smav device_printf(sc->dev, " connections: %d\n", w->nconns); 7076182999Smav device_printf(sc->dev, " |\n"); 7077183097Smav } 7078162922Sariff for (j = 0; j < w->nconns; j++) { 7079162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 7080182999Smav device_printf(sc->dev, " + %s<- nid=%d [%s]", 7081182999Smav (w->connsenable[j] == 0)?"[DISABLED] ":"", 7082162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 7083162922Sariff if (cw == NULL) 7084162922Sariff printf(" [UNKNOWN]"); 7085162922Sariff else if (cw->enable == 0) 7086162922Sariff printf(" [DISABLED]"); 7087162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 7088162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 7089162922Sariff printf(" (selected)"); 7090162922Sariff printf("\n"); 7091162922Sariff } 7092162922Sariff } 7093162922Sariff 7094162922Sariff} 7095162922Sariff 7096182999Smavstatic void 7097182999Smavhdac_dump_dst_nid(struct hdac_pcm_devinfo *pdevinfo, nid_t nid, int depth) 7098163057Sariff{ 7099182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7100163057Sariff struct hdac_widget *w, *cw; 7101182999Smav char buf[64]; 7102182999Smav int i, printed = 0; 7103163057Sariff 7104163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 7105182999Smav return; 7106163057Sariff 7107163057Sariff w = hdac_widget_get(devinfo, nid); 7108182999Smav if (w == NULL || w->enable == 0) 7109182999Smav return; 7110163057Sariff 7111182999Smav if (depth == 0) 7112182999Smav device_printf(pdevinfo->dev, "%*s", 4, ""); 7113182999Smav else 7114182999Smav device_printf(pdevinfo->dev, "%*s + <- ", 4 + (depth - 1) * 7, ""); 7115182999Smav printf("nid=%d [%s]", w->nid, w->name); 7116163057Sariff 7117182999Smav if (depth > 0) { 7118182999Smav if (w->ossmask == 0) { 7119182999Smav printf("\n"); 7120182999Smav return; 7121163057Sariff } 7122182999Smav printf(" [src: %s]", 7123182999Smav hdac_audio_ctl_ossmixer_mask2allname( 7124182999Smav w->ossmask, buf, sizeof(buf))); 7125182999Smav if (w->ossdev >= 0) { 7126182999Smav printf("\n"); 7127182999Smav return; 7128182999Smav } 7129163057Sariff } 7130182999Smav printf("\n"); 7131182999Smav 7132182999Smav for (i = 0; i < w->nconns; i++) { 7133182999Smav if (w->connsenable[i] == 0) 7134182999Smav continue; 7135182999Smav cw = hdac_widget_get(devinfo, w->conns[i]); 7136182999Smav if (cw == NULL || cw->enable == 0 || cw->bindas == -1) 7137182999Smav continue; 7138182999Smav if (printed == 0) { 7139182999Smav device_printf(pdevinfo->dev, "%*s |\n", 4 + (depth) * 7, ""); 7140182999Smav printed = 1; 7141182999Smav } 7142182999Smav hdac_dump_dst_nid(pdevinfo, w->conns[i], depth + 1); 7143182999Smav } 7144163057Sariff 7145163057Sariff} 7146163057Sariff 7147162922Sariffstatic void 7148182999Smavhdac_dump_dac(struct hdac_pcm_devinfo *pdevinfo) 7149162922Sariff{ 7150182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7151182999Smav struct hdac_softc *sc = devinfo->codec->sc; 7152202736Smav struct hdac_audio_as *as; 7153163057Sariff struct hdac_widget *w; 7154163057Sariff int i, printed = 0; 7155163057Sariff 7156182999Smav if (pdevinfo->play < 0) 7157182999Smav return; 7158182999Smav 7159202736Smav as = &devinfo->function.audio.as[sc->chans[pdevinfo->play].as]; 7160202736Smav for (i = 0; i < 16; i++) { 7161202736Smav if (as->pins[i] <= 0) 7162202736Smav continue; 7163202736Smav w = hdac_widget_get(devinfo, as->pins[i]); 7164163057Sariff if (w == NULL || w->enable == 0) 7165163057Sariff continue; 7166163057Sariff if (printed == 0) { 7167163057Sariff printed = 1; 7168182999Smav device_printf(pdevinfo->dev, "\n"); 7169182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7170163057Sariff } 7171182999Smav device_printf(pdevinfo->dev, "\n"); 7172202736Smav hdac_dump_dst_nid(pdevinfo, as->pins[i], 0); 7173163057Sariff } 7174162922Sariff} 7175162922Sariff 7176162922Sariffstatic void 7177182999Smavhdac_dump_adc(struct hdac_pcm_devinfo *pdevinfo) 7178162922Sariff{ 7179182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7180162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 7181182999Smav struct hdac_widget *w; 7182182999Smav int i; 7183162922Sariff int printed = 0; 7184162922Sariff 7185182999Smav if (pdevinfo->rec < 0) 7186182999Smav return; 7187182999Smav 7188162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7189162922Sariff w = hdac_widget_get(devinfo, i); 7190162922Sariff if (w == NULL || w->enable == 0) 7191162922Sariff continue; 7192182999Smav if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 7193162922Sariff continue; 7194182999Smav if (w->bindas != sc->chans[pdevinfo->rec].as) 7195182999Smav continue; 7196162922Sariff if (printed == 0) { 7197162922Sariff printed = 1; 7198182999Smav device_printf(pdevinfo->dev, "\n"); 7199182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7200162922Sariff } 7201182999Smav device_printf(pdevinfo->dev, "\n"); 7202182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7203182999Smav } 7204182999Smav} 7205182999Smav 7206182999Smavstatic void 7207182999Smavhdac_dump_mix(struct hdac_pcm_devinfo *pdevinfo) 7208182999Smav{ 7209182999Smav struct hdac_devinfo *devinfo = pdevinfo->devinfo; 7210182999Smav struct hdac_widget *w; 7211182999Smav int i; 7212182999Smav int printed = 0; 7213182999Smav 7214182999Smav if (pdevinfo->index != 0) 7215182999Smav return; 7216182999Smav 7217182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7218182999Smav w = hdac_widget_get(devinfo, i); 7219182999Smav if (w == NULL || w->enable == 0) 7220182999Smav continue; 7221202789Smav if (w->ossdev != SOUND_MIXER_IMIX) 7222182999Smav continue; 7223182999Smav if (printed == 0) { 7224182999Smav printed = 1; 7225182999Smav device_printf(pdevinfo->dev, "\n"); 7226182999Smav device_printf(pdevinfo->dev, "Input Mix:\n"); 7227162922Sariff } 7228182999Smav device_printf(pdevinfo->dev, "\n"); 7229182999Smav hdac_dump_dst_nid(pdevinfo, i, 0); 7230162922Sariff } 7231162922Sariff} 7232162922Sariff 7233162922Sariffstatic void 7234182999Smavhdac_dump_pcmchannels(struct hdac_pcm_devinfo *pdevinfo) 7235162922Sariff{ 7236182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 7237162922Sariff nid_t *nids; 7238182999Smav int i; 7239162922Sariff 7240182999Smav if (pdevinfo->play >= 0) { 7241182999Smav i = pdevinfo->play; 7242182999Smav device_printf(pdevinfo->dev, "\n"); 7243182999Smav device_printf(pdevinfo->dev, "Playback:\n"); 7244182999Smav device_printf(pdevinfo->dev, "\n"); 7245182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7246182999Smav sc->chans[i].supp_pcm_size_rate); 7247182999Smav device_printf(pdevinfo->dev, " DAC:"); 7248182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7249162922Sariff printf(" %d", *nids); 7250162922Sariff printf("\n"); 7251162922Sariff } 7252182999Smav if (pdevinfo->rec >= 0) { 7253182999Smav i = pdevinfo->rec; 7254182999Smav device_printf(pdevinfo->dev, "\n"); 7255182999Smav device_printf(pdevinfo->dev, "Record:\n"); 7256182999Smav device_printf(pdevinfo->dev, "\n"); 7257182999Smav hdac_dump_audio_formats(pdevinfo->dev, sc->chans[i].supp_stream_formats, 7258182999Smav sc->chans[i].supp_pcm_size_rate); 7259182999Smav device_printf(pdevinfo->dev, " ADC:"); 7260182999Smav for (nids = sc->chans[i].io; *nids != -1; nids++) 7261162922Sariff printf(" %d", *nids); 7262162922Sariff printf("\n"); 7263162922Sariff } 7264162922Sariff} 7265162922Sariff 7266162922Sariffstatic void 7267163057Sariffhdac_release_resources(struct hdac_softc *sc) 7268163057Sariff{ 7269182999Smav int i, j; 7270163057Sariff 7271163057Sariff if (sc == NULL) 7272163057Sariff return; 7273163057Sariff 7274163057Sariff hdac_lock(sc); 7275169277Sariff sc->polling = 0; 7276169277Sariff sc->poll_ival = 0; 7277170721Sariff callout_stop(&sc->poll_hda); 7278169277Sariff callout_stop(&sc->poll_hdac); 7279169277Sariff callout_stop(&sc->poll_jack); 7280182999Smav hdac_reset(sc, 0); 7281163057Sariff hdac_unlock(sc); 7282171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7283170721Sariff callout_drain(&sc->poll_hda); 7284169277Sariff callout_drain(&sc->poll_hdac); 7285169277Sariff callout_drain(&sc->poll_jack); 7286163057Sariff 7287169277Sariff hdac_irq_free(sc); 7288169277Sariff 7289182999Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 7290182999Smav if (sc->codecs[i] == NULL) 7291163057Sariff continue; 7292182999Smav for (j = 0; j < sc->codecs[i]->num_fgs; j++) { 7293182999Smav free(sc->codecs[i]->fgs[j].widget, M_HDAC); 7294182999Smav if (sc->codecs[i]->fgs[j].node_type == 7295182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7296182999Smav free(sc->codecs[i]->fgs[j].function.audio.ctl, 7297182999Smav M_HDAC); 7298182999Smav free(sc->codecs[i]->fgs[j].function.audio.as, 7299182999Smav M_HDAC); 7300182999Smav free(sc->codecs[i]->fgs[j].function.audio.devs, 7301182999Smav M_HDAC); 7302182999Smav } 7303182999Smav } 7304182999Smav free(sc->codecs[i]->fgs, M_HDAC); 7305182999Smav free(sc->codecs[i], M_HDAC); 7306163057Sariff sc->codecs[i] = NULL; 7307163057Sariff } 7308163057Sariff 7309169277Sariff hdac_dma_free(sc, &sc->pos_dma); 7310169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 7311169277Sariff hdac_dma_free(sc, &sc->corb_dma); 7312182999Smav for (i = 0; i < sc->num_chans; i++) { 7313182999Smav if (sc->chans[i].blkcnt > 0) 7314182999Smav hdac_dma_free(sc, &sc->chans[i].bdl_dma); 7315182999Smav } 7316182999Smav free(sc->chans, M_HDAC); 7317167702Sariff if (sc->chan_dmat != NULL) { 7318167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 7319167702Sariff sc->chan_dmat = NULL; 7320167702Sariff } 7321163057Sariff hdac_mem_free(sc); 7322169277Sariff snd_mtxfree(sc->lock); 7323163057Sariff} 7324163057Sariff 7325163057Sariff/* This function surely going to make its way into upper level someday. */ 7326163057Sariffstatic void 7327163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 7328163057Sariff{ 7329163057Sariff const char *res = NULL; 7330163057Sariff int i = 0, j, k, len, inv; 7331163057Sariff 7332163057Sariff if (on != NULL) 7333163057Sariff *on = 0; 7334163057Sariff if (off != NULL) 7335163057Sariff *off = 0; 7336163057Sariff if (sc == NULL) 7337163057Sariff return; 7338163057Sariff if (resource_string_value(device_get_name(sc->dev), 7339163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 7340163057Sariff return; 7341163057Sariff if (!(res != NULL && strlen(res) > 0)) 7342163057Sariff return; 7343163057Sariff HDA_BOOTVERBOSE( 7344182999Smav device_printf(sc->dev, "HDA Config:"); 7345163057Sariff ); 7346163057Sariff for (;;) { 7347163057Sariff while (res[i] != '\0' && 7348163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 7349163057Sariff i++; 7350163057Sariff if (res[i] == '\0') { 7351163057Sariff HDA_BOOTVERBOSE( 7352163057Sariff printf("\n"); 7353163057Sariff ); 7354163057Sariff return; 7355163057Sariff } 7356163057Sariff j = i; 7357163057Sariff while (res[j] != '\0' && 7358163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 7359163057Sariff j++; 7360163057Sariff len = j - i; 7361163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 7362163057Sariff inv = 2; 7363163057Sariff else 7364163057Sariff inv = 0; 7365163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 7366163057Sariff if (strncmp(res + i + inv, 7367163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 7368163057Sariff continue; 7369163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 7370187944Smav continue; 7371163057Sariff HDA_BOOTVERBOSE( 7372163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 7373163057Sariff hdac_quirks_tab[k].key); 7374163057Sariff ); 7375163057Sariff if (inv == 0 && on != NULL) 7376163057Sariff *on |= hdac_quirks_tab[k].value; 7377163057Sariff else if (inv != 0 && off != NULL) 7378163057Sariff *off |= hdac_quirks_tab[k].value; 7379163057Sariff break; 7380163057Sariff } 7381163057Sariff i = j; 7382163057Sariff } 7383163057Sariff} 7384163057Sariff 7385164614Sariffstatic int 7386164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 7387164614Sariff{ 7388164614Sariff struct hdac_softc *sc; 7389164614Sariff device_t dev; 7390164614Sariff uint32_t ctl; 7391164614Sariff int err, val; 7392164614Sariff 7393164614Sariff dev = oidp->oid_arg1; 7394182999Smav sc = device_get_softc(dev); 7395182999Smav if (sc == NULL) 7396164614Sariff return (EINVAL); 7397164614Sariff hdac_lock(sc); 7398164614Sariff val = sc->polling; 7399164614Sariff hdac_unlock(sc); 7400170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7401164614Sariff 7402169277Sariff if (err != 0 || req->newptr == NULL) 7403164614Sariff return (err); 7404164614Sariff if (val < 0 || val > 1) 7405164614Sariff return (EINVAL); 7406164614Sariff 7407164614Sariff hdac_lock(sc); 7408164614Sariff if (val != sc->polling) { 7409182999Smav if (val == 0) { 7410182999Smav callout_stop(&sc->poll_hda); 7411164614Sariff callout_stop(&sc->poll_hdac); 7412169277Sariff hdac_unlock(sc); 7413182999Smav callout_drain(&sc->poll_hda); 7414169277Sariff callout_drain(&sc->poll_hdac); 7415169277Sariff hdac_lock(sc); 7416164614Sariff sc->polling = 0; 7417182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7418182999Smav ctl |= HDAC_INTCTL_GIE; 7419182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7420164614Sariff } else { 7421182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 7422182999Smav ctl &= ~HDAC_INTCTL_GIE; 7423182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 7424171141Sariff hdac_unlock(sc); 7425171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7426171141Sariff hdac_lock(sc); 7427164614Sariff sc->polling = 1; 7428182999Smav hdac_poll_reinit(sc); 7429182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7430164614Sariff } 7431164614Sariff } 7432164614Sariff hdac_unlock(sc); 7433164614Sariff 7434164614Sariff return (err); 7435164614Sariff} 7436169277Sariff 7437169277Sariffstatic int 7438169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 7439169277Sariff{ 7440169277Sariff struct hdac_softc *sc; 7441169277Sariff device_t dev; 7442169277Sariff int err, val; 7443169277Sariff 7444169277Sariff dev = oidp->oid_arg1; 7445182999Smav sc = device_get_softc(dev); 7446182999Smav if (sc == NULL) 7447169277Sariff return (EINVAL); 7448169277Sariff hdac_lock(sc); 7449169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 7450169277Sariff hdac_unlock(sc); 7451170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7452169277Sariff 7453169277Sariff if (err != 0 || req->newptr == NULL) 7454169277Sariff return (err); 7455169277Sariff 7456169277Sariff if (val < 1) 7457169277Sariff val = 1; 7458169277Sariff if (val > 5000) 7459169277Sariff val = 5000; 7460169277Sariff val = ((uint64_t)val * hz) / 1000; 7461169277Sariff if (val < 1) 7462169277Sariff val = 1; 7463169277Sariff if (val > (hz * 5)) 7464169277Sariff val = hz * 5; 7465169277Sariff 7466169277Sariff hdac_lock(sc); 7467169277Sariff sc->poll_ival = val; 7468169277Sariff hdac_unlock(sc); 7469169277Sariff 7470169277Sariff return (err); 7471169277Sariff} 7472169277Sariff 7473169277Sariffstatic int 7474171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 7475169277Sariff{ 7476169277Sariff struct hdac_softc *sc; 7477182999Smav struct hdac_codec *codec; 7478169277Sariff struct hdac_devinfo *devinfo; 7479169277Sariff struct hdac_widget *w; 7480169277Sariff device_t dev; 7481182999Smav uint32_t res, pincap, delay; 7482182999Smav int codec_index, fg_index; 7483169277Sariff int i, err, val; 7484169277Sariff nid_t cad; 7485169277Sariff 7486169277Sariff dev = oidp->oid_arg1; 7487182999Smav sc = device_get_softc(dev); 7488182999Smav if (sc == NULL) 7489169277Sariff return (EINVAL); 7490169277Sariff val = 0; 7491170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 7492169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 7493169277Sariff return (err); 7494182999Smav 7495182999Smav /* XXX: Temporary. For debugging. */ 7496182999Smav if (val == 100) { 7497182999Smav hdac_suspend(dev); 7498182999Smav return (0); 7499182999Smav } else if (val == 101) { 7500182999Smav hdac_resume(dev); 7501182999Smav return (0); 7502182999Smav } 7503182999Smav 7504169277Sariff hdac_lock(sc); 7505182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7506182999Smav codec = sc->codecs[codec_index]; 7507182999Smav if (codec == NULL) 7508169277Sariff continue; 7509182999Smav cad = codec->cad; 7510182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7511182999Smav devinfo = &codec->fgs[fg_index]; 7512182999Smav if (devinfo->node_type != 7513182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 7514182999Smav continue; 7515182999Smav 7516182999Smav device_printf(dev, "Dumping AFG cad=%d nid=%d pins:\n", 7517182999Smav codec_index, devinfo->nid); 7518182999Smav for (i = devinfo->startnode; i < devinfo->endnode; i++) { 7519182999Smav w = hdac_widget_get(devinfo, i); 7520182999Smav if (w == NULL || w->type != 7521182999Smav HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 7522182999Smav continue; 7523182999Smav hdac_dump_pin_config(w, w->wclass.pin.config); 7524182999Smav pincap = w->wclass.pin.cap; 7525182999Smav device_printf(dev, " Caps: %2s %3s %2s %4s %4s", 7526182999Smav HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)?"IN":"", 7527182999Smav HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)?"OUT":"", 7528182999Smav HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)?"HP":"", 7529182999Smav HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)?"EAPD":"", 7530182999Smav HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)?"VREF":""); 7531182999Smav if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 7532182999Smav HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) { 7533182999Smav if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 7534182999Smav delay = 0; 7535182999Smav hdac_command(sc, 7536182999Smav HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 7537182999Smav do { 7538182999Smav res = hdac_command(sc, 7539182999Smav HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 7540182999Smav if (res != 0x7fffffff && res != 0xffffffff) 7541182999Smav break; 7542182999Smav DELAY(10); 7543182999Smav } while (++delay < 10000); 7544182999Smav } else { 7545182999Smav delay = 0; 7546182999Smav res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 7547182999Smav w->nid), cad); 7548182999Smav } 7549182999Smav printf(" Sense: 0x%08x", res); 7550182999Smav if (delay > 0) 7551182999Smav printf(" delay %dus", delay * 10); 7552182999Smav } 7553182999Smav printf("\n"); 7554182999Smav } 7555182999Smav device_printf(dev, 7556182999Smav "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 7557182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 7558182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 7559182999Smav HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 7560182999Smav HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 7561182999Smav HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 7562182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 7563182999Smav device_printf(dev, " GPI:"); 7564171141Sariff res = hdac_command(sc, 7565182999Smav HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 7566182999Smav printf(" data=0x%08x", res); 7567182999Smav res = hdac_command(sc, 7568182999Smav HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 7569182999Smav cad); 7570182999Smav printf(" wake=0x%08x", res); 7571182999Smav res = hdac_command(sc, 7572182999Smav HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7573182999Smav cad); 7574182999Smav printf(" unsol=0x%08x", res); 7575182999Smav res = hdac_command(sc, 7576182999Smav HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 7577182999Smav printf(" sticky=0x%08x\n", res); 7578182999Smav } 7579182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 7580182999Smav device_printf(dev, " GPO:"); 7581182999Smav res = hdac_command(sc, 7582182999Smav HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 7583182999Smav printf(" data=0x%08x\n", res); 7584182999Smav } 7585182999Smav if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 7586182999Smav device_printf(dev, "GPIO:"); 7587182999Smav res = hdac_command(sc, 7588182999Smav HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 7589182999Smav printf(" data=0x%08x", res); 7590182999Smav res = hdac_command(sc, 7591182999Smav HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 7592182999Smav printf(" enable=0x%08x", res); 7593182999Smav res = hdac_command(sc, 7594182999Smav HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 7595182999Smav printf(" direction=0x%08x\n", res); 7596182999Smav res = hdac_command(sc, 7597182999Smav HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 7598182999Smav device_printf(dev, " wake=0x%08x", res); 7599182999Smav res = hdac_command(sc, 7600182999Smav HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 7601182999Smav cad); 7602182999Smav printf(" unsol=0x%08x", res); 7603182999Smav res = hdac_command(sc, 7604182999Smav HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 7605182999Smav printf(" sticky=0x%08x\n", res); 7606182999Smav } 7607171141Sariff } 7608169277Sariff } 7609169277Sariff hdac_unlock(sc); 7610169277Sariff return (0); 7611169277Sariff} 7612164614Sariff 7613163057Sariffstatic void 7614162922Sariffhdac_attach2(void *arg) 7615162922Sariff{ 7616182999Smav struct hdac_codec *codec; 7617162922Sariff struct hdac_softc *sc; 7618162922Sariff struct hdac_audio_ctl *ctl; 7619163057Sariff uint32_t quirks_on, quirks_off; 7620182999Smav int codec_index, fg_index; 7621185225Smav int i, dmaalloc = 0; 7622182999Smav struct hdac_devinfo *devinfo; 7623162922Sariff 7624162922Sariff sc = (struct hdac_softc *)arg; 7625162922Sariff 7626163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 7627162922Sariff 7628183097Smav HDA_BOOTHVERBOSE( 7629182999Smav device_printf(sc->dev, "HDA Config: on=0x%08x off=0x%08x\n", 7630163057Sariff quirks_on, quirks_off); 7631163057Sariff ); 7632163057Sariff 7633162922Sariff hdac_lock(sc); 7634162922Sariff 7635162922Sariff /* Remove ourselves from the config hooks */ 7636162922Sariff if (sc->intrhook.ich_func != NULL) { 7637162922Sariff config_intrhook_disestablish(&sc->intrhook); 7638162922Sariff sc->intrhook.ich_func = NULL; 7639162922Sariff } 7640162922Sariff 7641162922Sariff /* Start the corb and rirb engines */ 7642183097Smav HDA_BOOTHVERBOSE( 7643182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 7644162922Sariff ); 7645162922Sariff hdac_corb_start(sc); 7646183097Smav HDA_BOOTHVERBOSE( 7647182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 7648162922Sariff ); 7649162922Sariff hdac_rirb_start(sc); 7650162922Sariff 7651183097Smav HDA_BOOTHVERBOSE( 7652162922Sariff device_printf(sc->dev, 7653182999Smav "Enabling controller interrupt...\n"); 7654162922Sariff ); 7655182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7656182999Smav HDAC_GCTL_UNSOL); 7657182999Smav if (sc->polling == 0) { 7658164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7659164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7660182999Smav } else { 7661182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7662182999Smav } 7663162922Sariff DELAY(1000); 7664162922Sariff 7665183097Smav HDA_BOOTHVERBOSE( 7666172811Sariff device_printf(sc->dev, 7667182999Smav "Scanning HDA codecs ...\n"); 7668162922Sariff ); 7669182999Smav hdac_scan_codecs(sc); 7670182999Smav 7671182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7672182999Smav codec = sc->codecs[codec_index]; 7673182999Smav if (codec == NULL) 7674182999Smav continue; 7675182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7676182999Smav devinfo = &codec->fgs[fg_index]; 7677183019Smav HDA_BOOTVERBOSE( 7678183019Smav device_printf(sc->dev, "\n"); 7679183097Smav device_printf(sc->dev, 7680183097Smav "Processing %s FG cad=%d nid=%d...\n", 7681183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) ? "audio": 7682183097Smav (devinfo->node_type == HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM) ? "modem": 7683183097Smav "unknown", 7684183097Smav devinfo->codec->cad, devinfo->nid); 7685183019Smav ); 7686182999Smav if (devinfo->node_type != 7687182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 7688183097Smav HDA_BOOTHVERBOSE( 7689182999Smav device_printf(sc->dev, 7690183097Smav "Powering down...\n"); 7691182999Smav ); 7692182999Smav hdac_command(sc, 7693182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7694182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7695182999Smav codec->cad); 7696182999Smav continue; 7697182999Smav } 7698162922Sariff 7699183097Smav HDA_BOOTHVERBOSE( 7700183097Smav device_printf(sc->dev, "Powering up...\n"); 7701182999Smav ); 7702182999Smav hdac_powerup(devinfo); 7703183097Smav HDA_BOOTHVERBOSE( 7704182999Smav device_printf(sc->dev, "Parsing audio FG...\n"); 7705182999Smav ); 7706182999Smav hdac_audio_parse(devinfo); 7707183097Smav HDA_BOOTHVERBOSE( 7708182999Smav device_printf(sc->dev, "Parsing Ctls...\n"); 7709182999Smav ); 7710182999Smav hdac_audio_ctl_parse(devinfo); 7711183097Smav HDA_BOOTHVERBOSE( 7712182999Smav device_printf(sc->dev, "Parsing vendor patch...\n"); 7713182999Smav ); 7714182999Smav hdac_vendor_patch_parse(devinfo); 7715182999Smav devinfo->function.audio.quirks |= quirks_on; 7716182999Smav devinfo->function.audio.quirks &= ~quirks_off; 7717162922Sariff 7718183097Smav HDA_BOOTHVERBOSE( 7719182999Smav device_printf(sc->dev, "Disabling nonaudio...\n"); 7720182999Smav ); 7721182999Smav hdac_audio_disable_nonaudio(devinfo); 7722183097Smav HDA_BOOTHVERBOSE( 7723182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7724182999Smav ); 7725182999Smav hdac_audio_disable_useless(devinfo); 7726182999Smav HDA_BOOTVERBOSE( 7727182999Smav device_printf(sc->dev, "Patched pins configuration:\n"); 7728182999Smav hdac_dump_pin_configs(devinfo); 7729183097Smav ); 7730183097Smav HDA_BOOTHVERBOSE( 7731182999Smav device_printf(sc->dev, "Parsing pin associations...\n"); 7732182999Smav ); 7733182999Smav hdac_audio_as_parse(devinfo); 7734183097Smav HDA_BOOTHVERBOSE( 7735182999Smav device_printf(sc->dev, "Building AFG tree...\n"); 7736182999Smav ); 7737182999Smav hdac_audio_build_tree(devinfo); 7738183097Smav HDA_BOOTHVERBOSE( 7739182999Smav device_printf(sc->dev, "Disabling unassociated " 7740182999Smav "widgets...\n"); 7741182999Smav ); 7742182999Smav hdac_audio_disable_unas(devinfo); 7743183097Smav HDA_BOOTHVERBOSE( 7744182999Smav device_printf(sc->dev, "Disabling nonselected " 7745182999Smav "inputs...\n"); 7746182999Smav ); 7747182999Smav hdac_audio_disable_notselected(devinfo); 7748183097Smav HDA_BOOTHVERBOSE( 7749182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7750182999Smav ); 7751182999Smav hdac_audio_disable_useless(devinfo); 7752183097Smav HDA_BOOTHVERBOSE( 7753182999Smav device_printf(sc->dev, "Disabling " 7754182999Smav "crossassociatement connections...\n"); 7755182999Smav ); 7756182999Smav hdac_audio_disable_crossas(devinfo); 7757183097Smav HDA_BOOTHVERBOSE( 7758182999Smav device_printf(sc->dev, "Disabling useless...\n"); 7759182999Smav ); 7760182999Smav hdac_audio_disable_useless(devinfo); 7761183097Smav HDA_BOOTHVERBOSE( 7762182999Smav device_printf(sc->dev, "Binding associations to channels...\n"); 7763182999Smav ); 7764182999Smav hdac_audio_bind_as(devinfo); 7765183097Smav HDA_BOOTHVERBOSE( 7766182999Smav device_printf(sc->dev, "Assigning names to signal sources...\n"); 7767182999Smav ); 7768182999Smav hdac_audio_assign_names(devinfo); 7769183097Smav HDA_BOOTHVERBOSE( 7770182999Smav device_printf(sc->dev, "Assigning mixers to the tree...\n"); 7771182999Smav ); 7772182999Smav hdac_audio_assign_mixers(devinfo); 7773183097Smav HDA_BOOTHVERBOSE( 7774182999Smav device_printf(sc->dev, "Preparing pin controls...\n"); 7775182999Smav ); 7776182999Smav hdac_audio_prepare_pin_ctrl(devinfo); 7777183097Smav HDA_BOOTHVERBOSE( 7778182999Smav device_printf(sc->dev, "AFG commit...\n"); 7779182999Smav ); 7780182999Smav hdac_audio_commit(devinfo); 7781183097Smav HDA_BOOTHVERBOSE( 7782182999Smav device_printf(sc->dev, "HP switch init...\n"); 7783182999Smav ); 7784182999Smav hdac_hp_switch_init(devinfo); 7785182999Smav 7786182999Smav if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 7787182999Smav dmaalloc == 0) { 7788182999Smav if (hdac_dma_alloc(sc, &sc->pos_dma, 7789182999Smav (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 7790182999Smav HDA_BOOTVERBOSE( 7791182999Smav device_printf(sc->dev, "Failed to " 7792182999Smav "allocate DMA pos buffer " 7793182999Smav "(non-fatal)\n"); 7794182999Smav ); 7795182999Smav } else 7796182999Smav dmaalloc = 1; 7797182999Smav } 7798182999Smav 7799185225Smav HDA_BOOTHVERBOSE( 7800185225Smav device_printf(sc->dev, "Creating PCM devices...\n"); 7801185225Smav ); 7802185225Smav hdac_create_pcms(devinfo); 7803182999Smav 7804182999Smav HDA_BOOTVERBOSE( 7805182999Smav if (devinfo->function.audio.quirks != 0) { 7806183097Smav device_printf(sc->dev, "FG config/quirks:"); 7807182999Smav for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 7808182999Smav if ((devinfo->function.audio.quirks & 7809182999Smav hdac_quirks_tab[i].value) == 7810182999Smav hdac_quirks_tab[i].value) 7811182999Smav printf(" %s", hdac_quirks_tab[i].key); 7812182999Smav } 7813182999Smav printf("\n"); 7814182999Smav } 7815182999Smav 7816182999Smav device_printf(sc->dev, "\n"); 7817182999Smav device_printf(sc->dev, "+-------------------+\n"); 7818182999Smav device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 7819182999Smav device_printf(sc->dev, "+-------------------+\n"); 7820182999Smav hdac_dump_nodes(devinfo); 7821183097Smav ); 7822182999Smav 7823183097Smav HDA_BOOTHVERBOSE( 7824182999Smav device_printf(sc->dev, "\n"); 7825182999Smav device_printf(sc->dev, "+------------------------+\n"); 7826182999Smav device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 7827182999Smav device_printf(sc->dev, "+------------------------+\n"); 7828182999Smav device_printf(sc->dev, "\n"); 7829182999Smav i = 0; 7830182999Smav while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 7831182999Smav device_printf(sc->dev, "%3d: nid %3d %s (%s) index %d", i, 7832182999Smav (ctl->widget != NULL) ? ctl->widget->nid : -1, 7833182999Smav (ctl->ndir == HDA_CTL_IN)?"in ":"out", 7834182999Smav (ctl->dir == HDA_CTL_IN)?"in ":"out", 7835182999Smav ctl->index); 7836182999Smav if (ctl->childwidget != NULL) 7837182999Smav printf(" cnid %3d", ctl->childwidget->nid); 7838182999Smav else 7839182999Smav printf(" "); 7840182999Smav printf(" ossmask=0x%08x\n", 7841182999Smav ctl->ossmask); 7842182999Smav device_printf(sc->dev, 7843182999Smav " mute: %d step: %3d size: %3d off: %3d%s\n", 7844182999Smav ctl->mute, ctl->step, ctl->size, ctl->offset, 7845182999Smav (ctl->enable == 0) ? " [DISABLED]" : 7846182999Smav ((ctl->ossmask == 0) ? " [UNUSED]" : "")); 7847182999Smav } 7848182999Smav ); 7849182999Smav } 7850162922Sariff } 7851182999Smav hdac_unlock(sc); 7852162922Sariff 7853163057Sariff HDA_BOOTVERBOSE( 7854182999Smav device_printf(sc->dev, "\n"); 7855162922Sariff ); 7856182999Smav 7857182999Smav bus_generic_attach(sc->dev); 7858182999Smav 7859182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7860182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7861182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7862182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 7863182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7864182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7865182999Smav "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 7866182999Smav sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 7867182999Smav "Controller/Jack Sense polling interval (1-1000 ms)"); 7868182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 7869182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 7870182999Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 7871182999Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 7872182999Smav} 7873182999Smav 7874182999Smav/**************************************************************************** 7875182999Smav * int hdac_suspend(device_t) 7876182999Smav * 7877182999Smav * Suspend and power down HDA bus and codecs. 7878182999Smav ****************************************************************************/ 7879182999Smavstatic int 7880182999Smavhdac_suspend(device_t dev) 7881182999Smav{ 7882182999Smav struct hdac_softc *sc; 7883182999Smav struct hdac_codec *codec; 7884182999Smav struct hdac_devinfo *devinfo; 7885182999Smav int codec_index, fg_index, i; 7886182999Smav 7887183097Smav HDA_BOOTHVERBOSE( 7888182999Smav device_printf(dev, "Suspend...\n"); 7889162922Sariff ); 7890182999Smav 7891182999Smav sc = device_get_softc(dev); 7892182999Smav hdac_lock(sc); 7893182999Smav 7894183097Smav HDA_BOOTHVERBOSE( 7895182999Smav device_printf(dev, "Stop streams...\n"); 7896162922Sariff ); 7897182999Smav for (i = 0; i < sc->num_chans; i++) { 7898182999Smav if (sc->chans[i].flags & HDAC_CHN_RUNNING) { 7899182999Smav sc->chans[i].flags |= HDAC_CHN_SUSPEND; 7900182999Smav hdac_channel_stop(sc, &sc->chans[i]); 7901182999Smav } 7902182999Smav } 7903162922Sariff 7904182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7905182999Smav codec = sc->codecs[codec_index]; 7906182999Smav if (codec == NULL) 7907162922Sariff continue; 7908182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 7909182999Smav devinfo = &codec->fgs[fg_index]; 7910183097Smav HDA_BOOTHVERBOSE( 7911182999Smav device_printf(dev, 7912182999Smav "Power down FG" 7913182999Smav " cad=%d nid=%d to the D3 state...\n", 7914182999Smav codec->cad, devinfo->nid); 7915182999Smav ); 7916182999Smav hdac_command(sc, 7917182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 7918182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 7919182999Smav codec->cad); 7920162922Sariff } 7921162922Sariff } 7922162922Sariff 7923183097Smav HDA_BOOTHVERBOSE( 7924182999Smav device_printf(dev, "Reset controller...\n"); 7925162922Sariff ); 7926182999Smav callout_stop(&sc->poll_hda); 7927182999Smav callout_stop(&sc->poll_hdac); 7928182999Smav callout_stop(&sc->poll_jack); 7929182999Smav hdac_reset(sc, 0); 7930182999Smav hdac_unlock(sc); 7931182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 7932182999Smav callout_drain(&sc->poll_hda); 7933182999Smav callout_drain(&sc->poll_hdac); 7934182999Smav callout_drain(&sc->poll_jack); 7935162922Sariff 7936183097Smav HDA_BOOTHVERBOSE( 7937182999Smav device_printf(dev, "Suspend done\n"); 7938162922Sariff ); 7939182999Smav 7940182999Smav return (0); 7941182999Smav} 7942182999Smav 7943182999Smav/**************************************************************************** 7944182999Smav * int hdac_resume(device_t) 7945182999Smav * 7946182999Smav * Powerup and restore HDA bus and codecs state. 7947182999Smav ****************************************************************************/ 7948182999Smavstatic int 7949182999Smavhdac_resume(device_t dev) 7950182999Smav{ 7951182999Smav struct hdac_softc *sc; 7952182999Smav struct hdac_codec *codec; 7953182999Smav struct hdac_devinfo *devinfo; 7954182999Smav int codec_index, fg_index, i; 7955182999Smav 7956183097Smav HDA_BOOTHVERBOSE( 7957182999Smav device_printf(dev, "Resume...\n"); 7958162922Sariff ); 7959162922Sariff 7960182999Smav sc = device_get_softc(dev); 7961182999Smav hdac_lock(sc); 7962182999Smav 7963182999Smav /* Quiesce everything */ 7964183097Smav HDA_BOOTHVERBOSE( 7965182999Smav device_printf(dev, "Reset controller...\n"); 7966162922Sariff ); 7967182999Smav hdac_reset(sc, 1); 7968182999Smav 7969182999Smav /* Initialize the CORB and RIRB */ 7970182999Smav hdac_corb_init(sc); 7971182999Smav hdac_rirb_init(sc); 7972182999Smav 7973182999Smav /* Start the corb and rirb engines */ 7974183097Smav HDA_BOOTHVERBOSE( 7975182999Smav device_printf(dev, "Starting CORB Engine...\n"); 7976162922Sariff ); 7977182999Smav hdac_corb_start(sc); 7978183097Smav HDA_BOOTHVERBOSE( 7979182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 7980162922Sariff ); 7981182999Smav hdac_rirb_start(sc); 7982163057Sariff 7983183097Smav HDA_BOOTHVERBOSE( 7984182999Smav device_printf(dev, 7985182999Smav "Enabling controller interrupt...\n"); 7986162922Sariff ); 7987182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 7988182999Smav HDAC_GCTL_UNSOL); 7989182999Smav if (sc->polling == 0) { 7990182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 7991182999Smav HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 7992182999Smav } else { 7993182999Smav callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 7994182999Smav } 7995182999Smav DELAY(1000); 7996162922Sariff 7997182999Smav for (codec_index = 0; codec_index < HDAC_CODEC_MAX; codec_index++) { 7998182999Smav codec = sc->codecs[codec_index]; 7999182999Smav if (codec == NULL) 8000182999Smav continue; 8001182999Smav for (fg_index = 0; fg_index < codec->num_fgs; fg_index++) { 8002182999Smav devinfo = &codec->fgs[fg_index]; 8003182999Smav if (devinfo->node_type != 8004182999Smav HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 8005183097Smav HDA_BOOTHVERBOSE( 8006182999Smav device_printf(dev, 8007182999Smav "Power down unsupported non-audio FG" 8008182999Smav " cad=%d nid=%d to the D3 state...\n", 8009182999Smav codec->cad, devinfo->nid); 8010182999Smav ); 8011182999Smav hdac_command(sc, 8012182999Smav HDA_CMD_SET_POWER_STATE(codec->cad, 8013182999Smav devinfo->nid, HDA_CMD_POWER_STATE_D3), 8014182999Smav codec->cad); 8015182999Smav continue; 8016182999Smav } 8017162922Sariff 8018183097Smav HDA_BOOTHVERBOSE( 8019182999Smav device_printf(dev, 8020182999Smav "Power up audio FG cad=%d nid=%d...\n", 8021182999Smav devinfo->codec->cad, devinfo->nid); 8022182999Smav ); 8023182999Smav hdac_powerup(devinfo); 8024183097Smav HDA_BOOTHVERBOSE( 8025182999Smav device_printf(dev, "AFG commit...\n"); 8026182999Smav ); 8027182999Smav hdac_audio_commit(devinfo); 8028183097Smav HDA_BOOTHVERBOSE( 8029182999Smav device_printf(dev, "HP switch init...\n"); 8030182999Smav ); 8031182999Smav hdac_hp_switch_init(devinfo); 8032182999Smav 8033182999Smav hdac_unlock(sc); 8034182999Smav for (i = 0; i < devinfo->function.audio.num_devs; i++) { 8035182999Smav struct hdac_pcm_devinfo *pdevinfo = 8036182999Smav &devinfo->function.audio.devs[i]; 8037183097Smav HDA_BOOTHVERBOSE( 8038182999Smav device_printf(pdevinfo->dev, 8039182999Smav "OSS mixer reinitialization...\n"); 8040182999Smav ); 8041182999Smav if (mixer_reinit(pdevinfo->dev) == -1) 8042182999Smav device_printf(pdevinfo->dev, 8043182999Smav "unable to reinitialize the mixer\n"); 8044182999Smav } 8045182999Smav hdac_lock(sc); 8046182999Smav } 8047169277Sariff } 8048169277Sariff 8049183097Smav HDA_BOOTHVERBOSE( 8050182999Smav device_printf(dev, "Start streams...\n"); 8051163057Sariff ); 8052182999Smav for (i = 0; i < sc->num_chans; i++) { 8053182999Smav if (sc->chans[i].flags & HDAC_CHN_SUSPEND) { 8054182999Smav sc->chans[i].flags &= ~HDAC_CHN_SUSPEND; 8055182999Smav hdac_channel_start(sc, &sc->chans[i]); 8056182999Smav } 8057182999Smav } 8058162922Sariff 8059182999Smav hdac_unlock(sc); 8060182999Smav 8061183097Smav HDA_BOOTHVERBOSE( 8062182999Smav device_printf(dev, "Resume done\n"); 8063162922Sariff ); 8064164614Sariff 8065182999Smav return (0); 8066162922Sariff} 8067162922Sariff/**************************************************************************** 8068162922Sariff * int hdac_detach(device_t) 8069162922Sariff * 8070162922Sariff * Detach and free up resources utilized by the hdac device. 8071162922Sariff ****************************************************************************/ 8072162922Sariffstatic int 8073162922Sariffhdac_detach(device_t dev) 8074162922Sariff{ 8075182999Smav struct hdac_softc *sc; 8076185177Smav device_t *devlist; 8077185177Smav int i, devcount, error; 8078162922Sariff 8079185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 8080185177Smav return (error); 8081185177Smav for (i = 0; i < devcount; i++) { 8082185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 8083185178Smav free(devlist, M_TEMP); 8084185178Smav return (error); 8085185178Smav } 8086185177Smav } 8087185177Smav free(devlist, M_TEMP); 8088185177Smav 8089182999Smav sc = device_get_softc(dev); 8090163057Sariff hdac_release_resources(sc); 8091162922Sariff 8092162922Sariff return (0); 8093162922Sariff} 8094162922Sariff 8095184095Smavstatic int 8096184095Smavhdac_print_child(device_t dev, device_t child) 8097184095Smav{ 8098184095Smav struct hdac_pcm_devinfo *pdevinfo = 8099184095Smav (struct hdac_pcm_devinfo *)device_get_ivars(child); 8100184095Smav int retval; 8101184095Smav 8102184095Smav retval = bus_print_child_header(dev, child); 8103184095Smav retval += printf(" at cad %d nid %d", 8104184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid); 8105184095Smav retval += bus_print_child_footer(dev, child); 8106184095Smav 8107184095Smav return (retval); 8108184095Smav} 8109184095Smav 8110162922Sariffstatic device_method_t hdac_methods[] = { 8111162922Sariff /* device interface */ 8112162922Sariff DEVMETHOD(device_probe, hdac_probe), 8113162922Sariff DEVMETHOD(device_attach, hdac_attach), 8114162922Sariff DEVMETHOD(device_detach, hdac_detach), 8115182999Smav DEVMETHOD(device_suspend, hdac_suspend), 8116182999Smav DEVMETHOD(device_resume, hdac_resume), 8117184095Smav /* Bus interface */ 8118184095Smav DEVMETHOD(bus_print_child, hdac_print_child), 8119162922Sariff { 0, 0 } 8120162922Sariff}; 8121162922Sariff 8122162922Sariffstatic driver_t hdac_driver = { 8123182999Smav "hdac", 8124162922Sariff hdac_methods, 8125182999Smav sizeof(struct hdac_softc), 8126162922Sariff}; 8127162922Sariff 8128182999Smavstatic devclass_t hdac_devclass; 8129182999Smav 8130182999SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 8131162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 8132162922SariffMODULE_VERSION(snd_hda, 1); 8133182999Smav 8134182999Smavstatic int 8135182999Smavhdac_pcm_probe(device_t dev) 8136182999Smav{ 8137182999Smav struct hdac_pcm_devinfo *pdevinfo = 8138182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8139182999Smav char buf[128]; 8140182999Smav 8141185225Smav snprintf(buf, sizeof(buf), "HDA %s PCM #%d %s", 8142182999Smav hdac_codec_name(pdevinfo->devinfo->codec), 8143185225Smav pdevinfo->index, 8144197611Smav (pdevinfo->digital == 3)?"DisplayPort": 8145197611Smav ((pdevinfo->digital == 2)?"HDMI": 8146197611Smav ((pdevinfo->digital)?"Digital":"Analog"))); 8147182999Smav device_set_desc_copy(dev, buf); 8148182999Smav return (0); 8149182999Smav} 8150182999Smav 8151182999Smavstatic int 8152182999Smavhdac_pcm_attach(device_t dev) 8153182999Smav{ 8154182999Smav struct hdac_pcm_devinfo *pdevinfo = 8155182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8156182999Smav struct hdac_softc *sc = pdevinfo->devinfo->codec->sc; 8157182999Smav char status[SND_STATUSLEN]; 8158182999Smav int i; 8159182999Smav 8160182999Smav pdevinfo->chan_size = pcm_getbuffersize(dev, 8161182999Smav HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 8162182999Smav 8163182999Smav HDA_BOOTVERBOSE( 8164182999Smav device_printf(dev, "+--------------------------------------+\n"); 8165182999Smav device_printf(dev, "| DUMPING PCM Playback/Record Channels |\n"); 8166182999Smav device_printf(dev, "+--------------------------------------+\n"); 8167182999Smav hdac_dump_pcmchannels(pdevinfo); 8168182999Smav device_printf(dev, "\n"); 8169189876Smav device_printf(dev, "+-------------------------------+\n"); 8170189876Smav device_printf(dev, "| DUMPING Playback/Record Paths |\n"); 8171189876Smav device_printf(dev, "+-------------------------------+\n"); 8172182999Smav hdac_dump_dac(pdevinfo); 8173182999Smav hdac_dump_adc(pdevinfo); 8174182999Smav hdac_dump_mix(pdevinfo); 8175182999Smav device_printf(dev, "\n"); 8176182999Smav device_printf(dev, "+-------------------------+\n"); 8177182999Smav device_printf(dev, "| DUMPING Volume Controls |\n"); 8178182999Smav device_printf(dev, "+-------------------------+\n"); 8179182999Smav hdac_dump_ctls(pdevinfo, "Master Volume", SOUND_MASK_VOLUME); 8180182999Smav hdac_dump_ctls(pdevinfo, "PCM Volume", SOUND_MASK_PCM); 8181182999Smav hdac_dump_ctls(pdevinfo, "CD Volume", SOUND_MASK_CD); 8182182999Smav hdac_dump_ctls(pdevinfo, "Microphone Volume", SOUND_MASK_MIC); 8183182999Smav hdac_dump_ctls(pdevinfo, "Microphone2 Volume", SOUND_MASK_MONITOR); 8184182999Smav hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE); 8185182999Smav hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", SOUND_MASK_SPEAKER); 8186182999Smav hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV); 8187202796Smav hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX); 8188202796Smav hdac_dump_ctls(pdevinfo, "Input Monitoring Level", SOUND_MASK_IGAIN); 8189182999Smav hdac_dump_ctls(pdevinfo, NULL, 0); 8190182999Smav device_printf(dev, "\n"); 8191182999Smav ); 8192182999Smav 8193182999Smav if (resource_int_value(device_get_name(dev), 8194182999Smav device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 8195182999Smav i &= HDA_BLK_ALIGN; 8196182999Smav if (i < HDA_BLK_MIN) 8197182999Smav i = HDA_BLK_MIN; 8198182999Smav pdevinfo->chan_blkcnt = pdevinfo->chan_size / i; 8199182999Smav i = 0; 8200182999Smav while (pdevinfo->chan_blkcnt >> i) 8201182999Smav i++; 8202182999Smav pdevinfo->chan_blkcnt = 1 << (i - 1); 8203182999Smav if (pdevinfo->chan_blkcnt < HDA_BDL_MIN) 8204182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MIN; 8205182999Smav else if (pdevinfo->chan_blkcnt > HDA_BDL_MAX) 8206182999Smav pdevinfo->chan_blkcnt = HDA_BDL_MAX; 8207182999Smav } else 8208182999Smav pdevinfo->chan_blkcnt = HDA_BDL_DEFAULT; 8209182999Smav 8210182999Smav /* 8211182999Smav * We don't register interrupt handler with snd_setup_intr 8212182999Smav * in pcm device. Mark pcm device as MPSAFE manually. 8213182999Smav */ 8214182999Smav pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 8215182999Smav 8216183097Smav HDA_BOOTHVERBOSE( 8217182999Smav device_printf(dev, "OSS mixer initialization...\n"); 8218182999Smav ); 8219182999Smav if (mixer_init(dev, &hdac_audio_ctl_ossmixer_class, pdevinfo) != 0) 8220182999Smav device_printf(dev, "Can't register mixer\n"); 8221182999Smav 8222183097Smav HDA_BOOTHVERBOSE( 8223182999Smav device_printf(dev, "Registering PCM channels...\n"); 8224182999Smav ); 8225182999Smav if (pcm_register(dev, pdevinfo, (pdevinfo->play >= 0)?1:0, 8226182999Smav (pdevinfo->rec >= 0)?1:0) != 0) 8227182999Smav device_printf(dev, "Can't register PCM\n"); 8228182999Smav 8229182999Smav pdevinfo->registered++; 8230182999Smav 8231182999Smav if (pdevinfo->play >= 0) 8232182999Smav pcm_addchan(dev, PCMDIR_PLAY, &hdac_channel_class, pdevinfo); 8233182999Smav if (pdevinfo->rec >= 0) 8234182999Smav pcm_addchan(dev, PCMDIR_REC, &hdac_channel_class, pdevinfo); 8235182999Smav 8236184095Smav snprintf(status, SND_STATUSLEN, "at cad %d nid %d on %s %s", 8237184095Smav pdevinfo->devinfo->codec->cad, pdevinfo->devinfo->nid, 8238184095Smav device_get_nameunit(sc->dev), PCM_KLDSTRING(snd_hda)); 8239182999Smav pcm_setstatus(dev, status); 8240182999Smav 8241182999Smav return (0); 8242182999Smav} 8243182999Smav 8244182999Smavstatic int 8245182999Smavhdac_pcm_detach(device_t dev) 8246182999Smav{ 8247182999Smav struct hdac_pcm_devinfo *pdevinfo = 8248182999Smav (struct hdac_pcm_devinfo *)device_get_ivars(dev); 8249182999Smav int err; 8250182999Smav 8251182999Smav if (pdevinfo->registered > 0) { 8252182999Smav err = pcm_unregister(dev); 8253182999Smav if (err != 0) 8254182999Smav return (err); 8255182999Smav } 8256182999Smav 8257182999Smav return (0); 8258182999Smav} 8259182999Smav 8260182999Smavstatic device_method_t hdac_pcm_methods[] = { 8261182999Smav /* device interface */ 8262182999Smav DEVMETHOD(device_probe, hdac_pcm_probe), 8263182999Smav DEVMETHOD(device_attach, hdac_pcm_attach), 8264182999Smav DEVMETHOD(device_detach, hdac_pcm_detach), 8265182999Smav { 0, 0 } 8266182999Smav}; 8267182999Smav 8268182999Smavstatic driver_t hdac_pcm_driver = { 8269182999Smav "pcm", 8270182999Smav hdac_pcm_methods, 8271182999Smav PCM_SOFTC_SIZE, 8272182999Smav}; 8273182999Smav 8274182999SmavDRIVER_MODULE(snd_hda_pcm, hdac, hdac_pcm_driver, pcm_devclass, 0, 0); 8275182999Smav 8276