hdac.c revision 264832
1162922Sariff/*- 2162922Sariff * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca> 3162922Sariff * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org> 4230130Smav * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org> 5162922Sariff * All rights reserved. 6162922Sariff * 7162922Sariff * Redistribution and use in source and binary forms, with or without 8162922Sariff * modification, are permitted provided that the following conditions 9162922Sariff * are met: 10162922Sariff * 1. Redistributions of source code must retain the above copyright 11162922Sariff * notice, this list of conditions and the following disclaimer. 12162922Sariff * 2. Redistributions in binary form must reproduce the above copyright 13162922Sariff * notice, this list of conditions and the following disclaimer in the 14162922Sariff * documentation and/or other materials provided with the distribution. 15162922Sariff * 16162922Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19162922Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26162922Sariff * SUCH DAMAGE. 27162922Sariff */ 28162922Sariff 29162922Sariff/* 30230130Smav * Intel High Definition Audio (Controller) driver for FreeBSD. 31162922Sariff */ 32162922Sariff 33193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 34193640Sariff#include "opt_snd.h" 35193640Sariff#endif 36193640Sariff 37162922Sariff#include <dev/sound/pcm/sound.h> 38162922Sariff#include <dev/pci/pcireg.h> 39162922Sariff#include <dev/pci/pcivar.h> 40162922Sariff 41171141Sariff#include <sys/ctype.h> 42171141Sariff#include <sys/taskqueue.h> 43171141Sariff 44162922Sariff#include <dev/sound/pci/hda/hdac_private.h> 45162922Sariff#include <dev/sound/pci/hda/hdac_reg.h> 46162922Sariff#include <dev/sound/pci/hda/hda_reg.h> 47162922Sariff#include <dev/sound/pci/hda/hdac.h> 48162922Sariff 49230571Smav#define HDA_DRV_TEST_REV "20120126_0002" 50162922Sariff 51162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 264832 2014-04-23 19:32:50Z marius $"); 52162922Sariff 53162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 54162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 55163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 56163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 57162922Sariff 58230130Smav#define HDAC_QUIRK_64BIT (1 << 0) 59230130Smav#define HDAC_QUIRK_DMAPOS (1 << 1) 60230130Smav#define HDAC_QUIRK_MSI (1 << 2) 61162965Sariff 62163057Sariffstatic const struct { 63264832Smarius const char *key; 64163057Sariff uint32_t value; 65163057Sariff} hdac_quirks_tab[] = { 66230130Smav { "64bit", HDAC_QUIRK_DMAPOS }, 67230130Smav { "dmapos", HDAC_QUIRK_DMAPOS }, 68230130Smav { "msi", HDAC_QUIRK_MSI }, 69163057Sariff}; 70163057Sariff 71230130SmavMALLOC_DEFINE(M_HDAC, "hdac", "HDA Controller"); 72162922Sariff 73162922Sariffstatic const struct { 74162922Sariff uint32_t model; 75264832Smarius const char *desc; 76230130Smav char quirks_on; 77230130Smav char quirks_off; 78162922Sariff} hdac_devices[] = { 79258170Smav { HDA_INTEL_OAK, "Intel Oaktrail", 0, 0 }, 80258170Smav { HDA_INTEL_BAY, "Intel BayTrail", 0, 0 }, 81258170Smav { HDA_INTEL_HSW1, "Intel Haswell", 0, 0 }, 82258170Smav { HDA_INTEL_HSW2, "Intel Haswell", 0, 0 }, 83258170Smav { HDA_INTEL_HSW3, "Intel Haswell", 0, 0 }, 84230130Smav { HDA_INTEL_CPT, "Intel Cougar Point", 0, 0 }, 85230130Smav { HDA_INTEL_PATSBURG,"Intel Patsburg", 0, 0 }, 86230130Smav { HDA_INTEL_PPT1, "Intel Panther Point", 0, 0 }, 87244980Sjfv { HDA_INTEL_LPT1, "Intel Lynx Point", 0, 0 }, 88244980Sjfv { HDA_INTEL_LPT2, "Intel Lynx Point", 0, 0 }, 89258170Smav { HDA_INTEL_WELLS1, "Intel Wellsburg", 0, 0 }, 90258170Smav { HDA_INTEL_WELLS2, "Intel Wellsburg", 0, 0 }, 91258170Smav { HDA_INTEL_LPTLP1, "Intel Lynx Point-LP", 0, 0 }, 92258170Smav { HDA_INTEL_LPTLP2, "Intel Lynx Point-LP", 0, 0 }, 93230130Smav { HDA_INTEL_82801F, "Intel 82801F", 0, 0 }, 94230130Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0, 0 }, 95230130Smav { HDA_INTEL_82801G, "Intel 82801G", 0, 0 }, 96230130Smav { HDA_INTEL_82801H, "Intel 82801H", 0, 0 }, 97230130Smav { HDA_INTEL_82801I, "Intel 82801I", 0, 0 }, 98230130Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0, 0 }, 99230130Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0, 0 }, 100230130Smav { HDA_INTEL_PCH, "Intel 5 Series/3400 Series", 0, 0 }, 101230130Smav { HDA_INTEL_PCH2, "Intel 5 Series/3400 Series", 0, 0 }, 102230130Smav { HDA_INTEL_SCH, "Intel SCH", 0, 0 }, 103230130Smav { HDA_NVIDIA_MCP51, "NVIDIA MCP51", 0, HDAC_QUIRK_MSI }, 104230130Smav { HDA_NVIDIA_MCP55, "NVIDIA MCP55", 0, HDAC_QUIRK_MSI }, 105230130Smav { HDA_NVIDIA_MCP61_1, "NVIDIA MCP61", 0, 0 }, 106230130Smav { HDA_NVIDIA_MCP61_2, "NVIDIA MCP61", 0, 0 }, 107230130Smav { HDA_NVIDIA_MCP65_1, "NVIDIA MCP65", 0, 0 }, 108230130Smav { HDA_NVIDIA_MCP65_2, "NVIDIA MCP65", 0, 0 }, 109230130Smav { HDA_NVIDIA_MCP67_1, "NVIDIA MCP67", 0, 0 }, 110230130Smav { HDA_NVIDIA_MCP67_2, "NVIDIA MCP67", 0, 0 }, 111230130Smav { HDA_NVIDIA_MCP73_1, "NVIDIA MCP73", 0, 0 }, 112230130Smav { HDA_NVIDIA_MCP73_2, "NVIDIA MCP73", 0, 0 }, 113230130Smav { HDA_NVIDIA_MCP78_1, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 114230130Smav { HDA_NVIDIA_MCP78_2, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 115230130Smav { HDA_NVIDIA_MCP78_3, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 116230130Smav { HDA_NVIDIA_MCP78_4, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 117230130Smav { HDA_NVIDIA_MCP79_1, "NVIDIA MCP79", 0, 0 }, 118230130Smav { HDA_NVIDIA_MCP79_2, "NVIDIA MCP79", 0, 0 }, 119230130Smav { HDA_NVIDIA_MCP79_3, "NVIDIA MCP79", 0, 0 }, 120230130Smav { HDA_NVIDIA_MCP79_4, "NVIDIA MCP79", 0, 0 }, 121230130Smav { HDA_NVIDIA_MCP89_1, "NVIDIA MCP89", 0, 0 }, 122230130Smav { HDA_NVIDIA_MCP89_2, "NVIDIA MCP89", 0, 0 }, 123230130Smav { HDA_NVIDIA_MCP89_3, "NVIDIA MCP89", 0, 0 }, 124230130Smav { HDA_NVIDIA_MCP89_4, "NVIDIA MCP89", 0, 0 }, 125230331Smav { HDA_NVIDIA_0BE2, "NVIDIA (0x0be2)", 0, HDAC_QUIRK_MSI }, 126230331Smav { HDA_NVIDIA_0BE3, "NVIDIA (0x0be3)", 0, HDAC_QUIRK_MSI }, 127230331Smav { HDA_NVIDIA_0BE4, "NVIDIA (0x0be4)", 0, HDAC_QUIRK_MSI }, 128230312Smav { HDA_NVIDIA_GT100, "NVIDIA GT100", 0, HDAC_QUIRK_MSI }, 129230312Smav { HDA_NVIDIA_GT104, "NVIDIA GT104", 0, HDAC_QUIRK_MSI }, 130230312Smav { HDA_NVIDIA_GT106, "NVIDIA GT106", 0, HDAC_QUIRK_MSI }, 131230312Smav { HDA_NVIDIA_GT108, "NVIDIA GT108", 0, HDAC_QUIRK_MSI }, 132230312Smav { HDA_NVIDIA_GT116, "NVIDIA GT116", 0, HDAC_QUIRK_MSI }, 133230312Smav { HDA_NVIDIA_GF119, "NVIDIA GF119", 0, 0 }, 134230312Smav { HDA_NVIDIA_GF110_1, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 135230312Smav { HDA_NVIDIA_GF110_2, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 136230130Smav { HDA_ATI_SB450, "ATI SB450", 0, 0 }, 137230130Smav { HDA_ATI_SB600, "ATI SB600", 0, 0 }, 138230130Smav { HDA_ATI_RS600, "ATI RS600", 0, 0 }, 139230130Smav { HDA_ATI_RS690, "ATI RS690", 0, 0 }, 140230130Smav { HDA_ATI_RS780, "ATI RS780", 0, 0 }, 141230130Smav { HDA_ATI_R600, "ATI R600", 0, 0 }, 142230130Smav { HDA_ATI_RV610, "ATI RV610", 0, 0 }, 143230130Smav { HDA_ATI_RV620, "ATI RV620", 0, 0 }, 144230130Smav { HDA_ATI_RV630, "ATI RV630", 0, 0 }, 145230130Smav { HDA_ATI_RV635, "ATI RV635", 0, 0 }, 146230130Smav { HDA_ATI_RV710, "ATI RV710", 0, 0 }, 147230130Smav { HDA_ATI_RV730, "ATI RV730", 0, 0 }, 148230130Smav { HDA_ATI_RV740, "ATI RV740", 0, 0 }, 149230130Smav { HDA_ATI_RV770, "ATI RV770", 0, 0 }, 150239908Smav { HDA_ATI_RV810, "ATI RV810", 0, 0 }, 151239908Smav { HDA_ATI_RV830, "ATI RV830", 0, 0 }, 152239908Smav { HDA_ATI_RV840, "ATI RV840", 0, 0 }, 153239908Smav { HDA_ATI_RV870, "ATI RV870", 0, 0 }, 154239908Smav { HDA_ATI_RV910, "ATI RV910", 0, 0 }, 155239908Smav { HDA_ATI_RV930, "ATI RV930", 0, 0 }, 156239908Smav { HDA_ATI_RV940, "ATI RV940", 0, 0 }, 157239908Smav { HDA_ATI_RV970, "ATI RV970", 0, 0 }, 158239908Smav { HDA_ATI_R1000, "ATI R1000", 0, 0 }, 159230130Smav { HDA_RDC_M3010, "RDC M3010", 0, 0 }, 160230130Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 }, 161230130Smav { HDA_SIS_966, "SiS 966", 0, 0 }, 162230130Smav { HDA_ULI_M5461, "ULI M5461", 0, 0 }, 163162922Sariff /* Unknown */ 164230331Smav { HDA_INTEL_ALL, "Intel", 0, 0 }, 165230331Smav { HDA_NVIDIA_ALL, "NVIDIA", 0, 0 }, 166230331Smav { HDA_ATI_ALL, "ATI", 0, 0 }, 167230331Smav { HDA_VIA_ALL, "VIA", 0, 0 }, 168230331Smav { HDA_SIS_ALL, "SiS", 0, 0 }, 169230331Smav { HDA_ULI_ALL, "ULI", 0, 0 }, 170162922Sariff}; 171162922Sariff 172162922Sariffstatic const struct { 173169277Sariff uint16_t vendor; 174169277Sariff uint8_t reg; 175169277Sariff uint8_t mask; 176169277Sariff uint8_t enable; 177169277Sariff} hdac_pcie_snoop[] = { 178169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 179169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 180169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 181169277Sariff}; 182169277Sariff 183162922Sariff/**************************************************************************** 184162922Sariff * Function prototypes 185162922Sariff ****************************************************************************/ 186162922Sariffstatic void hdac_intr_handler(void *); 187182999Smavstatic int hdac_reset(struct hdac_softc *, int); 188162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 189162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 190162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 191162922Sariff struct hdac_dma *, bus_size_t); 192169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 193162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 194162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 195162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 196162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 197162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 198162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 199162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 200162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 201162922Sariff 202162922Sariffstatic void hdac_attach2(void *); 203162922Sariff 204230130Smavstatic uint32_t hdac_send_command(struct hdac_softc *, nid_t, uint32_t); 205162922Sariff 206162922Sariffstatic int hdac_probe(device_t); 207162922Sariffstatic int hdac_attach(device_t); 208162922Sariffstatic int hdac_detach(device_t); 209182999Smavstatic int hdac_suspend(device_t); 210182999Smavstatic int hdac_resume(device_t); 211162922Sariff 212164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 213164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 214164614Sariff 215162922Sariff#define hdac_command(a1, a2, a3) \ 216230130Smav hdac_send_command(a1, a3, a2) 217162922Sariff 218230130Smav/* This function surely going to make its way into upper level someday. */ 219162922Sariffstatic void 220230130Smavhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 221162922Sariff{ 222230130Smav const char *res = NULL; 223230130Smav int i = 0, j, k, len, inv; 224162922Sariff 225230130Smav if (resource_string_value(device_get_name(sc->dev), 226230130Smav device_get_unit(sc->dev), "config", &res) != 0) 227162922Sariff return; 228230130Smav if (!(res != NULL && strlen(res) > 0)) 229230130Smav return; 230230130Smav HDA_BOOTVERBOSE( 231230130Smav device_printf(sc->dev, "Config options:"); 232230130Smav ); 233230130Smav for (;;) { 234230130Smav while (res[i] != '\0' && 235230130Smav (res[i] == ',' || isspace(res[i]) != 0)) 236230130Smav i++; 237230130Smav if (res[i] == '\0') { 238230130Smav HDA_BOOTVERBOSE( 239230130Smav printf("\n"); 240230130Smav ); 241230130Smav return; 242182999Smav } 243230130Smav j = i; 244230130Smav while (res[j] != '\0' && 245230130Smav !(res[j] == ',' || isspace(res[j]) != 0)) 246230130Smav j++; 247230130Smav len = j - i; 248230130Smav if (len > 2 && strncmp(res + i, "no", 2) == 0) 249230130Smav inv = 2; 250230130Smav else 251230130Smav inv = 0; 252264832Smarius for (k = 0; len > inv && k < nitems(hdac_quirks_tab); k++) { 253230130Smav if (strncmp(res + i + inv, 254230130Smav hdac_quirks_tab[k].key, len - inv) != 0) 255182999Smav continue; 256230130Smav if (len - inv != strlen(hdac_quirks_tab[k].key)) 257182999Smav continue; 258230130Smav HDA_BOOTVERBOSE( 259230130Smav printf(" %s%s", (inv != 0) ? "no" : "", 260230130Smav hdac_quirks_tab[k].key); 261230130Smav ); 262230130Smav if (inv == 0) { 263230130Smav *on |= hdac_quirks_tab[k].value; 264230130Smav *on &= ~hdac_quirks_tab[k].value; 265230130Smav } else if (inv != 0) { 266230130Smav *off |= hdac_quirks_tab[k].value; 267230130Smav *off &= ~hdac_quirks_tab[k].value; 268162922Sariff } 269162965Sariff break; 270182999Smav } 271230130Smav i = j; 272162922Sariff } 273162922Sariff} 274162922Sariff 275162922Sariff/**************************************************************************** 276162922Sariff * void hdac_intr_handler(void *) 277162922Sariff * 278162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 279162922Sariff ****************************************************************************/ 280162922Sariffstatic void 281162922Sariffhdac_intr_handler(void *context) 282162922Sariff{ 283162922Sariff struct hdac_softc *sc; 284230130Smav device_t dev; 285162922Sariff uint32_t intsts; 286162922Sariff uint8_t rirbsts; 287182999Smav int i; 288162922Sariff 289162922Sariff sc = (struct hdac_softc *)context; 290162922Sariff hdac_lock(sc); 291171141Sariff 292162922Sariff /* Do we have anything to do? */ 293162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 294230130Smav if ((intsts & HDAC_INTSTS_GIS) == 0) { 295162922Sariff hdac_unlock(sc); 296162922Sariff return; 297162922Sariff } 298162922Sariff 299162922Sariff /* Was this a controller interrupt? */ 300230130Smav if (intsts & HDAC_INTSTS_CIS) { 301162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 302162922Sariff /* Get as many responses that we can */ 303230130Smav while (rirbsts & HDAC_RIRBSTS_RINTFL) { 304164614Sariff HDAC_WRITE_1(&sc->mem, 305164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 306230130Smav hdac_rirb_flush(sc); 307162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 308162922Sariff } 309230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 310230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 311162922Sariff } 312164614Sariff 313163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 314230130Smav for (i = 0; i < sc->num_ss; i++) { 315230130Smav if ((intsts & (1 << i)) == 0) 316230130Smav continue; 317230130Smav HDAC_WRITE_1(&sc->mem, (i << 5) + HDAC_SDSTS, 318230130Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 319230130Smav if ((dev = sc->streams[i].dev) != NULL) { 320230130Smav HDAC_STREAM_INTR(dev, 321230130Smav sc->streams[i].dir, sc->streams[i].stream); 322230130Smav } 323182999Smav } 324162922Sariff } 325162922Sariff 326230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts); 327164614Sariff hdac_unlock(sc); 328230130Smav} 329162922Sariff 330230130Smavstatic void 331230130Smavhdac_poll_callback(void *arg) 332230130Smav{ 333230130Smav struct hdac_softc *sc = arg; 334230130Smav 335230130Smav if (sc == NULL) 336230130Smav return; 337230130Smav 338230130Smav hdac_lock(sc); 339230130Smav if (sc->polling == 0) { 340230130Smav hdac_unlock(sc); 341230130Smav return; 342182999Smav } 343230130Smav callout_reset(&sc->poll_callout, sc->poll_ival, 344230130Smav hdac_poll_callback, sc); 345230130Smav hdac_unlock(sc); 346230130Smav 347230130Smav hdac_intr_handler(sc); 348162922Sariff} 349162922Sariff 350162922Sariff/**************************************************************************** 351182999Smav * int hdac_reset(hdac_softc *, int) 352162922Sariff * 353162922Sariff * Reset the hdac to a quiescent and known state. 354162922Sariff ****************************************************************************/ 355162922Sariffstatic int 356182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 357162922Sariff{ 358162922Sariff uint32_t gctl; 359162922Sariff int count, i; 360162922Sariff 361162922Sariff /* 362162922Sariff * Stop all Streams DMA engine 363162922Sariff */ 364162922Sariff for (i = 0; i < sc->num_iss; i++) 365162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 366162922Sariff for (i = 0; i < sc->num_oss; i++) 367162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 368162922Sariff for (i = 0; i < sc->num_bss; i++) 369162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 370162922Sariff 371162922Sariff /* 372169277Sariff * Stop Control DMA engines. 373162922Sariff */ 374162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 375162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 376162922Sariff 377162922Sariff /* 378169277Sariff * Reset DMA position buffer. 379169277Sariff */ 380169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 381169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 382169277Sariff 383169277Sariff /* 384162922Sariff * Reset the controller. The reset must remain asserted for 385162922Sariff * a minimum of 100us. 386162922Sariff */ 387162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 388162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 389162922Sariff count = 10000; 390162922Sariff do { 391162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 392162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 393162922Sariff break; 394162922Sariff DELAY(10); 395162922Sariff } while (--count); 396162922Sariff if (gctl & HDAC_GCTL_CRST) { 397162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 398162922Sariff return (ENXIO); 399162922Sariff } 400230130Smav 401182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 402182999Smav if (!wakeup) 403182999Smav return (0); 404230130Smav 405162922Sariff DELAY(100); 406162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 407162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 408162922Sariff count = 10000; 409162922Sariff do { 410162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 411163057Sariff if (gctl & HDAC_GCTL_CRST) 412162922Sariff break; 413162922Sariff DELAY(10); 414162922Sariff } while (--count); 415162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 416162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 417162922Sariff return (ENXIO); 418162922Sariff } 419162922Sariff 420162922Sariff /* 421162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 422162922Sariff * should be of 250us but for some reasons, on it's not enough on my 423162922Sariff * computer. Let's use twice as much as necessary to make sure that 424162922Sariff * it's reset properly. 425162922Sariff */ 426162922Sariff DELAY(1000); 427162922Sariff 428162922Sariff return (0); 429162922Sariff} 430162922Sariff 431162922Sariff 432162922Sariff/**************************************************************************** 433162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 434162922Sariff * 435162922Sariff * Retreive the general capabilities of the hdac; 436162922Sariff * Number of Input Streams 437162922Sariff * Number of Output Streams 438162922Sariff * Number of bidirectional Streams 439162922Sariff * 64bit ready 440162922Sariff * CORB and RIRB sizes 441162922Sariff ****************************************************************************/ 442162922Sariffstatic int 443162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 444162922Sariff{ 445162922Sariff uint16_t gcap; 446162922Sariff uint8_t corbsize, rirbsize; 447162922Sariff 448162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 449162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 450162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 451162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 452230130Smav sc->num_ss = sc->num_iss + sc->num_oss + sc->num_bss; 453196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 454230130Smav sc->support_64bit = (gcap & HDAC_GCAP_64OK) != 0; 455230130Smav if (sc->quirks_on & HDAC_QUIRK_64BIT) 456230130Smav sc->support_64bit = 1; 457230130Smav else if (sc->quirks_off & HDAC_QUIRK_64BIT) 458230130Smav sc->support_64bit = 0; 459162922Sariff 460162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 461162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 462162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 463162922Sariff sc->corb_size = 256; 464162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 465162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 466162922Sariff sc->corb_size = 16; 467162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 468162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 469162922Sariff sc->corb_size = 2; 470162922Sariff else { 471162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 472162922Sariff __func__, corbsize); 473162922Sariff return (ENXIO); 474162922Sariff } 475162922Sariff 476162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 477162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 478162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 479162922Sariff sc->rirb_size = 256; 480162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 481162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 482162922Sariff sc->rirb_size = 16; 483162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 484162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 485162922Sariff sc->rirb_size = 2; 486162922Sariff else { 487162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 488162922Sariff __func__, rirbsize); 489162922Sariff return (ENXIO); 490162922Sariff } 491162922Sariff 492196762Smav HDA_BOOTVERBOSE( 493196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 494196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 495196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 496196762Smav sc->support_64bit ? ", 64bit" : "", 497196762Smav sc->corb_size, sc->rirb_size); 498182999Smav ); 499182999Smav 500162922Sariff return (0); 501162922Sariff} 502162922Sariff 503162922Sariff 504162922Sariff/**************************************************************************** 505162922Sariff * void hdac_dma_cb 506162922Sariff * 507162922Sariff * This function is called by bus_dmamap_load when the mapping has been 508162922Sariff * established. We just record the physical address of the mapping into 509162922Sariff * the struct hdac_dma passed in. 510162922Sariff ****************************************************************************/ 511162922Sariffstatic void 512162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 513162922Sariff{ 514162922Sariff struct hdac_dma *dma; 515162922Sariff 516162922Sariff if (error == 0) { 517162922Sariff dma = (struct hdac_dma *)callback_arg; 518162922Sariff dma->dma_paddr = segs[0].ds_addr; 519162922Sariff } 520162922Sariff} 521162922Sariff 522162922Sariff 523162922Sariff/**************************************************************************** 524162922Sariff * int hdac_dma_alloc 525162922Sariff * 526162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 527162922Sariff * It must be freed by a corresponding hdac_dma_free. 528162922Sariff ****************************************************************************/ 529162922Sariffstatic int 530162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 531162922Sariff{ 532169277Sariff bus_size_t roundsz; 533162922Sariff int result; 534162922Sariff 535230130Smav roundsz = roundup2(size, HDA_DMA_ALIGNMENT); 536162922Sariff bzero(dma, sizeof(*dma)); 537162922Sariff 538162922Sariff /* 539162922Sariff * Create a DMA tag 540162922Sariff */ 541194861Smav result = bus_dma_tag_create( 542194861Smav bus_get_dma_tag(sc->dev), /* parent */ 543230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 544162922Sariff 0, /* boundary */ 545194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 546194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 547162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 548162922Sariff NULL, /* filtfunc */ 549162922Sariff NULL, /* fistfuncarg */ 550169277Sariff roundsz, /* maxsize */ 551162922Sariff 1, /* nsegments */ 552169277Sariff roundsz, /* maxsegsz */ 553162922Sariff 0, /* flags */ 554162922Sariff NULL, /* lockfunc */ 555162922Sariff NULL, /* lockfuncarg */ 556162922Sariff &dma->dma_tag); /* dmat */ 557162922Sariff if (result != 0) { 558162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 559162922Sariff __func__, result); 560167773Sariff goto hdac_dma_alloc_fail; 561162922Sariff } 562162922Sariff 563162922Sariff /* 564162922Sariff * Allocate DMA memory 565162922Sariff */ 566162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 567169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 568171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 569171330Sariff &dma->dma_map); 570162922Sariff if (result != 0) { 571162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 572162922Sariff __func__, result); 573167773Sariff goto hdac_dma_alloc_fail; 574162922Sariff } 575162922Sariff 576169277Sariff dma->dma_size = roundsz; 577169277Sariff 578162922Sariff /* 579162922Sariff * Map the memory 580162922Sariff */ 581162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 582169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 583162922Sariff if (result != 0 || dma->dma_paddr == 0) { 584167773Sariff if (result == 0) 585167773Sariff result = ENOMEM; 586162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 587162922Sariff __func__, result); 588167773Sariff goto hdac_dma_alloc_fail; 589162922Sariff } 590162922Sariff 591183097Smav HDA_BOOTHVERBOSE( 592169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 593169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 594169277Sariff ); 595169277Sariff 596162922Sariff return (0); 597169277Sariff 598167773Sariffhdac_dma_alloc_fail: 599169277Sariff hdac_dma_free(sc, dma); 600167773Sariff 601162922Sariff return (result); 602162922Sariff} 603162922Sariff 604162922Sariff 605162922Sariff/**************************************************************************** 606169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 607162922Sariff * 608162922Sariff * Free a struct dhac_dma that has been previously allocated via the 609162922Sariff * hdac_dma_alloc function. 610162922Sariff ****************************************************************************/ 611162922Sariffstatic void 612169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 613162922Sariff{ 614167773Sariff if (dma->dma_map != NULL) { 615169277Sariff#if 0 616162922Sariff /* Flush caches */ 617162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 618162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 619169277Sariff#endif 620162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 621167773Sariff } 622167773Sariff if (dma->dma_vaddr != NULL) { 623162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 624167773Sariff dma->dma_vaddr = NULL; 625167773Sariff } 626167773Sariff dma->dma_map = NULL; 627167773Sariff if (dma->dma_tag != NULL) { 628162922Sariff bus_dma_tag_destroy(dma->dma_tag); 629167773Sariff dma->dma_tag = NULL; 630162922Sariff } 631167773Sariff dma->dma_size = 0; 632162922Sariff} 633162922Sariff 634162922Sariff/**************************************************************************** 635162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 636162922Sariff * 637162922Sariff * Allocate all the bus resources necessary to speak with the physical 638162922Sariff * controller. 639162922Sariff ****************************************************************************/ 640162922Sariffstatic int 641162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 642162922Sariff{ 643162922Sariff struct hdac_mem *mem; 644162922Sariff 645162922Sariff mem = &sc->mem; 646162922Sariff mem->mem_rid = PCIR_BAR(0); 647162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 648162922Sariff &mem->mem_rid, RF_ACTIVE); 649162922Sariff if (mem->mem_res == NULL) { 650162922Sariff device_printf(sc->dev, 651162922Sariff "%s: Unable to allocate memory resource\n", __func__); 652162922Sariff return (ENOMEM); 653162922Sariff } 654162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 655162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 656162922Sariff 657162922Sariff return (0); 658162922Sariff} 659162922Sariff 660162922Sariff/**************************************************************************** 661162922Sariff * void hdac_mem_free(struct hdac_softc *) 662162922Sariff * 663162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 664162922Sariff ****************************************************************************/ 665162922Sariffstatic void 666162922Sariffhdac_mem_free(struct hdac_softc *sc) 667162922Sariff{ 668162922Sariff struct hdac_mem *mem; 669162922Sariff 670162922Sariff mem = &sc->mem; 671162922Sariff if (mem->mem_res != NULL) 672162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 673162922Sariff mem->mem_res); 674164614Sariff mem->mem_res = NULL; 675162922Sariff} 676162922Sariff 677162922Sariff/**************************************************************************** 678162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 679162922Sariff * 680162922Sariff * Allocate and setup the resources necessary for interrupt handling. 681162922Sariff ****************************************************************************/ 682162922Sariffstatic int 683162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 684162922Sariff{ 685162922Sariff struct hdac_irq *irq; 686162922Sariff int result; 687162922Sariff 688162922Sariff irq = &sc->irq; 689162922Sariff irq->irq_rid = 0x0; 690171330Sariff 691230130Smav if ((sc->quirks_off & HDAC_QUIRK_MSI) == 0 && 692171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 693171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 694171330Sariff irq->irq_rid = 0x1; 695171330Sariff 696162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 697162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 698162922Sariff if (irq->irq_res == NULL) { 699162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 700162922Sariff __func__); 701167773Sariff goto hdac_irq_alloc_fail; 702162922Sariff } 703182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 704182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 705162922Sariff if (result != 0) { 706162922Sariff device_printf(sc->dev, 707162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 708162922Sariff __func__, result); 709167773Sariff goto hdac_irq_alloc_fail; 710162922Sariff } 711162922Sariff 712162922Sariff return (0); 713162922Sariff 714167773Sariffhdac_irq_alloc_fail: 715164614Sariff hdac_irq_free(sc); 716164614Sariff 717162922Sariff return (ENXIO); 718162922Sariff} 719162922Sariff 720162922Sariff/**************************************************************************** 721162922Sariff * void hdac_irq_free(struct hdac_softc *) 722162922Sariff * 723162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 724162922Sariff ****************************************************************************/ 725162922Sariffstatic void 726162922Sariffhdac_irq_free(struct hdac_softc *sc) 727162922Sariff{ 728162922Sariff struct hdac_irq *irq; 729162922Sariff 730162922Sariff irq = &sc->irq; 731164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 732162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 733162922Sariff if (irq->irq_res != NULL) 734162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 735162922Sariff irq->irq_res); 736188656Smav if (irq->irq_rid == 0x1) 737171330Sariff pci_release_msi(sc->dev); 738164614Sariff irq->irq_handle = NULL; 739164614Sariff irq->irq_res = NULL; 740171330Sariff irq->irq_rid = 0x0; 741162922Sariff} 742162922Sariff 743162922Sariff/**************************************************************************** 744162922Sariff * void hdac_corb_init(struct hdac_softc *) 745162922Sariff * 746162922Sariff * Initialize the corb registers for operations but do not start it up yet. 747162922Sariff * The CORB engine must not be running when this function is called. 748162922Sariff ****************************************************************************/ 749162922Sariffstatic void 750162922Sariffhdac_corb_init(struct hdac_softc *sc) 751162922Sariff{ 752162922Sariff uint8_t corbsize; 753162922Sariff uint64_t corbpaddr; 754162922Sariff 755162922Sariff /* Setup the CORB size. */ 756162922Sariff switch (sc->corb_size) { 757162922Sariff case 256: 758162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 759162922Sariff break; 760162922Sariff case 16: 761162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 762162922Sariff break; 763162922Sariff case 2: 764162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 765162922Sariff break; 766162922Sariff default: 767162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 768162922Sariff } 769162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 770162922Sariff 771162922Sariff /* Setup the CORB Address in the hdac */ 772162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 773162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 774162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 775162922Sariff 776162922Sariff /* Set the WP and RP */ 777162922Sariff sc->corb_wp = 0; 778162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 779162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 780162922Sariff /* 781162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 782162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 783162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 784162922Sariff * manually reset the bit to zero before continuing. 785162922Sariff */ 786162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 787162922Sariff 788162922Sariff /* Enable CORB error reporting */ 789162922Sariff#if 0 790162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 791162922Sariff#endif 792162922Sariff} 793162922Sariff 794162922Sariff/**************************************************************************** 795162922Sariff * void hdac_rirb_init(struct hdac_softc *) 796162922Sariff * 797162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 798162922Sariff * The RIRB engine must not be running when this function is called. 799162922Sariff ****************************************************************************/ 800162922Sariffstatic void 801162922Sariffhdac_rirb_init(struct hdac_softc *sc) 802162922Sariff{ 803162922Sariff uint8_t rirbsize; 804162922Sariff uint64_t rirbpaddr; 805162922Sariff 806162922Sariff /* Setup the RIRB size. */ 807162922Sariff switch (sc->rirb_size) { 808162922Sariff case 256: 809162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 810162922Sariff break; 811162922Sariff case 16: 812162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 813162922Sariff break; 814162922Sariff case 2: 815162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 816162922Sariff break; 817162922Sariff default: 818162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 819162922Sariff } 820162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 821162922Sariff 822162922Sariff /* Setup the RIRB Address in the hdac */ 823162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 824162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 825162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 826162922Sariff 827162922Sariff /* Setup the WP and RP */ 828162922Sariff sc->rirb_rp = 0; 829162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 830162922Sariff 831182999Smav /* Setup the interrupt threshold */ 832182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 833162922Sariff 834182999Smav /* Enable Overrun and response received reporting */ 835162922Sariff#if 0 836182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 837182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 838162922Sariff#else 839182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 840162922Sariff#endif 841162922Sariff 842169277Sariff#if 0 843162922Sariff /* 844162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 845162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 846162922Sariff * should be sufficient to do this only once as the rirb is purely 847162922Sariff * read-only from now on. 848162922Sariff */ 849162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 850162922Sariff BUS_DMASYNC_PREREAD); 851169277Sariff#endif 852162922Sariff} 853162922Sariff 854162922Sariff/**************************************************************************** 855162922Sariff * void hdac_corb_start(hdac_softc *) 856162922Sariff * 857162922Sariff * Startup the corb DMA engine 858162922Sariff ****************************************************************************/ 859162922Sariffstatic void 860162922Sariffhdac_corb_start(struct hdac_softc *sc) 861162922Sariff{ 862162922Sariff uint32_t corbctl; 863162922Sariff 864162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 865162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 866162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 867162922Sariff} 868162922Sariff 869162922Sariff/**************************************************************************** 870162922Sariff * void hdac_rirb_start(hdac_softc *) 871162922Sariff * 872162922Sariff * Startup the rirb DMA engine 873162922Sariff ****************************************************************************/ 874162922Sariffstatic void 875162922Sariffhdac_rirb_start(struct hdac_softc *sc) 876162922Sariff{ 877162922Sariff uint32_t rirbctl; 878162922Sariff 879162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 880162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 881162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 882162922Sariff} 883162922Sariff 884164614Sariffstatic int 885164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 886164614Sariff{ 887164614Sariff struct hdac_rirb *rirb_base, *rirb; 888164614Sariff nid_t cad; 889164614Sariff uint32_t resp; 890164614Sariff uint8_t rirbwp; 891171141Sariff int ret; 892164614Sariff 893164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 894164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 895169277Sariff#if 0 896164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 897164614Sariff BUS_DMASYNC_POSTREAD); 898169277Sariff#endif 899164614Sariff 900171141Sariff ret = 0; 901164614Sariff while (sc->rirb_rp != rirbwp) { 902164614Sariff sc->rirb_rp++; 903164614Sariff sc->rirb_rp %= sc->rirb_size; 904164614Sariff rirb = &rirb_base[sc->rirb_rp]; 905164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 906164614Sariff resp = rirb->response; 907164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 908230130Smav sc->unsolq[sc->unsolq_wp++] = resp; 909164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 910230130Smav sc->unsolq[sc->unsolq_wp++] = cad; 911230130Smav sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 912230130Smav } else if (sc->codecs[cad].pending <= 0) { 913230130Smav device_printf(sc->dev, "Unexpected unsolicited " 914230130Smav "response from address %d: %08x\n", cad, resp); 915230130Smav } else { 916230130Smav sc->codecs[cad].response = resp; 917230130Smav sc->codecs[cad].pending--; 918230130Smav } 919164614Sariff ret++; 920164614Sariff } 921164614Sariff return (ret); 922164614Sariff} 923164614Sariff 924164614Sariffstatic int 925164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 926164614Sariff{ 927230130Smav device_t child; 928164614Sariff nid_t cad; 929230130Smav uint32_t resp; 930164614Sariff int ret = 0; 931164614Sariff 932164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 933164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 934164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 935230130Smav resp = sc->unsolq[sc->unsolq_rp++]; 936164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 937230130Smav cad = sc->unsolq[sc->unsolq_rp++]; 938230130Smav sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 939230130Smav if ((child = sc->codecs[cad].dev) != NULL) 940230130Smav HDAC_UNSOL_INTR(child, resp); 941164614Sariff ret++; 942164614Sariff } 943164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 944164614Sariff } 945164614Sariff 946164614Sariff return (ret); 947164614Sariff} 948164614Sariff 949162922Sariff/**************************************************************************** 950162922Sariff * uint32_t hdac_command_sendone_internal 951162922Sariff * 952162922Sariff * Wrapper function that sends only one command to a given codec 953162922Sariff ****************************************************************************/ 954162922Sariffstatic uint32_t 955230130Smavhdac_send_command(struct hdac_softc *sc, nid_t cad, uint32_t verb) 956162922Sariff{ 957230130Smav int timeout; 958230130Smav uint32_t *corb; 959162922Sariff 960163057Sariff if (!hdac_lockowned(sc)) 961162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 962230130Smav verb &= ~HDA_CMD_CAD_MASK; 963230130Smav verb |= ((uint32_t)cad) << HDA_CMD_CAD_SHIFT; 964230130Smav sc->codecs[cad].response = HDA_INVALID; 965162922Sariff 966230130Smav sc->codecs[cad].pending++; 967230130Smav sc->corb_wp++; 968230130Smav sc->corb_wp %= sc->corb_size; 969162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 970169277Sariff#if 0 971230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 972230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 973169277Sariff#endif 974230130Smav corb[sc->corb_wp] = verb; 975169277Sariff#if 0 976230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 977230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 978169277Sariff#endif 979230130Smav HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 980162922Sariff 981230130Smav timeout = 10000; 982230130Smav do { 983230130Smav if (hdac_rirb_flush(sc) == 0) 984162922Sariff DELAY(10); 985230130Smav } while (sc->codecs[cad].pending != 0 && --timeout); 986162922Sariff 987230130Smav if (sc->codecs[cad].pending != 0) { 988230130Smav device_printf(sc->dev, "Command timeout on address %d\n", cad); 989230130Smav sc->codecs[cad].pending = 0; 990230130Smav } 991162922Sariff 992230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 993230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 994230130Smav return (sc->codecs[cad].response); 995162922Sariff} 996162922Sariff 997162922Sariff/**************************************************************************** 998162922Sariff * Device Methods 999162922Sariff ****************************************************************************/ 1000162922Sariff 1001162922Sariff/**************************************************************************** 1002162922Sariff * int hdac_probe(device_t) 1003162922Sariff * 1004162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 1005162922Sariff * match using the subclass of the device. 1006162922Sariff ****************************************************************************/ 1007162922Sariffstatic int 1008162922Sariffhdac_probe(device_t dev) 1009162922Sariff{ 1010162922Sariff int i, result; 1011163257Sariff uint32_t model; 1012163257Sariff uint16_t class, subclass; 1013162922Sariff char desc[64]; 1014162922Sariff 1015162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 1016162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1017162922Sariff class = pci_get_class(dev); 1018162922Sariff subclass = pci_get_subclass(dev); 1019162922Sariff 1020162922Sariff bzero(desc, sizeof(desc)); 1021162922Sariff result = ENXIO; 1022264832Smarius for (i = 0; i < nitems(hdac_devices); i++) { 1023162922Sariff if (hdac_devices[i].model == model) { 1024230331Smav strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1025230331Smav result = BUS_PROBE_DEFAULT; 1026162922Sariff break; 1027162922Sariff } 1028163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1029162922Sariff class == PCIC_MULTIMEDIA && 1030162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1031230331Smav snprintf(desc, sizeof(desc), 1032230331Smav "%s (0x%04x)", 1033230331Smav hdac_devices[i].desc, pci_get_device(dev)); 1034230331Smav result = BUS_PROBE_GENERIC; 1035162922Sariff break; 1036162922Sariff } 1037162922Sariff } 1038162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 1039162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1040230331Smav snprintf(desc, sizeof(desc), "Generic (0x%08x)", model); 1041230331Smav result = BUS_PROBE_GENERIC; 1042162922Sariff } 1043162922Sariff if (result != ENXIO) { 1044230331Smav strlcat(desc, " HDA Controller", sizeof(desc)); 1045162922Sariff device_set_desc_copy(dev, desc); 1046162922Sariff } 1047162922Sariff 1048162922Sariff return (result); 1049162922Sariff} 1050162922Sariff 1051162922Sariffstatic void 1052171141Sariffhdac_unsolq_task(void *context, int pending) 1053171141Sariff{ 1054171141Sariff struct hdac_softc *sc; 1055171141Sariff 1056171141Sariff sc = (struct hdac_softc *)context; 1057171141Sariff 1058171141Sariff hdac_lock(sc); 1059171141Sariff hdac_unsolq_flush(sc); 1060171141Sariff hdac_unlock(sc); 1061171141Sariff} 1062171141Sariff 1063162922Sariff/**************************************************************************** 1064162922Sariff * int hdac_attach(device_t) 1065162922Sariff * 1066162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 1067162922Sariff * when this function is called. Setup everything that doesn't require 1068162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 1069162922Sariff ****************************************************************************/ 1070162922Sariffstatic int 1071162922Sariffhdac_attach(device_t dev) 1072162922Sariff{ 1073162922Sariff struct hdac_softc *sc; 1074162922Sariff int result; 1075189086Smav int i, devid = -1; 1076189086Smav uint32_t model; 1077189086Smav uint16_t class, subclass; 1078169277Sariff uint16_t vendor; 1079169277Sariff uint8_t v; 1080162922Sariff 1081230130Smav sc = device_get_softc(dev); 1082223118Sjoel HDA_BOOTVERBOSE( 1083242352Smav device_printf(dev, "PCI card vendor: 0x%04x, device: 0x%04x\n", 1084242352Smav pci_get_subvendor(dev), pci_get_subdevice(dev)); 1085223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 1086223118Sjoel HDA_DRV_TEST_REV); 1087223118Sjoel ); 1088182999Smav 1089189086Smav model = (uint32_t)pci_get_device(dev) << 16; 1090189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1091189086Smav class = pci_get_class(dev); 1092189086Smav subclass = pci_get_subclass(dev); 1093189086Smav 1094264832Smarius for (i = 0; i < nitems(hdac_devices); i++) { 1095189086Smav if (hdac_devices[i].model == model) { 1096189086Smav devid = i; 1097189086Smav break; 1098189086Smav } 1099189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1100189086Smav class == PCIC_MULTIMEDIA && 1101189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 1102189086Smav devid = i; 1103189086Smav break; 1104189086Smav } 1105189086Smav } 1106189086Smav 1107230130Smav sc->lock = snd_mtxcreate(device_get_nameunit(dev), "HDA driver mutex"); 1108162922Sariff sc->dev = dev; 1109230130Smav TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 1110230130Smav callout_init(&sc->poll_callout, CALLOUT_MPSAFE); 1111230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) 1112230130Smav sc->codecs[i].dev = NULL; 1113230130Smav if (devid >= 0) { 1114230130Smav sc->quirks_on = hdac_devices[devid].quirks_on; 1115230130Smav sc->quirks_off = hdac_devices[devid].quirks_off; 1116230130Smav } else { 1117230130Smav sc->quirks_on = 0; 1118230130Smav sc->quirks_off = 0; 1119165281Sariff } 1120169277Sariff if (resource_int_value(device_get_name(dev), 1121230130Smav device_get_unit(dev), "msi", &i) == 0) { 1122230130Smav if (i == 0) 1123230130Smav sc->quirks_off |= HDAC_QUIRK_MSI; 1124230130Smav else { 1125230130Smav sc->quirks_on |= HDAC_QUIRK_MSI; 1126230130Smav sc->quirks_off |= ~HDAC_QUIRK_MSI; 1127230130Smav } 1128230130Smav } 1129230130Smav hdac_config_fetch(sc, &sc->quirks_on, &sc->quirks_off); 1130230130Smav HDA_BOOTVERBOSE( 1131230130Smav device_printf(sc->dev, 1132230130Smav "Config options: on=0x%08x off=0x%08x\n", 1133230130Smav sc->quirks_on, sc->quirks_off); 1134230130Smav ); 1135230130Smav sc->poll_ival = hz; 1136230130Smav if (resource_int_value(device_get_name(dev), 1137169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 1138164614Sariff sc->polling = 1; 1139164614Sariff else 1140164614Sariff sc->polling = 0; 1141164614Sariff 1142162922Sariff pci_enable_busmaster(dev); 1143162922Sariff 1144230130Smav vendor = pci_get_vendor(dev); 1145169277Sariff if (vendor == INTEL_VENDORID) { 1146169277Sariff /* TCSEL -> TC0 */ 1147169277Sariff v = pci_read_config(dev, 0x44, 1); 1148169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 1149183097Smav HDA_BOOTHVERBOSE( 1150169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 1151169277Sariff pci_read_config(dev, 0x44, 1)); 1152169277Sariff ); 1153169277Sariff } 1154169277Sariff 1155169277Sariff#if defined(__i386__) || defined(__amd64__) 1156171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1157169277Sariff 1158169277Sariff if (resource_int_value(device_get_name(dev), 1159169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 1160169277Sariff#else 1161171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1162169277Sariff#endif 1163169277Sariff /* 1164169277Sariff * Try to enable PCIe snoop to avoid messing around with 1165169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 1166169277Sariff * config is pretty much vendor specific, there are no 1167169277Sariff * general solutions on how to enable it, forcing us (even 1168169277Sariff * Microsoft) to enable uncacheable or write combined DMA 1169169277Sariff * by default. 1170169277Sariff * 1171169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 1172169277Sariff */ 1173264832Smarius for (i = 0; i < nitems(hdac_pcie_snoop); i++) { 1174169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 1175169277Sariff continue; 1176171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1177169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 1178169277Sariff break; 1179169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1180169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 1181169277Sariff hdac_pcie_snoop[i].enable) 1182169277Sariff break; 1183169277Sariff v &= hdac_pcie_snoop[i].mask; 1184169277Sariff v |= hdac_pcie_snoop[i].enable; 1185169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 1186169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1187169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 1188169277Sariff hdac_pcie_snoop[i].enable) { 1189169277Sariff HDA_BOOTVERBOSE( 1190169277Sariff device_printf(dev, 1191169277Sariff "WARNING: Failed to enable PCIe " 1192169277Sariff "snoop!\n"); 1193169277Sariff ); 1194169277Sariff#if defined(__i386__) || defined(__amd64__) 1195171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1196169277Sariff#endif 1197169277Sariff } 1198169277Sariff break; 1199169277Sariff } 1200169277Sariff#if defined(__i386__) || defined(__amd64__) 1201169277Sariff } 1202169277Sariff#endif 1203169277Sariff 1204183097Smav HDA_BOOTHVERBOSE( 1205169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 1206171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 1207171330Sariff "Uncacheable" : "PCIe snoop", vendor); 1208169277Sariff ); 1209169277Sariff 1210162922Sariff /* Allocate resources */ 1211162922Sariff result = hdac_mem_alloc(sc); 1212162922Sariff if (result != 0) 1213163057Sariff goto hdac_attach_fail; 1214162922Sariff result = hdac_irq_alloc(sc); 1215162922Sariff if (result != 0) 1216163057Sariff goto hdac_attach_fail; 1217162922Sariff 1218162922Sariff /* Get Capabilities */ 1219162922Sariff result = hdac_get_capabilities(sc); 1220162922Sariff if (result != 0) 1221163057Sariff goto hdac_attach_fail; 1222162922Sariff 1223230130Smav /* Allocate CORB, RIRB, POS and BDLs dma memory */ 1224162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 1225162922Sariff sc->corb_size * sizeof(uint32_t)); 1226162922Sariff if (result != 0) 1227163057Sariff goto hdac_attach_fail; 1228162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 1229162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 1230162922Sariff if (result != 0) 1231163057Sariff goto hdac_attach_fail; 1232230130Smav sc->streams = malloc(sizeof(struct hdac_stream) * sc->num_ss, 1233230130Smav M_HDAC, M_ZERO | M_WAITOK); 1234230130Smav for (i = 0; i < sc->num_ss; i++) { 1235230130Smav result = hdac_dma_alloc(sc, &sc->streams[i].bdl, 1236230130Smav sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1237230130Smav if (result != 0) 1238230130Smav goto hdac_attach_fail; 1239230130Smav } 1240230130Smav if (sc->quirks_on & HDAC_QUIRK_DMAPOS) { 1241230130Smav if (hdac_dma_alloc(sc, &sc->pos_dma, (sc->num_ss) * 8) != 0) { 1242230130Smav HDA_BOOTVERBOSE( 1243230130Smav device_printf(dev, "Failed to " 1244230130Smav "allocate DMA pos buffer " 1245230130Smav "(non-fatal)\n"); 1246230130Smav ); 1247230130Smav } else { 1248230130Smav uint64_t addr = sc->pos_dma.dma_paddr; 1249162922Sariff 1250230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, addr >> 32); 1251230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 1252230130Smav (addr & HDAC_DPLBASE_DPLBASE_MASK) | 1253230130Smav HDAC_DPLBASE_DPLBASE_DMAPBE); 1254230130Smav } 1255230130Smav } 1256230130Smav 1257194861Smav result = bus_dma_tag_create( 1258194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1259230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 1260194861Smav 0, /* boundary */ 1261194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1262194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1263194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 1264194861Smav NULL, /* filtfunc */ 1265194861Smav NULL, /* fistfuncarg */ 1266194861Smav HDA_BUFSZ_MAX, /* maxsize */ 1267194861Smav 1, /* nsegments */ 1268194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 1269194861Smav 0, /* flags */ 1270194861Smav NULL, /* lockfunc */ 1271194861Smav NULL, /* lockfuncarg */ 1272194861Smav &sc->chan_dmat); /* dmat */ 1273194861Smav if (result != 0) { 1274194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 1275194861Smav __func__, result); 1276194861Smav goto hdac_attach_fail; 1277194861Smav } 1278194861Smav 1279162922Sariff /* Quiesce everything */ 1280183097Smav HDA_BOOTHVERBOSE( 1281182999Smav device_printf(dev, "Reset controller...\n"); 1282182999Smav ); 1283182999Smav hdac_reset(sc, 1); 1284162922Sariff 1285162922Sariff /* Initialize the CORB and RIRB */ 1286162922Sariff hdac_corb_init(sc); 1287162922Sariff hdac_rirb_init(sc); 1288162922Sariff 1289162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 1290162922Sariff sc->intrhook.ich_func = hdac_attach2; 1291162922Sariff sc->intrhook.ich_arg = (void *)sc; 1292162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 1293162922Sariff sc->intrhook.ich_func = NULL; 1294162922Sariff hdac_attach2((void *)sc); 1295162922Sariff } 1296162922Sariff 1297163057Sariff return (0); 1298162922Sariff 1299163057Sariffhdac_attach_fail: 1300162922Sariff hdac_irq_free(sc); 1301230130Smav for (i = 0; i < sc->num_ss; i++) 1302230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1303230130Smav free(sc->streams, M_HDAC); 1304169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 1305169277Sariff hdac_dma_free(sc, &sc->corb_dma); 1306162922Sariff hdac_mem_free(sc); 1307162922Sariff snd_mtxfree(sc->lock); 1308162922Sariff 1309163057Sariff return (ENXIO); 1310162922Sariff} 1311162922Sariff 1312230130Smavstatic int 1313230130Smavsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 1314162922Sariff{ 1315230130Smav struct hdac_softc *sc; 1316230130Smav device_t *devlist; 1317230130Smav device_t dev; 1318230130Smav int devcount, i, err, val; 1319162922Sariff 1320230130Smav dev = oidp->oid_arg1; 1321230130Smav sc = device_get_softc(dev); 1322230130Smav if (sc == NULL) 1323230130Smav return (EINVAL); 1324230130Smav val = 0; 1325230130Smav err = sysctl_handle_int(oidp, &val, 0, req); 1326230130Smav if (err != 0 || req->newptr == NULL || val == 0) 1327230130Smav return (err); 1328162922Sariff 1329230130Smav /* XXX: Temporary. For debugging. */ 1330230130Smav if (val == 100) { 1331230130Smav hdac_suspend(dev); 1332182999Smav return (0); 1333230130Smav } else if (val == 101) { 1334230130Smav hdac_resume(dev); 1335182999Smav return (0); 1336182999Smav } 1337162922Sariff 1338230130Smav if ((err = device_get_children(dev, &devlist, &devcount)) != 0) 1339230130Smav return (err); 1340230130Smav hdac_lock(sc); 1341230130Smav for (i = 0; i < devcount; i++) 1342230130Smav HDAC_PINDUMP(devlist[i]); 1343230130Smav hdac_unlock(sc); 1344230130Smav free(devlist, M_TEMP); 1345182999Smav return (0); 1346162922Sariff} 1347162922Sariff 1348183097Smavstatic int 1349230326Smavhdac_mdata_rate(uint16_t fmt) 1350162922Sariff{ 1351230326Smav static const int mbits[8] = { 8, 16, 32, 32, 32, 32, 32, 32 }; 1352230326Smav int rate, bits; 1353162922Sariff 1354230130Smav if (fmt & (1 << 14)) 1355230130Smav rate = 44100; 1356230130Smav else 1357230130Smav rate = 48000; 1358230130Smav rate *= ((fmt >> 11) & 0x07) + 1; 1359230130Smav rate /= ((fmt >> 8) & 0x07) + 1; 1360230326Smav bits = mbits[(fmt >> 4) & 0x03]; 1361230326Smav bits *= (fmt & 0x0f) + 1; 1362230326Smav return (rate * bits); 1363182999Smav} 1364182999Smav 1365230326Smavstatic int 1366230326Smavhdac_bdata_rate(uint16_t fmt, int output) 1367230326Smav{ 1368230326Smav static const int bbits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 }; 1369230326Smav int rate, bits; 1370230326Smav 1371230326Smav rate = 48000; 1372230326Smav rate *= ((fmt >> 11) & 0x07) + 1; 1373230326Smav bits = bbits[(fmt >> 4) & 0x03]; 1374230326Smav bits *= (fmt & 0x0f) + 1; 1375230326Smav if (!output) 1376230326Smav bits = ((bits + 7) & ~0x07) + 10; 1377230326Smav return (rate * bits); 1378230326Smav} 1379230326Smav 1380182999Smavstatic void 1381230130Smavhdac_poll_reinit(struct hdac_softc *sc) 1382182999Smav{ 1383230130Smav int i, pollticks, min = 1000000; 1384230130Smav struct hdac_stream *s; 1385182999Smav 1386230130Smav if (sc->polling == 0) 1387230130Smav return; 1388230130Smav if (sc->unsol_registered > 0) 1389230130Smav min = hz / 2; 1390230130Smav for (i = 0; i < sc->num_ss; i++) { 1391230130Smav s = &sc->streams[i]; 1392230130Smav if (s->running == 0) 1393182999Smav continue; 1394230130Smav pollticks = ((uint64_t)hz * s->blksz) / 1395230326Smav (hdac_mdata_rate(s->format) / 8); 1396230130Smav pollticks >>= 1; 1397230130Smav if (pollticks > hz) 1398230130Smav pollticks = hz; 1399230130Smav if (pollticks < 1) { 1400182999Smav HDA_BOOTVERBOSE( 1401230130Smav device_printf(sc->dev, 1402230130Smav "poll interval < 1 tick !\n"); 1403182999Smav ); 1404230130Smav pollticks = 1; 1405162922Sariff } 1406230130Smav if (min > pollticks) 1407230130Smav min = pollticks; 1408162922Sariff } 1409202789Smav HDA_BOOTVERBOSE( 1410230130Smav device_printf(sc->dev, 1411230130Smav "poll interval %d -> %d ticks\n", 1412230130Smav sc->poll_ival, min); 1413202789Smav ); 1414230130Smav sc->poll_ival = min; 1415230130Smav if (min == 1000000) 1416230130Smav callout_stop(&sc->poll_callout); 1417182999Smav else 1418230130Smav callout_reset(&sc->poll_callout, 1, hdac_poll_callback, sc); 1419163057Sariff} 1420163057Sariff 1421164614Sariffstatic int 1422164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 1423164614Sariff{ 1424164614Sariff struct hdac_softc *sc; 1425164614Sariff device_t dev; 1426164614Sariff uint32_t ctl; 1427164614Sariff int err, val; 1428164614Sariff 1429164614Sariff dev = oidp->oid_arg1; 1430182999Smav sc = device_get_softc(dev); 1431182999Smav if (sc == NULL) 1432164614Sariff return (EINVAL); 1433164614Sariff hdac_lock(sc); 1434164614Sariff val = sc->polling; 1435164614Sariff hdac_unlock(sc); 1436170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 1437164614Sariff 1438169277Sariff if (err != 0 || req->newptr == NULL) 1439164614Sariff return (err); 1440164614Sariff if (val < 0 || val > 1) 1441164614Sariff return (EINVAL); 1442164614Sariff 1443164614Sariff hdac_lock(sc); 1444164614Sariff if (val != sc->polling) { 1445182999Smav if (val == 0) { 1446230130Smav callout_stop(&sc->poll_callout); 1447169277Sariff hdac_unlock(sc); 1448230130Smav callout_drain(&sc->poll_callout); 1449169277Sariff hdac_lock(sc); 1450164614Sariff sc->polling = 0; 1451182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1452182999Smav ctl |= HDAC_INTCTL_GIE; 1453182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1454164614Sariff } else { 1455182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1456182999Smav ctl &= ~HDAC_INTCTL_GIE; 1457182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1458164614Sariff sc->polling = 1; 1459182999Smav hdac_poll_reinit(sc); 1460164614Sariff } 1461164614Sariff } 1462164614Sariff hdac_unlock(sc); 1463164614Sariff 1464164614Sariff return (err); 1465164614Sariff} 1466169277Sariff 1467163057Sariffstatic void 1468162922Sariffhdac_attach2(void *arg) 1469162922Sariff{ 1470162922Sariff struct hdac_softc *sc; 1471230130Smav device_t child; 1472230130Smav uint32_t vendorid, revisionid; 1473230130Smav int i; 1474230130Smav uint16_t statests; 1475162922Sariff 1476162922Sariff sc = (struct hdac_softc *)arg; 1477162922Sariff 1478162922Sariff hdac_lock(sc); 1479162922Sariff 1480162922Sariff /* Remove ourselves from the config hooks */ 1481162922Sariff if (sc->intrhook.ich_func != NULL) { 1482162922Sariff config_intrhook_disestablish(&sc->intrhook); 1483162922Sariff sc->intrhook.ich_func = NULL; 1484162922Sariff } 1485162922Sariff 1486183097Smav HDA_BOOTHVERBOSE( 1487182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 1488162922Sariff ); 1489162922Sariff hdac_corb_start(sc); 1490183097Smav HDA_BOOTHVERBOSE( 1491182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 1492162922Sariff ); 1493162922Sariff hdac_rirb_start(sc); 1494183097Smav HDA_BOOTHVERBOSE( 1495162922Sariff device_printf(sc->dev, 1496182999Smav "Enabling controller interrupt...\n"); 1497162922Sariff ); 1498182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1499182999Smav HDAC_GCTL_UNSOL); 1500182999Smav if (sc->polling == 0) { 1501164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 1502164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1503182999Smav } 1504162922Sariff DELAY(1000); 1505162922Sariff 1506183097Smav HDA_BOOTHVERBOSE( 1507230130Smav device_printf(sc->dev, "Scanning HDA codecs ...\n"); 1508162922Sariff ); 1509230130Smav statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1510230130Smav hdac_unlock(sc); 1511230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1512230130Smav if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1513230130Smav HDA_BOOTHVERBOSE( 1514183097Smav device_printf(sc->dev, 1515230130Smav "Found CODEC at address %d\n", i); 1516183019Smav ); 1517230130Smav hdac_lock(sc); 1518230130Smav vendorid = hdac_send_command(sc, i, 1519230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_VENDOR_ID)); 1520230130Smav revisionid = hdac_send_command(sc, i, 1521230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_REVISION_ID)); 1522230130Smav hdac_unlock(sc); 1523230130Smav if (vendorid == HDA_INVALID && 1524230130Smav revisionid == HDA_INVALID) { 1525230130Smav device_printf(sc->dev, 1526230130Smav "CODEC is not responding!\n"); 1527182999Smav continue; 1528182999Smav } 1529230130Smav sc->codecs[i].vendor_id = 1530230130Smav HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1531230130Smav sc->codecs[i].device_id = 1532230130Smav HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1533230130Smav sc->codecs[i].revision_id = 1534230130Smav HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1535230130Smav sc->codecs[i].stepping_id = 1536230130Smav HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1537230130Smav child = device_add_child(sc->dev, "hdacc", -1); 1538230130Smav if (child == NULL) { 1539230130Smav device_printf(sc->dev, 1540230130Smav "Failed to add CODEC device\n"); 1541230130Smav continue; 1542182999Smav } 1543230130Smav device_set_ivars(child, (void *)(intptr_t)i); 1544230130Smav sc->codecs[i].dev = child; 1545182999Smav } 1546162922Sariff } 1547182999Smav bus_generic_attach(sc->dev); 1548182999Smav 1549182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1550182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1551230130Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1552230130Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 1553230130Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1554230130Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1555182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1556182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 1557182999Smav} 1558182999Smav 1559182999Smav/**************************************************************************** 1560182999Smav * int hdac_suspend(device_t) 1561182999Smav * 1562182999Smav * Suspend and power down HDA bus and codecs. 1563182999Smav ****************************************************************************/ 1564182999Smavstatic int 1565182999Smavhdac_suspend(device_t dev) 1566182999Smav{ 1567230130Smav struct hdac_softc *sc = device_get_softc(dev); 1568182999Smav 1569183097Smav HDA_BOOTHVERBOSE( 1570182999Smav device_printf(dev, "Suspend...\n"); 1571162922Sariff ); 1572230130Smav bus_generic_suspend(dev); 1573182999Smav 1574182999Smav hdac_lock(sc); 1575183097Smav HDA_BOOTHVERBOSE( 1576182999Smav device_printf(dev, "Reset controller...\n"); 1577162922Sariff ); 1578233606Smav callout_stop(&sc->poll_callout); 1579182999Smav hdac_reset(sc, 0); 1580182999Smav hdac_unlock(sc); 1581233606Smav callout_drain(&sc->poll_callout); 1582182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1583183097Smav HDA_BOOTHVERBOSE( 1584182999Smav device_printf(dev, "Suspend done\n"); 1585162922Sariff ); 1586182999Smav return (0); 1587182999Smav} 1588182999Smav 1589182999Smav/**************************************************************************** 1590182999Smav * int hdac_resume(device_t) 1591182999Smav * 1592182999Smav * Powerup and restore HDA bus and codecs state. 1593182999Smav ****************************************************************************/ 1594182999Smavstatic int 1595182999Smavhdac_resume(device_t dev) 1596182999Smav{ 1597230130Smav struct hdac_softc *sc = device_get_softc(dev); 1598230130Smav int error; 1599182999Smav 1600183097Smav HDA_BOOTHVERBOSE( 1601182999Smav device_printf(dev, "Resume...\n"); 1602162922Sariff ); 1603182999Smav hdac_lock(sc); 1604182999Smav 1605182999Smav /* Quiesce everything */ 1606183097Smav HDA_BOOTHVERBOSE( 1607182999Smav device_printf(dev, "Reset controller...\n"); 1608162922Sariff ); 1609182999Smav hdac_reset(sc, 1); 1610182999Smav 1611182999Smav /* Initialize the CORB and RIRB */ 1612182999Smav hdac_corb_init(sc); 1613182999Smav hdac_rirb_init(sc); 1614182999Smav 1615183097Smav HDA_BOOTHVERBOSE( 1616182999Smav device_printf(dev, "Starting CORB Engine...\n"); 1617162922Sariff ); 1618182999Smav hdac_corb_start(sc); 1619183097Smav HDA_BOOTHVERBOSE( 1620182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 1621162922Sariff ); 1622182999Smav hdac_rirb_start(sc); 1623183097Smav HDA_BOOTHVERBOSE( 1624230130Smav device_printf(dev, "Enabling controller interrupt...\n"); 1625162922Sariff ); 1626182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1627182999Smav HDAC_GCTL_UNSOL); 1628230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1629182999Smav DELAY(1000); 1630233606Smav hdac_poll_reinit(sc); 1631182999Smav hdac_unlock(sc); 1632182999Smav 1633230130Smav error = bus_generic_resume(dev); 1634183097Smav HDA_BOOTHVERBOSE( 1635182999Smav device_printf(dev, "Resume done\n"); 1636162922Sariff ); 1637230130Smav return (error); 1638230130Smav} 1639164614Sariff 1640162922Sariff/**************************************************************************** 1641162922Sariff * int hdac_detach(device_t) 1642162922Sariff * 1643162922Sariff * Detach and free up resources utilized by the hdac device. 1644162922Sariff ****************************************************************************/ 1645162922Sariffstatic int 1646162922Sariffhdac_detach(device_t dev) 1647162922Sariff{ 1648230130Smav struct hdac_softc *sc = device_get_softc(dev); 1649185177Smav device_t *devlist; 1650230130Smav int cad, i, devcount, error; 1651162922Sariff 1652185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 1653185177Smav return (error); 1654185177Smav for (i = 0; i < devcount; i++) { 1655230130Smav cad = (intptr_t)device_get_ivars(devlist[i]); 1656185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 1657185178Smav free(devlist, M_TEMP); 1658185178Smav return (error); 1659185178Smav } 1660230130Smav sc->codecs[cad].dev = NULL; 1661185177Smav } 1662185177Smav free(devlist, M_TEMP); 1663185177Smav 1664230130Smav hdac_lock(sc); 1665230130Smav hdac_reset(sc, 0); 1666230130Smav hdac_unlock(sc); 1667230130Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1668230130Smav hdac_irq_free(sc); 1669162922Sariff 1670230130Smav for (i = 0; i < sc->num_ss; i++) 1671230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1672230130Smav free(sc->streams, M_HDAC); 1673230130Smav hdac_dma_free(sc, &sc->pos_dma); 1674230130Smav hdac_dma_free(sc, &sc->rirb_dma); 1675230130Smav hdac_dma_free(sc, &sc->corb_dma); 1676230130Smav if (sc->chan_dmat != NULL) { 1677230130Smav bus_dma_tag_destroy(sc->chan_dmat); 1678230130Smav sc->chan_dmat = NULL; 1679230130Smav } 1680230130Smav hdac_mem_free(sc); 1681230130Smav snd_mtxfree(sc->lock); 1682162922Sariff return (0); 1683162922Sariff} 1684162922Sariff 1685230130Smavstatic bus_dma_tag_t 1686230130Smavhdac_get_dma_tag(device_t dev, device_t child) 1687230130Smav{ 1688230130Smav struct hdac_softc *sc = device_get_softc(dev); 1689230130Smav 1690230130Smav return (sc->chan_dmat); 1691230130Smav} 1692230130Smav 1693184095Smavstatic int 1694184095Smavhdac_print_child(device_t dev, device_t child) 1695184095Smav{ 1696184095Smav int retval; 1697184095Smav 1698184095Smav retval = bus_print_child_header(dev, child); 1699230130Smav retval += printf(" at cad %d", 1700230130Smav (int)(intptr_t)device_get_ivars(child)); 1701184095Smav retval += bus_print_child_footer(dev, child); 1702184095Smav 1703184095Smav return (retval); 1704184095Smav} 1705184095Smav 1706230130Smavstatic int 1707230130Smavhdac_child_location_str(device_t dev, device_t child, char *buf, 1708230130Smav size_t buflen) 1709230130Smav{ 1710162922Sariff 1711230130Smav snprintf(buf, buflen, "cad=%d", 1712230130Smav (int)(intptr_t)device_get_ivars(child)); 1713230130Smav return (0); 1714230130Smav} 1715162922Sariff 1716230130Smavstatic int 1717230130Smavhdac_child_pnpinfo_str_method(device_t dev, device_t child, char *buf, 1718230130Smav size_t buflen) 1719230130Smav{ 1720230130Smav struct hdac_softc *sc = device_get_softc(dev); 1721230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1722182999Smav 1723230130Smav snprintf(buf, buflen, "vendor=0x%04x device=0x%04x revision=0x%02x " 1724230130Smav "stepping=0x%02x", 1725230130Smav sc->codecs[cad].vendor_id, sc->codecs[cad].device_id, 1726230130Smav sc->codecs[cad].revision_id, sc->codecs[cad].stepping_id); 1727230130Smav return (0); 1728230130Smav} 1729182999Smav 1730182999Smavstatic int 1731230130Smavhdac_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1732182999Smav{ 1733230130Smav struct hdac_softc *sc = device_get_softc(dev); 1734230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1735182999Smav 1736230130Smav switch (which) { 1737230130Smav case HDA_IVAR_CODEC_ID: 1738230130Smav *result = cad; 1739230130Smav break; 1740230130Smav case HDA_IVAR_VENDOR_ID: 1741230130Smav *result = sc->codecs[cad].vendor_id; 1742230130Smav break; 1743230130Smav case HDA_IVAR_DEVICE_ID: 1744230130Smav *result = sc->codecs[cad].device_id; 1745230130Smav break; 1746230130Smav case HDA_IVAR_REVISION_ID: 1747230130Smav *result = sc->codecs[cad].revision_id; 1748230130Smav break; 1749230130Smav case HDA_IVAR_STEPPING_ID: 1750230130Smav *result = sc->codecs[cad].stepping_id; 1751230130Smav break; 1752230130Smav case HDA_IVAR_SUBVENDOR_ID: 1753230130Smav *result = pci_get_subvendor(dev); 1754230130Smav break; 1755230130Smav case HDA_IVAR_SUBDEVICE_ID: 1756230130Smav *result = pci_get_subdevice(dev); 1757230130Smav break; 1758230130Smav case HDA_IVAR_DMA_NOCACHE: 1759230130Smav *result = (sc->flags & HDAC_F_DMA_NOCACHE) != 0; 1760230130Smav break; 1761230130Smav default: 1762230130Smav return (ENOENT); 1763230130Smav } 1764182999Smav return (0); 1765182999Smav} 1766182999Smav 1767230130Smavstatic struct mtx * 1768230130Smavhdac_get_mtx(device_t dev, device_t child) 1769182999Smav{ 1770230130Smav struct hdac_softc *sc = device_get_softc(dev); 1771182999Smav 1772230130Smav return (sc->lock); 1773230130Smav} 1774182999Smav 1775230130Smavstatic uint32_t 1776230130Smavhdac_codec_command(device_t dev, device_t child, uint32_t verb) 1777230130Smav{ 1778182999Smav 1779230130Smav return (hdac_send_command(device_get_softc(dev), 1780230130Smav (intptr_t)device_get_ivars(child), verb)); 1781230130Smav} 1782182999Smav 1783230130Smavstatic int 1784230130Smavhdac_find_stream(struct hdac_softc *sc, int dir, int stream) 1785230130Smav{ 1786230130Smav int i, ss; 1787182999Smav 1788230130Smav ss = -1; 1789230130Smav /* Allocate ISS/BSS first. */ 1790230130Smav if (dir == 0) { 1791230130Smav for (i = 0; i < sc->num_iss; i++) { 1792230130Smav if (sc->streams[i].stream == stream) { 1793230130Smav ss = i; 1794230130Smav break; 1795230130Smav } 1796230130Smav } 1797230130Smav } else { 1798230130Smav for (i = 0; i < sc->num_oss; i++) { 1799230130Smav if (sc->streams[i + sc->num_iss].stream == stream) { 1800230130Smav ss = i + sc->num_iss; 1801230130Smav break; 1802230130Smav } 1803230130Smav } 1804230130Smav } 1805230130Smav /* Fallback to BSS. */ 1806230130Smav if (ss == -1) { 1807230130Smav for (i = 0; i < sc->num_bss; i++) { 1808230130Smav if (sc->streams[i + sc->num_iss + sc->num_oss].stream 1809230130Smav == stream) { 1810230130Smav ss = i + sc->num_iss + sc->num_oss; 1811230130Smav break; 1812230130Smav } 1813230130Smav } 1814230130Smav } 1815230130Smav return (ss); 1816230130Smav} 1817182999Smav 1818230130Smavstatic int 1819230326Smavhdac_stream_alloc(device_t dev, device_t child, int dir, int format, int stripe, 1820230130Smav uint32_t **dmapos) 1821230130Smav{ 1822230130Smav struct hdac_softc *sc = device_get_softc(dev); 1823230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1824230326Smav int stream, ss, bw, maxbw, prevbw; 1825182999Smav 1826230130Smav /* Look for empty stream. */ 1827230130Smav ss = hdac_find_stream(sc, dir, 0); 1828182999Smav 1829230130Smav /* Return if found nothing. */ 1830230130Smav if (ss < 0) 1831230130Smav return (0); 1832182999Smav 1833230326Smav /* Check bus bandwidth. */ 1834230326Smav bw = hdac_bdata_rate(format, dir); 1835230326Smav if (dir == 1) { 1836230326Smav bw *= 1 << (sc->num_sdo - stripe); 1837230326Smav prevbw = sc->sdo_bw_used; 1838230326Smav maxbw = 48000 * 960 * (1 << sc->num_sdo); 1839230326Smav } else { 1840230326Smav prevbw = sc->codecs[cad].sdi_bw_used; 1841230326Smav maxbw = 48000 * 464; 1842230326Smav } 1843230326Smav HDA_BOOTHVERBOSE( 1844230326Smav device_printf(dev, "%dKbps of %dKbps bandwidth used%s\n", 1845230326Smav (bw + prevbw) / 1000, maxbw / 1000, 1846230326Smav bw + prevbw > maxbw ? " -- OVERFLOW!" : ""); 1847230326Smav ); 1848230326Smav if (bw + prevbw > maxbw) 1849230326Smav return (0); 1850230326Smav if (dir == 1) 1851230326Smav sc->sdo_bw_used += bw; 1852230326Smav else 1853230326Smav sc->codecs[cad].sdi_bw_used += bw; 1854230326Smav 1855230130Smav /* Allocate stream number */ 1856230130Smav if (ss >= sc->num_iss + sc->num_oss) 1857230130Smav stream = 15 - (ss - sc->num_iss + sc->num_oss); 1858230130Smav else if (ss >= sc->num_iss) 1859230130Smav stream = ss - sc->num_iss + 1; 1860230130Smav else 1861230130Smav stream = ss + 1; 1862182999Smav 1863230130Smav sc->streams[ss].dev = child; 1864230130Smav sc->streams[ss].dir = dir; 1865230130Smav sc->streams[ss].stream = stream; 1866230326Smav sc->streams[ss].bw = bw; 1867230130Smav sc->streams[ss].format = format; 1868230326Smav sc->streams[ss].stripe = stripe; 1869230130Smav if (dmapos != NULL) { 1870230130Smav if (sc->pos_dma.dma_vaddr != NULL) 1871230130Smav *dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8); 1872230130Smav else 1873230130Smav *dmapos = NULL; 1874230130Smav } 1875230130Smav return (stream); 1876182999Smav} 1877182999Smav 1878230130Smavstatic void 1879230130Smavhdac_stream_free(device_t dev, device_t child, int dir, int stream) 1880230130Smav{ 1881230130Smav struct hdac_softc *sc = device_get_softc(dev); 1882230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1883230130Smav int ss; 1884230130Smav 1885230130Smav ss = hdac_find_stream(sc, dir, stream); 1886230130Smav KASSERT(ss >= 0, 1887230130Smav ("Free for not allocated stream (%d/%d)\n", dir, stream)); 1888230326Smav if (dir == 1) 1889230326Smav sc->sdo_bw_used -= sc->streams[ss].bw; 1890230326Smav else 1891230326Smav sc->codecs[cad].sdi_bw_used -= sc->streams[ss].bw; 1892230130Smav sc->streams[ss].stream = 0; 1893230130Smav sc->streams[ss].dev = NULL; 1894230130Smav} 1895230130Smav 1896182999Smavstatic int 1897230130Smavhdac_stream_start(device_t dev, device_t child, 1898230130Smav int dir, int stream, bus_addr_t buf, int blksz, int blkcnt) 1899182999Smav{ 1900230130Smav struct hdac_softc *sc = device_get_softc(dev); 1901230130Smav struct hdac_bdle *bdle; 1902230130Smav uint64_t addr; 1903230130Smav int i, ss, off; 1904230130Smav uint32_t ctl; 1905182999Smav 1906230130Smav ss = hdac_find_stream(sc, dir, stream); 1907230130Smav KASSERT(ss >= 0, 1908230130Smav ("Start for not allocated stream (%d/%d)\n", dir, stream)); 1909230130Smav 1910230130Smav addr = (uint64_t)buf; 1911230130Smav bdle = (struct hdac_bdle *)sc->streams[ss].bdl.dma_vaddr; 1912230130Smav for (i = 0; i < blkcnt; i++, bdle++) { 1913230130Smav bdle->addrl = (uint32_t)addr; 1914230130Smav bdle->addrh = (uint32_t)(addr >> 32); 1915230130Smav bdle->len = blksz; 1916230130Smav bdle->ioc = 1; 1917230130Smav addr += blksz; 1918182999Smav } 1919182999Smav 1920230130Smav off = ss << 5; 1921230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDCBL, blksz * blkcnt); 1922230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDLVI, blkcnt - 1); 1923230130Smav addr = sc->streams[ss].bdl.dma_paddr; 1924230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPL, (uint32_t)addr); 1925230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1926230130Smav 1927230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL2); 1928230130Smav if (dir) 1929230130Smav ctl |= HDAC_SDCTL2_DIR; 1930230130Smav else 1931230130Smav ctl &= ~HDAC_SDCTL2_DIR; 1932230130Smav ctl &= ~HDAC_SDCTL2_STRM_MASK; 1933230130Smav ctl |= stream << HDAC_SDCTL2_STRM_SHIFT; 1934230326Smav ctl &= ~HDAC_SDCTL2_STRIPE_MASK; 1935230326Smav ctl |= sc->streams[ss].stripe << HDAC_SDCTL2_STRIPE_SHIFT; 1936230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl); 1937230130Smav 1938230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format); 1939230130Smav 1940230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1941230130Smav ctl |= 1 << ss; 1942230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1943230130Smav 1944230807Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDSTS, 1945230807Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS); 1946230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1947230130Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1948230130Smav HDAC_SDCTL_RUN; 1949230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1950230130Smav 1951230130Smav sc->streams[ss].blksz = blksz; 1952230130Smav sc->streams[ss].running = 1; 1953230130Smav hdac_poll_reinit(sc); 1954182999Smav return (0); 1955182999Smav} 1956182999Smav 1957230130Smavstatic void 1958230130Smavhdac_stream_stop(device_t dev, device_t child, int dir, int stream) 1959230130Smav{ 1960230130Smav struct hdac_softc *sc = device_get_softc(dev); 1961230130Smav int ss, off; 1962230130Smav uint32_t ctl; 1963230130Smav 1964230130Smav ss = hdac_find_stream(sc, dir, stream); 1965230130Smav KASSERT(ss >= 0, 1966230130Smav ("Stop for not allocated stream (%d/%d)\n", dir, stream)); 1967230130Smav 1968230130Smav off = ss << 5; 1969230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1970230130Smav ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1971230130Smav HDAC_SDCTL_RUN); 1972230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1973230130Smav 1974230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1975230130Smav ctl &= ~(1 << ss); 1976230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1977230130Smav 1978230130Smav sc->streams[ss].running = 0; 1979230130Smav hdac_poll_reinit(sc); 1980230130Smav} 1981230130Smav 1982230130Smavstatic void 1983230130Smavhdac_stream_reset(device_t dev, device_t child, int dir, int stream) 1984230130Smav{ 1985230130Smav struct hdac_softc *sc = device_get_softc(dev); 1986230130Smav int timeout = 1000; 1987230130Smav int to = timeout; 1988230130Smav int ss, off; 1989230130Smav uint32_t ctl; 1990230130Smav 1991230130Smav ss = hdac_find_stream(sc, dir, stream); 1992230130Smav KASSERT(ss >= 0, 1993230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 1994230130Smav 1995230130Smav off = ss << 5; 1996230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1997230130Smav ctl |= HDAC_SDCTL_SRST; 1998230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1999230130Smav do { 2000230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2001230130Smav if (ctl & HDAC_SDCTL_SRST) 2002230130Smav break; 2003230130Smav DELAY(10); 2004230130Smav } while (--to); 2005230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2006230130Smav device_printf(dev, "Reset setting timeout\n"); 2007230130Smav ctl &= ~HDAC_SDCTL_SRST; 2008230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 2009230130Smav to = timeout; 2010230130Smav do { 2011230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2012230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2013230130Smav break; 2014230130Smav DELAY(10); 2015230130Smav } while (--to); 2016230130Smav if (ctl & HDAC_SDCTL_SRST) 2017230130Smav device_printf(dev, "Reset timeout!\n"); 2018230130Smav} 2019230130Smav 2020230130Smavstatic uint32_t 2021230130Smavhdac_stream_getptr(device_t dev, device_t child, int dir, int stream) 2022230130Smav{ 2023230130Smav struct hdac_softc *sc = device_get_softc(dev); 2024230130Smav int ss, off; 2025230130Smav 2026230130Smav ss = hdac_find_stream(sc, dir, stream); 2027230130Smav KASSERT(ss >= 0, 2028230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 2029230130Smav 2030230130Smav off = ss << 5; 2031230130Smav return (HDAC_READ_4(&sc->mem, off + HDAC_SDLPIB)); 2032230130Smav} 2033230130Smav 2034230130Smavstatic int 2035230130Smavhdac_unsol_alloc(device_t dev, device_t child, int tag) 2036230130Smav{ 2037230130Smav struct hdac_softc *sc = device_get_softc(dev); 2038230130Smav 2039230130Smav sc->unsol_registered++; 2040230130Smav hdac_poll_reinit(sc); 2041230130Smav return (tag); 2042230130Smav} 2043230130Smav 2044230130Smavstatic void 2045230130Smavhdac_unsol_free(device_t dev, device_t child, int tag) 2046230130Smav{ 2047230130Smav struct hdac_softc *sc = device_get_softc(dev); 2048230130Smav 2049230130Smav sc->unsol_registered--; 2050230130Smav hdac_poll_reinit(sc); 2051230130Smav} 2052230130Smav 2053230130Smavstatic device_method_t hdac_methods[] = { 2054182999Smav /* device interface */ 2055230130Smav DEVMETHOD(device_probe, hdac_probe), 2056230130Smav DEVMETHOD(device_attach, hdac_attach), 2057230130Smav DEVMETHOD(device_detach, hdac_detach), 2058230130Smav DEVMETHOD(device_suspend, hdac_suspend), 2059230130Smav DEVMETHOD(device_resume, hdac_resume), 2060230130Smav /* Bus interface */ 2061230130Smav DEVMETHOD(bus_get_dma_tag, hdac_get_dma_tag), 2062230130Smav DEVMETHOD(bus_print_child, hdac_print_child), 2063230130Smav DEVMETHOD(bus_child_location_str, hdac_child_location_str), 2064230130Smav DEVMETHOD(bus_child_pnpinfo_str, hdac_child_pnpinfo_str_method), 2065230130Smav DEVMETHOD(bus_read_ivar, hdac_read_ivar), 2066230130Smav DEVMETHOD(hdac_get_mtx, hdac_get_mtx), 2067230130Smav DEVMETHOD(hdac_codec_command, hdac_codec_command), 2068230130Smav DEVMETHOD(hdac_stream_alloc, hdac_stream_alloc), 2069230130Smav DEVMETHOD(hdac_stream_free, hdac_stream_free), 2070230130Smav DEVMETHOD(hdac_stream_start, hdac_stream_start), 2071230130Smav DEVMETHOD(hdac_stream_stop, hdac_stream_stop), 2072230130Smav DEVMETHOD(hdac_stream_reset, hdac_stream_reset), 2073230130Smav DEVMETHOD(hdac_stream_getptr, hdac_stream_getptr), 2074230130Smav DEVMETHOD(hdac_unsol_alloc, hdac_unsol_alloc), 2075230130Smav DEVMETHOD(hdac_unsol_free, hdac_unsol_free), 2076264832Smarius DEVMETHOD_END 2077182999Smav}; 2078182999Smav 2079230130Smavstatic driver_t hdac_driver = { 2080230130Smav "hdac", 2081230130Smav hdac_methods, 2082230130Smav sizeof(struct hdac_softc), 2083182999Smav}; 2084182999Smav 2085230130Smavstatic devclass_t hdac_devclass; 2086182999Smav 2087264832SmariusDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, NULL, NULL); 2088