hdac.c revision 162965
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 47162922Sariff * interesting documents, especiall UAA (Universal Audio Architecture). 48162922Sariff * 4) Possible vendor specific support. 49162922Sariff * (snd_hda_intel, snd_hda_ati, etc..) 50162922Sariff * 51162922Sariff * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the 52162922Sariff * Compaq V3000 with Conexant HDA. 53162922Sariff * 54162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 55162922Sariff * * * 56162922Sariff * * This driver is a collaborative effort made by: * 57162922Sariff * * * 58162922Sariff * * Stephane E. Potvin <sepotvin@videotron.ca> * 59162922Sariff * * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * 60162922Sariff * * Wesley Morgan <morganw@chemikals.org> * 61162922Sariff * * Daniel Eischen <deischen@FreeBSD.org> * 62162922Sariff * * Maxime Guillaud <bsd-ports@mguillaud.net> * 63162922Sariff * * Ariff Abdullah <ariff@FreeBSD.org> * 64162922Sariff * * * 65162922Sariff * * ....and various people from freebsd-multimedia@FreeBSD.org * 66162922Sariff * * * 67162922Sariff * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 68162922Sariff */ 69162922Sariff 70162922Sariff#include <dev/sound/pcm/sound.h> 71162922Sariff#include <dev/pci/pcireg.h> 72162922Sariff#include <dev/pci/pcivar.h> 73162922Sariff 74162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 75162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 76162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 77162922Sariff#include <dev/sound/pci/hda/hdac.h> 78162922Sariff 79162922Sariff#include "mixer_if.h" 80162922Sariff 81162965Sariff#define HDA_DRV_TEST_REV "20061003_0029" 82162922Sariff#define HDA_WIDGET_PARSER_REV 1 83162922Sariff 84162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 162965 2006-10-02 16:30:04Z ariff $"); 85162922Sariff 86162922Sariff#undef HDA_DEBUG_ENABLED 87162922Sariff#define HDA_DEBUG_ENABLED 1 88162922Sariff 89162922Sariff#ifdef HDA_DEBUG_ENABLED 90162922Sariff#define HDA_DEBUG_MSG(stmt) do { \ 91162922Sariff if (bootverbose) { \ 92162922Sariff stmt \ 93162922Sariff } \ 94162922Sariff} while(0) 95162922Sariff#else 96162922Sariff#define HDA_DEBUG_MSG(stmt) 97162922Sariff#endif 98162922Sariff 99162922Sariff#define HDA_BOOTVERBOSE_MSG(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) 112162922Sariff 113162965Sariff#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v)) 114162965Sariff#define HDA_MATCH_ALL 0xffffffff 115162965Sariff#define HDAC_INVALID 0xffffffff 116162965Sariff 117162922Sariff#define HDA_MODEL_CONSTRUCT(vendor, model) \ 118162922Sariff (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff)) 119162922Sariff 120162922Sariff/* Controller models */ 121162922Sariff 122162922Sariff/* Intel */ 123162922Sariff#define INTEL_VENDORID 0x8086 124162922Sariff#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) 125162922Sariff#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) 126162922Sariff#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) 127162922Sariff 128162922Sariff/* Nvidia */ 129162922Sariff#define NVIDIA_VENDORID 0x10de 130162922Sariff#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c) 131162922Sariff#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371) 132162922Sariff#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff) 133162922Sariff 134162922Sariff/* ATI */ 135162922Sariff#define ATI_VENDORID 0x1002 136162922Sariff#define HDA_ATI_SB450 HDA_MODEL_CONSTRUCT(ATI, 0x437b) 137162922Sariff#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff) 138162922Sariff 139162922Sariff/* OEM/subvendors */ 140162922Sariff 141162922Sariff/* HP/Compaq */ 142162922Sariff#define HP_VENDORID 0x103c 143162922Sariff#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5) 144162922Sariff#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2) 145162922Sariff#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa) 146162922Sariff#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff) 147162922Sariff 148162922Sariff/* Dell */ 149162922Sariff#define DELL_VENDORID 0x1028 150162922Sariff#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc) 151162922Sariff#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9) 152162922Sariff#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff) 153162922Sariff 154162922Sariff/* Clevo */ 155162922Sariff#define CLEVO_VENDORID 0x1558 156162922Sariff#define CLEVO_D900T_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0x0900) 157162922Sariff#define CLEVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(CLEVO, 0xffff) 158162922Sariff 159162922Sariff/* Acer */ 160162922Sariff#define ACER_VENDORID 0x1025 161162922Sariff#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff) 162162922Sariff 163162965Sariff/* Asus */ 164162965Sariff#define ASUS_VENDORID 0x1043 165162965Sariff#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993) 166162965Sariff#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff) 167162922Sariff 168162965Sariff 169162922Sariff/* Misc constants.. */ 170162922Sariff#define HDA_AMP_MUTE_DEFAULT (0xffffffff) 171162922Sariff#define HDA_AMP_MUTE_NONE (0) 172162922Sariff#define HDA_AMP_MUTE_LEFT (1 << 0) 173162922Sariff#define HDA_AMP_MUTE_RIGHT (1 << 1) 174162922Sariff#define HDA_AMP_MUTE_ALL (HDA_AMP_MUTE_LEFT | HDA_AMP_MUTE_RIGHT) 175162922Sariff 176162922Sariff#define HDA_AMP_LEFT_MUTED(v) ((v) & (HDA_AMP_MUTE_LEFT)) 177162922Sariff#define HDA_AMP_RIGHT_MUTED(v) (((v) & HDA_AMP_MUTE_RIGHT) >> 1) 178162922Sariff 179162922Sariff#define HDA_DAC_PATH (1 << 0) 180162922Sariff#define HDA_ADC_PATH (1 << 1) 181162922Sariff#define HDA_ADC_RECSEL (1 << 2) 182162922Sariff 183162922Sariff#define HDA_CTL_OUT 0x1 184162922Sariff#define HDA_CTL_IN 0x2 185162922Sariff#define HDA_CTL_BOTH (HDA_CTL_IN | HDA_CTL_OUT) 186162922Sariff 187162922Sariff#define HDA_QUIRK_GPIO1 (1 << 0) 188162922Sariff#define HDA_QUIRK_GPIO2 (1 << 1) 189162922Sariff#define HDA_QUIRK_SOFTPCMVOL (1 << 2) 190162922Sariff#define HDA_QUIRK_FIXEDRATE (1 << 3) 191162922Sariff#define HDA_QUIRK_FORCESTEREO (1 << 4) 192162922Sariff 193162922Sariff#define HDA_BDL_MIN 2 194162922Sariff#define HDA_BDL_MAX 256 195162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 196162922Sariff 197162922Sariff#define HDA_BUFSZ_MIN 4096 198162922Sariff#define HDA_BUFSZ_MAX 65536 199162922Sariff#define HDA_BUFSZ_DEFAULT 16384 200162922Sariff 201162922Sariff#define HDA_PARSE_MAXDEPTH 10 202162922Sariff 203162922Sariff#define HDAC_UNSOLTAG_EVENT_HP 0x00 204162922Sariff 205162922Sariffstatic MALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller"); 206162922Sariff 207162922Sariffenum { 208162922Sariff HDA_PARSE_MIXER, 209162922Sariff HDA_PARSE_DIRECT 210162922Sariff}; 211162922Sariff 212162922Sariff/* Default */ 213162922Sariffstatic uint32_t hdac_fmt[] = { 214162922Sariff AFMT_STEREO | AFMT_S16_LE, 215162922Sariff 0 216162922Sariff}; 217162922Sariff 218162922Sariffstatic struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0}; 219162922Sariff 220162922Sariffstatic const struct { 221162922Sariff uint32_t model; 222162922Sariff char *desc; 223162922Sariff} hdac_devices[] = { 224162922Sariff { HDA_INTEL_82801F, "Intel 82801F" }, 225162922Sariff { HDA_INTEL_82801G, "Intel 82801G" }, 226162922Sariff { HDA_NVIDIA_MCP51, "NVidia MCP51" }, 227162922Sariff { HDA_NVIDIA_MCP55, "NVidia MCP55" }, 228162922Sariff { HDA_ATI_SB450, "ATI SB450" }, 229162922Sariff /* Unknown */ 230162922Sariff { HDA_INTEL_ALL, "Intel (Unknown)" }, 231162922Sariff { HDA_NVIDIA_ALL, "NVidia (Unknown)" }, 232162922Sariff { HDA_ATI_ALL, "ATI (Unknown)" }, 233162922Sariff}; 234162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 235162922Sariff 236162922Sariffstatic const struct { 237162922Sariff uint32_t rate; 238162922Sariff int valid; 239162922Sariff uint16_t base; 240162922Sariff uint16_t mul; 241162922Sariff uint16_t div; 242162922Sariff} hda_rate_tab[] = { 243162922Sariff { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */ 244162922Sariff { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */ 245162922Sariff { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */ 246162922Sariff { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */ 247162922Sariff { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */ 248162922Sariff { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */ 249162922Sariff { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */ 250162922Sariff { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */ 251162922Sariff { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */ 252162922Sariff { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */ 253162922Sariff { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */ 254162922Sariff { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */ 255162922Sariff { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */ 256162922Sariff { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */ 257162922Sariff { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */ 258162922Sariff { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */ 259162922Sariff { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */ 260162922Sariff { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */ 261162922Sariff { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */ 262162922Sariff { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */ 263162922Sariff { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */ 264162922Sariff { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */ 265162922Sariff { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */ 266162922Sariff { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */ 267162922Sariff { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */ 268162922Sariff { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */ 269162922Sariff { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */ 270162922Sariff { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */ 271162922Sariff { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */ 272162922Sariff { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */ 273162922Sariff { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */ 274162922Sariff { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */ 275162922Sariff { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */ 276162922Sariff { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */ 277162922Sariff { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */ 278162922Sariff}; 279162922Sariff#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0])) 280162922Sariff 281162922Sariff/* All codecs you can eat... */ 282162922Sariff#define HDA_CODEC_CONSTRUCT(vendor, id) \ 283162922Sariff (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff)) 284162922Sariff 285162922Sariff/* Realtek */ 286162922Sariff#define REALTEK_VENDORID 0x10ec 287162922Sariff#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 288162922Sariff#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) 289162922Sariff#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) 290162922Sariff#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) 291162922Sariff#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) 292162922Sariff 293162922Sariff/* Analog Device */ 294162922Sariff#define ANALOGDEVICE_VENDORID 0x11d4 295162922Sariff#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1981) 296162922Sariff#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1983) 297162922Sariff#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1986) 298162922Sariff#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0xffff) 299162922Sariff 300162922Sariff/* CMedia */ 301162922Sariff#define CMEDIA_VENDORID 0x434d 302162922Sariff#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980) 303162922Sariff#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) 304162922Sariff 305162922Sariff/* Sigmatel */ 306162922Sariff#define SIGMATEL_VENDORID 0x8384 307162922Sariff#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) 308162922Sariff#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) 309162922Sariff#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) 310162922Sariff#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) 311162922Sariff#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) 312162922Sariff 313162922Sariff/* 314162922Sariff * Conexant 315162922Sariff * 316162922Sariff * Ok, the truth is, I don't have any idea at all whether 317162922Sariff * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only 318162922Sariff * place that tell me it is "Venice" is from its Windows driver INF. 319162922Sariff */ 320162922Sariff#define CONEXANT_VENDORID 0x14f1 321162922Sariff#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) 322162922Sariff#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) 323162922Sariff 324162922Sariff 325162922Sariff/* Codecs */ 326162922Sariffstatic const struct { 327162922Sariff uint32_t id; 328162922Sariff char *name; 329162922Sariff} hdac_codecs[] = { 330162922Sariff { HDA_CODEC_ALC260, "Realtek ALC260" }, 331162922Sariff { HDA_CODEC_ALC861, "Realtek ALC861" }, 332162922Sariff { HDA_CODEC_ALC880, "Realtek ALC880" }, 333162922Sariff { HDA_CODEC_ALC882, "Realtek ALC882" }, 334162922Sariff { HDA_CODEC_AD1981HD, "Analog Device AD1981HD" }, 335162922Sariff { HDA_CODEC_AD1983, "Analog Device AD1983" }, 336162922Sariff { HDA_CODEC_AD1986A, "Analog Device AD1986A" }, 337162922Sariff { HDA_CODEC_CMI9880, "CMedia CMI9880" }, 338162922Sariff { HDA_CODEC_STAC9221, "Sigmatel STAC9221" }, 339162922Sariff { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" }, 340162922Sariff { HDA_CODEC_STAC9220, "Sigmatel STAC9220" }, 341162922Sariff { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" }, 342162922Sariff { HDA_CODEC_CXVENICE, "Conexant Venice" }, 343162922Sariff /* Unknown codec */ 344162922Sariff { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" }, 345162922Sariff { HDA_CODEC_ADXXXX, "Analog Device (Unknown)" }, 346162922Sariff { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" }, 347162922Sariff { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" }, 348162922Sariff { HDA_CODEC_CXXXXX, "Conexant (Unknown)" }, 349162922Sariff}; 350162922Sariff#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0])) 351162922Sariff 352162922Sariffenum { 353162922Sariff HDAC_HP_SWITCH_CTL, 354162922Sariff HDAC_HP_SWITCH_CTRL 355162922Sariff}; 356162922Sariff 357162922Sariffstatic const struct { 358162965Sariff uint32_t model; 359162922Sariff uint32_t id; 360162922Sariff int type; 361162922Sariff nid_t hpnid; 362162922Sariff nid_t spkrnid[8]; 363162922Sariff nid_t eapdnid; 364162922Sariff} hdac_hp_switch[] = { 365162922Sariff /* Specific OEM models */ 366162922Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 367162922Sariff 17, { 16, -1 }, 16 }, 368162922Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 369162922Sariff 6, { 5, -1 }, 5 }, 370162922Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 371162922Sariff 6, { 5, -1 }, 5 }, 372162922Sariff { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 373162922Sariff 13, { 14, -1 }, -1 }, 374162922Sariff { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 375162922Sariff 13, { 14, -1 }, -1 }, 376162922Sariff /* 377162922Sariff * All models that at least come from the same vendor with 378162922Sariff * simmilar codec. 379162922Sariff */ 380162922Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 381162922Sariff 17, { 16, -1 }, 16 }, 382162922Sariff { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 383162922Sariff 6, { 5, -1 }, 5 }, 384162922Sariff { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 385162922Sariff 13, { 14, -1 }, -1 }, 386162922Sariff}; 387162922Sariff#define HDAC_HP_SWITCH_LEN \ 388162922Sariff (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0])) 389162922Sariff 390162922Sariffstatic const struct { 391162965Sariff uint32_t model; 392162922Sariff uint32_t id; 393162922Sariff nid_t eapdnid; 394162922Sariff int hp_switch; 395162922Sariff} hdac_eapd_switch[] = { 396162922Sariff { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, 16, 1 }, 397162922Sariff { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 398162922Sariff { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 }, 399162922Sariff}; 400162922Sariff#define HDAC_EAPD_SWITCH_LEN \ 401162922Sariff (sizeof(hdac_eapd_switch) / sizeof(hdac_eapd_switch[0])) 402162922Sariff 403162922Sariff/**************************************************************************** 404162922Sariff * Function prototypes 405162922Sariff ****************************************************************************/ 406162922Sariffstatic void hdac_intr_handler(void *); 407162922Sariffstatic int hdac_reset(struct hdac_softc *); 408162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 409162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 410162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 411162922Sariff struct hdac_dma *, bus_size_t); 412162922Sariffstatic void hdac_dma_free(struct hdac_dma *); 413162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 414162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 415162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 416162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 417162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 418162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 419162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 420162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 421162922Sariffstatic void hdac_scan_codecs(struct hdac_softc *); 422162922Sariffstatic int hdac_probe_codec(struct hdac_codec *); 423162922Sariffstatic struct hdac_devinfo *hdac_probe_function(struct hdac_codec *, nid_t); 424162922Sariffstatic void hdac_add_child(struct hdac_softc *, struct hdac_devinfo *); 425162922Sariff 426162922Sariffstatic void hdac_attach2(void *); 427162922Sariff 428162922Sariffstatic uint32_t hdac_command_sendone_internal(struct hdac_softc *, 429162922Sariff uint32_t, int); 430162922Sariffstatic void hdac_command_send_internal(struct hdac_softc *, 431162922Sariff struct hdac_command_list *, int); 432162922Sariff 433162922Sariffstatic int hdac_probe(device_t); 434162922Sariffstatic int hdac_attach(device_t); 435162922Sariffstatic int hdac_detach(device_t); 436162922Sariffstatic void hdac_widget_connection_select(struct hdac_widget *, uint8_t); 437162922Sariffstatic void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *, 438162922Sariff uint32_t, int, int); 439162922Sariffstatic struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *, 440162922Sariff nid_t, int, int); 441162922Sariffstatic void hdac_audio_ctl_amp_set_internal(struct hdac_softc *, 442162922Sariff nid_t, nid_t, int, int, int, int, int, int); 443162922Sariffstatic int hdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *); 444162922Sariffstatic struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t); 445162922Sariff 446162922Sariff#define hdac_command(a1, a2, a3) \ 447162922Sariff hdac_command_sendone_internal(a1, a2, a3) 448162922Sariff 449162922Sariff#define hdac_codec_id(d) \ 450162922Sariff ((uint32_t)((d == NULL) ? 0x00000000 : \ 451162922Sariff ((((uint32_t)(d)->vendor_id & 0x0000ffff) << 16) | \ 452162922Sariff ((uint32_t)(d)->device_id & 0x0000ffff)))) 453162922Sariff 454162922Sariffstatic char * 455162922Sariffhdac_codec_name(struct hdac_devinfo *devinfo) 456162922Sariff{ 457162922Sariff uint32_t id; 458162922Sariff int i; 459162922Sariff 460162922Sariff id = hdac_codec_id(devinfo); 461162922Sariff 462162922Sariff for (i = 0; i < HDAC_CODECS_LEN; i++) { 463162965Sariff if (HDA_FLAG_MATCH(hdac_codecs[i].id, id)) 464162922Sariff return (hdac_codecs[i].name); 465162922Sariff } 466162922Sariff 467162922Sariff return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec"); 468162922Sariff} 469162922Sariff 470162922Sariffstatic char * 471162922Sariffhdac_audio_ctl_ossmixer_mask2name(uint32_t devmask) 472162922Sariff{ 473162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 474162922Sariff static char *unknown = "???"; 475162922Sariff int i; 476162922Sariff 477162922Sariff for (i = SOUND_MIXER_NRDEVICES - 1; i >= 0; i--) { 478162922Sariff if (devmask & (1 << i)) 479162922Sariff return (ossname[i]); 480162922Sariff } 481162922Sariff return (unknown); 482162922Sariff} 483162922Sariff 484162922Sariffstatic void 485162922Sariffhdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len) 486162922Sariff{ 487162922Sariff static char *ossname[] = SOUND_DEVICE_NAMES; 488162922Sariff int i, first = 1; 489162922Sariff 490162922Sariff bzero(buf, len); 491162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 492162922Sariff if (mask & (1 << i)) { 493162922Sariff if (first == 0) 494162922Sariff strlcat(buf, ", ", len); 495162922Sariff strlcat(buf, ossname[i], len); 496162922Sariff first = 0; 497162922Sariff } 498162922Sariff } 499162922Sariff} 500162922Sariff 501162922Sariffstatic struct hdac_audio_ctl * 502162922Sariffhdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index) 503162922Sariff{ 504162922Sariff if (devinfo == NULL || 505162922Sariff devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO || 506162922Sariff index == NULL || devinfo->function.audio.ctl == NULL || 507162922Sariff devinfo->function.audio.ctlcnt < 1 || 508162922Sariff *index < 0 || *index >= devinfo->function.audio.ctlcnt) 509162922Sariff return (NULL); 510162922Sariff return (&devinfo->function.audio.ctl[(*index)++]); 511162922Sariff} 512162922Sariff 513162922Sariffstatic struct hdac_audio_ctl * 514162922Sariffhdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid, 515162922Sariff int index, int cnt) 516162922Sariff{ 517162922Sariff struct hdac_audio_ctl *ctl, *retctl = NULL; 518162922Sariff int i, at, atindex, found = 0; 519162922Sariff 520162922Sariff if (devinfo == NULL || devinfo->function.audio.ctl == NULL) 521162922Sariff return (NULL); 522162922Sariff 523162922Sariff at = cnt; 524162922Sariff if (at == 0) 525162922Sariff at = 1; 526162922Sariff else if (at < 0) 527162922Sariff at = -1; 528162922Sariff atindex = index; 529162922Sariff if (atindex < 0) 530162922Sariff atindex = -1; 531162922Sariff 532162922Sariff i = 0; 533162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 534162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 535162922Sariff continue; 536162922Sariff if (!(ctl->widget->nid == nid && (atindex == -1 || 537162922Sariff ctl->index == atindex))) 538162922Sariff continue; 539162922Sariff found++; 540162922Sariff if (found == cnt) 541162922Sariff return (ctl); 542162922Sariff retctl = ctl; 543162922Sariff } 544162922Sariff 545162922Sariff return ((at == -1) ? retctl : NULL); 546162922Sariff} 547162922Sariff 548162922Sariffstatic void 549162922Sariffhdac_hp_switch_handler(struct hdac_devinfo *devinfo) 550162922Sariff{ 551162922Sariff struct hdac_softc *sc; 552162922Sariff struct hdac_widget *w; 553162922Sariff struct hdac_audio_ctl *ctl; 554162922Sariff uint32_t id, res; 555162922Sariff int i = 0, j, forcemute; 556162922Sariff nid_t cad; 557162922Sariff 558162922Sariff if (devinfo == NULL || devinfo->codec == NULL || 559162922Sariff devinfo->codec->sc == NULL) 560162922Sariff return; 561162922Sariff 562162922Sariff sc = devinfo->codec->sc; 563162922Sariff cad = devinfo->codec->cad; 564162922Sariff id = hdac_codec_id(devinfo); 565162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 566162965Sariff if (HDA_FLAG_MATCH(hdac_hp_switch[i].model, 567162965Sariff sc->pci_subvendor) && 568162922Sariff hdac_hp_switch[i].id == id) 569162922Sariff break; 570162922Sariff } 571162922Sariff 572162922Sariff if (i >= HDAC_HP_SWITCH_LEN) 573162922Sariff return; 574162922Sariff 575162922Sariff forcemute = 0; 576162922Sariff if (hdac_hp_switch[i].eapdnid != -1) { 577162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid); 578162965Sariff if (w != NULL && w->param.eapdbtl != HDAC_INVALID) 579162922Sariff forcemute = (w->param.eapdbtl & 580162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1; 581162922Sariff } 582162922Sariff 583162922Sariff res = hdac_command(sc, 584162922Sariff HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad); 585162922Sariff HDA_BOOTVERBOSE_MSG( 586162922Sariff device_printf(sc->dev, 587162922Sariff "Pin sense: nid=%d res=0x%08x\n", 588162922Sariff hdac_hp_switch[i].hpnid, res); 589162922Sariff ); 590162922Sariff res >>= 31; 591162922Sariff 592162922Sariff switch (hdac_hp_switch[i].type) { 593162922Sariff case HDAC_HP_SWITCH_CTL: 594162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 595162922Sariff hdac_hp_switch[i].hpnid, 0, 1); 596162922Sariff if (ctl != NULL) { 597162922Sariff ctl->muted = (res != 0 && forcemute == 0) ? 598162922Sariff HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL; 599162922Sariff hdac_audio_ctl_amp_set(ctl, 600162922Sariff HDA_AMP_MUTE_DEFAULT, ctl->left, 601162922Sariff ctl->right); 602162922Sariff } 603162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 604162922Sariff ctl = hdac_audio_ctl_amp_get(devinfo, 605162922Sariff hdac_hp_switch[i].spkrnid[j], 0, 1); 606162922Sariff if (ctl != NULL) { 607162922Sariff ctl->muted = (res != 0 || forcemute == 1) ? 608162922Sariff HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE; 609162922Sariff hdac_audio_ctl_amp_set(ctl, 610162922Sariff HDA_AMP_MUTE_DEFAULT, ctl->left, 611162922Sariff ctl->right); 612162922Sariff } 613162922Sariff } 614162922Sariff break; 615162922Sariff case HDAC_HP_SWITCH_CTRL: 616162922Sariff if (res != 0) { 617162922Sariff /* HP in */ 618162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 619162922Sariff if (w != NULL) { 620162922Sariff if (forcemute == 0) 621162922Sariff w->wclass.pin.ctrl |= 622162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 623162922Sariff else 624162922Sariff w->wclass.pin.ctrl &= 625162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 626162922Sariff hdac_command(sc, 627162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 628162922Sariff w->wclass.pin.ctrl), cad); 629162922Sariff } 630162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 631162922Sariff w = hdac_widget_get(devinfo, 632162922Sariff hdac_hp_switch[i].spkrnid[j]); 633162922Sariff if (w != NULL) { 634162922Sariff w->wclass.pin.ctrl &= 635162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 636162922Sariff hdac_command(sc, 637162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 638162922Sariff w->nid, 639162922Sariff w->wclass.pin.ctrl), cad); 640162922Sariff } 641162922Sariff } 642162922Sariff } else { 643162922Sariff /* HP out */ 644162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 645162922Sariff if (w != NULL) { 646162922Sariff w->wclass.pin.ctrl &= 647162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 648162922Sariff hdac_command(sc, 649162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 650162922Sariff w->wclass.pin.ctrl), cad); 651162922Sariff } 652162922Sariff for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) { 653162922Sariff w = hdac_widget_get(devinfo, 654162922Sariff hdac_hp_switch[i].spkrnid[j]); 655162922Sariff if (w != NULL) { 656162922Sariff if (forcemute == 0) 657162922Sariff w->wclass.pin.ctrl |= 658162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 659162922Sariff else 660162922Sariff w->wclass.pin.ctrl &= 661162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 662162922Sariff hdac_command(sc, 663162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, 664162922Sariff w->nid, 665162922Sariff w->wclass.pin.ctrl), cad); 666162922Sariff } 667162922Sariff } 668162922Sariff } 669162922Sariff break; 670162922Sariff default: 671162922Sariff break; 672162922Sariff } 673162922Sariff} 674162922Sariff 675162922Sariffstatic void 676162922Sariffhdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag) 677162922Sariff{ 678162922Sariff struct hdac_softc *sc; 679162922Sariff struct hdac_devinfo *devinfo = NULL; 680162965Sariff device_t *devlist = NULL; 681162922Sariff int devcount, i; 682162922Sariff 683162922Sariff if (codec == NULL || codec->sc == NULL) 684162922Sariff return; 685162922Sariff 686162922Sariff sc = codec->sc; 687162922Sariff 688162922Sariff HDA_BOOTVERBOSE_MSG( 689162922Sariff device_printf(sc->dev, "Unsol Tag: 0x%08x\n", tag); 690162922Sariff ); 691162922Sariff 692162922Sariff device_get_children(sc->dev, &devlist, &devcount); 693162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 694162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 695162965Sariff if (devinfo != NULL && devinfo->node_type == 696162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 697162965Sariff devinfo->codec != NULL && 698162965Sariff devinfo->codec->cad == codec->cad) { 699162965Sariff break; 700162965Sariff } else 701162965Sariff devinfo = NULL; 702162922Sariff } 703162965Sariff if (devlist != NULL) 704162965Sariff free(devlist, M_TEMP); 705162965Sariff 706162922Sariff if (devinfo == NULL) 707162922Sariff return; 708162922Sariff 709162922Sariff switch (tag) { 710162922Sariff case HDAC_UNSOLTAG_EVENT_HP: 711162922Sariff hdac_hp_switch_handler(devinfo); 712162922Sariff break; 713162922Sariff default: 714162922Sariff break; 715162922Sariff } 716162922Sariff} 717162922Sariff 718162922Sariffstatic void 719162922Sariffhdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch) 720162922Sariff{ 721162922Sariff /* XXX to be removed */ 722162922Sariff#ifdef HDAC_INTR_EXTRA 723162922Sariff uint32_t res; 724162922Sariff#endif 725162922Sariff 726162922Sariff if (ch->blkcnt == 0) 727162922Sariff return; 728162922Sariff 729162922Sariff /* XXX to be removed */ 730162922Sariff#ifdef HDAC_INTR_EXTRA 731162922Sariff res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS); 732162922Sariff#endif 733162922Sariff 734162922Sariff /* XXX to be removed */ 735162922Sariff#ifdef HDAC_INTR_EXTRA 736162922Sariff if ((res & HDAC_SDSTS_DESE) || (res & HDAC_SDSTS_FIFOE)) 737162922Sariff device_printf(sc->dev, 738162922Sariff "PCMDIR_%s intr triggered beyond stream boundary: %08x\n", 739162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res); 740162922Sariff#endif 741162922Sariff 742162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS, 743162922Sariff HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 744162922Sariff 745162922Sariff /* XXX to be removed */ 746162922Sariff#ifdef HDAC_INTR_EXTRA 747162922Sariff if (res & HDAC_SDSTS_BCIS) { 748162922Sariff#endif 749162922Sariff ch->prevptr = ch->ptr; 750162922Sariff ch->ptr += sndbuf_getblksz(ch->b); 751162922Sariff ch->ptr %= sndbuf_getsize(ch->b); 752162922Sariff hdac_unlock(sc); 753162922Sariff chn_intr(ch->c); 754162922Sariff hdac_lock(sc); 755162922Sariff /* XXX to be removed */ 756162922Sariff#ifdef HDAC_INTR_EXTRA 757162922Sariff } 758162922Sariff#endif 759162922Sariff} 760162922Sariff 761162922Sariff/**************************************************************************** 762162922Sariff * void hdac_intr_handler(void *) 763162922Sariff * 764162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 765162922Sariff ****************************************************************************/ 766162922Sariffstatic void 767162922Sariffhdac_intr_handler(void *context) 768162922Sariff{ 769162922Sariff struct hdac_softc *sc; 770162922Sariff uint32_t intsts; 771162922Sariff uint8_t rirbsts; 772162922Sariff uint8_t rirbwp; 773162922Sariff struct hdac_rirb *rirb_base, *rirb; 774162922Sariff nid_t ucad; 775162922Sariff uint32_t utag; 776162922Sariff 777162922Sariff sc = (struct hdac_softc *)context; 778162922Sariff 779162922Sariff hdac_lock(sc); 780162922Sariff /* Do we have anything to do? */ 781162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 782162922Sariff if ((intsts & HDAC_INTSTS_GIS) != HDAC_INTSTS_GIS) { 783162922Sariff hdac_unlock(sc); 784162922Sariff return; 785162922Sariff } 786162922Sariff 787162922Sariff /* Was this a controller interrupt? */ 788162922Sariff if ((intsts & HDAC_INTSTS_CIS) == HDAC_INTSTS_CIS) { 789162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 790162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 791162922Sariff /* Get as many responses that we can */ 792162922Sariff while ((rirbsts & HDAC_RIRBSTS_RINTFL) == HDAC_RIRBSTS_RINTFL) { 793162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 794162922Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 795162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 796162922Sariff BUS_DMASYNC_POSTREAD); 797162922Sariff while (sc->rirb_rp != rirbwp) { 798162922Sariff sc->rirb_rp++; 799162922Sariff sc->rirb_rp %= sc->rirb_size; 800162922Sariff rirb = &rirb_base[sc->rirb_rp]; 801162922Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 802162922Sariff ucad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 803162922Sariff utag = rirb->response >> 26; 804162922Sariff if (ucad > -1 && ucad < HDAC_CODEC_MAX && 805162922Sariff sc->codecs[ucad] != NULL) { 806162922Sariff sc->unsolq[sc->unsolq_wp++] = 807162922Sariff (ucad << 16) | 808162922Sariff (utag & 0xffff); 809162922Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 810162922Sariff } 811162922Sariff } 812162922Sariff } 813162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 814162922Sariff } 815162922Sariff /* XXX to be removed */ 816162922Sariff /* Clear interrupt and exit */ 817162922Sariff#ifdef HDAC_INTR_EXTRA 818162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS); 819162922Sariff#endif 820162922Sariff } 821162922Sariff if ((intsts & HDAC_INTSTS_SIS_MASK)) { 822162922Sariff if (intsts & (1 << sc->num_iss)) 823162922Sariff hdac_stream_intr(sc, &sc->play); 824162922Sariff if (intsts & (1 << 0)) 825162922Sariff hdac_stream_intr(sc, &sc->rec); 826162922Sariff /* XXX to be removed */ 827162922Sariff#ifdef HDAC_INTR_EXTRA 828162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & HDAC_INTSTS_SIS_MASK); 829162922Sariff#endif 830162922Sariff } 831162922Sariff 832162922Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 833162922Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 834162922Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 835162922Sariff ucad = sc->unsolq[sc->unsolq_rp] >> 16; 836162922Sariff utag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 837162922Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 838162922Sariff hdac_unsolicited_handler(sc->codecs[ucad], utag); 839162922Sariff } 840162922Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 841162922Sariff } 842162922Sariff 843162922Sariff hdac_unlock(sc); 844162922Sariff} 845162922Sariff 846162922Sariff/**************************************************************************** 847162922Sariff * int had_reset(hdac_softc *) 848162922Sariff * 849162922Sariff * Reset the hdac to a quiescent and known state. 850162922Sariff ****************************************************************************/ 851162922Sariffstatic int 852162922Sariffhdac_reset(struct hdac_softc *sc) 853162922Sariff{ 854162922Sariff uint32_t gctl; 855162922Sariff int count, i; 856162922Sariff 857162922Sariff /* 858162922Sariff * Stop all Streams DMA engine 859162922Sariff */ 860162922Sariff for (i = 0; i < sc->num_iss; i++) 861162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 862162922Sariff for (i = 0; i < sc->num_oss; i++) 863162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 864162922Sariff for (i = 0; i < sc->num_bss; i++) 865162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 866162922Sariff 867162922Sariff /* 868162922Sariff * Stop Control DMA engines 869162922Sariff */ 870162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 871162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 872162922Sariff 873162922Sariff /* 874162922Sariff * Reset the controller. The reset must remain asserted for 875162922Sariff * a minimum of 100us. 876162922Sariff */ 877162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 878162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 879162922Sariff count = 10000; 880162922Sariff do { 881162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 882162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 883162922Sariff break; 884162922Sariff DELAY(10); 885162922Sariff } while (--count); 886162922Sariff if (gctl & HDAC_GCTL_CRST) { 887162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 888162922Sariff return (ENXIO); 889162922Sariff } 890162922Sariff DELAY(100); 891162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 892162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 893162922Sariff count = 10000; 894162922Sariff do { 895162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 896162922Sariff if ((gctl & HDAC_GCTL_CRST)) 897162922Sariff break; 898162922Sariff DELAY(10); 899162922Sariff } while (--count); 900162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 901162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 902162922Sariff return (ENXIO); 903162922Sariff } 904162922Sariff 905162922Sariff /* 906162922Sariff * Enable unsolicited interrupt. 907162922Sariff */ 908162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 909162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_UNSOL); 910162922Sariff 911162922Sariff /* 912162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 913162922Sariff * should be of 250us but for some reasons, on it's not enough on my 914162922Sariff * computer. Let's use twice as much as necessary to make sure that 915162922Sariff * it's reset properly. 916162922Sariff */ 917162922Sariff DELAY(1000); 918162922Sariff 919162922Sariff return (0); 920162922Sariff} 921162922Sariff 922162922Sariff 923162922Sariff/**************************************************************************** 924162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 925162922Sariff * 926162922Sariff * Retreive the general capabilities of the hdac; 927162922Sariff * Number of Input Streams 928162922Sariff * Number of Output Streams 929162922Sariff * Number of bidirectional Streams 930162922Sariff * 64bit ready 931162922Sariff * CORB and RIRB sizes 932162922Sariff ****************************************************************************/ 933162922Sariffstatic int 934162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 935162922Sariff{ 936162922Sariff uint16_t gcap; 937162922Sariff uint8_t corbsize, rirbsize; 938162922Sariff 939162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 940162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 941162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 942162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 943162922Sariff 944162922Sariff sc->support_64bit = (gcap & HDAC_GCAP_64OK) == HDAC_GCAP_64OK; 945162922Sariff 946162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 947162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 948162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 949162922Sariff sc->corb_size = 256; 950162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 951162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 952162922Sariff sc->corb_size = 16; 953162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 954162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 955162922Sariff sc->corb_size = 2; 956162922Sariff else { 957162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 958162922Sariff __func__, corbsize); 959162922Sariff return (ENXIO); 960162922Sariff } 961162922Sariff 962162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 963162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 964162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 965162922Sariff sc->rirb_size = 256; 966162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 967162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 968162922Sariff sc->rirb_size = 16; 969162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 970162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 971162922Sariff sc->rirb_size = 2; 972162922Sariff else { 973162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 974162922Sariff __func__, rirbsize); 975162922Sariff return (ENXIO); 976162922Sariff } 977162922Sariff 978162922Sariff return (0); 979162922Sariff} 980162922Sariff 981162922Sariff 982162922Sariff/**************************************************************************** 983162922Sariff * void hdac_dma_cb 984162922Sariff * 985162922Sariff * This function is called by bus_dmamap_load when the mapping has been 986162922Sariff * established. We just record the physical address of the mapping into 987162922Sariff * the struct hdac_dma passed in. 988162922Sariff ****************************************************************************/ 989162922Sariffstatic void 990162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 991162922Sariff{ 992162922Sariff struct hdac_dma *dma; 993162922Sariff 994162922Sariff if (error == 0) { 995162922Sariff dma = (struct hdac_dma *)callback_arg; 996162922Sariff dma->dma_paddr = segs[0].ds_addr; 997162922Sariff } 998162922Sariff} 999162922Sariff 1000162922Sariffstatic void 1001162922Sariffhdac_dma_nocache(void *ptr) 1002162922Sariff{ 1003162956Sariff#if defined(__i386__) || defined(__amd64__) 1004162922Sariff pt_entry_t *pte; 1005162922Sariff vm_offset_t va; 1006162922Sariff 1007162922Sariff va = (vm_offset_t)ptr; 1008162922Sariff pte = vtopte(va); 1009162922Sariff if (pte) { 1010162922Sariff *pte |= PG_N; 1011162922Sariff invltlb(); 1012162922Sariff } 1013162956Sariff#endif 1014162922Sariff} 1015162922Sariff 1016162922Sariff/**************************************************************************** 1017162922Sariff * int hdac_dma_alloc 1018162922Sariff * 1019162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 1020162922Sariff * It must be freed by a corresponding hdac_dma_free. 1021162922Sariff ****************************************************************************/ 1022162922Sariffstatic int 1023162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 1024162922Sariff{ 1025162922Sariff int result; 1026162922Sariff int lowaddr; 1027162922Sariff 1028162922Sariff lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1029162922Sariff BUS_SPACE_MAXADDR_32BIT; 1030162922Sariff bzero(dma, sizeof(*dma)); 1031162922Sariff 1032162922Sariff /* 1033162922Sariff * Create a DMA tag 1034162922Sariff */ 1035162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 1036162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 1037162922Sariff 0, /* boundary */ 1038162922Sariff lowaddr, /* lowaddr */ 1039162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 1040162922Sariff NULL, /* filtfunc */ 1041162922Sariff NULL, /* fistfuncarg */ 1042162922Sariff size, /* maxsize */ 1043162922Sariff 1, /* nsegments */ 1044162922Sariff size, /* maxsegsz */ 1045162922Sariff 0, /* flags */ 1046162922Sariff NULL, /* lockfunc */ 1047162922Sariff NULL, /* lockfuncarg */ 1048162922Sariff &dma->dma_tag); /* dmat */ 1049162922Sariff if (result != 0) { 1050162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 1051162922Sariff __func__, result); 1052162922Sariff goto fail; 1053162922Sariff } 1054162922Sariff 1055162922Sariff /* 1056162922Sariff * Allocate DMA memory 1057162922Sariff */ 1058162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1059162922Sariff BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); 1060162922Sariff if (result != 0) { 1061162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 1062162922Sariff __func__, result); 1063162922Sariff goto fail; 1064162922Sariff } 1065162922Sariff 1066162922Sariff /* 1067162922Sariff * Map the memory 1068162922Sariff */ 1069162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 1070162922Sariff (void *)dma->dma_vaddr, size, hdac_dma_cb, (void *)dma, 1071162922Sariff BUS_DMA_NOWAIT); 1072162922Sariff if (result != 0 || dma->dma_paddr == 0) { 1073162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 1074162922Sariff __func__, result); 1075162922Sariff goto fail; 1076162922Sariff } 1077162922Sariff bzero((void *)dma->dma_vaddr, size); 1078162922Sariff hdac_dma_nocache(dma->dma_vaddr); 1079162922Sariff 1080162922Sariff return (0); 1081162922Sarifffail: 1082162922Sariff if (dma->dma_map != NULL) 1083162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1084162922Sariff if (dma->dma_tag != NULL) 1085162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1086162922Sariff return (result); 1087162922Sariff} 1088162922Sariff 1089162922Sariff 1090162922Sariff/**************************************************************************** 1091162922Sariff * void hdac_dma_free(struct hdac_dma *) 1092162922Sariff * 1093162922Sariff * Free a struct dhac_dma that has been previously allocated via the 1094162922Sariff * hdac_dma_alloc function. 1095162922Sariff ****************************************************************************/ 1096162922Sariffstatic void 1097162922Sariffhdac_dma_free(struct hdac_dma *dma) 1098162922Sariff{ 1099162922Sariff if (dma->dma_tag != NULL) { 1100162922Sariff /* Flush caches */ 1101162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 1102162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1103162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1104162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1105162922Sariff bus_dma_tag_destroy(dma->dma_tag); 1106162922Sariff } 1107162922Sariff} 1108162922Sariff 1109162922Sariff/**************************************************************************** 1110162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 1111162922Sariff * 1112162922Sariff * Allocate all the bus resources necessary to speak with the physical 1113162922Sariff * controller. 1114162922Sariff ****************************************************************************/ 1115162922Sariffstatic int 1116162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 1117162922Sariff{ 1118162922Sariff struct hdac_mem *mem; 1119162922Sariff 1120162922Sariff mem = &sc->mem; 1121162922Sariff mem->mem_rid = PCIR_BAR(0); 1122162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 1123162922Sariff &mem->mem_rid, RF_ACTIVE); 1124162922Sariff if (mem->mem_res == NULL) { 1125162922Sariff device_printf(sc->dev, 1126162922Sariff "%s: Unable to allocate memory resource\n", __func__); 1127162922Sariff return (ENOMEM); 1128162922Sariff } 1129162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 1130162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 1131162922Sariff 1132162922Sariff return (0); 1133162922Sariff} 1134162922Sariff 1135162922Sariff/**************************************************************************** 1136162922Sariff * void hdac_mem_free(struct hdac_softc *) 1137162922Sariff * 1138162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 1139162922Sariff ****************************************************************************/ 1140162922Sariffstatic void 1141162922Sariffhdac_mem_free(struct hdac_softc *sc) 1142162922Sariff{ 1143162922Sariff struct hdac_mem *mem; 1144162922Sariff 1145162922Sariff mem = &sc->mem; 1146162922Sariff if (mem->mem_res != NULL) 1147162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 1148162922Sariff mem->mem_res); 1149162922Sariff} 1150162922Sariff 1151162922Sariff/**************************************************************************** 1152162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 1153162922Sariff * 1154162922Sariff * Allocate and setup the resources necessary for interrupt handling. 1155162922Sariff ****************************************************************************/ 1156162922Sariffstatic int 1157162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 1158162922Sariff{ 1159162922Sariff struct hdac_irq *irq; 1160162922Sariff int result; 1161162922Sariff 1162162922Sariff irq = &sc->irq; 1163162922Sariff irq->irq_rid = 0x0; 1164162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 1165162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 1166162922Sariff if (irq->irq_res == NULL) { 1167162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 1168162922Sariff __func__); 1169162922Sariff goto fail; 1170162922Sariff } 1171162922Sariff result = snd_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE, 1172162922Sariff hdac_intr_handler, sc, &irq->irq_handle); 1173162922Sariff if (result != 0) { 1174162922Sariff device_printf(sc->dev, 1175162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 1176162922Sariff __func__, result); 1177162922Sariff goto fail; 1178162922Sariff } 1179162922Sariff 1180162922Sariff return (0); 1181162922Sariff 1182162922Sarifffail: 1183162922Sariff if (irq->irq_res != NULL) 1184162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1185162922Sariff irq->irq_res); 1186162922Sariff return (ENXIO); 1187162922Sariff} 1188162922Sariff 1189162922Sariff/**************************************************************************** 1190162922Sariff * void hdac_irq_free(struct hdac_softc *) 1191162922Sariff * 1192162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 1193162922Sariff ****************************************************************************/ 1194162922Sariffstatic void 1195162922Sariffhdac_irq_free(struct hdac_softc *sc) 1196162922Sariff{ 1197162922Sariff struct hdac_irq *irq; 1198162922Sariff 1199162922Sariff irq = &sc->irq; 1200162922Sariff if (irq->irq_handle != NULL) 1201162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 1202162922Sariff if (irq->irq_res != NULL) 1203162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 1204162922Sariff irq->irq_res); 1205162922Sariff} 1206162922Sariff 1207162922Sariff/**************************************************************************** 1208162922Sariff * void hdac_corb_init(struct hdac_softc *) 1209162922Sariff * 1210162922Sariff * Initialize the corb registers for operations but do not start it up yet. 1211162922Sariff * The CORB engine must not be running when this function is called. 1212162922Sariff ****************************************************************************/ 1213162922Sariffstatic void 1214162922Sariffhdac_corb_init(struct hdac_softc *sc) 1215162922Sariff{ 1216162922Sariff uint8_t corbsize; 1217162922Sariff uint64_t corbpaddr; 1218162922Sariff 1219162922Sariff /* Setup the CORB size. */ 1220162922Sariff switch (sc->corb_size) { 1221162922Sariff case 256: 1222162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 1223162922Sariff break; 1224162922Sariff case 16: 1225162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 1226162922Sariff break; 1227162922Sariff case 2: 1228162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 1229162922Sariff break; 1230162922Sariff default: 1231162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 1232162922Sariff } 1233162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 1234162922Sariff 1235162922Sariff /* Setup the CORB Address in the hdac */ 1236162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 1237162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 1238162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 1239162922Sariff 1240162922Sariff /* Set the WP and RP */ 1241162922Sariff sc->corb_wp = 0; 1242162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 1243162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 1244162922Sariff /* 1245162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 1246162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 1247162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 1248162922Sariff * manually reset the bit to zero before continuing. 1249162922Sariff */ 1250162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 1251162922Sariff 1252162922Sariff /* Enable CORB error reporting */ 1253162922Sariff#if 0 1254162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 1255162922Sariff#endif 1256162922Sariff} 1257162922Sariff 1258162922Sariff/**************************************************************************** 1259162922Sariff * void hdac_rirb_init(struct hdac_softc *) 1260162922Sariff * 1261162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 1262162922Sariff * The RIRB engine must not be running when this function is called. 1263162922Sariff ****************************************************************************/ 1264162922Sariffstatic void 1265162922Sariffhdac_rirb_init(struct hdac_softc *sc) 1266162922Sariff{ 1267162922Sariff uint8_t rirbsize; 1268162922Sariff uint64_t rirbpaddr; 1269162922Sariff 1270162922Sariff /* Setup the RIRB size. */ 1271162922Sariff switch (sc->rirb_size) { 1272162922Sariff case 256: 1273162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 1274162922Sariff break; 1275162922Sariff case 16: 1276162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 1277162922Sariff break; 1278162922Sariff case 2: 1279162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 1280162922Sariff break; 1281162922Sariff default: 1282162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 1283162922Sariff } 1284162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 1285162922Sariff 1286162922Sariff /* Setup the RIRB Address in the hdac */ 1287162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 1288162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 1289162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 1290162922Sariff 1291162922Sariff /* Setup the WP and RP */ 1292162922Sariff sc->rirb_rp = 0; 1293162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 1294162922Sariff 1295162922Sariff /* Setup the interrupt threshold */ 1296162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 1297162922Sariff 1298162922Sariff /* Enable Overrun and response received reporting */ 1299162922Sariff#if 0 1300162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 1301162922Sariff HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 1302162922Sariff#else 1303162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 1304162922Sariff#endif 1305162922Sariff 1306162922Sariff /* 1307162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 1308162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 1309162922Sariff * should be sufficient to do this only once as the rirb is purely 1310162922Sariff * read-only from now on. 1311162922Sariff */ 1312162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 1313162922Sariff BUS_DMASYNC_PREREAD); 1314162922Sariff} 1315162922Sariff 1316162922Sariff/**************************************************************************** 1317162922Sariff * void hdac_corb_start(hdac_softc *) 1318162922Sariff * 1319162922Sariff * Startup the corb DMA engine 1320162922Sariff ****************************************************************************/ 1321162922Sariffstatic void 1322162922Sariffhdac_corb_start(struct hdac_softc *sc) 1323162922Sariff{ 1324162922Sariff uint32_t corbctl; 1325162922Sariff 1326162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 1327162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 1328162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 1329162922Sariff} 1330162922Sariff 1331162922Sariff/**************************************************************************** 1332162922Sariff * void hdac_rirb_start(hdac_softc *) 1333162922Sariff * 1334162922Sariff * Startup the rirb DMA engine 1335162922Sariff ****************************************************************************/ 1336162922Sariffstatic void 1337162922Sariffhdac_rirb_start(struct hdac_softc *sc) 1338162922Sariff{ 1339162922Sariff uint32_t rirbctl; 1340162922Sariff 1341162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 1342162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 1343162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 1344162922Sariff} 1345162922Sariff 1346162922Sariff 1347162922Sariff/**************************************************************************** 1348162922Sariff * void hdac_scan_codecs(struct hdac_softc *) 1349162922Sariff * 1350162922Sariff * Scan the bus for available codecs. 1351162922Sariff ****************************************************************************/ 1352162922Sariffstatic void 1353162922Sariffhdac_scan_codecs(struct hdac_softc *sc) 1354162922Sariff{ 1355162922Sariff struct hdac_codec *codec; 1356162922Sariff int i; 1357162922Sariff uint16_t statests; 1358162922Sariff 1359162922Sariff SLIST_INIT(&sc->codec_list); 1360162922Sariff 1361162922Sariff statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1362162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) { 1363162922Sariff if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1364162922Sariff /* We have found a codec. */ 1365162922Sariff hdac_unlock(sc); 1366162922Sariff codec = (struct hdac_codec *)malloc(sizeof(*codec), 1367162922Sariff M_HDAC, M_ZERO | M_NOWAIT); 1368162922Sariff hdac_lock(sc); 1369162922Sariff if (codec == NULL) { 1370162922Sariff device_printf(sc->dev, 1371162922Sariff "Unable to allocate memory for codec\n"); 1372162922Sariff continue; 1373162922Sariff } 1374162922Sariff codec->verbs_sent = 0; 1375162922Sariff codec->sc = sc; 1376162922Sariff codec->cad = i; 1377162922Sariff sc->codecs[i] = codec; 1378162922Sariff SLIST_INSERT_HEAD(&sc->codec_list, codec, next_codec); 1379162922Sariff if (hdac_probe_codec(codec) != 0) 1380162922Sariff break; 1381162922Sariff } 1382162922Sariff } 1383162922Sariff /* All codecs have been probed, now try to attach drivers to them */ 1384162922Sariff bus_generic_attach(sc->dev); 1385162922Sariff} 1386162922Sariff 1387162922Sariff/**************************************************************************** 1388162922Sariff * void hdac_probe_codec(struct hdac_softc *, int) 1389162922Sariff * 1390162922Sariff * Probe a the given codec_id for available function groups. 1391162922Sariff ****************************************************************************/ 1392162922Sariffstatic int 1393162922Sariffhdac_probe_codec(struct hdac_codec *codec) 1394162922Sariff{ 1395162922Sariff struct hdac_softc *sc = codec->sc; 1396162922Sariff struct hdac_devinfo *devinfo; 1397162922Sariff uint32_t vendorid, revisionid, subnode; 1398162922Sariff int startnode; 1399162922Sariff int endnode; 1400162922Sariff int i; 1401162922Sariff nid_t cad = codec->cad; 1402162922Sariff 1403162922Sariff HDA_DEBUG_MSG( 1404162922Sariff device_printf(sc->dev, "%s: Probing codec: %d\n", 1405162922Sariff __func__, cad); 1406162922Sariff ); 1407162922Sariff vendorid = hdac_command(sc, 1408162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID), 1409162922Sariff cad); 1410162922Sariff revisionid = hdac_command(sc, 1411162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID), 1412162922Sariff cad); 1413162922Sariff subnode = hdac_command(sc, 1414162922Sariff HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT), 1415162922Sariff cad); 1416162922Sariff startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); 1417162922Sariff endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); 1418162922Sariff 1419162922Sariff HDA_DEBUG_MSG( 1420162922Sariff device_printf(sc->dev, "%s: \tstartnode=%d endnode=%d\n", 1421162922Sariff __func__, startnode, endnode); 1422162922Sariff ); 1423162922Sariff for (i = startnode; i < endnode; i++) { 1424162922Sariff devinfo = hdac_probe_function(codec, i); 1425162922Sariff if (devinfo != NULL) { 1426162922Sariff /* XXX Ignore other FG. */ 1427162922Sariff devinfo->vendor_id = 1428162922Sariff HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1429162922Sariff devinfo->device_id = 1430162922Sariff HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1431162922Sariff devinfo->revision_id = 1432162922Sariff HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1433162922Sariff devinfo->stepping_id = 1434162922Sariff HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1435162922Sariff HDA_DEBUG_MSG( 1436162922Sariff device_printf(sc->dev, 1437162922Sariff "%s: \tFound AFG nid=%d " 1438162922Sariff "[startnode=%d endnode=%d]\n", 1439162922Sariff __func__, devinfo->nid, 1440162922Sariff startnode, endnode); 1441162922Sariff ); 1442162922Sariff return (1); 1443162922Sariff } 1444162922Sariff } 1445162922Sariff 1446162922Sariff HDA_DEBUG_MSG( 1447162922Sariff device_printf(sc->dev, "%s: \tAFG not found\n", 1448162922Sariff __func__); 1449162922Sariff ); 1450162922Sariff return (0); 1451162922Sariff} 1452162922Sariff 1453162922Sariffstatic struct hdac_devinfo * 1454162922Sariffhdac_probe_function(struct hdac_codec *codec, nid_t nid) 1455162922Sariff{ 1456162922Sariff struct hdac_softc *sc = codec->sc; 1457162922Sariff struct hdac_devinfo *devinfo; 1458162922Sariff uint32_t fctgrptype; 1459162922Sariff nid_t cad = codec->cad; 1460162922Sariff 1461162965Sariff fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc, 1462162965Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad)); 1463162922Sariff 1464162922Sariff /* XXX For now, ignore other FG. */ 1465162965Sariff if (fctgrptype != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) 1466162922Sariff return (NULL); 1467162922Sariff 1468162922Sariff hdac_unlock(sc); 1469162922Sariff devinfo = (struct hdac_devinfo *)malloc(sizeof(*devinfo), M_HDAC, 1470162922Sariff M_NOWAIT | M_ZERO); 1471162922Sariff hdac_lock(sc); 1472162922Sariff if (devinfo == NULL) { 1473162922Sariff device_printf(sc->dev, "%s: Unable to allocate ivar\n", 1474162922Sariff __func__); 1475162922Sariff return (NULL); 1476162922Sariff } 1477162922Sariff 1478162922Sariff devinfo->nid = nid; 1479162965Sariff devinfo->node_type = fctgrptype; 1480162922Sariff devinfo->codec = codec; 1481162922Sariff 1482162922Sariff hdac_add_child(sc, devinfo); 1483162922Sariff 1484162922Sariff return (devinfo); 1485162922Sariff} 1486162922Sariff 1487162922Sariffstatic void 1488162922Sariffhdac_add_child(struct hdac_softc *sc, struct hdac_devinfo *devinfo) 1489162922Sariff{ 1490162922Sariff devinfo->dev = device_add_child(sc->dev, NULL, -1); 1491162922Sariff device_set_ivars(devinfo->dev, (void *)devinfo); 1492162922Sariff /* XXX - Print more information when booting verbose??? */ 1493162922Sariff} 1494162922Sariff 1495162922Sariffstatic void 1496162922Sariffhdac_widget_connection_parse(struct hdac_widget *w) 1497162922Sariff{ 1498162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1499162922Sariff uint32_t res; 1500162922Sariff int i, j, max, found, entnum, cnid; 1501162922Sariff nid_t cad = w->devinfo->codec->cad; 1502162922Sariff nid_t nid = w->nid; 1503162922Sariff 1504162922Sariff res = hdac_command(sc, 1505162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); 1506162922Sariff 1507162922Sariff w->nconns = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res); 1508162922Sariff 1509162922Sariff if (w->nconns < 1) 1510162922Sariff return; 1511162922Sariff 1512162922Sariff entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4; 1513162922Sariff res = 0; 1514162922Sariff i = 0; 1515162922Sariff found = 0; 1516162922Sariff max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1; 1517162922Sariff 1518162922Sariff while (i < w->nconns) { 1519162922Sariff res = hdac_command(sc, 1520162922Sariff HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); 1521162922Sariff for (j = 0; j < entnum; j++) { 1522162922Sariff cnid = res; 1523162922Sariff cnid >>= (32 / entnum) * j; 1524162922Sariff cnid &= (1 << (32 / entnum)) - 1; 1525162922Sariff if (cnid == 0) 1526162922Sariff continue; 1527162922Sariff if (found > max) { 1528162922Sariff device_printf(sc->dev, 1529162922Sariff "node %d: Adding %d: " 1530162922Sariff "Max connection reached!\n", 1531162922Sariff nid, cnid); 1532162922Sariff continue; 1533162922Sariff } 1534162922Sariff w->conns[found++] = cnid; 1535162922Sariff } 1536162922Sariff i += entnum; 1537162922Sariff } 1538162922Sariff 1539162922Sariff HDA_BOOTVERBOSE_MSG( 1540162922Sariff if (w->nconns != found) { 1541162922Sariff device_printf(sc->dev, 1542162922Sariff "node %d: WARNING!!! Connection " 1543162922Sariff "length=%d != found=%d\n", 1544162922Sariff nid, w->nconns, found); 1545162922Sariff } 1546162922Sariff ); 1547162922Sariff} 1548162922Sariff 1549162922Sariffstatic uint32_t 1550162922Sariffhdac_widget_pin_getconfig(struct hdac_widget *w) 1551162922Sariff{ 1552162922Sariff struct hdac_softc *sc; 1553162922Sariff uint32_t config, id; 1554162922Sariff nid_t cad, nid; 1555162922Sariff 1556162922Sariff sc = w->devinfo->codec->sc; 1557162922Sariff cad = w->devinfo->codec->cad; 1558162922Sariff nid = w->nid; 1559162922Sariff id = hdac_codec_id(w->devinfo); 1560162922Sariff 1561162922Sariff config = hdac_command(sc, 1562162922Sariff HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid), 1563162922Sariff cad); 1564162965Sariff /* 1565162965Sariff * XXX REWRITE!!!! Don't argue! 1566162965Sariff */ 1567162922Sariff if (id == HDA_CODEC_ALC880 && 1568162965Sariff (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR || 1569162965Sariff sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) { 1570162922Sariff /* 1571162965Sariff * Super broken BIOS 1572162922Sariff */ 1573162922Sariff switch (nid) { 1574162922Sariff case 20: 1575162922Sariff break; 1576162922Sariff case 21: 1577162922Sariff break; 1578162922Sariff case 22: 1579162922Sariff break; 1580162922Sariff case 23: 1581162922Sariff break; 1582162922Sariff case 24: /* MIC1 */ 1583162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1584162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 1585162922Sariff break; 1586162922Sariff case 25: /* XXX MIC2 */ 1587162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1588162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 1589162922Sariff break; 1590162922Sariff case 26: /* LINE1 */ 1591162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1592162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1593162922Sariff break; 1594162922Sariff case 27: /* XXX LINE2 */ 1595162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1596162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 1597162922Sariff break; 1598162922Sariff case 28: /* CD */ 1599162922Sariff config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 1600162922Sariff config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 1601162922Sariff break; 1602162922Sariff case 30: 1603162922Sariff break; 1604162922Sariff case 31: 1605162922Sariff break; 1606162922Sariff default: 1607162922Sariff break; 1608162922Sariff } 1609162922Sariff } 1610162922Sariff 1611162922Sariff return (config); 1612162922Sariff} 1613162922Sariff 1614162922Sariffstatic void 1615162922Sariffhdac_widget_pin_parse(struct hdac_widget *w) 1616162922Sariff{ 1617162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1618162922Sariff uint32_t config, pincap; 1619162922Sariff char *devstr, *connstr; 1620162922Sariff nid_t cad = w->devinfo->codec->cad; 1621162922Sariff nid_t nid = w->nid; 1622162922Sariff 1623162922Sariff config = hdac_widget_pin_getconfig(w); 1624162922Sariff w->wclass.pin.config = config; 1625162922Sariff 1626162922Sariff pincap = hdac_command(sc, 1627162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad); 1628162922Sariff w->wclass.pin.cap = pincap; 1629162922Sariff 1630162922Sariff w->wclass.pin.ctrl = hdac_command(sc, 1631162922Sariff HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad) & 1632162922Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 1633162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 1634162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE); 1635162922Sariff 1636162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 1637162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 1638162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 1639162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE; 1640162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 1641162922Sariff w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 1642162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) { 1643162922Sariff w->param.eapdbtl = hdac_command(sc, 1644162922Sariff HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad); 1645162922Sariff w->param.eapdbtl &= 0x7; 1646162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 1647162922Sariff } else 1648162965Sariff w->param.eapdbtl = HDAC_INVALID; 1649162922Sariff 1650162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) { 1651162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: 1652162922Sariff devstr = "line out"; 1653162922Sariff break; 1654162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: 1655162922Sariff devstr = "speaker"; 1656162922Sariff break; 1657162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: 1658162922Sariff devstr = "headphones out"; 1659162922Sariff break; 1660162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 1661162922Sariff devstr = "CD"; 1662162922Sariff break; 1663162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: 1664162922Sariff devstr = "SPDIF out"; 1665162922Sariff break; 1666162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: 1667162922Sariff devstr = "digital (other) out"; 1668162922Sariff break; 1669162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE: 1670162922Sariff devstr = "modem, line side"; 1671162922Sariff break; 1672162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET: 1673162922Sariff devstr = "modem, handset side"; 1674162922Sariff break; 1675162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 1676162922Sariff devstr = "line in"; 1677162922Sariff break; 1678162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: 1679162922Sariff devstr = "AUX"; 1680162922Sariff break; 1681162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 1682162922Sariff devstr = "Mic in"; 1683162922Sariff break; 1684162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY: 1685162922Sariff devstr = "telephony"; 1686162922Sariff break; 1687162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: 1688162922Sariff devstr = "SPDIF in"; 1689162922Sariff break; 1690162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: 1691162922Sariff devstr = "digital (other) in"; 1692162922Sariff break; 1693162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER: 1694162922Sariff devstr = "other"; 1695162922Sariff break; 1696162922Sariff default: 1697162922Sariff devstr = "unknown"; 1698162922Sariff break; 1699162922Sariff } 1700162922Sariff 1701162922Sariff switch (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) { 1702162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK: 1703162922Sariff connstr = "jack"; 1704162922Sariff break; 1705162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE: 1706162922Sariff connstr = "none"; 1707162922Sariff break; 1708162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED: 1709162922Sariff connstr = "fixed"; 1710162922Sariff break; 1711162922Sariff case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH: 1712162922Sariff connstr = "jack / fixed"; 1713162922Sariff break; 1714162922Sariff default: 1715162922Sariff connstr = "unknown"; 1716162922Sariff break; 1717162922Sariff } 1718162922Sariff 1719162922Sariff strlcat(w->name, ": ", sizeof(w->name)); 1720162922Sariff strlcat(w->name, devstr, sizeof(w->name)); 1721162922Sariff strlcat(w->name, " (", sizeof(w->name)); 1722162922Sariff strlcat(w->name, connstr, sizeof(w->name)); 1723162922Sariff strlcat(w->name, ")", sizeof(w->name)); 1724162922Sariff} 1725162922Sariff 1726162922Sariffstatic void 1727162922Sariffhdac_widget_parse(struct hdac_widget *w) 1728162922Sariff{ 1729162922Sariff struct hdac_softc *sc = w->devinfo->codec->sc; 1730162922Sariff uint32_t wcap, cap; 1731162922Sariff char *typestr; 1732162922Sariff nid_t cad = w->devinfo->codec->cad; 1733162922Sariff nid_t nid = w->nid; 1734162922Sariff 1735162922Sariff wcap = hdac_command(sc, 1736162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP), 1737162922Sariff cad); 1738162922Sariff w->param.widget_cap = wcap; 1739162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap); 1740162922Sariff 1741162922Sariff switch (w->type) { 1742162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 1743162922Sariff typestr = "audio output"; 1744162922Sariff break; 1745162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 1746162922Sariff typestr = "audio input"; 1747162922Sariff break; 1748162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 1749162922Sariff typestr = "audio mixer"; 1750162922Sariff break; 1751162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 1752162922Sariff typestr = "audio selector"; 1753162922Sariff break; 1754162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 1755162922Sariff typestr = "pin"; 1756162922Sariff break; 1757162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: 1758162922Sariff typestr = "power widget"; 1759162922Sariff break; 1760162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: 1761162922Sariff typestr = "volume widget"; 1762162922Sariff break; 1763162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: 1764162922Sariff typestr = "beep widget"; 1765162922Sariff break; 1766162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: 1767162922Sariff typestr = "vendor widget"; 1768162922Sariff break; 1769162922Sariff default: 1770162922Sariff typestr = "unknown type"; 1771162922Sariff break; 1772162922Sariff } 1773162922Sariff 1774162922Sariff strlcpy(w->name, typestr, sizeof(w->name)); 1775162922Sariff 1776162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(wcap)) { 1777162922Sariff hdac_command(sc, 1778162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), 1779162922Sariff cad); 1780162922Sariff DELAY(1000); 1781162922Sariff } 1782162922Sariff 1783162922Sariff hdac_widget_connection_parse(w); 1784162922Sariff 1785162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) { 1786162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 1787162922Sariff w->param.outamp_cap = 1788162922Sariff hdac_command(sc, 1789162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1790162922Sariff HDA_PARAM_OUTPUT_AMP_CAP), cad); 1791162922Sariff else 1792162922Sariff w->param.outamp_cap = 1793162922Sariff w->devinfo->function.audio.outamp_cap; 1794162922Sariff } else 1795162922Sariff w->param.outamp_cap = 0; 1796162922Sariff 1797162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) { 1798162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap)) 1799162922Sariff w->param.inamp_cap = 1800162922Sariff hdac_command(sc, 1801162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1802162922Sariff HDA_PARAM_INPUT_AMP_CAP), cad); 1803162922Sariff else 1804162922Sariff w->param.inamp_cap = 1805162922Sariff w->devinfo->function.audio.inamp_cap; 1806162922Sariff } else 1807162922Sariff w->param.inamp_cap = 0; 1808162922Sariff 1809162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 1810162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 1811162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) { 1812162922Sariff cap = hdac_command(sc, 1813162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1814162922Sariff HDA_PARAM_SUPP_STREAM_FORMATS), cad); 1815162922Sariff w->param.supp_stream_formats = (cap != 0) ? cap : 1816162922Sariff w->devinfo->function.audio.supp_stream_formats; 1817162922Sariff cap = hdac_command(sc, 1818162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, 1819162922Sariff HDA_PARAM_SUPP_PCM_SIZE_RATE), cad); 1820162922Sariff w->param.supp_pcm_size_rate = (cap != 0) ? cap : 1821162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 1822162922Sariff } else { 1823162922Sariff w->param.supp_stream_formats = 1824162922Sariff w->devinfo->function.audio.supp_stream_formats; 1825162922Sariff w->param.supp_pcm_size_rate = 1826162922Sariff w->devinfo->function.audio.supp_pcm_size_rate; 1827162922Sariff } 1828162922Sariff } else { 1829162922Sariff w->param.supp_stream_formats = 0; 1830162922Sariff w->param.supp_pcm_size_rate = 0; 1831162922Sariff } 1832162922Sariff 1833162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 1834162922Sariff hdac_widget_pin_parse(w); 1835162922Sariff} 1836162922Sariff 1837162922Sariffstatic struct hdac_widget * 1838162922Sariffhdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid) 1839162922Sariff{ 1840162922Sariff if (devinfo == NULL || devinfo->widget == NULL || 1841162922Sariff nid < devinfo->startnode || nid >= devinfo->endnode) 1842162922Sariff return (NULL); 1843162922Sariff return (&devinfo->widget[nid - devinfo->startnode]); 1844162922Sariff} 1845162922Sariff 1846162922Sariffstatic void 1847162922Sariffhdac_stream_stop(struct hdac_chan *ch) 1848162922Sariff{ 1849162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 1850162922Sariff uint32_t ctl; 1851162922Sariff 1852162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 1853162922Sariff ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1854162922Sariff HDAC_SDCTL_RUN); 1855162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 1856162922Sariff 1857162922Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1858162922Sariff ctl &= ~(1 << (ch->off >> 5)); 1859162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1860162922Sariff} 1861162922Sariff 1862162922Sariffstatic void 1863162922Sariffhdac_stream_start(struct hdac_chan *ch) 1864162922Sariff{ 1865162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 1866162922Sariff uint32_t ctl; 1867162922Sariff 1868162922Sariff ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1869162922Sariff ctl |= 1 << (ch->off >> 5); 1870162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1871162922Sariff 1872162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 1873162922Sariff ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1874162922Sariff HDAC_SDCTL_RUN; 1875162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 1876162922Sariff} 1877162922Sariff 1878162922Sariffstatic void 1879162922Sariffhdac_stream_reset(struct hdac_chan *ch) 1880162922Sariff{ 1881162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 1882162922Sariff int timeout = 1000; 1883162922Sariff int to = timeout; 1884162922Sariff uint32_t ctl; 1885162922Sariff 1886162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 1887162922Sariff ctl |= HDAC_SDCTL_SRST; 1888162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 1889162922Sariff do { 1890162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 1891162922Sariff if (ctl & HDAC_SDCTL_SRST) 1892162922Sariff break; 1893162922Sariff DELAY(10); 1894162922Sariff } while (--to); 1895162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) { 1896162922Sariff device_printf(sc->dev, "timeout in reset\n"); 1897162922Sariff } 1898162922Sariff ctl &= ~HDAC_SDCTL_SRST; 1899162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl); 1900162922Sariff to = timeout; 1901162922Sariff do { 1902162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0); 1903162922Sariff if (!(ctl & HDAC_SDCTL_SRST)) 1904162922Sariff break; 1905162922Sariff DELAY(10); 1906162922Sariff } while (--to); 1907162922Sariff if ((ctl & HDAC_SDCTL_SRST)) 1908162922Sariff device_printf(sc->dev, "can't reset!\n"); 1909162922Sariff} 1910162922Sariff 1911162922Sariffstatic void 1912162922Sariffhdac_stream_setid(struct hdac_chan *ch) 1913162922Sariff{ 1914162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 1915162922Sariff uint32_t ctl; 1916162922Sariff 1917162922Sariff ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2); 1918162922Sariff ctl &= ~HDAC_SDCTL2_STRM_MASK; 1919162922Sariff ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT; 1920162922Sariff HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl); 1921162922Sariff} 1922162922Sariff 1923162922Sariffstatic void 1924162922Sariffhdac_bdl_setup(struct hdac_chan *ch) 1925162922Sariff{ 1926162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 1927162922Sariff uint64_t addr; 1928162922Sariff int blks, size, blocksize; 1929162922Sariff struct hdac_bdle *bdle; 1930162922Sariff int i; 1931162922Sariff 1932162922Sariff addr = (uint64_t)sndbuf_getbufaddr(ch->b); 1933162922Sariff size = sndbuf_getsize(ch->b); 1934162922Sariff blocksize = sndbuf_getblksz(ch->b); 1935162922Sariff blks = size / blocksize; 1936162922Sariff bdle = (struct hdac_bdle*)ch->bdl_dma.dma_vaddr; 1937162922Sariff 1938162922Sariff for (i = 0; i < blks; i++, bdle++) { 1939162922Sariff bdle->addrl = (uint32_t)addr; 1940162922Sariff bdle->addrh = (uint32_t)(addr >> 32); 1941162922Sariff bdle->len = blocksize; 1942162922Sariff bdle->ioc = 1; 1943162922Sariff 1944162922Sariff addr += blocksize; 1945162922Sariff } 1946162922Sariff 1947162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, size); 1948162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blks - 1); 1949162922Sariff addr = ch->bdl_dma.dma_paddr; 1950162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr); 1951162922Sariff HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1952162922Sariff} 1953162922Sariff 1954162922Sariffstatic int 1955162922Sariffhdac_bdl_alloc(struct hdac_chan *ch) 1956162922Sariff{ 1957162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 1958162922Sariff int rc; 1959162922Sariff 1960162922Sariff rc = hdac_dma_alloc(sc, &ch->bdl_dma, 1961162922Sariff sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1962162922Sariff if (rc) { 1963162922Sariff device_printf(sc->dev, "can't alloc bdl\n"); 1964162922Sariff return (rc); 1965162922Sariff } 1966162922Sariff hdac_dma_nocache(ch->bdl_dma.dma_vaddr); 1967162922Sariff 1968162922Sariff return (0); 1969162922Sariff} 1970162922Sariff 1971162922Sariffstatic void 1972162922Sariffhdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid, 1973162922Sariff int index, int lmute, int rmute, 1974162922Sariff int left, int right, int dir) 1975162922Sariff{ 1976162922Sariff uint16_t v = 0; 1977162922Sariff 1978162922Sariff if (sc == NULL) 1979162922Sariff return; 1980162922Sariff 1981162922Sariff if (left != right || lmute != rmute) { 1982162922Sariff v = (1 << (15 - dir)) | (1 << 13) | (index << 8) | 1983162922Sariff (lmute << 7) | left; 1984162922Sariff hdac_command(sc, 1985162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 1986162922Sariff v = (1 << (15 - dir)) | (1 << 12) | (index << 8) | 1987162922Sariff (rmute << 7) | right; 1988162922Sariff } else 1989162922Sariff v = (1 << (15 - dir)) | (3 << 12) | (index << 8) | 1990162922Sariff (lmute << 7) | left; 1991162922Sariff 1992162922Sariff hdac_command(sc, 1993162922Sariff HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad); 1994162922Sariff} 1995162922Sariff 1996162922Sariffstatic void 1997162922Sariffhdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute, 1998162922Sariff int left, int right) 1999162922Sariff{ 2000162922Sariff struct hdac_softc *sc; 2001162922Sariff nid_t nid, cad; 2002162922Sariff int lmute, rmute; 2003162922Sariff 2004162922Sariff if (ctl == NULL || ctl->widget == NULL || 2005162922Sariff ctl->widget->devinfo == NULL || 2006162922Sariff ctl->widget->devinfo->codec == NULL || 2007162922Sariff ctl->widget->devinfo->codec->sc == NULL) 2008162922Sariff return; 2009162922Sariff 2010162922Sariff sc = ctl->widget->devinfo->codec->sc; 2011162922Sariff cad = ctl->widget->devinfo->codec->cad; 2012162922Sariff nid = ctl->widget->nid; 2013162922Sariff 2014162922Sariff if (mute == HDA_AMP_MUTE_DEFAULT) { 2015162922Sariff lmute = HDA_AMP_LEFT_MUTED(ctl->muted); 2016162922Sariff rmute = HDA_AMP_RIGHT_MUTED(ctl->muted); 2017162922Sariff } else { 2018162922Sariff lmute = HDA_AMP_LEFT_MUTED(mute); 2019162922Sariff rmute = HDA_AMP_RIGHT_MUTED(mute); 2020162922Sariff } 2021162922Sariff 2022162922Sariff if (ctl->dir & HDA_CTL_OUT) 2023162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2024162922Sariff lmute, rmute, left, right, 0); 2025162922Sariff if (ctl->dir & HDA_CTL_IN) 2026162922Sariff hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index, 2027162922Sariff lmute, rmute, left, right, 1); 2028162922Sariff ctl->left = left; 2029162922Sariff ctl->right = right; 2030162922Sariff} 2031162922Sariff 2032162922Sariffstatic void 2033162922Sariffhdac_widget_connection_select(struct hdac_widget *w, uint8_t index) 2034162922Sariff{ 2035162922Sariff if (w == NULL || w->nconns < 1 || index > (w->nconns - 1)) 2036162922Sariff return; 2037162922Sariff hdac_command(w->devinfo->codec->sc, 2038162922Sariff HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad, 2039162922Sariff w->nid, index), w->devinfo->codec->cad); 2040162922Sariff w->selconn = index; 2041162922Sariff} 2042162922Sariff 2043162922Sariff 2044162922Sariff/**************************************************************************** 2045162922Sariff * uint32_t hdac_command_sendone_internal 2046162922Sariff * 2047162922Sariff * Wrapper function that sends only one command to a given codec 2048162922Sariff ****************************************************************************/ 2049162922Sariffstatic uint32_t 2050162922Sariffhdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad) 2051162922Sariff{ 2052162922Sariff struct hdac_command_list cl; 2053162965Sariff uint32_t response = HDAC_INVALID; 2054162922Sariff 2055162922Sariff if (!mtx_owned(sc->lock)) 2056162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 2057162922Sariff cl.num_commands = 1; 2058162922Sariff cl.verbs = &verb; 2059162922Sariff cl.responses = &response; 2060162922Sariff 2061162922Sariff hdac_command_send_internal(sc, &cl, cad); 2062162922Sariff 2063162922Sariff return (response); 2064162922Sariff} 2065162922Sariff 2066162922Sariff/**************************************************************************** 2067162922Sariff * hdac_command_send_internal 2068162922Sariff * 2069162922Sariff * Send a command list to the codec via the corb. We queue as much verbs as 2070162922Sariff * we can and msleep on the codec. When the interrupt get the responses 2071162922Sariff * back from the rirb, it will wake us up so we can queue the remaining verbs 2072162922Sariff * if any. 2073162922Sariff ****************************************************************************/ 2074162922Sariffstatic void 2075162922Sariffhdac_command_send_internal(struct hdac_softc *sc, 2076162922Sariff struct hdac_command_list *commands, nid_t cad) 2077162922Sariff{ 2078162922Sariff struct hdac_codec *codec; 2079162922Sariff int corbrp; 2080162922Sariff uint32_t *corb; 2081162922Sariff uint8_t rirbwp; 2082162922Sariff int timeout; 2083162922Sariff int retry = 10; 2084162922Sariff struct hdac_rirb *rirb_base, *rirb; 2085162922Sariff nid_t ucad; 2086162922Sariff uint32_t utag; 2087162922Sariff 2088162922Sariff if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL) 2089162922Sariff return; 2090162922Sariff 2091162922Sariff codec = sc->codecs[cad]; 2092162922Sariff codec->commands = commands; 2093162922Sariff codec->responses_received = 0; 2094162922Sariff codec->verbs_sent = 0; 2095162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 2096162922Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 2097162922Sariff 2098162922Sariff do { 2099162922Sariff if (codec->verbs_sent != commands->num_commands) { 2100162922Sariff /* Queue as many verbs as possible */ 2101162922Sariff corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP); 2102162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2103162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 2104162922Sariff while (codec->verbs_sent != commands->num_commands && 2105162922Sariff ((sc->corb_wp + 1) % sc->corb_size) != corbrp) { 2106162922Sariff sc->corb_wp++; 2107162922Sariff sc->corb_wp %= sc->corb_size; 2108162922Sariff corb[sc->corb_wp] = 2109162922Sariff commands->verbs[codec->verbs_sent++]; 2110162922Sariff } 2111162922Sariff 2112162922Sariff /* Send the verbs to the codecs */ 2113162922Sariff bus_dmamap_sync(sc->corb_dma.dma_tag, 2114162922Sariff sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 2115162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 2116162922Sariff } 2117162922Sariff 2118162922Sariff timeout = 1000; 2119162922Sariff do { 2120162922Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 2121162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 2122162922Sariff BUS_DMASYNC_POSTREAD); 2123162922Sariff if (sc->rirb_rp != rirbwp) { 2124162922Sariff do { 2125162922Sariff sc->rirb_rp++; 2126162922Sariff sc->rirb_rp %= sc->rirb_size; 2127162922Sariff rirb = &rirb_base[sc->rirb_rp]; 2128162922Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 2129162922Sariff ucad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 2130162922Sariff utag = rirb->response >> 26; 2131162922Sariff if (ucad > -1 && ucad < HDAC_CODEC_MAX && 2132162922Sariff sc->codecs[ucad] != NULL) { 2133162922Sariff sc->unsolq[sc->unsolq_wp++] = 2134162922Sariff (ucad << 16) | 2135162922Sariff (utag & 0xffff); 2136162922Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 2137162922Sariff } 2138162922Sariff } else if (codec->responses_received < commands->num_commands) 2139162922Sariff codec->commands->responses[codec->responses_received++] = 2140162922Sariff rirb->response; 2141162922Sariff } while (sc->rirb_rp != rirbwp); 2142162922Sariff break; 2143162922Sariff } 2144162922Sariff DELAY(10); 2145162922Sariff } while (--timeout); 2146162922Sariff } while ((codec->verbs_sent != commands->num_commands || 2147162922Sariff codec->responses_received != commands->num_commands) && 2148162922Sariff --retry); 2149162922Sariff 2150162922Sariff if (retry == 0) 2151162922Sariff device_printf(sc->dev, 2152162922Sariff "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n", 2153162922Sariff __func__, commands->num_commands, 2154162922Sariff codec->verbs_sent, codec->responses_received); 2155162922Sariff 2156162922Sariff codec->verbs_sent = 0; 2157162922Sariff 2158162922Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 2159162922Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 2160162922Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 2161162922Sariff ucad = sc->unsolq[sc->unsolq_rp] >> 16; 2162162922Sariff utag = sc->unsolq[sc->unsolq_rp++] & 0xffff; 2163162922Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 2164162922Sariff hdac_unsolicited_handler(sc->codecs[ucad], utag); 2165162922Sariff } 2166162922Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 2167162922Sariff } 2168162922Sariff} 2169162922Sariff 2170162922Sariff 2171162922Sariff/**************************************************************************** 2172162922Sariff * Device Methods 2173162922Sariff ****************************************************************************/ 2174162922Sariff 2175162922Sariff/**************************************************************************** 2176162922Sariff * int hdac_probe(device_t) 2177162922Sariff * 2178162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 2179162922Sariff * match using the subclass of the device. 2180162922Sariff ****************************************************************************/ 2181162922Sariffstatic int 2182162922Sariffhdac_probe(device_t dev) 2183162922Sariff{ 2184162922Sariff int i, result; 2185162922Sariff uint32_t model, class, subclass; 2186162922Sariff char desc[64]; 2187162922Sariff 2188162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 2189162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 2190162922Sariff class = pci_get_class(dev); 2191162922Sariff subclass = pci_get_subclass(dev); 2192162922Sariff 2193162922Sariff bzero(desc, sizeof(desc)); 2194162922Sariff result = ENXIO; 2195162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 2196162922Sariff if (hdac_devices[i].model == model) { 2197162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 2198162922Sariff result = BUS_PROBE_DEFAULT; 2199162922Sariff break; 2200162922Sariff } 2201162965Sariff if (HDA_FLAG_MATCH(hdac_devices[i].model, model) && 2202162922Sariff class == PCIC_MULTIMEDIA && 2203162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 2204162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 2205162922Sariff result = BUS_PROBE_GENERIC; 2206162922Sariff break; 2207162922Sariff } 2208162922Sariff } 2209162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 2210162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 2211162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 2212162922Sariff result = BUS_PROBE_GENERIC; 2213162922Sariff } 2214162922Sariff if (result != ENXIO) { 2215162922Sariff strlcat(desc, " High Definition Audio Controller", 2216162922Sariff sizeof(desc)); 2217162922Sariff device_set_desc_copy(dev, desc); 2218162922Sariff } 2219162922Sariff 2220162922Sariff return (result); 2221162922Sariff} 2222162922Sariff 2223162922Sariffstatic void * 2224162922Sariffhdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b, 2225162922Sariff struct pcm_channel *c, int dir) 2226162922Sariff{ 2227162922Sariff struct hdac_devinfo *devinfo = data; 2228162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2229162922Sariff struct hdac_chan *ch; 2230162922Sariff 2231162922Sariff hdac_lock(sc); 2232162922Sariff if (dir == PCMDIR_PLAY) { 2233162922Sariff ch = &sc->play; 2234162922Sariff ch->off = (sc->num_iss + devinfo->function.audio.playcnt) << 5; 2235162922Sariff ch->dir = PCMDIR_PLAY; 2236162922Sariff ch->sid = ++sc->streamcnt; 2237162922Sariff devinfo->function.audio.playcnt++; 2238162922Sariff } else { 2239162922Sariff ch = &sc->rec; 2240162922Sariff ch->off = devinfo->function.audio.reccnt << 5; 2241162922Sariff ch->dir = PCMDIR_REC; 2242162922Sariff ch->sid = ++sc->streamcnt; 2243162922Sariff devinfo->function.audio.reccnt++; 2244162922Sariff } 2245162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) { 2246162922Sariff ch->caps.minspeed = ch->caps.maxspeed = 48000; 2247162922Sariff ch->pcmrates[0] = 48000; 2248162922Sariff ch->pcmrates[1] = 0; 2249162922Sariff } 2250162922Sariff ch->b = b; 2251162922Sariff ch->c = c; 2252162922Sariff ch->devinfo = devinfo; 2253162922Sariff ch->blksz = sc->chan_size / sc->chan_blkcnt; 2254162922Sariff ch->blkcnt = sc->chan_blkcnt; 2255162922Sariff hdac_unlock(sc); 2256162922Sariff 2257162922Sariff if (hdac_bdl_alloc(ch) != 0) { 2258162922Sariff ch->blkcnt = 0; 2259162922Sariff return (NULL); 2260162922Sariff } 2261162922Sariff 2262162922Sariff if (sndbuf_alloc(ch->b, sc->chan_dmat, sc->chan_size) != 0) 2263162922Sariff return (NULL); 2264162922Sariff 2265162922Sariff hdac_dma_nocache(ch->b->buf); 2266162922Sariff 2267162922Sariff return (ch); 2268162922Sariff} 2269162922Sariff 2270162922Sariffstatic int 2271162922Sariffhdac_channel_setformat(kobj_t obj, void *data, uint32_t format) 2272162922Sariff{ 2273162922Sariff struct hdac_chan *ch = data; 2274162922Sariff int i; 2275162922Sariff 2276162922Sariff for (i = 0; ch->caps.fmtlist[i] != 0; i++) { 2277162922Sariff if (format == ch->caps.fmtlist[i]) { 2278162922Sariff ch->fmt = format; 2279162922Sariff return (0); 2280162922Sariff } 2281162922Sariff } 2282162922Sariff 2283162922Sariff return (EINVAL); 2284162922Sariff} 2285162922Sariff 2286162922Sariffstatic int 2287162922Sariffhdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed) 2288162922Sariff{ 2289162922Sariff struct hdac_chan *ch = data; 2290162922Sariff uint32_t spd = 0; 2291162922Sariff int i; 2292162922Sariff 2293162922Sariff for (i = 0; ch->pcmrates[i] != 0; i++) { 2294162922Sariff spd = ch->pcmrates[i]; 2295162922Sariff if (spd >= speed) 2296162922Sariff break; 2297162922Sariff } 2298162922Sariff 2299162922Sariff if (spd == 0) 2300162922Sariff ch->spd = 48000; 2301162922Sariff else 2302162922Sariff ch->spd = spd; 2303162922Sariff 2304162922Sariff return (ch->spd); 2305162922Sariff} 2306162922Sariff 2307162922Sariffstatic void 2308162922Sariffhdac_stream_setup(struct hdac_chan *ch) 2309162922Sariff{ 2310162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2311162922Sariff int i; 2312162922Sariff nid_t cad = ch->devinfo->codec->cad; 2313162922Sariff uint16_t fmt; 2314162922Sariff 2315162922Sariff /* 2316162922Sariff * 8bit = 0 2317162922Sariff * 16bit = 1 2318162922Sariff * 20bit = 2 2319162922Sariff * 24bit = 3 2320162922Sariff * 32bit = 4 2321162922Sariff */ 2322162922Sariff fmt = 0; 2323162922Sariff if (ch->fmt & AFMT_S16_LE) 2324162922Sariff fmt |= ch->bit16 << 4; 2325162922Sariff else if (ch->fmt & AFMT_S32_LE) 2326162922Sariff fmt |= ch->bit32 << 4; 2327162922Sariff else 2328162922Sariff fmt |= 1 << 4; 2329162922Sariff 2330162922Sariff for (i = 0; i < HDA_RATE_TAB_LEN; i++) { 2331162922Sariff if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) { 2332162922Sariff fmt |= hda_rate_tab[i].base; 2333162922Sariff fmt |= hda_rate_tab[i].mul; 2334162922Sariff fmt |= hda_rate_tab[i].div; 2335162922Sariff break; 2336162922Sariff } 2337162922Sariff } 2338162922Sariff 2339162922Sariff if (ch->fmt & AFMT_STEREO) 2340162922Sariff fmt |= 1; 2341162922Sariff 2342162922Sariff HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt); 2343162922Sariff 2344162922Sariff for (i = 0; ch->io[i] != -1; i++) { 2345162922Sariff HDA_BOOTVERBOSE_MSG( 2346162922Sariff device_printf(sc->dev, 2347162922Sariff "PCMDIR_%s: Stream setup nid=%d fmt=0x%08x\n", 2348162922Sariff (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", 2349162922Sariff ch->io[i], fmt); 2350162922Sariff ); 2351162922Sariff hdac_command(sc, 2352162922Sariff HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad); 2353162922Sariff hdac_command(sc, 2354162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 2355162922Sariff ch->sid << 4), cad); 2356162922Sariff } 2357162922Sariff} 2358162922Sariff 2359162922Sariffstatic int 2360162922Sariffhdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 2361162922Sariff{ 2362162922Sariff struct hdac_chan *ch = data; 2363162922Sariff 2364162922Sariff sndbuf_resize(ch->b, ch->blkcnt, ch->blksz); 2365162922Sariff 2366162922Sariff return (ch->blksz); 2367162922Sariff} 2368162922Sariff 2369162922Sariffstatic void 2370162922Sariffhdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch) 2371162922Sariff{ 2372162922Sariff struct hdac_devinfo *devinfo = ch->devinfo; 2373162922Sariff nid_t cad = devinfo->codec->cad; 2374162922Sariff int i; 2375162922Sariff 2376162922Sariff hdac_stream_stop(ch); 2377162922Sariff 2378162922Sariff for (i = 0; ch->io[i] != -1; i++) { 2379162922Sariff hdac_command(sc, 2380162922Sariff HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i], 2381162922Sariff 0), cad); 2382162922Sariff } 2383162922Sariff} 2384162922Sariff 2385162922Sariffstatic void 2386162922Sariffhdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch) 2387162922Sariff{ 2388162922Sariff ch->ptr = 0; 2389162922Sariff ch->prevptr = 0; 2390162922Sariff hdac_stream_stop(ch); 2391162922Sariff hdac_stream_reset(ch); 2392162922Sariff hdac_bdl_setup(ch); 2393162922Sariff hdac_stream_setid(ch); 2394162922Sariff hdac_stream_setup(ch); 2395162922Sariff hdac_stream_start(ch); 2396162922Sariff} 2397162922Sariff 2398162922Sariffstatic int 2399162922Sariffhdac_channel_trigger(kobj_t obj, void *data, int go) 2400162922Sariff{ 2401162922Sariff struct hdac_chan *ch = data; 2402162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2403162922Sariff 2404162922Sariff hdac_lock(sc); 2405162922Sariff switch (go) { 2406162922Sariff case PCMTRIG_START: 2407162922Sariff hdac_channel_start(sc, ch); 2408162922Sariff break; 2409162922Sariff case PCMTRIG_STOP: 2410162922Sariff case PCMTRIG_ABORT: 2411162922Sariff hdac_channel_stop(sc, ch); 2412162922Sariff break; 2413162922Sariff } 2414162922Sariff hdac_unlock(sc); 2415162922Sariff 2416162922Sariff return (0); 2417162922Sariff} 2418162922Sariff 2419162922Sariffstatic int 2420162922Sariffhdac_channel_getptr(kobj_t obj, void *data) 2421162922Sariff{ 2422162922Sariff struct hdac_chan *ch = data; 2423162922Sariff struct hdac_softc *sc = ch->devinfo->codec->sc; 2424162922Sariff int sz, delta; 2425162922Sariff uint32_t ptr; 2426162922Sariff 2427162922Sariff hdac_lock(sc); 2428162922Sariff ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB); 2429162922Sariff hdac_unlock(sc); 2430162922Sariff 2431162922Sariff sz = sndbuf_getsize(ch->b); 2432162922Sariff ptr %= sz; 2433162922Sariff 2434162922Sariff if (ch->dir == PCMDIR_REC) { 2435162922Sariff delta = ptr % sndbuf_getblksz(ch->b); 2436162922Sariff if (delta != 0) { 2437162922Sariff ptr -= delta; 2438162922Sariff if (ptr < delta) 2439162922Sariff ptr = sz - delta; 2440162922Sariff else 2441162922Sariff ptr -= delta; 2442162922Sariff } 2443162922Sariff } 2444162922Sariff 2445162922Sariff return (ptr); 2446162922Sariff} 2447162922Sariff 2448162922Sariffstatic struct pcmchan_caps * 2449162922Sariffhdac_channel_getcaps(kobj_t obj, void *data) 2450162922Sariff{ 2451162922Sariff return (&((struct hdac_chan *)data)->caps); 2452162922Sariff} 2453162922Sariff 2454162922Sariffstatic kobj_method_t hdac_channel_methods[] = { 2455162922Sariff KOBJMETHOD(channel_init, hdac_channel_init), 2456162922Sariff KOBJMETHOD(channel_setformat, hdac_channel_setformat), 2457162922Sariff KOBJMETHOD(channel_setspeed, hdac_channel_setspeed), 2458162922Sariff KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize), 2459162922Sariff KOBJMETHOD(channel_trigger, hdac_channel_trigger), 2460162922Sariff KOBJMETHOD(channel_getptr, hdac_channel_getptr), 2461162922Sariff KOBJMETHOD(channel_getcaps, hdac_channel_getcaps), 2462162922Sariff { 0, 0 } 2463162922Sariff}; 2464162922SariffCHANNEL_DECLARE(hdac_channel); 2465162922Sariff 2466162922Sariffstatic int 2467162922Sariffhdac_audio_ctl_ossmixer_init(struct snd_mixer *m) 2468162922Sariff{ 2469162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 2470162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2471162922Sariff struct hdac_widget *w, *cw; 2472162922Sariff struct hdac_audio_ctl *ctl; 2473162922Sariff uint32_t mask, recmask, id; 2474162922Sariff int i, j, softpcmvol; 2475162922Sariff nid_t cad; 2476162922Sariff 2477162922Sariff if (resource_int_value(device_get_name(sc->dev), 2478162922Sariff device_get_unit(sc->dev), "softpcmvol", &softpcmvol) == 0) 2479162922Sariff softpcmvol = (softpcmvol != 0) ? 1 : 0; 2480162922Sariff else 2481162922Sariff softpcmvol = (devinfo->function.audio.quirks & 2482162922Sariff HDA_QUIRK_SOFTPCMVOL) ? 2483162922Sariff 1 : 0; 2484162922Sariff 2485162922Sariff hdac_lock(sc); 2486162922Sariff 2487162922Sariff mask = 0; 2488162922Sariff recmask = 0; 2489162922Sariff 2490162922Sariff id = hdac_codec_id(devinfo); 2491162922Sariff cad = devinfo->codec->cad; 2492162922Sariff for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) { 2493162965Sariff if (!(HDA_FLAG_MATCH(hdac_hp_switch[i].model, 2494162965Sariff sc->pci_subvendor) && 2495162922Sariff hdac_hp_switch[i].id == id)) 2496162922Sariff continue; 2497162922Sariff w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid); 2498162922Sariff if (w != NULL && w->enable != 0 2499162922Sariff && w->type == 2500162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 2501162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) { 2502162922Sariff hdac_command(sc, 2503162922Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, 2504162922Sariff w->nid, 2505162922Sariff HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE| 2506162922Sariff HDAC_UNSOLTAG_EVENT_HP), cad); 2507162922Sariff hdac_hp_switch_handler(devinfo); 2508162922Sariff } 2509162922Sariff break; 2510162922Sariff } 2511162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 2512162965Sariff if (!(HDA_FLAG_MATCH(hdac_eapd_switch[i].model, 2513162965Sariff sc->pci_subvendor) && 2514162965Sariff hdac_eapd_switch[i].id == id)) 2515162922Sariff continue; 2516162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 2517162922Sariff if (w == NULL || w->enable == 0) 2518162922Sariff break; 2519162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 2520162965Sariff w->param.eapdbtl == HDAC_INVALID) 2521162922Sariff break; 2522162922Sariff mask |= SOUND_MASK_OGAIN; 2523162922Sariff break; 2524162922Sariff } 2525162922Sariff 2526162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 2527162922Sariff w = hdac_widget_get(devinfo, i); 2528162922Sariff if (w == NULL || w->enable == 0) 2529162922Sariff continue; 2530162922Sariff mask |= w->ctlflags; 2531162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 2532162922Sariff continue; 2533162922Sariff for (j = 0; j < w->nconns; j++) { 2534162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 2535162922Sariff if (cw == NULL || cw->enable == 0) 2536162922Sariff continue; 2537162922Sariff recmask |= cw->ctlflags; 2538162922Sariff } 2539162922Sariff } 2540162922Sariff 2541162922Sariff if (!(mask & SOUND_MASK_PCM)) { 2542162922Sariff softpcmvol = 1; 2543162922Sariff mask |= SOUND_MASK_PCM; 2544162922Sariff } 2545162922Sariff 2546162922Sariff i = 0; 2547162922Sariff ctl = NULL; 2548162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 2549162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 2550162922Sariff continue; 2551162922Sariff if (!(ctl->ossmask & SOUND_MASK_PCM)) 2552162922Sariff continue; 2553162922Sariff if (ctl->step > 0) 2554162922Sariff break; 2555162922Sariff } 2556162922Sariff 2557162922Sariff if (softpcmvol == 1 || ctl == NULL) { 2558162922Sariff struct snddev_info *d = NULL; 2559162922Sariff d = device_get_softc(sc->dev); 2560162922Sariff if (d != NULL) { 2561162922Sariff d->flags |= SD_F_SOFTPCMVOL; 2562162922Sariff HDA_BOOTVERBOSE_MSG( 2563162922Sariff device_printf(sc->dev, 2564162922Sariff "%s Soft PCM volume\n", 2565162922Sariff (softpcmvol == 1) ? 2566162922Sariff "Forcing" : "Enabling"); 2567162922Sariff ); 2568162922Sariff } 2569162922Sariff i = 0; 2570162922Sariff /* 2571162922Sariff * XXX Temporary quirk for STAC9220, until the parser 2572162922Sariff * become smarter. 2573162922Sariff */ 2574162922Sariff if (id == HDA_CODEC_STAC9220) { 2575162922Sariff mask |= SOUND_MASK_VOLUME; 2576162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 2577162922Sariff NULL) { 2578162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 2579162922Sariff continue; 2580162922Sariff if (ctl->widget->nid == 11 && ctl->index == 0) { 2581162922Sariff ctl->ossmask = SOUND_MASK_VOLUME; 2582162922Sariff ctl->ossval = 100 | (100 << 8); 2583162922Sariff } else 2584162922Sariff ctl->ossmask &= ~SOUND_MASK_VOLUME; 2585162922Sariff } 2586162922Sariff } else { 2587162922Sariff mix_setparentchild(m, SOUND_MIXER_VOLUME, 2588162922Sariff SOUND_MASK_PCM); 2589162922Sariff if (!(mask & SOUND_MASK_VOLUME)) 2590162922Sariff mix_setrealdev(m, SOUND_MIXER_VOLUME, 2591162922Sariff SOUND_MIXER_NONE); 2592162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != 2593162922Sariff NULL) { 2594162922Sariff if (ctl->widget == NULL || ctl->enable == 0) 2595162922Sariff continue; 2596162922Sariff if ((ctl->ossmask & (SOUND_MASK_VOLUME | 2597162922Sariff SOUND_MASK_PCM)) != (SOUND_MASK_VOLUME | 2598162922Sariff SOUND_MASK_PCM)) 2599162922Sariff continue; 2600162922Sariff if (!(ctl->mute == 1 && ctl->step == 0)) 2601162922Sariff ctl->enable = 0; 2602162922Sariff } 2603162922Sariff } 2604162922Sariff } 2605162922Sariff 2606162922Sariff recmask &= ~(SOUND_MASK_PCM | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER); 2607162922Sariff 2608162922Sariff mix_setrecdevs(m, recmask); 2609162922Sariff mix_setdevs(m, mask); 2610162922Sariff 2611162922Sariff hdac_unlock(sc); 2612162922Sariff 2613162922Sariff return (0); 2614162922Sariff} 2615162922Sariff 2616162922Sariffstatic int 2617162922Sariffhdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev, 2618162922Sariff unsigned left, unsigned right) 2619162922Sariff{ 2620162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 2621162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2622162922Sariff struct hdac_widget *w; 2623162922Sariff struct hdac_audio_ctl *ctl; 2624162922Sariff uint32_t id, mute; 2625162922Sariff int lvol, rvol, mlvol, mrvol; 2626162922Sariff int i = 0; 2627162922Sariff 2628162922Sariff hdac_lock(sc); 2629162922Sariff if (dev == SOUND_MIXER_OGAIN) { 2630162922Sariff /*if (left != right || !(left == 0 || left == 1)) { 2631162922Sariff hdac_unlock(sc); 2632162922Sariff return (-1); 2633162922Sariff }*/ 2634162922Sariff id = hdac_codec_id(devinfo); 2635162922Sariff for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) { 2636162965Sariff if (HDA_FLAG_MATCH(hdac_eapd_switch[i].model, 2637162965Sariff sc->pci_subvendor) && 2638162922Sariff hdac_eapd_switch[i].id == id) 2639162922Sariff break; 2640162922Sariff } 2641162922Sariff if (i >= HDAC_EAPD_SWITCH_LEN) { 2642162922Sariff hdac_unlock(sc); 2643162922Sariff return (-1); 2644162922Sariff } 2645162922Sariff w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid); 2646162922Sariff if (w == NULL || 2647162922Sariff w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX || 2648162965Sariff w->param.eapdbtl == HDAC_INVALID) { 2649162922Sariff hdac_unlock(sc); 2650162922Sariff return (-1); 2651162922Sariff } 2652162922Sariff if (left == 0) 2653162922Sariff w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2654162922Sariff else 2655162922Sariff w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD; 2656162922Sariff if (hdac_eapd_switch[i].hp_switch != 0) 2657162922Sariff hdac_hp_switch_handler(devinfo); 2658162922Sariff hdac_command(sc, 2659162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad, w->nid, 2660162922Sariff w->param.eapdbtl), devinfo->codec->cad); 2661162922Sariff hdac_unlock(sc); 2662162922Sariff return (left | (left << 8)); 2663162922Sariff } 2664162922Sariff if (dev == SOUND_MIXER_VOLUME) 2665162922Sariff devinfo->function.audio.mvol = left | (right << 8); 2666162922Sariff 2667162922Sariff mlvol = devinfo->function.audio.mvol & 0x7f; 2668162922Sariff mrvol = (devinfo->function.audio.mvol >> 8) & 0x7f; 2669162922Sariff lvol = 0; 2670162922Sariff rvol = 0; 2671162922Sariff 2672162922Sariff i = 0; 2673162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 2674162922Sariff if (ctl->widget == NULL || ctl->enable == 0 || 2675162922Sariff !(ctl->ossmask & (1 << dev))) 2676162922Sariff continue; 2677162922Sariff switch (dev) { 2678162922Sariff case SOUND_MIXER_VOLUME: 2679162922Sariff lvol = ((ctl->ossval & 0x7f) * left) / 100; 2680162922Sariff lvol = (lvol * ctl->step) / 100; 2681162922Sariff rvol = (((ctl->ossval >> 8) & 0x7f) * right) / 100; 2682162922Sariff rvol = (rvol * ctl->step) / 100; 2683162922Sariff break; 2684162922Sariff default: 2685162922Sariff if (ctl->ossmask & SOUND_MASK_VOLUME) { 2686162922Sariff lvol = (left * mlvol) / 100; 2687162922Sariff lvol = (lvol * ctl->step) / 100; 2688162922Sariff rvol = (right * mrvol) / 100; 2689162922Sariff rvol = (rvol * ctl->step) / 100; 2690162922Sariff } else { 2691162922Sariff lvol = (left * ctl->step) / 100; 2692162922Sariff rvol = (right * ctl->step) / 100; 2693162922Sariff } 2694162922Sariff ctl->ossval = left | (right << 8); 2695162922Sariff break; 2696162922Sariff } 2697162922Sariff mute = 0; 2698162922Sariff if (ctl->step < 1) { 2699162922Sariff mute |= (left == 0) ? HDA_AMP_MUTE_LEFT : 2700162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 2701162922Sariff mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 2702162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 2703162922Sariff } else { 2704162922Sariff mute |= (lvol == 0) ? HDA_AMP_MUTE_LEFT : 2705162922Sariff (ctl->muted & HDA_AMP_MUTE_LEFT); 2706162922Sariff mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 2707162922Sariff (ctl->muted & HDA_AMP_MUTE_RIGHT); 2708162922Sariff } 2709162922Sariff hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol); 2710162922Sariff } 2711162922Sariff hdac_unlock(sc); 2712162922Sariff 2713162922Sariff return (left | (right << 8)); 2714162922Sariff} 2715162922Sariff 2716162922Sariffstatic int 2717162922Sariffhdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src) 2718162922Sariff{ 2719162922Sariff struct hdac_devinfo *devinfo = mix_getdevinfo(m); 2720162922Sariff struct hdac_widget *w, *cw; 2721162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2722162922Sariff uint32_t ret = src, target; 2723162922Sariff int i, j; 2724162922Sariff 2725162922Sariff target = 0; 2726162922Sariff for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 2727162922Sariff if (src & (1 << i)) { 2728162922Sariff target = 1 << i; 2729162922Sariff break; 2730162922Sariff } 2731162922Sariff } 2732162922Sariff 2733162922Sariff hdac_lock(sc); 2734162922Sariff 2735162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 2736162922Sariff w = hdac_widget_get(devinfo, i); 2737162965Sariff if (w == NULL || w->enable == 0) 2738162922Sariff continue; 2739162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 2740162922Sariff continue; 2741162922Sariff for (j = 0; j < w->nconns; j++) { 2742162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 2743162922Sariff if (cw == NULL || cw->enable == 0) 2744162922Sariff continue; 2745162922Sariff if ((target == SOUND_MASK_VOLUME && 2746162922Sariff cw->type != 2747162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) || 2748162922Sariff (target != SOUND_MASK_VOLUME && 2749162922Sariff cw->type == 2750162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)) 2751162922Sariff continue; 2752162922Sariff if (cw->ctlflags & target) { 2753162922Sariff hdac_widget_connection_select(w, j); 2754162922Sariff ret = target; 2755162922Sariff j += w->nconns; 2756162922Sariff } 2757162922Sariff } 2758162922Sariff } 2759162922Sariff 2760162922Sariff hdac_unlock(sc); 2761162922Sariff 2762162922Sariff return (ret); 2763162922Sariff} 2764162922Sariff 2765162922Sariffstatic kobj_method_t hdac_audio_ctl_ossmixer_methods[] = { 2766162922Sariff KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init), 2767162922Sariff KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set), 2768162922Sariff KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc), 2769162922Sariff { 0, 0 } 2770162922Sariff}; 2771162922SariffMIXER_DECLARE(hdac_audio_ctl_ossmixer); 2772162922Sariff 2773162922Sariff/**************************************************************************** 2774162922Sariff * int hdac_attach(device_t) 2775162922Sariff * 2776162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 2777162922Sariff * when this function is called. Setup everything that doesn't require 2778162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 2779162922Sariff ****************************************************************************/ 2780162922Sariffstatic int 2781162922Sariffhdac_attach(device_t dev) 2782162922Sariff{ 2783162922Sariff struct hdac_softc *sc; 2784162922Sariff int result; 2785162922Sariff int i = 0; 2786162922Sariff 2787162922Sariff sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO); 2788162922Sariff if (sc == NULL) { 2789162922Sariff device_printf(dev, "cannot allocate softc\n"); 2790162922Sariff return (ENOMEM); 2791162922Sariff } 2792162922Sariff sc->dev = dev; 2793162922Sariff sc->pci_subvendor = pci_get_subdevice(sc->dev) << 16; 2794162922Sariff sc->pci_subvendor |= pci_get_subvendor(sc->dev); 2795162922Sariff 2796162922Sariff sc->chan_size = pcm_getbuffersize(dev, 2797162922Sariff HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_DEFAULT); 2798162922Sariff if (resource_int_value(device_get_name(sc->dev), 2799162922Sariff device_get_unit(sc->dev), "blocksize", &i) == 0 && 2800162922Sariff i > 0) { 2801162922Sariff sc->chan_blkcnt = sc->chan_size / i; 2802162922Sariff i = 0; 2803162922Sariff while (sc->chan_blkcnt >> i) 2804162922Sariff i++; 2805162922Sariff sc->chan_blkcnt = 1 << (i - 1); 2806162922Sariff if (sc->chan_blkcnt < HDA_BDL_MIN) 2807162922Sariff sc->chan_blkcnt = HDA_BDL_MIN; 2808162922Sariff else if (sc->chan_blkcnt > HDA_BDL_MAX) 2809162922Sariff sc->chan_blkcnt = HDA_BDL_MAX; 2810162922Sariff } else 2811162922Sariff sc->chan_blkcnt = HDA_BDL_DEFAULT; 2812162922Sariff 2813162922Sariff result = bus_dma_tag_create(NULL, /* parent */ 2814162922Sariff HDAC_DMA_ALIGNMENT, /* alignment */ 2815162922Sariff 0, /* boundary */ 2816162922Sariff BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 2817162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 2818162922Sariff NULL, /* filtfunc */ 2819162922Sariff NULL, /* fistfuncarg */ 2820162922Sariff sc->chan_size, /* maxsize */ 2821162922Sariff 1, /* nsegments */ 2822162922Sariff sc->chan_size, /* maxsegsz */ 2823162922Sariff 0, /* flags */ 2824162922Sariff NULL, /* lockfunc */ 2825162922Sariff NULL, /* lockfuncarg */ 2826162922Sariff &sc->chan_dmat); /* dmat */ 2827162922Sariff if (result != 0) { 2828162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 2829162922Sariff __func__, result); 2830162922Sariff free(sc, M_DEVBUF); 2831162922Sariff return (ENXIO); 2832162922Sariff } 2833162922Sariff 2834162922Sariff 2835162922Sariff sc->hdabus = NULL; 2836162922Sariff for (i = 0; i < HDAC_CODEC_MAX; i++) 2837162922Sariff sc->codecs[i] = NULL; 2838162922Sariff 2839162922Sariff pci_enable_busmaster(dev); 2840162922Sariff 2841162922Sariff /* Initialize driver mutex */ 2842162922Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME); 2843162922Sariff 2844162922Sariff /* Allocate resources */ 2845162922Sariff result = hdac_mem_alloc(sc); 2846162922Sariff if (result != 0) 2847162922Sariff goto fail; 2848162922Sariff result = hdac_irq_alloc(sc); 2849162922Sariff if (result != 0) 2850162922Sariff goto fail; 2851162922Sariff 2852162922Sariff /* Get Capabilities */ 2853162922Sariff result = hdac_get_capabilities(sc); 2854162922Sariff if (result != 0) 2855162922Sariff goto fail; 2856162922Sariff 2857162922Sariff /* Allocate CORB and RIRB dma memory */ 2858162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 2859162922Sariff sc->corb_size * sizeof(uint32_t)); 2860162922Sariff if (result != 0) 2861162922Sariff goto fail; 2862162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 2863162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 2864162922Sariff if (result != 0) 2865162922Sariff goto fail; 2866162922Sariff 2867162922Sariff /* Quiesce everything */ 2868162922Sariff hdac_reset(sc); 2869162922Sariff 2870162922Sariff /* Disable PCI-Express QOS */ 2871162922Sariff pci_write_config(sc->dev, 0x44, 2872162922Sariff pci_read_config(sc->dev, 0x44, 1) & 0xf8, 1); 2873162922Sariff 2874162922Sariff /* Initialize the CORB and RIRB */ 2875162922Sariff hdac_corb_init(sc); 2876162922Sariff hdac_rirb_init(sc); 2877162922Sariff 2878162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 2879162922Sariff sc->intrhook.ich_func = hdac_attach2; 2880162922Sariff sc->intrhook.ich_arg = (void *)sc; 2881162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 2882162922Sariff sc->intrhook.ich_func = NULL; 2883162922Sariff hdac_attach2((void *)sc); 2884162922Sariff } 2885162922Sariff 2886162922Sariff return(0); 2887162922Sariff 2888162922Sarifffail: 2889162922Sariff hdac_dma_free(&sc->rirb_dma); 2890162922Sariff hdac_dma_free(&sc->corb_dma); 2891162922Sariff hdac_irq_free(sc); 2892162922Sariff hdac_mem_free(sc); 2893162922Sariff snd_mtxfree(sc->lock); 2894162922Sariff 2895162922Sariff return(ENXIO); 2896162922Sariff} 2897162922Sariff 2898162922Sariffstatic void 2899162922Sariffhdac_audio_parse(struct hdac_devinfo *devinfo) 2900162922Sariff{ 2901162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2902162922Sariff struct hdac_widget *w; 2903162922Sariff uint32_t res; 2904162922Sariff int i; 2905162922Sariff nid_t cad, nid; 2906162922Sariff 2907162922Sariff cad = devinfo->codec->cad; 2908162922Sariff nid = devinfo->nid; 2909162922Sariff 2910162922Sariff hdac_command(sc, 2911162922Sariff HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), cad); 2912162922Sariff 2913162922Sariff DELAY(100); 2914162922Sariff 2915162922Sariff res = hdac_command(sc, 2916162922Sariff HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad); 2917162922Sariff 2918162922Sariff devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res); 2919162922Sariff devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res); 2920162922Sariff devinfo->endnode = devinfo->startnode + devinfo->nodecnt; 2921162922Sariff 2922162922Sariff HDA_BOOTVERBOSE_MSG( 2923162922Sariff device_printf(sc->dev, " Vendor: 0x%08x\n", 2924162922Sariff devinfo->vendor_id); 2925162922Sariff device_printf(sc->dev, " Device: 0x%08x\n", 2926162922Sariff devinfo->device_id); 2927162922Sariff device_printf(sc->dev, " Revision: 0x%08x\n", 2928162922Sariff devinfo->revision_id); 2929162922Sariff device_printf(sc->dev, " Stepping: 0x%08x\n", 2930162922Sariff devinfo->stepping_id); 2931162922Sariff device_printf(sc->dev, "PCI Subvendor: 0x%08x\n", 2932162922Sariff sc->pci_subvendor); 2933162922Sariff device_printf(sc->dev, " Nodes: start=%d " 2934162922Sariff "endnode=%d total=%d\n", 2935162922Sariff devinfo->startnode, devinfo->endnode, devinfo->nodecnt); 2936162922Sariff ); 2937162922Sariff 2938162922Sariff res = hdac_command(sc, 2939162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), 2940162922Sariff cad); 2941162922Sariff devinfo->function.audio.supp_stream_formats = res; 2942162922Sariff 2943162922Sariff res = hdac_command(sc, 2944162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE), 2945162922Sariff cad); 2946162922Sariff devinfo->function.audio.supp_pcm_size_rate = res; 2947162922Sariff 2948162922Sariff res = hdac_command(sc, 2949162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP), 2950162922Sariff cad); 2951162922Sariff devinfo->function.audio.outamp_cap = res; 2952162922Sariff 2953162922Sariff res = hdac_command(sc, 2954162922Sariff HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP), 2955162922Sariff cad); 2956162922Sariff devinfo->function.audio.inamp_cap = res; 2957162922Sariff 2958162922Sariff if (devinfo->nodecnt > 0) { 2959162922Sariff hdac_unlock(sc); 2960162922Sariff devinfo->widget = (struct hdac_widget *)malloc( 2961162922Sariff sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC, 2962162922Sariff M_NOWAIT | M_ZERO); 2963162922Sariff hdac_lock(sc); 2964162922Sariff } else 2965162922Sariff devinfo->widget = NULL; 2966162922Sariff 2967162922Sariff if (devinfo->widget == NULL) { 2968162922Sariff device_printf(sc->dev, "unable to allocate widgets!\n"); 2969162922Sariff devinfo->endnode = devinfo->startnode; 2970162922Sariff devinfo->nodecnt = 0; 2971162922Sariff return; 2972162922Sariff } 2973162922Sariff 2974162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 2975162922Sariff w = hdac_widget_get(devinfo, i); 2976162922Sariff if (w == NULL) 2977162922Sariff device_printf(sc->dev, "Ghost widget! nid=%d!\n", i); 2978162922Sariff else { 2979162922Sariff w->devinfo = devinfo; 2980162922Sariff w->nid = i; 2981162922Sariff w->enable = 1; 2982162922Sariff w->selconn = -1; 2983162922Sariff w->pflags = 0; 2984162922Sariff w->ctlflags = 0; 2985162965Sariff w->param.eapdbtl = HDAC_INVALID; 2986162922Sariff hdac_widget_parse(w); 2987162922Sariff } 2988162922Sariff } 2989162922Sariff} 2990162922Sariff 2991162922Sariffstatic void 2992162922Sariffhdac_audio_ctl_parse(struct hdac_devinfo *devinfo) 2993162922Sariff{ 2994162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 2995162922Sariff struct hdac_audio_ctl *ctls; 2996162922Sariff struct hdac_widget *w, *cw; 2997162922Sariff int i, j, cnt, max, ocap, icap; 2998162922Sariff 2999162922Sariff /* XXX This is redundant */ 3000162922Sariff max = 0; 3001162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3002162922Sariff w = hdac_widget_get(devinfo, i); 3003162922Sariff if (w == NULL || w->enable == 0) 3004162922Sariff continue; 3005162922Sariff if (w->param.outamp_cap != 0) 3006162922Sariff max++; 3007162922Sariff if (w->param.inamp_cap != 0) { 3008162922Sariff switch (w->type) { 3009162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3010162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3011162922Sariff for (j = 0; j < w->nconns; j++) { 3012162922Sariff cw = hdac_widget_get(devinfo, 3013162922Sariff w->conns[j]); 3014162922Sariff if (cw == NULL || cw->enable == 0) 3015162922Sariff continue; 3016162922Sariff max++; 3017162922Sariff } 3018162922Sariff break; 3019162922Sariff default: 3020162922Sariff max++; 3021162922Sariff break; 3022162922Sariff } 3023162922Sariff } 3024162922Sariff } 3025162922Sariff 3026162922Sariff devinfo->function.audio.ctlcnt = max; 3027162922Sariff 3028162922Sariff if (max < 1) 3029162922Sariff return; 3030162922Sariff 3031162922Sariff hdac_unlock(sc); 3032162922Sariff ctls = (struct hdac_audio_ctl *)malloc( 3033162922Sariff sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT); 3034162922Sariff hdac_lock(sc); 3035162922Sariff 3036162922Sariff if (ctls == NULL) { 3037162922Sariff /* Blekh! */ 3038162922Sariff device_printf(sc->dev, "unable to allocate ctls!\n"); 3039162922Sariff devinfo->function.audio.ctlcnt = 0; 3040162922Sariff return; 3041162922Sariff } 3042162922Sariff 3043162922Sariff cnt = 0; 3044162922Sariff for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) { 3045162922Sariff if (cnt >= max) { 3046162922Sariff device_printf(sc->dev, "%s: Ctl overflow!\n", 3047162922Sariff __func__); 3048162922Sariff break; 3049162922Sariff } 3050162922Sariff w = hdac_widget_get(devinfo, i); 3051162922Sariff if (w == NULL || w->enable == 0) 3052162922Sariff continue; 3053162922Sariff ocap = w->param.outamp_cap; 3054162922Sariff icap = w->param.inamp_cap; 3055162922Sariff if (ocap != 0) { 3056162922Sariff ctls[cnt].enable = 1; 3057162922Sariff ctls[cnt].widget = w; 3058162922Sariff ctls[cnt].mute = 3059162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap); 3060162922Sariff ctls[cnt].step = 3061162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap); 3062162922Sariff ctls[cnt].size = 3063162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap); 3064162922Sariff ctls[cnt].offset = 3065162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap); 3066162922Sariff ctls[cnt].left = ctls[cnt].offset; 3067162922Sariff ctls[cnt].right = ctls[cnt].offset; 3068162922Sariff ctls[cnt++].dir = HDA_CTL_OUT; 3069162922Sariff } 3070162922Sariff 3071162922Sariff if (icap != 0) { 3072162922Sariff switch (w->type) { 3073162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3074162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3075162922Sariff for (j = 0; j < w->nconns; j++) { 3076162922Sariff if (cnt >= max) { 3077162922Sariff device_printf(sc->dev, 3078162922Sariff "%s: Ctl overflow!\n", 3079162922Sariff __func__); 3080162922Sariff break; 3081162922Sariff } 3082162922Sariff cw = hdac_widget_get(devinfo, 3083162922Sariff w->conns[j]); 3084162922Sariff if (cw == NULL || cw->enable == 0) 3085162922Sariff continue; 3086162922Sariff ctls[cnt].enable = 1; 3087162922Sariff ctls[cnt].widget = w; 3088162922Sariff ctls[cnt].childwidget = cw; 3089162922Sariff ctls[cnt].index = j; 3090162922Sariff ctls[cnt].mute = 3091162922Sariff HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP(icap); 3092162922Sariff ctls[cnt].step = 3093162922Sariff HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS(icap); 3094162922Sariff ctls[cnt].size = 3095162922Sariff HDA_PARAM_INPUT_AMP_CAP_STEPSIZE(icap); 3096162922Sariff ctls[cnt].offset = 3097162922Sariff HDA_PARAM_INPUT_AMP_CAP_OFFSET(icap); 3098162922Sariff ctls[cnt].left = ctls[cnt].offset; 3099162922Sariff ctls[cnt].right = ctls[cnt].offset; 3100162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 3101162922Sariff } 3102162922Sariff break; 3103162922Sariff default: 3104162922Sariff if (cnt >= max) { 3105162922Sariff device_printf(sc->dev, 3106162922Sariff "%s: Ctl overflow!\n", 3107162922Sariff __func__); 3108162922Sariff break; 3109162922Sariff } 3110162922Sariff ctls[cnt].enable = 1; 3111162922Sariff ctls[cnt].widget = w; 3112162922Sariff ctls[cnt].mute = 3113162922Sariff HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP(icap); 3114162922Sariff ctls[cnt].step = 3115162922Sariff HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS(icap); 3116162922Sariff ctls[cnt].size = 3117162922Sariff HDA_PARAM_INPUT_AMP_CAP_STEPSIZE(icap); 3118162922Sariff ctls[cnt].offset = 3119162922Sariff HDA_PARAM_INPUT_AMP_CAP_OFFSET(icap); 3120162922Sariff ctls[cnt].left = ctls[cnt].offset; 3121162922Sariff ctls[cnt].right = ctls[cnt].offset; 3122162922Sariff ctls[cnt++].dir = HDA_CTL_IN; 3123162922Sariff break; 3124162922Sariff } 3125162922Sariff } 3126162922Sariff } 3127162922Sariff 3128162922Sariff devinfo->function.audio.ctl = ctls; 3129162922Sariff} 3130162922Sariff 3131162965Sariffstatic const struct { 3132162965Sariff uint32_t model; 3133162965Sariff uint32_t id; 3134162965Sariff uint32_t set, unset; 3135162965Sariff} hdac_quirks[] = { 3136162965Sariff { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, 3137162965Sariff HDA_QUIRK_GPIO1, 0 }, 3138162965Sariff { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, 3139162965Sariff HDA_QUIRK_GPIO1, 0 }, 3140162965Sariff { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 3141162965Sariff 0, HDA_QUIRK_FORCESTEREO }, 3142162965Sariff { HDA_MATCH_ALL, HDA_CODEC_STACXXXX, 3143162965Sariff HDA_QUIRK_SOFTPCMVOL, 0 } 3144162965Sariff}; 3145162965Sariff#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 3146162965Sariff 3147162922Sariffstatic void 3148162922Sariffhdac_vendor_patch_parse(struct hdac_devinfo *devinfo) 3149162922Sariff{ 3150162922Sariff struct hdac_widget *w; 3151162965Sariff uint32_t id, subvendor; 3152162922Sariff int i; 3153162922Sariff 3154162922Sariff /* 3155162922Sariff * XXX Fixed rate quirk. Other than 48000 3156162922Sariff * sounds pretty much like train wreck. 3157162922Sariff */ 3158162922Sariff devinfo->function.audio.quirks |= HDA_QUIRK_FIXEDRATE; 3159162922Sariff /* 3160162922Sariff * XXX Force stereo quirk. Monoural recording / playback 3161162922Sariff * on few codecs (especially ALC880) seems broken or 3162162922Sariff * or perhaps unsupported. 3163162922Sariff */ 3164162922Sariff devinfo->function.audio.quirks |= HDA_QUIRK_FORCESTEREO; 3165162922Sariff id = hdac_codec_id(devinfo); 3166162965Sariff subvendor = devinfo->codec->sc->pci_subvendor; 3167162922Sariff switch (id) { 3168162922Sariff case HDA_CODEC_ALC260: 3169162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3170162922Sariff w = hdac_widget_get(devinfo, i); 3171162922Sariff if (w == NULL || w->enable == 0) 3172162922Sariff continue; 3173162922Sariff if (w->type != 3174162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 3175162922Sariff continue; 3176162922Sariff if (w->nid != 5) 3177162922Sariff w->enable = 0; 3178162922Sariff } 3179162922Sariff break; 3180162922Sariff case HDA_CODEC_ALC880: 3181162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3182162922Sariff w = hdac_widget_get(devinfo, i); 3183162922Sariff if (w == NULL || w->enable == 0) 3184162922Sariff continue; 3185162922Sariff if (w->type == 3186162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 3187162922Sariff w->nid != 9 && w->nid != 29) { 3188162922Sariff w->enable = 0; 3189162922Sariff } else if (w->type != 3190162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET && 3191162922Sariff w->nid == 29) { 3192162922Sariff w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET; 3193162922Sariff w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 3194162922Sariff w->param.widget_cap |= 3195162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 3196162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 3197162922Sariff strlcpy(w->name, "beep widget", sizeof(w->name)); 3198162922Sariff } 3199162922Sariff } 3200162922Sariff break; 3201162922Sariff case HDA_CODEC_AD1986A: 3202162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3203162922Sariff w = hdac_widget_get(devinfo, i); 3204162922Sariff if (w == NULL || w->enable == 0) 3205162922Sariff continue; 3206162922Sariff if (w->type != 3207162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 3208162922Sariff continue; 3209162922Sariff if (w->nid != 3) 3210162922Sariff w->enable = 0; 3211162922Sariff } 3212162922Sariff break; 3213162922Sariff case HDA_CODEC_STAC9221: 3214162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3215162922Sariff w = hdac_widget_get(devinfo, i); 3216162922Sariff if (w == NULL || w->enable == 0) 3217162922Sariff continue; 3218162922Sariff if (w->type != 3219162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) 3220162922Sariff continue; 3221162922Sariff if (w->nid != 2) 3222162922Sariff w->enable = 0; 3223162922Sariff } 3224162922Sariff break; 3225162922Sariff case HDA_CODEC_STAC9221D: 3226162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3227162922Sariff w = hdac_widget_get(devinfo, i); 3228162922Sariff if (w == NULL || w->enable == 0) 3229162922Sariff continue; 3230162922Sariff if (w->type == 3231162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 3232162922Sariff w->nid != 6) 3233162922Sariff w->enable = 0; 3234162922Sariff 3235162922Sariff } 3236162922Sariff break; 3237162922Sariff default: 3238162922Sariff break; 3239162922Sariff } 3240162965Sariff 3241162965Sariff /* 3242162965Sariff * Quirks 3243162965Sariff */ 3244162965Sariff for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 3245162965Sariff if (!(HDA_FLAG_MATCH(hdac_quirks[i].model, subvendor) && 3246162965Sariff HDA_FLAG_MATCH(hdac_quirks[i].id, id))) 3247162965Sariff continue; 3248162965Sariff if (hdac_quirks[i].set != 0) 3249162965Sariff devinfo->function.audio.quirks |= 3250162965Sariff hdac_quirks[i].set; 3251162965Sariff if (hdac_quirks[i].unset != 0) 3252162965Sariff devinfo->function.audio.quirks &= 3253162965Sariff ~(hdac_quirks[i].unset); 3254162965Sariff break; 3255162922Sariff } 3256162922Sariff} 3257162922Sariff 3258162922Sariffstatic int 3259162922Sariffhdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *devinfo) 3260162922Sariff{ 3261162922Sariff int *dev = &devinfo->function.audio.ossidx; 3262162922Sariff 3263162922Sariff while (*dev < SOUND_MIXER_NRDEVICES) { 3264162922Sariff switch (*dev) { 3265162922Sariff case SOUND_MIXER_VOLUME: 3266162922Sariff case SOUND_MIXER_BASS: 3267162922Sariff case SOUND_MIXER_TREBLE: 3268162922Sariff case SOUND_MIXER_PCM: 3269162922Sariff case SOUND_MIXER_SPEAKER: 3270162922Sariff case SOUND_MIXER_LINE: 3271162922Sariff case SOUND_MIXER_MIC: 3272162922Sariff case SOUND_MIXER_CD: 3273162922Sariff case SOUND_MIXER_RECLEV: 3274162922Sariff case SOUND_MIXER_OGAIN: /* reserved for EAPD switch */ 3275162922Sariff (*dev)++; 3276162922Sariff break; 3277162922Sariff default: 3278162922Sariff return (*dev)++; 3279162922Sariff break; 3280162922Sariff } 3281162922Sariff } 3282162922Sariff 3283162922Sariff return (-1); 3284162922Sariff} 3285162922Sariff 3286162922Sariffstatic int 3287162922Sariffhdac_widget_find_dac_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3288162922Sariff{ 3289162922Sariff struct hdac_widget *w; 3290162922Sariff int i, ret = 0; 3291162922Sariff 3292162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3293162922Sariff return (0); 3294162922Sariff w = hdac_widget_get(devinfo, nid); 3295162922Sariff if (w == NULL || w->enable == 0) 3296162922Sariff return (0); 3297162922Sariff switch (w->type) { 3298162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: 3299162922Sariff w->pflags |= HDA_DAC_PATH; 3300162922Sariff ret = 1; 3301162922Sariff break; 3302162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3303162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3304162922Sariff for (i = 0; i < w->nconns; i++) { 3305162922Sariff if (hdac_widget_find_dac_path(devinfo, 3306162922Sariff w->conns[i], depth + 1) != 0) { 3307162922Sariff if (w->selconn == -1) 3308162922Sariff w->selconn = i; 3309162922Sariff ret = 1; 3310162922Sariff w->pflags |= HDA_DAC_PATH; 3311162922Sariff } 3312162922Sariff } 3313162922Sariff break; 3314162922Sariff default: 3315162922Sariff break; 3316162922Sariff } 3317162922Sariff return (ret); 3318162922Sariff} 3319162922Sariff 3320162922Sariffstatic int 3321162922Sariffhdac_widget_find_adc_path(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3322162922Sariff{ 3323162922Sariff struct hdac_widget *w; 3324162922Sariff int i, conndev, ret = 0; 3325162922Sariff 3326162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3327162922Sariff return (0); 3328162922Sariff w = hdac_widget_get(devinfo, nid); 3329162922Sariff if (w == NULL || w->enable == 0) 3330162922Sariff return (0); 3331162922Sariff switch (w->type) { 3332162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: 3333162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: 3334162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3335162922Sariff for (i = 0; i < w->nconns; i++) { 3336162922Sariff if (hdac_widget_find_adc_path(devinfo, w->conns[i], 3337162922Sariff depth + 1) != 0) { 3338162922Sariff if (w->selconn == -1) 3339162922Sariff w->selconn = i; 3340162922Sariff w->pflags |= HDA_ADC_PATH; 3341162922Sariff ret = 1; 3342162922Sariff } 3343162922Sariff } 3344162922Sariff break; 3345162922Sariff case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: 3346162922Sariff conndev = w->wclass.pin.config & 3347162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 3348162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 3349162922Sariff (conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_CD || 3350162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN || 3351162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN)) { 3352162922Sariff w->pflags |= HDA_ADC_PATH; 3353162922Sariff ret = 1; 3354162922Sariff } 3355162922Sariff break; 3356162922Sariff /*case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: 3357162922Sariff if (w->pflags & HDA_DAC_PATH) { 3358162922Sariff w->pflags |= HDA_ADC_PATH; 3359162922Sariff ret = 1; 3360162922Sariff } 3361162922Sariff break;*/ 3362162922Sariff default: 3363162922Sariff break; 3364162922Sariff } 3365162922Sariff return (ret); 3366162922Sariff} 3367162922Sariff 3368162922Sariffstatic uint32_t 3369162922Sariffhdac_audio_ctl_outamp_build(struct hdac_devinfo *devinfo, 3370162922Sariff nid_t nid, nid_t pnid, int index, int depth) 3371162922Sariff{ 3372162922Sariff struct hdac_widget *w, *pw; 3373162922Sariff struct hdac_audio_ctl *ctl; 3374162922Sariff uint32_t fl = 0; 3375162922Sariff int i, ossdev, conndev, strategy; 3376162922Sariff 3377162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3378162922Sariff return (0); 3379162922Sariff 3380162922Sariff w = hdac_widget_get(devinfo, nid); 3381162922Sariff if (w == NULL || w->enable == 0) 3382162922Sariff return (0); 3383162922Sariff 3384162922Sariff pw = hdac_widget_get(devinfo, pnid); 3385162922Sariff strategy = devinfo->function.audio.parsing_strategy; 3386162922Sariff 3387162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER 3388162922Sariff || w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) { 3389162922Sariff for (i = 0; i < w->nconns; i++) { 3390162922Sariff fl |= hdac_audio_ctl_outamp_build(devinfo, w->conns[i], 3391162922Sariff w->nid, i, depth + 1); 3392162922Sariff } 3393162922Sariff w->ctlflags |= fl; 3394162922Sariff return (fl); 3395162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT && 3396162922Sariff (w->pflags & HDA_DAC_PATH)) { 3397162922Sariff i = 0; 3398162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3399162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3400162922Sariff continue; 3401162922Sariff if ((ctl->widget->nid == w->nid) || 3402162922Sariff (ctl->widget->nid == pnid && ctl->index == index && 3403162922Sariff (ctl->dir & HDA_CTL_IN)) || 3404162922Sariff (ctl->widget->nid == pnid && pw != NULL && 3405162922Sariff pw->type == 3406162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 3407162922Sariff (pw->nconns < 2 || pw->selconn == index || 3408162922Sariff pw->selconn == -1) && 3409162922Sariff (ctl->dir & HDA_CTL_OUT)) || 3410162922Sariff (strategy == HDA_PARSE_DIRECT && 3411162922Sariff ctl->widget->nid == w->nid)) { 3412162922Sariff if (pw != NULL && pw->selconn == -1) 3413162922Sariff pw->selconn = index; 3414162922Sariff fl |= SOUND_MASK_VOLUME; 3415162922Sariff fl |= SOUND_MASK_PCM; 3416162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3417162922Sariff ctl->ossmask |= SOUND_MASK_PCM; 3418162922Sariff ctl->ossdev = SOUND_MIXER_PCM; 3419162922Sariff } 3420162922Sariff } 3421162922Sariff w->ctlflags |= fl; 3422162922Sariff return (fl); 3423162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX 3424162922Sariff && HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) && 3425162922Sariff (w->pflags & HDA_ADC_PATH)) { 3426162922Sariff conndev = w->wclass.pin.config & 3427162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 3428162922Sariff i = 0; 3429162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3430162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3431162922Sariff continue; 3432162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 3433162922Sariff (ctl->dir & HDA_CTL_IN)) || 3434162922Sariff (ctl->widget->nid == pnid && pw != NULL && 3435162922Sariff pw->type == 3436162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 3437162922Sariff (pw->nconns < 2 || pw->selconn == index || 3438162922Sariff pw->selconn == -1) && 3439162922Sariff (ctl->dir & HDA_CTL_OUT)) || 3440162922Sariff (strategy == HDA_PARSE_DIRECT && 3441162922Sariff ctl->widget->nid == w->nid)) && 3442162922Sariff (ctl->ossmask & ~SOUND_MASK_VOLUME) == 0) { 3443162922Sariff if (pw != NULL && pw->selconn == -1) 3444162922Sariff pw->selconn = index; 3445162922Sariff ossdev = 0; 3446162922Sariff switch (conndev) { 3447162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: 3448162922Sariff ossdev = SOUND_MIXER_MIC; 3449162922Sariff break; 3450162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: 3451162922Sariff ossdev = SOUND_MIXER_LINE; 3452162922Sariff break; 3453162922Sariff case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: 3454162922Sariff ossdev = SOUND_MIXER_CD; 3455162922Sariff break; 3456162922Sariff default: 3457162922Sariff ossdev = 3458162922Sariff hdac_audio_ctl_ossmixer_getnextdev( 3459162922Sariff devinfo); 3460162922Sariff if (ossdev < 0) 3461162922Sariff ossdev = 0; 3462162922Sariff break; 3463162922Sariff } 3464162922Sariff if (strategy == HDA_PARSE_MIXER) { 3465162922Sariff fl |= SOUND_MASK_VOLUME; 3466162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3467162922Sariff } 3468162922Sariff fl |= 1 << ossdev; 3469162922Sariff ctl->ossmask |= 1 << ossdev; 3470162922Sariff ctl->ossdev = ossdev; 3471162922Sariff } 3472162922Sariff } 3473162922Sariff w->ctlflags |= fl; 3474162922Sariff return (fl); 3475162922Sariff } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 3476162922Sariff i = 0; 3477162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3478162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3479162922Sariff continue; 3480162922Sariff if (((ctl->widget->nid == pnid && ctl->index == index && 3481162922Sariff (ctl->dir & HDA_CTL_IN)) || 3482162922Sariff (ctl->widget->nid == pnid && pw != NULL && 3483162922Sariff pw->type == 3484162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR && 3485162922Sariff (pw->nconns < 2 || pw->selconn == index || 3486162922Sariff pw->selconn == -1) && 3487162922Sariff (ctl->dir & HDA_CTL_OUT)) || 3488162922Sariff (strategy == HDA_PARSE_DIRECT && 3489162922Sariff ctl->widget->nid == w->nid)) && 3490162922Sariff (ctl->ossmask & ~SOUND_MASK_VOLUME) == 0) { 3491162922Sariff if (pw != NULL && pw->selconn == -1) 3492162922Sariff pw->selconn = index; 3493162922Sariff fl |= SOUND_MASK_VOLUME; 3494162922Sariff fl |= SOUND_MASK_SPEAKER; 3495162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3496162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 3497162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 3498162922Sariff } 3499162922Sariff } 3500162922Sariff w->ctlflags |= fl; 3501162922Sariff return (fl); 3502162922Sariff } 3503162922Sariff return (0); 3504162922Sariff} 3505162922Sariff 3506162922Sariffstatic uint32_t 3507162922Sariffhdac_audio_ctl_inamp_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3508162922Sariff{ 3509162922Sariff struct hdac_widget *w, *cw; 3510162922Sariff struct hdac_audio_ctl *ctl; 3511162922Sariff uint32_t fl; 3512162922Sariff int i; 3513162922Sariff 3514162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3515162922Sariff return (0); 3516162922Sariff 3517162922Sariff w = hdac_widget_get(devinfo, nid); 3518162922Sariff if (w == NULL || w->enable == 0) 3519162922Sariff return (0); 3520162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 3521162922Sariff return (0); 3522162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 3523162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 3524162922Sariff return (0);*/ 3525162922Sariff i = 0; 3526162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3527162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3528162922Sariff continue; 3529162922Sariff if (ctl->widget->nid == nid) { 3530162922Sariff ctl->ossmask |= SOUND_MASK_RECLEV; 3531162922Sariff w->ctlflags |= SOUND_MASK_RECLEV; 3532162922Sariff return (SOUND_MASK_RECLEV); 3533162922Sariff } 3534162922Sariff } 3535162922Sariff for (i = 0; i < w->nconns; i++) { 3536162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 3537162922Sariff if (cw == NULL || cw->enable == 0) 3538162922Sariff continue; 3539162922Sariff if (cw->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 3540162922Sariff continue; 3541162922Sariff fl = hdac_audio_ctl_inamp_build(devinfo, cw->nid, depth + 1); 3542162922Sariff if (fl != 0) { 3543162922Sariff cw->ctlflags |= fl; 3544162922Sariff w->ctlflags |= fl; 3545162922Sariff return (fl); 3546162922Sariff } 3547162922Sariff } 3548162922Sariff return (0); 3549162922Sariff} 3550162922Sariff 3551162922Sariffstatic int 3552162922Sariffhdac_audio_ctl_recsel_build(struct hdac_devinfo *devinfo, nid_t nid, int depth) 3553162922Sariff{ 3554162922Sariff struct hdac_widget *w, *cw; 3555162922Sariff int i, child = 0; 3556162922Sariff 3557162922Sariff if (depth > HDA_PARSE_MAXDEPTH) 3558162922Sariff return (0); 3559162922Sariff 3560162922Sariff w = hdac_widget_get(devinfo, nid); 3561162922Sariff if (w == NULL || w->enable == 0) 3562162922Sariff return (0); 3563162922Sariff /*if (!(w->pflags & HDA_ADC_PATH)) 3564162922Sariff return (0); 3565162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT || 3566162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 3567162922Sariff return (0);*/ 3568162922Sariff /* XXX weak! */ 3569162922Sariff for (i = 0; i < w->nconns; i++) { 3570162922Sariff cw = hdac_widget_get(devinfo, w->conns[i]); 3571162922Sariff if (cw == NULL) 3572162922Sariff continue; 3573162922Sariff if (++child > 1) { 3574162922Sariff w->pflags |= HDA_ADC_RECSEL; 3575162922Sariff return (1); 3576162922Sariff } 3577162922Sariff } 3578162922Sariff for (i = 0; i < w->nconns; i++) { 3579162922Sariff if (hdac_audio_ctl_recsel_build(devinfo, 3580162922Sariff w->conns[i], depth + 1) != 0) 3581162922Sariff return (1); 3582162922Sariff } 3583162922Sariff return (0); 3584162922Sariff} 3585162922Sariff 3586162922Sariffstatic int 3587162922Sariffhdac_audio_build_tree_strategy(struct hdac_devinfo *devinfo) 3588162922Sariff{ 3589162922Sariff struct hdac_widget *w, *cw; 3590162922Sariff int i, j, conndev, found_dac = 0; 3591162922Sariff int strategy; 3592162922Sariff 3593162922Sariff strategy = devinfo->function.audio.parsing_strategy; 3594162922Sariff 3595162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3596162922Sariff w = hdac_widget_get(devinfo, i); 3597162922Sariff if (w == NULL || w->enable == 0) 3598162922Sariff continue; 3599162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 3600162922Sariff continue; 3601162922Sariff if (!HDA_PARAM_PIN_CAP_OUTPUT_CAP(w->wclass.pin.cap)) 3602162922Sariff continue; 3603162922Sariff conndev = w->wclass.pin.config & 3604162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 3605162922Sariff if (!(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT || 3606162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER || 3607162922Sariff conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT)) 3608162922Sariff continue; 3609162922Sariff for (j = 0; j < w->nconns; j++) { 3610162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 3611162922Sariff if (cw == NULL || cw->enable == 0) 3612162922Sariff continue; 3613162922Sariff if (strategy == HDA_PARSE_MIXER && !(cw->type == 3614162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 3615162922Sariff cw->type == 3616162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)) 3617162922Sariff continue; 3618162922Sariff if (hdac_widget_find_dac_path(devinfo, cw->nid, 0) 3619162922Sariff != 0) { 3620162922Sariff if (w->selconn == -1) 3621162922Sariff w->selconn = j; 3622162922Sariff w->pflags |= HDA_DAC_PATH; 3623162922Sariff found_dac++; 3624162922Sariff } 3625162922Sariff } 3626162922Sariff } 3627162922Sariff 3628162922Sariff return (found_dac); 3629162922Sariff} 3630162922Sariff 3631162922Sariffstatic void 3632162922Sariffhdac_audio_build_tree(struct hdac_devinfo *devinfo) 3633162922Sariff{ 3634162922Sariff struct hdac_widget *w; 3635162922Sariff struct hdac_audio_ctl *ctl; 3636162922Sariff int i, j, dacs, strategy; 3637162922Sariff 3638162922Sariff /* Construct DAC path */ 3639162922Sariff strategy = HDA_PARSE_MIXER; 3640162922Sariff devinfo->function.audio.parsing_strategy = strategy; 3641162922Sariff HDA_BOOTVERBOSE_MSG( 3642162922Sariff device_printf(devinfo->codec->sc->dev, 3643162922Sariff "HWiP: HDA Widget Parser - Revision %d\n", 3644162922Sariff HDA_WIDGET_PARSER_REV); 3645162922Sariff ); 3646162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 3647162922Sariff if (dacs == 0) { 3648162922Sariff HDA_BOOTVERBOSE_MSG( 3649162922Sariff device_printf(devinfo->codec->sc->dev, 3650162922Sariff "HWiP: 0 DAC found! Retrying parser " 3651162922Sariff "using HDA_PARSE_DIRECT strategy.\n"); 3652162922Sariff ); 3653162922Sariff strategy = HDA_PARSE_DIRECT; 3654162922Sariff devinfo->function.audio.parsing_strategy = strategy; 3655162922Sariff dacs = hdac_audio_build_tree_strategy(devinfo); 3656162922Sariff } 3657162922Sariff 3658162922Sariff HDA_BOOTVERBOSE_MSG( 3659162922Sariff device_printf(devinfo->codec->sc->dev, 3660162922Sariff "HWiP: Found %d DAC(s) using HDA_PARSE_%s strategy.\n", 3661162922Sariff dacs, (strategy == HDA_PARSE_MIXER) ? "MIXER" : "DIRECT"); 3662162922Sariff ); 3663162922Sariff 3664162922Sariff /* Construct ADC path */ 3665162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3666162922Sariff w = hdac_widget_get(devinfo, i); 3667162922Sariff if (w == NULL || w->enable == 0) 3668162922Sariff continue; 3669162922Sariff if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) 3670162922Sariff continue; 3671162922Sariff (void)hdac_widget_find_adc_path(devinfo, w->nid, 0); 3672162922Sariff } 3673162922Sariff 3674162922Sariff /* Output mixers */ 3675162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3676162922Sariff w = hdac_widget_get(devinfo, i); 3677162922Sariff if (w == NULL || w->enable == 0) 3678162922Sariff continue; 3679162922Sariff if ((strategy == HDA_PARSE_MIXER && 3680162922Sariff (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER || 3681162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) 3682162922Sariff && (w->pflags & HDA_DAC_PATH)) || 3683162922Sariff (strategy == HDA_PARSE_DIRECT && (w->pflags & 3684162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)))) { 3685162922Sariff w->ctlflags |= hdac_audio_ctl_outamp_build(devinfo, 3686162922Sariff w->nid, devinfo->startnode - 1, 0, 0); 3687162922Sariff } else if (w->type == 3688162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) { 3689162922Sariff j = 0; 3690162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &j)) != 3691162922Sariff NULL) { 3692162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) 3693162922Sariff continue; 3694162922Sariff if (ctl->widget->nid != w->nid) 3695162922Sariff continue; 3696162922Sariff ctl->ossmask |= SOUND_MASK_VOLUME; 3697162922Sariff ctl->ossmask |= SOUND_MASK_SPEAKER; 3698162922Sariff ctl->ossdev = SOUND_MIXER_SPEAKER; 3699162922Sariff w->ctlflags |= SOUND_MASK_VOLUME; 3700162922Sariff w->ctlflags |= SOUND_MASK_SPEAKER; 3701162922Sariff } 3702162922Sariff } 3703162922Sariff } 3704162922Sariff 3705162922Sariff /* Input mixers (rec) */ 3706162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 3707162922Sariff w = hdac_widget_get(devinfo, i); 3708162922Sariff if (w == NULL || w->enable == 0) 3709162922Sariff continue; 3710162922Sariff if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT && 3711162922Sariff w->pflags & HDA_ADC_PATH)) 3712162922Sariff continue; 3713162922Sariff hdac_audio_ctl_inamp_build(devinfo, w->nid, 0); 3714162922Sariff hdac_audio_ctl_recsel_build(devinfo, w->nid, 0); 3715162922Sariff } 3716162922Sariff} 3717162922Sariff 3718162922Sariff#define HDA_COMMIT_CONN (1 << 0) 3719162922Sariff#define HDA_COMMIT_CTRL (1 << 1) 3720162922Sariff#define HDA_COMMIT_EAPD (1 << 2) 3721162922Sariff#define HDA_COMMIT_GPIO (1 << 3) 3722162922Sariff#define HDA_COMMIT_ALL (HDA_COMMIT_CONN | HDA_COMMIT_CTRL | \ 3723162922Sariff HDA_COMMIT_EAPD | HDA_COMMIT_GPIO) 3724162922Sariff 3725162922Sariffstatic void 3726162922Sariffhdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl) 3727162922Sariff{ 3728162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3729162922Sariff struct hdac_widget *w; 3730162922Sariff nid_t cad; 3731162922Sariff int i; 3732162922Sariff 3733162922Sariff if (!(cfl & HDA_COMMIT_ALL)) 3734162922Sariff return; 3735162922Sariff 3736162922Sariff cad = devinfo->codec->cad; 3737162922Sariff 3738162922Sariff if ((cfl & HDA_COMMIT_GPIO)) { 3739162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_GPIO1) { 3740162922Sariff hdac_command(sc, 3741162922Sariff HDA_CMD_SET_GPIO_ENABLE_MASK(cad, 0x01, 3742162922Sariff 0x01), cad); 3743162922Sariff hdac_command(sc, 3744162922Sariff HDA_CMD_SET_GPIO_DIRECTION(cad, 0x01, 3745162922Sariff 0x01), cad); 3746162922Sariff hdac_command(sc, 3747162922Sariff HDA_CMD_SET_GPIO_DATA(cad, 0x01, 3748162922Sariff 0x01), cad); 3749162922Sariff } 3750162922Sariff if (devinfo->function.audio.quirks & HDA_QUIRK_GPIO2) { 3751162922Sariff hdac_command(sc, 3752162922Sariff HDA_CMD_SET_GPIO_ENABLE_MASK(cad, 0x01, 3753162922Sariff 0x02), cad); 3754162922Sariff hdac_command(sc, 3755162922Sariff HDA_CMD_SET_GPIO_DIRECTION(cad, 0x01, 3756162922Sariff 0x02), cad); 3757162922Sariff hdac_command(sc, 3758162922Sariff HDA_CMD_SET_GPIO_DATA(cad, 0x01, 3759162922Sariff 0x02), cad); 3760162922Sariff } 3761162922Sariff } 3762162922Sariff 3763162922Sariff for (i = 0; i < devinfo->nodecnt; i++) { 3764162922Sariff w = &devinfo->widget[i]; 3765162922Sariff if (w == NULL || w->enable == 0) 3766162922Sariff continue; 3767162922Sariff if (cfl & HDA_COMMIT_CONN) { 3768162922Sariff if (w->selconn == -1) 3769162922Sariff w->selconn = 0; 3770162922Sariff if (w->nconns > 0) 3771162922Sariff hdac_widget_connection_select(w, w->selconn); 3772162922Sariff } 3773162922Sariff if ((cfl & HDA_COMMIT_CTRL) && 3774162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) { 3775162922Sariff if ((w->pflags & (HDA_DAC_PATH | HDA_ADC_PATH)) == 3776162922Sariff (HDA_DAC_PATH | HDA_ADC_PATH)) 3777162922Sariff device_printf(sc->dev, "WARNING: node %d " 3778162922Sariff "participate both for DAC/ADC!\n", w->nid); 3779162922Sariff if (w->pflags & HDA_DAC_PATH) { 3780162922Sariff w->wclass.pin.ctrl &= 3781162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE; 3782162922Sariff if ((w->wclass.pin.config & 3783162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) != 3784162922Sariff HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT) 3785162922Sariff w->wclass.pin.ctrl &= 3786162922Sariff ~HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE; 3787162922Sariff } else if (w->pflags & HDA_ADC_PATH) { 3788162922Sariff w->wclass.pin.ctrl &= 3789162922Sariff ~(HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 3790162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE); 3791162922Sariff } else 3792162922Sariff w->wclass.pin.ctrl &= ~( 3793162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE | 3794162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE | 3795162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE); 3796162922Sariff hdac_command(sc, 3797162922Sariff HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid, 3798162922Sariff w->wclass.pin.ctrl), cad); 3799162922Sariff } 3800162922Sariff if ((cfl & HDA_COMMIT_EAPD) && 3801162965Sariff w->param.eapdbtl != HDAC_INVALID) 3802162922Sariff hdac_command(sc, 3803162922Sariff HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid, 3804162922Sariff w->param.eapdbtl), cad); 3805162922Sariff 3806162922Sariff DELAY(1000); 3807162922Sariff } 3808162922Sariff} 3809162922Sariff 3810162922Sariffstatic void 3811162922Sariffhdac_audio_ctl_commit(struct hdac_devinfo *devinfo) 3812162922Sariff{ 3813162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3814162922Sariff struct hdac_audio_ctl *ctl; 3815162922Sariff int i; 3816162922Sariff 3817162922Sariff devinfo->function.audio.mvol = 100 | (100 << 8); 3818162922Sariff i = 0; 3819162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3820162922Sariff if (ctl->enable == 0 || ctl->widget == NULL) { 3821162922Sariff HDA_BOOTVERBOSE_MSG( 3822162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 3823162922Sariff i, (ctl->widget != NULL) ? 3824162922Sariff ctl->widget->nid : -1); 3825162922Sariff if (ctl->childwidget != NULL) 3826162922Sariff printf(" childnid=%d", 3827162922Sariff ctl->childwidget->nid); 3828162922Sariff if (ctl->widget == NULL) 3829162922Sariff printf(" NULL WIDGET!"); 3830162922Sariff printf(" DISABLED\n"); 3831162922Sariff ); 3832162922Sariff continue; 3833162922Sariff } 3834162922Sariff HDA_BOOTVERBOSE_MSG( 3835162922Sariff if (ctl->ossmask == 0) { 3836162922Sariff device_printf(sc->dev, "[%2d] Ctl nid=%d", 3837162922Sariff i, ctl->widget->nid); 3838162922Sariff if (ctl->childwidget != NULL) 3839162922Sariff printf(" childnid=%d", 3840162922Sariff ctl->childwidget->nid); 3841162922Sariff printf(" Bind to NONE\n"); 3842162922Sariff } 3843162922Sariff ); 3844162922Sariff if (ctl->step > 0) { 3845162922Sariff ctl->ossval = (ctl->left * 100) / ctl->step; 3846162922Sariff ctl->ossval |= ((ctl->right * 100) / ctl->step) << 8; 3847162922Sariff } else 3848162922Sariff ctl->ossval = 0; 3849162922Sariff hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT, 3850162922Sariff ctl->left, ctl->right); 3851162922Sariff } 3852162922Sariff} 3853162922Sariff 3854162922Sariffstatic int 3855162922Sariffhdac_pcmchannel_setup(struct hdac_devinfo *devinfo, int dir) 3856162922Sariff{ 3857162922Sariff struct hdac_chan *ch; 3858162922Sariff struct hdac_widget *w; 3859162922Sariff uint32_t cap, fmtcap, pcmcap, path; 3860162922Sariff int i, type, ret, max; 3861162922Sariff 3862162922Sariff if (dir == PCMDIR_PLAY) { 3863162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT; 3864162922Sariff ch = &devinfo->codec->sc->play; 3865162922Sariff path = HDA_DAC_PATH; 3866162922Sariff } else { 3867162922Sariff type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT; 3868162922Sariff ch = &devinfo->codec->sc->rec; 3869162922Sariff path = HDA_ADC_PATH; 3870162922Sariff } 3871162922Sariff 3872162922Sariff ch->caps = hdac_caps; 3873162922Sariff ch->caps.fmtlist = ch->fmtlist; 3874162922Sariff ch->bit16 = 1; 3875162922Sariff ch->bit32 = 0; 3876162922Sariff ch->pcmrates[0] = 48000; 3877162922Sariff ch->pcmrates[1] = 0; 3878162922Sariff 3879162922Sariff ret = 0; 3880162922Sariff fmtcap = devinfo->function.audio.supp_stream_formats; 3881162922Sariff pcmcap = devinfo->function.audio.supp_pcm_size_rate; 3882162922Sariff max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1; 3883162922Sariff 3884162922Sariff for (i = devinfo->startnode; i < devinfo->endnode && ret < max; i++) { 3885162922Sariff w = hdac_widget_get(devinfo, i); 3886162922Sariff if (w == NULL || w->enable == 0 || w->type != type || 3887162922Sariff (w->pflags & path) == 0) 3888162922Sariff continue; 3889162922Sariff cap = w->param.widget_cap; 3890162922Sariff /*if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(cap)) 3891162922Sariff continue;*/ 3892162922Sariff if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(cap)) 3893162922Sariff continue; 3894162922Sariff cap = w->param.supp_stream_formats; 3895162922Sariff /*if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) { 3896162922Sariff } 3897162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) { 3898162922Sariff }*/ 3899162922Sariff if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 3900162922Sariff continue; 3901162922Sariff ch->io[ret++] = i; 3902162922Sariff fmtcap &= w->param.supp_stream_formats; 3903162922Sariff pcmcap &= w->param.supp_pcm_size_rate; 3904162922Sariff } 3905162922Sariff ch->io[ret] = -1; 3906162922Sariff 3907162922Sariff ch->supp_stream_formats = fmtcap; 3908162922Sariff ch->supp_pcm_size_rate = pcmcap; 3909162922Sariff 3910162922Sariff /* 3911162922Sariff * 8bit = 0 3912162922Sariff * 16bit = 1 3913162922Sariff * 20bit = 2 3914162922Sariff * 24bit = 3 3915162922Sariff * 32bit = 4 3916162922Sariff */ 3917162922Sariff if (ret > 0) { 3918162922Sariff cap = pcmcap; 3919162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 3920162922Sariff ch->bit16 = 1; 3921162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 3922162922Sariff ch->bit16 = 0; 3923162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 3924162922Sariff ch->bit32 = 4; 3925162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 3926162922Sariff ch->bit32 = 3; 3927162922Sariff else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 3928162922Sariff ch->bit32 = 2; 3929162922Sariff i = 0; 3930162922Sariff if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO)) 3931162922Sariff ch->fmtlist[i++] = AFMT_S16_LE; 3932162922Sariff ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO; 3933162922Sariff if (ch->bit32 > 0) { 3934162922Sariff if (!(devinfo->function.audio.quirks & 3935162922Sariff HDA_QUIRK_FORCESTEREO)) 3936162922Sariff ch->fmtlist[i++] = AFMT_S32_LE; 3937162922Sariff ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO; 3938162922Sariff } 3939162922Sariff ch->fmtlist[i] = 0; 3940162922Sariff i = 0; 3941162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 3942162922Sariff ch->pcmrates[i++] = 8000; 3943162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 3944162922Sariff ch->pcmrates[i++] = 11025; 3945162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 3946162922Sariff ch->pcmrates[i++] = 16000; 3947162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 3948162922Sariff ch->pcmrates[i++] = 22050; 3949162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 3950162922Sariff ch->pcmrates[i++] = 32000; 3951162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 3952162922Sariff ch->pcmrates[i++] = 44100; 3953162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(cap)) */ 3954162922Sariff ch->pcmrates[i++] = 48000; 3955162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 3956162922Sariff ch->pcmrates[i++] = 88200; 3957162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 3958162922Sariff ch->pcmrates[i++] = 96000; 3959162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 3960162922Sariff ch->pcmrates[i++] = 176400; 3961162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 3962162922Sariff ch->pcmrates[i++] = 192000; 3963162922Sariff /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(cap)) */ 3964162922Sariff ch->pcmrates[i] = 0; 3965162922Sariff if (i > 0) { 3966162922Sariff ch->caps.minspeed = ch->pcmrates[0]; 3967162922Sariff ch->caps.maxspeed = ch->pcmrates[i - 1]; 3968162922Sariff } 3969162922Sariff } 3970162922Sariff 3971162922Sariff return (ret); 3972162922Sariff} 3973162922Sariff 3974162922Sariffstatic void 3975162922Sariffhdac_dump_ctls(struct hdac_devinfo *devinfo, const char *banner, uint32_t flag) 3976162922Sariff{ 3977162922Sariff struct hdac_audio_ctl *ctl; 3978162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 3979162922Sariff int i; 3980162922Sariff uint32_t fl = 0; 3981162922Sariff 3982162922Sariff 3983162922Sariff if (flag == 0) { 3984162922Sariff fl = SOUND_MASK_VOLUME | SOUND_MASK_PCM | 3985162922Sariff SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV | 3986162922Sariff SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN; 3987162922Sariff } 3988162922Sariff 3989162922Sariff i = 0; 3990162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 3991162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 3992162922Sariff ctl->widget->enable == 0) 3993162922Sariff continue; 3994162922Sariff if ((flag == 0 && (ctl->ossmask & ~fl)) || 3995162922Sariff (flag != 0 && (ctl->ossmask & flag))) { 3996162922Sariff if (banner != NULL) { 3997162922Sariff device_printf(sc->dev, "\n"); 3998162922Sariff device_printf(sc->dev, "%s\n", banner); 3999162922Sariff } 4000162922Sariff goto hdac_ctl_dump_it_all; 4001162922Sariff } 4002162922Sariff } 4003162922Sariff 4004162922Sariff return; 4005162922Sariff 4006162922Sariffhdac_ctl_dump_it_all: 4007162922Sariff i = 0; 4008162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4009162922Sariff if (ctl->enable == 0 || ctl->widget == NULL || 4010162922Sariff ctl->widget->enable == 0) 4011162922Sariff continue; 4012162922Sariff if (!((flag == 0 && (ctl->ossmask & ~fl)) || 4013162922Sariff (flag != 0 && (ctl->ossmask & flag)))) 4014162922Sariff continue; 4015162922Sariff if (flag == 0) { 4016162922Sariff device_printf(sc->dev, "\n"); 4017162922Sariff device_printf(sc->dev, "Unknown Ctl (OSS: %s)\n", 4018162922Sariff hdac_audio_ctl_ossmixer_mask2name(ctl->ossmask)); 4019162922Sariff } 4020162922Sariff device_printf(sc->dev, " |\n"); 4021162922Sariff device_printf(sc->dev, " +- nid: %2d index: %2d ", 4022162922Sariff ctl->widget->nid, ctl->index); 4023162922Sariff if (ctl->childwidget != NULL) 4024162922Sariff printf("(nid: %2d) ", ctl->childwidget->nid); 4025162922Sariff else 4026162922Sariff printf(" "); 4027162922Sariff printf("mute: %d step: %3d size: %3d off: %3d dir=0x%x ossmask=0x%08x\n", 4028162922Sariff ctl->mute, ctl->step, ctl->size, ctl->offset, ctl->dir, 4029162922Sariff ctl->ossmask); 4030162922Sariff } 4031162922Sariff} 4032162922Sariff 4033162922Sariffstatic void 4034162922Sariffhdac_dump_audio_formats(struct hdac_softc *sc, uint32_t fcap, uint32_t pcmcap) 4035162922Sariff{ 4036162922Sariff uint32_t cap; 4037162922Sariff 4038162922Sariff cap = fcap; 4039162922Sariff if (cap != 0) { 4040162922Sariff device_printf(sc->dev, " Stream cap: 0x%08x\n", cap); 4041162922Sariff device_printf(sc->dev, " Format:"); 4042162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) 4043162922Sariff printf(" AC3"); 4044162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) 4045162922Sariff printf(" FLOAT32"); 4046162922Sariff if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap)) 4047162922Sariff printf(" PCM"); 4048162922Sariff printf("\n"); 4049162922Sariff } 4050162922Sariff cap = pcmcap; 4051162922Sariff if (cap != 0) { 4052162922Sariff device_printf(sc->dev, " PCM cap: 0x%08x\n", cap); 4053162922Sariff device_printf(sc->dev, " PCM size:"); 4054162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap)) 4055162922Sariff printf(" 8"); 4056162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap)) 4057162922Sariff printf(" 16"); 4058162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap)) 4059162922Sariff printf(" 20"); 4060162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap)) 4061162922Sariff printf(" 24"); 4062162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap)) 4063162922Sariff printf(" 32"); 4064162922Sariff printf("\n"); 4065162922Sariff device_printf(sc->dev, " PCM rate:"); 4066162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap)) 4067162922Sariff printf(" 8"); 4068162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap)) 4069162922Sariff printf(" 11"); 4070162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap)) 4071162922Sariff printf(" 16"); 4072162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap)) 4073162922Sariff printf(" 22"); 4074162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap)) 4075162922Sariff printf(" 32"); 4076162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap)) 4077162922Sariff printf(" 44"); 4078162922Sariff printf(" 48"); 4079162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap)) 4080162922Sariff printf(" 88"); 4081162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap)) 4082162922Sariff printf(" 96"); 4083162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap)) 4084162922Sariff printf(" 176"); 4085162922Sariff if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap)) 4086162922Sariff printf(" 192"); 4087162922Sariff printf("\n"); 4088162922Sariff } 4089162922Sariff} 4090162922Sariff 4091162922Sariffstatic void 4092162922Sariffhdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w) 4093162922Sariff{ 4094162922Sariff uint32_t pincap, wcap; 4095162922Sariff 4096162922Sariff pincap = w->wclass.pin.cap; 4097162922Sariff wcap = w->param.widget_cap; 4098162922Sariff 4099162922Sariff device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap); 4100162922Sariff device_printf(sc->dev, " "); 4101162922Sariff if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap)) 4102162922Sariff printf(" ISC"); 4103162922Sariff if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) 4104162922Sariff printf(" TRQD"); 4105162922Sariff if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) 4106162922Sariff printf(" PDC"); 4107162922Sariff if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap)) 4108162922Sariff printf(" HP"); 4109162922Sariff if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap)) 4110162922Sariff printf(" OUT"); 4111162922Sariff if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap)) 4112162922Sariff printf(" IN"); 4113162922Sariff if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap)) 4114162922Sariff printf(" BAL"); 4115162922Sariff if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) 4116162922Sariff printf(" EAPD"); 4117162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(wcap)) 4118162922Sariff printf(" : UNSOL"); 4119162922Sariff printf("\n"); 4120162922Sariff device_printf(sc->dev, " Pin config: 0x%08x\n", 4121162922Sariff w->wclass.pin.config); 4122162922Sariff device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl); 4123162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE) 4124162922Sariff printf(" HP"); 4125162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE) 4126162922Sariff printf(" IN"); 4127162922Sariff if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE) 4128162922Sariff printf(" OUT"); 4129162922Sariff printf("\n"); 4130162922Sariff} 4131162922Sariff 4132162922Sariffstatic void 4133162922Sariffhdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner) 4134162922Sariff{ 4135162922Sariff device_printf(sc->dev, " %s amp: 0x%0x\n", banner, cap); 4136162922Sariff device_printf(sc->dev, " " 4137162922Sariff "mute=%d step=%d size=%d offset=%d\n", 4138162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap), 4139162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap), 4140162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap), 4141162922Sariff HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap)); 4142162922Sariff} 4143162922Sariff 4144162922Sariffstatic void 4145162922Sariffhdac_dump_nodes(struct hdac_devinfo *devinfo) 4146162922Sariff{ 4147162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4148162922Sariff struct hdac_widget *w, *cw; 4149162922Sariff int i, j; 4150162922Sariff 4151162922Sariff device_printf(sc->dev, "\n"); 4152162922Sariff device_printf(sc->dev, "Default Parameter\n"); 4153162922Sariff device_printf(sc->dev, "-----------------\n"); 4154162922Sariff hdac_dump_audio_formats(sc, 4155162922Sariff devinfo->function.audio.supp_stream_formats, 4156162922Sariff devinfo->function.audio.supp_pcm_size_rate); 4157162922Sariff device_printf(sc->dev, " IN amp: 0x%08x\n", 4158162922Sariff devinfo->function.audio.inamp_cap); 4159162922Sariff device_printf(sc->dev, " OUT amp: 0x%08x\n", 4160162922Sariff devinfo->function.audio.outamp_cap); 4161162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4162162922Sariff w = hdac_widget_get(devinfo, i); 4163162922Sariff if (w == NULL) { 4164162922Sariff device_printf(sc->dev, "Ghost widget nid=%d\n", i); 4165162922Sariff continue; 4166162922Sariff } 4167162922Sariff device_printf(sc->dev, "\n"); 4168162922Sariff device_printf(sc->dev, " nid: %d [%s]%s\n", w->nid, 4169162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) ? 4170162922Sariff "DIGITAL" : "ANALOG", 4171162922Sariff (w->enable == 0) ? " [DISABLED]" : ""); 4172162922Sariff device_printf(sc->dev, " name: %s\n", w->name); 4173162922Sariff device_printf(sc->dev, " widget_cap: 0x%08x\n", 4174162922Sariff w->param.widget_cap); 4175162922Sariff device_printf(sc->dev, " Parse flags: 0x%08x\n", 4176162922Sariff w->pflags); 4177162922Sariff device_printf(sc->dev, " Ctl flags: 0x%08x\n", 4178162922Sariff w->ctlflags); 4179162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT || 4180162922Sariff w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) { 4181162922Sariff hdac_dump_audio_formats(sc, 4182162922Sariff w->param.supp_stream_formats, 4183162922Sariff w->param.supp_pcm_size_rate); 4184162922Sariff } else if (w->type == 4185162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 4186162922Sariff hdac_dump_pin(sc, w); 4187162965Sariff if (w->param.eapdbtl != HDAC_INVALID) 4188162922Sariff device_printf(sc->dev, " EAPD: 0x%08x\n", 4189162922Sariff w->param.eapdbtl); 4190162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap)) 4191162922Sariff hdac_dump_amp(sc, w->param.outamp_cap, "Output"); 4192162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap)) 4193162922Sariff hdac_dump_amp(sc, w->param.inamp_cap, " Input"); 4194162922Sariff device_printf(sc->dev, " connections: %d\n", w->nconns); 4195162922Sariff for (j = 0; j < w->nconns; j++) { 4196162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 4197162922Sariff device_printf(sc->dev, " |\n"); 4198162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 4199162922Sariff w->conns[j], (cw == NULL) ? "GHOST!" : cw->name); 4200162922Sariff if (cw == NULL) 4201162922Sariff printf(" [UNKNOWN]"); 4202162922Sariff else if (cw->enable == 0) 4203162922Sariff printf(" [DISABLED]"); 4204162922Sariff if (w->nconns > 1 && w->selconn == j && w->type != 4205162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) 4206162922Sariff printf(" (selected)"); 4207162922Sariff printf("\n"); 4208162922Sariff } 4209162922Sariff } 4210162922Sariff 4211162922Sariff} 4212162922Sariff 4213162922Sariffstatic void 4214162922Sariffhdac_dump_dac(struct hdac_devinfo *devinfo) 4215162922Sariff{ 4216162922Sariff /* XXX TODO */ 4217162922Sariff} 4218162922Sariff 4219162922Sariffstatic void 4220162922Sariffhdac_dump_adc(struct hdac_devinfo *devinfo) 4221162922Sariff{ 4222162922Sariff struct hdac_widget *w, *cw; 4223162922Sariff struct hdac_softc *sc = devinfo->codec->sc; 4224162922Sariff int i, j; 4225162922Sariff int printed = 0; 4226162922Sariff char ossdevs[256]; 4227162922Sariff 4228162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4229162922Sariff w = hdac_widget_get(devinfo, i); 4230162922Sariff if (w == NULL || w->enable == 0) 4231162922Sariff continue; 4232162922Sariff if (!(w->pflags & HDA_ADC_RECSEL)) 4233162922Sariff continue; 4234162922Sariff if (printed == 0) { 4235162922Sariff printed = 1; 4236162922Sariff device_printf(sc->dev, "\n"); 4237162922Sariff device_printf(sc->dev, "Recording sources:\n"); 4238162922Sariff } 4239162922Sariff device_printf(sc->dev, "\n"); 4240162922Sariff device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name); 4241162922Sariff for (j = 0; j < w->nconns; j++) { 4242162922Sariff cw = hdac_widget_get(devinfo, w->conns[j]); 4243162922Sariff if (cw == NULL || cw->enable == 0) 4244162922Sariff continue; 4245162922Sariff hdac_audio_ctl_ossmixer_mask2allname(cw->ctlflags, 4246162922Sariff ossdevs, sizeof(ossdevs)); 4247162922Sariff device_printf(sc->dev, " |\n"); 4248162922Sariff device_printf(sc->dev, " + <- nid=%d [%s]", 4249162922Sariff cw->nid, cw->name); 4250162922Sariff if (strlen(ossdevs) > 0) { 4251162922Sariff printf(" [recsrc: %s]", ossdevs); 4252162922Sariff } 4253162922Sariff printf("\n"); 4254162922Sariff } 4255162922Sariff } 4256162922Sariff} 4257162922Sariff 4258162922Sariffstatic void 4259162922Sariffhdac_dump_pcmchannels(struct hdac_softc *sc, int pcnt, int rcnt) 4260162922Sariff{ 4261162922Sariff nid_t *nids; 4262162922Sariff 4263162922Sariff if (pcnt > 0) { 4264162922Sariff device_printf(sc->dev, "\n"); 4265162922Sariff device_printf(sc->dev, " PCM Playback: %d\n", pcnt); 4266162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 4267162922Sariff sc->play.supp_pcm_size_rate); 4268162922Sariff device_printf(sc->dev, " DAC:"); 4269162922Sariff for (nids = sc->play.io; *nids != -1; nids++) 4270162922Sariff printf(" %d", *nids); 4271162922Sariff printf("\n"); 4272162922Sariff } 4273162922Sariff 4274162922Sariff if (rcnt > 0) { 4275162922Sariff device_printf(sc->dev, "\n"); 4276162922Sariff device_printf(sc->dev, " PCM Record: %d\n", rcnt); 4277162922Sariff hdac_dump_audio_formats(sc, sc->play.supp_stream_formats, 4278162922Sariff sc->rec.supp_pcm_size_rate); 4279162922Sariff device_printf(sc->dev, " ADC:"); 4280162922Sariff for (nids = sc->rec.io; *nids != -1; nids++) 4281162922Sariff printf(" %d", *nids); 4282162922Sariff printf("\n"); 4283162922Sariff } 4284162922Sariff} 4285162922Sariff 4286162922Sariffstatic void 4287162922Sariffhdac_attach2(void *arg) 4288162922Sariff{ 4289162922Sariff struct hdac_softc *sc; 4290162922Sariff struct hdac_widget *w; 4291162922Sariff struct hdac_audio_ctl *ctl; 4292162922Sariff int pcnt, rcnt; 4293162922Sariff int i; 4294162922Sariff char status[SND_STATUSLEN]; 4295162965Sariff device_t *devlist = NULL; 4296162922Sariff int devcount; 4297162922Sariff struct hdac_devinfo *devinfo = NULL; 4298162922Sariff 4299162922Sariff sc = (struct hdac_softc *)arg; 4300162922Sariff 4301162922Sariff 4302162922Sariff hdac_lock(sc); 4303162922Sariff 4304162922Sariff /* Remove ourselves from the config hooks */ 4305162922Sariff if (sc->intrhook.ich_func != NULL) { 4306162922Sariff config_intrhook_disestablish(&sc->intrhook); 4307162922Sariff sc->intrhook.ich_func = NULL; 4308162922Sariff } 4309162922Sariff 4310162922Sariff /* Start the corb and rirb engines */ 4311162922Sariff HDA_DEBUG_MSG( 4312162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting CORB Engine...\n"); 4313162922Sariff ); 4314162922Sariff hdac_corb_start(sc); 4315162922Sariff HDA_DEBUG_MSG( 4316162922Sariff device_printf(sc->dev, "HDA_DEBUG: Starting RIRB Engine...\n"); 4317162922Sariff ); 4318162922Sariff hdac_rirb_start(sc); 4319162922Sariff 4320162922Sariff HDA_DEBUG_MSG( 4321162922Sariff device_printf(sc->dev, 4322162922Sariff "HDA_DEBUG: Enabling controller interrupt...\n"); 4323162922Sariff ); 4324162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 4325162922Sariff 4326162922Sariff DELAY(1000); 4327162922Sariff 4328162922Sariff HDA_DEBUG_MSG( 4329162922Sariff device_printf(sc->dev, "HDA_DEBUG: Scanning HDA codecs...\n"); 4330162922Sariff ); 4331162922Sariff hdac_scan_codecs(sc); 4332162922Sariff 4333162922Sariff device_get_children(sc->dev, &devlist, &devcount); 4334162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 4335162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 4336162965Sariff if (devinfo != NULL && devinfo->node_type == 4337162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) { 4338162965Sariff break; 4339162965Sariff } else 4340162965Sariff devinfo = NULL; 4341162922Sariff } 4342162965Sariff if (devlist != NULL) 4343162965Sariff free(devlist, M_TEMP); 4344162922Sariff 4345162922Sariff if (devinfo == NULL) { 4346162922Sariff hdac_unlock(sc); 4347162922Sariff device_printf(sc->dev, "Audio Function Group not found!\n"); 4348162922Sariff return; 4349162922Sariff } 4350162922Sariff 4351162922Sariff HDA_DEBUG_MSG( 4352162922Sariff device_printf(sc->dev, 4353162922Sariff "HDA_DEBUG: Parsing AFG nid=%d cad=%d\n", 4354162922Sariff devinfo->nid, devinfo->codec->cad); 4355162922Sariff ); 4356162922Sariff hdac_audio_parse(devinfo); 4357162922Sariff HDA_DEBUG_MSG( 4358162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing Ctls...\n"); 4359162922Sariff ); 4360162922Sariff hdac_audio_ctl_parse(devinfo); 4361162922Sariff HDA_DEBUG_MSG( 4362162922Sariff device_printf(sc->dev, "HDA_DEBUG: Parsing vendor patch...\n"); 4363162922Sariff ); 4364162922Sariff hdac_vendor_patch_parse(devinfo); 4365162922Sariff 4366162922Sariff /* XXX Disable all DIGITAL path. */ 4367162922Sariff for (i = devinfo->startnode; i < devinfo->endnode; i++) { 4368162922Sariff w = hdac_widget_get(devinfo, i); 4369162922Sariff if (w == NULL) 4370162922Sariff continue; 4371162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) { 4372162922Sariff w->enable = 0; 4373162922Sariff continue; 4374162922Sariff } 4375162922Sariff /* XXX Disable useless pin ? */ 4376162922Sariff if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 4377162922Sariff (w->wclass.pin.config & 4378162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) == 4379162922Sariff HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 4380162922Sariff w->enable = 0; 4381162922Sariff } 4382162922Sariff i = 0; 4383162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4384162922Sariff if (ctl->widget == NULL) 4385162922Sariff continue; 4386162922Sariff w = ctl->widget; 4387162922Sariff if (w->enable == 0) 4388162922Sariff ctl->enable = 0; 4389162922Sariff if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 4390162922Sariff ctl->enable = 0; 4391162922Sariff w = ctl->childwidget; 4392162922Sariff if (w == NULL) 4393162922Sariff continue; 4394162922Sariff if (w->enable == 0 || 4395162922Sariff HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) 4396162922Sariff ctl->enable = 0; 4397162922Sariff } 4398162922Sariff 4399162922Sariff HDA_DEBUG_MSG( 4400162922Sariff device_printf(sc->dev, "HDA_DEBUG: Building AFG tree...\n"); 4401162922Sariff ); 4402162922Sariff hdac_audio_build_tree(devinfo); 4403162922Sariff 4404162922Sariff HDA_DEBUG_MSG( 4405162922Sariff device_printf(sc->dev, "HDA_DEBUG: AFG commit...\n"); 4406162922Sariff ); 4407162922Sariff hdac_audio_commit(devinfo, HDA_COMMIT_ALL); 4408162922Sariff HDA_DEBUG_MSG( 4409162922Sariff device_printf(sc->dev, "HDA_DEBUG: Ctls commit...\n"); 4410162922Sariff ); 4411162922Sariff hdac_audio_ctl_commit(devinfo); 4412162922Sariff 4413162922Sariff HDA_DEBUG_MSG( 4414162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_PLAY setup...\n"); 4415162922Sariff ); 4416162922Sariff pcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_PLAY); 4417162922Sariff HDA_DEBUG_MSG( 4418162922Sariff device_printf(sc->dev, "HDA_DEBUG: PCMDIR_REC setup...\n"); 4419162922Sariff ); 4420162922Sariff rcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_REC); 4421162922Sariff 4422162922Sariff hdac_unlock(sc); 4423162922Sariff HDA_DEBUG_MSG( 4424162922Sariff device_printf(sc->dev, 4425162922Sariff "HDA_DEBUG: OSS mixer initialization...\n"); 4426162922Sariff ); 4427162922Sariff if (mixer_init(sc->dev, &hdac_audio_ctl_ossmixer_class, devinfo)) { 4428162922Sariff device_printf(sc->dev, "Can't register mixer\n"); 4429162922Sariff } 4430162922Sariff 4431162922Sariff if (pcnt > 0) 4432162922Sariff pcnt = 1; 4433162922Sariff if (rcnt > 0) 4434162922Sariff rcnt = 1; 4435162922Sariff 4436162922Sariff HDA_DEBUG_MSG( 4437162922Sariff device_printf(sc->dev, 4438162922Sariff "HDA_DEBUG: Registering PCM channels...\n"); 4439162922Sariff ); 4440162922Sariff if (pcm_register(sc->dev, devinfo, pcnt, rcnt)) { 4441162922Sariff device_printf(sc->dev, "Can't register PCM\n"); 4442162922Sariff } 4443162922Sariff 4444162922Sariff sc->registered++; 4445162922Sariff 4446162922Sariff for (i = 0; i < pcnt; i++) 4447162922Sariff pcm_addchan(sc->dev, PCMDIR_PLAY, &hdac_channel_class, devinfo); 4448162922Sariff for (i = 0; i < rcnt; i++) 4449162922Sariff pcm_addchan(sc->dev, PCMDIR_REC, &hdac_channel_class, devinfo); 4450162922Sariff 4451162922Sariff snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s [%s]", 4452162922Sariff rman_get_start(sc->mem.mem_res), 4453162922Sariff rman_get_start(sc->irq.irq_res), 4454162922Sariff PCM_KLDSTRING(snd_hda), HDA_DRV_TEST_REV); 4455162922Sariff pcm_setstatus(sc->dev, status); 4456162922Sariff device_printf(sc->dev, "<HDA Codec: %s>\n", hdac_codec_name(devinfo)); 4457162922Sariff device_printf(sc->dev, "<HDA Driver Revision: %s>\n", HDA_DRV_TEST_REV); 4458162922Sariff 4459162922Sariff HDA_BOOTVERBOSE_MSG( 4460162922Sariff if (devinfo->function.audio.quirks != 0) { 4461162922Sariff device_printf(sc->dev, "\n"); 4462162922Sariff device_printf(sc->dev, "HDA quirks:"); 4463162922Sariff if (devinfo->function.audio.quirks & 4464162922Sariff HDA_QUIRK_GPIO1) 4465162922Sariff printf(" GPIO1"); 4466162922Sariff if (devinfo->function.audio.quirks & 4467162922Sariff HDA_QUIRK_GPIO2) 4468162922Sariff printf(" GPIO2"); 4469162922Sariff if (devinfo->function.audio.quirks & 4470162922Sariff HDA_QUIRK_SOFTPCMVOL) 4471162922Sariff printf(" SOFTPCMVOL"); 4472162922Sariff if (devinfo->function.audio.quirks & 4473162922Sariff HDA_QUIRK_FIXEDRATE) 4474162922Sariff printf(" FIXEDRATE"); 4475162922Sariff if (devinfo->function.audio.quirks & 4476162922Sariff HDA_QUIRK_FORCESTEREO) 4477162922Sariff printf(" FORCESTEREO"); 4478162922Sariff printf("\n"); 4479162922Sariff } 4480162922Sariff device_printf(sc->dev, "\n"); 4481162922Sariff device_printf(sc->dev, "+-------------------+\n"); 4482162922Sariff device_printf(sc->dev, "| DUMPING HDA NODES |\n"); 4483162922Sariff device_printf(sc->dev, "+-------------------+\n"); 4484162922Sariff hdac_dump_nodes(devinfo); 4485162922Sariff device_printf(sc->dev, "\n"); 4486162922Sariff device_printf(sc->dev, "+------------------------+\n"); 4487162922Sariff device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n"); 4488162922Sariff device_printf(sc->dev, "+------------------------+\n"); 4489162922Sariff device_printf(sc->dev, "\n"); 4490162922Sariff i = 0; 4491162922Sariff while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) { 4492162922Sariff device_printf(sc->dev, "%3d: nid=%d", i, 4493162922Sariff (ctl->widget != NULL) ? ctl->widget->nid : -1); 4494162922Sariff if (ctl->childwidget != NULL) 4495162922Sariff printf(" cnid=%d", ctl->childwidget->nid); 4496162922Sariff printf(" dir=0x%x index=%d " 4497162922Sariff "ossmask=0x%08x ossdev=%d%s\n", 4498162922Sariff ctl->dir, ctl->index, 4499162922Sariff ctl->ossmask, ctl->ossdev, 4500162922Sariff (ctl->enable == 0) ? " [DISABLED]" : ""); 4501162922Sariff } 4502162922Sariff device_printf(sc->dev, "\n"); 4503162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 4504162922Sariff device_printf(sc->dev, "| DUMPING HDA AUDIO/VOLUME CONTROLS |\n"); 4505162922Sariff device_printf(sc->dev, "+-----------------------------------+\n"); 4506162922Sariff hdac_dump_ctls(devinfo, "Master Volume (OSS: vol)", SOUND_MASK_VOLUME); 4507162922Sariff hdac_dump_ctls(devinfo, "PCM Volume (OSS: pcm)", SOUND_MASK_PCM); 4508162922Sariff hdac_dump_ctls(devinfo, "CD Volume (OSS: cd)", SOUND_MASK_CD); 4509162922Sariff hdac_dump_ctls(devinfo, "Microphone Volume (OSS: mic)", SOUND_MASK_MIC); 4510162922Sariff hdac_dump_ctls(devinfo, "Line-in Volume (OSS: line)", SOUND_MASK_LINE); 4511162922Sariff hdac_dump_ctls(devinfo, "Recording Level (OSS: rec)", SOUND_MASK_RECLEV); 4512162922Sariff hdac_dump_ctls(devinfo, "Speaker/Beep (OSS: speaker)", SOUND_MASK_SPEAKER); 4513162922Sariff hdac_dump_ctls(devinfo, NULL, 0); 4514162922Sariff hdac_dump_dac(devinfo); 4515162922Sariff hdac_dump_adc(devinfo); 4516162922Sariff device_printf(sc->dev, "\n"); 4517162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 4518162922Sariff device_printf(sc->dev, "| DUMPING PCM Playback/Record Channels |\n"); 4519162922Sariff device_printf(sc->dev, "+--------------------------------------+\n"); 4520162922Sariff hdac_dump_pcmchannels(sc, pcnt, rcnt); 4521162922Sariff ); 4522162922Sariff} 4523162922Sariff 4524162922Sariff/**************************************************************************** 4525162922Sariff * int hdac_detach(device_t) 4526162922Sariff * 4527162922Sariff * Detach and free up resources utilized by the hdac device. 4528162922Sariff ****************************************************************************/ 4529162922Sariffstatic int 4530162922Sariffhdac_detach(device_t dev) 4531162922Sariff{ 4532162922Sariff struct hdac_softc *sc = NULL; 4533162965Sariff device_t *devlist = NULL; 4534162922Sariff int devcount; 4535162922Sariff struct hdac_devinfo *devinfo = NULL; 4536162965Sariff struct hdac_codec *codec; 4537162922Sariff int i; 4538162922Sariff 4539162922Sariff devinfo = (struct hdac_devinfo *)pcm_getdevinfo(dev); 4540162922Sariff if (devinfo != NULL && devinfo->codec != NULL) 4541162922Sariff sc = devinfo->codec->sc; 4542162922Sariff if (sc == NULL) 4543162922Sariff return (EINVAL); 4544162922Sariff 4545162922Sariff if (sc->registered > 0) { 4546162922Sariff i = pcm_unregister(dev); 4547162922Sariff if (i) 4548162922Sariff return (i); 4549162922Sariff } 4550162922Sariff 4551162922Sariff sc->registered = 0; 4552162922Sariff 4553162922Sariff /* Lock the mutex before messing with the dma engines */ 4554162922Sariff hdac_lock(sc); 4555162922Sariff hdac_reset(sc); 4556162922Sariff hdac_unlock(sc); 4557162922Sariff snd_mtxfree(sc->lock); 4558162922Sariff sc->lock = NULL; 4559162922Sariff 4560162922Sariff device_get_children(sc->dev, &devlist, &devcount); 4561162965Sariff for (i = 0; devlist != NULL && i < devcount; i++) { 4562162965Sariff devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]); 4563162965Sariff if (devinfo == NULL) 4564162965Sariff continue; 4565162965Sariff if (devinfo->widget != NULL) 4566162965Sariff free(devinfo->widget, M_HDAC); 4567162965Sariff if (devinfo->node_type == 4568162965Sariff HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO && 4569162965Sariff devinfo->function.audio.ctl != NULL) 4570162965Sariff free(devinfo->function.audio.ctl, M_HDAC); 4571162965Sariff free(devinfo, M_HDAC); 4572162965Sariff device_delete_child(sc->dev, devlist[i]); 4573162965Sariff } 4574162965Sariff if (devlist != NULL) 4575162922Sariff free(devlist, M_TEMP); 4576162922Sariff 4577162965Sariff while (!SLIST_EMPTY(&sc->codec_list)) { 4578162965Sariff codec = SLIST_FIRST(&sc->codec_list); 4579162965Sariff SLIST_REMOVE_HEAD(&sc->codec_list, next_codec); 4580162965Sariff free(codec, M_HDAC); 4581162922Sariff } 4582162922Sariff 4583162922Sariff hdac_dma_free(&sc->rirb_dma); 4584162922Sariff hdac_dma_free(&sc->corb_dma); 4585162922Sariff if (sc->play.blkcnt) 4586162922Sariff hdac_dma_free(&sc->play.bdl_dma); 4587162922Sariff if (sc->rec.blkcnt) 4588162922Sariff hdac_dma_free(&sc->rec.bdl_dma); 4589162922Sariff hdac_irq_free(sc); 4590162922Sariff hdac_mem_free(sc); 4591162922Sariff free(sc, M_DEVBUF); 4592162922Sariff 4593162922Sariff return (0); 4594162922Sariff} 4595162922Sariff 4596162922Sariffstatic device_method_t hdac_methods[] = { 4597162922Sariff /* device interface */ 4598162922Sariff DEVMETHOD(device_probe, hdac_probe), 4599162922Sariff DEVMETHOD(device_attach, hdac_attach), 4600162922Sariff DEVMETHOD(device_detach, hdac_detach), 4601162922Sariff { 0, 0 } 4602162922Sariff}; 4603162922Sariff 4604162922Sariffstatic driver_t hdac_driver = { 4605162922Sariff "pcm", 4606162922Sariff hdac_methods, 4607162922Sariff PCM_SOFTC_SIZE, 4608162922Sariff}; 4609162922Sariff 4610162922SariffDRIVER_MODULE(snd_hda, pci, hdac_driver, pcm_devclass, 0, 0); 4611162922SariffMODULE_DEPEND(snd_hda, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 4612162922SariffMODULE_VERSION(snd_hda, 1); 4613