hdac.c revision 178324
1162922Sariff/*- 2162922Sariff * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3162922Sariff * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4162922Sariff * All rights reserved. 5162922Sariff * 6162922Sariff * Redistribution and use in source and binary forms, with or without 7162922Sariff * modification, are permitted provided that the following conditions 8162922Sariff * are met: 9162922Sariff * 1. Redistributions of source code must retain the above copyright 10162922Sariff * notice, this list of conditions and the following disclaimer. 11162922Sariff * 2. Redistributions in binary form must reproduce the above copyright 12162922Sariff * notice, this list of conditions and the following disclaimer in the 13162922Sariff * documentation and/or other materials provided with the distribution. 14162922Sariff * 15162922Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18162922Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25162922Sariff * SUCH DAMAGE. 26162922Sariff */ 27162922Sariff 28162922Sariff/* 29162922Sariff * Intel High Definition Audio (Controller) driver for FreeBSD. Be advised 30162922Sariff * that this driver still in its early stage, and possible of rewrite are 31162922Sariff * pretty much guaranteed. There are supposedly several distinct parent/child 32162922Sariff * busses to make this "perfect", but as for now and for the sake of 33162922Sariff * simplicity, everything is gobble up within single source. 34162922Sariff * 35162922Sariff * List of subsys: 36162922Sariff * 1) HDA Controller support 37162922Sariff * 2) HDA Codecs support, which may include 38162922Sariff * - HDA 39162922Sariff * - Modem 40162922Sariff * - HDMI 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> * 64162922Sariff * * * 65162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 66162922Sariff * * * 67162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 68162922Sariff */ 69162922Sariff 70162922Sariff#include <dev/sound/pcm/sound.h> 71162922Sariff#include <dev/pci/pcireg.h> 72162922Sariff#include <dev/pci/pcivar.h> 73162922Sariff 74171141Sariff#include <sys/ctype.h> 75171141Sariff#include <sys/taskqueue.h> 76171141Sariff 77162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 78162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 79162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 80162922Sariff#include <dev/sound/pci/hda/hdac.h> 81162922Sariff 82162922Sariff#include "mixer_if.h" 83162922Sariff 84178324Sariff#define HDA_DRV_TEST_REV "20080420_0052" 85162922Sariff#define HDA_WIDGET_PARSER_REV 1 86162922Sariff 87162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 178324 2008-04-19 22:32:23Z ariff $"); 88162922Sariff 89169277Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 90169277Sariff if (bootverbose != 0 || snd_verbose > 3) { \ 91169277Sariff stmt \ 92169277Sariff } \ 93162922Sariff} while(0) 94162922Sariff 95162965Sariff#if 1 96162922Sariff#undef HDAC_INTR_EXTRA 97162922Sariff#define HDAC_INTR_EXTRA 1 98162922Sariff#endif 99162922Sariff 100162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 101162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 102163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 103163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 104162922Sariff 105178155Sariff#undef HDAC_MSI_ENABLED 106178155Sariff#if __FreeBSD_version >= 700026 || \ 107178155Sariff (__FreeBSD_version < 700000 && __FreeBSD_version >= 602106) 108178155Sariff#define HDAC_MSI_ENABLED 1 109178155Sariff#endif 110178155Sariff 111162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 112163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 113163257Sariff (fl) == 0xffffffff || \ 114163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 115163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 116163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 117163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 118162965Sariff#define HDA_MATCH_ALL 0xffffffff 119162965Sariff#define HDAC_INVALID 0xffffffff 120162965Sariff 121169277Sariff/* Default controller / jack sense poll: 250ms */ 122169277Sariff#define HDAC_POLL_INTERVAL max(hz >> 2, 1) 123169277Sariff 124171141Sariff/* 125171141Sariff * Make room for possible 4096 playback/record channels, in 100 years to come. 126171141Sariff */ 127171141Sariff#define HDAC_TRIGGER_NONE 0x00000000 128171141Sariff#define HDAC_TRIGGER_PLAY 0x00000fff 129171141Sariff#define HDAC_TRIGGER_REC 0x00fff000 130171141Sariff#define HDAC_TRIGGER_UNSOL 0x80000000 131171141Sariff 132162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 133162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 134162922Sariff 135162922Sariff/* Controller models */ 136162922Sariff 137162922Sariff/* Intel */ 138162922Sariff#define INTEL_VENDORID 0x8086 139162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 140171330Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 141162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 142163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 143171330Sariff#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e) 144162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 145162922Sariff 146162922Sariff/* Nvidia */ 147162922Sariff#define NVIDIA_VENDORID 0x10de 148162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 149162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 150173817Sariff#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 151173817Sariff#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 152173817Sariff#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 153173817Sariff#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 154173817Sariff#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c) 155173817Sariff#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d) 156162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 157162922Sariff 158162922Sariff/* ATI */ 159162922Sariff#define ATI_VENDORID 0x1002 160162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 161163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 162162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 163162922Sariff 164163136Sariff/* VIA */ 165163136Sariff#define VIA_VENDORID 0x1106 166163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 167163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 168163136Sariff 169163136Sariff/* SiS */ 170163136Sariff#define SIS_VENDORID 0x1039 171163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 172163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 173163136Sariff 174162922Sariff/* OEM/subvendors */ 175162922Sariff 176165466Sariff/* Intel */ 177165466Sariff#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600) 178165466Sariff 179162922Sariff/* HP/Compaq */ 180162922Sariff#define HP_VENDORID 0x103c 181162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 182162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 183162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 184165281Sariff#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0) 185166294Sariff#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013) 186169277Sariff#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010) 187169277Sariff#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5) 188174579Sariff#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801) 189172811Sariff#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802) 190162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 191165281Sariff/* What is wrong with XN 2563 anyway? (Got the picture ?) */ 192165281Sariff#define HP_NX6325_SUBVENDORX 0x103c30b0 193162922Sariff 194162922Sariff/* Dell */ 195162922Sariff#define DELL_VENDORID 0x1028 196162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 197178155Sariff#define DELL_V1500_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x0228) 198162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 199169277Sariff#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7) 200169277Sariff#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da) 201162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 202162922Sariff 203162922Sariff/* Clevo */ 204162922Sariff#define CLEVO_VENDORID 0x1558 205162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 206162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 207162922Sariff 208162922Sariff/* Acer */ 209162922Sariff#define ACER_VENDORID 0x1025 210165992Sariff#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f) 211173817Sariff#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127) 212174182Sariff#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f) 213169277Sariff#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110) 214162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 215162922Sariff 216162965Sariff/* Asus */ 217162965Sariff#define ASUS_VENDORID 0x1043 218178155Sariff#define ASUS_A8X_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 219163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 220178155Sariff#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 221165281Sariff#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323) 222178155Sariff#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338) 223178155Sariff#define ASUS_G2K_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1339) 224167623Sariff#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2) 225169277Sariff#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971) 226178155Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 227178155Sariff#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 228178155Sariff#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb) 229170518Sariff#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7) 230178155Sariff#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec) 231169277Sariff#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234) 232171141Sariff#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84) 233162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 234162922Sariff 235163257Sariff/* IBM / Lenovo */ 236163257Sariff#define IBM_VENDORID 0x1014 237163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 238163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 239162965Sariff 240164614Sariff/* Lenovo */ 241164657Sariff#define LENOVO_VENDORID 0x17aa 242164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 243172811Sariff#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015) 244164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 245163257Sariff 246164657Sariff/* Samsung */ 247164657Sariff#define SAMSUNG_VENDORID 0x144d 248164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 249164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 250164614Sariff 251164750Sariff/* Medion ? */ 252164750Sariff#define MEDION_VENDORID 0x161f 253164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 254164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 255164750Sariff 256173817Sariff/* Apple Computer Inc. */ 257173817Sariff#define APPLE_VENDORID 0x106b 258173817Sariff#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1) 259173817Sariff 260164828Sariff/* 261164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 262164828Sariff * instead of their own, which is beyond my comprehension 263164828Sariff * (see HDA_CODEC_STAC9221 below). 264164828Sariff */ 265164828Sariff#define APPLE_INTEL_MAC 0x76808384 266164828Sariff 267165281Sariff/* LG Electronics */ 268165281Sariff#define LG_VENDORID 0x1854 269165281Sariff#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018) 270165281Sariff#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff) 271165281Sariff 272165351Sariff/* Fujitsu Siemens */ 273165351Sariff#define FS_VENDORID 0x1734 274165351Sariff#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8) 275172811Sariff#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd) 276165351Sariff#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff) 277165351Sariff 278172811Sariff/* Fujitsu Limited */ 279172811Sariff#define FL_VENDORID 0x10cf 280172811Sariff#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326) 281172811Sariff#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff) 282172811Sariff 283165770Sariff/* Toshiba */ 284165770Sariff#define TOSHIBA_VENDORID 0x1179 285165770Sariff#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001) 286173817Sariff#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01) 287165770Sariff#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff) 288165770Sariff 289165992Sariff/* Micro-Star International (MSI) */ 290165992Sariff#define MSI_VENDORID 0x1462 291165992Sariff#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349) 292172811Sariff#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a) 293165992Sariff#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff) 294165992Sariff 295172811Sariff/* Giga-Byte Technology */ 296172811Sariff#define GB_VENDORID 0x1458 297172811Sariff#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022) 298172811Sariff#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff) 299172811Sariff 300169277Sariff/* Uniwill ? */ 301169277Sariff#define UNIWILL_VENDORID 0x1584 302169277Sariff#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075) 303170944Sariff#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080) 304169277Sariff 305169277Sariff 306162922Sariff/* Misc constants.. */ 307162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 308162922Sariff#define HDA_AMP_MUTE_NONE (0) 309162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 310162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 311162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 312162922Sariff 313162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 314162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 315162922Sariff 316162922Sariff#define HDA_DAC_PATH (1 << 0) 317162922Sariff#define HDA_ADC_PATH (1 << 1) 318162922Sariff#define HDA_ADC_RECSEL (1 << 2) 319162922Sariff 320169277Sariff#define HDA_DAC_LOCKED (1 << 3) 321169277Sariff#define HDA_ADC_LOCKED (1 << 4) 322169277Sariff 323163057Sariff#define HDA_CTL_OUT (1 << 0) 324163057Sariff#define HDA_CTL_IN (1 << 1) 325162922Sariff#define HDA_CTL_BOTH (HDA_CTL_IN | HDA_CTL_OUT) 326162922Sariff 327169277Sariff#define HDA_GPIO_MAX 8 328169277Sariff/* 0 - 7 = GPIO , 8 = Flush */ 329163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 330163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 331163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 332169277Sariff#define HDA_QUIRK_GPIO3 (1 << 3) 333169277Sariff#define HDA_QUIRK_GPIO4 (1 << 4) 334169277Sariff#define HDA_QUIRK_GPIO5 (1 << 5) 335169277Sariff#define HDA_QUIRK_GPIO6 (1 << 6) 336169277Sariff#define HDA_QUIRK_GPIO7 (1 << 7) 337169277Sariff#define HDA_QUIRK_GPIOFLUSH (1 << 8) 338162922Sariff 339169277Sariff/* 9 - 25 = anything else */ 340169277Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 9) 341169277Sariff#define HDA_QUIRK_FIXEDRATE (1 << 10) 342169277Sariff#define HDA_QUIRK_FORCESTEREO (1 << 11) 343169277Sariff#define HDA_QUIRK_EAPDINV (1 << 12) 344169277Sariff#define HDA_QUIRK_DMAPOS (1 << 13) 345169277Sariff 346169277Sariff/* 26 - 31 = vrefs */ 347169277Sariff#define HDA_QUIRK_IVREF50 (1 << 26) 348169277Sariff#define HDA_QUIRK_IVREF80 (1 << 27) 349169277Sariff#define HDA_QUIRK_IVREF100 (1 << 28) 350169277Sariff#define HDA_QUIRK_OVREF50 (1 << 29) 351169277Sariff#define HDA_QUIRK_OVREF80 (1 << 30) 352169277Sariff#define HDA_QUIRK_OVREF100 (1 << 31) 353169277Sariff 354169277Sariff#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \ 355169277Sariff HDA_QUIRK_IVREF100) 356169277Sariff#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \ 357169277Sariff HDA_QUIRK_OVREF100) 358169277Sariff#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF) 359169277Sariff 360169277Sariff#define SOUND_MASK_SKIP (1 << 30) 361169277Sariff#define SOUND_MASK_DISABLE (1 << 31) 362169277Sariff 363171141Sariff#if __FreeBSD_version < 600000 364171141Sariff#define taskqueue_drain(...) 365171141Sariff#endif 366171141Sariff 367163057Sariffstatic const struct { 368163057Sariff char *key; 369163057Sariff uint32_t value; 370163057Sariff} hdac_quirks_tab[] = { 371163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 372163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 373163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 374169277Sariff { "gpio3", HDA_QUIRK_GPIO3 }, 375169277Sariff { "gpio4", HDA_QUIRK_GPIO4 }, 376169277Sariff { "gpio5", HDA_QUIRK_GPIO5 }, 377169277Sariff { "gpio6", HDA_QUIRK_GPIO6 }, 378169277Sariff { "gpio7", HDA_QUIRK_GPIO7 }, 379165039Sariff { "gpioflush", HDA_QUIRK_GPIOFLUSH }, 380163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 381163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 382163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 383163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 384169277Sariff { "dmapos", HDA_QUIRK_DMAPOS }, 385169277Sariff { "ivref50", HDA_QUIRK_IVREF50 }, 386169277Sariff { "ivref80", HDA_QUIRK_IVREF80 }, 387169277Sariff { "ivref100", HDA_QUIRK_IVREF100 }, 388169277Sariff { "ovref50", HDA_QUIRK_OVREF50 }, 389169277Sariff { "ovref80", HDA_QUIRK_OVREF80 }, 390169277Sariff { "ovref100", HDA_QUIRK_OVREF100 }, 391169277Sariff { "ivref", HDA_QUIRK_IVREF }, 392169277Sariff { "ovref", HDA_QUIRK_OVREF }, 393165069Sariff { "vref", HDA_QUIRK_VREF }, 394163057Sariff}; 395163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 396163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 397163057Sariff 398162922Sariff#define HDA_BDL_MIN 2 399162922Sariff#define HDA_BDL_MAX 256 400162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 401162922Sariff 402169277Sariff#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT 403167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 404167648Sariff 405162922Sariff#define HDA_BUFSZ_MIN 4096 406162922Sariff#define HDA_BUFSZ_MAX 65536 407162922Sariff#define HDA_BUFSZ_DEFAULT 16384 408162922Sariff 409162922Sariff#define HDA_PARSE_MAXDEPTH 10 410162922Sariff 411169277Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 412169277Sariff#define HDAC_UNSOLTAG_EVENT_TEST 0x01 413162922Sariff 414165239SariffMALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 415162922Sariff 416162922Sariffenum { 417162922Sariff HDA_PARSE_MIXER, 418162922Sariff HDA_PARSE_DIRECT 419162922Sariff}; 420162922Sariff 421162922Sariff/* Default */ 422162922Sariffstatic uint32_t hdac_fmt[] = { 423162922Sariff AFMT_STEREO | AFMT_S16_LE, 424162922Sariff 0 425162922Sariff}; 426162922Sariff 427162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 428162922Sariff 429162922Sariffstatic const struct { 430162922Sariff uint32_t model; 431162922Sariff char *desc; 432162922Sariff} hdac_devices[] = { 433162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 434171330Sariff { HDA_INTEL_63XXESB, "Intel 631x/632xESB" }, 435162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 436163136Sariff { HDA_INTEL_82801H, "Intel 82801H" }, 437171330Sariff { HDA_INTEL_82801I, "Intel 82801I" }, 438162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 439162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 440173817Sariff { HDA_NVIDIA_MCP61_1, "NVidia MCP61" }, 441173817Sariff { HDA_NVIDIA_MCP61_2, "NVidia MCP61" }, 442173817Sariff { HDA_NVIDIA_MCP65_1, "NVidia MCP65" }, 443174004Sariff { HDA_NVIDIA_MCP65_2, "NVidia MCP65" }, 444173817Sariff { HDA_NVIDIA_MCP67_1, "NVidia MCP67" }, 445173817Sariff { HDA_NVIDIA_MCP67_2, "NVidia MCP67" }, 446162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 447163136Sariff { HDA_ATI_SB600, "ATI SB600" }, 448163136Sariff { HDA_VIA_VT82XX, "VIA VT8251/8237A" }, 449163136Sariff { HDA_SIS_966, "SiS 966" }, 450162922Sariff /* Unknown */ 451162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 452162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 453162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 454163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 455163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 456162922Sariff}; 457162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 458162922Sariff 459162922Sariffstatic const struct { 460169277Sariff uint16_t vendor; 461169277Sariff uint8_t reg; 462169277Sariff uint8_t mask; 463169277Sariff uint8_t enable; 464169277Sariff} hdac_pcie_snoop[] = { 465169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 466169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 467169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 468169277Sariff}; 469169277Sariff#define HDAC_PCIESNOOP_LEN \ 470169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 471169277Sariff 472169277Sariffstatic const struct { 473162922Sariff uint32_t rate; 474162922Sariff int valid; 475162922Sariff uint16_t base; 476162922Sariff uint16_t mul; 477162922Sariff uint16_t div; 478162922Sariff} hda_rate_tab[] = { 479162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 480162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 481162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 482162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 483162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 484162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 485162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 486162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 487162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 488162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 489162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 490162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 491162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 492162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 493162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 494162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 495162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 496162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 497162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 498162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 499162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 500162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 501162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 502162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 503162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 504162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 505162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 506162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 507162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 508162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 509162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 510162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 511162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 512162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 513162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 514162922Sariff}; 515162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 516162922Sariff 517162922Sariff/* All codecs you can eat... */ 518162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 519162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 520162922Sariff 521162922Sariff/* Realtek */ 522162922Sariff#define REALTEK_VENDORID 0x10ec 523162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 524169277Sariff#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) 525171330Sariff#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) 526170518Sariff#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) 527162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 528169277Sariff#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) 529162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 530163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 531163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 532169277Sariff#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) 533165305Sariff#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) 534162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 535162922Sariff 536169277Sariff/* Analog Devices */ 537169277Sariff#define ANALOGDEVICES_VENDORID 0x11d4 538169277Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) 539169277Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) 540174025Sariff#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) 541169277Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) 542169277Sariff#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) 543170518Sariff#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) 544169277Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) 545162922Sariff 546162922Sariff/* CMedia */ 547162922Sariff#define CMEDIA_VENDORID 0x434d 548162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 549162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 550162922Sariff 551162922Sariff/* Sigmatel */ 552162922Sariff#define SIGMATEL_VENDORID 0x8384 553162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 554162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 555162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 556162922Sariff#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 557165305Sariff#define HDA_CODEC_STAC9227 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) 558166796Sariff#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) 559178155Sariff#define HDA_CODEC_STAC9205 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) 560162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 561162922Sariff 562162922Sariff/* 563162922Sariff * Conexant 564162922Sariff * 565162922Sariff * Ok, the truth is, I don't have any idea at all whether 566162922Sariff * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only 567162922Sariff * place that tell me it is "Venice" is from its Windows driver INF. 568163057Sariff * 569163057Sariff * Venice - CX????? 570163057Sariff * Waikiki - CX20551-22 571162922Sariff */ 572162922Sariff#define CONEXANT_VENDORID 0x14f1 573162922Sariff#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 574163057Sariff#define HDA_CODEC_CXWAIKIKI HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 575162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 576162922Sariff 577169277Sariff/* VIA */ 578169277Sariff#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) 579169277Sariff#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) 580169277Sariff#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) 581169277Sariff#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) 582169277Sariff#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) 583169277Sariff#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) 584169277Sariff#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) 585169277Sariff#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) 586169277Sariff#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) 587169277Sariff#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) 588169277Sariff#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) 589169277Sariff#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) 590169277Sariff#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) 591162922Sariff 592169277Sariff 593162922Sariff/* Codecs */ 594162922Sariffstatic const struct { 595162922Sariff uint32_t id; 596162922Sariff char *name; 597162922Sariff} hdac_codecs[] = { 598162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 599169277Sariff { HDA_CODEC_ALC262, "Realtek ALC262" }, 600171330Sariff { HDA_CODEC_ALC268, "Realtek ALC268" }, 601170518Sariff { HDA_CODEC_ALC660, "Realtek ALC660" }, 602162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 603169277Sariff { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" }, 604162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 605162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 606163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 607169277Sariff { HDA_CODEC_ALC885, "Realtek ALC885" }, 608165305Sariff { HDA_CODEC_ALC888, "Realtek ALC888" }, 609169277Sariff { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" }, 610169277Sariff { HDA_CODEC_AD1983, "Analog Devices AD1983" }, 611174025Sariff { HDA_CODEC_AD1984, "Analog Devices AD1984" }, 612169277Sariff { HDA_CODEC_AD1986A, "Analog Devices AD1986A" }, 613169277Sariff { HDA_CODEC_AD1988, "Analog Devices AD1988" }, 614170518Sariff { HDA_CODEC_AD1988B, "Analog Devices AD1988B" }, 615162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 616162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 617162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 618162922Sariff { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 619162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 620165305Sariff { HDA_CODEC_STAC9227, "Sigmatel STAC9227" }, 621166796Sariff { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" }, 622178155Sariff { HDA_CODEC_STAC9205, "Sigmatel STAC9205" }, 623162922Sariff { HDA_CODEC_CXVENICE, "Conexant Venice" }, 624163057Sariff { HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" }, 625169277Sariff { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, 626169277Sariff { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, 627169277Sariff { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, 628169277Sariff { HDA_CODEC_VT1708_B, "VIA VT1708_B" }, 629169277Sariff { HDA_CODEC_VT1709_0, "VIA VT1709_0" }, 630169277Sariff { HDA_CODEC_VT1709_1, "VIA VT1709_1" }, 631169277Sariff { HDA_CODEC_VT1709_2, "VIA VT1709_2" }, 632169277Sariff { HDA_CODEC_VT1709_3, "VIA VT1709_3" }, 633169277Sariff { HDA_CODEC_VT1709_4, "VIA VT1709_4" }, 634169277Sariff { HDA_CODEC_VT1709_5, "VIA VT1709_5" }, 635169277Sariff { HDA_CODEC_VT1709_6, "VIA VT1709_6" }, 636169277Sariff { HDA_CODEC_VT1709_7, "VIA VT1709_7" }, 637162922Sariff /* Unknown codec */ 638162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 639169277Sariff { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" }, 640162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 641162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 642162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 643169277Sariff { HDA_CODEC_VTXXXX, "VIA (Unknown)" }, 644162922Sariff}; 645162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 646162922Sariff 647162922Sariffenum { 648162922Sariff HDAC_HP_SWITCH_CTL, 649169277Sariff HDAC_HP_SWITCH_CTRL, 650169277Sariff HDAC_HP_SWITCH_DEBUG 651162922Sariff}; 652162922Sariff 653162922Sariffstatic const struct { 654162965Sariff uint32_t model; 655162922Sariff uint32_t id; 656162922Sariff int type; 657165039Sariff int inverted; 658169277Sariff int polling; 659169277Sariff int execsense; 660162922Sariff nid_t hpnid; 661162922Sariff nid_t spkrnid[8]; 662162922Sariff nid_t eapdnid; 663162922Sariff} hdac_hp_switch[] = { 664162922Sariff /* Specific OEM models */ 665169277Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 666169277Sariff 0, 0, -1, 17, { 16, -1 }, 16 }, 667169277Sariff /* { HP_XW4300_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL, 668169277Sariff 0, 0, -1, 21, { 16, 17, -1 }, -1 } */ 669172811Sariff /* { HP_3010_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_DEBUG, 670172811Sariff 0, 1, 0, 16, { 15, 18, 19, 20, 21, -1 }, -1 }, */ 671169277Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 672169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 673169277Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 674169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 675169277Sariff { HP_NX6325_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 676169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 677172811Sariff /* { HP_DC7700_SUBVENDOR, HDA_CODEC_ALC262, HDAC_HP_SWITCH_CTL, 678172811Sariff 0, 0, -1, 21, { 22, 27, -1 }, -1 }, */ 679169277Sariff { TOSHIBA_U200_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 680169277Sariff 0, 0, -1, 6, { 5, -1 }, -1 }, 681173817Sariff { TOSHIBA_A135_SUBVENDOR, HDA_CODEC_ALC861VD, HDAC_HP_SWITCH_CTL, 682173817Sariff 0, 0, -1, 27, { 20, -1 }, -1 }, 683169277Sariff { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 684169277Sariff 0, 0, -1, 13, { 14, -1 }, -1 }, 685169277Sariff { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 686169277Sariff 0, 0, -1, 13, { 14, -1 }, -1 }, 687169277Sariff { DELL_OPLX745_SUBVENDOR, HDA_CODEC_AD1983, HDAC_HP_SWITCH_CTL, 688169277Sariff 0, 0, -1, 6, { 5, 7, -1 }, -1 }, 689178155Sariff { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205, HDAC_HP_SWITCH_CTRL, 690178155Sariff 0, 0, -1, 10, { 13, -1 }, -1 }, 691173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDAC_HP_SWITCH_CTL, 692173817Sariff 0, 0, -1, 21, { 20, 22, -1 }, -1 }, 693169277Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL, 694169277Sariff 0, 0, -1, 10, { 13, -1 }, -1 }, 695169277Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 696169277Sariff 1, 0, -1, 26, { 27, -1 }, -1 }, 697172811Sariff /* { LENOVO_TCA55_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 698172811Sariff 0, 0, -1, 26, { 27, 28, 29, 30, -1 }, -1 }, */ 699169277Sariff { LG_LW20_SUBVENDOR, HDA_CODEC_ALC880, HDAC_HP_SWITCH_CTL, 700169277Sariff 0, 0, -1, 27, { 20, -1 }, -1 }, 701169277Sariff { ACER_A5050_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 702169277Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 703169277Sariff { ACER_3681WXM_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 704169277Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 705173817Sariff { ACER_A4520_SUBVENDOR, HDA_CODEC_ALC268, HDAC_HP_SWITCH_CTL, 706173817Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 707174182Sariff { ACER_A4710_SUBVENDOR, HDA_CODEC_ALC268, HDAC_HP_SWITCH_CTL, 708174182Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 709170944Sariff { UNIWILL_9080_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 710170944Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 711169277Sariff { MSI_MS1034_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 712169277Sariff 0, 0, -1, 20, { 27, -1 }, -1 }, 713172811Sariff { MSI_MS034A_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 714172811Sariff 0, 0, -1, 20, { 27, -1 }, -1 }, 715172811Sariff { FS_SI1848_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 716172811Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 717172811Sariff { FL_S7020D_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL, 718172811Sariff 0, 0, -1, 20, { 16, -1 }, -1 }, 719162922Sariff /* 720162922Sariff * All models that at least come from the same vendor with 721162922Sariff * simmilar codec. 722162922Sariff */ 723169277Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 724169277Sariff 0, 0, -1, 17, { 16, -1 }, 16 }, 725169277Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 726169277Sariff 0, 0, -1, 6, { 5, -1 }, 5 }, 727169277Sariff { TOSHIBA_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 728169277Sariff 0, 0, -1, 6, { 5, -1 }, -1 }, 729169277Sariff { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 730169277Sariff 0, 0, -1, 13, { 14, -1 }, -1 }, 731172811Sariff#if 0 732169277Sariff { LENOVO_ALL_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 733169277Sariff 1, 0, -1, 26, { 27, -1 }, -1 }, 734169277Sariff { ACER_ALL_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL, 735169277Sariff 0, 0, -1, 20, { 21, -1 }, -1 }, 736166294Sariff#endif 737162922Sariff}; 738162922Sariff#define HDAC_HP_SWITCH_LEN \ 739162922Sariff (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0])) 740162922Sariff 741162922Sariffstatic const struct { 742162965Sariff uint32_t model; 743162922Sariff uint32_t id; 744162922Sariff nid_t eapdnid; 745162922Sariff int hp_switch; 746162922Sariff} hdac_eapd_switch[] = { 747162922Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, 16, 1 }, 748162922Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 749162922Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 750162922Sariff}; 751162922Sariff#define HDAC_EAPD_SWITCH_LEN \ 752162922Sariff (sizeof(hdac_eapd_switch) / sizeof(hdac_eapd_switch[0])) 753162922Sariff 754162922Sariff/**************************************************************************** 755162922Sariff * Function prototypes 756162922Sariff ****************************************************************************/ 757162922Sariffstatic void hdac_intr_handler(void *); 758162922Sariffstatic int hdac_reset(struct hdac_softc *); 759162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 760162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 761162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 762162922Sariff struct hdac_dma *, bus_size_t); 763169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 764162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 765162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 766162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 767162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 768162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 769162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 770162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 771162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 772172811Sariffstatic void hdac_scan_codecs(struct hdac_softc *, int); 773162922Sariffstatic int hdac_probe_codec(struct hdac_codec *); 774162922Sariffstatic struct hdac_devinfo *hdac_probe_function(struct hdac_codec *, nid_t); 775162922Sariffstatic void hdac_add_child(struct hdac_softc *, struct hdac_devinfo *); 776162922Sariff 777162922Sariffstatic void hdac_attach2(void *); 778162922Sariff 779162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 780162922Sariff uint32_t, int); 781162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 782162922Sariff struct hdac_command_list *, int); 783162922Sariff 784162922Sariffstatic int hdac_probe(device_t); 785162922Sariffstatic int hdac_attach(device_t); 786162922Sariffstatic int hdac_detach(device_t); 787162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 788162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 789162922Sariff uint32_t, int, int); 790162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 791162922Sariff nid_t, int, int); 792162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 793162922Sariff nid_t, nid_t, int, int, int, int, int, int); 794162922Sariffstatic int hdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *); 795162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 796162922Sariff 797164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 798164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 799164614Sariff 800162922Sariff#define hdac_command(a1, a2, a3) \ 801162922Sariff hdac_command_sendone_internal(a1, a2, a3) 802162922Sariff 803162922Sariff#define hdac_codec_id(d) \ 804162922Sariff ((uint32_t)((d == NULL) ? 0x00000000 : \ 805162922Sariff ((((uint32_t)(d)->vendor_id & 0x0000ffff) << 16) | \ 806162922Sariff ((uint32_t)(d)->device_id & 0x0000ffff)))) 807162922Sariff 808162922Sariffstatic char * 809162922Sariffhdac_codec_name(struct hdac_devinfo *devinfo) 810162922Sariff{ 811162922Sariff uint32_t id; 812162922Sariff int i; 813162922Sariff 814162922Sariff id = hdac_codec_id(devinfo); 815162922Sariff 816162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 817163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 818162922Sariff return (hdac_codecs[i].name); 819162922Sariff } 820162922Sariff 821162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 822162922Sariff} 823162922Sariff 824162922Sariffstatic char * 825162922Sariffhdac_audio_ctl_ossmixer_mask2name(uint32_t devmask) 826162922Sariff{ 827162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 828162922Sariff static char *unknown = "???"; 829162922Sariff int i; 830162922Sariff 831162922Sariff for (i = SOUND_MIXER_NRDEVICES - 1; i >= 0; i--) { 832162922Sariff if (devmask & (1 << i)) 833162922Sariff return (ossname[i]); 834162922Sariff } 835162922Sariff return (unknown); 836162922Sariff} 837162922Sariff 838162922Sariffstatic void 839162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 840162922Sariff{ 841162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 842162922Sariff int i, first = 1; 843162922Sariff 844162922Sariff bzero(buf, len); 845162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 846162922Sariff if (mask & (1 << i)) { 847162922Sariff if (first == 0) 848162922Sariff strlcat(buf, ", ", len); 849162922Sariff strlcat(buf, ossname[i], len); 850162922Sariff first = 0; 851162922Sariff } 852162922Sariff } 853162922Sariff} 854162922Sariff 855162922Sariffstatic struct hdac_audio_ctl * 856162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 857162922Sariff{ 858162922Sariff if (devinfo == NULL || 859162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 860162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 861162922Sariff devinfo->function.audio.ctlcnt < 1 || 862162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 863162922Sariff return (NULL); 864162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 865162922Sariff} 866162922Sariff 867162922Sariffstatic struct hdac_audio_ctl * 868162922Sariffhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, 869162922Sariff int index, int cnt) 870162922Sariff{ 871162922Sariff struct hdac_audio_ctl *ctl, *retctl = NULL; 872162922Sariff int i, at, atindex, found = 0; 873162922Sariff 874162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 875162922Sariff return (NULL); 876162922Sariff 877162922Sariff at = cnt; 878162922Sariff if (at == 0) 879162922Sariff at = 1; 880162922Sariff else if (at < 0) 881162922Sariff at = -1; 882162922Sariff atindex = index; 883162922Sariff if (atindex < 0) 884162922Sariff atindex = -1; 885162922Sariff 886162922Sariff i = 0; 887162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 888162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 889162922Sariff continue; 890162922Sariff if (!(ctl->widget->nid == nid && (atindex == -1 || 891162922Sariff ctl->index == atindex))) 892162922Sariff continue; 893162922Sariff found++; 894162922Sariff if (found == cnt) 895162922Sariff return (ctl); 896162922Sariff retctl = ctl; 897162922Sariff } 898162922Sariff 899162922Sariff return ((at == -1) ? retctl : NULL); 900162922Sariff} 901162922Sariff 902162922Sariffstatic void 903162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 904162922Sariff{ 905162922Sariff struct hdac_softc *sc; 906162922Sariff struct hdac_widget *w; 907162922Sariff struct hdac_audio_ctl *ctl; 908169277Sariff uint32_t val, id, res; 909171141Sariff int i = 0, j, timeout, forcemute; 910162922Sariff nid_t cad; 911162922Sariff 912162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 913162922Sariff devinfo->codec->sc == NULL) 914162922Sariff return; 915162922Sariff 916162922Sariff sc = devinfo->codec->sc; 917162922Sariff cad = devinfo->codec->cad; 918162922Sariff id = hdac_codec_id(devinfo); 919162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 920163257Sariff if (HDA_DEV_MATCH(hdac_hp_switch[i].model, 921162965Sariff sc->pci_subvendor) && 922162922Sariff hdac_hp_switch[i].id == id) 923162922Sariff break; 924162922Sariff } 925162922Sariff 926162922Sariff if (i >= HDAC_HP_SWITCH_LEN) 927162922Sariff return; 928162922Sariff 929162922Sariff forcemute = 0; 930162922Sariff if (hdac_hp_switch[i].eapdnid != -1) { 931162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid); 932162965Sariff if (w != NULL && w->param.eapdbtl != HDAC_INVALID) 933162922Sariff forcemute = (w->param.eapdbtl & 934162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1; 935162922Sariff } 936162922Sariff 937169277Sariff if (hdac_hp_switch[i].execsense != -1) 938169277Sariff hdac_command(sc, 939169277Sariff HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid, 940169277Sariff hdac_hp_switch[i].execsense), cad); 941171141Sariff 942171141Sariff timeout = 10000; 943171141Sariff do { 944171141Sariff res = hdac_command(sc, 945171141Sariff HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), 946171141Sariff cad); 947171141Sariff if (hdac_hp_switch[i].execsense == -1 || res != 0x7fffffff) 948171141Sariff break; 949171141Sariff DELAY(10); 950171141Sariff } while (--timeout != 0); 951171141Sariff 952163057Sariff HDA_BOOTVERBOSE( 953162922Sariff device_printf(sc->dev, 954171141Sariff "HDA_DEBUG: Pin sense: nid=%d timeout=%d res=0x%08x\n", 955171141Sariff hdac_hp_switch[i].hpnid, timeout, res); 956162922Sariff ); 957171141Sariff 958169277Sariff res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res); 959165039Sariff res ^= hdac_hp_switch[i].inverted; 960162922Sariff 961162922Sariff switch (hdac_hp_switch[i].type) { 962162922Sariff case HDAC_HP_SWITCH_CTL: 963162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 964162922Sariff hdac_hp_switch[i].hpnid, 0, 1); 965162922Sariff if (ctl != NULL) { 966169277Sariff val = (res != 0 && forcemute == 0) ? 967162922Sariff HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL; 968169277Sariff if (val != ctl->muted) { 969169277Sariff ctl->muted = val; 970162922Sariff hdac_audio_ctl_amp_set(ctl, 971162922Sariff HDA_AMP_MUTE_DEFAULT, ctl->left, 972162922Sariff ctl->right); 973162922Sariff } 974162922Sariff } 975169277Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 976169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 977169277Sariff hdac_hp_switch[i].spkrnid[j], 0, 1); 978169277Sariff if (ctl == NULL) 979169277Sariff continue; 980169277Sariff val = (res != 0 || forcemute == 1) ? 981169277Sariff HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE; 982169277Sariff if (val == ctl->muted) 983169277Sariff continue; 984169277Sariff ctl->muted = val; 985169277Sariff hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT, 986169277Sariff ctl->left, ctl->right); 987169277Sariff } 988162922Sariff break; 989162922Sariff case HDAC_HP_SWITCH_CTRL: 990162922Sariff if (res != 0) { 991162922Sariff /* HP in */ 992162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 993163057Sariff if (w != NULL && w->type == 994163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 995162922Sariff if (forcemute == 0) 996169277Sariff val = w->wclass.pin.ctrl | 997162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 998162922Sariff else 999169277Sariff val = w->wclass.pin.ctrl & 1000162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1001169277Sariff if (val != w->wclass.pin.ctrl) { 1002169277Sariff w->wclass.pin.ctrl = val; 1003169277Sariff hdac_command(sc, 1004169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1005169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1006169277Sariff } 1007162922Sariff } 1008162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 1009162922Sariff w = hdac_widget_get(devinfo, 1010162922Sariff hdac_hp_switch[i].spkrnid[j]); 1011169277Sariff if (w == NULL || w->type != 1012169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1013169277Sariff continue; 1014169277Sariff val = w->wclass.pin.ctrl & 1015169277Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1016169277Sariff if (val == w->wclass.pin.ctrl) 1017169277Sariff continue; 1018169277Sariff w->wclass.pin.ctrl = val; 1019169277Sariff hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL( 1020169277Sariff cad, w->nid, w->wclass.pin.ctrl), cad); 1021162922Sariff } 1022162922Sariff } else { 1023162922Sariff /* HP out */ 1024162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 1025163057Sariff if (w != NULL && w->type == 1026163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 1027169277Sariff val = w->wclass.pin.ctrl & 1028162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1029169277Sariff if (val != w->wclass.pin.ctrl) { 1030169277Sariff w->wclass.pin.ctrl = val; 1031169277Sariff hdac_command(sc, 1032169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 1033169277Sariff w->nid, w->wclass.pin.ctrl), cad); 1034169277Sariff } 1035162922Sariff } 1036162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 1037162922Sariff w = hdac_widget_get(devinfo, 1038162922Sariff hdac_hp_switch[i].spkrnid[j]); 1039169277Sariff if (w == NULL || w->type != 1040169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1041169277Sariff continue; 1042169277Sariff if (forcemute == 0) 1043169277Sariff val = w->wclass.pin.ctrl | 1044169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1045169277Sariff else 1046169277Sariff val = w->wclass.pin.ctrl & 1047169277Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1048169277Sariff if (val == w->wclass.pin.ctrl) 1049169277Sariff continue; 1050169277Sariff w->wclass.pin.ctrl = val; 1051169277Sariff hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL( 1052169277Sariff cad, w->nid, w->wclass.pin.ctrl), cad); 1053162922Sariff } 1054162922Sariff } 1055162922Sariff break; 1056169277Sariff case HDAC_HP_SWITCH_DEBUG: 1057169277Sariff if (hdac_hp_switch[i].execsense != -1) 1058169277Sariff hdac_command(sc, 1059169277Sariff HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid, 1060169277Sariff hdac_hp_switch[i].execsense), cad); 1061169277Sariff res = hdac_command(sc, 1062169277Sariff HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad); 1063169277Sariff device_printf(sc->dev, 1064169277Sariff "[ 0] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n", 1065169277Sariff hdac_hp_switch[i].hpnid, res); 1066169277Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 1067169277Sariff w = hdac_widget_get(devinfo, 1068169277Sariff hdac_hp_switch[i].spkrnid[j]); 1069169277Sariff if (w == NULL || w->type != 1070169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1071169277Sariff continue; 1072169277Sariff if (hdac_hp_switch[i].execsense != -1) 1073169277Sariff hdac_command(sc, 1074169277Sariff HDA_CMD_SET_PIN_SENSE(cad, w->nid, 1075169277Sariff hdac_hp_switch[i].execsense), cad); 1076169277Sariff res = hdac_command(sc, 1077169277Sariff HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 1078169277Sariff device_printf(sc->dev, 1079169277Sariff "[%2d] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n", 1080169277Sariff j + 1, w->nid, res); 1081169277Sariff } 1082169277Sariff break; 1083162922Sariff default: 1084162922Sariff break; 1085162922Sariff } 1086162922Sariff} 1087162922Sariff 1088162922Sariffstatic void 1089162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 1090162922Sariff{ 1091162922Sariff struct hdac_softc *sc; 1092162922Sariff struct hdac_devinfo *devinfo = NULL; 1093162965Sariff device_t *devlist = NULL; 1094162922Sariff int devcount, i; 1095162922Sariff 1096162922Sariff if (codec == NULL || codec->sc == NULL) 1097162922Sariff return; 1098162922Sariff 1099162922Sariff sc = codec->sc; 1100162922Sariff 1101163057Sariff HDA_BOOTVERBOSE( 1102163057Sariff device_printf(sc->dev, "HDA_DEBUG: Unsol Tag: 0x%08x\n", tag); 1103162922Sariff ); 1104162922Sariff 1105162922Sariff device_get_children(sc->dev, &devlist, &devcount); 1106162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 1107162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 1108162965Sariff if (devinfo != NULL && devinfo->node_type == 1109162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 1110162965Sariff devinfo->codec != NULL && 1111162965Sariff devinfo->codec->cad == codec->cad) { 1112162965Sariff break; 1113162965Sariff } else 1114162965Sariff devinfo = NULL; 1115162922Sariff } 1116162965Sariff if (devlist != NULL) 1117162965Sariff free(devlist, M_TEMP); 1118162965Sariff 1119162922Sariff if (devinfo == NULL) 1120162922Sariff return; 1121162922Sariff 1122162922Sariff switch (tag) { 1123162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 1124162922Sariff hdac_hp_switch_handler(devinfo); 1125162922Sariff break; 1126169277Sariff case HDAC_UNSOLTAG_EVENT_TEST: 1127169277Sariff device_printf(sc->dev, "Unsol Test!\n"); 1128169277Sariff break; 1129162922Sariff default: 1130162922Sariff break; 1131162922Sariff } 1132162922Sariff} 1133162922Sariff 1134164614Sariffstatic int 1135162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 1136162922Sariff{ 1137162922Sariff /* XXX to be removed */ 1138162922Sariff#ifdef HDAC_INTR_EXTRA 1139162922Sariff uint32_t res; 1140162922Sariff#endif 1141162922Sariff 1142171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 1143164614Sariff return (0); 1144162922Sariff 1145162922Sariff /* XXX to be removed */ 1146162922Sariff#ifdef HDAC_INTR_EXTRA 1147162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 1148162922Sariff#endif 1149162922Sariff 1150162922Sariff /* XXX to be removed */ 1151162922Sariff#ifdef HDAC_INTR_EXTRA 1152163057Sariff HDA_BOOTVERBOSE( 1153163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 1154163057Sariff device_printf(sc->dev, 1155163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 1156163057Sariff "%08x\n", 1157163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 1158163057Sariff ); 1159162922Sariff#endif 1160162922Sariff 1161162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 1162163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 1163162922Sariff 1164162922Sariff /* XXX to be removed */ 1165162922Sariff#ifdef HDAC_INTR_EXTRA 1166162922Sariff if (res & HDAC_SDSTS_BCIS) { 1167162922Sariff#endif 1168164614Sariff return (1); 1169162922Sariff /* XXX to be removed */ 1170162922Sariff#ifdef HDAC_INTR_EXTRA 1171162922Sariff } 1172162922Sariff#endif 1173164614Sariff 1174164614Sariff return (0); 1175162922Sariff} 1176162922Sariff 1177162922Sariff/**************************************************************************** 1178162922Sariff * void hdac_intr_handler(void *) 1179162922Sariff * 1180162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 1181162922Sariff ****************************************************************************/ 1182162922Sariffstatic void 1183162922Sariffhdac_intr_handler(void *context) 1184162922Sariff{ 1185162922Sariff struct hdac_softc *sc; 1186162922Sariff uint32_t intsts; 1187162922Sariff uint8_t rirbsts; 1188164614Sariff struct hdac_rirb *rirb_base; 1189171141Sariff uint32_t trigger; 1190162922Sariff 1191162922Sariff sc = (struct hdac_softc *)context; 1192162922Sariff 1193162922Sariff hdac_lock(sc); 1194164614Sariff if (sc->polling != 0) { 1195164614Sariff hdac_unlock(sc); 1196164614Sariff return; 1197164614Sariff } 1198171141Sariff 1199162922Sariff /* Do we have anything to do? */ 1200162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 1201163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 1202162922Sariff hdac_unlock(sc); 1203162922Sariff return; 1204162922Sariff } 1205162922Sariff 1206171141Sariff trigger = 0; 1207171141Sariff 1208162922Sariff /* Was this a controller interrupt? */ 1209163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 1210162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1211162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1212162922Sariff /* Get as many responses that we can */ 1213163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 1214164614Sariff HDAC_WRITE_1(&sc->mem, 1215164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 1216171141Sariff if (hdac_rirb_flush(sc) != 0) 1217171141Sariff trigger |= HDAC_TRIGGER_UNSOL; 1218162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 1219162922Sariff } 1220162922Sariff /* XXX to be removed */ 1221162922Sariff /* Clear interrupt and exit */ 1222162922Sariff#ifdef HDAC_INTR_EXTRA 1223162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 1224162922Sariff#endif 1225162922Sariff } 1226164614Sariff 1227163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 1228164614Sariff if ((intsts & (1 << sc->num_iss)) && 1229164614Sariff hdac_stream_intr(sc, &sc->play) != 0) 1230171141Sariff trigger |= HDAC_TRIGGER_PLAY; 1231164614Sariff if ((intsts & (1 << 0)) && 1232164614Sariff hdac_stream_intr(sc, &sc->rec) != 0) 1233171141Sariff trigger |= HDAC_TRIGGER_REC; 1234162922Sariff /* XXX to be removed */ 1235162922Sariff#ifdef HDAC_INTR_EXTRA 1236164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 1237164614Sariff HDAC_INTSTS_SIS_MASK); 1238162922Sariff#endif 1239162922Sariff } 1240162922Sariff 1241164614Sariff hdac_unlock(sc); 1242162922Sariff 1243171141Sariff if (trigger & HDAC_TRIGGER_PLAY) 1244164614Sariff chn_intr(sc->play.c); 1245171141Sariff if (trigger & HDAC_TRIGGER_REC) 1246164614Sariff chn_intr(sc->rec.c); 1247171141Sariff if (trigger & HDAC_TRIGGER_UNSOL) 1248171141Sariff taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1249162922Sariff} 1250162922Sariff 1251162922Sariff/**************************************************************************** 1252163057Sariff * int hdac_reset(hdac_softc *) 1253162922Sariff * 1254162922Sariff * Reset the hdac to a quiescent and known state. 1255162922Sariff ****************************************************************************/ 1256162922Sariffstatic int 1257162922Sariffhdac_reset(struct hdac_softc *sc) 1258162922Sariff{ 1259162922Sariff uint32_t gctl; 1260162922Sariff int count, i; 1261162922Sariff 1262162922Sariff /* 1263162922Sariff * Stop all Streams DMA engine 1264162922Sariff */ 1265162922Sariff for (i = 0; i < sc->num_iss; i++) 1266162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 1267162922Sariff for (i = 0; i < sc->num_oss; i++) 1268162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 1269162922Sariff for (i = 0; i < sc->num_bss; i++) 1270162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 1271162922Sariff 1272162922Sariff /* 1273169277Sariff * Stop Control DMA engines. 1274162922Sariff */ 1275162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 1276162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 1277162922Sariff 1278162922Sariff /* 1279169277Sariff * Reset DMA position buffer. 1280169277Sariff */ 1281169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 1282169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 1283169277Sariff 1284169277Sariff /* 1285162922Sariff * Reset the controller. The reset must remain asserted for 1286162922Sariff * a minimum of 100us. 1287162922Sariff */ 1288162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1289162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 1290162922Sariff count = 10000; 1291162922Sariff do { 1292162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1293162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 1294162922Sariff break; 1295162922Sariff DELAY(10); 1296162922Sariff } while (--count); 1297162922Sariff if (gctl & HDAC_GCTL_CRST) { 1298162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 1299162922Sariff return (ENXIO); 1300162922Sariff } 1301162922Sariff DELAY(100); 1302162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1303162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 1304162922Sariff count = 10000; 1305162922Sariff do { 1306162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 1307163057Sariff if (gctl & HDAC_GCTL_CRST) 1308162922Sariff break; 1309162922Sariff DELAY(10); 1310162922Sariff } while (--count); 1311162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 1312162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 1313162922Sariff return (ENXIO); 1314162922Sariff } 1315162922Sariff 1316162922Sariff /* 1317162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 1318162922Sariff * should be of 250us but for some reasons, on it's not enough on my 1319162922Sariff * computer. Let's use twice as much as necessary to make sure that 1320162922Sariff * it's reset properly. 1321162922Sariff */ 1322162922Sariff DELAY(1000); 1323162922Sariff 1324162922Sariff return (0); 1325162922Sariff} 1326162922Sariff 1327162922Sariff 1328162922Sariff/**************************************************************************** 1329162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1330162922Sariff * 1331162922Sariff * Retreive the general capabilities of the hdac; 1332162922Sariff * Number of Input Streams 1333162922Sariff * Number of Output Streams 1334162922Sariff * Number of bidirectional Streams 1335162922Sariff * 64bit ready 1336162922Sariff * CORB and RIRB sizes 1337162922Sariff ****************************************************************************/ 1338162922Sariffstatic int 1339162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1340162922Sariff{ 1341162922Sariff uint16_t gcap; 1342162922Sariff uint8_t corbsize, rirbsize; 1343162922Sariff 1344162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1345162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1346162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1347162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1348162922Sariff 1349163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1350162922Sariff 1351162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1352162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1353162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1354162922Sariff sc->corb_size = 256; 1355162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1356162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1357162922Sariff sc->corb_size = 16; 1358162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1359162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1360162922Sariff sc->corb_size = 2; 1361162922Sariff else { 1362162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1363162922Sariff __func__, corbsize); 1364162922Sariff return (ENXIO); 1365162922Sariff } 1366162922Sariff 1367162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1368162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1369162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1370162922Sariff sc->rirb_size = 256; 1371162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1372162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1373162922Sariff sc->rirb_size = 16; 1374162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1375162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1376162922Sariff sc->rirb_size = 2; 1377162922Sariff else { 1378162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1379162922Sariff __func__, rirbsize); 1380162922Sariff return (ENXIO); 1381162922Sariff } 1382162922Sariff 1383162922Sariff return (0); 1384162922Sariff} 1385162922Sariff 1386162922Sariff 1387162922Sariff/**************************************************************************** 1388162922Sariff * void hdac_dma_cb 1389162922Sariff * 1390162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1391162922Sariff * established. We just record the physical address of the mapping into 1392162922Sariff * the struct hdac_dma passed in. 1393162922Sariff ****************************************************************************/ 1394162922Sariffstatic void 1395162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1396162922Sariff{ 1397162922Sariff struct hdac_dma *dma; 1398162922Sariff 1399162922Sariff if (error == 0) { 1400162922Sariff dma = (struct hdac_dma *)callback_arg; 1401162922Sariff dma->dma_paddr = segs[0].ds_addr; 1402162922Sariff } 1403162922Sariff} 1404162922Sariff 1405162922Sariff 1406162922Sariff/**************************************************************************** 1407162922Sariff * int hdac_dma_alloc 1408162922Sariff * 1409162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1410162922Sariff * It must be freed by a corresponding hdac_dma_free. 1411162922Sariff ****************************************************************************/ 1412162922Sariffstatic int 1413162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1414162922Sariff{ 1415169277Sariff bus_size_t roundsz; 1416162922Sariff int result; 1417162922Sariff int lowaddr; 1418162922Sariff 1419169277Sariff roundsz = roundup2(size, HDAC_DMA_ALIGNMENT); 1420162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1421162922Sariff BUS_SPACE_MAXADDR_32BIT; 1422162922Sariff bzero(dma, sizeof(*dma)); 1423162922Sariff 1424162922Sariff /* 1425162922Sariff * Create a DMA tag 1426162922Sariff */ 1427162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1428162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1429162922Sariff 0, /* boundary */ 1430162922Sariff lowaddr, /* lowaddr */ 1431162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1432162922Sariff NULL, /* filtfunc */ 1433162922Sariff NULL, /* fistfuncarg */ 1434169277Sariff roundsz, /* maxsize */ 1435162922Sariff 1, /* nsegments */ 1436169277Sariff roundsz, /* maxsegsz */ 1437162922Sariff 0, /* flags */ 1438162922Sariff NULL, /* lockfunc */ 1439162922Sariff NULL, /* lockfuncarg */ 1440162922Sariff &dma->dma_tag); /* dmat */ 1441162922Sariff if (result != 0) { 1442162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1443162922Sariff __func__, result); 1444167773Sariff goto hdac_dma_alloc_fail; 1445162922Sariff } 1446162922Sariff 1447162922Sariff /* 1448162922Sariff * Allocate DMA memory 1449162922Sariff */ 1450162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1451169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 1452171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 1453171330Sariff &dma->dma_map); 1454162922Sariff if (result != 0) { 1455162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1456162922Sariff __func__, result); 1457167773Sariff goto hdac_dma_alloc_fail; 1458162922Sariff } 1459162922Sariff 1460169277Sariff dma->dma_size = roundsz; 1461169277Sariff 1462162922Sariff /* 1463162922Sariff * Map the memory 1464162922Sariff */ 1465162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1466169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 1467162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1468167773Sariff if (result == 0) 1469167773Sariff result = ENOMEM; 1470162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1471162922Sariff __func__, result); 1472167773Sariff goto hdac_dma_alloc_fail; 1473162922Sariff } 1474162922Sariff 1475169277Sariff HDA_BOOTVERBOSE( 1476169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 1477169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 1478169277Sariff ); 1479169277Sariff 1480162922Sariff return (0); 1481169277Sariff 1482167773Sariffhdac_dma_alloc_fail: 1483169277Sariff hdac_dma_free(sc, dma); 1484167773Sariff 1485162922Sariff return (result); 1486162922Sariff} 1487162922Sariff 1488162922Sariff 1489162922Sariff/**************************************************************************** 1490169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 1491162922Sariff * 1492162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1493162922Sariff * hdac_dma_alloc function. 1494162922Sariff ****************************************************************************/ 1495162922Sariffstatic void 1496169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 1497162922Sariff{ 1498167773Sariff if (dma->dma_map != NULL) { 1499169277Sariff#if 0 1500162922Sariff /* Flush caches */ 1501162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1502162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1503169277Sariff#endif 1504162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1505167773Sariff } 1506167773Sariff if (dma->dma_vaddr != NULL) { 1507162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1508167773Sariff dma->dma_vaddr = NULL; 1509167773Sariff } 1510167773Sariff dma->dma_map = NULL; 1511167773Sariff if (dma->dma_tag != NULL) { 1512162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1513167773Sariff dma->dma_tag = NULL; 1514162922Sariff } 1515167773Sariff dma->dma_size = 0; 1516162922Sariff} 1517162922Sariff 1518162922Sariff/**************************************************************************** 1519162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1520162922Sariff * 1521162922Sariff * Allocate all the bus resources necessary to speak with the physical 1522162922Sariff * controller. 1523162922Sariff ****************************************************************************/ 1524162922Sariffstatic int 1525162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1526162922Sariff{ 1527162922Sariff struct hdac_mem *mem; 1528162922Sariff 1529162922Sariff mem = &sc->mem; 1530162922Sariff mem->mem_rid = PCIR_BAR(0); 1531162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1532162922Sariff &mem->mem_rid, RF_ACTIVE); 1533162922Sariff if (mem->mem_res == NULL) { 1534162922Sariff device_printf(sc->dev, 1535162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1536162922Sariff return (ENOMEM); 1537162922Sariff } 1538162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1539162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1540162922Sariff 1541162922Sariff return (0); 1542162922Sariff} 1543162922Sariff 1544162922Sariff/**************************************************************************** 1545162922Sariff * void hdac_mem_free(struct hdac_softc *) 1546162922Sariff * 1547162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1548162922Sariff ****************************************************************************/ 1549162922Sariffstatic void 1550162922Sariffhdac_mem_free(struct hdac_softc *sc) 1551162922Sariff{ 1552162922Sariff struct hdac_mem *mem; 1553162922Sariff 1554162922Sariff mem = &sc->mem; 1555162922Sariff if (mem->mem_res != NULL) 1556162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1557162922Sariff mem->mem_res); 1558164614Sariff mem->mem_res = NULL; 1559162922Sariff} 1560162922Sariff 1561162922Sariff/**************************************************************************** 1562162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1563162922Sariff * 1564162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1565162922Sariff ****************************************************************************/ 1566162922Sariffstatic int 1567162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1568162922Sariff{ 1569162922Sariff struct hdac_irq *irq; 1570162922Sariff int result; 1571162922Sariff 1572162922Sariff irq = &sc->irq; 1573162922Sariff irq->irq_rid = 0x0; 1574171330Sariff 1575178155Sariff#ifdef HDAC_MSI_ENABLED 1576171330Sariff if ((sc->flags & HDAC_F_MSI) && 1577171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 1578171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 1579171330Sariff irq->irq_rid = 0x1; 1580171330Sariff else 1581171330Sariff#endif 1582171330Sariff sc->flags &= ~HDAC_F_MSI; 1583171330Sariff 1584162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1585162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1586162922Sariff if (irq->irq_res == NULL) { 1587162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1588162922Sariff __func__); 1589167773Sariff goto hdac_irq_alloc_fail; 1590162922Sariff } 1591162922Sariff result = snd_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE, 1592164614Sariff hdac_intr_handler, sc, &irq->irq_handle); 1593162922Sariff if (result != 0) { 1594162922Sariff device_printf(sc->dev, 1595162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1596162922Sariff __func__, result); 1597167773Sariff goto hdac_irq_alloc_fail; 1598162922Sariff } 1599162922Sariff 1600162922Sariff return (0); 1601162922Sariff 1602167773Sariffhdac_irq_alloc_fail: 1603164614Sariff hdac_irq_free(sc); 1604164614Sariff 1605162922Sariff return (ENXIO); 1606162922Sariff} 1607162922Sariff 1608162922Sariff/**************************************************************************** 1609162922Sariff * void hdac_irq_free(struct hdac_softc *) 1610162922Sariff * 1611162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1612162922Sariff ****************************************************************************/ 1613162922Sariffstatic void 1614162922Sariffhdac_irq_free(struct hdac_softc *sc) 1615162922Sariff{ 1616162922Sariff struct hdac_irq *irq; 1617162922Sariff 1618162922Sariff irq = &sc->irq; 1619164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1620162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1621162922Sariff if (irq->irq_res != NULL) 1622162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1623162922Sariff irq->irq_res); 1624178155Sariff#ifdef HDAC_MSI_ENABLED 1625171330Sariff if ((sc->flags & HDAC_F_MSI) && irq->irq_rid == 0x1) 1626171330Sariff pci_release_msi(sc->dev); 1627171330Sariff#endif 1628164614Sariff irq->irq_handle = NULL; 1629164614Sariff irq->irq_res = NULL; 1630171330Sariff irq->irq_rid = 0x0; 1631162922Sariff} 1632162922Sariff 1633162922Sariff/**************************************************************************** 1634162922Sariff * void hdac_corb_init(struct hdac_softc *) 1635162922Sariff * 1636162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1637162922Sariff * The CORB engine must not be running when this function is called. 1638162922Sariff ****************************************************************************/ 1639162922Sariffstatic void 1640162922Sariffhdac_corb_init(struct hdac_softc *sc) 1641162922Sariff{ 1642162922Sariff uint8_t corbsize; 1643162922Sariff uint64_t corbpaddr; 1644162922Sariff 1645162922Sariff /* Setup the CORB size. */ 1646162922Sariff switch (sc->corb_size) { 1647162922Sariff case 256: 1648162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1649162922Sariff break; 1650162922Sariff case 16: 1651162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1652162922Sariff break; 1653162922Sariff case 2: 1654162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1655162922Sariff break; 1656162922Sariff default: 1657162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1658162922Sariff } 1659162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1660162922Sariff 1661162922Sariff /* Setup the CORB Address in the hdac */ 1662162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1663162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1664162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1665162922Sariff 1666162922Sariff /* Set the WP and RP */ 1667162922Sariff sc->corb_wp = 0; 1668162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1669162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1670162922Sariff /* 1671162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1672162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1673162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1674162922Sariff * manually reset the bit to zero before continuing. 1675162922Sariff */ 1676162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1677162922Sariff 1678162922Sariff /* Enable CORB error reporting */ 1679162922Sariff#if 0 1680162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1681162922Sariff#endif 1682162922Sariff} 1683162922Sariff 1684162922Sariff/**************************************************************************** 1685162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1686162922Sariff * 1687162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1688162922Sariff * The RIRB engine must not be running when this function is called. 1689162922Sariff ****************************************************************************/ 1690162922Sariffstatic void 1691162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1692162922Sariff{ 1693162922Sariff uint8_t rirbsize; 1694162922Sariff uint64_t rirbpaddr; 1695162922Sariff 1696162922Sariff /* Setup the RIRB size. */ 1697162922Sariff switch (sc->rirb_size) { 1698162922Sariff case 256: 1699162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1700162922Sariff break; 1701162922Sariff case 16: 1702162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1703162922Sariff break; 1704162922Sariff case 2: 1705162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1706162922Sariff break; 1707162922Sariff default: 1708162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1709162922Sariff } 1710162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1711162922Sariff 1712162922Sariff /* Setup the RIRB Address in the hdac */ 1713162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1714162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1715162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1716162922Sariff 1717162922Sariff /* Setup the WP and RP */ 1718162922Sariff sc->rirb_rp = 0; 1719162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1720162922Sariff 1721164614Sariff if (sc->polling == 0) { 1722164614Sariff /* Setup the interrupt threshold */ 1723164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1724162922Sariff 1725164614Sariff /* Enable Overrun and response received reporting */ 1726162922Sariff#if 0 1727164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1728164614Sariff HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1729162922Sariff#else 1730164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1731162922Sariff#endif 1732164614Sariff } 1733162922Sariff 1734169277Sariff#if 0 1735162922Sariff /* 1736162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1737162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1738162922Sariff * should be sufficient to do this only once as the rirb is purely 1739162922Sariff * read-only from now on. 1740162922Sariff */ 1741162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1742162922Sariff BUS_DMASYNC_PREREAD); 1743169277Sariff#endif 1744162922Sariff} 1745162922Sariff 1746162922Sariff/**************************************************************************** 1747162922Sariff * void hdac_corb_start(hdac_softc *) 1748162922Sariff * 1749162922Sariff * Startup the corb DMA engine 1750162922Sariff ****************************************************************************/ 1751162922Sariffstatic void 1752162922Sariffhdac_corb_start(struct hdac_softc *sc) 1753162922Sariff{ 1754162922Sariff uint32_t corbctl; 1755162922Sariff 1756162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1757162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1758162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1759162922Sariff} 1760162922Sariff 1761162922Sariff/**************************************************************************** 1762162922Sariff * void hdac_rirb_start(hdac_softc *) 1763162922Sariff * 1764162922Sariff * Startup the rirb DMA engine 1765162922Sariff ****************************************************************************/ 1766162922Sariffstatic void 1767162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1768162922Sariff{ 1769162922Sariff uint32_t rirbctl; 1770162922Sariff 1771162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1772162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1773162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1774162922Sariff} 1775162922Sariff 1776162922Sariff 1777162922Sariff/**************************************************************************** 1778172811Sariff * void hdac_scan_codecs(struct hdac_softc *, int) 1779162922Sariff * 1780172811Sariff * Scan the bus for available codecs, starting with num. 1781162922Sariff ****************************************************************************/ 1782162922Sariffstatic void 1783172811Sariffhdac_scan_codecs(struct hdac_softc *sc, int num) 1784162922Sariff{ 1785162922Sariff struct hdac_codec *codec; 1786162922Sariff int i; 1787162922Sariff uint16_t statests; 1788162922Sariff 1789172811Sariff if (num < 0) 1790172811Sariff num = 0; 1791172811Sariff if (num >= HDAC_CODEC_MAX) 1792172811Sariff num = HDAC_CODEC_MAX - 1; 1793172811Sariff 1794162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1795172811Sariff for (i = num; i < HDAC_CODEC_MAX; i++) { 1796162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1797162922Sariff /* We have found a codec. */ 1798162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1799162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1800162922Sariff if (codec == NULL) { 1801162922Sariff device_printf(sc->dev, 1802162922Sariff "Unable to allocate memory for codec\n"); 1803162922Sariff continue; 1804162922Sariff } 1805164614Sariff codec->commands = NULL; 1806164614Sariff codec->responses_received = 0; 1807162922Sariff codec->verbs_sent = 0; 1808162922Sariff codec->sc = sc; 1809162922Sariff codec->cad = i; 1810162922Sariff sc->codecs[i] = codec; 1811162922Sariff if (hdac_probe_codec(codec) != 0) 1812162922Sariff break; 1813162922Sariff } 1814162922Sariff } 1815162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1816163057Sariff /* bus_generic_attach(sc->dev); */ 1817162922Sariff} 1818162922Sariff 1819162922Sariff/**************************************************************************** 1820162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1821162922Sariff * 1822162922Sariff * Probe a the given codec_id for available function groups. 1823162922Sariff ****************************************************************************/ 1824162922Sariffstatic int 1825162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1826162922Sariff{ 1827162922Sariff struct hdac_softc *sc = codec->sc; 1828162922Sariff struct hdac_devinfo *devinfo; 1829162922Sariff uint32_t vendorid, revisionid, subnode; 1830162922Sariff int startnode; 1831162922Sariff int endnode; 1832162922Sariff int i; 1833162922Sariff nid_t cad = codec->cad; 1834162922Sariff 1835163057Sariff HDA_BOOTVERBOSE( 1836163057Sariff device_printf(sc->dev, "HDA_DEBUG: Probing codec: %d\n", cad); 1837162922Sariff ); 1838162922Sariff vendorid = hdac_command(sc, 1839162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1840162922Sariff cad); 1841162922Sariff revisionid = hdac_command(sc, 1842162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1843162922Sariff cad); 1844162922Sariff subnode = hdac_command(sc, 1845162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1846162922Sariff cad); 1847162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1848162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1849162922Sariff 1850163057Sariff HDA_BOOTVERBOSE( 1851163057Sariff device_printf(sc->dev, "HDA_DEBUG: \tstartnode=%d endnode=%d\n", 1852163057Sariff startnode, endnode); 1853162922Sariff ); 1854162922Sariff for (i = startnode; i < endnode; i++) { 1855162922Sariff devinfo = hdac_probe_function(codec, i); 1856162922Sariff if (devinfo != NULL) { 1857162922Sariff /* XXX Ignore other FG. */ 1858162922Sariff devinfo->vendor_id = 1859162922Sariff HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1860162922Sariff devinfo->device_id = 1861162922Sariff HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1862162922Sariff devinfo->revision_id = 1863162922Sariff HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1864162922Sariff devinfo->stepping_id = 1865162922Sariff HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1866163057Sariff HDA_BOOTVERBOSE( 1867162922Sariff device_printf(sc->dev, 1868163057Sariff "HDA_DEBUG: \tFound AFG nid=%d " 1869162922Sariff "[startnode=%d endnode=%d]\n", 1870163057Sariff devinfo->nid, startnode, endnode); 1871162922Sariff ); 1872162922Sariff return (1); 1873162922Sariff } 1874162922Sariff } 1875162922Sariff 1876163057Sariff HDA_BOOTVERBOSE( 1877163057Sariff device_printf(sc->dev, "HDA_DEBUG: \tAFG not found\n"); 1878162922Sariff ); 1879162922Sariff return (0); 1880162922Sariff} 1881162922Sariff 1882162922Sariffstatic struct hdac_devinfo * 1883162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1884162922Sariff{ 1885162922Sariff struct hdac_softc *sc = codec->sc; 1886162922Sariff struct hdac_devinfo *devinfo; 1887162922Sariff uint32_t fctgrptype; 1888162922Sariff nid_t cad = codec->cad; 1889162922Sariff 1890162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1891162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1892162922Sariff 1893162922Sariff /* XXX For now, ignore other FG. */ 1894162965Sariff if (fctgrptype != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 1895162922Sariff return (NULL); 1896162922Sariff 1897162922Sariff devinfo = (struct hdac_devinfo *)malloc(sizeof(*devinfo), M_HDAC, 1898162922Sariff M_NOWAIT | M_ZERO); 1899162922Sariff if (devinfo == NULL) { 1900162922Sariff device_printf(sc->dev, "%s: Unable to allocate ivar\n", 1901162922Sariff __func__); 1902162922Sariff return (NULL); 1903162922Sariff } 1904162922Sariff 1905162922Sariff devinfo->nid = nid; 1906162965Sariff devinfo->node_type = fctgrptype; 1907162922Sariff devinfo->codec = codec; 1908162922Sariff 1909162922Sariff hdac_add_child(sc, devinfo); 1910162922Sariff 1911162922Sariff return (devinfo); 1912162922Sariff} 1913162922Sariff 1914162922Sariffstatic void 1915162922Sariffhdac_add_child(struct hdac_softc *sc, struct hdac_devinfo *devinfo) 1916162922Sariff{ 1917162922Sariff devinfo->dev = device_add_child(sc->dev, NULL, -1); 1918162922Sariff device_set_ivars(devinfo->dev, (void *)devinfo); 1919162922Sariff /* XXX - Print more information when booting verbose??? */ 1920162922Sariff} 1921162922Sariff 1922162922Sariffstatic void 1923162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 1924162922Sariff{ 1925162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1926162922Sariff uint32_t res; 1927169277Sariff int i, j, max, ents, entnum; 1928162922Sariff nid_t cad = w->devinfo->codec->cad; 1929162922Sariff nid_t nid = w->nid; 1930169277Sariff nid_t cnid, addcnid, prevcnid; 1931162922Sariff 1932169277Sariff w->nconns = 0; 1933169277Sariff 1934162922Sariff res = hdac_command(sc, 1935162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 1936162922Sariff 1937169277Sariff ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 1938162922Sariff 1939169277Sariff if (ents < 1) 1940162922Sariff return; 1941162922Sariff 1942162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 1943162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 1944169277Sariff prevcnid = 0; 1945162922Sariff 1946169277Sariff#define CONN_RMASK(e) (1 << ((32 / (e)) - 1)) 1947169277Sariff#define CONN_NMASK(e) (CONN_RMASK(e) - 1) 1948169277Sariff#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n))) 1949169277Sariff#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e)) 1950169277Sariff#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e)) 1951169277Sariff 1952169277Sariff for (i = 0; i < ents; i += entnum) { 1953162922Sariff res = hdac_command(sc, 1954162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 1955162922Sariff for (j = 0; j < entnum; j++) { 1956169277Sariff cnid = CONN_CNID(res, entnum, j); 1957169277Sariff if (cnid == 0) { 1958169277Sariff if (w->nconns < ents) 1959169277Sariff device_printf(sc->dev, 1960169277Sariff "%s: nid=%d WARNING: zero cnid " 1961169277Sariff "entnum=%d j=%d index=%d " 1962169277Sariff "entries=%d found=%d res=0x%08x\n", 1963169277Sariff __func__, nid, entnum, j, i, 1964169277Sariff ents, w->nconns, res); 1965169277Sariff else 1966169277Sariff goto getconns_out; 1967169277Sariff } 1968169277Sariff if (cnid < w->devinfo->startnode || 1969169277Sariff cnid >= w->devinfo->endnode) { 1970169277Sariff HDA_BOOTVERBOSE( 1971169277Sariff device_printf(sc->dev, 1972169277Sariff "%s: GHOST: nid=%d j=%d " 1973169277Sariff "entnum=%d index=%d res=0x%08x\n", 1974169277Sariff __func__, nid, j, entnum, i, res); 1975169277Sariff ); 1976169277Sariff } 1977169277Sariff if (CONN_RANGE(res, entnum, j) == 0) 1978169277Sariff addcnid = cnid; 1979169277Sariff else if (prevcnid == 0 || prevcnid >= cnid) { 1980162922Sariff device_printf(sc->dev, 1981169277Sariff "%s: WARNING: Invalid child range " 1982169277Sariff "nid=%d index=%d j=%d entnum=%d " 1983169277Sariff "prevcnid=%d cnid=%d res=0x%08x\n", 1984169277Sariff __func__, nid, i, j, entnum, prevcnid, 1985169277Sariff cnid, res); 1986169277Sariff addcnid = cnid; 1987169277Sariff } else 1988169277Sariff addcnid = prevcnid + 1; 1989169277Sariff while (addcnid <= cnid) { 1990169277Sariff if (w->nconns > max) { 1991169277Sariff device_printf(sc->dev, 1992169277Sariff "%s: nid=%d: Adding %d: " 1993169277Sariff "Max connection reached! max=%d\n", 1994169277Sariff __func__, nid, addcnid, max + 1); 1995169277Sariff goto getconns_out; 1996169277Sariff } 1997169277Sariff w->conns[w->nconns++] = addcnid++; 1998162922Sariff } 1999169277Sariff prevcnid = cnid; 2000162922Sariff } 2001162922Sariff } 2002162922Sariff 2003169277Sariffgetconns_out: 2004163057Sariff HDA_BOOTVERBOSE( 2005169277Sariff device_printf(sc->dev, 2006169277Sariff "HDA_DEBUG: %s: nid=%d entries=%d found=%d\n", 2007169277Sariff __func__, nid, ents, w->nconns); 2008162922Sariff ); 2009169277Sariff return; 2010162922Sariff} 2011162922Sariff 2012162922Sariffstatic uint32_t 2013162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 2014162922Sariff{ 2015162922Sariff struct hdac_softc *sc; 2016166965Sariff uint32_t config, orig, id; 2017162922Sariff nid_t cad, nid; 2018162922Sariff 2019162922Sariff sc = w->devinfo->codec->sc; 2020162922Sariff cad = w->devinfo->codec->cad; 2021162922Sariff nid = w->nid; 2022162922Sariff id = hdac_codec_id(w->devinfo); 2023162922Sariff 2024162922Sariff config = hdac_command(sc, 2025162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 2026162922Sariff cad); 2027166965Sariff orig = config; 2028166965Sariff 2029162965Sariff /* 2030162965Sariff * XXX REWRITE!!!! Don't argue! 2031162965Sariff */ 2032165281Sariff if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) { 2033165281Sariff switch (nid) { 2034165281Sariff case 26: 2035165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2036165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2037165281Sariff break; 2038165281Sariff case 27: 2039165281Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2040165281Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 2041165281Sariff break; 2042167610Sariff default: 2043167610Sariff break; 2044165281Sariff } 2045165281Sariff } else if (id == HDA_CODEC_ALC880 && 2046162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 2047162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 2048162922Sariff /* 2049162965Sariff * Super broken BIOS 2050162922Sariff */ 2051162922Sariff switch (nid) { 2052162922Sariff case 20: 2053162922Sariff break; 2054162922Sariff case 21: 2055162922Sariff break; 2056162922Sariff case 22: 2057162922Sariff break; 2058162922Sariff case 23: 2059162922Sariff break; 2060162922Sariff case 24: /* MIC1 */ 2061162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2062162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2063162922Sariff break; 2064162922Sariff case 25: /* XXX MIC2 */ 2065162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2066162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2067162922Sariff break; 2068162922Sariff case 26: /* LINE1 */ 2069162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2070162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2071162922Sariff break; 2072162922Sariff case 27: /* XXX LINE2 */ 2073162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2074162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2075162922Sariff break; 2076162922Sariff case 28: /* CD */ 2077162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2078162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 2079162922Sariff break; 2080162922Sariff case 30: 2081162922Sariff break; 2082162922Sariff case 31: 2083162922Sariff break; 2084162922Sariff default: 2085162922Sariff break; 2086162922Sariff } 2087166965Sariff } else if (id == HDA_CODEC_ALC883 && 2088172811Sariff (sc->pci_subvendor == MSI_MS034A_SUBVENDOR || 2089172811Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) { 2090166965Sariff switch (nid) { 2091166965Sariff case 25: 2092166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2093166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2094166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2095166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2096166965Sariff break; 2097169277Sariff case 28: 2098169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2099169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2100169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2101169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2102169277Sariff break; 2103166965Sariff default: 2104166965Sariff break; 2105166965Sariff } 2106166965Sariff } else if (id == HDA_CODEC_CXVENICE && sc->pci_subvendor == 2107166965Sariff HP_V3000_SUBVENDOR) { 2108166965Sariff switch (nid) { 2109166965Sariff case 18: 2110166965Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2111166965Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2112166965Sariff break; 2113166965Sariff case 20: 2114166965Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2115166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2116166965Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2117166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2118166965Sariff break; 2119167454Sariff case 21: 2120167454Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2121167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2122167454Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2123167454Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2124167454Sariff break; 2125166965Sariff default: 2126166965Sariff break; 2127166965Sariff } 2128169277Sariff } else if (id == HDA_CODEC_CXWAIKIKI && sc->pci_subvendor == 2129169277Sariff HP_DV5000_SUBVENDOR) { 2130169277Sariff switch (nid) { 2131169277Sariff case 20: 2132169277Sariff case 21: 2133169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 2134169277Sariff config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 2135169277Sariff break; 2136169277Sariff default: 2137169277Sariff break; 2138169277Sariff } 2139169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2140169277Sariff ASUS_W6F_SUBVENDOR) { 2141169277Sariff switch (nid) { 2142169277Sariff case 11: 2143169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2144169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2145169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 2146169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2147169277Sariff break; 2148178324Sariff case 12: 2149178324Sariff case 14: 2150178324Sariff case 16: 2151178324Sariff case 31: 2152178324Sariff case 32: 2153178324Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2154178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2155178324Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 2156178324Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2157178324Sariff break; 2158169277Sariff case 15: 2159169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2160169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2161169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2162169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2163169277Sariff break; 2164169277Sariff default: 2165169277Sariff break; 2166169277Sariff } 2167169277Sariff } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor == 2168169277Sariff UNIWILL_9075_SUBVENDOR) { 2169169277Sariff switch (nid) { 2170169277Sariff case 15: 2171169277Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2172169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2173169277Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 2174169277Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 2175169277Sariff break; 2176169277Sariff default: 2177169277Sariff break; 2178169277Sariff } 2179171141Sariff } else if (id == HDA_CODEC_AD1986A && 2180171141Sariff (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR || 2181171141Sariff sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) { 2182169277Sariff switch (nid) { 2183169277Sariff case 28: /* LINE */ 2184169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2185169277Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 2186169277Sariff break; 2187169277Sariff case 29: /* MIC */ 2188169277Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 2189169277Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 2190169277Sariff break; 2191169277Sariff default: 2192169277Sariff break; 2193169277Sariff } 2194174578Sariff } else if (id == HDA_CODEC_ALC268 && 2195174578Sariff HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) { 2196174578Sariff switch (nid) { 2197174578Sariff case 28: 2198174578Sariff config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 2199174578Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 2200174578Sariff config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 2201174578Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 2202174578Sariff break; 2203174578Sariff default: 2204174578Sariff break; 2205174578Sariff } 2206162922Sariff } 2207162922Sariff 2208166965Sariff HDA_BOOTVERBOSE( 2209166965Sariff if (config != orig) 2210166965Sariff device_printf(sc->dev, 2211166965Sariff "HDA_DEBUG: Pin config nid=%u 0x%08x -> 0x%08x\n", 2212166965Sariff nid, orig, config); 2213166965Sariff ); 2214166965Sariff 2215162922Sariff return (config); 2216162922Sariff} 2217162922Sariff 2218166965Sariffstatic uint32_t 2219166965Sariffhdac_widget_pin_getcaps(struct hdac_widget *w) 2220166965Sariff{ 2221166965Sariff struct hdac_softc *sc; 2222166965Sariff uint32_t caps, orig, id; 2223166965Sariff nid_t cad, nid; 2224166965Sariff 2225166965Sariff sc = w->devinfo->codec->sc; 2226166965Sariff cad = w->devinfo->codec->cad; 2227166965Sariff nid = w->nid; 2228166965Sariff id = hdac_codec_id(w->devinfo); 2229166965Sariff 2230166965Sariff caps = hdac_command(sc, 2231166965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 2232166965Sariff orig = caps; 2233166965Sariff 2234166965Sariff HDA_BOOTVERBOSE( 2235166965Sariff if (caps != orig) 2236166965Sariff device_printf(sc->dev, 2237166965Sariff "HDA_DEBUG: Pin caps nid=%u 0x%08x -> 0x%08x\n", 2238166965Sariff nid, orig, caps); 2239166965Sariff ); 2240166965Sariff 2241166965Sariff return (caps); 2242166965Sariff} 2243166965Sariff 2244162922Sariffstatic void 2245162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 2246162922Sariff{ 2247162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2248162922Sariff uint32_t config, pincap; 2249162922Sariff char *devstr, *connstr; 2250162922Sariff nid_t cad = w->devinfo->codec->cad; 2251162922Sariff nid_t nid = w->nid; 2252162922Sariff 2253162922Sariff config = hdac_widget_pin_getconfig(w); 2254162922Sariff w->wclass.pin.config = config; 2255162922Sariff 2256166965Sariff pincap = hdac_widget_pin_getcaps(w); 2257162922Sariff w->wclass.pin.cap = pincap; 2258162922Sariff 2259162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 2260164614Sariff HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad) & 2261164614Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 2262164614Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 2263169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 2264169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 2265162922Sariff 2266162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 2267162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 2268162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 2269162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 2270162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 2271162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 2272162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 2273162922Sariff w->param.eapdbtl = hdac_command(sc, 2274162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 2275162922Sariff w->param.eapdbtl &= 0x7; 2276162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2277162922Sariff } else 2278162965Sariff w->param.eapdbtl = HDAC_INVALID; 2279162922Sariff 2280162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 2281162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 2282162922Sariff devstr = "line out"; 2283162922Sariff break; 2284162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 2285162922Sariff devstr = "speaker"; 2286162922Sariff break; 2287162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 2288162922Sariff devstr = "headphones out"; 2289162922Sariff break; 2290162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 2291162922Sariff devstr = "CD"; 2292162922Sariff break; 2293162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 2294162922Sariff devstr = "SPDIF out"; 2295162922Sariff break; 2296162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 2297162922Sariff devstr = "digital (other) out"; 2298162922Sariff break; 2299162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE: 2300162922Sariff devstr = "modem, line side"; 2301162922Sariff break; 2302162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET: 2303162922Sariff devstr = "modem, handset side"; 2304162922Sariff break; 2305162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 2306162922Sariff devstr = "line in"; 2307162922Sariff break; 2308162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 2309162922Sariff devstr = "AUX"; 2310162922Sariff break; 2311162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 2312162922Sariff devstr = "Mic in"; 2313162922Sariff break; 2314162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY: 2315162922Sariff devstr = "telephony"; 2316162922Sariff break; 2317162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 2318162922Sariff devstr = "SPDIF in"; 2319162922Sariff break; 2320162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 2321162922Sariff devstr = "digital (other) in"; 2322162922Sariff break; 2323162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER: 2324162922Sariff devstr = "other"; 2325162922Sariff break; 2326162922Sariff default: 2327162922Sariff devstr = "unknown"; 2328162922Sariff break; 2329162922Sariff } 2330162922Sariff 2331162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) { 2332162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK: 2333162922Sariff connstr = "jack"; 2334162922Sariff break; 2335162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE: 2336162922Sariff connstr = "none"; 2337162922Sariff break; 2338162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED: 2339162922Sariff connstr = "fixed"; 2340162922Sariff break; 2341162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH: 2342162922Sariff connstr = "jack / fixed"; 2343162922Sariff break; 2344162922Sariff default: 2345162922Sariff connstr = "unknown"; 2346162922Sariff break; 2347162922Sariff } 2348162922Sariff 2349162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 2350162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 2351162922Sariff strlcat(w->name, " (", sizeof(w->name)); 2352162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 2353162922Sariff strlcat(w->name, ")", sizeof(w->name)); 2354162922Sariff} 2355162922Sariff 2356162922Sariffstatic void 2357162922Sariffhdac_widget_parse(struct hdac_widget *w) 2358162922Sariff{ 2359162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 2360162922Sariff uint32_t wcap, cap; 2361162922Sariff char *typestr; 2362162922Sariff nid_t cad = w->devinfo->codec->cad; 2363162922Sariff nid_t nid = w->nid; 2364162922Sariff 2365162922Sariff wcap = hdac_command(sc, 2366162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 2367162922Sariff cad); 2368162922Sariff w->param.widget_cap = wcap; 2369162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 2370162922Sariff 2371162922Sariff switch (w->type) { 2372162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 2373162922Sariff typestr = "audio output"; 2374162922Sariff break; 2375162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 2376162922Sariff typestr = "audio input"; 2377162922Sariff break; 2378162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 2379162922Sariff typestr = "audio mixer"; 2380162922Sariff break; 2381162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 2382162922Sariff typestr = "audio selector"; 2383162922Sariff break; 2384162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 2385162922Sariff typestr = "pin"; 2386162922Sariff break; 2387162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 2388162922Sariff typestr = "power widget"; 2389162922Sariff break; 2390162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 2391162922Sariff typestr = "volume widget"; 2392162922Sariff break; 2393162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 2394162922Sariff typestr = "beep widget"; 2395162922Sariff break; 2396162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 2397162922Sariff typestr = "vendor widget"; 2398162922Sariff break; 2399162922Sariff default: 2400162922Sariff typestr = "unknown type"; 2401162922Sariff break; 2402162922Sariff } 2403162922Sariff 2404162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 2405162922Sariff 2406162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(wcap)) { 2407162922Sariff hdac_command(sc, 2408162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), 2409162922Sariff cad); 2410162922Sariff DELAY(1000); 2411162922Sariff } 2412162922Sariff 2413162922Sariff hdac_widget_connection_parse(w); 2414162922Sariff 2415162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 2416162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2417162922Sariff w->param.outamp_cap = 2418162922Sariff hdac_command(sc, 2419162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2420162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 2421162922Sariff else 2422162922Sariff w->param.outamp_cap = 2423162922Sariff w->devinfo->function.audio.outamp_cap; 2424162922Sariff } else 2425162922Sariff w->param.outamp_cap = 0; 2426162922Sariff 2427162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 2428162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 2429162922Sariff w->param.inamp_cap = 2430162922Sariff hdac_command(sc, 2431162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2432162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 2433162922Sariff else 2434162922Sariff w->param.inamp_cap = 2435162922Sariff w->devinfo->function.audio.inamp_cap; 2436162922Sariff } else 2437162922Sariff w->param.inamp_cap = 0; 2438162922Sariff 2439162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 2440162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 2441162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 2442162922Sariff cap = hdac_command(sc, 2443162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2444162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 2445162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 2446162922Sariff w->devinfo->function.audio.supp_stream_formats; 2447162922Sariff cap = hdac_command(sc, 2448162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 2449162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 2450162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 2451162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2452162922Sariff } else { 2453162922Sariff w->param.supp_stream_formats = 2454162922Sariff w->devinfo->function.audio.supp_stream_formats; 2455162922Sariff w->param.supp_pcm_size_rate = 2456162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 2457162922Sariff } 2458162922Sariff } else { 2459162922Sariff w->param.supp_stream_formats = 0; 2460162922Sariff w->param.supp_pcm_size_rate = 0; 2461162922Sariff } 2462162922Sariff 2463162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 2464162922Sariff hdac_widget_pin_parse(w); 2465162922Sariff} 2466162922Sariff 2467162922Sariffstatic struct hdac_widget * 2468162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 2469162922Sariff{ 2470162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 2471162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 2472162922Sariff return (NULL); 2473162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 2474162922Sariff} 2475162922Sariff 2476164614Sariffstatic __inline int 2477164614Sariffhda_poll_channel(struct hdac_chan *ch) 2478164614Sariff{ 2479164614Sariff uint32_t sz, delta; 2480164614Sariff volatile uint32_t ptr; 2481164614Sariff 2482171330Sariff if (!(ch->flags & HDAC_CHN_RUNNING)) 2483164614Sariff return (0); 2484164614Sariff 2485164614Sariff sz = ch->blksz * ch->blkcnt; 2486169277Sariff if (ch->dmapos != NULL) 2487169277Sariff ptr = *(ch->dmapos); 2488169277Sariff else 2489169277Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, 2490169277Sariff ch->off + HDAC_SDLPIB); 2491164614Sariff ch->ptr = ptr; 2492164614Sariff ptr %= sz; 2493164614Sariff ptr &= ~(ch->blksz - 1); 2494164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 2495164614Sariff 2496164614Sariff if (delta < ch->blksz) 2497164614Sariff return (0); 2498164614Sariff 2499164614Sariff ch->prevptr = ptr; 2500164614Sariff 2501164614Sariff return (1); 2502164614Sariff} 2503164614Sariff 2504171330Sariff#define hda_chan_active(sc) (((sc)->play.flags | (sc)->rec.flags) & \ 2505171330Sariff HDAC_CHN_RUNNING) 2506164614Sariff 2507162922Sariffstatic void 2508164614Sariffhda_poll_callback(void *arg) 2509164614Sariff{ 2510164614Sariff struct hdac_softc *sc = arg; 2511171141Sariff uint32_t trigger; 2512164614Sariff 2513164614Sariff if (sc == NULL) 2514164614Sariff return; 2515164614Sariff 2516164614Sariff hdac_lock(sc); 2517164614Sariff if (sc->polling == 0 || hda_chan_active(sc) == 0) { 2518164614Sariff hdac_unlock(sc); 2519164614Sariff return; 2520164614Sariff } 2521164614Sariff 2522171141Sariff trigger = 0; 2523171141Sariff trigger |= (hda_poll_channel(&sc->play) != 0) ? HDAC_TRIGGER_PLAY : 0; 2524171141Sariff trigger |= (hda_poll_channel(&sc->rec)) != 0 ? HDAC_TRIGGER_REC : 0; 2525164614Sariff 2526164614Sariff /* XXX */ 2527164614Sariff callout_reset(&sc->poll_hda, 1/*sc->poll_ticks*/, 2528164614Sariff hda_poll_callback, sc); 2529164614Sariff 2530164614Sariff hdac_unlock(sc); 2531164614Sariff 2532171141Sariff if (trigger & HDAC_TRIGGER_PLAY) 2533164614Sariff chn_intr(sc->play.c); 2534171141Sariff if (trigger & HDAC_TRIGGER_REC) 2535164614Sariff chn_intr(sc->rec.c); 2536164614Sariff} 2537164614Sariff 2538164614Sariffstatic int 2539164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 2540164614Sariff{ 2541164614Sariff struct hdac_rirb *rirb_base, *rirb; 2542164614Sariff struct hdac_codec *codec; 2543164614Sariff struct hdac_command_list *commands; 2544164614Sariff nid_t cad; 2545164614Sariff uint32_t resp; 2546164614Sariff uint8_t rirbwp; 2547171141Sariff int ret; 2548164614Sariff 2549164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2550164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2551169277Sariff#if 0 2552164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2553164614Sariff BUS_DMASYNC_POSTREAD); 2554169277Sariff#endif 2555164614Sariff 2556171141Sariff ret = 0; 2557171141Sariff 2558164614Sariff while (sc->rirb_rp != rirbwp) { 2559164614Sariff sc->rirb_rp++; 2560164614Sariff sc->rirb_rp %= sc->rirb_size; 2561164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2562164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2563164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2564164614Sariff sc->codecs[cad] == NULL) 2565164614Sariff continue; 2566164614Sariff resp = rirb->response; 2567164614Sariff codec = sc->codecs[cad]; 2568164614Sariff commands = codec->commands; 2569164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2570164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2571164614Sariff ((resp >> 26) & 0xffff); 2572164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2573164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2574164614Sariff codec->responses_received < commands->num_commands) 2575164614Sariff commands->responses[codec->responses_received++] = 2576164614Sariff resp; 2577164614Sariff ret++; 2578164614Sariff } 2579164614Sariff 2580164614Sariff return (ret); 2581164614Sariff} 2582164614Sariff 2583164614Sariffstatic int 2584164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2585164614Sariff{ 2586164614Sariff nid_t cad; 2587164614Sariff uint32_t tag; 2588164614Sariff int ret = 0; 2589164614Sariff 2590164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2591164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2592164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2593164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2594164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2595164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2596164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2597164614Sariff ret++; 2598164614Sariff } 2599164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2600164614Sariff } 2601164614Sariff 2602164614Sariff return (ret); 2603164614Sariff} 2604164614Sariff 2605164614Sariffstatic void 2606164614Sariffhdac_poll_callback(void *arg) 2607164614Sariff{ 2608164614Sariff struct hdac_softc *sc = arg; 2609164614Sariff if (sc == NULL) 2610164614Sariff return; 2611166796Sariff 2612164614Sariff hdac_lock(sc); 2613169277Sariff if (sc->polling == 0 || sc->poll_ival == 0) { 2614164614Sariff hdac_unlock(sc); 2615164614Sariff return; 2616164614Sariff } 2617171141Sariff if (hdac_rirb_flush(sc) != 0) 2618171141Sariff hdac_unsolq_flush(sc); 2619169277Sariff callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc); 2620164614Sariff hdac_unlock(sc); 2621164614Sariff} 2622164614Sariff 2623164614Sariffstatic void 2624162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2625162922Sariff{ 2626162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2627162922Sariff uint32_t ctl; 2628162922Sariff 2629162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2630162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2631162922Sariff HDAC_SDCTL_RUN); 2632162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2633162922Sariff 2634171330Sariff ch->flags &= ~HDAC_CHN_RUNNING; 2635164614Sariff 2636164614Sariff if (sc->polling != 0) { 2637164614Sariff int pollticks; 2638164614Sariff 2639164614Sariff if (hda_chan_active(sc) == 0) { 2640164614Sariff callout_stop(&sc->poll_hda); 2641164614Sariff sc->poll_ticks = 1; 2642164614Sariff } else { 2643171330Sariff if (sc->play.flags & HDAC_CHN_RUNNING) 2644164614Sariff ch = &sc->play; 2645164614Sariff else 2646164614Sariff ch = &sc->rec; 2647164614Sariff pollticks = ((uint64_t)hz * ch->blksz) / 2648164614Sariff ((uint64_t)sndbuf_getbps(ch->b) * 2649164614Sariff sndbuf_getspd(ch->b)); 2650164614Sariff pollticks >>= 2; 2651164614Sariff if (pollticks > hz) 2652164614Sariff pollticks = hz; 2653164614Sariff if (pollticks < 1) { 2654164614Sariff HDA_BOOTVERBOSE( 2655164614Sariff device_printf(sc->dev, 2656164614Sariff "%s: pollticks=%d < 1 !\n", 2657164614Sariff __func__, pollticks); 2658164614Sariff ); 2659164614Sariff pollticks = 1; 2660164614Sariff } 2661164614Sariff if (pollticks > sc->poll_ticks) { 2662164614Sariff HDA_BOOTVERBOSE( 2663164614Sariff device_printf(sc->dev, 2664164614Sariff "%s: pollticks %d -> %d\n", 2665164614Sariff __func__, sc->poll_ticks, 2666164614Sariff pollticks); 2667164614Sariff ); 2668164614Sariff sc->poll_ticks = pollticks; 2669164614Sariff callout_reset(&sc->poll_hda, 1, 2670164614Sariff hda_poll_callback, sc); 2671164614Sariff } 2672164614Sariff } 2673164614Sariff } else { 2674164614Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2675164614Sariff ctl &= ~(1 << (ch->off >> 5)); 2676164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2677164614Sariff } 2678162922Sariff} 2679162922Sariff 2680162922Sariffstatic void 2681162922Sariffhdac_stream_start(struct hdac_chan *ch) 2682162922Sariff{ 2683162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2684162922Sariff uint32_t ctl; 2685162922Sariff 2686164614Sariff if (sc->polling != 0) { 2687164614Sariff int pollticks; 2688162922Sariff 2689164614Sariff pollticks = ((uint64_t)hz * ch->blksz) / 2690164614Sariff ((uint64_t)sndbuf_getbps(ch->b) * sndbuf_getspd(ch->b)); 2691164614Sariff pollticks >>= 2; 2692164614Sariff if (pollticks > hz) 2693164614Sariff pollticks = hz; 2694164614Sariff if (pollticks < 1) { 2695164614Sariff HDA_BOOTVERBOSE( 2696164614Sariff device_printf(sc->dev, 2697164614Sariff "%s: pollticks=%d < 1 !\n", 2698164614Sariff __func__, pollticks); 2699164614Sariff ); 2700164614Sariff pollticks = 1; 2701164614Sariff } 2702164614Sariff if (hda_chan_active(sc) == 0 || pollticks < sc->poll_ticks) { 2703164614Sariff HDA_BOOTVERBOSE( 2704164614Sariff if (hda_chan_active(sc) == 0) { 2705164614Sariff device_printf(sc->dev, 2706164614Sariff "%s: pollticks=%d\n", 2707164614Sariff __func__, pollticks); 2708164614Sariff } else { 2709164614Sariff device_printf(sc->dev, 2710164614Sariff "%s: pollticks %d -> %d\n", 2711164614Sariff __func__, sc->poll_ticks, 2712164614Sariff pollticks); 2713164614Sariff } 2714164614Sariff ); 2715164614Sariff sc->poll_ticks = pollticks; 2716164614Sariff callout_reset(&sc->poll_hda, 1, hda_poll_callback, 2717164614Sariff sc); 2718164614Sariff } 2719164614Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2720164614Sariff ctl |= HDAC_SDCTL_RUN; 2721164614Sariff } else { 2722164614Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2723164614Sariff ctl |= 1 << (ch->off >> 5); 2724164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2725164614Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2726164614Sariff ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2727164614Sariff HDAC_SDCTL_RUN; 2728164614Sariff } 2729162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2730164614Sariff 2731171330Sariff ch->flags |= HDAC_CHN_RUNNING; 2732162922Sariff} 2733162922Sariff 2734162922Sariffstatic void 2735162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2736162922Sariff{ 2737162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2738162922Sariff int timeout = 1000; 2739162922Sariff int to = timeout; 2740162922Sariff uint32_t ctl; 2741162922Sariff 2742162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2743162922Sariff ctl |= HDAC_SDCTL_SRST; 2744162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2745162922Sariff do { 2746162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2747162922Sariff if (ctl & HDAC_SDCTL_SRST) 2748162922Sariff break; 2749162922Sariff DELAY(10); 2750162922Sariff } while (--to); 2751162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2752162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2753162922Sariff } 2754162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2755162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2756162922Sariff to = timeout; 2757162922Sariff do { 2758162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2759162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2760162922Sariff break; 2761162922Sariff DELAY(10); 2762162922Sariff } while (--to); 2763163057Sariff if (ctl & HDAC_SDCTL_SRST) 2764162922Sariff device_printf(sc->dev, "can't reset!\n"); 2765162922Sariff} 2766162922Sariff 2767162922Sariffstatic void 2768162922Sariffhdac_stream_setid(struct hdac_chan *ch) 2769162922Sariff{ 2770162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2771162922Sariff uint32_t ctl; 2772162922Sariff 2773162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 2774162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 2775162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 2776162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 2777162922Sariff} 2778162922Sariff 2779162922Sariffstatic void 2780162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 2781162922Sariff{ 2782162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2783164614Sariff struct hdac_bdle *bdle; 2784162922Sariff uint64_t addr; 2785164614Sariff uint32_t blksz, blkcnt; 2786162922Sariff int i; 2787162922Sariff 2788162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 2789164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 2790162922Sariff 2791164614Sariff if (sc->polling != 0) { 2792164614Sariff blksz = ch->blksz * ch->blkcnt; 2793164614Sariff blkcnt = 1; 2794164614Sariff } else { 2795164614Sariff blksz = ch->blksz; 2796164614Sariff blkcnt = ch->blkcnt; 2797164614Sariff } 2798164614Sariff 2799164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 2800162922Sariff bdle->addrl = (uint32_t)addr; 2801162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 2802164614Sariff bdle->len = blksz; 2803164614Sariff bdle->ioc = 1 ^ sc->polling; 2804164614Sariff addr += blksz; 2805162922Sariff } 2806162922Sariff 2807164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 2808164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 2809162922Sariff addr = ch->bdl_dma.dma_paddr; 2810162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 2811162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 2812169277Sariff if (ch->dmapos != NULL && 2813169277Sariff !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) { 2814169277Sariff addr = sc->pos_dma.dma_paddr; 2815169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 2816169277Sariff ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001); 2817169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32)); 2818169277Sariff } 2819162922Sariff} 2820162922Sariff 2821162922Sariffstatic int 2822162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 2823162922Sariff{ 2824162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2825162922Sariff int rc; 2826162922Sariff 2827162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 2828162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 2829162922Sariff if (rc) { 2830162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 2831162922Sariff return (rc); 2832162922Sariff } 2833162922Sariff 2834162922Sariff return (0); 2835162922Sariff} 2836162922Sariff 2837162922Sariffstatic void 2838162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 2839162922Sariff int index, int lmute, int rmute, 2840162922Sariff int left, int right, int dir) 2841162922Sariff{ 2842162922Sariff uint16_t v = 0; 2843162922Sariff 2844162922Sariff if (sc == NULL) 2845162922Sariff return; 2846162922Sariff 2847162922Sariff if (left != right || lmute != rmute) { 2848162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 2849162922Sariff (lmute << 7) | left; 2850162922Sariff hdac_command(sc, 2851164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2852162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 2853162922Sariff (rmute << 7) | right; 2854162922Sariff } else 2855162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 2856162922Sariff (lmute << 7) | left; 2857162922Sariff 2858162922Sariff hdac_command(sc, 2859162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2860162922Sariff} 2861162922Sariff 2862162922Sariffstatic void 2863162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 2864162922Sariff int left, int right) 2865162922Sariff{ 2866162922Sariff struct hdac_softc *sc; 2867162922Sariff nid_t nid, cad; 2868162922Sariff int lmute, rmute; 2869162922Sariff 2870162922Sariff if (ctl == NULL || ctl->widget == NULL || 2871162922Sariff ctl->widget->devinfo == NULL || 2872162922Sariff ctl->widget->devinfo->codec == NULL || 2873162922Sariff ctl->widget->devinfo->codec->sc == NULL) 2874162922Sariff return; 2875162922Sariff 2876162922Sariff sc = ctl->widget->devinfo->codec->sc; 2877162922Sariff cad = ctl->widget->devinfo->codec->cad; 2878162922Sariff nid = ctl->widget->nid; 2879162922Sariff 2880162922Sariff if (mute == HDA_AMP_MUTE_DEFAULT) { 2881162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 2882162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 2883162922Sariff } else { 2884162922Sariff lmute = HDA_AMP_LEFT_MUTED(mute); 2885162922Sariff rmute = HDA_AMP_RIGHT_MUTED(mute); 2886162922Sariff } 2887162922Sariff 2888162922Sariff if (ctl->dir & HDA_CTL_OUT) 2889162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2890162922Sariff lmute, rmute, left, right, 0); 2891162922Sariff if (ctl->dir & HDA_CTL_IN) 2892162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2893162922Sariff lmute, rmute, left, right, 1); 2894162922Sariff ctl->left = left; 2895162922Sariff ctl->right = right; 2896162922Sariff} 2897162922Sariff 2898162922Sariffstatic void 2899162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 2900162922Sariff{ 2901162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 2902162922Sariff return; 2903162922Sariff hdac_command(w->devinfo->codec->sc, 2904162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 2905162922Sariff w->nid, index), w->devinfo->codec->cad); 2906162922Sariff w->selconn = index; 2907162922Sariff} 2908162922Sariff 2909162922Sariff 2910162922Sariff/**************************************************************************** 2911162922Sariff * uint32_t hdac_command_sendone_internal 2912162922Sariff * 2913162922Sariff * Wrapper function that sends only one command to a given codec 2914162922Sariff ****************************************************************************/ 2915162922Sariffstatic uint32_t 2916162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 2917162922Sariff{ 2918162922Sariff struct hdac_command_list cl; 2919162965Sariff uint32_t response = HDAC_INVALID; 2920162922Sariff 2921163057Sariff if (!hdac_lockowned(sc)) 2922162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 2923162922Sariff cl.num_commands = 1; 2924162922Sariff cl.verbs = &verb; 2925162922Sariff cl.responses = &response; 2926162922Sariff 2927162922Sariff hdac_command_send_internal(sc, &cl, cad); 2928162922Sariff 2929162922Sariff return (response); 2930162922Sariff} 2931162922Sariff 2932162922Sariff/**************************************************************************** 2933162922Sariff * hdac_command_send_internal 2934162922Sariff * 2935162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 2936162922Sariff * we can and msleep on the codec. When the interrupt get the responses 2937162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 2938162922Sariff * if any. 2939162922Sariff ****************************************************************************/ 2940162922Sariffstatic void 2941162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 2942162922Sariff struct hdac_command_list *commands, nid_t cad) 2943162922Sariff{ 2944162922Sariff struct hdac_codec *codec; 2945162922Sariff int corbrp; 2946162922Sariff uint32_t *corb; 2947162922Sariff int timeout; 2948162922Sariff int retry = 10; 2949164614Sariff struct hdac_rirb *rirb_base; 2950162922Sariff 2951164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 2952164614Sariff commands->num_commands < 1) 2953162922Sariff return; 2954162922Sariff 2955162922Sariff codec = sc->codecs[cad]; 2956162922Sariff codec->commands = commands; 2957162922Sariff codec->responses_received = 0; 2958162922Sariff codec->verbs_sent = 0; 2959162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 2960162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2961162922Sariff 2962162922Sariff do { 2963162922Sariff if (codec->verbs_sent != commands->num_commands) { 2964162922Sariff /* Queue as many verbs as possible */ 2965162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 2966169277Sariff#if 0 2967162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2968162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 2969169277Sariff#endif 2970162922Sariff while (codec->verbs_sent != commands->num_commands && 2971162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 2972162922Sariff sc->corb_wp++; 2973162922Sariff sc->corb_wp %= sc->corb_size; 2974162922Sariff corb[sc->corb_wp] = 2975162922Sariff commands->verbs[codec->verbs_sent++]; 2976162922Sariff } 2977162922Sariff 2978162922Sariff /* Send the verbs to the codecs */ 2979169277Sariff#if 0 2980162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2981162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 2982169277Sariff#endif 2983162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 2984162922Sariff } 2985162922Sariff 2986162922Sariff timeout = 1000; 2987164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 2988162922Sariff DELAY(10); 2989162922Sariff } while ((codec->verbs_sent != commands->num_commands || 2990164614Sariff codec->responses_received != commands->num_commands) && --retry); 2991162922Sariff 2992162922Sariff if (retry == 0) 2993162922Sariff device_printf(sc->dev, 2994164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 2995164614Sariff __func__, commands->num_commands, codec->verbs_sent, 2996164614Sariff codec->responses_received); 2997162922Sariff 2998164614Sariff codec->commands = NULL; 2999164614Sariff codec->responses_received = 0; 3000162922Sariff codec->verbs_sent = 0; 3001162922Sariff 3002164614Sariff hdac_unsolq_flush(sc); 3003162922Sariff} 3004162922Sariff 3005162922Sariff 3006162922Sariff/**************************************************************************** 3007162922Sariff * Device Methods 3008162922Sariff ****************************************************************************/ 3009162922Sariff 3010162922Sariff/**************************************************************************** 3011162922Sariff * int hdac_probe(device_t) 3012162922Sariff * 3013162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 3014162922Sariff * match using the subclass of the device. 3015162922Sariff ****************************************************************************/ 3016162922Sariffstatic int 3017162922Sariffhdac_probe(device_t dev) 3018162922Sariff{ 3019162922Sariff int i, result; 3020163257Sariff uint32_t model; 3021163257Sariff uint16_t class, subclass; 3022162922Sariff char desc[64]; 3023162922Sariff 3024162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 3025162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 3026162922Sariff class = pci_get_class(dev); 3027162922Sariff subclass = pci_get_subclass(dev); 3028162922Sariff 3029162922Sariff bzero(desc, sizeof(desc)); 3030162922Sariff result = ENXIO; 3031162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 3032162922Sariff if (hdac_devices[i].model == model) { 3033162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3034162922Sariff result = BUS_PROBE_DEFAULT; 3035162922Sariff break; 3036162922Sariff } 3037163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 3038162922Sariff class == PCIC_MULTIMEDIA && 3039162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3040162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 3041162922Sariff result = BUS_PROBE_GENERIC; 3042162922Sariff break; 3043162922Sariff } 3044162922Sariff } 3045162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 3046162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 3047162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 3048162922Sariff result = BUS_PROBE_GENERIC; 3049162922Sariff } 3050162922Sariff if (result != ENXIO) { 3051162922Sariff strlcat(desc, " High Definition Audio Controller", 3052162922Sariff sizeof(desc)); 3053162922Sariff device_set_desc_copy(dev, desc); 3054162922Sariff } 3055162922Sariff 3056162922Sariff return (result); 3057162922Sariff} 3058162922Sariff 3059162922Sariffstatic void * 3060162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 3061162922Sariff struct pcm_channel *c, int dir) 3062162922Sariff{ 3063162922Sariff struct hdac_devinfo *devinfo = data; 3064162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3065162922Sariff struct hdac_chan *ch; 3066162922Sariff 3067162922Sariff hdac_lock(sc); 3068162922Sariff if (dir == PCMDIR_PLAY) { 3069162922Sariff ch = &sc->play; 3070162922Sariff ch->off = (sc->num_iss + devinfo->function.audio.playcnt) << 5; 3071162922Sariff devinfo->function.audio.playcnt++; 3072162922Sariff } else { 3073162922Sariff ch = &sc->rec; 3074162922Sariff ch->off = devinfo->function.audio.reccnt << 5; 3075162922Sariff devinfo->function.audio.reccnt++; 3076162922Sariff } 3077162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 3078162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 3079162922Sariff ch->pcmrates[0] = 48000; 3080162922Sariff ch->pcmrates[1] = 0; 3081162922Sariff } 3082169277Sariff if (sc->pos_dma.dma_vaddr != NULL) 3083169277Sariff ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + 3084169277Sariff (sc->streamcnt * 8)); 3085169277Sariff else 3086169277Sariff ch->dmapos = NULL; 3087169277Sariff ch->sid = ++sc->streamcnt; 3088169277Sariff ch->dir = dir; 3089162922Sariff ch->b = b; 3090162922Sariff ch->c = c; 3091162922Sariff ch->devinfo = devinfo; 3092162922Sariff ch->blksz = sc->chan_size / sc->chan_blkcnt; 3093162922Sariff ch->blkcnt = sc->chan_blkcnt; 3094162922Sariff hdac_unlock(sc); 3095162922Sariff 3096162922Sariff if (hdac_bdl_alloc(ch) != 0) { 3097162922Sariff ch->blkcnt = 0; 3098162922Sariff return (NULL); 3099162922Sariff } 3100162922Sariff 3101169277Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, 3102171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0, 3103171330Sariff sc->chan_size) != 0) 3104162922Sariff return (NULL); 3105162922Sariff 3106162922Sariff return (ch); 3107162922Sariff} 3108162922Sariff 3109162922Sariffstatic int 3110162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 3111162922Sariff{ 3112162922Sariff struct hdac_chan *ch = data; 3113162922Sariff int i; 3114162922Sariff 3115162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 3116162922Sariff if (format == ch->caps.fmtlist[i]) { 3117162922Sariff ch->fmt = format; 3118162922Sariff return (0); 3119162922Sariff } 3120162922Sariff } 3121162922Sariff 3122162922Sariff return (EINVAL); 3123162922Sariff} 3124162922Sariff 3125162922Sariffstatic int 3126162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 3127162922Sariff{ 3128162922Sariff struct hdac_chan *ch = data; 3129164614Sariff uint32_t spd = 0, threshold; 3130162922Sariff int i; 3131162922Sariff 3132162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 3133162922Sariff spd = ch->pcmrates[i]; 3134164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 3135164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 3136164614Sariff if (speed < threshold) 3137162922Sariff break; 3138162922Sariff } 3139162922Sariff 3140164614Sariff if (spd == 0) /* impossible */ 3141162922Sariff ch->spd = 48000; 3142162922Sariff else 3143162922Sariff ch->spd = spd; 3144162922Sariff 3145162922Sariff return (ch->spd); 3146162922Sariff} 3147162922Sariff 3148162922Sariffstatic void 3149162922Sariffhdac_stream_setup(struct hdac_chan *ch) 3150162922Sariff{ 3151162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3152173817Sariff struct hdac_widget *w; 3153173817Sariff int i, chn, totalchn; 3154162922Sariff nid_t cad = ch->devinfo->codec->cad; 3155162922Sariff uint16_t fmt; 3156162922Sariff 3157162922Sariff fmt = 0; 3158162922Sariff if (ch->fmt & AFMT_S16_LE) 3159162922Sariff fmt |= ch->bit16 << 4; 3160162922Sariff else if (ch->fmt & AFMT_S32_LE) 3161162922Sariff fmt |= ch->bit32 << 4; 3162162922Sariff else 3163162922Sariff fmt |= 1 << 4; 3164162922Sariff 3165162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 3166162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 3167162922Sariff fmt |= hda_rate_tab[i].base; 3168162922Sariff fmt |= hda_rate_tab[i].mul; 3169162922Sariff fmt |= hda_rate_tab[i].div; 3170162922Sariff break; 3171162922Sariff } 3172162922Sariff } 3173162922Sariff 3174173817Sariff if (ch->fmt & AFMT_STEREO) { 3175162922Sariff fmt |= 1; 3176173817Sariff totalchn = 2; 3177173817Sariff } else 3178173817Sariff totalchn = 1; 3179162922Sariff 3180162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 3181162922Sariff 3182173817Sariff chn = 0; 3183162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3184173817Sariff w = hdac_widget_get(ch->devinfo, ch->io[i]); 3185173817Sariff if (w == NULL) 3186173817Sariff continue; 3187163057Sariff HDA_BOOTVERBOSE( 3188162922Sariff device_printf(sc->dev, 3189163057Sariff "HDA_DEBUG: PCMDIR_%s: Stream setup nid=%d " 3190163057Sariff "fmt=0x%08x\n", 3191162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 3192162922Sariff ch->io[i], fmt); 3193162922Sariff ); 3194162922Sariff hdac_command(sc, 3195162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 3196174025Sariff if (ch->dir == PCMDIR_REC) 3197174025Sariff hdac_command(sc, 3198174025Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3199174025Sariff (chn < totalchn) ? ((ch->sid << 4) | chn) : 0), 3200174025Sariff cad); 3201174025Sariff else 3202174025Sariff hdac_command(sc, 3203174025Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3204174025Sariff ch->sid << 4), cad); 3205173817Sariff chn += 3206173817Sariff HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ? 3207173817Sariff 2 : 1; 3208162922Sariff } 3209162922Sariff} 3210162922Sariff 3211162922Sariffstatic int 3212167648Sariffhdac_channel_setfragments(kobj_t obj, void *data, 3213167648Sariff uint32_t blksz, uint32_t blkcnt) 3214162922Sariff{ 3215162922Sariff struct hdac_chan *ch = data; 3216164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3217162922Sariff 3218167648Sariff blksz &= HDA_BLK_ALIGN; 3219162922Sariff 3220167648Sariff if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) 3221167648Sariff blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; 3222167648Sariff if (blksz < HDA_BLK_MIN) 3223167648Sariff blksz = HDA_BLK_MIN; 3224167648Sariff if (blkcnt > HDA_BDL_MAX) 3225167648Sariff blkcnt = HDA_BDL_MAX; 3226167648Sariff if (blkcnt < HDA_BDL_MIN) 3227167648Sariff blkcnt = HDA_BDL_MIN; 3228164614Sariff 3229167648Sariff while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) { 3230167648Sariff if ((blkcnt >> 1) >= HDA_BDL_MIN) 3231167648Sariff blkcnt >>= 1; 3232167648Sariff else if ((blksz >> 1) >= HDA_BLK_MIN) 3233167648Sariff blksz >>= 1; 3234167648Sariff else 3235167648Sariff break; 3236167648Sariff } 3237167648Sariff 3238164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 3239167648Sariff sndbuf_getblkcnt(ch->b) != blkcnt) && 3240167648Sariff sndbuf_resize(ch->b, blkcnt, blksz) != 0) 3241164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 3242167648Sariff __func__, blksz, blkcnt); 3243164614Sariff 3244164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 3245167648Sariff ch->blkcnt = sndbuf_getblkcnt(ch->b); 3246164614Sariff 3247167648Sariff return (1); 3248167648Sariff} 3249167648Sariff 3250167648Sariffstatic int 3251167648Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 3252167648Sariff{ 3253167648Sariff struct hdac_chan *ch = data; 3254167648Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3255167648Sariff 3256167648Sariff hdac_channel_setfragments(obj, data, blksz, sc->chan_blkcnt); 3257167648Sariff 3258162922Sariff return (ch->blksz); 3259162922Sariff} 3260162922Sariff 3261162922Sariffstatic void 3262162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 3263162922Sariff{ 3264162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 3265162922Sariff nid_t cad = devinfo->codec->cad; 3266162922Sariff int i; 3267162922Sariff 3268162922Sariff hdac_stream_stop(ch); 3269162922Sariff 3270162922Sariff for (i = 0; ch->io[i] != -1; i++) { 3271162922Sariff hdac_command(sc, 3272162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 3273162922Sariff 0), cad); 3274162922Sariff } 3275162922Sariff} 3276162922Sariff 3277162922Sariffstatic void 3278162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 3279162922Sariff{ 3280162922Sariff ch->ptr = 0; 3281162922Sariff ch->prevptr = 0; 3282162922Sariff hdac_stream_stop(ch); 3283162922Sariff hdac_stream_reset(ch); 3284162922Sariff hdac_bdl_setup(ch); 3285162922Sariff hdac_stream_setid(ch); 3286162922Sariff hdac_stream_setup(ch); 3287162922Sariff hdac_stream_start(ch); 3288162922Sariff} 3289162922Sariff 3290162922Sariffstatic int 3291162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 3292162922Sariff{ 3293162922Sariff struct hdac_chan *ch = data; 3294162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3295162922Sariff 3296170521Sariff if (!PCMTRIG_COMMON(go)) 3297170521Sariff return (0); 3298170521Sariff 3299162922Sariff hdac_lock(sc); 3300162922Sariff switch (go) { 3301162922Sariff case PCMTRIG_START: 3302162922Sariff hdac_channel_start(sc, ch); 3303162922Sariff break; 3304162922Sariff case PCMTRIG_STOP: 3305162922Sariff case PCMTRIG_ABORT: 3306162922Sariff hdac_channel_stop(sc, ch); 3307162922Sariff break; 3308167610Sariff default: 3309167610Sariff break; 3310162922Sariff } 3311162922Sariff hdac_unlock(sc); 3312162922Sariff 3313162922Sariff return (0); 3314162922Sariff} 3315162922Sariff 3316162922Sariffstatic int 3317162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 3318162922Sariff{ 3319162922Sariff struct hdac_chan *ch = data; 3320162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 3321162922Sariff uint32_t ptr; 3322162922Sariff 3323162922Sariff hdac_lock(sc); 3324164614Sariff if (sc->polling != 0) 3325164614Sariff ptr = ch->ptr; 3326169277Sariff else if (ch->dmapos != NULL) 3327169277Sariff ptr = *(ch->dmapos); 3328164614Sariff else 3329164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 3330162922Sariff hdac_unlock(sc); 3331162922Sariff 3332164614Sariff /* 3333164614Sariff * Round to available space and force 128 bytes aligment. 3334164614Sariff */ 3335164614Sariff ptr %= ch->blksz * ch->blkcnt; 3336167648Sariff ptr &= HDA_BLK_ALIGN; 3337162922Sariff 3338162922Sariff return (ptr); 3339162922Sariff} 3340162922Sariff 3341162922Sariffstatic struct pcmchan_caps * 3342162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 3343162922Sariff{ 3344162922Sariff return (&((struct hdac_chan *)data)->caps); 3345162922Sariff} 3346162922Sariff 3347162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 3348162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 3349162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 3350162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 3351162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 3352167648Sariff KOBJMETHOD(channel_setfragments, hdac_channel_setfragments), 3353162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 3354162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 3355162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 3356162922Sariff { 0, 0 } 3357162922Sariff}; 3358162922SariffCHANNEL_DECLARE(hdac_channel); 3359162922Sariff 3360169277Sariffstatic void 3361169277Sariffhdac_jack_poll_callback(void *arg) 3362169277Sariff{ 3363169277Sariff struct hdac_devinfo *devinfo = arg; 3364169277Sariff struct hdac_softc *sc; 3365169277Sariff 3366169277Sariff if (devinfo == NULL || devinfo->codec == NULL || 3367169277Sariff devinfo->codec->sc == NULL) 3368169277Sariff return; 3369169277Sariff sc = devinfo->codec->sc; 3370169277Sariff hdac_lock(sc); 3371169277Sariff if (sc->poll_ival == 0) { 3372169277Sariff hdac_unlock(sc); 3373169277Sariff return; 3374169277Sariff } 3375169277Sariff hdac_hp_switch_handler(devinfo); 3376169277Sariff callout_reset(&sc->poll_jack, sc->poll_ival, 3377169277Sariff hdac_jack_poll_callback, devinfo); 3378169277Sariff hdac_unlock(sc); 3379169277Sariff} 3380169277Sariff 3381162922Sariffstatic int 3382162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 3383162922Sariff{ 3384162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3385162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3386162922Sariff struct hdac_widget *w, *cw; 3387162922Sariff struct hdac_audio_ctl *ctl; 3388162922Sariff uint32_t mask, recmask, id; 3389162922Sariff int i, j, softpcmvol; 3390162922Sariff nid_t cad; 3391162922Sariff 3392162922Sariff hdac_lock(sc); 3393162922Sariff 3394162922Sariff mask = 0; 3395162922Sariff recmask = 0; 3396162922Sariff 3397162922Sariff id = hdac_codec_id(devinfo); 3398162922Sariff cad = devinfo->codec->cad; 3399162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 3400163257Sariff if (!(HDA_DEV_MATCH(hdac_hp_switch[i].model, 3401169277Sariff sc->pci_subvendor) && hdac_hp_switch[i].id == id)) 3402162922Sariff continue; 3403162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 3404169277Sariff if (w == NULL || w->enable == 0 || w->type != 3405169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 3406169277Sariff continue; 3407169277Sariff if (hdac_hp_switch[i].polling != 0) 3408169277Sariff callout_reset(&sc->poll_jack, 1, 3409169277Sariff hdac_jack_poll_callback, devinfo); 3410169277Sariff else if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) 3411162922Sariff hdac_command(sc, 3412169277Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid, 3413169277Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | 3414162922Sariff HDAC_UNSOLTAG_EVENT_HP), cad); 3415169277Sariff else 3416169277Sariff continue; 3417169277Sariff hdac_hp_switch_handler(devinfo); 3418169277Sariff HDA_BOOTVERBOSE( 3419169277Sariff device_printf(sc->dev, 3420169277Sariff "HDA_DEBUG: Enabling headphone/speaker " 3421169277Sariff "audio routing switching:\n"); 3422169277Sariff device_printf(sc->dev, 3423169277Sariff "HDA_DEBUG: \tindex=%d nid=%d " 3424169277Sariff "pci_subvendor=0x%08x " 3425169277Sariff "codec=0x%08x [%s]\n", 3426169277Sariff i, w->nid, sc->pci_subvendor, id, 3427169277Sariff (hdac_hp_switch[i].polling != 0) ? "POLL" : 3428169277Sariff "UNSOL"); 3429169277Sariff ); 3430162922Sariff break; 3431162922Sariff } 3432162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 3433163257Sariff if (!(HDA_DEV_MATCH(hdac_eapd_switch[i].model, 3434162965Sariff sc->pci_subvendor) && 3435162965Sariff hdac_eapd_switch[i].id == id)) 3436162922Sariff continue; 3437162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 3438162922Sariff if (w == NULL || w->enable == 0) 3439162922Sariff break; 3440162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3441162965Sariff w->param.eapdbtl == HDAC_INVALID) 3442162922Sariff break; 3443162922Sariff mask |= SOUND_MASK_OGAIN; 3444162922Sariff break; 3445162922Sariff } 3446162922Sariff 3447162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3448162922Sariff w = hdac_widget_get(devinfo, i); 3449162922Sariff if (w == NULL || w->enable == 0) 3450162922Sariff continue; 3451162922Sariff mask |= w->ctlflags; 3452162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 3453162922Sariff continue; 3454162922Sariff for (j = 0; j < w->nconns; j++) { 3455162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3456162922Sariff if (cw == NULL || cw->enable == 0) 3457162922Sariff continue; 3458162922Sariff recmask |= cw->ctlflags; 3459162922Sariff } 3460162922Sariff } 3461162922Sariff 3462162922Sariff if (!(mask & SOUND_MASK_PCM)) { 3463162922Sariff softpcmvol = 1; 3464162922Sariff mask |= SOUND_MASK_PCM; 3465163057Sariff } else 3466163057Sariff softpcmvol = (devinfo->function.audio.quirks & 3467163057Sariff HDA_QUIRK_SOFTPCMVOL) ? 1 : 0; 3468162922Sariff 3469162922Sariff i = 0; 3470162922Sariff ctl = NULL; 3471162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3472162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 3473162922Sariff continue; 3474162922Sariff if (!(ctl->ossmask & SOUND_MASK_PCM)) 3475162922Sariff continue; 3476162922Sariff if (ctl->step > 0) 3477162922Sariff break; 3478162922Sariff } 3479162922Sariff 3480162922Sariff if (softpcmvol == 1 || ctl == NULL) { 3481170207Sariff pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL); 3482170207Sariff HDA_BOOTVERBOSE( 3483170207Sariff device_printf(sc->dev, 3484170207Sariff "HDA_DEBUG: %s Soft PCM volume\n", 3485170207Sariff (softpcmvol == 1) ? 3486170207Sariff "Forcing" : "Enabling"); 3487170207Sariff ); 3488162922Sariff i = 0; 3489162922Sariff /* 3490162922Sariff * XXX Temporary quirk for STAC9220, until the parser 3491162922Sariff * become smarter. 3492162922Sariff */ 3493162922Sariff if (id == HDA_CODEC_STAC9220) { 3494162922Sariff mask |= SOUND_MASK_VOLUME; 3495162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 3496162922Sariff NULL) { 3497162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 3498162922Sariff continue; 3499162922Sariff if (ctl->widget->nid == 11 && ctl->index == 0) { 3500162922Sariff ctl->ossmask = SOUND_MASK_VOLUME; 3501162922Sariff ctl->ossval = 100 | (100 << 8); 3502162922Sariff } else 3503162922Sariff ctl->ossmask &= ~SOUND_MASK_VOLUME; 3504162922Sariff } 3505165992Sariff } else if (id == HDA_CODEC_STAC9221) { 3506165992Sariff mask |= SOUND_MASK_VOLUME; 3507165992Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 3508165992Sariff NULL) { 3509165992Sariff if (ctl->widget == NULL) 3510165992Sariff continue; 3511169277Sariff if (ctl->widget->type == 3512169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT && 3513169277Sariff ctl->index == 0 && (ctl->widget->nid == 2 || 3514169277Sariff ctl->widget->enable != 0)) { 3515165992Sariff ctl->enable = 1; 3516165992Sariff ctl->ossmask = SOUND_MASK_VOLUME; 3517165992Sariff ctl->ossval = 100 | (100 << 8); 3518165992Sariff } else if (ctl->enable == 0) 3519165992Sariff continue; 3520165992Sariff else 3521165992Sariff ctl->ossmask &= ~SOUND_MASK_VOLUME; 3522165992Sariff } 3523162922Sariff } else { 3524162922Sariff mix_setparentchild(m, SOUND_MIXER_VOLUME, 3525162922Sariff SOUND_MASK_PCM); 3526162922Sariff if (!(mask & SOUND_MASK_VOLUME)) 3527162922Sariff mix_setrealdev(m, SOUND_MIXER_VOLUME, 3528162922Sariff SOUND_MIXER_NONE); 3529162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 3530162922Sariff NULL) { 3531162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 3532162922Sariff continue; 3533163057Sariff if (!HDA_FLAG_MATCH(ctl->ossmask, 3534163057Sariff SOUND_MASK_VOLUME | SOUND_MASK_PCM)) 3535162922Sariff continue; 3536162922Sariff if (!(ctl->mute == 1 && ctl->step == 0)) 3537162922Sariff ctl->enable = 0; 3538162922Sariff } 3539162922Sariff } 3540162922Sariff } 3541162922Sariff 3542169277Sariff recmask &= ~(SOUND_MASK_PCM | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER | 3543169277Sariff SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_IGAIN | 3544169277Sariff SOUND_MASK_OGAIN); 3545169277Sariff recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3546169277Sariff mask &= (1 << SOUND_MIXER_NRDEVICES) - 1; 3547162922Sariff 3548162922Sariff mix_setrecdevs(m, recmask); 3549162922Sariff mix_setdevs(m, mask); 3550162922Sariff 3551162922Sariff hdac_unlock(sc); 3552162922Sariff 3553162922Sariff return (0); 3554162922Sariff} 3555162922Sariff 3556162922Sariffstatic int 3557162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 3558162922Sariff unsigned left, unsigned right) 3559162922Sariff{ 3560162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3561162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3562162922Sariff struct hdac_widget *w; 3563162922Sariff struct hdac_audio_ctl *ctl; 3564162922Sariff uint32_t id, mute; 3565162922Sariff int lvol, rvol, mlvol, mrvol; 3566162922Sariff int i = 0; 3567162922Sariff 3568162922Sariff hdac_lock(sc); 3569162922Sariff if (dev == SOUND_MIXER_OGAIN) { 3570163257Sariff uint32_t orig; 3571162922Sariff /*if (left != right || !(left == 0 || left == 1)) { 3572162922Sariff hdac_unlock(sc); 3573162922Sariff return (-1); 3574162922Sariff }*/ 3575162922Sariff id = hdac_codec_id(devinfo); 3576162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 3577163257Sariff if (HDA_DEV_MATCH(hdac_eapd_switch[i].model, 3578162965Sariff sc->pci_subvendor) && 3579162922Sariff hdac_eapd_switch[i].id == id) 3580162922Sariff break; 3581162922Sariff } 3582162922Sariff if (i >= HDAC_EAPD_SWITCH_LEN) { 3583162922Sariff hdac_unlock(sc); 3584162922Sariff return (-1); 3585162922Sariff } 3586162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 3587162922Sariff if (w == NULL || 3588162922Sariff w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 3589162965Sariff w->param.eapdbtl == HDAC_INVALID) { 3590162922Sariff hdac_unlock(sc); 3591162922Sariff return (-1); 3592162922Sariff } 3593163257Sariff orig = w->param.eapdbtl; 3594163432Sariff if (left == 0) 3595162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3596162922Sariff else 3597162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3598163257Sariff if (orig != w->param.eapdbtl) { 3599163432Sariff uint32_t val; 3600163432Sariff 3601163257Sariff if (hdac_eapd_switch[i].hp_switch != 0) 3602163257Sariff hdac_hp_switch_handler(devinfo); 3603163432Sariff val = w->param.eapdbtl; 3604163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 3605163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 3606163257Sariff hdac_command(sc, 3607163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 3608163432Sariff w->nid, val), devinfo->codec->cad); 3609163257Sariff } 3610162922Sariff hdac_unlock(sc); 3611162922Sariff return (left | (left << 8)); 3612162922Sariff } 3613162922Sariff if (dev == SOUND_MIXER_VOLUME) 3614162922Sariff devinfo->function.audio.mvol = left | (right << 8); 3615162922Sariff 3616162922Sariff mlvol = devinfo->function.audio.mvol & 0x7f; 3617162922Sariff mrvol = (devinfo->function.audio.mvol >> 8) & 0x7f; 3618162922Sariff lvol = 0; 3619162922Sariff rvol = 0; 3620162922Sariff 3621162922Sariff i = 0; 3622162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3623162922Sariff if (ctl->widget == NULL || ctl->enable == 0 || 3624162922Sariff !(ctl->ossmask & (1 << dev))) 3625162922Sariff continue; 3626162922Sariff switch (dev) { 3627162922Sariff case SOUND_MIXER_VOLUME: 3628162922Sariff lvol = ((ctl->ossval & 0x7f) * left) / 100; 3629162922Sariff lvol = (lvol * ctl->step) / 100; 3630162922Sariff rvol = (((ctl->ossval >> 8) & 0x7f) * right) / 100; 3631162922Sariff rvol = (rvol * ctl->step) / 100; 3632162922Sariff break; 3633162922Sariff default: 3634162922Sariff if (ctl->ossmask & SOUND_MASK_VOLUME) { 3635162922Sariff lvol = (left * mlvol) / 100; 3636162922Sariff lvol = (lvol * ctl->step) / 100; 3637162922Sariff rvol = (right * mrvol) / 100; 3638162922Sariff rvol = (rvol * ctl->step) / 100; 3639162922Sariff } else { 3640162922Sariff lvol = (left * ctl->step) / 100; 3641162922Sariff rvol = (right * ctl->step) / 100; 3642162922Sariff } 3643162922Sariff ctl->ossval = left | (right << 8); 3644162922Sariff break; 3645162922Sariff } 3646162922Sariff mute = 0; 3647162922Sariff if (ctl->step < 1) { 3648162922Sariff mute |= (left == 0) ? HDA_AMP_MUTE_LEFT : 3649162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 3650162922Sariff mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 3651162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 3652162922Sariff } else { 3653162922Sariff mute |= (lvol == 0) ? HDA_AMP_MUTE_LEFT : 3654162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 3655162922Sariff mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 3656162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 3657162922Sariff } 3658162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 3659162922Sariff } 3660162922Sariff hdac_unlock(sc); 3661162922Sariff 3662162922Sariff return (left | (right << 8)); 3663162922Sariff} 3664162922Sariff 3665162922Sariffstatic int 3666162922Sariffhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 3667162922Sariff{ 3668162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3669162922Sariff struct hdac_widget *w, *cw; 3670162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3671162922Sariff uint32_t ret = src, target; 3672162922Sariff int i, j; 3673162922Sariff 3674162922Sariff target = 0; 3675162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3676162922Sariff if (src & (1 << i)) { 3677162922Sariff target = 1 << i; 3678162922Sariff break; 3679162922Sariff } 3680162922Sariff } 3681162922Sariff 3682162922Sariff hdac_lock(sc); 3683162922Sariff 3684162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3685162922Sariff w = hdac_widget_get(devinfo, i); 3686162965Sariff if (w == NULL || w->enable == 0) 3687162922Sariff continue; 3688162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 3689162922Sariff continue; 3690162922Sariff for (j = 0; j < w->nconns; j++) { 3691162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3692162922Sariff if (cw == NULL || cw->enable == 0) 3693162922Sariff continue; 3694162922Sariff if ((target == SOUND_MASK_VOLUME && 3695162922Sariff cw->type != 3696162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 3697162922Sariff (target != SOUND_MASK_VOLUME && 3698162922Sariff cw->type == 3699162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)) 3700162922Sariff continue; 3701162922Sariff if (cw->ctlflags & target) { 3702169277Sariff if (!(w->pflags & HDA_ADC_LOCKED)) 3703169277Sariff hdac_widget_connection_select(w, j); 3704162922Sariff ret = target; 3705162922Sariff j += w->nconns; 3706162922Sariff } 3707162922Sariff } 3708162922Sariff } 3709162922Sariff 3710162922Sariff hdac_unlock(sc); 3711162922Sariff 3712162922Sariff return (ret); 3713162922Sariff} 3714162922Sariff 3715162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3716162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3717162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3718162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3719162922Sariff { 0, 0 } 3720162922Sariff}; 3721162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3722162922Sariff 3723171141Sariffstatic void 3724171141Sariffhdac_unsolq_task(void *context, int pending) 3725171141Sariff{ 3726171141Sariff struct hdac_softc *sc; 3727171141Sariff 3728171141Sariff sc = (struct hdac_softc *)context; 3729171141Sariff 3730171141Sariff hdac_lock(sc); 3731171141Sariff hdac_unsolq_flush(sc); 3732171141Sariff hdac_unlock(sc); 3733171141Sariff} 3734171141Sariff 3735162922Sariff/**************************************************************************** 3736162922Sariff * int hdac_attach(device_t) 3737162922Sariff * 3738162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3739162922Sariff * when this function is called. Setup everything that doesn't require 3740162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3741162922Sariff ****************************************************************************/ 3742162922Sariffstatic int 3743162922Sariffhdac_attach(device_t dev) 3744162922Sariff{ 3745162922Sariff struct hdac_softc *sc; 3746162922Sariff int result; 3747169277Sariff int i; 3748169277Sariff uint16_t vendor; 3749169277Sariff uint8_t v; 3750162922Sariff 3751170721Sariff sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 3752163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 3753162922Sariff sc->dev = dev; 3754163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 3755163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 3756169277Sariff vendor = pci_get_vendor(dev); 3757162922Sariff 3758165281Sariff if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) { 3759165281Sariff /* Screw nx6325 - subdevice/subvendor swapped */ 3760165281Sariff sc->pci_subvendor = HP_NX6325_SUBVENDOR; 3761165281Sariff } 3762165281Sariff 3763164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 3764164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 3765169277Sariff callout_init(&sc->poll_jack, CALLOUT_MPSAFE); 3766164614Sariff 3767171141Sariff TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 3768171141Sariff 3769164614Sariff sc->poll_ticks = 1; 3770169277Sariff sc->poll_ival = HDAC_POLL_INTERVAL; 3771169277Sariff if (resource_int_value(device_get_name(dev), 3772169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 3773164614Sariff sc->polling = 1; 3774164614Sariff else 3775164614Sariff sc->polling = 0; 3776164614Sariff 3777162922Sariff sc->chan_size = pcm_getbuffersize(dev, 3778164614Sariff HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 3779164614Sariff 3780169277Sariff if (resource_int_value(device_get_name(dev), 3781169277Sariff device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 3782167648Sariff i &= HDA_BLK_ALIGN; 3783167648Sariff if (i < HDA_BLK_MIN) 3784167648Sariff i = HDA_BLK_MIN; 3785162922Sariff sc->chan_blkcnt = sc->chan_size / i; 3786162922Sariff i = 0; 3787162922Sariff while (sc->chan_blkcnt >> i) 3788162922Sariff i++; 3789162922Sariff sc->chan_blkcnt = 1 << (i - 1); 3790162922Sariff if (sc->chan_blkcnt < HDA_BDL_MIN) 3791162922Sariff sc->chan_blkcnt = HDA_BDL_MIN; 3792162922Sariff else if (sc->chan_blkcnt > HDA_BDL_MAX) 3793162922Sariff sc->chan_blkcnt = HDA_BDL_MAX; 3794162922Sariff } else 3795162922Sariff sc->chan_blkcnt = HDA_BDL_DEFAULT; 3796162922Sariff 3797162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 3798162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 3799162922Sariff 0, /* boundary */ 3800162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 3801162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 3802162922Sariff NULL, /* filtfunc */ 3803162922Sariff NULL, /* fistfuncarg */ 3804165281Sariff sc->chan_size, /* maxsize */ 3805162922Sariff 1, /* nsegments */ 3806165281Sariff sc->chan_size, /* maxsegsz */ 3807162922Sariff 0, /* flags */ 3808162922Sariff NULL, /* lockfunc */ 3809162922Sariff NULL, /* lockfuncarg */ 3810162922Sariff &sc->chan_dmat); /* dmat */ 3811162922Sariff if (result != 0) { 3812169277Sariff device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 3813162922Sariff __func__, result); 3814163057Sariff snd_mtxfree(sc->lock); 3815162922Sariff free(sc, M_DEVBUF); 3816162922Sariff return (ENXIO); 3817162922Sariff } 3818162922Sariff 3819162922Sariff 3820162922Sariff sc->hdabus = NULL; 3821162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 3822162922Sariff sc->codecs[i] = NULL; 3823162922Sariff 3824162922Sariff pci_enable_busmaster(dev); 3825162922Sariff 3826169277Sariff if (vendor == INTEL_VENDORID) { 3827169277Sariff /* TCSEL -> TC0 */ 3828169277Sariff v = pci_read_config(dev, 0x44, 1); 3829169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 3830169277Sariff HDA_BOOTVERBOSE( 3831169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 3832169277Sariff pci_read_config(dev, 0x44, 1)); 3833169277Sariff ); 3834169277Sariff } 3835169277Sariff 3836178155Sariff#ifdef HDAC_MSI_ENABLED 3837171330Sariff if (resource_int_value(device_get_name(dev), 3838171330Sariff device_get_unit(dev), "msi", &i) == 0 && i != 0 && 3839171330Sariff pci_msi_count(dev) == 1) 3840171330Sariff sc->flags |= HDAC_F_MSI; 3841171330Sariff else 3842171330Sariff#endif 3843171330Sariff sc->flags &= ~HDAC_F_MSI; 3844171330Sariff 3845169277Sariff#if defined(__i386__) || defined(__amd64__) 3846171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3847169277Sariff 3848169277Sariff if (resource_int_value(device_get_name(dev), 3849169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 3850169277Sariff#else 3851171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3852169277Sariff#endif 3853169277Sariff /* 3854169277Sariff * Try to enable PCIe snoop to avoid messing around with 3855169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 3856169277Sariff * config is pretty much vendor specific, there are no 3857169277Sariff * general solutions on how to enable it, forcing us (even 3858169277Sariff * Microsoft) to enable uncacheable or write combined DMA 3859169277Sariff * by default. 3860169277Sariff * 3861169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 3862169277Sariff */ 3863169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 3864169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 3865169277Sariff continue; 3866171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 3867169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 3868169277Sariff break; 3869169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3870169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 3871169277Sariff hdac_pcie_snoop[i].enable) 3872169277Sariff break; 3873169277Sariff v &= hdac_pcie_snoop[i].mask; 3874169277Sariff v |= hdac_pcie_snoop[i].enable; 3875169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 3876169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 3877169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 3878169277Sariff hdac_pcie_snoop[i].enable) { 3879169277Sariff HDA_BOOTVERBOSE( 3880169277Sariff device_printf(dev, 3881169277Sariff "WARNING: Failed to enable PCIe " 3882169277Sariff "snoop!\n"); 3883169277Sariff ); 3884169277Sariff#if defined(__i386__) || defined(__amd64__) 3885171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 3886169277Sariff#endif 3887169277Sariff } 3888169277Sariff break; 3889169277Sariff } 3890169277Sariff#if defined(__i386__) || defined(__amd64__) 3891169277Sariff } 3892169277Sariff#endif 3893169277Sariff 3894169277Sariff HDA_BOOTVERBOSE( 3895169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 3896171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 3897171330Sariff "Uncacheable" : "PCIe snoop", vendor); 3898169277Sariff ); 3899169277Sariff 3900162922Sariff /* Allocate resources */ 3901162922Sariff result = hdac_mem_alloc(sc); 3902162922Sariff if (result != 0) 3903163057Sariff goto hdac_attach_fail; 3904162922Sariff result = hdac_irq_alloc(sc); 3905162922Sariff if (result != 0) 3906163057Sariff goto hdac_attach_fail; 3907162922Sariff 3908162922Sariff /* Get Capabilities */ 3909162922Sariff result = hdac_get_capabilities(sc); 3910162922Sariff if (result != 0) 3911163057Sariff goto hdac_attach_fail; 3912162922Sariff 3913162922Sariff /* Allocate CORB and RIRB dma memory */ 3914162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 3915162922Sariff sc->corb_size * sizeof(uint32_t)); 3916162922Sariff if (result != 0) 3917163057Sariff goto hdac_attach_fail; 3918162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 3919162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 3920162922Sariff if (result != 0) 3921163057Sariff goto hdac_attach_fail; 3922162922Sariff 3923162922Sariff /* Quiesce everything */ 3924162922Sariff hdac_reset(sc); 3925162922Sariff 3926162922Sariff /* Initialize the CORB and RIRB */ 3927162922Sariff hdac_corb_init(sc); 3928162922Sariff hdac_rirb_init(sc); 3929162922Sariff 3930162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 3931162922Sariff sc->intrhook.ich_func = hdac_attach2; 3932162922Sariff sc->intrhook.ich_arg = (void *)sc; 3933162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 3934162922Sariff sc->intrhook.ich_func = NULL; 3935162922Sariff hdac_attach2((void *)sc); 3936162922Sariff } 3937162922Sariff 3938163057Sariff return (0); 3939162922Sariff 3940163057Sariffhdac_attach_fail: 3941162922Sariff hdac_irq_free(sc); 3942169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 3943169277Sariff hdac_dma_free(sc, &sc->corb_dma); 3944162922Sariff hdac_mem_free(sc); 3945162922Sariff snd_mtxfree(sc->lock); 3946163057Sariff free(sc, M_DEVBUF); 3947162922Sariff 3948163057Sariff return (ENXIO); 3949162922Sariff} 3950162922Sariff 3951162922Sariffstatic void 3952162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 3953162922Sariff{ 3954162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3955162922Sariff struct hdac_widget *w; 3956162922Sariff uint32_t res; 3957162922Sariff int i; 3958162922Sariff nid_t cad, nid; 3959162922Sariff 3960162922Sariff cad = devinfo->codec->cad; 3961162922Sariff nid = devinfo->nid; 3962162922Sariff 3963162922Sariff hdac_command(sc, 3964162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), cad); 3965162922Sariff 3966162922Sariff DELAY(100); 3967162922Sariff 3968162922Sariff res = hdac_command(sc, 3969162922Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 3970162922Sariff 3971162922Sariff devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 3972162922Sariff devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 3973162922Sariff devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 3974162922Sariff 3975169277Sariff res = hdac_command(sc, 3976169277Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad); 3977169277Sariff devinfo->function.audio.gpio = res; 3978169277Sariff 3979163057Sariff HDA_BOOTVERBOSE( 3980162922Sariff device_printf(sc->dev, " Vendor: 0x%08x\n", 3981162922Sariff devinfo->vendor_id); 3982162922Sariff device_printf(sc->dev, " Device: 0x%08x\n", 3983162922Sariff devinfo->device_id); 3984162922Sariff device_printf(sc->dev, " Revision: 0x%08x\n", 3985162922Sariff devinfo->revision_id); 3986162922Sariff device_printf(sc->dev, " Stepping: 0x%08x\n", 3987162922Sariff devinfo->stepping_id); 3988162922Sariff device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 3989162922Sariff sc->pci_subvendor); 3990162922Sariff device_printf(sc->dev, " Nodes: start=%d " 3991162922Sariff "endnode=%d total=%d\n", 3992162922Sariff devinfo->startnode, devinfo->endnode, devinfo->nodecnt); 3993169277Sariff device_printf(sc->dev, " CORB size: %d\n", sc->corb_size); 3994169277Sariff device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size); 3995169277Sariff device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n", 3996169277Sariff sc->num_iss, sc->num_oss, sc->num_bss); 3997169277Sariff device_printf(sc->dev, " GPIO: 0x%08x\n", 3998169277Sariff devinfo->function.audio.gpio); 3999169277Sariff device_printf(sc->dev, " NumGPIO=%d NumGPO=%d " 4000169277Sariff "NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 4001169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 4002169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 4003169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 4004169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 4005169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 4006162922Sariff ); 4007162922Sariff 4008162922Sariff res = hdac_command(sc, 4009162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 4010162922Sariff cad); 4011162922Sariff devinfo->function.audio.supp_stream_formats = res; 4012162922Sariff 4013162922Sariff res = hdac_command(sc, 4014162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 4015162922Sariff cad); 4016162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 4017162922Sariff 4018162922Sariff res = hdac_command(sc, 4019162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 4020162922Sariff cad); 4021162922Sariff devinfo->function.audio.outamp_cap = res; 4022162922Sariff 4023162922Sariff res = hdac_command(sc, 4024162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 4025162922Sariff cad); 4026162922Sariff devinfo->function.audio.inamp_cap = res; 4027162922Sariff 4028169277Sariff if (devinfo->nodecnt > 0) 4029162922Sariff devinfo->widget = (struct hdac_widget *)malloc( 4030162922Sariff sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 4031162922Sariff M_NOWAIT | M_ZERO); 4032169277Sariff else 4033162922Sariff devinfo->widget = NULL; 4034162922Sariff 4035162922Sariff if (devinfo->widget == NULL) { 4036162922Sariff device_printf(sc->dev, "unable to allocate widgets!\n"); 4037162922Sariff devinfo->endnode = devinfo->startnode; 4038162922Sariff devinfo->nodecnt = 0; 4039162922Sariff return; 4040162922Sariff } 4041162922Sariff 4042162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4043162922Sariff w = hdac_widget_get(devinfo, i); 4044162922Sariff if (w == NULL) 4045162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 4046162922Sariff else { 4047162922Sariff w->devinfo = devinfo; 4048162922Sariff w->nid = i; 4049162922Sariff w->enable = 1; 4050162922Sariff w->selconn = -1; 4051162922Sariff w->pflags = 0; 4052162922Sariff w->ctlflags = 0; 4053162965Sariff w->param.eapdbtl = HDAC_INVALID; 4054162922Sariff hdac_widget_parse(w); 4055162922Sariff } 4056162922Sariff } 4057162922Sariff} 4058162922Sariff 4059162922Sariffstatic void 4060162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 4061162922Sariff{ 4062162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4063162922Sariff struct hdac_audio_ctl *ctls; 4064162922Sariff struct hdac_widget *w, *cw; 4065162922Sariff int i, j, cnt, max, ocap, icap; 4066163057Sariff int mute, offset, step, size; 4067162922Sariff 4068162922Sariff /* XXX This is redundant */ 4069162922Sariff max = 0; 4070162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4071162922Sariff w = hdac_widget_get(devinfo, i); 4072162922Sariff if (w == NULL || w->enable == 0) 4073162922Sariff continue; 4074162922Sariff if (w->param.outamp_cap != 0) 4075162922Sariff max++; 4076162922Sariff if (w->param.inamp_cap != 0) { 4077162922Sariff switch (w->type) { 4078162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4079162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4080162922Sariff for (j = 0; j < w->nconns; j++) { 4081162922Sariff cw = hdac_widget_get(devinfo, 4082162922Sariff w->conns[j]); 4083162922Sariff if (cw == NULL || cw->enable == 0) 4084162922Sariff continue; 4085162922Sariff max++; 4086162922Sariff } 4087162922Sariff break; 4088162922Sariff default: 4089162922Sariff max++; 4090162922Sariff break; 4091162922Sariff } 4092162922Sariff } 4093162922Sariff } 4094162922Sariff 4095162922Sariff devinfo->function.audio.ctlcnt = max; 4096162922Sariff 4097162922Sariff if (max < 1) 4098162922Sariff return; 4099162922Sariff 4100162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 4101162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 4102162922Sariff 4103162922Sariff if (ctls == NULL) { 4104162922Sariff /* Blekh! */ 4105162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 4106162922Sariff devinfo->function.audio.ctlcnt = 0; 4107162922Sariff return; 4108162922Sariff } 4109162922Sariff 4110162922Sariff cnt = 0; 4111162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 4112162922Sariff if (cnt >= max) { 4113162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 4114162922Sariff __func__); 4115162922Sariff break; 4116162922Sariff } 4117162922Sariff w = hdac_widget_get(devinfo, i); 4118162922Sariff if (w == NULL || w->enable == 0) 4119162922Sariff continue; 4120162922Sariff ocap = w->param.outamp_cap; 4121162922Sariff icap = w->param.inamp_cap; 4122162922Sariff if (ocap != 0) { 4123163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 4124163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 4125163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 4126163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 4127163057Sariff /*if (offset > step) { 4128163057Sariff HDA_BOOTVERBOSE( 4129163057Sariff device_printf(sc->dev, 4130163057Sariff "HDA_DEBUG: BUGGY outamp: nid=%d " 4131163057Sariff "[offset=%d > step=%d]\n", 4132163057Sariff w->nid, offset, step); 4133163057Sariff ); 4134163057Sariff offset = step; 4135163057Sariff }*/ 4136162922Sariff ctls[cnt].enable = 1; 4137162922Sariff ctls[cnt].widget = w; 4138163057Sariff ctls[cnt].mute = mute; 4139163057Sariff ctls[cnt].step = step; 4140163057Sariff ctls[cnt].size = size; 4141163057Sariff ctls[cnt].offset = offset; 4142163057Sariff ctls[cnt].left = offset; 4143163057Sariff ctls[cnt].right = offset; 4144162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 4145162922Sariff } 4146162922Sariff 4147162922Sariff if (icap != 0) { 4148163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 4149163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 4150163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 4151163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 4152163057Sariff /*if (offset > step) { 4153163057Sariff HDA_BOOTVERBOSE( 4154163057Sariff device_printf(sc->dev, 4155163057Sariff "HDA_DEBUG: BUGGY inamp: nid=%d " 4156163057Sariff "[offset=%d > step=%d]\n", 4157163057Sariff w->nid, offset, step); 4158163057Sariff ); 4159163057Sariff offset = step; 4160163057Sariff }*/ 4161162922Sariff switch (w->type) { 4162162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4163162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4164162922Sariff for (j = 0; j < w->nconns; j++) { 4165162922Sariff if (cnt >= max) { 4166162922Sariff device_printf(sc->dev, 4167162922Sariff "%s: Ctl overflow!\n", 4168162922Sariff __func__); 4169162922Sariff break; 4170162922Sariff } 4171162922Sariff cw = hdac_widget_get(devinfo, 4172162922Sariff w->conns[j]); 4173162922Sariff if (cw == NULL || cw->enable == 0) 4174162922Sariff continue; 4175162922Sariff ctls[cnt].enable = 1; 4176162922Sariff ctls[cnt].widget = w; 4177162922Sariff ctls[cnt].childwidget = cw; 4178162922Sariff ctls[cnt].index = j; 4179163057Sariff ctls[cnt].mute = mute; 4180163057Sariff ctls[cnt].step = step; 4181163057Sariff ctls[cnt].size = size; 4182163057Sariff ctls[cnt].offset = offset; 4183163057Sariff ctls[cnt].left = offset; 4184163057Sariff ctls[cnt].right = offset; 4185162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4186162922Sariff } 4187162922Sariff break; 4188162922Sariff default: 4189162922Sariff if (cnt >= max) { 4190162922Sariff device_printf(sc->dev, 4191162922Sariff "%s: Ctl overflow!\n", 4192162922Sariff __func__); 4193162922Sariff break; 4194162922Sariff } 4195162922Sariff ctls[cnt].enable = 1; 4196162922Sariff ctls[cnt].widget = w; 4197163057Sariff ctls[cnt].mute = mute; 4198163057Sariff ctls[cnt].step = step; 4199163057Sariff ctls[cnt].size = size; 4200163057Sariff ctls[cnt].offset = offset; 4201163057Sariff ctls[cnt].left = offset; 4202163057Sariff ctls[cnt].right = offset; 4203162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 4204162922Sariff break; 4205162922Sariff } 4206162922Sariff } 4207162922Sariff } 4208162922Sariff 4209162922Sariff devinfo->function.audio.ctl = ctls; 4210162922Sariff} 4211162922Sariff 4212162965Sariffstatic const struct { 4213162965Sariff uint32_t model; 4214162965Sariff uint32_t id; 4215162965Sariff uint32_t set, unset; 4216162965Sariff} hdac_quirks[] = { 4217163057Sariff /* 4218163057Sariff * XXX Force stereo quirk. Monoural recording / playback 4219163057Sariff * on few codecs (especially ALC880) seems broken or 4220163057Sariff * perhaps unsupported. 4221163057Sariff */ 4222163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 4223169277Sariff HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 }, 4224162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 4225165039Sariff HDA_QUIRK_GPIO0, 0 }, 4226178155Sariff { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, 4227178155Sariff HDA_QUIRK_GPIO0, 0 }, 4228162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 4229165039Sariff HDA_QUIRK_GPIO0, 0 }, 4230165281Sariff { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, 4231165281Sariff HDA_QUIRK_GPIO0, 0 }, 4232167623Sariff { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, 4233167623Sariff HDA_QUIRK_GPIO0, 0 }, 4234169277Sariff { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, 4235169277Sariff HDA_QUIRK_GPIO0, 0 }, 4236163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 4237163276Sariff HDA_QUIRK_EAPDINV, 0 }, 4238178155Sariff { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, 4239163432Sariff HDA_QUIRK_EAPDINV, 0 }, 4240169277Sariff { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, 4241169277Sariff HDA_QUIRK_OVREF, 0 }, 4242169277Sariff { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, 4243169277Sariff HDA_QUIRK_OVREF, 0 }, 4244169277Sariff /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, 4245169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/ 4246165281Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 4247165281Sariff HDA_QUIRK_GPIO1, 0 }, 4248164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 4249164614Sariff HDA_QUIRK_EAPDINV, 0 }, 4250164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 4251164657Sariff HDA_QUIRK_EAPDINV, 0 }, 4252173817Sariff { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, 4253173817Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, 4254165039Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, 4255165039Sariff HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, 4256178155Sariff { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205, 4257178155Sariff HDA_QUIRK_GPIO0, 0 }, 4258169277Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988, 4259169277Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4260170518Sariff { HDA_MATCH_ALL, HDA_CODEC_AD1988B, 4261170518Sariff HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 }, 4262162965Sariff { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 4263162965Sariff 0, HDA_QUIRK_FORCESTEREO }, 4264162965Sariff { HDA_MATCH_ALL, HDA_CODEC_STACXXXX, 4265162965Sariff HDA_QUIRK_SOFTPCMVOL, 0 } 4266162965Sariff}; 4267162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 4268162965Sariff 4269162922Sariffstatic void 4270162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 4271162922Sariff{ 4272162922Sariff struct hdac_widget *w; 4273165466Sariff struct hdac_audio_ctl *ctl; 4274162965Sariff uint32_t id, subvendor; 4275162922Sariff int i; 4276162922Sariff 4277163057Sariff id = hdac_codec_id(devinfo); 4278163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 4279163057Sariff 4280162922Sariff /* 4281163057Sariff * Quirks 4282162922Sariff */ 4283163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 4284163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 4285163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 4286163057Sariff continue; 4287163057Sariff if (hdac_quirks[i].set != 0) 4288163057Sariff devinfo->function.audio.quirks |= 4289163057Sariff hdac_quirks[i].set; 4290163057Sariff if (hdac_quirks[i].unset != 0) 4291163057Sariff devinfo->function.audio.quirks &= 4292163057Sariff ~(hdac_quirks[i].unset); 4293163057Sariff } 4294163057Sariff 4295162922Sariff switch (id) { 4296162922Sariff case HDA_CODEC_ALC260: 4297162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4298162922Sariff w = hdac_widget_get(devinfo, i); 4299162922Sariff if (w == NULL || w->enable == 0) 4300162922Sariff continue; 4301162922Sariff if (w->type != 4302162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4303162922Sariff continue; 4304162922Sariff if (w->nid != 5) 4305162922Sariff w->enable = 0; 4306162922Sariff } 4307166294Sariff if (subvendor == HP_XW4300_SUBVENDOR) { 4308166294Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 16, 0, 1); 4309166294Sariff if (ctl != NULL && ctl->widget != NULL) { 4310166294Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4311166294Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4312166294Sariff } 4313166294Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 17, 0, 1); 4314166294Sariff if (ctl != NULL && ctl->widget != NULL) { 4315166294Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4316166294Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4317166294Sariff } 4318169277Sariff } else if (subvendor == HP_3010_SUBVENDOR) { 4319169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 17, 0, 1); 4320169277Sariff if (ctl != NULL && ctl->widget != NULL) { 4321169277Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4322169277Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4323169277Sariff } 4324169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 21, 0, 1); 4325169277Sariff if (ctl != NULL && ctl->widget != NULL) { 4326169277Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4327169277Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4328169277Sariff } 4329166294Sariff } 4330162922Sariff break; 4331172811Sariff case HDA_CODEC_ALC262: 4332174579Sariff if (subvendor == HP_DC7700S_SUBVENDOR) { 4333174579Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 21, 0, 1); 4334174579Sariff if (ctl != NULL && ctl->widget != NULL) { 4335174579Sariff ctl->ossmask = SOUND_MASK_PHONEOUT; 4336174579Sariff ctl->widget->ctlflags |= SOUND_MASK_PHONEOUT; 4337174579Sariff } 4338172811Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 22, 0, 1); 4339172811Sariff if (ctl != NULL && ctl->widget != NULL) { 4340172811Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4341172811Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4342172811Sariff } 4343174579Sariff } else if (subvendor == HP_DC7700_SUBVENDOR) { 4344174579Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 22, 0, 1); 4345174579Sariff if (ctl != NULL && ctl->widget != NULL) { 4346174579Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4347174579Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4348174579Sariff } 4349172811Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 27, 0, 1); 4350172811Sariff if (ctl != NULL && ctl->widget != NULL) { 4351172811Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4352172811Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4353172811Sariff } 4354172811Sariff } 4355172811Sariff break; 4356174025Sariff case HDA_CODEC_ALC268: 4357174025Sariff if (HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subvendor)) { 4358174025Sariff w = hdac_widget_get(devinfo, 29); 4359174025Sariff if (w != NULL) { 4360174025Sariff w->enable = 1; 4361174025Sariff w->type = 4362174025Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET; 4363174025Sariff w->param.widget_cap &= 4364174025Sariff ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 4365174025Sariff w->param.widget_cap |= 4366174025Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 4367174025Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 4368174025Sariff strlcpy(w->name, "beep widget", sizeof(w->name)); 4369174025Sariff } 4370174025Sariff } 4371174025Sariff break; 4372165103Sariff case HDA_CODEC_ALC861: 4373169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 21, 2, 1); 4374165466Sariff if (ctl != NULL) 4375165466Sariff ctl->muted = HDA_AMP_MUTE_ALL; 4376165103Sariff break; 4377162922Sariff case HDA_CODEC_ALC880: 4378162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4379162922Sariff w = hdac_widget_get(devinfo, i); 4380162922Sariff if (w == NULL || w->enable == 0) 4381162922Sariff continue; 4382162922Sariff if (w->type == 4383162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 4384162922Sariff w->nid != 9 && w->nid != 29) { 4385162922Sariff w->enable = 0; 4386162922Sariff } else if (w->type != 4387162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET && 4388162922Sariff w->nid == 29) { 4389163057Sariff w->type = 4390163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET; 4391163057Sariff w->param.widget_cap &= 4392163057Sariff ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 4393162922Sariff w->param.widget_cap |= 4394162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 4395162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 4396162922Sariff strlcpy(w->name, "beep widget", sizeof(w->name)); 4397162922Sariff } 4398162922Sariff } 4399162922Sariff break; 4400166965Sariff case HDA_CODEC_ALC883: 4401166965Sariff /* 4402166965Sariff * nid: 24/25 = External (jack) or Internal (fixed) Mic. 4403166965Sariff * Clear vref cap for jack connectivity. 4404166965Sariff */ 4405166965Sariff w = hdac_widget_get(devinfo, 24); 4406166965Sariff if (w != NULL && w->enable != 0 && w->type == 4407166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4408166965Sariff (w->wclass.pin.config & 4409166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4410166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4411166965Sariff w->wclass.pin.cap &= ~( 4412166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4413166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4414166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4415166965Sariff w = hdac_widget_get(devinfo, 25); 4416166965Sariff if (w != NULL && w->enable != 0 && w->type == 4417166965Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4418166965Sariff (w->wclass.pin.config & 4419166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4420166965Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK) 4421166965Sariff w->wclass.pin.cap &= ~( 4422166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK | 4423166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK | 4424166965Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK); 4425166965Sariff /* 4426166965Sariff * nid: 26 = Line-in, leave it alone. 4427166965Sariff */ 4428166965Sariff break; 4429163257Sariff case HDA_CODEC_AD1981HD: 4430163257Sariff w = hdac_widget_get(devinfo, 11); 4431163257Sariff if (w != NULL && w->enable != 0 && w->nconns > 3) 4432163257Sariff w->selconn = 3; 4433163257Sariff if (subvendor == IBM_M52_SUBVENDOR) { 4434163257Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 7, 0, 1); 4435163257Sariff if (ctl != NULL) 4436163257Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 4437163257Sariff } 4438163257Sariff break; 4439162922Sariff case HDA_CODEC_AD1986A: 4440162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4441162922Sariff w = hdac_widget_get(devinfo, i); 4442162922Sariff if (w == NULL || w->enable == 0) 4443162922Sariff continue; 4444162922Sariff if (w->type != 4445162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 4446162922Sariff continue; 4447162922Sariff if (w->nid != 3) 4448162922Sariff w->enable = 0; 4449162922Sariff } 4450171141Sariff if (subvendor == ASUS_M2NPVMX_SUBVENDOR || 4451171141Sariff subvendor == ASUS_A8NVMCSM_SUBVENDOR) { 4452169277Sariff /* nid 28 is mic, nid 29 is line-in */ 4453169277Sariff w = hdac_widget_get(devinfo, 15); 4454169277Sariff if (w != NULL) 4455169277Sariff w->selconn = 2; 4456169277Sariff w = hdac_widget_get(devinfo, 16); 4457169277Sariff if (w != NULL) 4458169277Sariff w->selconn = 1; 4459178155Sariff } else if (subvendor == ASUS_A8X_SUBVENDOR) { 4460178155Sariff /* 4461178155Sariff * This is just plain ridiculous.. There 4462178155Sariff * are several A8 series that share the same 4463178155Sariff * pci id but works differently (EAPD). 4464178155Sariff */ 4465178155Sariff w = hdac_widget_get(devinfo, 26); 4466178155Sariff if (w != NULL && w->type == 4467178155Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4468178155Sariff (w->wclass.pin.config & 4469178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 4470178155Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4471178155Sariff devinfo->function.audio.quirks &= 4472178155Sariff ~HDA_QUIRK_EAPDINV; 4473169277Sariff } 4474162922Sariff break; 4475169277Sariff case HDA_CODEC_AD1988: 4476170518Sariff case HDA_CODEC_AD1988B: 4477169277Sariff /*w = hdac_widget_get(devinfo, 12); 4478169277Sariff if (w != NULL) { 4479169277Sariff w->selconn = 1; 4480169277Sariff w->pflags |= HDA_ADC_LOCKED; 4481169277Sariff } 4482169277Sariff w = hdac_widget_get(devinfo, 13); 4483169277Sariff if (w != NULL) { 4484169277Sariff w->selconn = 4; 4485169277Sariff w->pflags |= HDA_ADC_LOCKED; 4486169277Sariff } 4487169277Sariff w = hdac_widget_get(devinfo, 14); 4488169277Sariff if (w != NULL) { 4489169277Sariff w->selconn = 2; 4490169277Sariff w->pflags |= HDA_ADC_LOCKED; 4491169277Sariff }*/ 4492169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 57, 0, 1); 4493169277Sariff if (ctl != NULL) { 4494169277Sariff ctl->ossmask = SOUND_MASK_IGAIN; 4495169277Sariff ctl->widget->ctlflags |= SOUND_MASK_IGAIN; 4496169277Sariff } 4497169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 58, 0, 1); 4498169277Sariff if (ctl != NULL) { 4499169277Sariff ctl->ossmask = SOUND_MASK_IGAIN; 4500169277Sariff ctl->widget->ctlflags |= SOUND_MASK_IGAIN; 4501169277Sariff } 4502169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 60, 0, 1); 4503169277Sariff if (ctl != NULL) { 4504169277Sariff ctl->ossmask = SOUND_MASK_IGAIN; 4505169277Sariff ctl->widget->ctlflags |= SOUND_MASK_IGAIN; 4506169277Sariff } 4507169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 0, 1); 4508169277Sariff if (ctl != NULL) { 4509169277Sariff ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME; 4510169277Sariff ctl->widget->ctlflags |= SOUND_MASK_MIC; 4511169277Sariff } 4512169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 4, 1); 4513169277Sariff if (ctl != NULL) { 4514169277Sariff ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME; 4515169277Sariff ctl->widget->ctlflags |= SOUND_MASK_MIC; 4516169277Sariff } 4517169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 1, 1); 4518169277Sariff if (ctl != NULL) { 4519169277Sariff ctl->ossmask = SOUND_MASK_LINE | SOUND_MASK_VOLUME; 4520169277Sariff ctl->widget->ctlflags |= SOUND_MASK_LINE; 4521169277Sariff } 4522169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 32, 7, 1); 4523169277Sariff if (ctl != NULL) { 4524169277Sariff ctl->ossmask = SOUND_MASK_SPEAKER | SOUND_MASK_VOLUME; 4525169277Sariff ctl->widget->ctlflags |= SOUND_MASK_SPEAKER; 4526169277Sariff } 4527169277Sariff break; 4528178155Sariff case HDA_CODEC_STAC9205: 4529178155Sariff if (subvendor == DELL_V1500_SUBVENDOR) { 4530178155Sariff w = hdac_widget_get(devinfo, 29); 4531178155Sariff if (w != NULL) 4532178155Sariff w->selconn = 1; 4533178155Sariff w = hdac_widget_get(devinfo, 30); 4534178155Sariff if (w != NULL) 4535178155Sariff w->selconn = 1; 4536178155Sariff } 4537178155Sariff break; 4538162922Sariff case HDA_CODEC_STAC9221: 4539169277Sariff /* 4540169277Sariff * Dell XPS M1210 need all DACs for each output jacks 4541169277Sariff */ 4542169277Sariff if (subvendor == DELL_XPSM1210_SUBVENDOR) 4543169277Sariff break; 4544162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4545162922Sariff w = hdac_widget_get(devinfo, i); 4546162922Sariff if (w == NULL || w->enable == 0) 4547162922Sariff continue; 4548162922Sariff if (w->type != 4549162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 4550162922Sariff continue; 4551162922Sariff if (w->nid != 2) 4552162922Sariff w->enable = 0; 4553162922Sariff } 4554162922Sariff break; 4555162922Sariff case HDA_CODEC_STAC9221D: 4556162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4557162922Sariff w = hdac_widget_get(devinfo, i); 4558162922Sariff if (w == NULL || w->enable == 0) 4559162922Sariff continue; 4560162922Sariff if (w->type == 4561162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 4562162922Sariff w->nid != 6) 4563162922Sariff w->enable = 0; 4564162922Sariff 4565162922Sariff } 4566162922Sariff break; 4567169277Sariff case HDA_CODEC_STAC9227: 4568169277Sariff w = hdac_widget_get(devinfo, 8); 4569169277Sariff if (w != NULL) 4570169277Sariff w->enable = 0; 4571169277Sariff w = hdac_widget_get(devinfo, 9); 4572169277Sariff if (w != NULL) 4573169277Sariff w->enable = 0; 4574169277Sariff break; 4575169277Sariff case HDA_CODEC_CXWAIKIKI: 4576169277Sariff if (subvendor == HP_DV5000_SUBVENDOR) { 4577169277Sariff w = hdac_widget_get(devinfo, 27); 4578169277Sariff if (w != NULL) 4579169277Sariff w->enable = 0; 4580169277Sariff } 4581169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 16, 0, 1); 4582169277Sariff if (ctl != NULL) 4583169277Sariff ctl->ossmask = SOUND_MASK_SKIP; 4584169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 25, 0, 1); 4585169277Sariff if (ctl != NULL && ctl->childwidget != NULL && 4586169277Sariff ctl->childwidget->enable != 0) { 4587169277Sariff ctl->ossmask = SOUND_MASK_PCM | SOUND_MASK_VOLUME; 4588169277Sariff ctl->childwidget->ctlflags |= SOUND_MASK_PCM; 4589169277Sariff } 4590169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 25, 1, 1); 4591169277Sariff if (ctl != NULL && ctl->childwidget != NULL && 4592169277Sariff ctl->childwidget->enable != 0) { 4593169277Sariff ctl->ossmask = SOUND_MASK_LINE | SOUND_MASK_VOLUME; 4594169277Sariff ctl->childwidget->ctlflags |= SOUND_MASK_LINE; 4595169277Sariff } 4596169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 25, 2, 1); 4597169277Sariff if (ctl != NULL && ctl->childwidget != NULL && 4598169277Sariff ctl->childwidget->enable != 0) { 4599169277Sariff ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME; 4600169277Sariff ctl->childwidget->ctlflags |= SOUND_MASK_MIC; 4601169277Sariff } 4602169277Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 26, 0, 1); 4603169277Sariff if (ctl != NULL) { 4604169277Sariff ctl->ossmask = SOUND_MASK_SKIP; 4605169277Sariff /* XXX mixer \=rec mic broken.. why?!? */ 4606169277Sariff /* ctl->widget->ctlflags |= SOUND_MASK_MIC; */ 4607169277Sariff } 4608169277Sariff break; 4609162922Sariff default: 4610162922Sariff break; 4611162922Sariff } 4612162922Sariff} 4613162922Sariff 4614162922Sariffstatic int 4615162922Sariffhdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *devinfo) 4616162922Sariff{ 4617162922Sariff int *dev = &devinfo->function.audio.ossidx; 4618162922Sariff 4619162922Sariff while (*dev < SOUND_MIXER_NRDEVICES) { 4620162922Sariff switch (*dev) { 4621162922Sariff case SOUND_MIXER_VOLUME: 4622162922Sariff case SOUND_MIXER_BASS: 4623162922Sariff case SOUND_MIXER_TREBLE: 4624162922Sariff case SOUND_MIXER_PCM: 4625162922Sariff case SOUND_MIXER_SPEAKER: 4626162922Sariff case SOUND_MIXER_LINE: 4627162922Sariff case SOUND_MIXER_MIC: 4628162922Sariff case SOUND_MIXER_CD: 4629162922Sariff case SOUND_MIXER_RECLEV: 4630169277Sariff case SOUND_MIXER_IGAIN: 4631162922Sariff case SOUND_MIXER_OGAIN: /* reserved for EAPD switch */ 4632162922Sariff (*dev)++; 4633162922Sariff break; 4634162922Sariff default: 4635162922Sariff return (*dev)++; 4636162922Sariff break; 4637162922Sariff } 4638162922Sariff } 4639162922Sariff 4640162922Sariff return (-1); 4641162922Sariff} 4642162922Sariff 4643162922Sariffstatic int 4644162922Sariffhdac_widget_find_dac_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4645162922Sariff{ 4646162922Sariff struct hdac_widget *w; 4647162922Sariff int i, ret = 0; 4648162922Sariff 4649162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4650162922Sariff return (0); 4651162922Sariff w = hdac_widget_get(devinfo, nid); 4652162922Sariff if (w == NULL || w->enable == 0) 4653162922Sariff return (0); 4654162922Sariff switch (w->type) { 4655162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 4656162922Sariff w->pflags |= HDA_DAC_PATH; 4657162922Sariff ret = 1; 4658162922Sariff break; 4659162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4660162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4661162922Sariff for (i = 0; i < w->nconns; i++) { 4662162922Sariff if (hdac_widget_find_dac_path(devinfo, 4663162922Sariff w->conns[i], depth + 1) != 0) { 4664162922Sariff if (w->selconn == -1) 4665162922Sariff w->selconn = i; 4666162922Sariff ret = 1; 4667162922Sariff w->pflags |= HDA_DAC_PATH; 4668162922Sariff } 4669162922Sariff } 4670162922Sariff break; 4671162922Sariff default: 4672162922Sariff break; 4673162922Sariff } 4674162922Sariff return (ret); 4675162922Sariff} 4676162922Sariff 4677162922Sariffstatic int 4678162922Sariffhdac_widget_find_adc_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4679162922Sariff{ 4680162922Sariff struct hdac_widget *w; 4681162922Sariff int i, conndev, ret = 0; 4682162922Sariff 4683162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4684162922Sariff return (0); 4685162922Sariff w = hdac_widget_get(devinfo, nid); 4686162922Sariff if (w == NULL || w->enable == 0) 4687162922Sariff return (0); 4688162922Sariff switch (w->type) { 4689162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 4690162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 4691162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4692162922Sariff for (i = 0; i < w->nconns; i++) { 4693162922Sariff if (hdac_widget_find_adc_path(devinfo, w->conns[i], 4694162922Sariff depth + 1) != 0) { 4695162922Sariff if (w->selconn == -1) 4696162922Sariff w->selconn = i; 4697162922Sariff w->pflags |= HDA_ADC_PATH; 4698162922Sariff ret = 1; 4699162922Sariff } 4700162922Sariff } 4701162922Sariff break; 4702162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 4703162922Sariff conndev = w->wclass.pin.config & 4704162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4705162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 4706162922Sariff (conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_CD || 4707162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN || 4708162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN)) { 4709162922Sariff w->pflags |= HDA_ADC_PATH; 4710162922Sariff ret = 1; 4711162922Sariff } 4712162922Sariff break; 4713162922Sariff /*case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 4714162922Sariff if (w->pflags & HDA_DAC_PATH) { 4715162922Sariff w->pflags |= HDA_ADC_PATH; 4716162922Sariff ret = 1; 4717162922Sariff } 4718162922Sariff break;*/ 4719162922Sariff default: 4720162922Sariff break; 4721162922Sariff } 4722162922Sariff return (ret); 4723162922Sariff} 4724162922Sariff 4725162922Sariffstatic uint32_t 4726162922Sariffhdac_audio_ctl_outamp_build(struct hdac_devinfo *devinfo, 4727162922Sariff nid_t nid, nid_t pnid, int index, int depth) 4728162922Sariff{ 4729162922Sariff struct hdac_widget *w, *pw; 4730162922Sariff struct hdac_audio_ctl *ctl; 4731162922Sariff uint32_t fl = 0; 4732162922Sariff int i, ossdev, conndev, strategy; 4733162922Sariff 4734162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4735162922Sariff return (0); 4736162922Sariff 4737162922Sariff w = hdac_widget_get(devinfo, nid); 4738162922Sariff if (w == NULL || w->enable == 0) 4739162922Sariff return (0); 4740162922Sariff 4741162922Sariff pw = hdac_widget_get(devinfo, pnid); 4742162922Sariff strategy = devinfo->function.audio.parsing_strategy; 4743162922Sariff 4744162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER 4745162922Sariff || w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) { 4746162922Sariff for (i = 0; i < w->nconns; i++) { 4747162922Sariff fl |= hdac_audio_ctl_outamp_build(devinfo, w->conns[i], 4748162922Sariff w->nid, i, depth + 1); 4749162922Sariff } 4750162922Sariff w->ctlflags |= fl; 4751162922Sariff return (fl); 4752162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT && 4753162922Sariff (w->pflags & HDA_DAC_PATH)) { 4754162922Sariff i = 0; 4755162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4756162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4757162922Sariff continue; 4758163057Sariff /* XXX This should be compressed! */ 4759169277Sariff if (((ctl->widget->nid == w->nid) || 4760162922Sariff (ctl->widget->nid == pnid && ctl->index == index && 4761162922Sariff (ctl->dir & HDA_CTL_IN)) || 4762162922Sariff (ctl->widget->nid == pnid && pw != NULL && 4763162922Sariff pw->type == 4764162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4765162922Sariff (pw->nconns < 2 || pw->selconn == index || 4766162922Sariff pw->selconn == -1) && 4767162922Sariff (ctl->dir & HDA_CTL_OUT)) || 4768162922Sariff (strategy == HDA_PARSE_DIRECT && 4769169277Sariff ctl->widget->nid == w->nid)) && 4770169277Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 4771163057Sariff /*if (pw != NULL && pw->selconn == -1) 4772162922Sariff pw->selconn = index; 4773162922Sariff fl |= SOUND_MASK_VOLUME; 4774162922Sariff fl |= SOUND_MASK_PCM; 4775162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4776162922Sariff ctl->ossmask |= SOUND_MASK_PCM; 4777163057Sariff ctl->ossdev = SOUND_MIXER_PCM;*/ 4778163057Sariff if (!(w->ctlflags & SOUND_MASK_PCM) || 4779163057Sariff (pw != NULL && 4780163057Sariff !(pw->ctlflags & SOUND_MASK_PCM))) { 4781163057Sariff fl |= SOUND_MASK_VOLUME; 4782163057Sariff fl |= SOUND_MASK_PCM; 4783163057Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4784163057Sariff ctl->ossmask |= SOUND_MASK_PCM; 4785163057Sariff ctl->ossdev = SOUND_MIXER_PCM; 4786163057Sariff w->ctlflags |= SOUND_MASK_VOLUME; 4787163057Sariff w->ctlflags |= SOUND_MASK_PCM; 4788163057Sariff if (pw != NULL) { 4789163057Sariff if (pw->selconn == -1) 4790163057Sariff pw->selconn = index; 4791163057Sariff pw->ctlflags |= 4792163057Sariff SOUND_MASK_VOLUME; 4793163057Sariff pw->ctlflags |= 4794163057Sariff SOUND_MASK_PCM; 4795163057Sariff } 4796163057Sariff } 4797162922Sariff } 4798162922Sariff } 4799162922Sariff w->ctlflags |= fl; 4800162922Sariff return (fl); 4801164614Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4802164614Sariff HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 4803162922Sariff (w->pflags & HDA_ADC_PATH)) { 4804162922Sariff conndev = w->wclass.pin.config & 4805162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4806162922Sariff i = 0; 4807162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4808162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4809162922Sariff continue; 4810163057Sariff /* XXX This should be compressed! */ 4811162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 4812162922Sariff (ctl->dir & HDA_CTL_IN)) || 4813162922Sariff (ctl->widget->nid == pnid && pw != NULL && 4814162922Sariff pw->type == 4815162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4816162922Sariff (pw->nconns < 2 || pw->selconn == index || 4817162922Sariff pw->selconn == -1) && 4818162922Sariff (ctl->dir & HDA_CTL_OUT)) || 4819162922Sariff (strategy == HDA_PARSE_DIRECT && 4820162922Sariff ctl->widget->nid == w->nid)) && 4821163057Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 4822162922Sariff if (pw != NULL && pw->selconn == -1) 4823162922Sariff pw->selconn = index; 4824162922Sariff ossdev = 0; 4825162922Sariff switch (conndev) { 4826162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 4827162922Sariff ossdev = SOUND_MIXER_MIC; 4828162922Sariff break; 4829162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 4830162922Sariff ossdev = SOUND_MIXER_LINE; 4831162922Sariff break; 4832162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 4833162922Sariff ossdev = SOUND_MIXER_CD; 4834162922Sariff break; 4835162922Sariff default: 4836162922Sariff ossdev = 4837162922Sariff hdac_audio_ctl_ossmixer_getnextdev( 4838162922Sariff devinfo); 4839162922Sariff if (ossdev < 0) 4840162922Sariff ossdev = 0; 4841162922Sariff break; 4842162922Sariff } 4843162922Sariff if (strategy == HDA_PARSE_MIXER) { 4844162922Sariff fl |= SOUND_MASK_VOLUME; 4845162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4846162922Sariff } 4847162922Sariff fl |= 1 << ossdev; 4848162922Sariff ctl->ossmask |= 1 << ossdev; 4849162922Sariff ctl->ossdev = ossdev; 4850162922Sariff } 4851162922Sariff } 4852162922Sariff w->ctlflags |= fl; 4853162922Sariff return (fl); 4854162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 4855162922Sariff i = 0; 4856162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4857162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4858162922Sariff continue; 4859163057Sariff /* XXX This should be compressed! */ 4860162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 4861162922Sariff (ctl->dir & HDA_CTL_IN)) || 4862162922Sariff (ctl->widget->nid == pnid && pw != NULL && 4863162922Sariff pw->type == 4864162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 4865162922Sariff (pw->nconns < 2 || pw->selconn == index || 4866162922Sariff pw->selconn == -1) && 4867162922Sariff (ctl->dir & HDA_CTL_OUT)) || 4868162922Sariff (strategy == HDA_PARSE_DIRECT && 4869162922Sariff ctl->widget->nid == w->nid)) && 4870163057Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 4871162922Sariff if (pw != NULL && pw->selconn == -1) 4872162922Sariff pw->selconn = index; 4873162922Sariff fl |= SOUND_MASK_VOLUME; 4874162922Sariff fl |= SOUND_MASK_SPEAKER; 4875162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4876162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 4877162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 4878162922Sariff } 4879162922Sariff } 4880162922Sariff w->ctlflags |= fl; 4881162922Sariff return (fl); 4882162922Sariff } 4883162922Sariff return (0); 4884162922Sariff} 4885162922Sariff 4886162922Sariffstatic uint32_t 4887162922Sariffhdac_audio_ctl_inamp_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4888162922Sariff{ 4889162922Sariff struct hdac_widget *w, *cw; 4890162922Sariff struct hdac_audio_ctl *ctl; 4891162922Sariff uint32_t fl; 4892162922Sariff int i; 4893162922Sariff 4894162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4895162922Sariff return (0); 4896162922Sariff 4897162922Sariff w = hdac_widget_get(devinfo, nid); 4898162922Sariff if (w == NULL || w->enable == 0) 4899162922Sariff return (0); 4900162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 4901162922Sariff return (0); 4902162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 4903162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4904162922Sariff return (0);*/ 4905162922Sariff i = 0; 4906162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4907162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4908162922Sariff continue; 4909162922Sariff if (ctl->widget->nid == nid) { 4910162922Sariff ctl->ossmask |= SOUND_MASK_RECLEV; 4911162922Sariff w->ctlflags |= SOUND_MASK_RECLEV; 4912162922Sariff return (SOUND_MASK_RECLEV); 4913162922Sariff } 4914162922Sariff } 4915162922Sariff for (i = 0; i < w->nconns; i++) { 4916162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 4917162922Sariff if (cw == NULL || cw->enable == 0) 4918162922Sariff continue; 4919162922Sariff if (cw->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 4920162922Sariff continue; 4921162922Sariff fl = hdac_audio_ctl_inamp_build(devinfo, cw->nid, depth + 1); 4922162922Sariff if (fl != 0) { 4923162922Sariff cw->ctlflags |= fl; 4924162922Sariff w->ctlflags |= fl; 4925162922Sariff return (fl); 4926162922Sariff } 4927162922Sariff } 4928162922Sariff return (0); 4929162922Sariff} 4930162922Sariff 4931162922Sariffstatic int 4932162922Sariffhdac_audio_ctl_recsel_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4933162922Sariff{ 4934162922Sariff struct hdac_widget *w, *cw; 4935162922Sariff int i, child = 0; 4936162922Sariff 4937162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 4938162922Sariff return (0); 4939162922Sariff 4940162922Sariff w = hdac_widget_get(devinfo, nid); 4941162922Sariff if (w == NULL || w->enable == 0) 4942162922Sariff return (0); 4943162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 4944162922Sariff return (0); 4945162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 4946162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4947162922Sariff return (0);*/ 4948162922Sariff /* XXX weak! */ 4949162922Sariff for (i = 0; i < w->nconns; i++) { 4950162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 4951162922Sariff if (cw == NULL) 4952162922Sariff continue; 4953162922Sariff if (++child > 1) { 4954162922Sariff w->pflags |= HDA_ADC_RECSEL; 4955162922Sariff return (1); 4956162922Sariff } 4957162922Sariff } 4958162922Sariff for (i = 0; i < w->nconns; i++) { 4959162922Sariff if (hdac_audio_ctl_recsel_build(devinfo, 4960162922Sariff w->conns[i], depth + 1) != 0) 4961162922Sariff return (1); 4962162922Sariff } 4963162922Sariff return (0); 4964162922Sariff} 4965162922Sariff 4966162922Sariffstatic int 4967162922Sariffhdac_audio_build_tree_strategy(struct hdac_devinfo *devinfo) 4968162922Sariff{ 4969162922Sariff struct hdac_widget *w, *cw; 4970162922Sariff int i, j, conndev, found_dac = 0; 4971162922Sariff int strategy; 4972162922Sariff 4973162922Sariff strategy = devinfo->function.audio.parsing_strategy; 4974162922Sariff 4975162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4976162922Sariff w = hdac_widget_get(devinfo, i); 4977162922Sariff if (w == NULL || w->enable == 0) 4978162922Sariff continue; 4979162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4980162922Sariff continue; 4981162922Sariff if (!HDA_PARAM_PIN_CAP_OUTPUT_CAP(w->wclass.pin.cap)) 4982162922Sariff continue; 4983162922Sariff conndev = w->wclass.pin.config & 4984162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 4985162922Sariff if (!(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 4986162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 4987162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT)) 4988162922Sariff continue; 4989162922Sariff for (j = 0; j < w->nconns; j++) { 4990162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 4991162922Sariff if (cw == NULL || cw->enable == 0) 4992162922Sariff continue; 4993162922Sariff if (strategy == HDA_PARSE_MIXER && !(cw->type == 4994162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 4995162922Sariff cw->type == 4996162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 4997162922Sariff continue; 4998162922Sariff if (hdac_widget_find_dac_path(devinfo, cw->nid, 0) 4999162922Sariff != 0) { 5000162922Sariff if (w->selconn == -1) 5001162922Sariff w->selconn = j; 5002162922Sariff w->pflags |= HDA_DAC_PATH; 5003162922Sariff found_dac++; 5004162922Sariff } 5005162922Sariff } 5006162922Sariff } 5007162922Sariff 5008162922Sariff return (found_dac); 5009162922Sariff} 5010162922Sariff 5011162922Sariffstatic void 5012162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 5013162922Sariff{ 5014162922Sariff struct hdac_widget *w; 5015162922Sariff struct hdac_audio_ctl *ctl; 5016162922Sariff int i, j, dacs, strategy; 5017162922Sariff 5018162922Sariff /* Construct DAC path */ 5019162922Sariff strategy = HDA_PARSE_MIXER; 5020162922Sariff devinfo->function.audio.parsing_strategy = strategy; 5021163057Sariff HDA_BOOTVERBOSE( 5022162922Sariff device_printf(devinfo->codec->sc->dev, 5023163057Sariff "HDA_DEBUG: HWiP: HDA Widget Parser - Revision %d\n", 5024162922Sariff HDA_WIDGET_PARSER_REV); 5025162922Sariff ); 5026162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 5027162922Sariff if (dacs == 0) { 5028163057Sariff HDA_BOOTVERBOSE( 5029162922Sariff device_printf(devinfo->codec->sc->dev, 5030163057Sariff "HDA_DEBUG: HWiP: 0 DAC path found! " 5031163057Sariff "Retrying parser " 5032162922Sariff "using HDA_PARSE_DIRECT strategy.\n"); 5033162922Sariff ); 5034162922Sariff strategy = HDA_PARSE_DIRECT; 5035162922Sariff devinfo->function.audio.parsing_strategy = strategy; 5036162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 5037162922Sariff } 5038162922Sariff 5039163057Sariff HDA_BOOTVERBOSE( 5040162922Sariff device_printf(devinfo->codec->sc->dev, 5041163057Sariff "HDA_DEBUG: HWiP: Found %d DAC path using HDA_PARSE_%s " 5042163057Sariff "strategy.\n", 5043162922Sariff dacs, (strategy == HDA_PARSE_MIXER) ? "MIXER" : "DIRECT"); 5044162922Sariff ); 5045162922Sariff 5046162922Sariff /* Construct ADC path */ 5047162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5048162922Sariff w = hdac_widget_get(devinfo, i); 5049162922Sariff if (w == NULL || w->enable == 0) 5050162922Sariff continue; 5051162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 5052162922Sariff continue; 5053162922Sariff (void)hdac_widget_find_adc_path(devinfo, w->nid, 0); 5054162922Sariff } 5055162922Sariff 5056162922Sariff /* Output mixers */ 5057162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5058162922Sariff w = hdac_widget_get(devinfo, i); 5059162922Sariff if (w == NULL || w->enable == 0) 5060162922Sariff continue; 5061162922Sariff if ((strategy == HDA_PARSE_MIXER && 5062162922Sariff (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 5063162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 5064162922Sariff && (w->pflags & HDA_DAC_PATH)) || 5065162922Sariff (strategy == HDA_PARSE_DIRECT && (w->pflags & 5066162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)))) { 5067162922Sariff w->ctlflags |= hdac_audio_ctl_outamp_build(devinfo, 5068162922Sariff w->nid, devinfo->startnode - 1, 0, 0); 5069162922Sariff } else if (w->type == 5070162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 5071162922Sariff j = 0; 5072162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &j)) != 5073162922Sariff NULL) { 5074162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 5075162922Sariff continue; 5076162922Sariff if (ctl->widget->nid != w->nid) 5077162922Sariff continue; 5078162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 5079162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 5080162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 5081162922Sariff w->ctlflags |= SOUND_MASK_VOLUME; 5082162922Sariff w->ctlflags |= SOUND_MASK_SPEAKER; 5083162922Sariff } 5084162922Sariff } 5085162922Sariff } 5086162922Sariff 5087162922Sariff /* Input mixers (rec) */ 5088162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5089162922Sariff w = hdac_widget_get(devinfo, i); 5090162922Sariff if (w == NULL || w->enable == 0) 5091162922Sariff continue; 5092162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 5093162922Sariff w->pflags & HDA_ADC_PATH)) 5094162922Sariff continue; 5095162922Sariff hdac_audio_ctl_inamp_build(devinfo, w->nid, 0); 5096162922Sariff hdac_audio_ctl_recsel_build(devinfo, w->nid, 0); 5097162922Sariff } 5098162922Sariff} 5099162922Sariff 5100162922Sariff#define HDA_COMMIT_CONN (1 << 0) 5101162922Sariff#define HDA_COMMIT_CTRL (1 << 1) 5102162922Sariff#define HDA_COMMIT_EAPD (1 << 2) 5103162922Sariff#define HDA_COMMIT_GPIO (1 << 3) 5104169277Sariff#define HDA_COMMIT_MISC (1 << 4) 5105162922Sariff#define HDA_COMMIT_ALL (HDA_COMMIT_CONN | HDA_COMMIT_CTRL | \ 5106169277Sariff HDA_COMMIT_EAPD | HDA_COMMIT_GPIO | HDA_COMMIT_MISC) 5107162922Sariff 5108162922Sariffstatic void 5109162922Sariffhdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl) 5110162922Sariff{ 5111162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5112162922Sariff struct hdac_widget *w; 5113164750Sariff nid_t cad; 5114164750Sariff int i; 5115162922Sariff 5116162922Sariff if (!(cfl & HDA_COMMIT_ALL)) 5117162922Sariff return; 5118162922Sariff 5119162922Sariff cad = devinfo->codec->cad; 5120162922Sariff 5121169277Sariff if ((cfl & HDA_COMMIT_MISC)) { 5122169277Sariff if (sc->pci_subvendor == APPLE_INTEL_MAC) 5123169277Sariff hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 5124169277Sariff 0x7e7, 0), cad); 5125169277Sariff } 5126169277Sariff 5127163057Sariff if (cfl & HDA_COMMIT_GPIO) { 5128165039Sariff uint32_t gdata, gmask, gdir; 5129169277Sariff int commitgpio, numgpio; 5130164828Sariff 5131165039Sariff gdata = 0; 5132165039Sariff gmask = 0; 5133165039Sariff gdir = 0; 5134169277Sariff commitgpio = 0; 5135166796Sariff 5136169277Sariff numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO( 5137169277Sariff devinfo->function.audio.gpio); 5138165039Sariff 5139165039Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) 5140169277Sariff commitgpio = (numgpio > 0) ? 1 : 0; 5141165039Sariff else { 5142169277Sariff for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) { 5143165039Sariff if (!(devinfo->function.audio.quirks & 5144165039Sariff (1 << i))) 5145165039Sariff continue; 5146165039Sariff if (commitgpio == 0) { 5147165039Sariff commitgpio = 1; 5148165039Sariff HDA_BOOTVERBOSE( 5149169277Sariff gdata = hdac_command(sc, 5150169277Sariff HDA_CMD_GET_GPIO_DATA(cad, 5151169277Sariff devinfo->nid), cad); 5152169277Sariff gmask = hdac_command(sc, 5153169277Sariff HDA_CMD_GET_GPIO_ENABLE_MASK(cad, 5154169277Sariff devinfo->nid), cad); 5155169277Sariff gdir = hdac_command(sc, 5156169277Sariff HDA_CMD_GET_GPIO_DIRECTION(cad, 5157169277Sariff devinfo->nid), cad); 5158165039Sariff device_printf(sc->dev, 5159165039Sariff "GPIO init: data=0x%08x " 5160165039Sariff "mask=0x%08x dir=0x%08x\n", 5161165039Sariff gdata, gmask, gdir); 5162169277Sariff gdata = 0; 5163169277Sariff gmask = 0; 5164169277Sariff gdir = 0; 5165165039Sariff ); 5166165039Sariff } 5167165039Sariff gdata |= 1 << i; 5168165039Sariff gmask |= 1 << i; 5169165039Sariff gdir |= 1 << i; 5170165039Sariff } 5171165039Sariff } 5172165039Sariff 5173165039Sariff if (commitgpio != 0) { 5174165039Sariff HDA_BOOTVERBOSE( 5175165039Sariff device_printf(sc->dev, 5176165039Sariff "GPIO commit: data=0x%08x mask=0x%08x " 5177165039Sariff "dir=0x%08x\n", 5178165039Sariff gdata, gmask, gdir); 5179165039Sariff ); 5180162922Sariff hdac_command(sc, 5181164828Sariff HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 5182164828Sariff gmask), cad); 5183164828Sariff hdac_command(sc, 5184164828Sariff HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 5185164828Sariff gdir), cad); 5186164828Sariff hdac_command(sc, 5187164828Sariff HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 5188164828Sariff gdata), cad); 5189162922Sariff } 5190162922Sariff } 5191162922Sariff 5192162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 5193162922Sariff w = &devinfo->widget[i]; 5194162922Sariff if (w == NULL || w->enable == 0) 5195162922Sariff continue; 5196162922Sariff if (cfl & HDA_COMMIT_CONN) { 5197162922Sariff if (w->selconn == -1) 5198162922Sariff w->selconn = 0; 5199162922Sariff if (w->nconns > 0) 5200162922Sariff hdac_widget_connection_select(w, w->selconn); 5201162922Sariff } 5202162922Sariff if ((cfl & HDA_COMMIT_CTRL) && 5203162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5204169277Sariff uint32_t pincap; 5205169277Sariff 5206169277Sariff pincap = w->wclass.pin.cap; 5207169277Sariff 5208162922Sariff if ((w->pflags & (HDA_DAC_PATH | HDA_ADC_PATH)) == 5209162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)) 5210162922Sariff device_printf(sc->dev, "WARNING: node %d " 5211162922Sariff "participate both for DAC/ADC!\n", w->nid); 5212162922Sariff if (w->pflags & HDA_DAC_PATH) { 5213162922Sariff w->wclass.pin.ctrl &= 5214162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 5215162922Sariff if ((w->wclass.pin.config & 5216162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) != 5217162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 5218162922Sariff w->wclass.pin.ctrl &= 5219162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 5220169277Sariff if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) && 5221169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5222169277Sariff w->wclass.pin.ctrl |= 5223169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5224169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5225169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) && 5226169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5227169277Sariff w->wclass.pin.ctrl |= 5228169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5229169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5230169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) && 5231169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5232169277Sariff w->wclass.pin.ctrl |= 5233169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5234169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5235162922Sariff } else if (w->pflags & HDA_ADC_PATH) { 5236162922Sariff w->wclass.pin.ctrl &= 5237162922Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 5238162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE); 5239169277Sariff if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) && 5240169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5241169277Sariff w->wclass.pin.ctrl |= 5242169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5243169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100); 5244169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) && 5245169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5246169277Sariff w->wclass.pin.ctrl |= 5247169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5248169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80); 5249169277Sariff else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) && 5250169277Sariff HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5251169277Sariff w->wclass.pin.ctrl |= 5252169277Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE( 5253169277Sariff HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50); 5254162922Sariff } else 5255162922Sariff w->wclass.pin.ctrl &= ~( 5256162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 5257162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 5258165069Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE | 5259165069Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK); 5260162922Sariff hdac_command(sc, 5261162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 5262162922Sariff w->wclass.pin.ctrl), cad); 5263162922Sariff } 5264162922Sariff if ((cfl & HDA_COMMIT_EAPD) && 5265163276Sariff w->param.eapdbtl != HDAC_INVALID) { 5266163432Sariff uint32_t val; 5267163432Sariff 5268163432Sariff val = w->param.eapdbtl; 5269163276Sariff if (devinfo->function.audio.quirks & 5270163432Sariff HDA_QUIRK_EAPDINV) 5271163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 5272162922Sariff hdac_command(sc, 5273162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 5274163432Sariff val), cad); 5275162922Sariff 5276163276Sariff } 5277162922Sariff DELAY(1000); 5278162922Sariff } 5279162922Sariff} 5280162922Sariff 5281162922Sariffstatic void 5282162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 5283162922Sariff{ 5284162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5285162922Sariff struct hdac_audio_ctl *ctl; 5286162922Sariff int i; 5287162922Sariff 5288162922Sariff devinfo->function.audio.mvol = 100 | (100 << 8); 5289162922Sariff i = 0; 5290162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5291162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) { 5292163057Sariff HDA_BOOTVERBOSE( 5293162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 5294162922Sariff i, (ctl->widget != NULL) ? 5295162922Sariff ctl->widget->nid : -1); 5296162922Sariff if (ctl->childwidget != NULL) 5297162922Sariff printf(" childnid=%d", 5298162922Sariff ctl->childwidget->nid); 5299162922Sariff if (ctl->widget == NULL) 5300162922Sariff printf(" NULL WIDGET!"); 5301162922Sariff printf(" DISABLED\n"); 5302162922Sariff ); 5303162922Sariff continue; 5304162922Sariff } 5305163057Sariff HDA_BOOTVERBOSE( 5306162922Sariff if (ctl->ossmask == 0) { 5307162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 5308162922Sariff i, ctl->widget->nid); 5309162922Sariff if (ctl->childwidget != NULL) 5310162922Sariff printf(" childnid=%d", 5311162922Sariff ctl->childwidget->nid); 5312162922Sariff printf(" Bind to NONE\n"); 5313166294Sariff } 5314162922Sariff ); 5315162922Sariff if (ctl->step > 0) { 5316162922Sariff ctl->ossval = (ctl->left * 100) / ctl->step; 5317162922Sariff ctl->ossval |= ((ctl->right * 100) / ctl->step) << 8; 5318162922Sariff } else 5319162922Sariff ctl->ossval = 0; 5320162922Sariff hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT, 5321162922Sariff ctl->left, ctl->right); 5322162922Sariff } 5323162922Sariff} 5324162922Sariff 5325162922Sariffstatic int 5326162922Sariffhdac_pcmchannel_setup(struct hdac_devinfo *devinfo, int dir) 5327162922Sariff{ 5328162922Sariff struct hdac_chan *ch; 5329162922Sariff struct hdac_widget *w; 5330162922Sariff uint32_t cap, fmtcap, pcmcap, path; 5331162922Sariff int i, type, ret, max; 5332162922Sariff 5333162922Sariff if (dir == PCMDIR_PLAY) { 5334162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT; 5335162922Sariff ch = &devinfo->codec->sc->play; 5336162922Sariff path = HDA_DAC_PATH; 5337162922Sariff } else { 5338162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT; 5339162922Sariff ch = &devinfo->codec->sc->rec; 5340162922Sariff path = HDA_ADC_PATH; 5341162922Sariff } 5342162922Sariff 5343162922Sariff ch->caps = hdac_caps; 5344162922Sariff ch->caps.fmtlist = ch->fmtlist; 5345162922Sariff ch->bit16 = 1; 5346162922Sariff ch->bit32 = 0; 5347162922Sariff ch->pcmrates[0] = 48000; 5348162922Sariff ch->pcmrates[1] = 0; 5349162922Sariff 5350162922Sariff ret = 0; 5351162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 5352162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 5353162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 5354162922Sariff 5355162922Sariff for (i = devinfo->startnode; i < devinfo->endnode && ret < max; i++) { 5356162922Sariff w = hdac_widget_get(devinfo, i); 5357162922Sariff if (w == NULL || w->enable == 0 || w->type != type || 5358163057Sariff !(w->pflags & path)) 5359162922Sariff continue; 5360162922Sariff cap = w->param.widget_cap; 5361162922Sariff /*if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(cap)) 5362162922Sariff continue;*/ 5363162922Sariff if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(cap)) 5364162922Sariff continue; 5365162922Sariff cap = w->param.supp_stream_formats; 5366162922Sariff /*if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) { 5367162922Sariff } 5368162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 5369162922Sariff }*/ 5370162922Sariff if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 5371162922Sariff continue; 5372164614Sariff if (ret == 0) { 5373164614Sariff fmtcap = w->param.supp_stream_formats; 5374164614Sariff pcmcap = w->param.supp_pcm_size_rate; 5375164614Sariff } else { 5376164614Sariff fmtcap &= w->param.supp_stream_formats; 5377164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 5378164614Sariff } 5379162922Sariff ch->io[ret++] = i; 5380162922Sariff } 5381162922Sariff ch->io[ret] = -1; 5382162922Sariff 5383162922Sariff ch->supp_stream_formats = fmtcap; 5384162922Sariff ch->supp_pcm_size_rate = pcmcap; 5385162922Sariff 5386162922Sariff /* 5387162922Sariff * 8bit = 0 5388162922Sariff * 16bit = 1 5389162922Sariff * 20bit = 2 5390162922Sariff * 24bit = 3 5391162922Sariff * 32bit = 4 5392162922Sariff */ 5393162922Sariff if (ret > 0) { 5394162922Sariff cap = pcmcap; 5395162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 5396162922Sariff ch->bit16 = 1; 5397162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 5398162922Sariff ch->bit16 = 0; 5399162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 5400162922Sariff ch->bit32 = 4; 5401162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 5402162922Sariff ch->bit32 = 3; 5403162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 5404162922Sariff ch->bit32 = 2; 5405162922Sariff i = 0; 5406162922Sariff if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 5407162922Sariff ch->fmtlist[i++] = AFMT_S16_LE; 5408162922Sariff ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 5409162922Sariff if (ch->bit32 > 0) { 5410162922Sariff if (!(devinfo->function.audio.quirks & 5411162922Sariff HDA_QUIRK_FORCESTEREO)) 5412162922Sariff ch->fmtlist[i++] = AFMT_S32_LE; 5413162922Sariff ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 5414162922Sariff } 5415162922Sariff ch->fmtlist[i] = 0; 5416162922Sariff i = 0; 5417162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 5418162922Sariff ch->pcmrates[i++] = 8000; 5419162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 5420162922Sariff ch->pcmrates[i++] = 11025; 5421162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 5422162922Sariff ch->pcmrates[i++] = 16000; 5423162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 5424162922Sariff ch->pcmrates[i++] = 22050; 5425162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 5426162922Sariff ch->pcmrates[i++] = 32000; 5427162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 5428162922Sariff ch->pcmrates[i++] = 44100; 5429162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(cap)) */ 5430162922Sariff ch->pcmrates[i++] = 48000; 5431162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 5432162922Sariff ch->pcmrates[i++] = 88200; 5433162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 5434162922Sariff ch->pcmrates[i++] = 96000; 5435162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 5436162922Sariff ch->pcmrates[i++] = 176400; 5437162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 5438162922Sariff ch->pcmrates[i++] = 192000; 5439162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(cap)) */ 5440162922Sariff ch->pcmrates[i] = 0; 5441162922Sariff if (i > 0) { 5442162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 5443162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 5444162922Sariff } 5445162922Sariff } 5446162922Sariff 5447162922Sariff return (ret); 5448162922Sariff} 5449162922Sariff 5450162922Sariffstatic void 5451162922Sariffhdac_dump_ctls(struct hdac_devinfo *devinfo, const char *banner, uint32_t flag) 5452162922Sariff{ 5453162922Sariff struct hdac_audio_ctl *ctl; 5454162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5455162922Sariff int i; 5456162922Sariff uint32_t fl = 0; 5457162922Sariff 5458162922Sariff 5459162922Sariff if (flag == 0) { 5460162922Sariff fl = SOUND_MASK_VOLUME | SOUND_MASK_PCM | 5461162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 5462162922Sariff SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN; 5463162922Sariff } 5464162922Sariff 5465162922Sariff i = 0; 5466162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5467162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 5468169277Sariff ctl->widget->enable == 0 || (ctl->ossmask & 5469169277Sariff (SOUND_MASK_SKIP | SOUND_MASK_DISABLE))) 5470162922Sariff continue; 5471162922Sariff if ((flag == 0 && (ctl->ossmask & ~fl)) || 5472162922Sariff (flag != 0 && (ctl->ossmask & flag))) { 5473162922Sariff if (banner != NULL) { 5474162922Sariff device_printf(sc->dev, "\n"); 5475162922Sariff device_printf(sc->dev, "%s\n", banner); 5476162922Sariff } 5477162922Sariff goto hdac_ctl_dump_it_all; 5478162922Sariff } 5479162922Sariff } 5480162922Sariff 5481162922Sariff return; 5482162922Sariff 5483162922Sariffhdac_ctl_dump_it_all: 5484162922Sariff i = 0; 5485162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5486162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 5487162922Sariff ctl->widget->enable == 0) 5488162922Sariff continue; 5489162922Sariff if (!((flag == 0 && (ctl->ossmask & ~fl)) || 5490162922Sariff (flag != 0 && (ctl->ossmask & flag)))) 5491162922Sariff continue; 5492162922Sariff if (flag == 0) { 5493162922Sariff device_printf(sc->dev, "\n"); 5494162922Sariff device_printf(sc->dev, "Unknown Ctl (OSS: %s)\n", 5495162922Sariff hdac_audio_ctl_ossmixer_mask2name(ctl->ossmask)); 5496162922Sariff } 5497162922Sariff device_printf(sc->dev, " |\n"); 5498162922Sariff device_printf(sc->dev, " +- nid: %2d index: %2d ", 5499162922Sariff ctl->widget->nid, ctl->index); 5500162922Sariff if (ctl->childwidget != NULL) 5501162922Sariff printf("(nid: %2d) ", ctl->childwidget->nid); 5502162922Sariff else 5503162922Sariff printf(" "); 5504162922Sariff printf("mute: %d step: %3d size: %3d off: %3d dir=0x%x ossmask=0x%08x\n", 5505162922Sariff ctl->mute, ctl->step, ctl->size, ctl->offset, ctl->dir, 5506162922Sariff ctl->ossmask); 5507162922Sariff } 5508162922Sariff} 5509162922Sariff 5510162922Sariffstatic void 5511162922Sariffhdac_dump_audio_formats(struct hdac_softc *sc, uint32_t fcap, uint32_t pcmcap) 5512162922Sariff{ 5513162922Sariff uint32_t cap; 5514162922Sariff 5515162922Sariff cap = fcap; 5516162922Sariff if (cap != 0) { 5517162922Sariff device_printf(sc->dev, " Stream cap: 0x%08x\n", cap); 5518162922Sariff device_printf(sc->dev, " Format:"); 5519162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 5520162922Sariff printf(" AC3"); 5521162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 5522162922Sariff printf(" FLOAT32"); 5523162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 5524162922Sariff printf(" PCM"); 5525162922Sariff printf("\n"); 5526162922Sariff } 5527162922Sariff cap = pcmcap; 5528162922Sariff if (cap != 0) { 5529162922Sariff device_printf(sc->dev, " PCM cap: 0x%08x\n", cap); 5530162922Sariff device_printf(sc->dev, " PCM size:"); 5531162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 5532162922Sariff printf(" 8"); 5533162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 5534162922Sariff printf(" 16"); 5535162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 5536162922Sariff printf(" 20"); 5537162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 5538162922Sariff printf(" 24"); 5539162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 5540162922Sariff printf(" 32"); 5541162922Sariff printf("\n"); 5542162922Sariff device_printf(sc->dev, " PCM rate:"); 5543162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 5544162922Sariff printf(" 8"); 5545162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 5546162922Sariff printf(" 11"); 5547162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 5548162922Sariff printf(" 16"); 5549162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 5550162922Sariff printf(" 22"); 5551162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 5552162922Sariff printf(" 32"); 5553162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 5554162922Sariff printf(" 44"); 5555162922Sariff printf(" 48"); 5556162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 5557162922Sariff printf(" 88"); 5558162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 5559162922Sariff printf(" 96"); 5560162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 5561162922Sariff printf(" 176"); 5562162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 5563162922Sariff printf(" 192"); 5564162922Sariff printf("\n"); 5565162922Sariff } 5566162922Sariff} 5567162922Sariff 5568162922Sariffstatic void 5569162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 5570162922Sariff{ 5571162922Sariff uint32_t pincap, wcap; 5572162922Sariff 5573162922Sariff pincap = w->wclass.pin.cap; 5574162922Sariff wcap = w->param.widget_cap; 5575162922Sariff 5576162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 5577162922Sariff device_printf(sc->dev, " "); 5578162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 5579162922Sariff printf(" ISC"); 5580162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 5581162922Sariff printf(" TRQD"); 5582162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 5583162922Sariff printf(" PDC"); 5584162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 5585162922Sariff printf(" HP"); 5586162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 5587162922Sariff printf(" OUT"); 5588162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 5589162922Sariff printf(" IN"); 5590162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 5591162922Sariff printf(" BAL"); 5592165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) { 5593165069Sariff printf(" VREF["); 5594165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap)) 5595165069Sariff printf(" 50"); 5596165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap)) 5597165069Sariff printf(" 80"); 5598165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap)) 5599165069Sariff printf(" 100"); 5600165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap)) 5601165069Sariff printf(" GROUND"); 5602165069Sariff if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap)) 5603165069Sariff printf(" HIZ"); 5604165069Sariff printf(" ]"); 5605165069Sariff } 5606162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 5607162922Sariff printf(" EAPD"); 5608162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(wcap)) 5609162922Sariff printf(" : UNSOL"); 5610162922Sariff printf("\n"); 5611162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 5612162922Sariff w->wclass.pin.config); 5613162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 5614162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 5615162922Sariff printf(" HP"); 5616162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 5617162922Sariff printf(" IN"); 5618162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 5619162922Sariff printf(" OUT"); 5620162922Sariff printf("\n"); 5621162922Sariff} 5622162922Sariff 5623162922Sariffstatic void 5624162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 5625162922Sariff{ 5626163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 5627162922Sariff device_printf(sc->dev, " " 5628162922Sariff "mute=%d step=%d size=%d offset=%d\n", 5629162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 5630162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 5631162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 5632162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 5633162922Sariff} 5634162922Sariff 5635162922Sariffstatic void 5636162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 5637162922Sariff{ 5638162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5639162922Sariff struct hdac_widget *w, *cw; 5640162922Sariff int i, j; 5641162922Sariff 5642162922Sariff device_printf(sc->dev, "\n"); 5643162922Sariff device_printf(sc->dev, "Default Parameter\n"); 5644162922Sariff device_printf(sc->dev, "-----------------\n"); 5645162922Sariff hdac_dump_audio_formats(sc, 5646162922Sariff devinfo->function.audio.supp_stream_formats, 5647162922Sariff devinfo->function.audio.supp_pcm_size_rate); 5648162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 5649162922Sariff devinfo->function.audio.inamp_cap); 5650162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 5651162922Sariff devinfo->function.audio.outamp_cap); 5652162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5653162922Sariff w = hdac_widget_get(devinfo, i); 5654162922Sariff if (w == NULL) { 5655162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 5656162922Sariff continue; 5657162922Sariff } 5658162922Sariff device_printf(sc->dev, "\n"); 5659162922Sariff device_printf(sc->dev, " nid: %d [%s]%s\n", w->nid, 5660162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) ? 5661162922Sariff "DIGITAL" : "ANALOG", 5662162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 5663162922Sariff device_printf(sc->dev, " name: %s\n", w->name); 5664162922Sariff device_printf(sc->dev, " widget_cap: 0x%08x\n", 5665162922Sariff w->param.widget_cap); 5666162922Sariff device_printf(sc->dev, " Parse flags: 0x%08x\n", 5667162922Sariff w->pflags); 5668162922Sariff device_printf(sc->dev, " Ctl flags: 0x%08x\n", 5669162922Sariff w->ctlflags); 5670162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 5671162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 5672162922Sariff hdac_dump_audio_formats(sc, 5673162922Sariff w->param.supp_stream_formats, 5674162922Sariff w->param.supp_pcm_size_rate); 5675162922Sariff } else if (w->type == 5676162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5677162922Sariff hdac_dump_pin(sc, w); 5678162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 5679162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 5680162922Sariff w->param.eapdbtl); 5681163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 5682163057Sariff w->param.outamp_cap != 0) 5683162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 5684163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 5685163057Sariff w->param.inamp_cap != 0) 5686162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 5687162922Sariff device_printf(sc->dev, " connections: %d\n", w->nconns); 5688162922Sariff for (j = 0; j < w->nconns; j++) { 5689162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 5690162922Sariff device_printf(sc->dev, " |\n"); 5691162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 5692162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 5693162922Sariff if (cw == NULL) 5694162922Sariff printf(" [UNKNOWN]"); 5695162922Sariff else if (cw->enable == 0) 5696162922Sariff printf(" [DISABLED]"); 5697162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 5698162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 5699162922Sariff printf(" (selected)"); 5700162922Sariff printf("\n"); 5701162922Sariff } 5702162922Sariff } 5703162922Sariff 5704162922Sariff} 5705162922Sariff 5706163057Sariffstatic int 5707163057Sariffhdac_dump_dac_internal(struct hdac_devinfo *devinfo, nid_t nid, int depth) 5708163057Sariff{ 5709163057Sariff struct hdac_widget *w, *cw; 5710163057Sariff struct hdac_softc *sc = devinfo->codec->sc; 5711163057Sariff int i; 5712163057Sariff 5713163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 5714163057Sariff return (0); 5715163057Sariff 5716163057Sariff w = hdac_widget_get(devinfo, nid); 5717163057Sariff if (w == NULL || w->enable == 0 || !(w->pflags & HDA_DAC_PATH)) 5718163057Sariff return (0); 5719163057Sariff 5720163057Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 5721163057Sariff device_printf(sc->dev, "\n"); 5722163057Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 5723163057Sariff device_printf(sc->dev, " ^\n"); 5724163057Sariff device_printf(sc->dev, " |\n"); 5725163057Sariff device_printf(sc->dev, " +-----<------+\n"); 5726163057Sariff } else { 5727163057Sariff device_printf(sc->dev, " ^\n"); 5728163057Sariff device_printf(sc->dev, " |\n"); 5729163057Sariff device_printf(sc->dev, " "); 5730163057Sariff printf(" nid=%d [%s]\n", w->nid, w->name); 5731163057Sariff } 5732163057Sariff 5733163057Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) { 5734163057Sariff return (1); 5735163057Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 5736163057Sariff for (i = 0; i < w->nconns; i++) { 5737163057Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 5738163057Sariff if (cw == NULL || cw->enable == 0 || cw->type == 5739163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 5740163057Sariff continue; 5741163057Sariff if (hdac_dump_dac_internal(devinfo, cw->nid, 5742163057Sariff depth + 1) != 0) 5743163057Sariff return (1); 5744163057Sariff } 5745163057Sariff } else if ((w->type == 5746163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR || 5747163057Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 5748163057Sariff w->selconn > -1 && w->selconn < w->nconns) { 5749163057Sariff if (hdac_dump_dac_internal(devinfo, w->conns[w->selconn], 5750163057Sariff depth + 1) != 0) 5751163057Sariff return (1); 5752163057Sariff } 5753163057Sariff 5754163057Sariff return (0); 5755163057Sariff} 5756163057Sariff 5757162922Sariffstatic void 5758162922Sariffhdac_dump_dac(struct hdac_devinfo *devinfo) 5759162922Sariff{ 5760163057Sariff struct hdac_widget *w; 5761163057Sariff struct hdac_softc *sc = devinfo->codec->sc; 5762163057Sariff int i, printed = 0; 5763163057Sariff 5764163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5765163057Sariff w = hdac_widget_get(devinfo, i); 5766163057Sariff if (w == NULL || w->enable == 0) 5767163057Sariff continue; 5768163057Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 5769163057Sariff !(w->pflags & HDA_DAC_PATH)) 5770163057Sariff continue; 5771163057Sariff if (printed == 0) { 5772163057Sariff printed = 1; 5773163057Sariff device_printf(sc->dev, "\n"); 5774163057Sariff device_printf(sc->dev, "Playback path:\n"); 5775163057Sariff } 5776163057Sariff hdac_dump_dac_internal(devinfo, w->nid, 0); 5777163057Sariff } 5778162922Sariff} 5779162922Sariff 5780162922Sariffstatic void 5781162922Sariffhdac_dump_adc(struct hdac_devinfo *devinfo) 5782162922Sariff{ 5783162922Sariff struct hdac_widget *w, *cw; 5784162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 5785162922Sariff int i, j; 5786162922Sariff int printed = 0; 5787162922Sariff char ossdevs[256]; 5788162922Sariff 5789162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5790162922Sariff w = hdac_widget_get(devinfo, i); 5791162922Sariff if (w == NULL || w->enable == 0) 5792162922Sariff continue; 5793162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 5794162922Sariff continue; 5795162922Sariff if (printed == 0) { 5796162922Sariff printed = 1; 5797162922Sariff device_printf(sc->dev, "\n"); 5798162922Sariff device_printf(sc->dev, "Recording sources:\n"); 5799162922Sariff } 5800162922Sariff device_printf(sc->dev, "\n"); 5801162922Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 5802162922Sariff for (j = 0; j < w->nconns; j++) { 5803162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 5804162922Sariff if (cw == NULL || cw->enable == 0) 5805162922Sariff continue; 5806162922Sariff hdac_audio_ctl_ossmixer_mask2allname(cw->ctlflags, 5807162922Sariff ossdevs, sizeof(ossdevs)); 5808162922Sariff device_printf(sc->dev, " |\n"); 5809162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 5810162922Sariff cw->nid, cw->name); 5811162922Sariff if (strlen(ossdevs) > 0) { 5812162922Sariff printf(" [recsrc: %s]", ossdevs); 5813162922Sariff } 5814162922Sariff printf("\n"); 5815162922Sariff } 5816162922Sariff } 5817162922Sariff} 5818162922Sariff 5819162922Sariffstatic void 5820162922Sariffhdac_dump_pcmchannels(struct hdac_softc *sc, int pcnt, int rcnt) 5821162922Sariff{ 5822162922Sariff nid_t *nids; 5823162922Sariff 5824162922Sariff if (pcnt > 0) { 5825162922Sariff device_printf(sc->dev, "\n"); 5826162922Sariff device_printf(sc->dev, " PCM Playback: %d\n", pcnt); 5827162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 5828162922Sariff sc->play.supp_pcm_size_rate); 5829162922Sariff device_printf(sc->dev, " DAC:"); 5830162922Sariff for (nids = sc->play.io; *nids != -1; nids++) 5831162922Sariff printf(" %d", *nids); 5832162922Sariff printf("\n"); 5833162922Sariff } 5834162922Sariff 5835162922Sariff if (rcnt > 0) { 5836162922Sariff device_printf(sc->dev, "\n"); 5837162922Sariff device_printf(sc->dev, " PCM Record: %d\n", rcnt); 5838162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 5839162922Sariff sc->rec.supp_pcm_size_rate); 5840162922Sariff device_printf(sc->dev, " ADC:"); 5841162922Sariff for (nids = sc->rec.io; *nids != -1; nids++) 5842162922Sariff printf(" %d", *nids); 5843162922Sariff printf("\n"); 5844162922Sariff } 5845162922Sariff} 5846162922Sariff 5847162922Sariffstatic void 5848163057Sariffhdac_release_resources(struct hdac_softc *sc) 5849163057Sariff{ 5850163057Sariff struct hdac_devinfo *devinfo = NULL; 5851163057Sariff device_t *devlist = NULL; 5852163057Sariff int i, devcount; 5853163057Sariff 5854163057Sariff if (sc == NULL) 5855163057Sariff return; 5856163057Sariff 5857163057Sariff hdac_lock(sc); 5858169277Sariff sc->polling = 0; 5859169277Sariff sc->poll_ival = 0; 5860170721Sariff callout_stop(&sc->poll_hda); 5861169277Sariff callout_stop(&sc->poll_hdac); 5862169277Sariff callout_stop(&sc->poll_jack); 5863163057Sariff hdac_reset(sc); 5864163057Sariff hdac_unlock(sc); 5865171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 5866170721Sariff callout_drain(&sc->poll_hda); 5867169277Sariff callout_drain(&sc->poll_hdac); 5868169277Sariff callout_drain(&sc->poll_jack); 5869163057Sariff 5870169277Sariff hdac_irq_free(sc); 5871169277Sariff 5872163057Sariff device_get_children(sc->dev, &devlist, &devcount); 5873163057Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 5874163057Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 5875163057Sariff if (devinfo == NULL) 5876163057Sariff continue; 5877163057Sariff if (devinfo->widget != NULL) 5878163057Sariff free(devinfo->widget, M_HDAC); 5879163057Sariff if (devinfo->node_type == 5880163057Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 5881163057Sariff devinfo->function.audio.ctl != NULL) 5882163057Sariff free(devinfo->function.audio.ctl, M_HDAC); 5883163057Sariff free(devinfo, M_HDAC); 5884163057Sariff device_delete_child(sc->dev, devlist[i]); 5885163057Sariff } 5886163057Sariff if (devlist != NULL) 5887163057Sariff free(devlist, M_TEMP); 5888163057Sariff 5889163057Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) { 5890163057Sariff if (sc->codecs[i] != NULL) 5891163057Sariff free(sc->codecs[i], M_HDAC); 5892163057Sariff sc->codecs[i] = NULL; 5893163057Sariff } 5894163057Sariff 5895169277Sariff hdac_dma_free(sc, &sc->pos_dma); 5896169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 5897169277Sariff hdac_dma_free(sc, &sc->corb_dma); 5898163057Sariff if (sc->play.blkcnt > 0) 5899169277Sariff hdac_dma_free(sc, &sc->play.bdl_dma); 5900163057Sariff if (sc->rec.blkcnt > 0) 5901169277Sariff hdac_dma_free(sc, &sc->rec.bdl_dma); 5902167702Sariff if (sc->chan_dmat != NULL) { 5903167702Sariff bus_dma_tag_destroy(sc->chan_dmat); 5904167702Sariff sc->chan_dmat = NULL; 5905167702Sariff } 5906163057Sariff hdac_mem_free(sc); 5907169277Sariff snd_mtxfree(sc->lock); 5908163057Sariff free(sc, M_DEVBUF); 5909163057Sariff} 5910163057Sariff 5911163057Sariff/* This function surely going to make its way into upper level someday. */ 5912163057Sariffstatic void 5913163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 5914163057Sariff{ 5915163057Sariff const char *res = NULL; 5916163057Sariff int i = 0, j, k, len, inv; 5917163057Sariff 5918163057Sariff if (on != NULL) 5919163057Sariff *on = 0; 5920163057Sariff if (off != NULL) 5921163057Sariff *off = 0; 5922163057Sariff if (sc == NULL) 5923163057Sariff return; 5924163057Sariff if (resource_string_value(device_get_name(sc->dev), 5925163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 5926163057Sariff return; 5927163057Sariff if (!(res != NULL && strlen(res) > 0)) 5928163057Sariff return; 5929163057Sariff HDA_BOOTVERBOSE( 5930163057Sariff device_printf(sc->dev, "HDA_DEBUG: HDA Config:"); 5931163057Sariff ); 5932163057Sariff for (;;) { 5933163057Sariff while (res[i] != '\0' && 5934163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 5935163057Sariff i++; 5936163057Sariff if (res[i] == '\0') { 5937163057Sariff HDA_BOOTVERBOSE( 5938163057Sariff printf("\n"); 5939163057Sariff ); 5940163057Sariff return; 5941163057Sariff } 5942163057Sariff j = i; 5943163057Sariff while (res[j] != '\0' && 5944163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 5945163057Sariff j++; 5946163057Sariff len = j - i; 5947163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 5948163057Sariff inv = 2; 5949163057Sariff else 5950163057Sariff inv = 0; 5951163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 5952163057Sariff if (strncmp(res + i + inv, 5953163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 5954163057Sariff continue; 5955163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 5956163057Sariff break; 5957163057Sariff HDA_BOOTVERBOSE( 5958163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 5959163057Sariff hdac_quirks_tab[k].key); 5960163057Sariff ); 5961163057Sariff if (inv == 0 && on != NULL) 5962163057Sariff *on |= hdac_quirks_tab[k].value; 5963163057Sariff else if (inv != 0 && off != NULL) 5964163057Sariff *off |= hdac_quirks_tab[k].value; 5965163057Sariff break; 5966163057Sariff } 5967163057Sariff i = j; 5968163057Sariff } 5969163057Sariff} 5970163057Sariff 5971164614Sariff#ifdef SND_DYNSYSCTL 5972164614Sariffstatic int 5973164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 5974164614Sariff{ 5975164614Sariff struct hdac_softc *sc; 5976164614Sariff struct hdac_devinfo *devinfo; 5977164614Sariff device_t dev; 5978164614Sariff uint32_t ctl; 5979164614Sariff int err, val; 5980164614Sariff 5981164614Sariff dev = oidp->oid_arg1; 5982164614Sariff devinfo = pcm_getdevinfo(dev); 5983164614Sariff if (devinfo == NULL || devinfo->codec == NULL || 5984164614Sariff devinfo->codec->sc == NULL) 5985164614Sariff return (EINVAL); 5986164614Sariff sc = devinfo->codec->sc; 5987164614Sariff hdac_lock(sc); 5988164614Sariff val = sc->polling; 5989164614Sariff hdac_unlock(sc); 5990170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 5991164614Sariff 5992169277Sariff if (err != 0 || req->newptr == NULL) 5993164614Sariff return (err); 5994164614Sariff if (val < 0 || val > 1) 5995164614Sariff return (EINVAL); 5996164614Sariff 5997164614Sariff hdac_lock(sc); 5998164614Sariff if (val != sc->polling) { 5999164614Sariff if (hda_chan_active(sc) != 0) 6000164614Sariff err = EBUSY; 6001164614Sariff else if (val == 0) { 6002164614Sariff callout_stop(&sc->poll_hdac); 6003169277Sariff hdac_unlock(sc); 6004169277Sariff callout_drain(&sc->poll_hdac); 6005169277Sariff hdac_lock(sc); 6006164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 6007164614Sariff sc->rirb_size / 2); 6008164614Sariff ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 6009164614Sariff ctl |= HDAC_RIRBCTL_RINTCTL; 6010164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl); 6011164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 6012164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 6013164614Sariff sc->polling = 0; 6014164614Sariff DELAY(1000); 6015164614Sariff } else { 6016164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 0); 6017164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 0); 6018164614Sariff ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 6019164614Sariff ctl &= ~HDAC_RIRBCTL_RINTCTL; 6020164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl); 6021171141Sariff hdac_unlock(sc); 6022171141Sariff taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 6023171141Sariff hdac_lock(sc); 6024164614Sariff callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, 6025164614Sariff sc); 6026164614Sariff sc->polling = 1; 6027164614Sariff DELAY(1000); 6028164614Sariff } 6029164614Sariff } 6030164614Sariff hdac_unlock(sc); 6031164614Sariff 6032164614Sariff return (err); 6033164614Sariff} 6034169277Sariff 6035169277Sariffstatic int 6036169277Sariffsysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS) 6037169277Sariff{ 6038169277Sariff struct hdac_softc *sc; 6039169277Sariff struct hdac_devinfo *devinfo; 6040169277Sariff device_t dev; 6041169277Sariff int err, val; 6042169277Sariff 6043169277Sariff dev = oidp->oid_arg1; 6044169277Sariff devinfo = pcm_getdevinfo(dev); 6045169277Sariff if (devinfo == NULL || devinfo->codec == NULL || 6046169277Sariff devinfo->codec->sc == NULL) 6047169277Sariff return (EINVAL); 6048169277Sariff sc = devinfo->codec->sc; 6049169277Sariff hdac_lock(sc); 6050169277Sariff val = ((uint64_t)sc->poll_ival * 1000) / hz; 6051169277Sariff hdac_unlock(sc); 6052170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6053169277Sariff 6054169277Sariff if (err != 0 || req->newptr == NULL) 6055169277Sariff return (err); 6056169277Sariff 6057169277Sariff if (val < 1) 6058169277Sariff val = 1; 6059169277Sariff if (val > 5000) 6060169277Sariff val = 5000; 6061169277Sariff val = ((uint64_t)val * hz) / 1000; 6062169277Sariff if (val < 1) 6063169277Sariff val = 1; 6064169277Sariff if (val > (hz * 5)) 6065169277Sariff val = hz * 5; 6066169277Sariff 6067169277Sariff hdac_lock(sc); 6068169277Sariff sc->poll_ival = val; 6069169277Sariff hdac_unlock(sc); 6070169277Sariff 6071169277Sariff return (err); 6072169277Sariff} 6073169277Sariff 6074169277Sariff#ifdef SND_DEBUG 6075169277Sariffstatic int 6076171141Sariffsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 6077169277Sariff{ 6078169277Sariff struct hdac_softc *sc; 6079169277Sariff struct hdac_devinfo *devinfo; 6080169277Sariff struct hdac_widget *w; 6081169277Sariff device_t dev; 6082171141Sariff uint32_t res, pincap, timeout; 6083169277Sariff int i, err, val; 6084169277Sariff nid_t cad; 6085169277Sariff 6086169277Sariff dev = oidp->oid_arg1; 6087169277Sariff devinfo = pcm_getdevinfo(dev); 6088169277Sariff if (devinfo == NULL || devinfo->codec == NULL || 6089169277Sariff devinfo->codec->sc == NULL) 6090169277Sariff return (EINVAL); 6091169277Sariff val = 0; 6092170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 6093169277Sariff if (err != 0 || req->newptr == NULL || val == 0) 6094169277Sariff return (err); 6095169277Sariff sc = devinfo->codec->sc; 6096169277Sariff cad = devinfo->codec->cad; 6097169277Sariff hdac_lock(sc); 6098169277Sariff device_printf(dev, "HDAC Dump AFG [nid=%d]:\n", devinfo->nid); 6099169277Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6100169277Sariff w = hdac_widget_get(devinfo, i); 6101169277Sariff if (w == NULL || w->type != 6102169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 6103169277Sariff continue; 6104171141Sariff pincap = w->wclass.pin.cap; 6105171141Sariff if ((HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) || 6106171141Sariff HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) && 6107171141Sariff HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) { 6108171141Sariff timeout = 10000; 6109171141Sariff hdac_command(sc, 6110171141Sariff HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad); 6111171141Sariff do { 6112171141Sariff res = hdac_command(sc, 6113171141Sariff HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad); 6114171141Sariff if (res != 0x7fffffff) 6115171141Sariff break; 6116171141Sariff DELAY(10); 6117171141Sariff } while (--timeout != 0); 6118171141Sariff } else { 6119171141Sariff timeout = -1; 6120171141Sariff res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad, 6121171141Sariff w->nid), cad); 6122171141Sariff } 6123171141Sariff device_printf(dev, 6124171141Sariff "PIN_SENSE: nid=%-3d timeout=%d res=0x%08x [%s]\n", 6125171141Sariff w->nid, timeout, res, 6126169277Sariff (w->enable == 0) ? "DISABLED" : "ENABLED"); 6127169277Sariff } 6128169277Sariff device_printf(dev, 6129169277Sariff "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n", 6130169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio), 6131169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio), 6132169277Sariff HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio), 6133169277Sariff HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio), 6134169277Sariff HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio)); 6135171141Sariff if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) { 6136169277Sariff device_printf(dev, " GPI:"); 6137169277Sariff res = hdac_command(sc, 6138169277Sariff HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad); 6139169277Sariff printf(" data=0x%08x", res); 6140169277Sariff res = hdac_command(sc, 6141169277Sariff HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid), 6142169277Sariff cad); 6143169277Sariff printf(" wake=0x%08x", res); 6144169277Sariff res = hdac_command(sc, 6145169277Sariff HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 6146169277Sariff cad); 6147169277Sariff printf(" unsol=0x%08x", res); 6148169277Sariff res = hdac_command(sc, 6149169277Sariff HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad); 6150169277Sariff printf(" sticky=0x%08x\n", res); 6151169277Sariff } 6152171141Sariff if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) { 6153169277Sariff device_printf(dev, " GPO:"); 6154169277Sariff res = hdac_command(sc, 6155169277Sariff HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad); 6156169277Sariff printf(" data=0x%08x\n", res); 6157169277Sariff } 6158171141Sariff if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) { 6159169277Sariff device_printf(dev, "GPI0:"); 6160169277Sariff res = hdac_command(sc, 6161169277Sariff HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad); 6162169277Sariff printf(" data=0x%08x", res); 6163169277Sariff res = hdac_command(sc, 6164169277Sariff HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad); 6165169277Sariff printf(" enable=0x%08x", res); 6166169277Sariff res = hdac_command(sc, 6167169277Sariff HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad); 6168169277Sariff printf(" direction=0x%08x\n", res); 6169169277Sariff res = hdac_command(sc, 6170169277Sariff HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad); 6171169277Sariff device_printf(dev, " wake=0x%08x", res); 6172169277Sariff res = hdac_command(sc, 6173169277Sariff HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid), 6174169277Sariff cad); 6175169277Sariff printf(" unsol=0x%08x", res); 6176169277Sariff res = hdac_command(sc, 6177169277Sariff HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad); 6178169277Sariff printf(" sticky=0x%08x\n", res); 6179169277Sariff } 6180169277Sariff hdac_unlock(sc); 6181169277Sariff return (0); 6182169277Sariff} 6183164614Sariff#endif 6184169277Sariff#endif 6185164614Sariff 6186163057Sariffstatic void 6187162922Sariffhdac_attach2(void *arg) 6188162922Sariff{ 6189162922Sariff struct hdac_softc *sc; 6190162922Sariff struct hdac_widget *w; 6191162922Sariff struct hdac_audio_ctl *ctl; 6192163057Sariff uint32_t quirks_on, quirks_off; 6193172811Sariff int pcnt, rcnt, codec_index; 6194162922Sariff int i; 6195162922Sariff char status[SND_STATUSLEN]; 6196162965Sariff device_t *devlist = NULL; 6197162922Sariff int devcount; 6198162922Sariff struct hdac_devinfo *devinfo = NULL; 6199162922Sariff 6200162922Sariff sc = (struct hdac_softc *)arg; 6201162922Sariff 6202163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 6203162922Sariff 6204163057Sariff HDA_BOOTVERBOSE( 6205163057Sariff device_printf(sc->dev, "HDA_DEBUG: HDA Config: on=0x%08x off=0x%08x\n", 6206163057Sariff quirks_on, quirks_off); 6207163057Sariff ); 6208163057Sariff 6209172811Sariff if (resource_int_value(device_get_name(sc->dev), 6210172811Sariff device_get_unit(sc->dev), "codec_index", &codec_index) != 0) { 6211172811Sariff switch (sc->pci_subvendor) { 6212172811Sariff case GB_G33S2H_SUBVENDOR: 6213172811Sariff codec_index = 2; 6214172811Sariff break; 6215172811Sariff default: 6216172811Sariff codec_index = 0; 6217172811Sariff break; 6218172811Sariff } 6219172811Sariff } 6220172811Sariff 6221162922Sariff hdac_lock(sc); 6222162922Sariff 6223162922Sariff /* Remove ourselves from the config hooks */ 6224162922Sariff if (sc->intrhook.ich_func != NULL) { 6225162922Sariff config_intrhook_disestablish(&sc->intrhook); 6226162922Sariff sc->intrhook.ich_func = NULL; 6227162922Sariff } 6228162922Sariff 6229162922Sariff /* Start the corb and rirb engines */ 6230163057Sariff HDA_BOOTVERBOSE( 6231162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting CORB Engine...\n"); 6232162922Sariff ); 6233162922Sariff hdac_corb_start(sc); 6234163057Sariff HDA_BOOTVERBOSE( 6235162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting RIRB Engine...\n"); 6236162922Sariff ); 6237162922Sariff hdac_rirb_start(sc); 6238162922Sariff 6239163057Sariff HDA_BOOTVERBOSE( 6240162922Sariff device_printf(sc->dev, 6241162922Sariff "HDA_DEBUG: Enabling controller interrupt...\n"); 6242162922Sariff ); 6243164614Sariff if (sc->polling == 0) 6244164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 6245164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 6246163057Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 6247163057Sariff HDAC_GCTL_UNSOL); 6248162922Sariff 6249162922Sariff DELAY(1000); 6250162922Sariff 6251163057Sariff HDA_BOOTVERBOSE( 6252172811Sariff device_printf(sc->dev, 6253172811Sariff "HDA_DEBUG: Scanning HDA codecs [start index=%d] ...\n", 6254172811Sariff codec_index); 6255162922Sariff ); 6256172811Sariff hdac_scan_codecs(sc, codec_index); 6257162922Sariff 6258162922Sariff device_get_children(sc->dev, &devlist, &devcount); 6259162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 6260162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 6261162965Sariff if (devinfo != NULL && devinfo->node_type == 6262162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 6263162965Sariff break; 6264162965Sariff } else 6265162965Sariff devinfo = NULL; 6266162922Sariff } 6267162965Sariff if (devlist != NULL) 6268162965Sariff free(devlist, M_TEMP); 6269162922Sariff 6270162922Sariff if (devinfo == NULL) { 6271162922Sariff hdac_unlock(sc); 6272162922Sariff device_printf(sc->dev, "Audio Function Group not found!\n"); 6273163057Sariff hdac_release_resources(sc); 6274162922Sariff return; 6275162922Sariff } 6276162922Sariff 6277163057Sariff HDA_BOOTVERBOSE( 6278162922Sariff device_printf(sc->dev, 6279162922Sariff "HDA_DEBUG: Parsing AFG nid=%d cad=%d\n", 6280162922Sariff devinfo->nid, devinfo->codec->cad); 6281162922Sariff ); 6282162922Sariff hdac_audio_parse(devinfo); 6283163057Sariff HDA_BOOTVERBOSE( 6284162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing Ctls...\n"); 6285162922Sariff ); 6286162922Sariff hdac_audio_ctl_parse(devinfo); 6287163057Sariff HDA_BOOTVERBOSE( 6288162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing vendor patch...\n"); 6289162922Sariff ); 6290162922Sariff hdac_vendor_patch_parse(devinfo); 6291163057Sariff if (quirks_on != 0) 6292163057Sariff devinfo->function.audio.quirks |= quirks_on; 6293163057Sariff if (quirks_off != 0) 6294163057Sariff devinfo->function.audio.quirks &= ~quirks_off; 6295162922Sariff 6296162922Sariff /* XXX Disable all DIGITAL path. */ 6297162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 6298162922Sariff w = hdac_widget_get(devinfo, i); 6299162922Sariff if (w == NULL) 6300162922Sariff continue; 6301162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 6302162922Sariff w->enable = 0; 6303162922Sariff continue; 6304162922Sariff } 6305162922Sariff /* XXX Disable useless pin ? */ 6306162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 6307162922Sariff (w->wclass.pin.config & 6308162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 6309162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 6310162922Sariff w->enable = 0; 6311162922Sariff } 6312162922Sariff i = 0; 6313162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6314162922Sariff if (ctl->widget == NULL) 6315162922Sariff continue; 6316169277Sariff if (ctl->ossmask & SOUND_MASK_DISABLE) 6317169277Sariff ctl->enable = 0; 6318162922Sariff w = ctl->widget; 6319169277Sariff if (w->enable == 0 || 6320169277Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6321162922Sariff ctl->enable = 0; 6322162922Sariff w = ctl->childwidget; 6323162922Sariff if (w == NULL) 6324162922Sariff continue; 6325162922Sariff if (w->enable == 0 || 6326162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 6327162922Sariff ctl->enable = 0; 6328162922Sariff } 6329162922Sariff 6330163057Sariff HDA_BOOTVERBOSE( 6331162922Sariff device_printf(sc->dev, "HDA_DEBUG: Building AFG tree...\n"); 6332162922Sariff ); 6333162922Sariff hdac_audio_build_tree(devinfo); 6334162922Sariff 6335169277Sariff i = 0; 6336169277Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6337169277Sariff if (ctl->ossmask & (SOUND_MASK_SKIP | SOUND_MASK_DISABLE)) 6338169277Sariff ctl->ossmask = 0; 6339169277Sariff } 6340163057Sariff HDA_BOOTVERBOSE( 6341162922Sariff device_printf(sc->dev, "HDA_DEBUG: AFG commit...\n"); 6342162922Sariff ); 6343162922Sariff hdac_audio_commit(devinfo, HDA_COMMIT_ALL); 6344163057Sariff HDA_BOOTVERBOSE( 6345162922Sariff device_printf(sc->dev, "HDA_DEBUG: Ctls commit...\n"); 6346162922Sariff ); 6347162922Sariff hdac_audio_ctl_commit(devinfo); 6348162922Sariff 6349163057Sariff HDA_BOOTVERBOSE( 6350162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_PLAY setup...\n"); 6351162922Sariff ); 6352162922Sariff pcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_PLAY); 6353163057Sariff HDA_BOOTVERBOSE( 6354162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_REC setup...\n"); 6355162922Sariff ); 6356162922Sariff rcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_REC); 6357162922Sariff 6358162922Sariff hdac_unlock(sc); 6359163057Sariff HDA_BOOTVERBOSE( 6360162922Sariff device_printf(sc->dev, 6361162922Sariff "HDA_DEBUG: OSS mixer initialization...\n"); 6362162922Sariff ); 6363163057Sariff 6364163057Sariff /* 6365163057Sariff * There is no point of return after this. If the driver failed, 6366163057Sariff * so be it. Let the detach procedure do all the cleanup. 6367163057Sariff */ 6368163057Sariff if (mixer_init(sc->dev, &hdac_audio_ctl_ossmixer_class, devinfo) != 0) 6369162922Sariff device_printf(sc->dev, "Can't register mixer\n"); 6370162922Sariff 6371162922Sariff if (pcnt > 0) 6372162922Sariff pcnt = 1; 6373162922Sariff if (rcnt > 0) 6374162922Sariff rcnt = 1; 6375162922Sariff 6376163057Sariff HDA_BOOTVERBOSE( 6377162922Sariff device_printf(sc->dev, 6378162922Sariff "HDA_DEBUG: Registering PCM channels...\n"); 6379162922Sariff ); 6380163057Sariff if (pcm_register(sc->dev, devinfo, pcnt, rcnt) != 0) 6381162922Sariff device_printf(sc->dev, "Can't register PCM\n"); 6382162922Sariff 6383162922Sariff sc->registered++; 6384162922Sariff 6385169277Sariff if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) && 6386169277Sariff hdac_dma_alloc(sc, &sc->pos_dma, 6387169277Sariff (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) { 6388169277Sariff HDA_BOOTVERBOSE( 6389169277Sariff device_printf(sc->dev, 6390169277Sariff "Failed to allocate DMA pos buffer (non-fatal)\n"); 6391169277Sariff ); 6392169277Sariff } 6393169277Sariff 6394162922Sariff for (i = 0; i < pcnt; i++) 6395162922Sariff pcm_addchan(sc->dev, PCMDIR_PLAY, &hdac_channel_class, devinfo); 6396162922Sariff for (i = 0; i < rcnt; i++) 6397162922Sariff pcm_addchan(sc->dev, PCMDIR_REC, &hdac_channel_class, devinfo); 6398162922Sariff 6399164614Sariff#ifdef SND_DYNSYSCTL 6400164614Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 6401164614Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 6402164614Sariff "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 6403164614Sariff sysctl_hdac_polling, "I", "Enable polling mode"); 6404169277Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 6405169277Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 6406169277Sariff "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev, 6407169277Sariff sizeof(sc->dev), sysctl_hdac_polling_interval, "I", 6408169277Sariff "Controller/Jack Sense polling interval (1-1000 ms)"); 6409169277Sariff#ifdef SND_DEBUG 6410169277Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 6411169277Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 6412171141Sariff "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 6413171141Sariff sysctl_hdac_pindump, "I", "Dump pin states/data"); 6414164614Sariff#endif 6415169277Sariff#endif 6416164614Sariff 6417162922Sariff snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s [%s]", 6418164614Sariff rman_get_start(sc->mem.mem_res), rman_get_start(sc->irq.irq_res), 6419164614Sariff PCM_KLDSTRING(snd_hda), HDA_DRV_TEST_REV); 6420162922Sariff pcm_setstatus(sc->dev, status); 6421162922Sariff device_printf(sc->dev, "<HDA Codec: %s>\n", hdac_codec_name(devinfo)); 6422163057Sariff HDA_BOOTVERBOSE( 6423163057Sariff device_printf(sc->dev, "<HDA Codec ID: 0x%08x>\n", 6424163057Sariff hdac_codec_id(devinfo)); 6425163057Sariff ); 6426164614Sariff device_printf(sc->dev, "<HDA Driver Revision: %s>\n", 6427164614Sariff HDA_DRV_TEST_REV); 6428162922Sariff 6429163057Sariff HDA_BOOTVERBOSE( 6430162922Sariff if (devinfo->function.audio.quirks != 0) { 6431162922Sariff device_printf(sc->dev, "\n"); 6432163057Sariff device_printf(sc->dev, "HDA config/quirks:"); 6433163057Sariff for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 6434169277Sariff if ((devinfo->function.audio.quirks & 6435169277Sariff hdac_quirks_tab[i].value) == 6436163057Sariff hdac_quirks_tab[i].value) 6437163057Sariff printf(" %s", hdac_quirks_tab[i].key); 6438163057Sariff } 6439162922Sariff printf("\n"); 6440162922Sariff } 6441162922Sariff device_printf(sc->dev, "\n"); 6442162922Sariff device_printf(sc->dev, "+-------------------+\n"); 6443162922Sariff device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 6444162922Sariff device_printf(sc->dev, "+-------------------+\n"); 6445162922Sariff hdac_dump_nodes(devinfo); 6446162922Sariff device_printf(sc->dev, "\n"); 6447162922Sariff device_printf(sc->dev, "+------------------------+\n"); 6448162922Sariff device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 6449162922Sariff device_printf(sc->dev, "+------------------------+\n"); 6450162922Sariff device_printf(sc->dev, "\n"); 6451162922Sariff i = 0; 6452162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 6453162922Sariff device_printf(sc->dev, "%3d: nid=%d", i, 6454162922Sariff (ctl->widget != NULL) ? ctl->widget->nid : -1); 6455162922Sariff if (ctl->childwidget != NULL) 6456162922Sariff printf(" cnid=%d", ctl->childwidget->nid); 6457162922Sariff printf(" dir=0x%x index=%d " 6458162922Sariff "ossmask=0x%08x ossdev=%d%s\n", 6459162922Sariff ctl->dir, ctl->index, 6460162922Sariff ctl->ossmask, ctl->ossdev, 6461162922Sariff (ctl->enable == 0) ? " [DISABLED]" : ""); 6462162922Sariff } 6463162922Sariff device_printf(sc->dev, "\n"); 6464162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 6465162922Sariff device_printf(sc->dev, "| DUMPING HDA AUDIO/VOLUME CONTROLS |\n"); 6466162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 6467162922Sariff hdac_dump_ctls(devinfo, "Master Volume (OSS: vol)", SOUND_MASK_VOLUME); 6468162922Sariff hdac_dump_ctls(devinfo, "PCM Volume (OSS: pcm)", SOUND_MASK_PCM); 6469162922Sariff hdac_dump_ctls(devinfo, "CD Volume (OSS: cd)", SOUND_MASK_CD); 6470162922Sariff hdac_dump_ctls(devinfo, "Microphone Volume (OSS: mic)", SOUND_MASK_MIC); 6471162922Sariff hdac_dump_ctls(devinfo, "Line-in Volume (OSS: line)", SOUND_MASK_LINE); 6472162922Sariff hdac_dump_ctls(devinfo, "Recording Level (OSS: rec)", SOUND_MASK_RECLEV); 6473162922Sariff hdac_dump_ctls(devinfo, "Speaker/Beep (OSS: speaker)", SOUND_MASK_SPEAKER); 6474162922Sariff hdac_dump_ctls(devinfo, NULL, 0); 6475162922Sariff hdac_dump_dac(devinfo); 6476162922Sariff hdac_dump_adc(devinfo); 6477162922Sariff device_printf(sc->dev, "\n"); 6478162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 6479162922Sariff device_printf(sc->dev, "| DUMPING PCM Playback/Record Channels |\n"); 6480162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 6481162922Sariff hdac_dump_pcmchannels(sc, pcnt, rcnt); 6482162922Sariff ); 6483164614Sariff 6484164614Sariff if (sc->polling != 0) { 6485164614Sariff hdac_lock(sc); 6486164614Sariff callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 6487164614Sariff hdac_unlock(sc); 6488164614Sariff } 6489162922Sariff} 6490162922Sariff 6491162922Sariff/**************************************************************************** 6492162922Sariff * int hdac_detach(device_t) 6493162922Sariff * 6494162922Sariff * Detach and free up resources utilized by the hdac device. 6495162922Sariff ****************************************************************************/ 6496162922Sariffstatic int 6497162922Sariffhdac_detach(device_t dev) 6498162922Sariff{ 6499162922Sariff struct hdac_softc *sc = NULL; 6500162922Sariff struct hdac_devinfo *devinfo = NULL; 6501163057Sariff int err; 6502162922Sariff 6503162922Sariff devinfo = (struct hdac_devinfo *)pcm_getdevinfo(dev); 6504162922Sariff if (devinfo != NULL && devinfo->codec != NULL) 6505162922Sariff sc = devinfo->codec->sc; 6506162922Sariff if (sc == NULL) 6507163057Sariff return (0); 6508162922Sariff 6509162922Sariff if (sc->registered > 0) { 6510163057Sariff err = pcm_unregister(dev); 6511163057Sariff if (err != 0) 6512163057Sariff return (err); 6513162922Sariff } 6514162922Sariff 6515163057Sariff hdac_release_resources(sc); 6516162922Sariff 6517162922Sariff return (0); 6518162922Sariff} 6519162922Sariff 6520162922Sariffstatic device_method_t hdac_methods[] = { 6521162922Sariff /* device interface */ 6522162922Sariff DEVMETHOD(device_probe, hdac_probe), 6523162922Sariff DEVMETHOD(device_attach, hdac_attach), 6524162922Sariff DEVMETHOD(device_detach, hdac_detach), 6525162922Sariff { 0, 0 } 6526162922Sariff}; 6527162922Sariff 6528162922Sariffstatic driver_t hdac_driver = { 6529162922Sariff "pcm", 6530162922Sariff hdac_methods, 6531162922Sariff PCM_SOFTC_SIZE, 6532162922Sariff}; 6533162922Sariff 6534162922SariffDRIVER_MODULE(snd_hda, pci, hdac_driver, pcm_devclass, 0, 0); 6535162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 6536162922SariffMODULE_VERSION(snd_hda, 1); 6537