hdac.c revision 164828
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 70163057Sariff#include <sys/ctype.h> 71163057Sariff 72162922Sariff#include <dev/sound/pcm/sound.h> 73162922Sariff#include <dev/pci/pcireg.h> 74162922Sariff#include <dev/pci/pcivar.h> 75162922Sariff 76162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 77162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 78162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 79162922Sariff#include <dev/sound/pci/hda/hdac.h> 80162922Sariff 81162922Sariff#include "mixer_if.h" 82162922Sariff 83164828Sariff#define HDA_DRV_TEST_REV "20061203_0035" 84162922Sariff#define HDA_WIDGET_PARSER_REV 1 85162922Sariff 86162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 164828 2006-12-02 17:12:24Z ariff $"); 87162922Sariff 88162922Sariff#undef HDA_DEBUG_ENABLED 89162922Sariff#define HDA_DEBUG_ENABLED 1 90162922Sariff 91162922Sariff#ifdef HDA_DEBUG_ENABLED 92163057Sariff#define HDA_DEBUG(stmt) do { \ 93163057Sariff stmt \ 94162922Sariff} while(0) 95162922Sariff#else 96163057Sariff#define HDA_DEBUG(stmt) 97162922Sariff#endif 98162922Sariff 99163057Sariff#define HDA_BOOTVERBOSE(stmt) do { \ 100162922Sariff if (bootverbose) { \ 101162922Sariff stmt \ 102162922Sariff } \ 103162922Sariff} while(0) 104162922Sariff 105162965Sariff#if 1 106162922Sariff#undef HDAC_INTR_EXTRA 107162922Sariff#define HDAC_INTR_EXTRA 1 108162922Sariff#endif 109162922Sariff 110162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 111162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 112163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 113163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 114162922Sariff 115162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 116163257Sariff#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \ 117163257Sariff (fl) == 0xffffffff || \ 118163257Sariff (((fl) & 0xffff0000) == 0xffff0000 && \ 119163257Sariff ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ 120163257Sariff (((fl) & 0x0000ffff) == 0x0000ffff && \ 121163257Sariff ((fl) & 0xffff0000) == ((v) & 0xffff0000))) 122162965Sariff#define HDA_MATCH_ALL 0xffffffff 123162965Sariff#define HDAC_INVALID 0xffffffff 124162965Sariff 125162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 126162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 127162922Sariff 128162922Sariff/* Controller models */ 129162922Sariff 130162922Sariff/* Intel */ 131162922Sariff#define INTEL_VENDORID 0x8086 132162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 133162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 134163136Sariff#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b) 135163136Sariff#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) 136162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 137162922Sariff 138162922Sariff/* Nvidia */ 139162922Sariff#define NVIDIA_VENDORID 0x10de 140162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 141162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 142163136Sariff#define HDA_NVIDIA_MCP61A HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4) 143163136Sariff#define HDA_NVIDIA_MCP61B HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0) 144163136Sariff#define HDA_NVIDIA_MCP65A HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a) 145163136Sariff#define HDA_NVIDIA_MCP65B HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b) 146162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 147162922Sariff 148162922Sariff/* ATI */ 149162922Sariff#define ATI_VENDORID 0x1002 150162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 151163136Sariff#define HDA_ATI_SB600 HDA_MODEL_CONSTRUCT(ATI, 0x4383) 152162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 153162922Sariff 154163136Sariff/* VIA */ 155163136Sariff#define VIA_VENDORID 0x1106 156163136Sariff#define HDA_VIA_VT82XX HDA_MODEL_CONSTRUCT(VIA, 0x3288) 157163136Sariff#define HDA_VIA_ALL HDA_MODEL_CONSTRUCT(VIA, 0xffff) 158163136Sariff 159163136Sariff/* SiS */ 160163136Sariff#define SIS_VENDORID 0x1039 161163136Sariff#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502) 162163136Sariff#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff) 163163136Sariff 164162922Sariff/* OEM/subvendors */ 165162922Sariff 166162922Sariff/* HP/Compaq */ 167162922Sariff#define HP_VENDORID 0x103c 168162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 169162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 170162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 171162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 172162922Sariff 173162922Sariff/* Dell */ 174162922Sariff#define DELL_VENDORID 0x1028 175162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 176162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 177162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 178162922Sariff 179162922Sariff/* Clevo */ 180162922Sariff#define CLEVO_VENDORID 0x1558 181162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 182162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 183162922Sariff 184162922Sariff/* Acer */ 185162922Sariff#define ACER_VENDORID 0x1025 186162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 187162922Sariff 188162965Sariff/* Asus */ 189162965Sariff#define ASUS_VENDORID 0x1043 190162965Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 191163276Sariff#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263) 192163432Sariff#define ASUS_A8JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153) 193162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 194162922Sariff 195163257Sariff/* IBM / Lenovo */ 196163257Sariff#define IBM_VENDORID 0x1014 197163257Sariff#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6) 198163257Sariff#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff) 199162965Sariff 200164614Sariff/* Lenovo */ 201164657Sariff#define LENOVO_VENDORID 0x17aa 202164657Sariff#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066) 203164657Sariff#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff) 204163257Sariff 205164657Sariff/* Samsung */ 206164657Sariff#define SAMSUNG_VENDORID 0x144d 207164657Sariff#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027) 208164657Sariff#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff) 209164614Sariff 210164750Sariff/* Medion ? */ 211164750Sariff#define MEDION_VENDORID 0x161f 212164750Sariff#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d) 213164750Sariff#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff) 214164750Sariff 215164828Sariff/* 216164828Sariff * Apple Intel MacXXXX seems using Sigmatel codec/vendor id 217164828Sariff * instead of their own, which is beyond my comprehension 218164828Sariff * (see HDA_CODEC_STAC9221 below). 219164828Sariff */ 220164828Sariff#define APPLE_INTEL_MAC 0x76808384 221164828Sariff 222162922Sariff/* Misc constants.. */ 223162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 224162922Sariff#define HDA_AMP_MUTE_NONE (0) 225162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 226162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 227162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 228162922Sariff 229162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 230162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 231162922Sariff 232162922Sariff#define HDA_DAC_PATH (1 << 0) 233162922Sariff#define HDA_ADC_PATH (1 << 1) 234162922Sariff#define HDA_ADC_RECSEL (1 << 2) 235162922Sariff 236163057Sariff#define HDA_CTL_OUT (1 << 0) 237163057Sariff#define HDA_CTL_IN (1 << 1) 238162922Sariff#define HDA_CTL_BOTH (HDA_CTL_IN | HDA_CTL_OUT) 239162922Sariff 240163057Sariff#define HDA_GPIO_MAX 15 241163057Sariff/* 0 - 14 = GPIO */ 242163057Sariff#define HDA_QUIRK_GPIO0 (1 << 0) 243163057Sariff#define HDA_QUIRK_GPIO1 (1 << 1) 244163057Sariff#define HDA_QUIRK_GPIO2 (1 << 2) 245163057Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 15) 246163057Sariff#define HDA_QUIRK_FIXEDRATE (1 << 16) 247163057Sariff#define HDA_QUIRK_FORCESTEREO (1 << 17) 248163276Sariff#define HDA_QUIRK_EAPDINV (1 << 18) 249162922Sariff 250163057Sariffstatic const struct { 251163057Sariff char *key; 252163057Sariff uint32_t value; 253163057Sariff} hdac_quirks_tab[] = { 254163057Sariff { "gpio0", HDA_QUIRK_GPIO0 }, 255163057Sariff { "gpio1", HDA_QUIRK_GPIO1 }, 256163057Sariff { "gpio2", HDA_QUIRK_GPIO2 }, 257163057Sariff { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, 258163057Sariff { "fixedrate", HDA_QUIRK_FIXEDRATE }, 259163136Sariff { "forcestereo", HDA_QUIRK_FORCESTEREO }, 260163276Sariff { "eapdinv", HDA_QUIRK_EAPDINV }, 261163057Sariff}; 262163057Sariff#define HDAC_QUIRKS_TAB_LEN \ 263163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 264163057Sariff 265162922Sariff#define HDA_BDL_MIN 2 266162922Sariff#define HDA_BDL_MAX 256 267162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 268162922Sariff 269162922Sariff#define HDA_BUFSZ_MIN 4096 270162922Sariff#define HDA_BUFSZ_MAX 65536 271162922Sariff#define HDA_BUFSZ_DEFAULT 16384 272162922Sariff 273162922Sariff#define HDA_PARSE_MAXDEPTH 10 274162922Sariff 275162922Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 276162922Sariff 277162922Sariffstatic MALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 278162922Sariff 279162922Sariffenum { 280162922Sariff HDA_PARSE_MIXER, 281162922Sariff HDA_PARSE_DIRECT 282162922Sariff}; 283162922Sariff 284162922Sariff/* Default */ 285162922Sariffstatic uint32_t hdac_fmt[] = { 286162922Sariff AFMT_STEREO | AFMT_S16_LE, 287162922Sariff 0 288162922Sariff}; 289162922Sariff 290162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 291162922Sariff 292162922Sariffstatic const struct { 293162922Sariff uint32_t model; 294162922Sariff char *desc; 295162922Sariff} hdac_devices[] = { 296162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 297162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 298163136Sariff { HDA_INTEL_82801H, "Intel 82801H" }, 299163136Sariff { HDA_INTEL_63XXESB, "Intel 631x/632xESB" }, 300162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 301162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 302163136Sariff { HDA_NVIDIA_MCP61A, "NVidia MCP61A" }, 303163136Sariff { HDA_NVIDIA_MCP61B, "NVidia MCP61B" }, 304163136Sariff { HDA_NVIDIA_MCP65A, "NVidia MCP65A" }, 305163136Sariff { HDA_NVIDIA_MCP65B, "NVidia MCP65B" }, 306162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 307163136Sariff { HDA_ATI_SB600, "ATI SB600" }, 308163136Sariff { HDA_VIA_VT82XX, "VIA VT8251/8237A" }, 309163136Sariff { HDA_SIS_966, "SiS 966" }, 310162922Sariff /* Unknown */ 311162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 312162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 313162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 314163136Sariff { HDA_VIA_ALL, "VIA (Unknown)" }, 315163136Sariff { HDA_SIS_ALL, "SiS (Unknown)" }, 316162922Sariff}; 317162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 318162922Sariff 319162922Sariffstatic const struct { 320162922Sariff uint32_t rate; 321162922Sariff int valid; 322162922Sariff uint16_t base; 323162922Sariff uint16_t mul; 324162922Sariff uint16_t div; 325162922Sariff} hda_rate_tab[] = { 326162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 327162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 328162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 329162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 330162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 331162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 332162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 333162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 334162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 335162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 336162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 337162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 338162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 339162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 340162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 341162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 342162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 343162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 344162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 345162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 346162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 347162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 348162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 349162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 350162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 351162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 352162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 353162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 354162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 355162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 356162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 357162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 358162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 359162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 360162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 361162922Sariff}; 362162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 363162922Sariff 364162922Sariff/* All codecs you can eat... */ 365162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 366162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 367162922Sariff 368162922Sariff/* Realtek */ 369162922Sariff#define REALTEK_VENDORID 0x10ec 370162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 371162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 372162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 373163057Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) 374163057Sariff#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) 375162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 376162922Sariff 377162922Sariff/* Analog Device */ 378162922Sariff#define ANALOGDEVICE_VENDORID 0x11d4 379162922Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1981) 380162922Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1983) 381162922Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1986) 382162922Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0xffff) 383162922Sariff 384162922Sariff/* CMedia */ 385162922Sariff#define CMEDIA_VENDORID 0x434d 386162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 387162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 388162922Sariff 389162922Sariff/* Sigmatel */ 390162922Sariff#define SIGMATEL_VENDORID 0x8384 391162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 392162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 393162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 394162922Sariff#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 395162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 396162922Sariff 397162922Sariff/* 398162922Sariff * Conexant 399162922Sariff * 400162922Sariff * Ok, the truth is, I don't have any idea at all whether 401162922Sariff * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only 402162922Sariff * place that tell me it is "Venice" is from its Windows driver INF. 403163057Sariff * 404163057Sariff * Venice - CX????? 405163057Sariff * Waikiki - CX20551-22 406162922Sariff */ 407162922Sariff#define CONEXANT_VENDORID 0x14f1 408162922Sariff#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 409163057Sariff#define HDA_CODEC_CXWAIKIKI HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) 410162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 411162922Sariff 412162922Sariff 413162922Sariff/* Codecs */ 414162922Sariffstatic const struct { 415162922Sariff uint32_t id; 416162922Sariff char *name; 417162922Sariff} hdac_codecs[] = { 418162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 419162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 420162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 421162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 422163057Sariff { HDA_CODEC_ALC883, "Realtek ALC883" }, 423162922Sariff { HDA_CODEC_AD1981HD, "Analog Device AD1981HD" }, 424162922Sariff { HDA_CODEC_AD1983, "Analog Device AD1983" }, 425162922Sariff { HDA_CODEC_AD1986A, "Analog Device AD1986A" }, 426162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 427162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 428162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 429162922Sariff { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 430162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 431162922Sariff { HDA_CODEC_CXVENICE, "Conexant Venice" }, 432163057Sariff { HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" }, 433162922Sariff /* Unknown codec */ 434162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 435162922Sariff { HDA_CODEC_ADXXXX, "Analog Device (Unknown)" }, 436162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 437162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 438162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 439162922Sariff}; 440162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 441162922Sariff 442162922Sariffenum { 443162922Sariff HDAC_HP_SWITCH_CTL, 444162922Sariff HDAC_HP_SWITCH_CTRL 445162922Sariff}; 446162922Sariff 447162922Sariffstatic const struct { 448162965Sariff uint32_t model; 449162922Sariff uint32_t id; 450162922Sariff int type; 451162922Sariff nid_t hpnid; 452162922Sariff nid_t spkrnid[8]; 453162922Sariff nid_t eapdnid; 454162922Sariff} hdac_hp_switch[] = { 455162922Sariff /* Specific OEM models */ 456162922Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 457162922Sariff 17, { 16, -1 }, 16 }, 458162922Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 459162922Sariff 6, { 5, -1 }, 5 }, 460162922Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 461162922Sariff 6, { 5, -1 }, 5 }, 462162922Sariff { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 463162922Sariff 13, { 14, -1 }, -1 }, 464162922Sariff { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 465162922Sariff 13, { 14, -1 }, -1 }, 466164828Sariff { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL, 467164828Sariff 10, { 13, -1 }, -1 }, 468162922Sariff /* 469162922Sariff * All models that at least come from the same vendor with 470162922Sariff * simmilar codec. 471162922Sariff */ 472162922Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 473162922Sariff 17, { 16, -1 }, 16 }, 474162922Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 475162922Sariff 6, { 5, -1 }, 5 }, 476162922Sariff { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 477162922Sariff 13, { 14, -1 }, -1 }, 478162922Sariff}; 479162922Sariff#define HDAC_HP_SWITCH_LEN \ 480162922Sariff (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0])) 481162922Sariff 482162922Sariffstatic const struct { 483162965Sariff uint32_t model; 484162922Sariff uint32_t id; 485162922Sariff nid_t eapdnid; 486162922Sariff int hp_switch; 487162922Sariff} hdac_eapd_switch[] = { 488162922Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, 16, 1 }, 489162922Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 490162922Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 491162922Sariff}; 492162922Sariff#define HDAC_EAPD_SWITCH_LEN \ 493162922Sariff (sizeof(hdac_eapd_switch) / sizeof(hdac_eapd_switch[0])) 494162922Sariff 495162922Sariff/**************************************************************************** 496162922Sariff * Function prototypes 497162922Sariff ****************************************************************************/ 498162922Sariffstatic void hdac_intr_handler(void *); 499162922Sariffstatic int hdac_reset(struct hdac_softc *); 500162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 501162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 502162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 503162922Sariff struct hdac_dma *, bus_size_t); 504162922Sariffstatic void hdac_dma_free(struct hdac_dma *); 505162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 506162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 507162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 508162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 509162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 510162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 511162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 512162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 513162922Sariffstatic void hdac_scan_codecs(struct hdac_softc *); 514162922Sariffstatic int hdac_probe_codec(struct hdac_codec *); 515162922Sariffstatic struct hdac_devinfo *hdac_probe_function(struct hdac_codec *, nid_t); 516162922Sariffstatic void hdac_add_child(struct hdac_softc *, struct hdac_devinfo *); 517162922Sariff 518162922Sariffstatic void hdac_attach2(void *); 519162922Sariff 520162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 521162922Sariff uint32_t, int); 522162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 523162922Sariff struct hdac_command_list *, int); 524162922Sariff 525162922Sariffstatic int hdac_probe(device_t); 526162922Sariffstatic int hdac_attach(device_t); 527162922Sariffstatic int hdac_detach(device_t); 528162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 529162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 530162922Sariff uint32_t, int, int); 531162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 532162922Sariff nid_t, int, int); 533162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 534162922Sariff nid_t, nid_t, int, int, int, int, int, int); 535162922Sariffstatic int hdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *); 536162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 537162922Sariff 538164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 539164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 540164614Sariff 541162922Sariff#define hdac_command(a1, a2, a3) \ 542162922Sariff hdac_command_sendone_internal(a1, a2, a3) 543162922Sariff 544162922Sariff#define hdac_codec_id(d) \ 545162922Sariff ((uint32_t)((d == NULL) ? 0x00000000 : \ 546162922Sariff ((((uint32_t)(d)->vendor_id & 0x0000ffff) << 16) | \ 547162922Sariff ((uint32_t)(d)->device_id & 0x0000ffff)))) 548162922Sariff 549162922Sariffstatic char * 550162922Sariffhdac_codec_name(struct hdac_devinfo *devinfo) 551162922Sariff{ 552162922Sariff uint32_t id; 553162922Sariff int i; 554162922Sariff 555162922Sariff id = hdac_codec_id(devinfo); 556162922Sariff 557162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 558163257Sariff if (HDA_DEV_MATCH(hdac_codecs[i].id, id)) 559162922Sariff return (hdac_codecs[i].name); 560162922Sariff } 561162922Sariff 562162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 563162922Sariff} 564162922Sariff 565162922Sariffstatic char * 566162922Sariffhdac_audio_ctl_ossmixer_mask2name(uint32_t devmask) 567162922Sariff{ 568162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 569162922Sariff static char *unknown = "???"; 570162922Sariff int i; 571162922Sariff 572162922Sariff for (i = SOUND_MIXER_NRDEVICES - 1; i >= 0; i--) { 573162922Sariff if (devmask & (1 << i)) 574162922Sariff return (ossname[i]); 575162922Sariff } 576162922Sariff return (unknown); 577162922Sariff} 578162922Sariff 579162922Sariffstatic void 580162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 581162922Sariff{ 582162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 583162922Sariff int i, first = 1; 584162922Sariff 585162922Sariff bzero(buf, len); 586162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 587162922Sariff if (mask & (1 << i)) { 588162922Sariff if (first == 0) 589162922Sariff strlcat(buf, ", ", len); 590162922Sariff strlcat(buf, ossname[i], len); 591162922Sariff first = 0; 592162922Sariff } 593162922Sariff } 594162922Sariff} 595162922Sariff 596162922Sariffstatic struct hdac_audio_ctl * 597162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 598162922Sariff{ 599162922Sariff if (devinfo == NULL || 600162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 601162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 602162922Sariff devinfo->function.audio.ctlcnt < 1 || 603162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 604162922Sariff return (NULL); 605162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 606162922Sariff} 607162922Sariff 608162922Sariffstatic struct hdac_audio_ctl * 609162922Sariffhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, 610162922Sariff int index, int cnt) 611162922Sariff{ 612162922Sariff struct hdac_audio_ctl *ctl, *retctl = NULL; 613162922Sariff int i, at, atindex, found = 0; 614162922Sariff 615162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 616162922Sariff return (NULL); 617162922Sariff 618162922Sariff at = cnt; 619162922Sariff if (at == 0) 620162922Sariff at = 1; 621162922Sariff else if (at < 0) 622162922Sariff at = -1; 623162922Sariff atindex = index; 624162922Sariff if (atindex < 0) 625162922Sariff atindex = -1; 626162922Sariff 627162922Sariff i = 0; 628162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 629162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 630162922Sariff continue; 631162922Sariff if (!(ctl->widget->nid == nid && (atindex == -1 || 632162922Sariff ctl->index == atindex))) 633162922Sariff continue; 634162922Sariff found++; 635162922Sariff if (found == cnt) 636162922Sariff return (ctl); 637162922Sariff retctl = ctl; 638162922Sariff } 639162922Sariff 640162922Sariff return ((at == -1) ? retctl : NULL); 641162922Sariff} 642162922Sariff 643162922Sariffstatic void 644162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 645162922Sariff{ 646162922Sariff struct hdac_softc *sc; 647162922Sariff struct hdac_widget *w; 648162922Sariff struct hdac_audio_ctl *ctl; 649162922Sariff uint32_t id, res; 650162922Sariff int i = 0, j, forcemute; 651162922Sariff nid_t cad; 652162922Sariff 653162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 654162922Sariff devinfo->codec->sc == NULL) 655162922Sariff return; 656162922Sariff 657162922Sariff sc = devinfo->codec->sc; 658162922Sariff cad = devinfo->codec->cad; 659162922Sariff id = hdac_codec_id(devinfo); 660162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 661163257Sariff if (HDA_DEV_MATCH(hdac_hp_switch[i].model, 662162965Sariff sc->pci_subvendor) && 663162922Sariff hdac_hp_switch[i].id == id) 664162922Sariff break; 665162922Sariff } 666162922Sariff 667162922Sariff if (i >= HDAC_HP_SWITCH_LEN) 668162922Sariff return; 669162922Sariff 670162922Sariff forcemute = 0; 671162922Sariff if (hdac_hp_switch[i].eapdnid != -1) { 672162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid); 673162965Sariff if (w != NULL && w->param.eapdbtl != HDAC_INVALID) 674162922Sariff forcemute = (w->param.eapdbtl & 675162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1; 676162922Sariff } 677162922Sariff 678162922Sariff res = hdac_command(sc, 679162922Sariff HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad); 680163057Sariff HDA_BOOTVERBOSE( 681162922Sariff device_printf(sc->dev, 682163057Sariff "HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n", 683162922Sariff hdac_hp_switch[i].hpnid, res); 684162922Sariff ); 685162922Sariff res >>= 31; 686162922Sariff 687162922Sariff switch (hdac_hp_switch[i].type) { 688162922Sariff case HDAC_HP_SWITCH_CTL: 689162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 690162922Sariff hdac_hp_switch[i].hpnid, 0, 1); 691162922Sariff if (ctl != NULL) { 692162922Sariff ctl->muted = (res != 0 && forcemute == 0) ? 693162922Sariff HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL; 694162922Sariff hdac_audio_ctl_amp_set(ctl, 695162922Sariff HDA_AMP_MUTE_DEFAULT, ctl->left, 696162922Sariff ctl->right); 697162922Sariff } 698162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 699162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 700162922Sariff hdac_hp_switch[i].spkrnid[j], 0, 1); 701162922Sariff if (ctl != NULL) { 702162922Sariff ctl->muted = (res != 0 || forcemute == 1) ? 703162922Sariff HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE; 704162922Sariff hdac_audio_ctl_amp_set(ctl, 705162922Sariff HDA_AMP_MUTE_DEFAULT, ctl->left, 706162922Sariff ctl->right); 707162922Sariff } 708162922Sariff } 709162922Sariff break; 710162922Sariff case HDAC_HP_SWITCH_CTRL: 711162922Sariff if (res != 0) { 712162922Sariff /* HP in */ 713162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 714163057Sariff if (w != NULL && w->type == 715163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 716162922Sariff if (forcemute == 0) 717162922Sariff w->wclass.pin.ctrl |= 718162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 719162922Sariff else 720162922Sariff w->wclass.pin.ctrl &= 721162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 722162922Sariff hdac_command(sc, 723162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 724162922Sariff w->wclass.pin.ctrl), cad); 725162922Sariff } 726162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 727162922Sariff w = hdac_widget_get(devinfo, 728162922Sariff hdac_hp_switch[i].spkrnid[j]); 729163057Sariff if (w != NULL && w->type == 730163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 731162922Sariff w->wclass.pin.ctrl &= 732162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 733162922Sariff hdac_command(sc, 734162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 735162922Sariff w->nid, 736162922Sariff w->wclass.pin.ctrl), cad); 737162922Sariff } 738162922Sariff } 739162922Sariff } else { 740162922Sariff /* HP out */ 741162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 742163057Sariff if (w != NULL && w->type == 743163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 744162922Sariff w->wclass.pin.ctrl &= 745162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 746162922Sariff hdac_command(sc, 747162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 748162922Sariff w->wclass.pin.ctrl), cad); 749162922Sariff } 750162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 751162922Sariff w = hdac_widget_get(devinfo, 752162922Sariff hdac_hp_switch[i].spkrnid[j]); 753163057Sariff if (w != NULL && w->type == 754163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 755162922Sariff if (forcemute == 0) 756162922Sariff w->wclass.pin.ctrl |= 757162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 758162922Sariff else 759162922Sariff w->wclass.pin.ctrl &= 760162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 761162922Sariff hdac_command(sc, 762162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 763162922Sariff w->nid, 764162922Sariff w->wclass.pin.ctrl), cad); 765162922Sariff } 766162922Sariff } 767162922Sariff } 768162922Sariff break; 769162922Sariff default: 770162922Sariff break; 771162922Sariff } 772162922Sariff} 773162922Sariff 774162922Sariffstatic void 775162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 776162922Sariff{ 777162922Sariff struct hdac_softc *sc; 778162922Sariff struct hdac_devinfo *devinfo = NULL; 779162965Sariff device_t *devlist = NULL; 780162922Sariff int devcount, i; 781162922Sariff 782162922Sariff if (codec == NULL || codec->sc == NULL) 783162922Sariff return; 784162922Sariff 785162922Sariff sc = codec->sc; 786162922Sariff 787163057Sariff HDA_BOOTVERBOSE( 788163057Sariff device_printf(sc->dev, "HDA_DEBUG: Unsol Tag: 0x%08x\n", tag); 789162922Sariff ); 790162922Sariff 791162922Sariff device_get_children(sc->dev, &devlist, &devcount); 792162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 793162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 794162965Sariff if (devinfo != NULL && devinfo->node_type == 795162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 796162965Sariff devinfo->codec != NULL && 797162965Sariff devinfo->codec->cad == codec->cad) { 798162965Sariff break; 799162965Sariff } else 800162965Sariff devinfo = NULL; 801162922Sariff } 802162965Sariff if (devlist != NULL) 803162965Sariff free(devlist, M_TEMP); 804162965Sariff 805162922Sariff if (devinfo == NULL) 806162922Sariff return; 807162922Sariff 808162922Sariff switch (tag) { 809162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 810162922Sariff hdac_hp_switch_handler(devinfo); 811162922Sariff break; 812162922Sariff default: 813162922Sariff break; 814162922Sariff } 815162922Sariff} 816162922Sariff 817164614Sariffstatic int 818162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 819162922Sariff{ 820162922Sariff /* XXX to be removed */ 821162922Sariff#ifdef HDAC_INTR_EXTRA 822162922Sariff uint32_t res; 823162922Sariff#endif 824162922Sariff 825162922Sariff if (ch->blkcnt == 0) 826164614Sariff return (0); 827162922Sariff 828162922Sariff /* XXX to be removed */ 829162922Sariff#ifdef HDAC_INTR_EXTRA 830162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 831162922Sariff#endif 832162922Sariff 833162922Sariff /* XXX to be removed */ 834162922Sariff#ifdef HDAC_INTR_EXTRA 835163057Sariff HDA_BOOTVERBOSE( 836163057Sariff if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE)) 837163057Sariff device_printf(sc->dev, 838163057Sariff "PCMDIR_%s intr triggered beyond stream boundary:" 839163057Sariff "%08x\n", 840163057Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 841163057Sariff ); 842162922Sariff#endif 843162922Sariff 844162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 845163057Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 846162922Sariff 847162922Sariff /* XXX to be removed */ 848162922Sariff#ifdef HDAC_INTR_EXTRA 849162922Sariff if (res & HDAC_SDSTS_BCIS) { 850162922Sariff#endif 851164614Sariff return (1); 852162922Sariff /* XXX to be removed */ 853162922Sariff#ifdef HDAC_INTR_EXTRA 854162922Sariff } 855162922Sariff#endif 856164614Sariff 857164614Sariff return (0); 858162922Sariff} 859162922Sariff 860162922Sariff/**************************************************************************** 861162922Sariff * void hdac_intr_handler(void *) 862162922Sariff * 863162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 864162922Sariff ****************************************************************************/ 865162922Sariffstatic void 866162922Sariffhdac_intr_handler(void *context) 867162922Sariff{ 868162922Sariff struct hdac_softc *sc; 869162922Sariff uint32_t intsts; 870162922Sariff uint8_t rirbsts; 871164614Sariff struct hdac_rirb *rirb_base; 872164614Sariff uint32_t trigger = 0; 873162922Sariff 874162922Sariff sc = (struct hdac_softc *)context; 875162922Sariff 876162922Sariff hdac_lock(sc); 877164614Sariff if (sc->polling != 0) { 878164614Sariff hdac_unlock(sc); 879164614Sariff return; 880164614Sariff } 881162922Sariff /* Do we have anything to do? */ 882162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 883163057Sariff if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) { 884162922Sariff hdac_unlock(sc); 885162922Sariff return; 886162922Sariff } 887162922Sariff 888162922Sariff /* Was this a controller interrupt? */ 889163057Sariff if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) { 890162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 891162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 892162922Sariff /* Get as many responses that we can */ 893163057Sariff while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) { 894164614Sariff HDAC_WRITE_1(&sc->mem, 895164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 896164614Sariff hdac_rirb_flush(sc); 897162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 898162922Sariff } 899162922Sariff /* XXX to be removed */ 900162922Sariff /* Clear interrupt and exit */ 901162922Sariff#ifdef HDAC_INTR_EXTRA 902162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 903162922Sariff#endif 904162922Sariff } 905164614Sariff 906164614Sariff hdac_unsolq_flush(sc); 907164614Sariff 908163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 909164614Sariff if ((intsts & (1 << sc->num_iss)) && 910164614Sariff hdac_stream_intr(sc, &sc->play) != 0) 911164614Sariff trigger |= 1; 912164614Sariff if ((intsts & (1 << 0)) && 913164614Sariff hdac_stream_intr(sc, &sc->rec) != 0) 914164614Sariff trigger |= 2; 915162922Sariff /* XXX to be removed */ 916162922Sariff#ifdef HDAC_INTR_EXTRA 917164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & 918164614Sariff HDAC_INTSTS_SIS_MASK); 919162922Sariff#endif 920162922Sariff } 921162922Sariff 922164614Sariff hdac_unlock(sc); 923162922Sariff 924164614Sariff if (trigger & 1) 925164614Sariff chn_intr(sc->play.c); 926164614Sariff if (trigger & 2) 927164614Sariff chn_intr(sc->rec.c); 928162922Sariff} 929162922Sariff 930162922Sariff/**************************************************************************** 931163057Sariff * int hdac_reset(hdac_softc *) 932162922Sariff * 933162922Sariff * Reset the hdac to a quiescent and known state. 934162922Sariff ****************************************************************************/ 935162922Sariffstatic int 936162922Sariffhdac_reset(struct hdac_softc *sc) 937162922Sariff{ 938162922Sariff uint32_t gctl; 939162922Sariff int count, i; 940162922Sariff 941162922Sariff /* 942162922Sariff * Stop all Streams DMA engine 943162922Sariff */ 944162922Sariff for (i = 0; i < sc->num_iss; i++) 945162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 946162922Sariff for (i = 0; i < sc->num_oss; i++) 947162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 948162922Sariff for (i = 0; i < sc->num_bss; i++) 949162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 950162922Sariff 951162922Sariff /* 952162922Sariff * Stop Control DMA engines 953162922Sariff */ 954162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 955162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 956162922Sariff 957162922Sariff /* 958162922Sariff * Reset the controller. The reset must remain asserted for 959162922Sariff * a minimum of 100us. 960162922Sariff */ 961162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 962162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 963162922Sariff count = 10000; 964162922Sariff do { 965162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 966162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 967162922Sariff break; 968162922Sariff DELAY(10); 969162922Sariff } while (--count); 970162922Sariff if (gctl & HDAC_GCTL_CRST) { 971162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 972162922Sariff return (ENXIO); 973162922Sariff } 974162922Sariff DELAY(100); 975162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 976162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 977162922Sariff count = 10000; 978162922Sariff do { 979162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 980163057Sariff if (gctl & HDAC_GCTL_CRST) 981162922Sariff break; 982162922Sariff DELAY(10); 983162922Sariff } while (--count); 984162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 985162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 986162922Sariff return (ENXIO); 987162922Sariff } 988162922Sariff 989162922Sariff /* 990162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 991162922Sariff * should be of 250us but for some reasons, on it's not enough on my 992162922Sariff * computer. Let's use twice as much as necessary to make sure that 993162922Sariff * it's reset properly. 994162922Sariff */ 995162922Sariff DELAY(1000); 996162922Sariff 997162922Sariff return (0); 998162922Sariff} 999162922Sariff 1000162922Sariff 1001162922Sariff/**************************************************************************** 1002162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 1003162922Sariff * 1004162922Sariff * Retreive the general capabilities of the hdac; 1005162922Sariff * Number of Input Streams 1006162922Sariff * Number of Output Streams 1007162922Sariff * Number of bidirectional Streams 1008162922Sariff * 64bit ready 1009162922Sariff * CORB and RIRB sizes 1010162922Sariff ****************************************************************************/ 1011162922Sariffstatic int 1012162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 1013162922Sariff{ 1014162922Sariff uint16_t gcap; 1015162922Sariff uint8_t corbsize, rirbsize; 1016162922Sariff 1017162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 1018162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 1019162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 1020162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 1021162922Sariff 1022163057Sariff sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK); 1023162922Sariff 1024162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 1025162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 1026162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 1027162922Sariff sc->corb_size = 256; 1028162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 1029162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 1030162922Sariff sc->corb_size = 16; 1031162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 1032162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 1033162922Sariff sc->corb_size = 2; 1034162922Sariff else { 1035162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 1036162922Sariff __func__, corbsize); 1037162922Sariff return (ENXIO); 1038162922Sariff } 1039162922Sariff 1040162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 1041162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 1042162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 1043162922Sariff sc->rirb_size = 256; 1044162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 1045162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 1046162922Sariff sc->rirb_size = 16; 1047162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 1048162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 1049162922Sariff sc->rirb_size = 2; 1050162922Sariff else { 1051162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 1052162922Sariff __func__, rirbsize); 1053162922Sariff return (ENXIO); 1054162922Sariff } 1055162922Sariff 1056162922Sariff return (0); 1057162922Sariff} 1058162922Sariff 1059162922Sariff 1060162922Sariff/**************************************************************************** 1061162922Sariff * void hdac_dma_cb 1062162922Sariff * 1063162922Sariff * This function is called by bus_dmamap_load when the mapping has been 1064162922Sariff * established. We just record the physical address of the mapping into 1065162922Sariff * the struct hdac_dma passed in. 1066162922Sariff ****************************************************************************/ 1067162922Sariffstatic void 1068162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 1069162922Sariff{ 1070162922Sariff struct hdac_dma *dma; 1071162922Sariff 1072162922Sariff if (error == 0) { 1073162922Sariff dma = (struct hdac_dma *)callback_arg; 1074162922Sariff dma->dma_paddr = segs[0].ds_addr; 1075162922Sariff } 1076162922Sariff} 1077162922Sariff 1078162922Sariffstatic void 1079162922Sariffhdac_dma_nocache(void *ptr) 1080162922Sariff{ 1081162956Sariff#if defined(__i386__) || defined(__amd64__) 1082162922Sariff pt_entry_t *pte; 1083162922Sariff vm_offset_t va; 1084162922Sariff 1085162922Sariff va = (vm_offset_t)ptr; 1086162922Sariff pte = vtopte(va); 1087162922Sariff if (pte) { 1088162922Sariff *pte |= PG_N; 1089162922Sariff invltlb(); 1090162922Sariff } 1091162956Sariff#endif 1092162922Sariff} 1093162922Sariff 1094162922Sariff/**************************************************************************** 1095162922Sariff * int hdac_dma_alloc 1096162922Sariff * 1097162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1098162922Sariff * It must be freed by a corresponding hdac_dma_free. 1099162922Sariff ****************************************************************************/ 1100162922Sariffstatic int 1101162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1102162922Sariff{ 1103162922Sariff int result; 1104162922Sariff int lowaddr; 1105162922Sariff 1106162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1107162922Sariff BUS_SPACE_MAXADDR_32BIT; 1108162922Sariff bzero(dma, sizeof(*dma)); 1109162922Sariff 1110162922Sariff /* 1111162922Sariff * Create a DMA tag 1112162922Sariff */ 1113162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1114162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1115162922Sariff 0, /* boundary */ 1116162922Sariff lowaddr, /* lowaddr */ 1117162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1118162922Sariff NULL, /* filtfunc */ 1119162922Sariff NULL, /* fistfuncarg */ 1120162922Sariff size, /* maxsize */ 1121162922Sariff 1, /* nsegments */ 1122162922Sariff size, /* maxsegsz */ 1123162922Sariff 0, /* flags */ 1124162922Sariff NULL, /* lockfunc */ 1125162922Sariff NULL, /* lockfuncarg */ 1126162922Sariff &dma->dma_tag); /* dmat */ 1127162922Sariff if (result != 0) { 1128162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1129162922Sariff __func__, result); 1130162922Sariff goto fail; 1131162922Sariff } 1132162922Sariff 1133162922Sariff /* 1134162922Sariff * Allocate DMA memory 1135162922Sariff */ 1136162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1137162922Sariff BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); 1138162922Sariff if (result != 0) { 1139162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1140162922Sariff __func__, result); 1141162922Sariff goto fail; 1142162922Sariff } 1143162922Sariff 1144162922Sariff /* 1145162922Sariff * Map the memory 1146162922Sariff */ 1147162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1148162922Sariff (void *)dma->dma_vaddr, size, hdac_dma_cb, (void *)dma, 1149162922Sariff BUS_DMA_NOWAIT); 1150162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1151162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1152162922Sariff __func__, result); 1153162922Sariff goto fail; 1154162922Sariff } 1155162922Sariff bzero((void *)dma->dma_vaddr, size); 1156162922Sariff hdac_dma_nocache(dma->dma_vaddr); 1157162922Sariff 1158162922Sariff return (0); 1159162922Sarifffail: 1160162922Sariff if (dma->dma_map != NULL) 1161162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1162162922Sariff if (dma->dma_tag != NULL) 1163162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1164162922Sariff return (result); 1165162922Sariff} 1166162922Sariff 1167162922Sariff 1168162922Sariff/**************************************************************************** 1169162922Sariff * void hdac_dma_free(struct hdac_dma *) 1170162922Sariff * 1171162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1172162922Sariff * hdac_dma_alloc function. 1173162922Sariff ****************************************************************************/ 1174162922Sariffstatic void 1175162922Sariffhdac_dma_free(struct hdac_dma *dma) 1176162922Sariff{ 1177162922Sariff if (dma->dma_tag != NULL) { 1178162922Sariff /* Flush caches */ 1179162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1180162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1181162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1182162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1183162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1184162922Sariff } 1185162922Sariff} 1186162922Sariff 1187162922Sariff/**************************************************************************** 1188162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1189162922Sariff * 1190162922Sariff * Allocate all the bus resources necessary to speak with the physical 1191162922Sariff * controller. 1192162922Sariff ****************************************************************************/ 1193162922Sariffstatic int 1194162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1195162922Sariff{ 1196162922Sariff struct hdac_mem *mem; 1197162922Sariff 1198162922Sariff mem = &sc->mem; 1199162922Sariff mem->mem_rid = PCIR_BAR(0); 1200162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1201162922Sariff &mem->mem_rid, RF_ACTIVE); 1202162922Sariff if (mem->mem_res == NULL) { 1203162922Sariff device_printf(sc->dev, 1204162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1205162922Sariff return (ENOMEM); 1206162922Sariff } 1207162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1208162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1209162922Sariff 1210162922Sariff return (0); 1211162922Sariff} 1212162922Sariff 1213162922Sariff/**************************************************************************** 1214162922Sariff * void hdac_mem_free(struct hdac_softc *) 1215162922Sariff * 1216162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1217162922Sariff ****************************************************************************/ 1218162922Sariffstatic void 1219162922Sariffhdac_mem_free(struct hdac_softc *sc) 1220162922Sariff{ 1221162922Sariff struct hdac_mem *mem; 1222162922Sariff 1223162922Sariff mem = &sc->mem; 1224162922Sariff if (mem->mem_res != NULL) 1225162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1226162922Sariff mem->mem_res); 1227164614Sariff mem->mem_res = NULL; 1228162922Sariff} 1229162922Sariff 1230162922Sariff/**************************************************************************** 1231162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1232162922Sariff * 1233162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1234162922Sariff ****************************************************************************/ 1235162922Sariffstatic int 1236162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1237162922Sariff{ 1238162922Sariff struct hdac_irq *irq; 1239162922Sariff int result; 1240162922Sariff 1241162922Sariff irq = &sc->irq; 1242162922Sariff irq->irq_rid = 0x0; 1243162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1244162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1245162922Sariff if (irq->irq_res == NULL) { 1246162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1247162922Sariff __func__); 1248162922Sariff goto fail; 1249162922Sariff } 1250162922Sariff result = snd_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE, 1251164614Sariff hdac_intr_handler, sc, &irq->irq_handle); 1252162922Sariff if (result != 0) { 1253162922Sariff device_printf(sc->dev, 1254162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1255162922Sariff __func__, result); 1256162922Sariff goto fail; 1257162922Sariff } 1258162922Sariff 1259162922Sariff return (0); 1260162922Sariff 1261162922Sarifffail: 1262164614Sariff hdac_irq_free(sc); 1263164614Sariff 1264162922Sariff return (ENXIO); 1265162922Sariff} 1266162922Sariff 1267162922Sariff/**************************************************************************** 1268162922Sariff * void hdac_irq_free(struct hdac_softc *) 1269162922Sariff * 1270162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1271162922Sariff ****************************************************************************/ 1272162922Sariffstatic void 1273162922Sariffhdac_irq_free(struct hdac_softc *sc) 1274162922Sariff{ 1275162922Sariff struct hdac_irq *irq; 1276162922Sariff 1277162922Sariff irq = &sc->irq; 1278164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 1279162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1280162922Sariff if (irq->irq_res != NULL) 1281162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1282162922Sariff irq->irq_res); 1283164614Sariff irq->irq_handle = NULL; 1284164614Sariff irq->irq_res = NULL; 1285162922Sariff} 1286162922Sariff 1287162922Sariff/**************************************************************************** 1288162922Sariff * void hdac_corb_init(struct hdac_softc *) 1289162922Sariff * 1290162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1291162922Sariff * The CORB engine must not be running when this function is called. 1292162922Sariff ****************************************************************************/ 1293162922Sariffstatic void 1294162922Sariffhdac_corb_init(struct hdac_softc *sc) 1295162922Sariff{ 1296162922Sariff uint8_t corbsize; 1297162922Sariff uint64_t corbpaddr; 1298162922Sariff 1299162922Sariff /* Setup the CORB size. */ 1300162922Sariff switch (sc->corb_size) { 1301162922Sariff case 256: 1302162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1303162922Sariff break; 1304162922Sariff case 16: 1305162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1306162922Sariff break; 1307162922Sariff case 2: 1308162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1309162922Sariff break; 1310162922Sariff default: 1311162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1312162922Sariff } 1313162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1314162922Sariff 1315162922Sariff /* Setup the CORB Address in the hdac */ 1316162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1317162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1318162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1319162922Sariff 1320162922Sariff /* Set the WP and RP */ 1321162922Sariff sc->corb_wp = 0; 1322162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1323162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1324162922Sariff /* 1325162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1326162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1327162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1328162922Sariff * manually reset the bit to zero before continuing. 1329162922Sariff */ 1330162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1331162922Sariff 1332162922Sariff /* Enable CORB error reporting */ 1333162922Sariff#if 0 1334162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1335162922Sariff#endif 1336162922Sariff} 1337162922Sariff 1338162922Sariff/**************************************************************************** 1339162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1340162922Sariff * 1341162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1342162922Sariff * The RIRB engine must not be running when this function is called. 1343162922Sariff ****************************************************************************/ 1344162922Sariffstatic void 1345162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1346162922Sariff{ 1347162922Sariff uint8_t rirbsize; 1348162922Sariff uint64_t rirbpaddr; 1349162922Sariff 1350162922Sariff /* Setup the RIRB size. */ 1351162922Sariff switch (sc->rirb_size) { 1352162922Sariff case 256: 1353162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1354162922Sariff break; 1355162922Sariff case 16: 1356162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1357162922Sariff break; 1358162922Sariff case 2: 1359162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1360162922Sariff break; 1361162922Sariff default: 1362162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1363162922Sariff } 1364162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1365162922Sariff 1366162922Sariff /* Setup the RIRB Address in the hdac */ 1367162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1368162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1369162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1370162922Sariff 1371162922Sariff /* Setup the WP and RP */ 1372162922Sariff sc->rirb_rp = 0; 1373162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1374162922Sariff 1375164614Sariff if (sc->polling == 0) { 1376164614Sariff /* Setup the interrupt threshold */ 1377164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1378162922Sariff 1379164614Sariff /* Enable Overrun and response received reporting */ 1380162922Sariff#if 0 1381164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1382164614Sariff HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1383162922Sariff#else 1384164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1385162922Sariff#endif 1386164614Sariff } 1387162922Sariff 1388162922Sariff /* 1389162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1390162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1391162922Sariff * should be sufficient to do this only once as the rirb is purely 1392162922Sariff * read-only from now on. 1393162922Sariff */ 1394162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1395162922Sariff BUS_DMASYNC_PREREAD); 1396162922Sariff} 1397162922Sariff 1398162922Sariff/**************************************************************************** 1399162922Sariff * void hdac_corb_start(hdac_softc *) 1400162922Sariff * 1401162922Sariff * Startup the corb DMA engine 1402162922Sariff ****************************************************************************/ 1403162922Sariffstatic void 1404162922Sariffhdac_corb_start(struct hdac_softc *sc) 1405162922Sariff{ 1406162922Sariff uint32_t corbctl; 1407162922Sariff 1408162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1409162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1410162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1411162922Sariff} 1412162922Sariff 1413162922Sariff/**************************************************************************** 1414162922Sariff * void hdac_rirb_start(hdac_softc *) 1415162922Sariff * 1416162922Sariff * Startup the rirb DMA engine 1417162922Sariff ****************************************************************************/ 1418162922Sariffstatic void 1419162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1420162922Sariff{ 1421162922Sariff uint32_t rirbctl; 1422162922Sariff 1423162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1424162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1425162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1426162922Sariff} 1427162922Sariff 1428162922Sariff 1429162922Sariff/**************************************************************************** 1430162922Sariff * void hdac_scan_codecs(struct hdac_softc *) 1431162922Sariff * 1432162922Sariff * Scan the bus for available codecs. 1433162922Sariff ****************************************************************************/ 1434162922Sariffstatic void 1435162922Sariffhdac_scan_codecs(struct hdac_softc *sc) 1436162922Sariff{ 1437162922Sariff struct hdac_codec *codec; 1438162922Sariff int i; 1439162922Sariff uint16_t statests; 1440162922Sariff 1441162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1442162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) { 1443162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1444162922Sariff /* We have found a codec. */ 1445162922Sariff hdac_unlock(sc); 1446162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1447162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1448162922Sariff hdac_lock(sc); 1449162922Sariff if (codec == NULL) { 1450162922Sariff device_printf(sc->dev, 1451162922Sariff "Unable to allocate memory for codec\n"); 1452162922Sariff continue; 1453162922Sariff } 1454164614Sariff codec->commands = NULL; 1455164614Sariff codec->responses_received = 0; 1456162922Sariff codec->verbs_sent = 0; 1457162922Sariff codec->sc = sc; 1458162922Sariff codec->cad = i; 1459162922Sariff sc->codecs[i] = codec; 1460162922Sariff if (hdac_probe_codec(codec) != 0) 1461162922Sariff break; 1462162922Sariff } 1463162922Sariff } 1464162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1465163057Sariff /* bus_generic_attach(sc->dev); */ 1466162922Sariff} 1467162922Sariff 1468162922Sariff/**************************************************************************** 1469162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1470162922Sariff * 1471162922Sariff * Probe a the given codec_id for available function groups. 1472162922Sariff ****************************************************************************/ 1473162922Sariffstatic int 1474162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1475162922Sariff{ 1476162922Sariff struct hdac_softc *sc = codec->sc; 1477162922Sariff struct hdac_devinfo *devinfo; 1478162922Sariff uint32_t vendorid, revisionid, subnode; 1479162922Sariff int startnode; 1480162922Sariff int endnode; 1481162922Sariff int i; 1482162922Sariff nid_t cad = codec->cad; 1483162922Sariff 1484163057Sariff HDA_BOOTVERBOSE( 1485163057Sariff device_printf(sc->dev, "HDA_DEBUG: Probing codec: %d\n", cad); 1486162922Sariff ); 1487162922Sariff vendorid = hdac_command(sc, 1488162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1489162922Sariff cad); 1490162922Sariff revisionid = hdac_command(sc, 1491162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1492162922Sariff cad); 1493162922Sariff subnode = hdac_command(sc, 1494162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1495162922Sariff cad); 1496162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1497162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1498162922Sariff 1499163057Sariff HDA_BOOTVERBOSE( 1500163057Sariff device_printf(sc->dev, "HDA_DEBUG: \tstartnode=%d endnode=%d\n", 1501163057Sariff startnode, endnode); 1502162922Sariff ); 1503162922Sariff for (i = startnode; i < endnode; i++) { 1504162922Sariff devinfo = hdac_probe_function(codec, i); 1505162922Sariff if (devinfo != NULL) { 1506162922Sariff /* XXX Ignore other FG. */ 1507162922Sariff devinfo->vendor_id = 1508162922Sariff HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1509162922Sariff devinfo->device_id = 1510162922Sariff HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1511162922Sariff devinfo->revision_id = 1512162922Sariff HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1513162922Sariff devinfo->stepping_id = 1514162922Sariff HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1515163057Sariff HDA_BOOTVERBOSE( 1516162922Sariff device_printf(sc->dev, 1517163057Sariff "HDA_DEBUG: \tFound AFG nid=%d " 1518162922Sariff "[startnode=%d endnode=%d]\n", 1519163057Sariff devinfo->nid, startnode, endnode); 1520162922Sariff ); 1521162922Sariff return (1); 1522162922Sariff } 1523162922Sariff } 1524162922Sariff 1525163057Sariff HDA_BOOTVERBOSE( 1526163057Sariff device_printf(sc->dev, "HDA_DEBUG: \tAFG not found\n"); 1527162922Sariff ); 1528162922Sariff return (0); 1529162922Sariff} 1530162922Sariff 1531162922Sariffstatic struct hdac_devinfo * 1532162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1533162922Sariff{ 1534162922Sariff struct hdac_softc *sc = codec->sc; 1535162922Sariff struct hdac_devinfo *devinfo; 1536162922Sariff uint32_t fctgrptype; 1537162922Sariff nid_t cad = codec->cad; 1538162922Sariff 1539162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1540162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1541162922Sariff 1542162922Sariff /* XXX For now, ignore other FG. */ 1543162965Sariff if (fctgrptype != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 1544162922Sariff return (NULL); 1545162922Sariff 1546162922Sariff hdac_unlock(sc); 1547162922Sariff devinfo = (struct hdac_devinfo *)malloc(sizeof(*devinfo), M_HDAC, 1548162922Sariff M_NOWAIT | M_ZERO); 1549162922Sariff hdac_lock(sc); 1550162922Sariff if (devinfo == NULL) { 1551162922Sariff device_printf(sc->dev, "%s: Unable to allocate ivar\n", 1552162922Sariff __func__); 1553162922Sariff return (NULL); 1554162922Sariff } 1555162922Sariff 1556162922Sariff devinfo->nid = nid; 1557162965Sariff devinfo->node_type = fctgrptype; 1558162922Sariff devinfo->codec = codec; 1559162922Sariff 1560162922Sariff hdac_add_child(sc, devinfo); 1561162922Sariff 1562162922Sariff return (devinfo); 1563162922Sariff} 1564162922Sariff 1565162922Sariffstatic void 1566162922Sariffhdac_add_child(struct hdac_softc *sc, struct hdac_devinfo *devinfo) 1567162922Sariff{ 1568162922Sariff devinfo->dev = device_add_child(sc->dev, NULL, -1); 1569162922Sariff device_set_ivars(devinfo->dev, (void *)devinfo); 1570162922Sariff /* XXX - Print more information when booting verbose??? */ 1571162922Sariff} 1572162922Sariff 1573162922Sariffstatic void 1574162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 1575162922Sariff{ 1576162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1577162922Sariff uint32_t res; 1578162922Sariff int i, j, max, found, entnum, cnid; 1579162922Sariff nid_t cad = w->devinfo->codec->cad; 1580162922Sariff nid_t nid = w->nid; 1581162922Sariff 1582162922Sariff res = hdac_command(sc, 1583162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 1584162922Sariff 1585162922Sariff w->nconns = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 1586162922Sariff 1587162922Sariff if (w->nconns < 1) 1588162922Sariff return; 1589162922Sariff 1590162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 1591162922Sariff res = 0; 1592162922Sariff i = 0; 1593162922Sariff found = 0; 1594162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 1595162922Sariff 1596162922Sariff while (i < w->nconns) { 1597162922Sariff res = hdac_command(sc, 1598162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 1599162922Sariff for (j = 0; j < entnum; j++) { 1600162922Sariff cnid = res; 1601162922Sariff cnid >>= (32 / entnum) * j; 1602162922Sariff cnid &= (1 << (32 / entnum)) - 1; 1603162922Sariff if (cnid == 0) 1604162922Sariff continue; 1605162922Sariff if (found > max) { 1606162922Sariff device_printf(sc->dev, 1607162922Sariff "node %d: Adding %d: " 1608162922Sariff "Max connection reached!\n", 1609162922Sariff nid, cnid); 1610162922Sariff continue; 1611162922Sariff } 1612162922Sariff w->conns[found++] = cnid; 1613162922Sariff } 1614162922Sariff i += entnum; 1615162922Sariff } 1616162922Sariff 1617163057Sariff HDA_BOOTVERBOSE( 1618162922Sariff if (w->nconns != found) { 1619162922Sariff device_printf(sc->dev, 1620163057Sariff "HDA_DEBUG: nid=%d WARNING!!! Connection " 1621162922Sariff "length=%d != found=%d\n", 1622162922Sariff nid, w->nconns, found); 1623162922Sariff } 1624162922Sariff ); 1625162922Sariff} 1626162922Sariff 1627162922Sariffstatic uint32_t 1628162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 1629162922Sariff{ 1630162922Sariff struct hdac_softc *sc; 1631162922Sariff uint32_t config, id; 1632162922Sariff nid_t cad, nid; 1633162922Sariff 1634162922Sariff sc = w->devinfo->codec->sc; 1635162922Sariff cad = w->devinfo->codec->cad; 1636162922Sariff nid = w->nid; 1637162922Sariff id = hdac_codec_id(w->devinfo); 1638162922Sariff 1639162922Sariff config = hdac_command(sc, 1640162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 1641162922Sariff cad); 1642162965Sariff /* 1643162965Sariff * XXX REWRITE!!!! Don't argue! 1644162965Sariff */ 1645162922Sariff if (id == HDA_CODEC_ALC880 && 1646162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 1647162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 1648162922Sariff /* 1649162965Sariff * Super broken BIOS 1650162922Sariff */ 1651162922Sariff switch (nid) { 1652162922Sariff case 20: 1653162922Sariff break; 1654162922Sariff case 21: 1655162922Sariff break; 1656162922Sariff case 22: 1657162922Sariff break; 1658162922Sariff case 23: 1659162922Sariff break; 1660162922Sariff case 24: /* MIC1 */ 1661162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1662162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 1663162922Sariff break; 1664162922Sariff case 25: /* XXX MIC2 */ 1665162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1666162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 1667162922Sariff break; 1668162922Sariff case 26: /* LINE1 */ 1669162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1670162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1671162922Sariff break; 1672162922Sariff case 27: /* XXX LINE2 */ 1673162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1674162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1675162922Sariff break; 1676162922Sariff case 28: /* CD */ 1677162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1678162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 1679162922Sariff break; 1680162922Sariff case 30: 1681162922Sariff break; 1682162922Sariff case 31: 1683162922Sariff break; 1684162922Sariff default: 1685162922Sariff break; 1686162922Sariff } 1687162922Sariff } 1688162922Sariff 1689162922Sariff return (config); 1690162922Sariff} 1691162922Sariff 1692162922Sariffstatic void 1693162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 1694162922Sariff{ 1695162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1696162922Sariff uint32_t config, pincap; 1697162922Sariff char *devstr, *connstr; 1698162922Sariff nid_t cad = w->devinfo->codec->cad; 1699162922Sariff nid_t nid = w->nid; 1700162922Sariff 1701162922Sariff config = hdac_widget_pin_getconfig(w); 1702162922Sariff w->wclass.pin.config = config; 1703162922Sariff 1704162922Sariff pincap = hdac_command(sc, 1705164614Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 1706162922Sariff w->wclass.pin.cap = pincap; 1707162922Sariff 1708162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 1709164614Sariff HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad) & 1710164614Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 1711164614Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 1712164614Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE); 1713162922Sariff 1714162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 1715162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 1716162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 1717162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1718162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 1719162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 1720162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 1721162922Sariff w->param.eapdbtl = hdac_command(sc, 1722162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 1723162922Sariff w->param.eapdbtl &= 0x7; 1724162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 1725162922Sariff } else 1726162965Sariff w->param.eapdbtl = HDAC_INVALID; 1727162922Sariff 1728162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 1729162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 1730162922Sariff devstr = "line out"; 1731162922Sariff break; 1732162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 1733162922Sariff devstr = "speaker"; 1734162922Sariff break; 1735162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 1736162922Sariff devstr = "headphones out"; 1737162922Sariff break; 1738162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 1739162922Sariff devstr = "CD"; 1740162922Sariff break; 1741162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 1742162922Sariff devstr = "SPDIF out"; 1743162922Sariff break; 1744162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 1745162922Sariff devstr = "digital (other) out"; 1746162922Sariff break; 1747162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE: 1748162922Sariff devstr = "modem, line side"; 1749162922Sariff break; 1750162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET: 1751162922Sariff devstr = "modem, handset side"; 1752162922Sariff break; 1753162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 1754162922Sariff devstr = "line in"; 1755162922Sariff break; 1756162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 1757162922Sariff devstr = "AUX"; 1758162922Sariff break; 1759162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 1760162922Sariff devstr = "Mic in"; 1761162922Sariff break; 1762162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY: 1763162922Sariff devstr = "telephony"; 1764162922Sariff break; 1765162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 1766162922Sariff devstr = "SPDIF in"; 1767162922Sariff break; 1768162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 1769162922Sariff devstr = "digital (other) in"; 1770162922Sariff break; 1771162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER: 1772162922Sariff devstr = "other"; 1773162922Sariff break; 1774162922Sariff default: 1775162922Sariff devstr = "unknown"; 1776162922Sariff break; 1777162922Sariff } 1778162922Sariff 1779162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) { 1780162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK: 1781162922Sariff connstr = "jack"; 1782162922Sariff break; 1783162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE: 1784162922Sariff connstr = "none"; 1785162922Sariff break; 1786162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED: 1787162922Sariff connstr = "fixed"; 1788162922Sariff break; 1789162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH: 1790162922Sariff connstr = "jack / fixed"; 1791162922Sariff break; 1792162922Sariff default: 1793162922Sariff connstr = "unknown"; 1794162922Sariff break; 1795162922Sariff } 1796162922Sariff 1797162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 1798162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 1799162922Sariff strlcat(w->name, " (", sizeof(w->name)); 1800162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 1801162922Sariff strlcat(w->name, ")", sizeof(w->name)); 1802162922Sariff} 1803162922Sariff 1804162922Sariffstatic void 1805162922Sariffhdac_widget_parse(struct hdac_widget *w) 1806162922Sariff{ 1807162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1808162922Sariff uint32_t wcap, cap; 1809162922Sariff char *typestr; 1810162922Sariff nid_t cad = w->devinfo->codec->cad; 1811162922Sariff nid_t nid = w->nid; 1812162922Sariff 1813162922Sariff wcap = hdac_command(sc, 1814162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 1815162922Sariff cad); 1816162922Sariff w->param.widget_cap = wcap; 1817162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 1818162922Sariff 1819162922Sariff switch (w->type) { 1820162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 1821162922Sariff typestr = "audio output"; 1822162922Sariff break; 1823162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 1824162922Sariff typestr = "audio input"; 1825162922Sariff break; 1826162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 1827162922Sariff typestr = "audio mixer"; 1828162922Sariff break; 1829162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 1830162922Sariff typestr = "audio selector"; 1831162922Sariff break; 1832162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 1833162922Sariff typestr = "pin"; 1834162922Sariff break; 1835162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 1836162922Sariff typestr = "power widget"; 1837162922Sariff break; 1838162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 1839162922Sariff typestr = "volume widget"; 1840162922Sariff break; 1841162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 1842162922Sariff typestr = "beep widget"; 1843162922Sariff break; 1844162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 1845162922Sariff typestr = "vendor widget"; 1846162922Sariff break; 1847162922Sariff default: 1848162922Sariff typestr = "unknown type"; 1849162922Sariff break; 1850162922Sariff } 1851162922Sariff 1852162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 1853162922Sariff 1854162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(wcap)) { 1855162922Sariff hdac_command(sc, 1856162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), 1857162922Sariff cad); 1858162922Sariff DELAY(1000); 1859162922Sariff } 1860162922Sariff 1861162922Sariff hdac_widget_connection_parse(w); 1862162922Sariff 1863162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 1864162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 1865162922Sariff w->param.outamp_cap = 1866162922Sariff hdac_command(sc, 1867162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1868162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 1869162922Sariff else 1870162922Sariff w->param.outamp_cap = 1871162922Sariff w->devinfo->function.audio.outamp_cap; 1872162922Sariff } else 1873162922Sariff w->param.outamp_cap = 0; 1874162922Sariff 1875162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 1876162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 1877162922Sariff w->param.inamp_cap = 1878162922Sariff hdac_command(sc, 1879162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1880162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 1881162922Sariff else 1882162922Sariff w->param.inamp_cap = 1883162922Sariff w->devinfo->function.audio.inamp_cap; 1884162922Sariff } else 1885162922Sariff w->param.inamp_cap = 0; 1886162922Sariff 1887162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 1888162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 1889162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 1890162922Sariff cap = hdac_command(sc, 1891162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1892162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 1893162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 1894162922Sariff w->devinfo->function.audio.supp_stream_formats; 1895162922Sariff cap = hdac_command(sc, 1896162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1897162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 1898162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 1899162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 1900162922Sariff } else { 1901162922Sariff w->param.supp_stream_formats = 1902162922Sariff w->devinfo->function.audio.supp_stream_formats; 1903162922Sariff w->param.supp_pcm_size_rate = 1904162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 1905162922Sariff } 1906162922Sariff } else { 1907162922Sariff w->param.supp_stream_formats = 0; 1908162922Sariff w->param.supp_pcm_size_rate = 0; 1909162922Sariff } 1910162922Sariff 1911162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1912162922Sariff hdac_widget_pin_parse(w); 1913162922Sariff} 1914162922Sariff 1915162922Sariffstatic struct hdac_widget * 1916162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 1917162922Sariff{ 1918162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 1919162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 1920162922Sariff return (NULL); 1921162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 1922162922Sariff} 1923162922Sariff 1924164614Sariffstatic __inline int 1925164614Sariffhda_poll_channel(struct hdac_chan *ch) 1926164614Sariff{ 1927164614Sariff uint32_t sz, delta; 1928164614Sariff volatile uint32_t ptr; 1929164614Sariff 1930164614Sariff if (ch->active == 0) 1931164614Sariff return (0); 1932164614Sariff 1933164614Sariff sz = ch->blksz * ch->blkcnt; 1934164614Sariff ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem, ch->off + HDAC_SDLPIB); 1935164614Sariff ch->ptr = ptr; 1936164614Sariff ptr %= sz; 1937164614Sariff ptr &= ~(ch->blksz - 1); 1938164614Sariff delta = (sz + ptr - ch->prevptr) % sz; 1939164614Sariff 1940164614Sariff if (delta < ch->blksz) 1941164614Sariff return (0); 1942164614Sariff 1943164614Sariff ch->prevptr = ptr; 1944164614Sariff 1945164614Sariff return (1); 1946164614Sariff} 1947164614Sariff 1948164614Sariff#define hda_chan_active(sc) ((sc)->play.active + (sc)->rec.active) 1949164614Sariff 1950162922Sariffstatic void 1951164614Sariffhda_poll_callback(void *arg) 1952164614Sariff{ 1953164614Sariff struct hdac_softc *sc = arg; 1954164614Sariff uint32_t trigger = 0; 1955164614Sariff 1956164614Sariff if (sc == NULL) 1957164614Sariff return; 1958164614Sariff 1959164614Sariff hdac_lock(sc); 1960164614Sariff if (sc->polling == 0 || hda_chan_active(sc) == 0) { 1961164614Sariff hdac_unlock(sc); 1962164614Sariff return; 1963164614Sariff } 1964164614Sariff 1965164614Sariff trigger |= (hda_poll_channel(&sc->play) != 0) ? 1 : 0; 1966164614Sariff trigger |= (hda_poll_channel(&sc->rec) != 0) ? 2 : 0; 1967164614Sariff 1968164614Sariff /* XXX */ 1969164614Sariff callout_reset(&sc->poll_hda, 1/*sc->poll_ticks*/, 1970164614Sariff hda_poll_callback, sc); 1971164614Sariff 1972164614Sariff hdac_unlock(sc); 1973164614Sariff 1974164614Sariff if (trigger & 1) 1975164614Sariff chn_intr(sc->play.c); 1976164614Sariff if (trigger & 2) 1977164614Sariff chn_intr(sc->rec.c); 1978164614Sariff} 1979164614Sariff 1980164614Sariffstatic int 1981164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 1982164614Sariff{ 1983164614Sariff struct hdac_rirb *rirb_base, *rirb; 1984164614Sariff struct hdac_codec *codec; 1985164614Sariff struct hdac_command_list *commands; 1986164614Sariff nid_t cad; 1987164614Sariff uint32_t resp; 1988164614Sariff uint8_t rirbwp; 1989164614Sariff int ret = 0; 1990164614Sariff 1991164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 1992164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 1993164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1994164614Sariff BUS_DMASYNC_POSTREAD); 1995164614Sariff 1996164614Sariff while (sc->rirb_rp != rirbwp) { 1997164614Sariff sc->rirb_rp++; 1998164614Sariff sc->rirb_rp %= sc->rirb_size; 1999164614Sariff rirb = &rirb_base[sc->rirb_rp]; 2000164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2001164614Sariff if (cad < 0 || cad >= HDAC_CODEC_MAX || 2002164614Sariff sc->codecs[cad] == NULL) 2003164614Sariff continue; 2004164614Sariff resp = rirb->response; 2005164614Sariff codec = sc->codecs[cad]; 2006164614Sariff commands = codec->commands; 2007164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2008164614Sariff sc->unsolq[sc->unsolq_wp++] = (cad << 16) | 2009164614Sariff ((resp >> 26) & 0xffff); 2010164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2011164614Sariff } else if (commands != NULL && commands->num_commands > 0 && 2012164614Sariff codec->responses_received < commands->num_commands) 2013164614Sariff commands->responses[codec->responses_received++] = 2014164614Sariff resp; 2015164614Sariff ret++; 2016164614Sariff } 2017164614Sariff 2018164614Sariff return (ret); 2019164614Sariff} 2020164614Sariff 2021164614Sariffstatic int 2022164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 2023164614Sariff{ 2024164614Sariff nid_t cad; 2025164614Sariff uint32_t tag; 2026164614Sariff int ret = 0; 2027164614Sariff 2028164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2029164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2030164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2031164614Sariff cad = sc->unsolq[sc->unsolq_rp] >> 16; 2032164614Sariff tag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2033164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2034164614Sariff hdac_unsolicited_handler(sc->codecs[cad], tag); 2035164614Sariff ret++; 2036164614Sariff } 2037164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2038164614Sariff } 2039164614Sariff 2040164614Sariff return (ret); 2041164614Sariff} 2042164614Sariff 2043164614Sariffstatic void 2044164614Sariffhdac_poll_callback(void *arg) 2045164614Sariff{ 2046164614Sariff struct hdac_softc *sc = arg; 2047164614Sariff if (sc == NULL) 2048164614Sariff return; 2049164614Sariff 2050164614Sariff hdac_lock(sc); 2051164614Sariff if (sc->polling == 0) { 2052164614Sariff hdac_unlock(sc); 2053164614Sariff return; 2054164614Sariff } 2055164614Sariff hdac_rirb_flush(sc); 2056164614Sariff hdac_unsolq_flush(sc); 2057164614Sariff callout_reset(&sc->poll_hdac, max(hz >> 2, 1), 2058164614Sariff hdac_poll_callback, sc); 2059164614Sariff hdac_unlock(sc); 2060164614Sariff} 2061164614Sariff 2062164614Sariffstatic void 2063162922Sariffhdac_stream_stop(struct hdac_chan *ch) 2064162922Sariff{ 2065162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2066162922Sariff uint32_t ctl; 2067162922Sariff 2068162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2069162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2070162922Sariff HDAC_SDCTL_RUN); 2071162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2072162922Sariff 2073164614Sariff ch->active = 0; 2074164614Sariff 2075164614Sariff if (sc->polling != 0) { 2076164614Sariff int pollticks; 2077164614Sariff 2078164614Sariff if (hda_chan_active(sc) == 0) { 2079164614Sariff callout_stop(&sc->poll_hda); 2080164614Sariff sc->poll_ticks = 1; 2081164614Sariff } else { 2082164614Sariff if (sc->play.active != 0) 2083164614Sariff ch = &sc->play; 2084164614Sariff else 2085164614Sariff ch = &sc->rec; 2086164614Sariff pollticks = ((uint64_t)hz * ch->blksz) / 2087164614Sariff ((uint64_t)sndbuf_getbps(ch->b) * 2088164614Sariff sndbuf_getspd(ch->b)); 2089164614Sariff pollticks >>= 2; 2090164614Sariff if (pollticks > hz) 2091164614Sariff pollticks = hz; 2092164614Sariff if (pollticks < 1) { 2093164614Sariff HDA_BOOTVERBOSE( 2094164614Sariff device_printf(sc->dev, 2095164614Sariff "%s: pollticks=%d < 1 !\n", 2096164614Sariff __func__, pollticks); 2097164614Sariff ); 2098164614Sariff pollticks = 1; 2099164614Sariff } 2100164614Sariff if (pollticks > sc->poll_ticks) { 2101164614Sariff HDA_BOOTVERBOSE( 2102164614Sariff device_printf(sc->dev, 2103164614Sariff "%s: pollticks %d -> %d\n", 2104164614Sariff __func__, sc->poll_ticks, 2105164614Sariff pollticks); 2106164614Sariff ); 2107164614Sariff sc->poll_ticks = pollticks; 2108164614Sariff callout_reset(&sc->poll_hda, 1, 2109164614Sariff hda_poll_callback, sc); 2110164614Sariff } 2111164614Sariff } 2112164614Sariff } else { 2113164614Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2114164614Sariff ctl &= ~(1 << (ch->off >> 5)); 2115164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2116164614Sariff } 2117162922Sariff} 2118162922Sariff 2119162922Sariffstatic void 2120162922Sariffhdac_stream_start(struct hdac_chan *ch) 2121162922Sariff{ 2122162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2123162922Sariff uint32_t ctl; 2124162922Sariff 2125164614Sariff if (sc->polling != 0) { 2126164614Sariff int pollticks; 2127162922Sariff 2128164614Sariff pollticks = ((uint64_t)hz * ch->blksz) / 2129164614Sariff ((uint64_t)sndbuf_getbps(ch->b) * sndbuf_getspd(ch->b)); 2130164614Sariff pollticks >>= 2; 2131164614Sariff if (pollticks > hz) 2132164614Sariff pollticks = hz; 2133164614Sariff if (pollticks < 1) { 2134164614Sariff HDA_BOOTVERBOSE( 2135164614Sariff device_printf(sc->dev, 2136164614Sariff "%s: pollticks=%d < 1 !\n", 2137164614Sariff __func__, pollticks); 2138164614Sariff ); 2139164614Sariff pollticks = 1; 2140164614Sariff } 2141164614Sariff if (hda_chan_active(sc) == 0 || pollticks < sc->poll_ticks) { 2142164614Sariff HDA_BOOTVERBOSE( 2143164614Sariff if (hda_chan_active(sc) == 0) { 2144164614Sariff device_printf(sc->dev, 2145164614Sariff "%s: pollticks=%d\n", 2146164614Sariff __func__, pollticks); 2147164614Sariff } else { 2148164614Sariff device_printf(sc->dev, 2149164614Sariff "%s: pollticks %d -> %d\n", 2150164614Sariff __func__, sc->poll_ticks, 2151164614Sariff pollticks); 2152164614Sariff } 2153164614Sariff ); 2154164614Sariff sc->poll_ticks = pollticks; 2155164614Sariff callout_reset(&sc->poll_hda, 1, hda_poll_callback, 2156164614Sariff sc); 2157164614Sariff } 2158164614Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2159164614Sariff ctl |= HDAC_SDCTL_RUN; 2160164614Sariff } else { 2161164614Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 2162164614Sariff ctl |= 1 << (ch->off >> 5); 2163164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 2164164614Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2165164614Sariff ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 2166164614Sariff HDAC_SDCTL_RUN; 2167164614Sariff } 2168162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2169164614Sariff 2170164614Sariff ch->active = 1; 2171162922Sariff} 2172162922Sariff 2173162922Sariffstatic void 2174162922Sariffhdac_stream_reset(struct hdac_chan *ch) 2175162922Sariff{ 2176162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2177162922Sariff int timeout = 1000; 2178162922Sariff int to = timeout; 2179162922Sariff uint32_t ctl; 2180162922Sariff 2181162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2182162922Sariff ctl |= HDAC_SDCTL_SRST; 2183162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2184162922Sariff do { 2185162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2186162922Sariff if (ctl & HDAC_SDCTL_SRST) 2187162922Sariff break; 2188162922Sariff DELAY(10); 2189162922Sariff } while (--to); 2190162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 2191162922Sariff device_printf(sc->dev, "timeout in reset\n"); 2192162922Sariff } 2193162922Sariff ctl &= ~HDAC_SDCTL_SRST; 2194162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 2195162922Sariff to = timeout; 2196162922Sariff do { 2197162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 2198162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 2199162922Sariff break; 2200162922Sariff DELAY(10); 2201162922Sariff } while (--to); 2202163057Sariff if (ctl & HDAC_SDCTL_SRST) 2203162922Sariff device_printf(sc->dev, "can't reset!\n"); 2204162922Sariff} 2205162922Sariff 2206162922Sariffstatic void 2207162922Sariffhdac_stream_setid(struct hdac_chan *ch) 2208162922Sariff{ 2209162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2210162922Sariff uint32_t ctl; 2211162922Sariff 2212162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 2213162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 2214162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 2215162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 2216162922Sariff} 2217162922Sariff 2218162922Sariffstatic void 2219162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 2220162922Sariff{ 2221162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2222164614Sariff struct hdac_bdle *bdle; 2223162922Sariff uint64_t addr; 2224164614Sariff uint32_t blksz, blkcnt; 2225162922Sariff int i; 2226162922Sariff 2227162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 2228164614Sariff bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr; 2229162922Sariff 2230164614Sariff if (sc->polling != 0) { 2231164614Sariff blksz = ch->blksz * ch->blkcnt; 2232164614Sariff blkcnt = 1; 2233164614Sariff } else { 2234164614Sariff blksz = ch->blksz; 2235164614Sariff blkcnt = ch->blkcnt; 2236164614Sariff } 2237164614Sariff 2238164614Sariff for (i = 0; i < blkcnt; i++, bdle++) { 2239162922Sariff bdle->addrl = (uint32_t)addr; 2240162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 2241164614Sariff bdle->len = blksz; 2242164614Sariff bdle->ioc = 1 ^ sc->polling; 2243164614Sariff addr += blksz; 2244162922Sariff } 2245162922Sariff 2246164614Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt); 2247164614Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1); 2248162922Sariff addr = ch->bdl_dma.dma_paddr; 2249162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 2250162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 2251162922Sariff} 2252162922Sariff 2253162922Sariffstatic int 2254162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 2255162922Sariff{ 2256162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2257162922Sariff int rc; 2258162922Sariff 2259162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 2260162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 2261162922Sariff if (rc) { 2262162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 2263162922Sariff return (rc); 2264162922Sariff } 2265162922Sariff hdac_dma_nocache(ch->bdl_dma.dma_vaddr); 2266162922Sariff 2267162922Sariff return (0); 2268162922Sariff} 2269162922Sariff 2270162922Sariffstatic void 2271162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 2272162922Sariff int index, int lmute, int rmute, 2273162922Sariff int left, int right, int dir) 2274162922Sariff{ 2275162922Sariff uint16_t v = 0; 2276162922Sariff 2277162922Sariff if (sc == NULL) 2278162922Sariff return; 2279162922Sariff 2280162922Sariff if (left != right || lmute != rmute) { 2281162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 2282162922Sariff (lmute << 7) | left; 2283162922Sariff hdac_command(sc, 2284164614Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2285162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 2286162922Sariff (rmute << 7) | right; 2287162922Sariff } else 2288162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 2289162922Sariff (lmute << 7) | left; 2290162922Sariff 2291162922Sariff hdac_command(sc, 2292162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 2293162922Sariff} 2294162922Sariff 2295162922Sariffstatic void 2296162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 2297162922Sariff int left, int right) 2298162922Sariff{ 2299162922Sariff struct hdac_softc *sc; 2300162922Sariff nid_t nid, cad; 2301162922Sariff int lmute, rmute; 2302162922Sariff 2303162922Sariff if (ctl == NULL || ctl->widget == NULL || 2304162922Sariff ctl->widget->devinfo == NULL || 2305162922Sariff ctl->widget->devinfo->codec == NULL || 2306162922Sariff ctl->widget->devinfo->codec->sc == NULL) 2307162922Sariff return; 2308162922Sariff 2309162922Sariff sc = ctl->widget->devinfo->codec->sc; 2310162922Sariff cad = ctl->widget->devinfo->codec->cad; 2311162922Sariff nid = ctl->widget->nid; 2312162922Sariff 2313162922Sariff if (mute == HDA_AMP_MUTE_DEFAULT) { 2314162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 2315162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 2316162922Sariff } else { 2317162922Sariff lmute = HDA_AMP_LEFT_MUTED(mute); 2318162922Sariff rmute = HDA_AMP_RIGHT_MUTED(mute); 2319162922Sariff } 2320162922Sariff 2321162922Sariff if (ctl->dir & HDA_CTL_OUT) 2322162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2323162922Sariff lmute, rmute, left, right, 0); 2324162922Sariff if (ctl->dir & HDA_CTL_IN) 2325162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2326162922Sariff lmute, rmute, left, right, 1); 2327162922Sariff ctl->left = left; 2328162922Sariff ctl->right = right; 2329162922Sariff} 2330162922Sariff 2331162922Sariffstatic void 2332162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 2333162922Sariff{ 2334162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 2335162922Sariff return; 2336162922Sariff hdac_command(w->devinfo->codec->sc, 2337162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 2338162922Sariff w->nid, index), w->devinfo->codec->cad); 2339162922Sariff w->selconn = index; 2340162922Sariff} 2341162922Sariff 2342162922Sariff 2343162922Sariff/**************************************************************************** 2344162922Sariff * uint32_t hdac_command_sendone_internal 2345162922Sariff * 2346162922Sariff * Wrapper function that sends only one command to a given codec 2347162922Sariff ****************************************************************************/ 2348162922Sariffstatic uint32_t 2349162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 2350162922Sariff{ 2351162922Sariff struct hdac_command_list cl; 2352162965Sariff uint32_t response = HDAC_INVALID; 2353162922Sariff 2354163057Sariff if (!hdac_lockowned(sc)) 2355162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 2356162922Sariff cl.num_commands = 1; 2357162922Sariff cl.verbs = &verb; 2358162922Sariff cl.responses = &response; 2359162922Sariff 2360162922Sariff hdac_command_send_internal(sc, &cl, cad); 2361162922Sariff 2362162922Sariff return (response); 2363162922Sariff} 2364162922Sariff 2365162922Sariff/**************************************************************************** 2366162922Sariff * hdac_command_send_internal 2367162922Sariff * 2368162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 2369162922Sariff * we can and msleep on the codec. When the interrupt get the responses 2370162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 2371162922Sariff * if any. 2372162922Sariff ****************************************************************************/ 2373162922Sariffstatic void 2374162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 2375162922Sariff struct hdac_command_list *commands, nid_t cad) 2376162922Sariff{ 2377162922Sariff struct hdac_codec *codec; 2378162922Sariff int corbrp; 2379162922Sariff uint32_t *corb; 2380162922Sariff int timeout; 2381162922Sariff int retry = 10; 2382164614Sariff struct hdac_rirb *rirb_base; 2383162922Sariff 2384164614Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL || 2385164614Sariff commands->num_commands < 1) 2386162922Sariff return; 2387162922Sariff 2388162922Sariff codec = sc->codecs[cad]; 2389162922Sariff codec->commands = commands; 2390162922Sariff codec->responses_received = 0; 2391162922Sariff codec->verbs_sent = 0; 2392162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 2393162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2394162922Sariff 2395162922Sariff do { 2396162922Sariff if (codec->verbs_sent != commands->num_commands) { 2397162922Sariff /* Queue as many verbs as possible */ 2398162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 2399162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2400162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 2401162922Sariff while (codec->verbs_sent != commands->num_commands && 2402162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 2403162922Sariff sc->corb_wp++; 2404162922Sariff sc->corb_wp %= sc->corb_size; 2405162922Sariff corb[sc->corb_wp] = 2406162922Sariff commands->verbs[codec->verbs_sent++]; 2407162922Sariff } 2408162922Sariff 2409162922Sariff /* Send the verbs to the codecs */ 2410162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2411162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 2412162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 2413162922Sariff } 2414162922Sariff 2415162922Sariff timeout = 1000; 2416164614Sariff while (hdac_rirb_flush(sc) == 0 && --timeout) 2417162922Sariff DELAY(10); 2418162922Sariff } while ((codec->verbs_sent != commands->num_commands || 2419164614Sariff codec->responses_received != commands->num_commands) && --retry); 2420162922Sariff 2421162922Sariff if (retry == 0) 2422162922Sariff device_printf(sc->dev, 2423164614Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 2424164614Sariff __func__, commands->num_commands, codec->verbs_sent, 2425164614Sariff codec->responses_received); 2426162922Sariff 2427164614Sariff codec->commands = NULL; 2428164614Sariff codec->responses_received = 0; 2429162922Sariff codec->verbs_sent = 0; 2430162922Sariff 2431164614Sariff hdac_unsolq_flush(sc); 2432162922Sariff} 2433162922Sariff 2434162922Sariff 2435162922Sariff/**************************************************************************** 2436162922Sariff * Device Methods 2437162922Sariff ****************************************************************************/ 2438162922Sariff 2439162922Sariff/**************************************************************************** 2440162922Sariff * int hdac_probe(device_t) 2441162922Sariff * 2442162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 2443162922Sariff * match using the subclass of the device. 2444162922Sariff ****************************************************************************/ 2445162922Sariffstatic int 2446162922Sariffhdac_probe(device_t dev) 2447162922Sariff{ 2448162922Sariff int i, result; 2449163257Sariff uint32_t model; 2450163257Sariff uint16_t class, subclass; 2451162922Sariff char desc[64]; 2452162922Sariff 2453162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 2454162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 2455162922Sariff class = pci_get_class(dev); 2456162922Sariff subclass = pci_get_subclass(dev); 2457162922Sariff 2458162922Sariff bzero(desc, sizeof(desc)); 2459162922Sariff result = ENXIO; 2460162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 2461162922Sariff if (hdac_devices[i].model == model) { 2462162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 2463162922Sariff result = BUS_PROBE_DEFAULT; 2464162922Sariff break; 2465162922Sariff } 2466163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 2467162922Sariff class == PCIC_MULTIMEDIA && 2468162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 2469162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 2470162922Sariff result = BUS_PROBE_GENERIC; 2471162922Sariff break; 2472162922Sariff } 2473162922Sariff } 2474162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 2475162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 2476162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 2477162922Sariff result = BUS_PROBE_GENERIC; 2478162922Sariff } 2479162922Sariff if (result != ENXIO) { 2480162922Sariff strlcat(desc, " High Definition Audio Controller", 2481162922Sariff sizeof(desc)); 2482162922Sariff device_set_desc_copy(dev, desc); 2483162922Sariff } 2484162922Sariff 2485162922Sariff return (result); 2486162922Sariff} 2487162922Sariff 2488162922Sariffstatic void * 2489162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 2490162922Sariff struct pcm_channel *c, int dir) 2491162922Sariff{ 2492162922Sariff struct hdac_devinfo *devinfo = data; 2493162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2494162922Sariff struct hdac_chan *ch; 2495162922Sariff 2496162922Sariff hdac_lock(sc); 2497162922Sariff if (dir == PCMDIR_PLAY) { 2498162922Sariff ch = &sc->play; 2499162922Sariff ch->off = (sc->num_iss + devinfo->function.audio.playcnt) << 5; 2500162922Sariff ch->dir = PCMDIR_PLAY; 2501162922Sariff ch->sid = ++sc->streamcnt; 2502162922Sariff devinfo->function.audio.playcnt++; 2503162922Sariff } else { 2504162922Sariff ch = &sc->rec; 2505162922Sariff ch->off = devinfo->function.audio.reccnt << 5; 2506162922Sariff ch->dir = PCMDIR_REC; 2507162922Sariff ch->sid = ++sc->streamcnt; 2508162922Sariff devinfo->function.audio.reccnt++; 2509162922Sariff } 2510162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 2511162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 2512162922Sariff ch->pcmrates[0] = 48000; 2513162922Sariff ch->pcmrates[1] = 0; 2514162922Sariff } 2515162922Sariff ch->b = b; 2516162922Sariff ch->c = c; 2517162922Sariff ch->devinfo = devinfo; 2518162922Sariff ch->blksz = sc->chan_size / sc->chan_blkcnt; 2519162922Sariff ch->blkcnt = sc->chan_blkcnt; 2520162922Sariff hdac_unlock(sc); 2521162922Sariff 2522162922Sariff if (hdac_bdl_alloc(ch) != 0) { 2523162922Sariff ch->blkcnt = 0; 2524162922Sariff return (NULL); 2525162922Sariff } 2526162922Sariff 2527162922Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, sc->chan_size) != 0) 2528162922Sariff return (NULL); 2529162922Sariff 2530162922Sariff hdac_dma_nocache(ch->b->buf); 2531162922Sariff 2532162922Sariff return (ch); 2533162922Sariff} 2534162922Sariff 2535162922Sariffstatic int 2536162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 2537162922Sariff{ 2538162922Sariff struct hdac_chan *ch = data; 2539162922Sariff int i; 2540162922Sariff 2541162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 2542162922Sariff if (format == ch->caps.fmtlist[i]) { 2543162922Sariff ch->fmt = format; 2544162922Sariff return (0); 2545162922Sariff } 2546162922Sariff } 2547162922Sariff 2548162922Sariff return (EINVAL); 2549162922Sariff} 2550162922Sariff 2551162922Sariffstatic int 2552162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 2553162922Sariff{ 2554162922Sariff struct hdac_chan *ch = data; 2555164614Sariff uint32_t spd = 0, threshold; 2556162922Sariff int i; 2557162922Sariff 2558162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 2559162922Sariff spd = ch->pcmrates[i]; 2560164614Sariff threshold = spd + ((ch->pcmrates[i + 1] != 0) ? 2561164614Sariff ((ch->pcmrates[i + 1] - spd) >> 1) : 0); 2562164614Sariff if (speed < threshold) 2563162922Sariff break; 2564162922Sariff } 2565162922Sariff 2566164614Sariff if (spd == 0) /* impossible */ 2567162922Sariff ch->spd = 48000; 2568162922Sariff else 2569162922Sariff ch->spd = spd; 2570162922Sariff 2571162922Sariff return (ch->spd); 2572162922Sariff} 2573162922Sariff 2574162922Sariffstatic void 2575162922Sariffhdac_stream_setup(struct hdac_chan *ch) 2576162922Sariff{ 2577162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2578162922Sariff int i; 2579162922Sariff nid_t cad = ch->devinfo->codec->cad; 2580162922Sariff uint16_t fmt; 2581162922Sariff 2582162922Sariff fmt = 0; 2583162922Sariff if (ch->fmt & AFMT_S16_LE) 2584162922Sariff fmt |= ch->bit16 << 4; 2585162922Sariff else if (ch->fmt & AFMT_S32_LE) 2586162922Sariff fmt |= ch->bit32 << 4; 2587162922Sariff else 2588162922Sariff fmt |= 1 << 4; 2589162922Sariff 2590162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 2591162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 2592162922Sariff fmt |= hda_rate_tab[i].base; 2593162922Sariff fmt |= hda_rate_tab[i].mul; 2594162922Sariff fmt |= hda_rate_tab[i].div; 2595162922Sariff break; 2596162922Sariff } 2597162922Sariff } 2598162922Sariff 2599162922Sariff if (ch->fmt & AFMT_STEREO) 2600162922Sariff fmt |= 1; 2601162922Sariff 2602162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 2603162922Sariff 2604162922Sariff for (i = 0; ch->io[i] != -1; i++) { 2605163057Sariff HDA_BOOTVERBOSE( 2606162922Sariff device_printf(sc->dev, 2607163057Sariff "HDA_DEBUG: PCMDIR_%s: Stream setup nid=%d " 2608163057Sariff "fmt=0x%08x\n", 2609162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 2610162922Sariff ch->io[i], fmt); 2611162922Sariff ); 2612162922Sariff hdac_command(sc, 2613162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 2614162922Sariff hdac_command(sc, 2615162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 2616162922Sariff ch->sid << 4), cad); 2617162922Sariff } 2618162922Sariff} 2619162922Sariff 2620162922Sariffstatic int 2621164614Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz) 2622162922Sariff{ 2623162922Sariff struct hdac_chan *ch = data; 2624164614Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2625162922Sariff 2626164614Sariff blksz &= ~0x7f; 2627164614Sariff if (blksz < 0x80) 2628164614Sariff blksz = 0x80; 2629162922Sariff 2630164614Sariff if ((blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->b)) 2631164614Sariff blksz = sndbuf_getmaxsize(ch->b) / ch->blkcnt; 2632164614Sariff 2633164614Sariff if ((sndbuf_getblksz(ch->b) != blksz || 2634164614Sariff sndbuf_getblkcnt(ch->b) != ch->blkcnt) && 2635164614Sariff sndbuf_resize(ch->b, ch->blkcnt, blksz) != 0) 2636164614Sariff device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", 2637164614Sariff __func__, blksz, ch->blkcnt); 2638164614Sariff 2639164614Sariff ch->blksz = sndbuf_getblksz(ch->b); 2640164614Sariff 2641162922Sariff return (ch->blksz); 2642162922Sariff} 2643162922Sariff 2644162922Sariffstatic void 2645162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 2646162922Sariff{ 2647162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 2648162922Sariff nid_t cad = devinfo->codec->cad; 2649162922Sariff int i; 2650162922Sariff 2651162922Sariff hdac_stream_stop(ch); 2652162922Sariff 2653162922Sariff for (i = 0; ch->io[i] != -1; i++) { 2654162922Sariff hdac_command(sc, 2655162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 2656162922Sariff 0), cad); 2657162922Sariff } 2658162922Sariff} 2659162922Sariff 2660162922Sariffstatic void 2661162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 2662162922Sariff{ 2663162922Sariff ch->ptr = 0; 2664162922Sariff ch->prevptr = 0; 2665162922Sariff hdac_stream_stop(ch); 2666162922Sariff hdac_stream_reset(ch); 2667162922Sariff hdac_bdl_setup(ch); 2668162922Sariff hdac_stream_setid(ch); 2669162922Sariff hdac_stream_setup(ch); 2670162922Sariff hdac_stream_start(ch); 2671162922Sariff} 2672162922Sariff 2673162922Sariffstatic int 2674162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 2675162922Sariff{ 2676162922Sariff struct hdac_chan *ch = data; 2677162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2678162922Sariff 2679162922Sariff hdac_lock(sc); 2680162922Sariff switch (go) { 2681162922Sariff case PCMTRIG_START: 2682162922Sariff hdac_channel_start(sc, ch); 2683162922Sariff break; 2684162922Sariff case PCMTRIG_STOP: 2685162922Sariff case PCMTRIG_ABORT: 2686162922Sariff hdac_channel_stop(sc, ch); 2687162922Sariff break; 2688162922Sariff } 2689162922Sariff hdac_unlock(sc); 2690162922Sariff 2691162922Sariff return (0); 2692162922Sariff} 2693162922Sariff 2694162922Sariffstatic int 2695162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 2696162922Sariff{ 2697162922Sariff struct hdac_chan *ch = data; 2698162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2699162922Sariff uint32_t ptr; 2700162922Sariff 2701162922Sariff hdac_lock(sc); 2702164614Sariff if (sc->polling != 0) 2703164614Sariff ptr = ch->ptr; 2704164614Sariff else 2705164614Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 2706162922Sariff hdac_unlock(sc); 2707162922Sariff 2708164614Sariff /* 2709164614Sariff * Round to available space and force 128 bytes aligment. 2710164614Sariff */ 2711164614Sariff ptr %= ch->blksz * ch->blkcnt; 2712164614Sariff ptr &= ~0x7f; 2713162922Sariff 2714162922Sariff return (ptr); 2715162922Sariff} 2716162922Sariff 2717162922Sariffstatic struct pcmchan_caps * 2718162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 2719162922Sariff{ 2720162922Sariff return (&((struct hdac_chan *)data)->caps); 2721162922Sariff} 2722162922Sariff 2723162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 2724162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 2725162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 2726162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 2727162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 2728162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 2729162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 2730162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 2731162922Sariff { 0, 0 } 2732162922Sariff}; 2733162922SariffCHANNEL_DECLARE(hdac_channel); 2734162922Sariff 2735162922Sariffstatic int 2736162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 2737162922Sariff{ 2738162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 2739162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2740162922Sariff struct hdac_widget *w, *cw; 2741162922Sariff struct hdac_audio_ctl *ctl; 2742162922Sariff uint32_t mask, recmask, id; 2743162922Sariff int i, j, softpcmvol; 2744162922Sariff nid_t cad; 2745162922Sariff 2746162922Sariff hdac_lock(sc); 2747162922Sariff 2748162922Sariff mask = 0; 2749162922Sariff recmask = 0; 2750162922Sariff 2751162922Sariff id = hdac_codec_id(devinfo); 2752162922Sariff cad = devinfo->codec->cad; 2753162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 2754163257Sariff if (!(HDA_DEV_MATCH(hdac_hp_switch[i].model, 2755162965Sariff sc->pci_subvendor) && 2756162922Sariff hdac_hp_switch[i].id == id)) 2757162922Sariff continue; 2758162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 2759162922Sariff if (w != NULL && w->enable != 0 2760162922Sariff && w->type == 2761162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 2762162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 2763162922Sariff hdac_command(sc, 2764162922Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, 2765162922Sariff w->nid, 2766162922Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE| 2767162922Sariff HDAC_UNSOLTAG_EVENT_HP), cad); 2768162922Sariff hdac_hp_switch_handler(devinfo); 2769163057Sariff HDA_BOOTVERBOSE( 2770163057Sariff device_printf(sc->dev, 2771163057Sariff "HDA_DEBUG: Enabling headphone/speaker " 2772163057Sariff "audio routing switching:\n"); 2773163057Sariff device_printf(sc->dev, 2774163057Sariff "HDA_DEBUG: \tindex=%d nid=%d " 2775163057Sariff "pci_subvendor=0x%08x " 2776163057Sariff "codec=0x%08x\n", 2777163057Sariff i, w->nid, sc->pci_subvendor, id); 2778163057Sariff ); 2779162922Sariff } 2780162922Sariff break; 2781162922Sariff } 2782162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 2783163257Sariff if (!(HDA_DEV_MATCH(hdac_eapd_switch[i].model, 2784162965Sariff sc->pci_subvendor) && 2785162965Sariff hdac_eapd_switch[i].id == id)) 2786162922Sariff continue; 2787162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 2788162922Sariff if (w == NULL || w->enable == 0) 2789162922Sariff break; 2790162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 2791162965Sariff w->param.eapdbtl == HDAC_INVALID) 2792162922Sariff break; 2793162922Sariff mask |= SOUND_MASK_OGAIN; 2794162922Sariff break; 2795162922Sariff } 2796162922Sariff 2797162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 2798162922Sariff w = hdac_widget_get(devinfo, i); 2799162922Sariff if (w == NULL || w->enable == 0) 2800162922Sariff continue; 2801162922Sariff mask |= w->ctlflags; 2802162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 2803162922Sariff continue; 2804162922Sariff for (j = 0; j < w->nconns; j++) { 2805162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 2806162922Sariff if (cw == NULL || cw->enable == 0) 2807162922Sariff continue; 2808162922Sariff recmask |= cw->ctlflags; 2809162922Sariff } 2810162922Sariff } 2811162922Sariff 2812162922Sariff if (!(mask & SOUND_MASK_PCM)) { 2813162922Sariff softpcmvol = 1; 2814162922Sariff mask |= SOUND_MASK_PCM; 2815163057Sariff } else 2816163057Sariff softpcmvol = (devinfo->function.audio.quirks & 2817163057Sariff HDA_QUIRK_SOFTPCMVOL) ? 1 : 0; 2818162922Sariff 2819162922Sariff i = 0; 2820162922Sariff ctl = NULL; 2821162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 2822162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 2823162922Sariff continue; 2824162922Sariff if (!(ctl->ossmask & SOUND_MASK_PCM)) 2825162922Sariff continue; 2826162922Sariff if (ctl->step > 0) 2827162922Sariff break; 2828162922Sariff } 2829162922Sariff 2830162922Sariff if (softpcmvol == 1 || ctl == NULL) { 2831162922Sariff struct snddev_info *d = NULL; 2832162922Sariff d = device_get_softc(sc->dev); 2833162922Sariff if (d != NULL) { 2834162922Sariff d->flags |= SD_F_SOFTPCMVOL; 2835163057Sariff HDA_BOOTVERBOSE( 2836162922Sariff device_printf(sc->dev, 2837163057Sariff "HDA_DEBUG: %s Soft PCM volume\n", 2838162922Sariff (softpcmvol == 1) ? 2839162922Sariff "Forcing" : "Enabling"); 2840162922Sariff ); 2841162922Sariff } 2842162922Sariff i = 0; 2843162922Sariff /* 2844162922Sariff * XXX Temporary quirk for STAC9220, until the parser 2845162922Sariff * become smarter. 2846162922Sariff */ 2847162922Sariff if (id == HDA_CODEC_STAC9220) { 2848162922Sariff mask |= SOUND_MASK_VOLUME; 2849162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 2850162922Sariff NULL) { 2851162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 2852162922Sariff continue; 2853162922Sariff if (ctl->widget->nid == 11 && ctl->index == 0) { 2854162922Sariff ctl->ossmask = SOUND_MASK_VOLUME; 2855162922Sariff ctl->ossval = 100 | (100 << 8); 2856162922Sariff } else 2857162922Sariff ctl->ossmask &= ~SOUND_MASK_VOLUME; 2858162922Sariff } 2859162922Sariff } else { 2860162922Sariff mix_setparentchild(m, SOUND_MIXER_VOLUME, 2861162922Sariff SOUND_MASK_PCM); 2862162922Sariff if (!(mask & SOUND_MASK_VOLUME)) 2863162922Sariff mix_setrealdev(m, SOUND_MIXER_VOLUME, 2864162922Sariff SOUND_MIXER_NONE); 2865162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 2866162922Sariff NULL) { 2867162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 2868162922Sariff continue; 2869163057Sariff if (!HDA_FLAG_MATCH(ctl->ossmask, 2870163057Sariff SOUND_MASK_VOLUME | SOUND_MASK_PCM)) 2871162922Sariff continue; 2872162922Sariff if (!(ctl->mute == 1 && ctl->step == 0)) 2873162922Sariff ctl->enable = 0; 2874162922Sariff } 2875162922Sariff } 2876162922Sariff } 2877162922Sariff 2878162922Sariff recmask &= ~(SOUND_MASK_PCM | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER); 2879162922Sariff 2880162922Sariff mix_setrecdevs(m, recmask); 2881162922Sariff mix_setdevs(m, mask); 2882162922Sariff 2883162922Sariff hdac_unlock(sc); 2884162922Sariff 2885162922Sariff return (0); 2886162922Sariff} 2887162922Sariff 2888162922Sariffstatic int 2889162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 2890162922Sariff unsigned left, unsigned right) 2891162922Sariff{ 2892162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 2893162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2894162922Sariff struct hdac_widget *w; 2895162922Sariff struct hdac_audio_ctl *ctl; 2896162922Sariff uint32_t id, mute; 2897162922Sariff int lvol, rvol, mlvol, mrvol; 2898162922Sariff int i = 0; 2899162922Sariff 2900162922Sariff hdac_lock(sc); 2901162922Sariff if (dev == SOUND_MIXER_OGAIN) { 2902163257Sariff uint32_t orig; 2903162922Sariff /*if (left != right || !(left == 0 || left == 1)) { 2904162922Sariff hdac_unlock(sc); 2905162922Sariff return (-1); 2906162922Sariff }*/ 2907162922Sariff id = hdac_codec_id(devinfo); 2908162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 2909163257Sariff if (HDA_DEV_MATCH(hdac_eapd_switch[i].model, 2910162965Sariff sc->pci_subvendor) && 2911162922Sariff hdac_eapd_switch[i].id == id) 2912162922Sariff break; 2913162922Sariff } 2914162922Sariff if (i >= HDAC_EAPD_SWITCH_LEN) { 2915162922Sariff hdac_unlock(sc); 2916162922Sariff return (-1); 2917162922Sariff } 2918162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 2919162922Sariff if (w == NULL || 2920162922Sariff w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 2921162965Sariff w->param.eapdbtl == HDAC_INVALID) { 2922162922Sariff hdac_unlock(sc); 2923162922Sariff return (-1); 2924162922Sariff } 2925163257Sariff orig = w->param.eapdbtl; 2926163432Sariff if (left == 0) 2927162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2928162922Sariff else 2929162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2930163257Sariff if (orig != w->param.eapdbtl) { 2931163432Sariff uint32_t val; 2932163432Sariff 2933163257Sariff if (hdac_eapd_switch[i].hp_switch != 0) 2934163257Sariff hdac_hp_switch_handler(devinfo); 2935163432Sariff val = w->param.eapdbtl; 2936163432Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV) 2937163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2938163257Sariff hdac_command(sc, 2939163257Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, 2940163432Sariff w->nid, val), devinfo->codec->cad); 2941163257Sariff } 2942162922Sariff hdac_unlock(sc); 2943162922Sariff return (left | (left << 8)); 2944162922Sariff } 2945162922Sariff if (dev == SOUND_MIXER_VOLUME) 2946162922Sariff devinfo->function.audio.mvol = left | (right << 8); 2947162922Sariff 2948162922Sariff mlvol = devinfo->function.audio.mvol & 0x7f; 2949162922Sariff mrvol = (devinfo->function.audio.mvol >> 8) & 0x7f; 2950162922Sariff lvol = 0; 2951162922Sariff rvol = 0; 2952162922Sariff 2953162922Sariff i = 0; 2954162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 2955162922Sariff if (ctl->widget == NULL || ctl->enable == 0 || 2956162922Sariff !(ctl->ossmask & (1 << dev))) 2957162922Sariff continue; 2958162922Sariff switch (dev) { 2959162922Sariff case SOUND_MIXER_VOLUME: 2960162922Sariff lvol = ((ctl->ossval & 0x7f) * left) / 100; 2961162922Sariff lvol = (lvol * ctl->step) / 100; 2962162922Sariff rvol = (((ctl->ossval >> 8) & 0x7f) * right) / 100; 2963162922Sariff rvol = (rvol * ctl->step) / 100; 2964162922Sariff break; 2965162922Sariff default: 2966162922Sariff if (ctl->ossmask & SOUND_MASK_VOLUME) { 2967162922Sariff lvol = (left * mlvol) / 100; 2968162922Sariff lvol = (lvol * ctl->step) / 100; 2969162922Sariff rvol = (right * mrvol) / 100; 2970162922Sariff rvol = (rvol * ctl->step) / 100; 2971162922Sariff } else { 2972162922Sariff lvol = (left * ctl->step) / 100; 2973162922Sariff rvol = (right * ctl->step) / 100; 2974162922Sariff } 2975162922Sariff ctl->ossval = left | (right << 8); 2976162922Sariff break; 2977162922Sariff } 2978162922Sariff mute = 0; 2979162922Sariff if (ctl->step < 1) { 2980162922Sariff mute |= (left == 0) ? HDA_AMP_MUTE_LEFT : 2981162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 2982162922Sariff mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 2983162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 2984162922Sariff } else { 2985162922Sariff mute |= (lvol == 0) ? HDA_AMP_MUTE_LEFT : 2986162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 2987162922Sariff mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 2988162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 2989162922Sariff } 2990162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 2991162922Sariff } 2992162922Sariff hdac_unlock(sc); 2993162922Sariff 2994162922Sariff return (left | (right << 8)); 2995162922Sariff} 2996162922Sariff 2997162922Sariffstatic int 2998162922Sariffhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 2999162922Sariff{ 3000162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 3001162922Sariff struct hdac_widget *w, *cw; 3002162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3003162922Sariff uint32_t ret = src, target; 3004162922Sariff int i, j; 3005162922Sariff 3006162922Sariff target = 0; 3007162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 3008162922Sariff if (src & (1 << i)) { 3009162922Sariff target = 1 << i; 3010162922Sariff break; 3011162922Sariff } 3012162922Sariff } 3013162922Sariff 3014162922Sariff hdac_lock(sc); 3015162922Sariff 3016162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3017162922Sariff w = hdac_widget_get(devinfo, i); 3018162965Sariff if (w == NULL || w->enable == 0) 3019162922Sariff continue; 3020162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 3021162922Sariff continue; 3022162922Sariff for (j = 0; j < w->nconns; j++) { 3023162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3024162922Sariff if (cw == NULL || cw->enable == 0) 3025162922Sariff continue; 3026162922Sariff if ((target == SOUND_MASK_VOLUME && 3027162922Sariff cw->type != 3028162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 3029162922Sariff (target != SOUND_MASK_VOLUME && 3030162922Sariff cw->type == 3031162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)) 3032162922Sariff continue; 3033162922Sariff if (cw->ctlflags & target) { 3034162922Sariff hdac_widget_connection_select(w, j); 3035162922Sariff ret = target; 3036162922Sariff j += w->nconns; 3037162922Sariff } 3038162922Sariff } 3039162922Sariff } 3040162922Sariff 3041162922Sariff hdac_unlock(sc); 3042162922Sariff 3043162922Sariff return (ret); 3044162922Sariff} 3045162922Sariff 3046162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 3047162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 3048162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 3049162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 3050162922Sariff { 0, 0 } 3051162922Sariff}; 3052162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 3053162922Sariff 3054162922Sariff/**************************************************************************** 3055162922Sariff * int hdac_attach(device_t) 3056162922Sariff * 3057162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 3058162922Sariff * when this function is called. Setup everything that doesn't require 3059162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 3060162922Sariff ****************************************************************************/ 3061162922Sariffstatic int 3062162922Sariffhdac_attach(device_t dev) 3063162922Sariff{ 3064162922Sariff struct hdac_softc *sc; 3065162922Sariff int result; 3066162922Sariff int i = 0; 3067162922Sariff 3068162922Sariff sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO); 3069162922Sariff if (sc == NULL) { 3070162922Sariff device_printf(dev, "cannot allocate softc\n"); 3071162922Sariff return (ENOMEM); 3072162922Sariff } 3073163057Sariff 3074163057Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 3075163057Sariff if (sc->lock == NULL) { 3076163057Sariff device_printf(dev, "mutex creation failed\n"); 3077163057Sariff free(sc, M_DEVBUF); 3078163057Sariff return (ENOMEM); 3079163057Sariff } 3080163057Sariff 3081162922Sariff sc->dev = dev; 3082163257Sariff sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16; 3083163257Sariff sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff; 3084162922Sariff 3085164614Sariff callout_init(&sc->poll_hda, CALLOUT_MPSAFE); 3086164614Sariff callout_init(&sc->poll_hdac, CALLOUT_MPSAFE); 3087164614Sariff 3088164614Sariff sc->poll_ticks = 1; 3089164614Sariff if (resource_int_value(device_get_name(sc->dev), 3090164614Sariff device_get_unit(sc->dev), "polling", &i) == 0 && i != 0) 3091164614Sariff sc->polling = 1; 3092164614Sariff else 3093164614Sariff sc->polling = 0; 3094164614Sariff 3095162922Sariff sc->chan_size = pcm_getbuffersize(dev, 3096164614Sariff HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX); 3097164614Sariff 3098162922Sariff if (resource_int_value(device_get_name(sc->dev), 3099164614Sariff device_get_unit(sc->dev), "blocksize", &i) == 0 && i > 0) { 3100164614Sariff i &= ~0x7f; 3101164614Sariff if (i < 0x80) 3102164614Sariff i = 0x80; 3103162922Sariff sc->chan_blkcnt = sc->chan_size / i; 3104162922Sariff i = 0; 3105162922Sariff while (sc->chan_blkcnt >> i) 3106162922Sariff i++; 3107162922Sariff sc->chan_blkcnt = 1 << (i - 1); 3108162922Sariff if (sc->chan_blkcnt < HDA_BDL_MIN) 3109162922Sariff sc->chan_blkcnt = HDA_BDL_MIN; 3110162922Sariff else if (sc->chan_blkcnt > HDA_BDL_MAX) 3111162922Sariff sc->chan_blkcnt = HDA_BDL_MAX; 3112162922Sariff } else 3113162922Sariff sc->chan_blkcnt = HDA_BDL_DEFAULT; 3114162922Sariff 3115162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 3116162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 3117162922Sariff 0, /* boundary */ 3118162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 3119162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 3120162922Sariff NULL, /* filtfunc */ 3121162922Sariff NULL, /* fistfuncarg */ 3122162922Sariff sc->chan_size, /* maxsize */ 3123162922Sariff 1, /* nsegments */ 3124162922Sariff sc->chan_size, /* maxsegsz */ 3125162922Sariff 0, /* flags */ 3126162922Sariff NULL, /* lockfunc */ 3127162922Sariff NULL, /* lockfuncarg */ 3128162922Sariff &sc->chan_dmat); /* dmat */ 3129162922Sariff if (result != 0) { 3130162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 3131162922Sariff __func__, result); 3132163057Sariff snd_mtxfree(sc->lock); 3133162922Sariff free(sc, M_DEVBUF); 3134162922Sariff return (ENXIO); 3135162922Sariff } 3136162922Sariff 3137162922Sariff 3138162922Sariff sc->hdabus = NULL; 3139162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 3140162922Sariff sc->codecs[i] = NULL; 3141162922Sariff 3142162922Sariff pci_enable_busmaster(dev); 3143162922Sariff 3144162922Sariff /* Allocate resources */ 3145162922Sariff result = hdac_mem_alloc(sc); 3146162922Sariff if (result != 0) 3147163057Sariff goto hdac_attach_fail; 3148162922Sariff result = hdac_irq_alloc(sc); 3149162922Sariff if (result != 0) 3150163057Sariff goto hdac_attach_fail; 3151162922Sariff 3152162922Sariff /* Get Capabilities */ 3153162922Sariff result = hdac_get_capabilities(sc); 3154162922Sariff if (result != 0) 3155163057Sariff goto hdac_attach_fail; 3156162922Sariff 3157162922Sariff /* Allocate CORB and RIRB dma memory */ 3158162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 3159162922Sariff sc->corb_size * sizeof(uint32_t)); 3160162922Sariff if (result != 0) 3161163057Sariff goto hdac_attach_fail; 3162162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 3163162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 3164162922Sariff if (result != 0) 3165163057Sariff goto hdac_attach_fail; 3166162922Sariff 3167162922Sariff /* Quiesce everything */ 3168162922Sariff hdac_reset(sc); 3169162922Sariff 3170162922Sariff /* Disable PCI-Express QOS */ 3171162922Sariff pci_write_config(sc->dev, 0x44, 3172162922Sariff pci_read_config(sc->dev, 0x44, 1) & 0xf8, 1); 3173162922Sariff 3174162922Sariff /* Initialize the CORB and RIRB */ 3175162922Sariff hdac_corb_init(sc); 3176162922Sariff hdac_rirb_init(sc); 3177162922Sariff 3178162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 3179162922Sariff sc->intrhook.ich_func = hdac_attach2; 3180162922Sariff sc->intrhook.ich_arg = (void *)sc; 3181162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 3182162922Sariff sc->intrhook.ich_func = NULL; 3183162922Sariff hdac_attach2((void *)sc); 3184162922Sariff } 3185162922Sariff 3186163057Sariff return (0); 3187162922Sariff 3188163057Sariffhdac_attach_fail: 3189162922Sariff hdac_dma_free(&sc->rirb_dma); 3190162922Sariff hdac_dma_free(&sc->corb_dma); 3191162922Sariff hdac_irq_free(sc); 3192162922Sariff hdac_mem_free(sc); 3193162922Sariff snd_mtxfree(sc->lock); 3194163057Sariff free(sc, M_DEVBUF); 3195162922Sariff 3196163057Sariff return (ENXIO); 3197162922Sariff} 3198162922Sariff 3199162922Sariffstatic void 3200162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 3201162922Sariff{ 3202162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3203162922Sariff struct hdac_widget *w; 3204162922Sariff uint32_t res; 3205162922Sariff int i; 3206162922Sariff nid_t cad, nid; 3207162922Sariff 3208162922Sariff cad = devinfo->codec->cad; 3209162922Sariff nid = devinfo->nid; 3210162922Sariff 3211162922Sariff hdac_command(sc, 3212162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), cad); 3213162922Sariff 3214162922Sariff DELAY(100); 3215162922Sariff 3216162922Sariff res = hdac_command(sc, 3217162922Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 3218162922Sariff 3219162922Sariff devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 3220162922Sariff devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 3221162922Sariff devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 3222162922Sariff 3223163057Sariff HDA_BOOTVERBOSE( 3224162922Sariff device_printf(sc->dev, " Vendor: 0x%08x\n", 3225162922Sariff devinfo->vendor_id); 3226162922Sariff device_printf(sc->dev, " Device: 0x%08x\n", 3227162922Sariff devinfo->device_id); 3228162922Sariff device_printf(sc->dev, " Revision: 0x%08x\n", 3229162922Sariff devinfo->revision_id); 3230162922Sariff device_printf(sc->dev, " Stepping: 0x%08x\n", 3231162922Sariff devinfo->stepping_id); 3232162922Sariff device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 3233162922Sariff sc->pci_subvendor); 3234162922Sariff device_printf(sc->dev, " Nodes: start=%d " 3235162922Sariff "endnode=%d total=%d\n", 3236162922Sariff devinfo->startnode, devinfo->endnode, devinfo->nodecnt); 3237162922Sariff ); 3238162922Sariff 3239162922Sariff res = hdac_command(sc, 3240162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 3241162922Sariff cad); 3242162922Sariff devinfo->function.audio.supp_stream_formats = res; 3243162922Sariff 3244162922Sariff res = hdac_command(sc, 3245162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 3246162922Sariff cad); 3247162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 3248162922Sariff 3249162922Sariff res = hdac_command(sc, 3250162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 3251162922Sariff cad); 3252162922Sariff devinfo->function.audio.outamp_cap = res; 3253162922Sariff 3254162922Sariff res = hdac_command(sc, 3255162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 3256162922Sariff cad); 3257162922Sariff devinfo->function.audio.inamp_cap = res; 3258162922Sariff 3259162922Sariff if (devinfo->nodecnt > 0) { 3260162922Sariff hdac_unlock(sc); 3261162922Sariff devinfo->widget = (struct hdac_widget *)malloc( 3262162922Sariff sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 3263162922Sariff M_NOWAIT | M_ZERO); 3264162922Sariff hdac_lock(sc); 3265162922Sariff } else 3266162922Sariff devinfo->widget = NULL; 3267162922Sariff 3268162922Sariff if (devinfo->widget == NULL) { 3269162922Sariff device_printf(sc->dev, "unable to allocate widgets!\n"); 3270162922Sariff devinfo->endnode = devinfo->startnode; 3271162922Sariff devinfo->nodecnt = 0; 3272162922Sariff return; 3273162922Sariff } 3274162922Sariff 3275162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3276162922Sariff w = hdac_widget_get(devinfo, i); 3277162922Sariff if (w == NULL) 3278162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 3279162922Sariff else { 3280162922Sariff w->devinfo = devinfo; 3281162922Sariff w->nid = i; 3282162922Sariff w->enable = 1; 3283162922Sariff w->selconn = -1; 3284162922Sariff w->pflags = 0; 3285162922Sariff w->ctlflags = 0; 3286162965Sariff w->param.eapdbtl = HDAC_INVALID; 3287162922Sariff hdac_widget_parse(w); 3288162922Sariff } 3289162922Sariff } 3290162922Sariff} 3291162922Sariff 3292162922Sariffstatic void 3293162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 3294162922Sariff{ 3295162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3296162922Sariff struct hdac_audio_ctl *ctls; 3297162922Sariff struct hdac_widget *w, *cw; 3298162922Sariff int i, j, cnt, max, ocap, icap; 3299163057Sariff int mute, offset, step, size; 3300162922Sariff 3301162922Sariff /* XXX This is redundant */ 3302162922Sariff max = 0; 3303162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3304162922Sariff w = hdac_widget_get(devinfo, i); 3305162922Sariff if (w == NULL || w->enable == 0) 3306162922Sariff continue; 3307162922Sariff if (w->param.outamp_cap != 0) 3308162922Sariff max++; 3309162922Sariff if (w->param.inamp_cap != 0) { 3310162922Sariff switch (w->type) { 3311162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3312162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3313162922Sariff for (j = 0; j < w->nconns; j++) { 3314162922Sariff cw = hdac_widget_get(devinfo, 3315162922Sariff w->conns[j]); 3316162922Sariff if (cw == NULL || cw->enable == 0) 3317162922Sariff continue; 3318162922Sariff max++; 3319162922Sariff } 3320162922Sariff break; 3321162922Sariff default: 3322162922Sariff max++; 3323162922Sariff break; 3324162922Sariff } 3325162922Sariff } 3326162922Sariff } 3327162922Sariff 3328162922Sariff devinfo->function.audio.ctlcnt = max; 3329162922Sariff 3330162922Sariff if (max < 1) 3331162922Sariff return; 3332162922Sariff 3333162922Sariff hdac_unlock(sc); 3334162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 3335162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 3336162922Sariff hdac_lock(sc); 3337162922Sariff 3338162922Sariff if (ctls == NULL) { 3339162922Sariff /* Blekh! */ 3340162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 3341162922Sariff devinfo->function.audio.ctlcnt = 0; 3342162922Sariff return; 3343162922Sariff } 3344162922Sariff 3345162922Sariff cnt = 0; 3346162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 3347162922Sariff if (cnt >= max) { 3348162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 3349162922Sariff __func__); 3350162922Sariff break; 3351162922Sariff } 3352162922Sariff w = hdac_widget_get(devinfo, i); 3353162922Sariff if (w == NULL || w->enable == 0) 3354162922Sariff continue; 3355162922Sariff ocap = w->param.outamp_cap; 3356162922Sariff icap = w->param.inamp_cap; 3357162922Sariff if (ocap != 0) { 3358163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 3359163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 3360163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 3361163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 3362163057Sariff /*if (offset > step) { 3363163057Sariff HDA_BOOTVERBOSE( 3364163057Sariff device_printf(sc->dev, 3365163057Sariff "HDA_DEBUG: BUGGY outamp: nid=%d " 3366163057Sariff "[offset=%d > step=%d]\n", 3367163057Sariff w->nid, offset, step); 3368163057Sariff ); 3369163057Sariff offset = step; 3370163057Sariff }*/ 3371162922Sariff ctls[cnt].enable = 1; 3372162922Sariff ctls[cnt].widget = w; 3373163057Sariff ctls[cnt].mute = mute; 3374163057Sariff ctls[cnt].step = step; 3375163057Sariff ctls[cnt].size = size; 3376163057Sariff ctls[cnt].offset = offset; 3377163057Sariff ctls[cnt].left = offset; 3378163057Sariff ctls[cnt].right = offset; 3379162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 3380162922Sariff } 3381162922Sariff 3382162922Sariff if (icap != 0) { 3383163057Sariff mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap); 3384163057Sariff step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap); 3385163057Sariff size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap); 3386163057Sariff offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap); 3387163057Sariff /*if (offset > step) { 3388163057Sariff HDA_BOOTVERBOSE( 3389163057Sariff device_printf(sc->dev, 3390163057Sariff "HDA_DEBUG: BUGGY inamp: nid=%d " 3391163057Sariff "[offset=%d > step=%d]\n", 3392163057Sariff w->nid, offset, step); 3393163057Sariff ); 3394163057Sariff offset = step; 3395163057Sariff }*/ 3396162922Sariff switch (w->type) { 3397162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3398162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3399162922Sariff for (j = 0; j < w->nconns; j++) { 3400162922Sariff if (cnt >= max) { 3401162922Sariff device_printf(sc->dev, 3402162922Sariff "%s: Ctl overflow!\n", 3403162922Sariff __func__); 3404162922Sariff break; 3405162922Sariff } 3406162922Sariff cw = hdac_widget_get(devinfo, 3407162922Sariff w->conns[j]); 3408162922Sariff if (cw == NULL || cw->enable == 0) 3409162922Sariff continue; 3410162922Sariff ctls[cnt].enable = 1; 3411162922Sariff ctls[cnt].widget = w; 3412162922Sariff ctls[cnt].childwidget = cw; 3413162922Sariff ctls[cnt].index = j; 3414163057Sariff ctls[cnt].mute = mute; 3415163057Sariff ctls[cnt].step = step; 3416163057Sariff ctls[cnt].size = size; 3417163057Sariff ctls[cnt].offset = offset; 3418163057Sariff ctls[cnt].left = offset; 3419163057Sariff ctls[cnt].right = offset; 3420162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 3421162922Sariff } 3422162922Sariff break; 3423162922Sariff default: 3424162922Sariff if (cnt >= max) { 3425162922Sariff device_printf(sc->dev, 3426162922Sariff "%s: Ctl overflow!\n", 3427162922Sariff __func__); 3428162922Sariff break; 3429162922Sariff } 3430162922Sariff ctls[cnt].enable = 1; 3431162922Sariff ctls[cnt].widget = w; 3432163057Sariff ctls[cnt].mute = mute; 3433163057Sariff ctls[cnt].step = step; 3434163057Sariff ctls[cnt].size = size; 3435163057Sariff ctls[cnt].offset = offset; 3436163057Sariff ctls[cnt].left = offset; 3437163057Sariff ctls[cnt].right = offset; 3438162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 3439162922Sariff break; 3440162922Sariff } 3441162922Sariff } 3442162922Sariff } 3443162922Sariff 3444162922Sariff devinfo->function.audio.ctl = ctls; 3445162922Sariff} 3446162922Sariff 3447162965Sariffstatic const struct { 3448162965Sariff uint32_t model; 3449162965Sariff uint32_t id; 3450162965Sariff uint32_t set, unset; 3451162965Sariff} hdac_quirks[] = { 3452163057Sariff /* 3453163057Sariff * XXX Force stereo quirk. Monoural recording / playback 3454163057Sariff * on few codecs (especially ALC880) seems broken or 3455163057Sariff * perhaps unsupported. 3456163057Sariff */ 3457163057Sariff { HDA_MATCH_ALL, HDA_MATCH_ALL, 3458164614Sariff HDA_QUIRK_FORCESTEREO, 0 }, 3459162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 3460162965Sariff HDA_QUIRK_GPIO1, 0 }, 3461162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 3462162965Sariff HDA_QUIRK_GPIO1, 0 }, 3463164750Sariff { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, 3464164750Sariff HDA_QUIRK_GPIO2, 0 }, 3465163276Sariff { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, 3466163276Sariff HDA_QUIRK_EAPDINV, 0 }, 3467163432Sariff { ASUS_A8JC_SUBVENDOR, HDA_CODEC_AD1986A, 3468163432Sariff HDA_QUIRK_EAPDINV, 0 }, 3469164657Sariff { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, 3470164614Sariff HDA_QUIRK_EAPDINV, 0 }, 3471164657Sariff { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, 3472164657Sariff HDA_QUIRK_EAPDINV, 0 }, 3473162965Sariff { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 3474162965Sariff 0, HDA_QUIRK_FORCESTEREO }, 3475162965Sariff { HDA_MATCH_ALL, HDA_CODEC_STACXXXX, 3476162965Sariff HDA_QUIRK_SOFTPCMVOL, 0 } 3477162965Sariff}; 3478162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 3479162965Sariff 3480162922Sariffstatic void 3481162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 3482162922Sariff{ 3483162922Sariff struct hdac_widget *w; 3484162965Sariff uint32_t id, subvendor; 3485162922Sariff int i; 3486162922Sariff 3487163057Sariff id = hdac_codec_id(devinfo); 3488163057Sariff subvendor = devinfo->codec->sc->pci_subvendor; 3489163057Sariff 3490162922Sariff /* 3491163057Sariff * Quirks 3492162922Sariff */ 3493163057Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 3494163257Sariff if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) && 3495163257Sariff HDA_DEV_MATCH(hdac_quirks[i].id, id))) 3496163057Sariff continue; 3497163057Sariff if (hdac_quirks[i].set != 0) 3498163057Sariff devinfo->function.audio.quirks |= 3499163057Sariff hdac_quirks[i].set; 3500163057Sariff if (hdac_quirks[i].unset != 0) 3501163057Sariff devinfo->function.audio.quirks &= 3502163057Sariff ~(hdac_quirks[i].unset); 3503163057Sariff } 3504163057Sariff 3505162922Sariff switch (id) { 3506162922Sariff case HDA_CODEC_ALC260: 3507162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3508162922Sariff w = hdac_widget_get(devinfo, i); 3509162922Sariff if (w == NULL || w->enable == 0) 3510162922Sariff continue; 3511162922Sariff if (w->type != 3512162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 3513162922Sariff continue; 3514162922Sariff if (w->nid != 5) 3515162922Sariff w->enable = 0; 3516162922Sariff } 3517162922Sariff break; 3518162922Sariff case HDA_CODEC_ALC880: 3519162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3520162922Sariff w = hdac_widget_get(devinfo, i); 3521162922Sariff if (w == NULL || w->enable == 0) 3522162922Sariff continue; 3523162922Sariff if (w->type == 3524162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 3525162922Sariff w->nid != 9 && w->nid != 29) { 3526162922Sariff w->enable = 0; 3527162922Sariff } else if (w->type != 3528162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET && 3529162922Sariff w->nid == 29) { 3530163057Sariff w->type = 3531163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET; 3532163057Sariff w->param.widget_cap &= 3533163057Sariff ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 3534162922Sariff w->param.widget_cap |= 3535162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 3536162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 3537162922Sariff strlcpy(w->name, "beep widget", sizeof(w->name)); 3538162922Sariff } 3539162922Sariff } 3540162922Sariff break; 3541163257Sariff case HDA_CODEC_AD1981HD: 3542163257Sariff w = hdac_widget_get(devinfo, 11); 3543163257Sariff if (w != NULL && w->enable != 0 && w->nconns > 3) 3544163257Sariff w->selconn = 3; 3545163257Sariff if (subvendor == IBM_M52_SUBVENDOR) { 3546163257Sariff struct hdac_audio_ctl *ctl; 3547163257Sariff 3548163257Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 7, 0, 1); 3549163257Sariff if (ctl != NULL) 3550163257Sariff ctl->ossmask = SOUND_MASK_SPEAKER; 3551163257Sariff } 3552163257Sariff break; 3553162922Sariff case HDA_CODEC_AD1986A: 3554162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3555162922Sariff w = hdac_widget_get(devinfo, i); 3556162922Sariff if (w == NULL || w->enable == 0) 3557162922Sariff continue; 3558162922Sariff if (w->type != 3559162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 3560162922Sariff continue; 3561162922Sariff if (w->nid != 3) 3562162922Sariff w->enable = 0; 3563162922Sariff } 3564162922Sariff break; 3565162922Sariff case HDA_CODEC_STAC9221: 3566162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3567162922Sariff w = hdac_widget_get(devinfo, i); 3568162922Sariff if (w == NULL || w->enable == 0) 3569162922Sariff continue; 3570162922Sariff if (w->type != 3571162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 3572162922Sariff continue; 3573162922Sariff if (w->nid != 2) 3574162922Sariff w->enable = 0; 3575162922Sariff } 3576162922Sariff break; 3577162922Sariff case HDA_CODEC_STAC9221D: 3578162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3579162922Sariff w = hdac_widget_get(devinfo, i); 3580162922Sariff if (w == NULL || w->enable == 0) 3581162922Sariff continue; 3582162922Sariff if (w->type == 3583162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 3584162922Sariff w->nid != 6) 3585162922Sariff w->enable = 0; 3586162922Sariff 3587162922Sariff } 3588162922Sariff break; 3589162922Sariff default: 3590162922Sariff break; 3591162922Sariff } 3592162922Sariff} 3593162922Sariff 3594162922Sariffstatic int 3595162922Sariffhdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *devinfo) 3596162922Sariff{ 3597162922Sariff int *dev = &devinfo->function.audio.ossidx; 3598162922Sariff 3599162922Sariff while (*dev < SOUND_MIXER_NRDEVICES) { 3600162922Sariff switch (*dev) { 3601162922Sariff case SOUND_MIXER_VOLUME: 3602162922Sariff case SOUND_MIXER_BASS: 3603162922Sariff case SOUND_MIXER_TREBLE: 3604162922Sariff case SOUND_MIXER_PCM: 3605162922Sariff case SOUND_MIXER_SPEAKER: 3606162922Sariff case SOUND_MIXER_LINE: 3607162922Sariff case SOUND_MIXER_MIC: 3608162922Sariff case SOUND_MIXER_CD: 3609162922Sariff case SOUND_MIXER_RECLEV: 3610162922Sariff case SOUND_MIXER_OGAIN: /* reserved for EAPD switch */ 3611162922Sariff (*dev)++; 3612162922Sariff break; 3613162922Sariff default: 3614162922Sariff return (*dev)++; 3615162922Sariff break; 3616162922Sariff } 3617162922Sariff } 3618162922Sariff 3619162922Sariff return (-1); 3620162922Sariff} 3621162922Sariff 3622162922Sariffstatic int 3623162922Sariffhdac_widget_find_dac_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3624162922Sariff{ 3625162922Sariff struct hdac_widget *w; 3626162922Sariff int i, ret = 0; 3627162922Sariff 3628162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3629162922Sariff return (0); 3630162922Sariff w = hdac_widget_get(devinfo, nid); 3631162922Sariff if (w == NULL || w->enable == 0) 3632162922Sariff return (0); 3633162922Sariff switch (w->type) { 3634162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 3635162922Sariff w->pflags |= HDA_DAC_PATH; 3636162922Sariff ret = 1; 3637162922Sariff break; 3638162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3639162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3640162922Sariff for (i = 0; i < w->nconns; i++) { 3641162922Sariff if (hdac_widget_find_dac_path(devinfo, 3642162922Sariff w->conns[i], depth + 1) != 0) { 3643162922Sariff if (w->selconn == -1) 3644162922Sariff w->selconn = i; 3645162922Sariff ret = 1; 3646162922Sariff w->pflags |= HDA_DAC_PATH; 3647162922Sariff } 3648162922Sariff } 3649162922Sariff break; 3650162922Sariff default: 3651162922Sariff break; 3652162922Sariff } 3653162922Sariff return (ret); 3654162922Sariff} 3655162922Sariff 3656162922Sariffstatic int 3657162922Sariffhdac_widget_find_adc_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3658162922Sariff{ 3659162922Sariff struct hdac_widget *w; 3660162922Sariff int i, conndev, ret = 0; 3661162922Sariff 3662162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3663162922Sariff return (0); 3664162922Sariff w = hdac_widget_get(devinfo, nid); 3665162922Sariff if (w == NULL || w->enable == 0) 3666162922Sariff return (0); 3667162922Sariff switch (w->type) { 3668162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 3669162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3670162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3671162922Sariff for (i = 0; i < w->nconns; i++) { 3672162922Sariff if (hdac_widget_find_adc_path(devinfo, w->conns[i], 3673162922Sariff depth + 1) != 0) { 3674162922Sariff if (w->selconn == -1) 3675162922Sariff w->selconn = i; 3676162922Sariff w->pflags |= HDA_ADC_PATH; 3677162922Sariff ret = 1; 3678162922Sariff } 3679162922Sariff } 3680162922Sariff break; 3681162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 3682162922Sariff conndev = w->wclass.pin.config & 3683162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 3684162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 3685162922Sariff (conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_CD || 3686162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN || 3687162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN)) { 3688162922Sariff w->pflags |= HDA_ADC_PATH; 3689162922Sariff ret = 1; 3690162922Sariff } 3691162922Sariff break; 3692162922Sariff /*case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3693162922Sariff if (w->pflags & HDA_DAC_PATH) { 3694162922Sariff w->pflags |= HDA_ADC_PATH; 3695162922Sariff ret = 1; 3696162922Sariff } 3697162922Sariff break;*/ 3698162922Sariff default: 3699162922Sariff break; 3700162922Sariff } 3701162922Sariff return (ret); 3702162922Sariff} 3703162922Sariff 3704162922Sariffstatic uint32_t 3705162922Sariffhdac_audio_ctl_outamp_build(struct hdac_devinfo *devinfo, 3706162922Sariff nid_t nid, nid_t pnid, int index, int depth) 3707162922Sariff{ 3708162922Sariff struct hdac_widget *w, *pw; 3709162922Sariff struct hdac_audio_ctl *ctl; 3710162922Sariff uint32_t fl = 0; 3711162922Sariff int i, ossdev, conndev, strategy; 3712162922Sariff 3713162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3714162922Sariff return (0); 3715162922Sariff 3716162922Sariff w = hdac_widget_get(devinfo, nid); 3717162922Sariff if (w == NULL || w->enable == 0) 3718162922Sariff return (0); 3719162922Sariff 3720162922Sariff pw = hdac_widget_get(devinfo, pnid); 3721162922Sariff strategy = devinfo->function.audio.parsing_strategy; 3722162922Sariff 3723162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER 3724162922Sariff || w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) { 3725162922Sariff for (i = 0; i < w->nconns; i++) { 3726162922Sariff fl |= hdac_audio_ctl_outamp_build(devinfo, w->conns[i], 3727162922Sariff w->nid, i, depth + 1); 3728162922Sariff } 3729162922Sariff w->ctlflags |= fl; 3730162922Sariff return (fl); 3731162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT && 3732162922Sariff (w->pflags & HDA_DAC_PATH)) { 3733162922Sariff i = 0; 3734162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3735162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3736162922Sariff continue; 3737163057Sariff /* XXX This should be compressed! */ 3738162922Sariff if ((ctl->widget->nid == w->nid) || 3739162922Sariff (ctl->widget->nid == pnid && ctl->index == index && 3740162922Sariff (ctl->dir & HDA_CTL_IN)) || 3741162922Sariff (ctl->widget->nid == pnid && pw != NULL && 3742162922Sariff pw->type == 3743162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 3744162922Sariff (pw->nconns < 2 || pw->selconn == index || 3745162922Sariff pw->selconn == -1) && 3746162922Sariff (ctl->dir & HDA_CTL_OUT)) || 3747162922Sariff (strategy == HDA_PARSE_DIRECT && 3748162922Sariff ctl->widget->nid == w->nid)) { 3749163057Sariff /*if (pw != NULL && pw->selconn == -1) 3750162922Sariff pw->selconn = index; 3751162922Sariff fl |= SOUND_MASK_VOLUME; 3752162922Sariff fl |= SOUND_MASK_PCM; 3753162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3754162922Sariff ctl->ossmask |= SOUND_MASK_PCM; 3755163057Sariff ctl->ossdev = SOUND_MIXER_PCM;*/ 3756163057Sariff if (!(w->ctlflags & SOUND_MASK_PCM) || 3757163057Sariff (pw != NULL && 3758163057Sariff !(pw->ctlflags & SOUND_MASK_PCM))) { 3759163057Sariff fl |= SOUND_MASK_VOLUME; 3760163057Sariff fl |= SOUND_MASK_PCM; 3761163057Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3762163057Sariff ctl->ossmask |= SOUND_MASK_PCM; 3763163057Sariff ctl->ossdev = SOUND_MIXER_PCM; 3764163057Sariff w->ctlflags |= SOUND_MASK_VOLUME; 3765163057Sariff w->ctlflags |= SOUND_MASK_PCM; 3766163057Sariff if (pw != NULL) { 3767163057Sariff if (pw->selconn == -1) 3768163057Sariff pw->selconn = index; 3769163057Sariff pw->ctlflags |= 3770163057Sariff SOUND_MASK_VOLUME; 3771163057Sariff pw->ctlflags |= 3772163057Sariff SOUND_MASK_PCM; 3773163057Sariff } 3774163057Sariff } 3775162922Sariff } 3776162922Sariff } 3777162922Sariff w->ctlflags |= fl; 3778162922Sariff return (fl); 3779164614Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 3780164614Sariff HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 3781162922Sariff (w->pflags & HDA_ADC_PATH)) { 3782162922Sariff conndev = w->wclass.pin.config & 3783162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 3784162922Sariff i = 0; 3785162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3786162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3787162922Sariff continue; 3788163057Sariff /* XXX This should be compressed! */ 3789162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 3790162922Sariff (ctl->dir & HDA_CTL_IN)) || 3791162922Sariff (ctl->widget->nid == pnid && pw != NULL && 3792162922Sariff pw->type == 3793162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 3794162922Sariff (pw->nconns < 2 || pw->selconn == index || 3795162922Sariff pw->selconn == -1) && 3796162922Sariff (ctl->dir & HDA_CTL_OUT)) || 3797162922Sariff (strategy == HDA_PARSE_DIRECT && 3798162922Sariff ctl->widget->nid == w->nid)) && 3799163057Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 3800162922Sariff if (pw != NULL && pw->selconn == -1) 3801162922Sariff pw->selconn = index; 3802162922Sariff ossdev = 0; 3803162922Sariff switch (conndev) { 3804162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 3805162922Sariff ossdev = SOUND_MIXER_MIC; 3806162922Sariff break; 3807162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 3808162922Sariff ossdev = SOUND_MIXER_LINE; 3809162922Sariff break; 3810162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 3811162922Sariff ossdev = SOUND_MIXER_CD; 3812162922Sariff break; 3813162922Sariff default: 3814162922Sariff ossdev = 3815162922Sariff hdac_audio_ctl_ossmixer_getnextdev( 3816162922Sariff devinfo); 3817162922Sariff if (ossdev < 0) 3818162922Sariff ossdev = 0; 3819162922Sariff break; 3820162922Sariff } 3821162922Sariff if (strategy == HDA_PARSE_MIXER) { 3822162922Sariff fl |= SOUND_MASK_VOLUME; 3823162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3824162922Sariff } 3825162922Sariff fl |= 1 << ossdev; 3826162922Sariff ctl->ossmask |= 1 << ossdev; 3827162922Sariff ctl->ossdev = ossdev; 3828162922Sariff } 3829162922Sariff } 3830162922Sariff w->ctlflags |= fl; 3831162922Sariff return (fl); 3832162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 3833162922Sariff i = 0; 3834162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3835162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3836162922Sariff continue; 3837163057Sariff /* XXX This should be compressed! */ 3838162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 3839162922Sariff (ctl->dir & HDA_CTL_IN)) || 3840162922Sariff (ctl->widget->nid == pnid && pw != NULL && 3841162922Sariff pw->type == 3842162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 3843162922Sariff (pw->nconns < 2 || pw->selconn == index || 3844162922Sariff pw->selconn == -1) && 3845162922Sariff (ctl->dir & HDA_CTL_OUT)) || 3846162922Sariff (strategy == HDA_PARSE_DIRECT && 3847162922Sariff ctl->widget->nid == w->nid)) && 3848163057Sariff !(ctl->ossmask & ~SOUND_MASK_VOLUME)) { 3849162922Sariff if (pw != NULL && pw->selconn == -1) 3850162922Sariff pw->selconn = index; 3851162922Sariff fl |= SOUND_MASK_VOLUME; 3852162922Sariff fl |= SOUND_MASK_SPEAKER; 3853162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3854162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 3855162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 3856162922Sariff } 3857162922Sariff } 3858162922Sariff w->ctlflags |= fl; 3859162922Sariff return (fl); 3860162922Sariff } 3861162922Sariff return (0); 3862162922Sariff} 3863162922Sariff 3864162922Sariffstatic uint32_t 3865162922Sariffhdac_audio_ctl_inamp_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3866162922Sariff{ 3867162922Sariff struct hdac_widget *w, *cw; 3868162922Sariff struct hdac_audio_ctl *ctl; 3869162922Sariff uint32_t fl; 3870162922Sariff int i; 3871162922Sariff 3872162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3873162922Sariff return (0); 3874162922Sariff 3875162922Sariff w = hdac_widget_get(devinfo, nid); 3876162922Sariff if (w == NULL || w->enable == 0) 3877162922Sariff return (0); 3878162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 3879162922Sariff return (0); 3880162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 3881162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 3882162922Sariff return (0);*/ 3883162922Sariff i = 0; 3884162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3885162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3886162922Sariff continue; 3887162922Sariff if (ctl->widget->nid == nid) { 3888162922Sariff ctl->ossmask |= SOUND_MASK_RECLEV; 3889162922Sariff w->ctlflags |= SOUND_MASK_RECLEV; 3890162922Sariff return (SOUND_MASK_RECLEV); 3891162922Sariff } 3892162922Sariff } 3893162922Sariff for (i = 0; i < w->nconns; i++) { 3894162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 3895162922Sariff if (cw == NULL || cw->enable == 0) 3896162922Sariff continue; 3897162922Sariff if (cw->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 3898162922Sariff continue; 3899162922Sariff fl = hdac_audio_ctl_inamp_build(devinfo, cw->nid, depth + 1); 3900162922Sariff if (fl != 0) { 3901162922Sariff cw->ctlflags |= fl; 3902162922Sariff w->ctlflags |= fl; 3903162922Sariff return (fl); 3904162922Sariff } 3905162922Sariff } 3906162922Sariff return (0); 3907162922Sariff} 3908162922Sariff 3909162922Sariffstatic int 3910162922Sariffhdac_audio_ctl_recsel_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3911162922Sariff{ 3912162922Sariff struct hdac_widget *w, *cw; 3913162922Sariff int i, child = 0; 3914162922Sariff 3915162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3916162922Sariff return (0); 3917162922Sariff 3918162922Sariff w = hdac_widget_get(devinfo, nid); 3919162922Sariff if (w == NULL || w->enable == 0) 3920162922Sariff return (0); 3921162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 3922162922Sariff return (0); 3923162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 3924162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 3925162922Sariff return (0);*/ 3926162922Sariff /* XXX weak! */ 3927162922Sariff for (i = 0; i < w->nconns; i++) { 3928162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 3929162922Sariff if (cw == NULL) 3930162922Sariff continue; 3931162922Sariff if (++child > 1) { 3932162922Sariff w->pflags |= HDA_ADC_RECSEL; 3933162922Sariff return (1); 3934162922Sariff } 3935162922Sariff } 3936162922Sariff for (i = 0; i < w->nconns; i++) { 3937162922Sariff if (hdac_audio_ctl_recsel_build(devinfo, 3938162922Sariff w->conns[i], depth + 1) != 0) 3939162922Sariff return (1); 3940162922Sariff } 3941162922Sariff return (0); 3942162922Sariff} 3943162922Sariff 3944162922Sariffstatic int 3945162922Sariffhdac_audio_build_tree_strategy(struct hdac_devinfo *devinfo) 3946162922Sariff{ 3947162922Sariff struct hdac_widget *w, *cw; 3948162922Sariff int i, j, conndev, found_dac = 0; 3949162922Sariff int strategy; 3950162922Sariff 3951162922Sariff strategy = devinfo->function.audio.parsing_strategy; 3952162922Sariff 3953162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3954162922Sariff w = hdac_widget_get(devinfo, i); 3955162922Sariff if (w == NULL || w->enable == 0) 3956162922Sariff continue; 3957162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 3958162922Sariff continue; 3959162922Sariff if (!HDA_PARAM_PIN_CAP_OUTPUT_CAP(w->wclass.pin.cap)) 3960162922Sariff continue; 3961162922Sariff conndev = w->wclass.pin.config & 3962162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 3963162922Sariff if (!(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 3964162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 3965162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT)) 3966162922Sariff continue; 3967162922Sariff for (j = 0; j < w->nconns; j++) { 3968162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3969162922Sariff if (cw == NULL || cw->enable == 0) 3970162922Sariff continue; 3971162922Sariff if (strategy == HDA_PARSE_MIXER && !(cw->type == 3972162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 3973162922Sariff cw->type == 3974162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 3975162922Sariff continue; 3976162922Sariff if (hdac_widget_find_dac_path(devinfo, cw->nid, 0) 3977162922Sariff != 0) { 3978162922Sariff if (w->selconn == -1) 3979162922Sariff w->selconn = j; 3980162922Sariff w->pflags |= HDA_DAC_PATH; 3981162922Sariff found_dac++; 3982162922Sariff } 3983162922Sariff } 3984162922Sariff } 3985162922Sariff 3986162922Sariff return (found_dac); 3987162922Sariff} 3988162922Sariff 3989162922Sariffstatic void 3990162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 3991162922Sariff{ 3992162922Sariff struct hdac_widget *w; 3993162922Sariff struct hdac_audio_ctl *ctl; 3994162922Sariff int i, j, dacs, strategy; 3995162922Sariff 3996162922Sariff /* Construct DAC path */ 3997162922Sariff strategy = HDA_PARSE_MIXER; 3998162922Sariff devinfo->function.audio.parsing_strategy = strategy; 3999163057Sariff HDA_BOOTVERBOSE( 4000162922Sariff device_printf(devinfo->codec->sc->dev, 4001163057Sariff "HDA_DEBUG: HWiP: HDA Widget Parser - Revision %d\n", 4002162922Sariff HDA_WIDGET_PARSER_REV); 4003162922Sariff ); 4004162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 4005162922Sariff if (dacs == 0) { 4006163057Sariff HDA_BOOTVERBOSE( 4007162922Sariff device_printf(devinfo->codec->sc->dev, 4008163057Sariff "HDA_DEBUG: HWiP: 0 DAC path found! " 4009163057Sariff "Retrying parser " 4010162922Sariff "using HDA_PARSE_DIRECT strategy.\n"); 4011162922Sariff ); 4012162922Sariff strategy = HDA_PARSE_DIRECT; 4013162922Sariff devinfo->function.audio.parsing_strategy = strategy; 4014162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 4015162922Sariff } 4016162922Sariff 4017163057Sariff HDA_BOOTVERBOSE( 4018162922Sariff device_printf(devinfo->codec->sc->dev, 4019163057Sariff "HDA_DEBUG: HWiP: Found %d DAC path using HDA_PARSE_%s " 4020163057Sariff "strategy.\n", 4021162922Sariff dacs, (strategy == HDA_PARSE_MIXER) ? "MIXER" : "DIRECT"); 4022162922Sariff ); 4023162922Sariff 4024162922Sariff /* Construct ADC path */ 4025162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4026162922Sariff w = hdac_widget_get(devinfo, i); 4027162922Sariff if (w == NULL || w->enable == 0) 4028162922Sariff continue; 4029162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 4030162922Sariff continue; 4031162922Sariff (void)hdac_widget_find_adc_path(devinfo, w->nid, 0); 4032162922Sariff } 4033162922Sariff 4034162922Sariff /* Output mixers */ 4035162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4036162922Sariff w = hdac_widget_get(devinfo, i); 4037162922Sariff if (w == NULL || w->enable == 0) 4038162922Sariff continue; 4039162922Sariff if ((strategy == HDA_PARSE_MIXER && 4040162922Sariff (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 4041162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 4042162922Sariff && (w->pflags & HDA_DAC_PATH)) || 4043162922Sariff (strategy == HDA_PARSE_DIRECT && (w->pflags & 4044162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)))) { 4045162922Sariff w->ctlflags |= hdac_audio_ctl_outamp_build(devinfo, 4046162922Sariff w->nid, devinfo->startnode - 1, 0, 0); 4047162922Sariff } else if (w->type == 4048162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 4049162922Sariff j = 0; 4050162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &j)) != 4051162922Sariff NULL) { 4052162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 4053162922Sariff continue; 4054162922Sariff if (ctl->widget->nid != w->nid) 4055162922Sariff continue; 4056162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 4057162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 4058162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 4059162922Sariff w->ctlflags |= SOUND_MASK_VOLUME; 4060162922Sariff w->ctlflags |= SOUND_MASK_SPEAKER; 4061162922Sariff } 4062162922Sariff } 4063162922Sariff } 4064162922Sariff 4065162922Sariff /* Input mixers (rec) */ 4066162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4067162922Sariff w = hdac_widget_get(devinfo, i); 4068162922Sariff if (w == NULL || w->enable == 0) 4069162922Sariff continue; 4070162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 4071162922Sariff w->pflags & HDA_ADC_PATH)) 4072162922Sariff continue; 4073162922Sariff hdac_audio_ctl_inamp_build(devinfo, w->nid, 0); 4074162922Sariff hdac_audio_ctl_recsel_build(devinfo, w->nid, 0); 4075162922Sariff } 4076162922Sariff} 4077162922Sariff 4078162922Sariff#define HDA_COMMIT_CONN (1 << 0) 4079162922Sariff#define HDA_COMMIT_CTRL (1 << 1) 4080162922Sariff#define HDA_COMMIT_EAPD (1 << 2) 4081162922Sariff#define HDA_COMMIT_GPIO (1 << 3) 4082162922Sariff#define HDA_COMMIT_ALL (HDA_COMMIT_CONN | HDA_COMMIT_CTRL | \ 4083162922Sariff HDA_COMMIT_EAPD | HDA_COMMIT_GPIO) 4084162922Sariff 4085162922Sariffstatic void 4086162922Sariffhdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl) 4087162922Sariff{ 4088162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4089162922Sariff struct hdac_widget *w; 4090164750Sariff nid_t cad; 4091164750Sariff int i; 4092162922Sariff 4093162922Sariff if (!(cfl & HDA_COMMIT_ALL)) 4094162922Sariff return; 4095162922Sariff 4096162922Sariff cad = devinfo->codec->cad; 4097162922Sariff 4098163057Sariff if (cfl & HDA_COMMIT_GPIO) { 4099164828Sariff if (sc->pci_subvendor == APPLE_INTEL_MAC) { 4100164828Sariff uint32_t gdata, gmask, gdir; 4101164828Sariff 4102164828Sariff gdata = hdac_command(sc, 4103164828Sariff HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), 4104163057Sariff cad); 4105164828Sariff gmask = hdac_command(sc, 4106164828Sariff HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), 4107163057Sariff cad); 4108164828Sariff gdir = hdac_command(sc, 4109164828Sariff HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), 4110164828Sariff cad); 4111164828Sariff gdata |= 0x03; 4112164828Sariff gmask |= 0x03; 4113164828Sariff gdir |= 0x03; 4114164828Sariff hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 4115164828Sariff 0x7e7, 0), cad); 4116162922Sariff hdac_command(sc, 4117164828Sariff HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, 4118164828Sariff gmask), cad); 4119164828Sariff hdac_command(sc, 4120164828Sariff HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid, 4121164828Sariff gdir), cad); 4122164828Sariff hdac_command(sc, 4123164828Sariff HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 4124164828Sariff gdata), cad); 4125164828Sariff } else { 4126164828Sariff for (i = 0; i < HDA_GPIO_MAX; i++) { 4127164828Sariff if (!(devinfo->function.audio.quirks & 4128164828Sariff (1 << i))) 4129164828Sariff continue; 4130164828Sariff hdac_command(sc, 4131164828Sariff HDA_CMD_SET_GPIO_ENABLE_MASK(cad, 4132164828Sariff devinfo->nid, i), cad); 4133164828Sariff hdac_command(sc, 4134164828Sariff HDA_CMD_SET_GPIO_DIRECTION(cad, 4135164828Sariff devinfo->nid, i), cad); 4136164828Sariff hdac_command(sc, 4137164828Sariff HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, 4138164828Sariff i), cad); 4139164828Sariff } 4140162922Sariff } 4141162922Sariff } 4142162922Sariff 4143162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 4144162922Sariff w = &devinfo->widget[i]; 4145162922Sariff if (w == NULL || w->enable == 0) 4146162922Sariff continue; 4147162922Sariff if (cfl & HDA_COMMIT_CONN) { 4148162922Sariff if (w->selconn == -1) 4149162922Sariff w->selconn = 0; 4150162922Sariff if (w->nconns > 0) 4151162922Sariff hdac_widget_connection_select(w, w->selconn); 4152162922Sariff } 4153162922Sariff if ((cfl & HDA_COMMIT_CTRL) && 4154162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 4155162922Sariff if ((w->pflags & (HDA_DAC_PATH | HDA_ADC_PATH)) == 4156162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)) 4157162922Sariff device_printf(sc->dev, "WARNING: node %d " 4158162922Sariff "participate both for DAC/ADC!\n", w->nid); 4159162922Sariff if (w->pflags & HDA_DAC_PATH) { 4160162922Sariff w->wclass.pin.ctrl &= 4161162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 4162162922Sariff if ((w->wclass.pin.config & 4163162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) != 4164162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 4165162922Sariff w->wclass.pin.ctrl &= 4166162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 4167162922Sariff } else if (w->pflags & HDA_ADC_PATH) { 4168162922Sariff w->wclass.pin.ctrl &= 4169162922Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 4170162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE); 4171162922Sariff } else 4172162922Sariff w->wclass.pin.ctrl &= ~( 4173162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 4174162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 4175162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE); 4176162922Sariff hdac_command(sc, 4177162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 4178162922Sariff w->wclass.pin.ctrl), cad); 4179162922Sariff } 4180162922Sariff if ((cfl & HDA_COMMIT_EAPD) && 4181163276Sariff w->param.eapdbtl != HDAC_INVALID) { 4182163432Sariff uint32_t val; 4183163432Sariff 4184163432Sariff val = w->param.eapdbtl; 4185163276Sariff if (devinfo->function.audio.quirks & 4186163432Sariff HDA_QUIRK_EAPDINV) 4187163432Sariff val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 4188162922Sariff hdac_command(sc, 4189162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 4190163432Sariff val), cad); 4191162922Sariff 4192163276Sariff } 4193162922Sariff DELAY(1000); 4194162922Sariff } 4195162922Sariff} 4196162922Sariff 4197162922Sariffstatic void 4198162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 4199162922Sariff{ 4200162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4201162922Sariff struct hdac_audio_ctl *ctl; 4202162922Sariff int i; 4203162922Sariff 4204162922Sariff devinfo->function.audio.mvol = 100 | (100 << 8); 4205162922Sariff i = 0; 4206162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4207162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) { 4208163057Sariff HDA_BOOTVERBOSE( 4209162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 4210162922Sariff i, (ctl->widget != NULL) ? 4211162922Sariff ctl->widget->nid : -1); 4212162922Sariff if (ctl->childwidget != NULL) 4213162922Sariff printf(" childnid=%d", 4214162922Sariff ctl->childwidget->nid); 4215162922Sariff if (ctl->widget == NULL) 4216162922Sariff printf(" NULL WIDGET!"); 4217162922Sariff printf(" DISABLED\n"); 4218162922Sariff ); 4219162922Sariff continue; 4220162922Sariff } 4221163057Sariff HDA_BOOTVERBOSE( 4222162922Sariff if (ctl->ossmask == 0) { 4223162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 4224162922Sariff i, ctl->widget->nid); 4225162922Sariff if (ctl->childwidget != NULL) 4226162922Sariff printf(" childnid=%d", 4227162922Sariff ctl->childwidget->nid); 4228162922Sariff printf(" Bind to NONE\n"); 4229162922Sariff } 4230162922Sariff ); 4231162922Sariff if (ctl->step > 0) { 4232162922Sariff ctl->ossval = (ctl->left * 100) / ctl->step; 4233162922Sariff ctl->ossval |= ((ctl->right * 100) / ctl->step) << 8; 4234162922Sariff } else 4235162922Sariff ctl->ossval = 0; 4236162922Sariff hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT, 4237162922Sariff ctl->left, ctl->right); 4238162922Sariff } 4239162922Sariff} 4240162922Sariff 4241162922Sariffstatic int 4242162922Sariffhdac_pcmchannel_setup(struct hdac_devinfo *devinfo, int dir) 4243162922Sariff{ 4244162922Sariff struct hdac_chan *ch; 4245162922Sariff struct hdac_widget *w; 4246162922Sariff uint32_t cap, fmtcap, pcmcap, path; 4247162922Sariff int i, type, ret, max; 4248162922Sariff 4249162922Sariff if (dir == PCMDIR_PLAY) { 4250162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT; 4251162922Sariff ch = &devinfo->codec->sc->play; 4252162922Sariff path = HDA_DAC_PATH; 4253162922Sariff } else { 4254162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT; 4255162922Sariff ch = &devinfo->codec->sc->rec; 4256162922Sariff path = HDA_ADC_PATH; 4257162922Sariff } 4258162922Sariff 4259162922Sariff ch->caps = hdac_caps; 4260162922Sariff ch->caps.fmtlist = ch->fmtlist; 4261162922Sariff ch->bit16 = 1; 4262162922Sariff ch->bit32 = 0; 4263162922Sariff ch->pcmrates[0] = 48000; 4264162922Sariff ch->pcmrates[1] = 0; 4265162922Sariff 4266162922Sariff ret = 0; 4267162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 4268162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 4269162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 4270162922Sariff 4271162922Sariff for (i = devinfo->startnode; i < devinfo->endnode && ret < max; i++) { 4272162922Sariff w = hdac_widget_get(devinfo, i); 4273162922Sariff if (w == NULL || w->enable == 0 || w->type != type || 4274163057Sariff !(w->pflags & path)) 4275162922Sariff continue; 4276162922Sariff cap = w->param.widget_cap; 4277162922Sariff /*if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(cap)) 4278162922Sariff continue;*/ 4279162922Sariff if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(cap)) 4280162922Sariff continue; 4281162922Sariff cap = w->param.supp_stream_formats; 4282162922Sariff /*if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) { 4283162922Sariff } 4284162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 4285162922Sariff }*/ 4286162922Sariff if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 4287162922Sariff continue; 4288164614Sariff if (ret == 0) { 4289164614Sariff fmtcap = w->param.supp_stream_formats; 4290164614Sariff pcmcap = w->param.supp_pcm_size_rate; 4291164614Sariff } else { 4292164614Sariff fmtcap &= w->param.supp_stream_formats; 4293164614Sariff pcmcap &= w->param.supp_pcm_size_rate; 4294164614Sariff } 4295162922Sariff ch->io[ret++] = i; 4296162922Sariff } 4297162922Sariff ch->io[ret] = -1; 4298162922Sariff 4299162922Sariff ch->supp_stream_formats = fmtcap; 4300162922Sariff ch->supp_pcm_size_rate = pcmcap; 4301162922Sariff 4302162922Sariff /* 4303162922Sariff * 8bit = 0 4304162922Sariff * 16bit = 1 4305162922Sariff * 20bit = 2 4306162922Sariff * 24bit = 3 4307162922Sariff * 32bit = 4 4308162922Sariff */ 4309162922Sariff if (ret > 0) { 4310162922Sariff cap = pcmcap; 4311162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 4312162922Sariff ch->bit16 = 1; 4313162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 4314162922Sariff ch->bit16 = 0; 4315162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 4316162922Sariff ch->bit32 = 4; 4317162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 4318162922Sariff ch->bit32 = 3; 4319162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 4320162922Sariff ch->bit32 = 2; 4321162922Sariff i = 0; 4322162922Sariff if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 4323162922Sariff ch->fmtlist[i++] = AFMT_S16_LE; 4324162922Sariff ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 4325162922Sariff if (ch->bit32 > 0) { 4326162922Sariff if (!(devinfo->function.audio.quirks & 4327162922Sariff HDA_QUIRK_FORCESTEREO)) 4328162922Sariff ch->fmtlist[i++] = AFMT_S32_LE; 4329162922Sariff ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 4330162922Sariff } 4331162922Sariff ch->fmtlist[i] = 0; 4332162922Sariff i = 0; 4333162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 4334162922Sariff ch->pcmrates[i++] = 8000; 4335162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 4336162922Sariff ch->pcmrates[i++] = 11025; 4337162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 4338162922Sariff ch->pcmrates[i++] = 16000; 4339162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 4340162922Sariff ch->pcmrates[i++] = 22050; 4341162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 4342162922Sariff ch->pcmrates[i++] = 32000; 4343162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 4344162922Sariff ch->pcmrates[i++] = 44100; 4345162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(cap)) */ 4346162922Sariff ch->pcmrates[i++] = 48000; 4347162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 4348162922Sariff ch->pcmrates[i++] = 88200; 4349162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 4350162922Sariff ch->pcmrates[i++] = 96000; 4351162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 4352162922Sariff ch->pcmrates[i++] = 176400; 4353162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 4354162922Sariff ch->pcmrates[i++] = 192000; 4355162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(cap)) */ 4356162922Sariff ch->pcmrates[i] = 0; 4357162922Sariff if (i > 0) { 4358162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 4359162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 4360162922Sariff } 4361162922Sariff } 4362162922Sariff 4363162922Sariff return (ret); 4364162922Sariff} 4365162922Sariff 4366162922Sariffstatic void 4367162922Sariffhdac_dump_ctls(struct hdac_devinfo *devinfo, const char *banner, uint32_t flag) 4368162922Sariff{ 4369162922Sariff struct hdac_audio_ctl *ctl; 4370162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4371162922Sariff int i; 4372162922Sariff uint32_t fl = 0; 4373162922Sariff 4374162922Sariff 4375162922Sariff if (flag == 0) { 4376162922Sariff fl = SOUND_MASK_VOLUME | SOUND_MASK_PCM | 4377162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 4378162922Sariff SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN; 4379162922Sariff } 4380162922Sariff 4381162922Sariff i = 0; 4382162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4383162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 4384162922Sariff ctl->widget->enable == 0) 4385162922Sariff continue; 4386162922Sariff if ((flag == 0 && (ctl->ossmask & ~fl)) || 4387162922Sariff (flag != 0 && (ctl->ossmask & flag))) { 4388162922Sariff if (banner != NULL) { 4389162922Sariff device_printf(sc->dev, "\n"); 4390162922Sariff device_printf(sc->dev, "%s\n", banner); 4391162922Sariff } 4392162922Sariff goto hdac_ctl_dump_it_all; 4393162922Sariff } 4394162922Sariff } 4395162922Sariff 4396162922Sariff return; 4397162922Sariff 4398162922Sariffhdac_ctl_dump_it_all: 4399162922Sariff i = 0; 4400162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4401162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 4402162922Sariff ctl->widget->enable == 0) 4403162922Sariff continue; 4404162922Sariff if (!((flag == 0 && (ctl->ossmask & ~fl)) || 4405162922Sariff (flag != 0 && (ctl->ossmask & flag)))) 4406162922Sariff continue; 4407162922Sariff if (flag == 0) { 4408162922Sariff device_printf(sc->dev, "\n"); 4409162922Sariff device_printf(sc->dev, "Unknown Ctl (OSS: %s)\n", 4410162922Sariff hdac_audio_ctl_ossmixer_mask2name(ctl->ossmask)); 4411162922Sariff } 4412162922Sariff device_printf(sc->dev, " |\n"); 4413162922Sariff device_printf(sc->dev, " +- nid: %2d index: %2d ", 4414162922Sariff ctl->widget->nid, ctl->index); 4415162922Sariff if (ctl->childwidget != NULL) 4416162922Sariff printf("(nid: %2d) ", ctl->childwidget->nid); 4417162922Sariff else 4418162922Sariff printf(" "); 4419162922Sariff printf("mute: %d step: %3d size: %3d off: %3d dir=0x%x ossmask=0x%08x\n", 4420162922Sariff ctl->mute, ctl->step, ctl->size, ctl->offset, ctl->dir, 4421162922Sariff ctl->ossmask); 4422162922Sariff } 4423162922Sariff} 4424162922Sariff 4425162922Sariffstatic void 4426162922Sariffhdac_dump_audio_formats(struct hdac_softc *sc, uint32_t fcap, uint32_t pcmcap) 4427162922Sariff{ 4428162922Sariff uint32_t cap; 4429162922Sariff 4430162922Sariff cap = fcap; 4431162922Sariff if (cap != 0) { 4432162922Sariff device_printf(sc->dev, " Stream cap: 0x%08x\n", cap); 4433162922Sariff device_printf(sc->dev, " Format:"); 4434162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 4435162922Sariff printf(" AC3"); 4436162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 4437162922Sariff printf(" FLOAT32"); 4438162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 4439162922Sariff printf(" PCM"); 4440162922Sariff printf("\n"); 4441162922Sariff } 4442162922Sariff cap = pcmcap; 4443162922Sariff if (cap != 0) { 4444162922Sariff device_printf(sc->dev, " PCM cap: 0x%08x\n", cap); 4445162922Sariff device_printf(sc->dev, " PCM size:"); 4446162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 4447162922Sariff printf(" 8"); 4448162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 4449162922Sariff printf(" 16"); 4450162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 4451162922Sariff printf(" 20"); 4452162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 4453162922Sariff printf(" 24"); 4454162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 4455162922Sariff printf(" 32"); 4456162922Sariff printf("\n"); 4457162922Sariff device_printf(sc->dev, " PCM rate:"); 4458162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 4459162922Sariff printf(" 8"); 4460162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 4461162922Sariff printf(" 11"); 4462162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 4463162922Sariff printf(" 16"); 4464162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 4465162922Sariff printf(" 22"); 4466162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 4467162922Sariff printf(" 32"); 4468162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 4469162922Sariff printf(" 44"); 4470162922Sariff printf(" 48"); 4471162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 4472162922Sariff printf(" 88"); 4473162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 4474162922Sariff printf(" 96"); 4475162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 4476162922Sariff printf(" 176"); 4477162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 4478162922Sariff printf(" 192"); 4479162922Sariff printf("\n"); 4480162922Sariff } 4481162922Sariff} 4482162922Sariff 4483162922Sariffstatic void 4484162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 4485162922Sariff{ 4486162922Sariff uint32_t pincap, wcap; 4487162922Sariff 4488162922Sariff pincap = w->wclass.pin.cap; 4489162922Sariff wcap = w->param.widget_cap; 4490162922Sariff 4491162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 4492162922Sariff device_printf(sc->dev, " "); 4493162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 4494162922Sariff printf(" ISC"); 4495162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 4496162922Sariff printf(" TRQD"); 4497162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 4498162922Sariff printf(" PDC"); 4499162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 4500162922Sariff printf(" HP"); 4501162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 4502162922Sariff printf(" OUT"); 4503162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 4504162922Sariff printf(" IN"); 4505162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 4506162922Sariff printf(" BAL"); 4507162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 4508162922Sariff printf(" EAPD"); 4509162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(wcap)) 4510162922Sariff printf(" : UNSOL"); 4511162922Sariff printf("\n"); 4512162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 4513162922Sariff w->wclass.pin.config); 4514162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 4515162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 4516162922Sariff printf(" HP"); 4517162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 4518162922Sariff printf(" IN"); 4519162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 4520162922Sariff printf(" OUT"); 4521162922Sariff printf("\n"); 4522162922Sariff} 4523162922Sariff 4524162922Sariffstatic void 4525162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 4526162922Sariff{ 4527163057Sariff device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap); 4528162922Sariff device_printf(sc->dev, " " 4529162922Sariff "mute=%d step=%d size=%d offset=%d\n", 4530162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 4531162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 4532162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 4533162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 4534162922Sariff} 4535162922Sariff 4536162922Sariffstatic void 4537162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 4538162922Sariff{ 4539162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4540162922Sariff struct hdac_widget *w, *cw; 4541162922Sariff int i, j; 4542162922Sariff 4543162922Sariff device_printf(sc->dev, "\n"); 4544162922Sariff device_printf(sc->dev, "Default Parameter\n"); 4545162922Sariff device_printf(sc->dev, "-----------------\n"); 4546162922Sariff hdac_dump_audio_formats(sc, 4547162922Sariff devinfo->function.audio.supp_stream_formats, 4548162922Sariff devinfo->function.audio.supp_pcm_size_rate); 4549162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 4550162922Sariff devinfo->function.audio.inamp_cap); 4551162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 4552162922Sariff devinfo->function.audio.outamp_cap); 4553162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4554162922Sariff w = hdac_widget_get(devinfo, i); 4555162922Sariff if (w == NULL) { 4556162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 4557162922Sariff continue; 4558162922Sariff } 4559162922Sariff device_printf(sc->dev, "\n"); 4560162922Sariff device_printf(sc->dev, " nid: %d [%s]%s\n", w->nid, 4561162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) ? 4562162922Sariff "DIGITAL" : "ANALOG", 4563162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 4564162922Sariff device_printf(sc->dev, " name: %s\n", w->name); 4565162922Sariff device_printf(sc->dev, " widget_cap: 0x%08x\n", 4566162922Sariff w->param.widget_cap); 4567162922Sariff device_printf(sc->dev, " Parse flags: 0x%08x\n", 4568162922Sariff w->pflags); 4569162922Sariff device_printf(sc->dev, " Ctl flags: 0x%08x\n", 4570162922Sariff w->ctlflags); 4571162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 4572162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 4573162922Sariff hdac_dump_audio_formats(sc, 4574162922Sariff w->param.supp_stream_formats, 4575162922Sariff w->param.supp_pcm_size_rate); 4576162922Sariff } else if (w->type == 4577162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4578162922Sariff hdac_dump_pin(sc, w); 4579162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 4580162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 4581162922Sariff w->param.eapdbtl); 4582163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) && 4583163057Sariff w->param.outamp_cap != 0) 4584162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 4585163057Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) && 4586163057Sariff w->param.inamp_cap != 0) 4587162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 4588162922Sariff device_printf(sc->dev, " connections: %d\n", w->nconns); 4589162922Sariff for (j = 0; j < w->nconns; j++) { 4590162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 4591162922Sariff device_printf(sc->dev, " |\n"); 4592162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 4593162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 4594162922Sariff if (cw == NULL) 4595162922Sariff printf(" [UNKNOWN]"); 4596162922Sariff else if (cw->enable == 0) 4597162922Sariff printf(" [DISABLED]"); 4598162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 4599162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 4600162922Sariff printf(" (selected)"); 4601162922Sariff printf("\n"); 4602162922Sariff } 4603162922Sariff } 4604162922Sariff 4605162922Sariff} 4606162922Sariff 4607163057Sariffstatic int 4608163057Sariffhdac_dump_dac_internal(struct hdac_devinfo *devinfo, nid_t nid, int depth) 4609163057Sariff{ 4610163057Sariff struct hdac_widget *w, *cw; 4611163057Sariff struct hdac_softc *sc = devinfo->codec->sc; 4612163057Sariff int i; 4613163057Sariff 4614163057Sariff if (depth > HDA_PARSE_MAXDEPTH) 4615163057Sariff return (0); 4616163057Sariff 4617163057Sariff w = hdac_widget_get(devinfo, nid); 4618163057Sariff if (w == NULL || w->enable == 0 || !(w->pflags & HDA_DAC_PATH)) 4619163057Sariff return (0); 4620163057Sariff 4621163057Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 4622163057Sariff device_printf(sc->dev, "\n"); 4623163057Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 4624163057Sariff device_printf(sc->dev, " ^\n"); 4625163057Sariff device_printf(sc->dev, " |\n"); 4626163057Sariff device_printf(sc->dev, " +-----<------+\n"); 4627163057Sariff } else { 4628163057Sariff device_printf(sc->dev, " ^\n"); 4629163057Sariff device_printf(sc->dev, " |\n"); 4630163057Sariff device_printf(sc->dev, " "); 4631163057Sariff printf(" nid=%d [%s]\n", w->nid, w->name); 4632163057Sariff } 4633163057Sariff 4634163057Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) { 4635163057Sariff return (1); 4636163057Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) { 4637163057Sariff for (i = 0; i < w->nconns; i++) { 4638163057Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 4639163057Sariff if (cw == NULL || cw->enable == 0 || cw->type == 4640163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4641163057Sariff continue; 4642163057Sariff if (hdac_dump_dac_internal(devinfo, cw->nid, 4643163057Sariff depth + 1) != 0) 4644163057Sariff return (1); 4645163057Sariff } 4646163057Sariff } else if ((w->type == 4647163057Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR || 4648163057Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) && 4649163057Sariff w->selconn > -1 && w->selconn < w->nconns) { 4650163057Sariff if (hdac_dump_dac_internal(devinfo, w->conns[w->selconn], 4651163057Sariff depth + 1) != 0) 4652163057Sariff return (1); 4653163057Sariff } 4654163057Sariff 4655163057Sariff return (0); 4656163057Sariff} 4657163057Sariff 4658162922Sariffstatic void 4659162922Sariffhdac_dump_dac(struct hdac_devinfo *devinfo) 4660162922Sariff{ 4661163057Sariff struct hdac_widget *w; 4662163057Sariff struct hdac_softc *sc = devinfo->codec->sc; 4663163057Sariff int i, printed = 0; 4664163057Sariff 4665163057Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4666163057Sariff w = hdac_widget_get(devinfo, i); 4667163057Sariff if (w == NULL || w->enable == 0) 4668163057Sariff continue; 4669163057Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 4670163057Sariff !(w->pflags & HDA_DAC_PATH)) 4671163057Sariff continue; 4672163057Sariff if (printed == 0) { 4673163057Sariff printed = 1; 4674163057Sariff device_printf(sc->dev, "\n"); 4675163057Sariff device_printf(sc->dev, "Playback path:\n"); 4676163057Sariff } 4677163057Sariff hdac_dump_dac_internal(devinfo, w->nid, 0); 4678163057Sariff } 4679162922Sariff} 4680162922Sariff 4681162922Sariffstatic void 4682162922Sariffhdac_dump_adc(struct hdac_devinfo *devinfo) 4683162922Sariff{ 4684162922Sariff struct hdac_widget *w, *cw; 4685162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4686162922Sariff int i, j; 4687162922Sariff int printed = 0; 4688162922Sariff char ossdevs[256]; 4689162922Sariff 4690162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4691162922Sariff w = hdac_widget_get(devinfo, i); 4692162922Sariff if (w == NULL || w->enable == 0) 4693162922Sariff continue; 4694162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 4695162922Sariff continue; 4696162922Sariff if (printed == 0) { 4697162922Sariff printed = 1; 4698162922Sariff device_printf(sc->dev, "\n"); 4699162922Sariff device_printf(sc->dev, "Recording sources:\n"); 4700162922Sariff } 4701162922Sariff device_printf(sc->dev, "\n"); 4702162922Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 4703162922Sariff for (j = 0; j < w->nconns; j++) { 4704162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 4705162922Sariff if (cw == NULL || cw->enable == 0) 4706162922Sariff continue; 4707162922Sariff hdac_audio_ctl_ossmixer_mask2allname(cw->ctlflags, 4708162922Sariff ossdevs, sizeof(ossdevs)); 4709162922Sariff device_printf(sc->dev, " |\n"); 4710162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 4711162922Sariff cw->nid, cw->name); 4712162922Sariff if (strlen(ossdevs) > 0) { 4713162922Sariff printf(" [recsrc: %s]", ossdevs); 4714162922Sariff } 4715162922Sariff printf("\n"); 4716162922Sariff } 4717162922Sariff } 4718162922Sariff} 4719162922Sariff 4720162922Sariffstatic void 4721162922Sariffhdac_dump_pcmchannels(struct hdac_softc *sc, int pcnt, int rcnt) 4722162922Sariff{ 4723162922Sariff nid_t *nids; 4724162922Sariff 4725162922Sariff if (pcnt > 0) { 4726162922Sariff device_printf(sc->dev, "\n"); 4727162922Sariff device_printf(sc->dev, " PCM Playback: %d\n", pcnt); 4728162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 4729162922Sariff sc->play.supp_pcm_size_rate); 4730162922Sariff device_printf(sc->dev, " DAC:"); 4731162922Sariff for (nids = sc->play.io; *nids != -1; nids++) 4732162922Sariff printf(" %d", *nids); 4733162922Sariff printf("\n"); 4734162922Sariff } 4735162922Sariff 4736162922Sariff if (rcnt > 0) { 4737162922Sariff device_printf(sc->dev, "\n"); 4738162922Sariff device_printf(sc->dev, " PCM Record: %d\n", rcnt); 4739162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 4740162922Sariff sc->rec.supp_pcm_size_rate); 4741162922Sariff device_printf(sc->dev, " ADC:"); 4742162922Sariff for (nids = sc->rec.io; *nids != -1; nids++) 4743162922Sariff printf(" %d", *nids); 4744162922Sariff printf("\n"); 4745162922Sariff } 4746162922Sariff} 4747162922Sariff 4748162922Sariffstatic void 4749163057Sariffhdac_release_resources(struct hdac_softc *sc) 4750163057Sariff{ 4751163057Sariff struct hdac_devinfo *devinfo = NULL; 4752163057Sariff device_t *devlist = NULL; 4753163057Sariff int i, devcount; 4754163057Sariff 4755163057Sariff if (sc == NULL) 4756163057Sariff return; 4757163057Sariff 4758163057Sariff hdac_lock(sc); 4759164614Sariff if (sc->polling != 0) 4760164614Sariff callout_stop(&sc->poll_hdac); 4761163057Sariff hdac_reset(sc); 4762163057Sariff hdac_unlock(sc); 4763163057Sariff snd_mtxfree(sc->lock); 4764163057Sariff 4765163057Sariff device_get_children(sc->dev, &devlist, &devcount); 4766163057Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 4767163057Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 4768163057Sariff if (devinfo == NULL) 4769163057Sariff continue; 4770163057Sariff if (devinfo->widget != NULL) 4771163057Sariff free(devinfo->widget, M_HDAC); 4772163057Sariff if (devinfo->node_type == 4773163057Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 4774163057Sariff devinfo->function.audio.ctl != NULL) 4775163057Sariff free(devinfo->function.audio.ctl, M_HDAC); 4776163057Sariff free(devinfo, M_HDAC); 4777163057Sariff device_delete_child(sc->dev, devlist[i]); 4778163057Sariff } 4779163057Sariff if (devlist != NULL) 4780163057Sariff free(devlist, M_TEMP); 4781163057Sariff 4782163057Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) { 4783163057Sariff if (sc->codecs[i] != NULL) 4784163057Sariff free(sc->codecs[i], M_HDAC); 4785163057Sariff sc->codecs[i] = NULL; 4786163057Sariff } 4787163057Sariff 4788163057Sariff hdac_dma_free(&sc->rirb_dma); 4789163057Sariff hdac_dma_free(&sc->corb_dma); 4790163057Sariff if (sc->play.blkcnt > 0) 4791163057Sariff hdac_dma_free(&sc->play.bdl_dma); 4792163057Sariff if (sc->rec.blkcnt > 0) 4793163057Sariff hdac_dma_free(&sc->rec.bdl_dma); 4794163057Sariff hdac_irq_free(sc); 4795163057Sariff hdac_mem_free(sc); 4796163057Sariff free(sc, M_DEVBUF); 4797163057Sariff 4798163057Sariff} 4799163057Sariff 4800163057Sariff/* This function surely going to make its way into upper level someday. */ 4801163057Sariffstatic void 4802163057Sariffhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 4803163057Sariff{ 4804163057Sariff const char *res = NULL; 4805163057Sariff int i = 0, j, k, len, inv; 4806163057Sariff 4807163057Sariff if (on != NULL) 4808163057Sariff *on = 0; 4809163057Sariff if (off != NULL) 4810163057Sariff *off = 0; 4811163057Sariff if (sc == NULL) 4812163057Sariff return; 4813163057Sariff if (resource_string_value(device_get_name(sc->dev), 4814163057Sariff device_get_unit(sc->dev), "config", &res) != 0) 4815163057Sariff return; 4816163057Sariff if (!(res != NULL && strlen(res) > 0)) 4817163057Sariff return; 4818163057Sariff HDA_BOOTVERBOSE( 4819163057Sariff device_printf(sc->dev, "HDA_DEBUG: HDA Config:"); 4820163057Sariff ); 4821163057Sariff for (;;) { 4822163057Sariff while (res[i] != '\0' && 4823163057Sariff (res[i] == ',' || isspace(res[i]) != 0)) 4824163057Sariff i++; 4825163057Sariff if (res[i] == '\0') { 4826163057Sariff HDA_BOOTVERBOSE( 4827163057Sariff printf("\n"); 4828163057Sariff ); 4829163057Sariff return; 4830163057Sariff } 4831163057Sariff j = i; 4832163057Sariff while (res[j] != '\0' && 4833163057Sariff !(res[j] == ',' || isspace(res[j]) != 0)) 4834163057Sariff j++; 4835163057Sariff len = j - i; 4836163057Sariff if (len > 2 && strncmp(res + i, "no", 2) == 0) 4837163057Sariff inv = 2; 4838163057Sariff else 4839163057Sariff inv = 0; 4840163057Sariff for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 4841163057Sariff if (strncmp(res + i + inv, 4842163057Sariff hdac_quirks_tab[k].key, len - inv) != 0) 4843163057Sariff continue; 4844163057Sariff if (len - inv != strlen(hdac_quirks_tab[k].key)) 4845163057Sariff break; 4846163057Sariff HDA_BOOTVERBOSE( 4847163057Sariff printf(" %s%s", (inv != 0) ? "no" : "", 4848163057Sariff hdac_quirks_tab[k].key); 4849163057Sariff ); 4850163057Sariff if (inv == 0 && on != NULL) 4851163057Sariff *on |= hdac_quirks_tab[k].value; 4852163057Sariff else if (inv != 0 && off != NULL) 4853163057Sariff *off |= hdac_quirks_tab[k].value; 4854163057Sariff break; 4855163057Sariff } 4856163057Sariff i = j; 4857163057Sariff } 4858163057Sariff} 4859163057Sariff 4860164614Sariff#ifdef SND_DYNSYSCTL 4861164614Sariffstatic int 4862164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 4863164614Sariff{ 4864164614Sariff struct hdac_softc *sc; 4865164614Sariff struct hdac_devinfo *devinfo; 4866164614Sariff device_t dev; 4867164614Sariff uint32_t ctl; 4868164614Sariff int err, val; 4869164614Sariff 4870164614Sariff dev = oidp->oid_arg1; 4871164614Sariff devinfo = pcm_getdevinfo(dev); 4872164614Sariff if (devinfo == NULL || devinfo->codec == NULL || 4873164614Sariff devinfo->codec->sc == NULL) 4874164614Sariff return (EINVAL); 4875164614Sariff sc = devinfo->codec->sc; 4876164614Sariff hdac_lock(sc); 4877164614Sariff val = sc->polling; 4878164614Sariff hdac_unlock(sc); 4879164614Sariff err = sysctl_handle_int(oidp, &val, sizeof(val), req); 4880164614Sariff 4881164614Sariff if (err || req->newptr == NULL) 4882164614Sariff return (err); 4883164614Sariff if (val < 0 || val > 1) 4884164614Sariff return (EINVAL); 4885164614Sariff 4886164614Sariff hdac_lock(sc); 4887164614Sariff if (val != sc->polling) { 4888164614Sariff if (hda_chan_active(sc) != 0) 4889164614Sariff err = EBUSY; 4890164614Sariff else if (val == 0) { 4891164614Sariff callout_stop(&sc->poll_hdac); 4892164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 4893164614Sariff sc->rirb_size / 2); 4894164614Sariff ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 4895164614Sariff ctl |= HDAC_RIRBCTL_RINTCTL; 4896164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl); 4897164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 4898164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 4899164614Sariff sc->polling = 0; 4900164614Sariff DELAY(1000); 4901164614Sariff } else { 4902164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 0); 4903164614Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 0); 4904164614Sariff ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 4905164614Sariff ctl &= ~HDAC_RIRBCTL_RINTCTL; 4906164614Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl); 4907164614Sariff callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, 4908164614Sariff sc); 4909164614Sariff sc->polling = 1; 4910164614Sariff DELAY(1000); 4911164614Sariff } 4912164614Sariff } 4913164614Sariff hdac_unlock(sc); 4914164614Sariff 4915164614Sariff return (err); 4916164614Sariff} 4917164614Sariff#endif 4918164614Sariff 4919163057Sariffstatic void 4920162922Sariffhdac_attach2(void *arg) 4921162922Sariff{ 4922162922Sariff struct hdac_softc *sc; 4923162922Sariff struct hdac_widget *w; 4924162922Sariff struct hdac_audio_ctl *ctl; 4925163057Sariff uint32_t quirks_on, quirks_off; 4926162922Sariff int pcnt, rcnt; 4927162922Sariff int i; 4928162922Sariff char status[SND_STATUSLEN]; 4929162965Sariff device_t *devlist = NULL; 4930162922Sariff int devcount; 4931162922Sariff struct hdac_devinfo *devinfo = NULL; 4932162922Sariff 4933162922Sariff sc = (struct hdac_softc *)arg; 4934162922Sariff 4935163057Sariff hdac_config_fetch(sc, &quirks_on, &quirks_off); 4936162922Sariff 4937163057Sariff HDA_BOOTVERBOSE( 4938163057Sariff device_printf(sc->dev, "HDA_DEBUG: HDA Config: on=0x%08x off=0x%08x\n", 4939163057Sariff quirks_on, quirks_off); 4940163057Sariff ); 4941163057Sariff 4942162922Sariff hdac_lock(sc); 4943162922Sariff 4944162922Sariff /* Remove ourselves from the config hooks */ 4945162922Sariff if (sc->intrhook.ich_func != NULL) { 4946162922Sariff config_intrhook_disestablish(&sc->intrhook); 4947162922Sariff sc->intrhook.ich_func = NULL; 4948162922Sariff } 4949162922Sariff 4950162922Sariff /* Start the corb and rirb engines */ 4951163057Sariff HDA_BOOTVERBOSE( 4952162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting CORB Engine...\n"); 4953162922Sariff ); 4954162922Sariff hdac_corb_start(sc); 4955163057Sariff HDA_BOOTVERBOSE( 4956162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting RIRB Engine...\n"); 4957162922Sariff ); 4958162922Sariff hdac_rirb_start(sc); 4959162922Sariff 4960163057Sariff HDA_BOOTVERBOSE( 4961162922Sariff device_printf(sc->dev, 4962162922Sariff "HDA_DEBUG: Enabling controller interrupt...\n"); 4963162922Sariff ); 4964164614Sariff if (sc->polling == 0) 4965164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 4966164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 4967163057Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 4968163057Sariff HDAC_GCTL_UNSOL); 4969162922Sariff 4970162922Sariff DELAY(1000); 4971162922Sariff 4972163057Sariff HDA_BOOTVERBOSE( 4973162922Sariff device_printf(sc->dev, "HDA_DEBUG: Scanning HDA codecs...\n"); 4974162922Sariff ); 4975162922Sariff hdac_scan_codecs(sc); 4976162922Sariff 4977162922Sariff device_get_children(sc->dev, &devlist, &devcount); 4978162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 4979162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 4980162965Sariff if (devinfo != NULL && devinfo->node_type == 4981162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 4982162965Sariff break; 4983162965Sariff } else 4984162965Sariff devinfo = NULL; 4985162922Sariff } 4986162965Sariff if (devlist != NULL) 4987162965Sariff free(devlist, M_TEMP); 4988162922Sariff 4989162922Sariff if (devinfo == NULL) { 4990162922Sariff hdac_unlock(sc); 4991162922Sariff device_printf(sc->dev, "Audio Function Group not found!\n"); 4992163057Sariff hdac_release_resources(sc); 4993162922Sariff return; 4994162922Sariff } 4995162922Sariff 4996163057Sariff HDA_BOOTVERBOSE( 4997162922Sariff device_printf(sc->dev, 4998162922Sariff "HDA_DEBUG: Parsing AFG nid=%d cad=%d\n", 4999162922Sariff devinfo->nid, devinfo->codec->cad); 5000162922Sariff ); 5001162922Sariff hdac_audio_parse(devinfo); 5002163057Sariff HDA_BOOTVERBOSE( 5003162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing Ctls...\n"); 5004162922Sariff ); 5005162922Sariff hdac_audio_ctl_parse(devinfo); 5006163057Sariff HDA_BOOTVERBOSE( 5007162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing vendor patch...\n"); 5008162922Sariff ); 5009162922Sariff hdac_vendor_patch_parse(devinfo); 5010163057Sariff if (quirks_on != 0) 5011163057Sariff devinfo->function.audio.quirks |= quirks_on; 5012163057Sariff if (quirks_off != 0) 5013163057Sariff devinfo->function.audio.quirks &= ~quirks_off; 5014162922Sariff 5015162922Sariff /* XXX Disable all DIGITAL path. */ 5016162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 5017162922Sariff w = hdac_widget_get(devinfo, i); 5018162922Sariff if (w == NULL) 5019162922Sariff continue; 5020162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 5021162922Sariff w->enable = 0; 5022162922Sariff continue; 5023162922Sariff } 5024162922Sariff /* XXX Disable useless pin ? */ 5025162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 5026162922Sariff (w->wclass.pin.config & 5027162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 5028162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 5029162922Sariff w->enable = 0; 5030162922Sariff } 5031162922Sariff i = 0; 5032162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5033162922Sariff if (ctl->widget == NULL) 5034162922Sariff continue; 5035162922Sariff w = ctl->widget; 5036162922Sariff if (w->enable == 0) 5037162922Sariff ctl->enable = 0; 5038162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 5039162922Sariff ctl->enable = 0; 5040162922Sariff w = ctl->childwidget; 5041162922Sariff if (w == NULL) 5042162922Sariff continue; 5043162922Sariff if (w->enable == 0 || 5044162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 5045162922Sariff ctl->enable = 0; 5046162922Sariff } 5047162922Sariff 5048163057Sariff HDA_BOOTVERBOSE( 5049162922Sariff device_printf(sc->dev, "HDA_DEBUG: Building AFG tree...\n"); 5050162922Sariff ); 5051162922Sariff hdac_audio_build_tree(devinfo); 5052162922Sariff 5053163057Sariff HDA_BOOTVERBOSE( 5054162922Sariff device_printf(sc->dev, "HDA_DEBUG: AFG commit...\n"); 5055162922Sariff ); 5056162922Sariff hdac_audio_commit(devinfo, HDA_COMMIT_ALL); 5057163057Sariff HDA_BOOTVERBOSE( 5058162922Sariff device_printf(sc->dev, "HDA_DEBUG: Ctls commit...\n"); 5059162922Sariff ); 5060162922Sariff hdac_audio_ctl_commit(devinfo); 5061162922Sariff 5062163057Sariff HDA_BOOTVERBOSE( 5063162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_PLAY setup...\n"); 5064162922Sariff ); 5065162922Sariff pcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_PLAY); 5066163057Sariff HDA_BOOTVERBOSE( 5067162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_REC setup...\n"); 5068162922Sariff ); 5069162922Sariff rcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_REC); 5070162922Sariff 5071162922Sariff hdac_unlock(sc); 5072163057Sariff HDA_BOOTVERBOSE( 5073162922Sariff device_printf(sc->dev, 5074162922Sariff "HDA_DEBUG: OSS mixer initialization...\n"); 5075162922Sariff ); 5076163057Sariff 5077163057Sariff /* 5078163057Sariff * There is no point of return after this. If the driver failed, 5079163057Sariff * so be it. Let the detach procedure do all the cleanup. 5080163057Sariff */ 5081163057Sariff if (mixer_init(sc->dev, &hdac_audio_ctl_ossmixer_class, devinfo) != 0) 5082162922Sariff device_printf(sc->dev, "Can't register mixer\n"); 5083162922Sariff 5084162922Sariff if (pcnt > 0) 5085162922Sariff pcnt = 1; 5086162922Sariff if (rcnt > 0) 5087162922Sariff rcnt = 1; 5088162922Sariff 5089163057Sariff HDA_BOOTVERBOSE( 5090162922Sariff device_printf(sc->dev, 5091162922Sariff "HDA_DEBUG: Registering PCM channels...\n"); 5092162922Sariff ); 5093163057Sariff if (pcm_register(sc->dev, devinfo, pcnt, rcnt) != 0) 5094162922Sariff device_printf(sc->dev, "Can't register PCM\n"); 5095162922Sariff 5096162922Sariff sc->registered++; 5097162922Sariff 5098162922Sariff for (i = 0; i < pcnt; i++) 5099162922Sariff pcm_addchan(sc->dev, PCMDIR_PLAY, &hdac_channel_class, devinfo); 5100162922Sariff for (i = 0; i < rcnt; i++) 5101162922Sariff pcm_addchan(sc->dev, PCMDIR_REC, &hdac_channel_class, devinfo); 5102162922Sariff 5103164614Sariff#ifdef SND_DYNSYSCTL 5104164614Sariff SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 5105164614Sariff SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 5106164614Sariff "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 5107164614Sariff sysctl_hdac_polling, "I", "Enable polling mode"); 5108164614Sariff#endif 5109164614Sariff 5110162922Sariff snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s [%s]", 5111164614Sariff rman_get_start(sc->mem.mem_res), rman_get_start(sc->irq.irq_res), 5112164614Sariff PCM_KLDSTRING(snd_hda), HDA_DRV_TEST_REV); 5113162922Sariff pcm_setstatus(sc->dev, status); 5114162922Sariff device_printf(sc->dev, "<HDA Codec: %s>\n", hdac_codec_name(devinfo)); 5115163057Sariff HDA_BOOTVERBOSE( 5116163057Sariff device_printf(sc->dev, "<HDA Codec ID: 0x%08x>\n", 5117163057Sariff hdac_codec_id(devinfo)); 5118163057Sariff ); 5119164614Sariff device_printf(sc->dev, "<HDA Driver Revision: %s>\n", 5120164614Sariff HDA_DRV_TEST_REV); 5121162922Sariff 5122163057Sariff HDA_BOOTVERBOSE( 5123162922Sariff if (devinfo->function.audio.quirks != 0) { 5124162922Sariff device_printf(sc->dev, "\n"); 5125163057Sariff device_printf(sc->dev, "HDA config/quirks:"); 5126163057Sariff for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) { 5127163057Sariff if (devinfo->function.audio.quirks & 5128163057Sariff hdac_quirks_tab[i].value) 5129163057Sariff printf(" %s", hdac_quirks_tab[i].key); 5130163057Sariff } 5131162922Sariff printf("\n"); 5132162922Sariff } 5133162922Sariff device_printf(sc->dev, "\n"); 5134162922Sariff device_printf(sc->dev, "+-------------------+\n"); 5135162922Sariff device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 5136162922Sariff device_printf(sc->dev, "+-------------------+\n"); 5137162922Sariff hdac_dump_nodes(devinfo); 5138162922Sariff device_printf(sc->dev, "\n"); 5139162922Sariff device_printf(sc->dev, "+------------------------+\n"); 5140162922Sariff device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 5141162922Sariff device_printf(sc->dev, "+------------------------+\n"); 5142162922Sariff device_printf(sc->dev, "\n"); 5143162922Sariff i = 0; 5144162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 5145162922Sariff device_printf(sc->dev, "%3d: nid=%d", i, 5146162922Sariff (ctl->widget != NULL) ? ctl->widget->nid : -1); 5147162922Sariff if (ctl->childwidget != NULL) 5148162922Sariff printf(" cnid=%d", ctl->childwidget->nid); 5149162922Sariff printf(" dir=0x%x index=%d " 5150162922Sariff "ossmask=0x%08x ossdev=%d%s\n", 5151162922Sariff ctl->dir, ctl->index, 5152162922Sariff ctl->ossmask, ctl->ossdev, 5153162922Sariff (ctl->enable == 0) ? " [DISABLED]" : ""); 5154162922Sariff } 5155162922Sariff device_printf(sc->dev, "\n"); 5156162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 5157162922Sariff device_printf(sc->dev, "| DUMPING HDA AUDIO/VOLUME CONTROLS |\n"); 5158162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 5159162922Sariff hdac_dump_ctls(devinfo, "Master Volume (OSS: vol)", SOUND_MASK_VOLUME); 5160162922Sariff hdac_dump_ctls(devinfo, "PCM Volume (OSS: pcm)", SOUND_MASK_PCM); 5161162922Sariff hdac_dump_ctls(devinfo, "CD Volume (OSS: cd)", SOUND_MASK_CD); 5162162922Sariff hdac_dump_ctls(devinfo, "Microphone Volume (OSS: mic)", SOUND_MASK_MIC); 5163162922Sariff hdac_dump_ctls(devinfo, "Line-in Volume (OSS: line)", SOUND_MASK_LINE); 5164162922Sariff hdac_dump_ctls(devinfo, "Recording Level (OSS: rec)", SOUND_MASK_RECLEV); 5165162922Sariff hdac_dump_ctls(devinfo, "Speaker/Beep (OSS: speaker)", SOUND_MASK_SPEAKER); 5166162922Sariff hdac_dump_ctls(devinfo, NULL, 0); 5167162922Sariff hdac_dump_dac(devinfo); 5168162922Sariff hdac_dump_adc(devinfo); 5169162922Sariff device_printf(sc->dev, "\n"); 5170162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 5171162922Sariff device_printf(sc->dev, "| DUMPING PCM Playback/Record Channels |\n"); 5172162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 5173162922Sariff hdac_dump_pcmchannels(sc, pcnt, rcnt); 5174162922Sariff ); 5175164614Sariff 5176164614Sariff if (sc->polling != 0) { 5177164614Sariff hdac_lock(sc); 5178164614Sariff callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc); 5179164614Sariff hdac_unlock(sc); 5180164614Sariff } 5181162922Sariff} 5182162922Sariff 5183162922Sariff/**************************************************************************** 5184162922Sariff * int hdac_detach(device_t) 5185162922Sariff * 5186162922Sariff * Detach and free up resources utilized by the hdac device. 5187162922Sariff ****************************************************************************/ 5188162922Sariffstatic int 5189162922Sariffhdac_detach(device_t dev) 5190162922Sariff{ 5191162922Sariff struct hdac_softc *sc = NULL; 5192162922Sariff struct hdac_devinfo *devinfo = NULL; 5193163057Sariff int err; 5194162922Sariff 5195162922Sariff devinfo = (struct hdac_devinfo *)pcm_getdevinfo(dev); 5196162922Sariff if (devinfo != NULL && devinfo->codec != NULL) 5197162922Sariff sc = devinfo->codec->sc; 5198162922Sariff if (sc == NULL) 5199163057Sariff return (0); 5200162922Sariff 5201162922Sariff if (sc->registered > 0) { 5202163057Sariff err = pcm_unregister(dev); 5203163057Sariff if (err != 0) 5204163057Sariff return (err); 5205162922Sariff } 5206162922Sariff 5207163057Sariff hdac_release_resources(sc); 5208162922Sariff 5209162922Sariff return (0); 5210162922Sariff} 5211162922Sariff 5212162922Sariffstatic device_method_t hdac_methods[] = { 5213162922Sariff /* device interface */ 5214162922Sariff DEVMETHOD(device_probe, hdac_probe), 5215162922Sariff DEVMETHOD(device_attach, hdac_attach), 5216162922Sariff DEVMETHOD(device_detach, hdac_detach), 5217162922Sariff { 0, 0 } 5218162922Sariff}; 5219162922Sariff 5220162922Sariffstatic driver_t hdac_driver = { 5221162922Sariff "pcm", 5222162922Sariff hdac_methods, 5223162922Sariff PCM_SOFTC_SIZE, 5224162922Sariff}; 5225162922Sariff 5226162922SariffDRIVER_MODULE(snd_hda, pci, hdac_driver, pcm_devclass, 0, 0); 5227162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 5228162922SariffMODULE_VERSION(snd_hda, 1); 5229