hdac.c revision 230807
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 230807 2012-01-31 12:57:21Z mav $"); 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 { 63163057Sariff 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#define HDAC_QUIRKS_TAB_LEN \ 71163057Sariff (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0])) 72163057Sariff 73230130SmavMALLOC_DEFINE(M_HDAC, "hdac", "HDA Controller"); 74162922Sariff 75162922Sariffstatic const struct { 76162922Sariff uint32_t model; 77162922Sariff char *desc; 78230130Smav char quirks_on; 79230130Smav char quirks_off; 80162922Sariff} hdac_devices[] = { 81230130Smav { HDA_INTEL_CPT, "Intel Cougar Point", 0, 0 }, 82230130Smav { HDA_INTEL_PATSBURG,"Intel Patsburg", 0, 0 }, 83230130Smav { HDA_INTEL_PPT1, "Intel Panther Point", 0, 0 }, 84230130Smav { HDA_INTEL_82801F, "Intel 82801F", 0, 0 }, 85230130Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0, 0 }, 86230130Smav { HDA_INTEL_82801G, "Intel 82801G", 0, 0 }, 87230130Smav { HDA_INTEL_82801H, "Intel 82801H", 0, 0 }, 88230130Smav { HDA_INTEL_82801I, "Intel 82801I", 0, 0 }, 89230130Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0, 0 }, 90230130Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0, 0 }, 91230130Smav { HDA_INTEL_PCH, "Intel 5 Series/3400 Series", 0, 0 }, 92230130Smav { HDA_INTEL_PCH2, "Intel 5 Series/3400 Series", 0, 0 }, 93230130Smav { HDA_INTEL_SCH, "Intel SCH", 0, 0 }, 94230130Smav { HDA_NVIDIA_MCP51, "NVIDIA MCP51", 0, HDAC_QUIRK_MSI }, 95230130Smav { HDA_NVIDIA_MCP55, "NVIDIA MCP55", 0, HDAC_QUIRK_MSI }, 96230130Smav { HDA_NVIDIA_MCP61_1, "NVIDIA MCP61", 0, 0 }, 97230130Smav { HDA_NVIDIA_MCP61_2, "NVIDIA MCP61", 0, 0 }, 98230130Smav { HDA_NVIDIA_MCP65_1, "NVIDIA MCP65", 0, 0 }, 99230130Smav { HDA_NVIDIA_MCP65_2, "NVIDIA MCP65", 0, 0 }, 100230130Smav { HDA_NVIDIA_MCP67_1, "NVIDIA MCP67", 0, 0 }, 101230130Smav { HDA_NVIDIA_MCP67_2, "NVIDIA MCP67", 0, 0 }, 102230130Smav { HDA_NVIDIA_MCP73_1, "NVIDIA MCP73", 0, 0 }, 103230130Smav { HDA_NVIDIA_MCP73_2, "NVIDIA MCP73", 0, 0 }, 104230130Smav { HDA_NVIDIA_MCP78_1, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 105230130Smav { HDA_NVIDIA_MCP78_2, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 106230130Smav { HDA_NVIDIA_MCP78_3, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 107230130Smav { HDA_NVIDIA_MCP78_4, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 108230130Smav { HDA_NVIDIA_MCP79_1, "NVIDIA MCP79", 0, 0 }, 109230130Smav { HDA_NVIDIA_MCP79_2, "NVIDIA MCP79", 0, 0 }, 110230130Smav { HDA_NVIDIA_MCP79_3, "NVIDIA MCP79", 0, 0 }, 111230130Smav { HDA_NVIDIA_MCP79_4, "NVIDIA MCP79", 0, 0 }, 112230130Smav { HDA_NVIDIA_MCP89_1, "NVIDIA MCP89", 0, 0 }, 113230130Smav { HDA_NVIDIA_MCP89_2, "NVIDIA MCP89", 0, 0 }, 114230130Smav { HDA_NVIDIA_MCP89_3, "NVIDIA MCP89", 0, 0 }, 115230130Smav { HDA_NVIDIA_MCP89_4, "NVIDIA MCP89", 0, 0 }, 116230331Smav { HDA_NVIDIA_0BE2, "NVIDIA (0x0be2)", 0, HDAC_QUIRK_MSI }, 117230331Smav { HDA_NVIDIA_0BE3, "NVIDIA (0x0be3)", 0, HDAC_QUIRK_MSI }, 118230331Smav { HDA_NVIDIA_0BE4, "NVIDIA (0x0be4)", 0, HDAC_QUIRK_MSI }, 119230312Smav { HDA_NVIDIA_GT100, "NVIDIA GT100", 0, HDAC_QUIRK_MSI }, 120230312Smav { HDA_NVIDIA_GT104, "NVIDIA GT104", 0, HDAC_QUIRK_MSI }, 121230312Smav { HDA_NVIDIA_GT106, "NVIDIA GT106", 0, HDAC_QUIRK_MSI }, 122230312Smav { HDA_NVIDIA_GT108, "NVIDIA GT108", 0, HDAC_QUIRK_MSI }, 123230312Smav { HDA_NVIDIA_GT116, "NVIDIA GT116", 0, HDAC_QUIRK_MSI }, 124230312Smav { HDA_NVIDIA_GF119, "NVIDIA GF119", 0, 0 }, 125230312Smav { HDA_NVIDIA_GF110_1, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 126230312Smav { HDA_NVIDIA_GF110_2, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 127230130Smav { HDA_ATI_SB450, "ATI SB450", 0, 0 }, 128230130Smav { HDA_ATI_SB600, "ATI SB600", 0, 0 }, 129230130Smav { HDA_ATI_RS600, "ATI RS600", 0, 0 }, 130230130Smav { HDA_ATI_RS690, "ATI RS690", 0, 0 }, 131230130Smav { HDA_ATI_RS780, "ATI RS780", 0, 0 }, 132230130Smav { HDA_ATI_R600, "ATI R600", 0, 0 }, 133230130Smav { HDA_ATI_RV610, "ATI RV610", 0, 0 }, 134230130Smav { HDA_ATI_RV620, "ATI RV620", 0, 0 }, 135230130Smav { HDA_ATI_RV630, "ATI RV630", 0, 0 }, 136230130Smav { HDA_ATI_RV635, "ATI RV635", 0, 0 }, 137230130Smav { HDA_ATI_RV710, "ATI RV710", 0, 0 }, 138230130Smav { HDA_ATI_RV730, "ATI RV730", 0, 0 }, 139230130Smav { HDA_ATI_RV740, "ATI RV740", 0, 0 }, 140230130Smav { HDA_ATI_RV770, "ATI RV770", 0, 0 }, 141230130Smav { HDA_RDC_M3010, "RDC M3010", 0, 0 }, 142230130Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 }, 143230130Smav { HDA_SIS_966, "SiS 966", 0, 0 }, 144230130Smav { HDA_ULI_M5461, "ULI M5461", 0, 0 }, 145162922Sariff /* Unknown */ 146230331Smav { HDA_INTEL_ALL, "Intel", 0, 0 }, 147230331Smav { HDA_NVIDIA_ALL, "NVIDIA", 0, 0 }, 148230331Smav { HDA_ATI_ALL, "ATI", 0, 0 }, 149230331Smav { HDA_VIA_ALL, "VIA", 0, 0 }, 150230331Smav { HDA_SIS_ALL, "SiS", 0, 0 }, 151230331Smav { HDA_ULI_ALL, "ULI", 0, 0 }, 152162922Sariff}; 153162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 154162922Sariff 155162922Sariffstatic const struct { 156169277Sariff uint16_t vendor; 157169277Sariff uint8_t reg; 158169277Sariff uint8_t mask; 159169277Sariff uint8_t enable; 160169277Sariff} hdac_pcie_snoop[] = { 161169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 162169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 163169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 164169277Sariff}; 165169277Sariff#define HDAC_PCIESNOOP_LEN \ 166169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 167169277Sariff 168162922Sariff/**************************************************************************** 169162922Sariff * Function prototypes 170162922Sariff ****************************************************************************/ 171162922Sariffstatic void hdac_intr_handler(void *); 172182999Smavstatic int hdac_reset(struct hdac_softc *, int); 173162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 174162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 175162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 176162922Sariff struct hdac_dma *, bus_size_t); 177169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 178162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 179162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 180162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 181162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 182162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 183162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 184162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 185162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 186162922Sariff 187162922Sariffstatic void hdac_attach2(void *); 188162922Sariff 189230130Smavstatic uint32_t hdac_send_command(struct hdac_softc *, nid_t, uint32_t); 190162922Sariff 191162922Sariffstatic int hdac_probe(device_t); 192162922Sariffstatic int hdac_attach(device_t); 193162922Sariffstatic int hdac_detach(device_t); 194182999Smavstatic int hdac_suspend(device_t); 195182999Smavstatic int hdac_resume(device_t); 196162922Sariff 197164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 198164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 199164614Sariff 200162922Sariff#define hdac_command(a1, a2, a3) \ 201230130Smav hdac_send_command(a1, a3, a2) 202162922Sariff 203230130Smav/* This function surely going to make its way into upper level someday. */ 204162922Sariffstatic void 205230130Smavhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 206162922Sariff{ 207230130Smav const char *res = NULL; 208230130Smav int i = 0, j, k, len, inv; 209162922Sariff 210230130Smav if (resource_string_value(device_get_name(sc->dev), 211230130Smav device_get_unit(sc->dev), "config", &res) != 0) 212162922Sariff return; 213230130Smav if (!(res != NULL && strlen(res) > 0)) 214230130Smav return; 215230130Smav HDA_BOOTVERBOSE( 216230130Smav device_printf(sc->dev, "Config options:"); 217230130Smav ); 218230130Smav for (;;) { 219230130Smav while (res[i] != '\0' && 220230130Smav (res[i] == ',' || isspace(res[i]) != 0)) 221230130Smav i++; 222230130Smav if (res[i] == '\0') { 223230130Smav HDA_BOOTVERBOSE( 224230130Smav printf("\n"); 225230130Smav ); 226230130Smav return; 227182999Smav } 228230130Smav j = i; 229230130Smav while (res[j] != '\0' && 230230130Smav !(res[j] == ',' || isspace(res[j]) != 0)) 231230130Smav j++; 232230130Smav len = j - i; 233230130Smav if (len > 2 && strncmp(res + i, "no", 2) == 0) 234230130Smav inv = 2; 235230130Smav else 236230130Smav inv = 0; 237230130Smav for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 238230130Smav if (strncmp(res + i + inv, 239230130Smav hdac_quirks_tab[k].key, len - inv) != 0) 240182999Smav continue; 241230130Smav if (len - inv != strlen(hdac_quirks_tab[k].key)) 242182999Smav continue; 243230130Smav HDA_BOOTVERBOSE( 244230130Smav printf(" %s%s", (inv != 0) ? "no" : "", 245230130Smav hdac_quirks_tab[k].key); 246230130Smav ); 247230130Smav if (inv == 0) { 248230130Smav *on |= hdac_quirks_tab[k].value; 249230130Smav *on &= ~hdac_quirks_tab[k].value; 250230130Smav } else if (inv != 0) { 251230130Smav *off |= hdac_quirks_tab[k].value; 252230130Smav *off &= ~hdac_quirks_tab[k].value; 253162922Sariff } 254162965Sariff break; 255182999Smav } 256230130Smav i = j; 257162922Sariff } 258162922Sariff} 259162922Sariff 260162922Sariff/**************************************************************************** 261162922Sariff * void hdac_intr_handler(void *) 262162922Sariff * 263162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 264162922Sariff ****************************************************************************/ 265162922Sariffstatic void 266162922Sariffhdac_intr_handler(void *context) 267162922Sariff{ 268162922Sariff struct hdac_softc *sc; 269230130Smav device_t dev; 270162922Sariff uint32_t intsts; 271162922Sariff uint8_t rirbsts; 272182999Smav int i; 273162922Sariff 274162922Sariff sc = (struct hdac_softc *)context; 275162922Sariff hdac_lock(sc); 276171141Sariff 277162922Sariff /* Do we have anything to do? */ 278162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 279230130Smav if ((intsts & HDAC_INTSTS_GIS) == 0) { 280162922Sariff hdac_unlock(sc); 281162922Sariff return; 282162922Sariff } 283162922Sariff 284162922Sariff /* Was this a controller interrupt? */ 285230130Smav if (intsts & HDAC_INTSTS_CIS) { 286162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 287162922Sariff /* Get as many responses that we can */ 288230130Smav while (rirbsts & HDAC_RIRBSTS_RINTFL) { 289164614Sariff HDAC_WRITE_1(&sc->mem, 290164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 291230130Smav hdac_rirb_flush(sc); 292162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 293162922Sariff } 294230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 295230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 296162922Sariff } 297164614Sariff 298163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 299230130Smav for (i = 0; i < sc->num_ss; i++) { 300230130Smav if ((intsts & (1 << i)) == 0) 301230130Smav continue; 302230130Smav HDAC_WRITE_1(&sc->mem, (i << 5) + HDAC_SDSTS, 303230130Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 304230130Smav if ((dev = sc->streams[i].dev) != NULL) { 305230130Smav HDAC_STREAM_INTR(dev, 306230130Smav sc->streams[i].dir, sc->streams[i].stream); 307230130Smav } 308182999Smav } 309162922Sariff } 310162922Sariff 311230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts); 312164614Sariff hdac_unlock(sc); 313230130Smav} 314162922Sariff 315230130Smavstatic void 316230130Smavhdac_poll_callback(void *arg) 317230130Smav{ 318230130Smav struct hdac_softc *sc = arg; 319230130Smav 320230130Smav if (sc == NULL) 321230130Smav return; 322230130Smav 323230130Smav hdac_lock(sc); 324230130Smav if (sc->polling == 0) { 325230130Smav hdac_unlock(sc); 326230130Smav return; 327182999Smav } 328230130Smav callout_reset(&sc->poll_callout, sc->poll_ival, 329230130Smav hdac_poll_callback, sc); 330230130Smav hdac_unlock(sc); 331230130Smav 332230130Smav hdac_intr_handler(sc); 333162922Sariff} 334162922Sariff 335162922Sariff/**************************************************************************** 336182999Smav * int hdac_reset(hdac_softc *, int) 337162922Sariff * 338162922Sariff * Reset the hdac to a quiescent and known state. 339162922Sariff ****************************************************************************/ 340162922Sariffstatic int 341182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 342162922Sariff{ 343162922Sariff uint32_t gctl; 344162922Sariff int count, i; 345162922Sariff 346162922Sariff /* 347162922Sariff * Stop all Streams DMA engine 348162922Sariff */ 349162922Sariff for (i = 0; i < sc->num_iss; i++) 350162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 351162922Sariff for (i = 0; i < sc->num_oss; i++) 352162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 353162922Sariff for (i = 0; i < sc->num_bss; i++) 354162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 355162922Sariff 356162922Sariff /* 357169277Sariff * Stop Control DMA engines. 358162922Sariff */ 359162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 360162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 361162922Sariff 362162922Sariff /* 363169277Sariff * Reset DMA position buffer. 364169277Sariff */ 365169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 366169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 367169277Sariff 368169277Sariff /* 369162922Sariff * Reset the controller. The reset must remain asserted for 370162922Sariff * a minimum of 100us. 371162922Sariff */ 372162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 373162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 374162922Sariff count = 10000; 375162922Sariff do { 376162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 377162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 378162922Sariff break; 379162922Sariff DELAY(10); 380162922Sariff } while (--count); 381162922Sariff if (gctl & HDAC_GCTL_CRST) { 382162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 383162922Sariff return (ENXIO); 384162922Sariff } 385230130Smav 386182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 387182999Smav if (!wakeup) 388182999Smav return (0); 389230130Smav 390162922Sariff DELAY(100); 391162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 392162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 393162922Sariff count = 10000; 394162922Sariff do { 395162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 396163057Sariff if (gctl & HDAC_GCTL_CRST) 397162922Sariff break; 398162922Sariff DELAY(10); 399162922Sariff } while (--count); 400162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 401162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 402162922Sariff return (ENXIO); 403162922Sariff } 404162922Sariff 405162922Sariff /* 406162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 407162922Sariff * should be of 250us but for some reasons, on it's not enough on my 408162922Sariff * computer. Let's use twice as much as necessary to make sure that 409162922Sariff * it's reset properly. 410162922Sariff */ 411162922Sariff DELAY(1000); 412162922Sariff 413162922Sariff return (0); 414162922Sariff} 415162922Sariff 416162922Sariff 417162922Sariff/**************************************************************************** 418162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 419162922Sariff * 420162922Sariff * Retreive the general capabilities of the hdac; 421162922Sariff * Number of Input Streams 422162922Sariff * Number of Output Streams 423162922Sariff * Number of bidirectional Streams 424162922Sariff * 64bit ready 425162922Sariff * CORB and RIRB sizes 426162922Sariff ****************************************************************************/ 427162922Sariffstatic int 428162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 429162922Sariff{ 430162922Sariff uint16_t gcap; 431162922Sariff uint8_t corbsize, rirbsize; 432162922Sariff 433162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 434162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 435162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 436162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 437230130Smav sc->num_ss = sc->num_iss + sc->num_oss + sc->num_bss; 438196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 439230130Smav sc->support_64bit = (gcap & HDAC_GCAP_64OK) != 0; 440230130Smav if (sc->quirks_on & HDAC_QUIRK_64BIT) 441230130Smav sc->support_64bit = 1; 442230130Smav else if (sc->quirks_off & HDAC_QUIRK_64BIT) 443230130Smav sc->support_64bit = 0; 444162922Sariff 445162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 446162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 447162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 448162922Sariff sc->corb_size = 256; 449162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 450162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 451162922Sariff sc->corb_size = 16; 452162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 453162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 454162922Sariff sc->corb_size = 2; 455162922Sariff else { 456162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 457162922Sariff __func__, corbsize); 458162922Sariff return (ENXIO); 459162922Sariff } 460162922Sariff 461162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 462162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 463162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 464162922Sariff sc->rirb_size = 256; 465162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 466162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 467162922Sariff sc->rirb_size = 16; 468162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 469162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 470162922Sariff sc->rirb_size = 2; 471162922Sariff else { 472162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 473162922Sariff __func__, rirbsize); 474162922Sariff return (ENXIO); 475162922Sariff } 476162922Sariff 477196762Smav HDA_BOOTVERBOSE( 478196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 479196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 480196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 481196762Smav sc->support_64bit ? ", 64bit" : "", 482196762Smav sc->corb_size, sc->rirb_size); 483182999Smav ); 484182999Smav 485162922Sariff return (0); 486162922Sariff} 487162922Sariff 488162922Sariff 489162922Sariff/**************************************************************************** 490162922Sariff * void hdac_dma_cb 491162922Sariff * 492162922Sariff * This function is called by bus_dmamap_load when the mapping has been 493162922Sariff * established. We just record the physical address of the mapping into 494162922Sariff * the struct hdac_dma passed in. 495162922Sariff ****************************************************************************/ 496162922Sariffstatic void 497162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 498162922Sariff{ 499162922Sariff struct hdac_dma *dma; 500162922Sariff 501162922Sariff if (error == 0) { 502162922Sariff dma = (struct hdac_dma *)callback_arg; 503162922Sariff dma->dma_paddr = segs[0].ds_addr; 504162922Sariff } 505162922Sariff} 506162922Sariff 507162922Sariff 508162922Sariff/**************************************************************************** 509162922Sariff * int hdac_dma_alloc 510162922Sariff * 511162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 512162922Sariff * It must be freed by a corresponding hdac_dma_free. 513162922Sariff ****************************************************************************/ 514162922Sariffstatic int 515162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 516162922Sariff{ 517169277Sariff bus_size_t roundsz; 518162922Sariff int result; 519162922Sariff 520230130Smav roundsz = roundup2(size, HDA_DMA_ALIGNMENT); 521162922Sariff bzero(dma, sizeof(*dma)); 522162922Sariff 523162922Sariff /* 524162922Sariff * Create a DMA tag 525162922Sariff */ 526194861Smav result = bus_dma_tag_create( 527194861Smav bus_get_dma_tag(sc->dev), /* parent */ 528230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 529162922Sariff 0, /* boundary */ 530194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 531194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 532162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 533162922Sariff NULL, /* filtfunc */ 534162922Sariff NULL, /* fistfuncarg */ 535169277Sariff roundsz, /* maxsize */ 536162922Sariff 1, /* nsegments */ 537169277Sariff roundsz, /* maxsegsz */ 538162922Sariff 0, /* flags */ 539162922Sariff NULL, /* lockfunc */ 540162922Sariff NULL, /* lockfuncarg */ 541162922Sariff &dma->dma_tag); /* dmat */ 542162922Sariff if (result != 0) { 543162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 544162922Sariff __func__, result); 545167773Sariff goto hdac_dma_alloc_fail; 546162922Sariff } 547162922Sariff 548162922Sariff /* 549162922Sariff * Allocate DMA memory 550162922Sariff */ 551162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 552169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 553171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 554171330Sariff &dma->dma_map); 555162922Sariff if (result != 0) { 556162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 557162922Sariff __func__, result); 558167773Sariff goto hdac_dma_alloc_fail; 559162922Sariff } 560162922Sariff 561169277Sariff dma->dma_size = roundsz; 562169277Sariff 563162922Sariff /* 564162922Sariff * Map the memory 565162922Sariff */ 566162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 567169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 568162922Sariff if (result != 0 || dma->dma_paddr == 0) { 569167773Sariff if (result == 0) 570167773Sariff result = ENOMEM; 571162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 572162922Sariff __func__, result); 573167773Sariff goto hdac_dma_alloc_fail; 574162922Sariff } 575162922Sariff 576183097Smav HDA_BOOTHVERBOSE( 577169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 578169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 579169277Sariff ); 580169277Sariff 581162922Sariff return (0); 582169277Sariff 583167773Sariffhdac_dma_alloc_fail: 584169277Sariff hdac_dma_free(sc, dma); 585167773Sariff 586162922Sariff return (result); 587162922Sariff} 588162922Sariff 589162922Sariff 590162922Sariff/**************************************************************************** 591169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 592162922Sariff * 593162922Sariff * Free a struct dhac_dma that has been previously allocated via the 594162922Sariff * hdac_dma_alloc function. 595162922Sariff ****************************************************************************/ 596162922Sariffstatic void 597169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 598162922Sariff{ 599167773Sariff if (dma->dma_map != NULL) { 600169277Sariff#if 0 601162922Sariff /* Flush caches */ 602162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 603162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 604169277Sariff#endif 605162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 606167773Sariff } 607167773Sariff if (dma->dma_vaddr != NULL) { 608162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 609167773Sariff dma->dma_vaddr = NULL; 610167773Sariff } 611167773Sariff dma->dma_map = NULL; 612167773Sariff if (dma->dma_tag != NULL) { 613162922Sariff bus_dma_tag_destroy(dma->dma_tag); 614167773Sariff dma->dma_tag = NULL; 615162922Sariff } 616167773Sariff dma->dma_size = 0; 617162922Sariff} 618162922Sariff 619162922Sariff/**************************************************************************** 620162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 621162922Sariff * 622162922Sariff * Allocate all the bus resources necessary to speak with the physical 623162922Sariff * controller. 624162922Sariff ****************************************************************************/ 625162922Sariffstatic int 626162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 627162922Sariff{ 628162922Sariff struct hdac_mem *mem; 629162922Sariff 630162922Sariff mem = &sc->mem; 631162922Sariff mem->mem_rid = PCIR_BAR(0); 632162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 633162922Sariff &mem->mem_rid, RF_ACTIVE); 634162922Sariff if (mem->mem_res == NULL) { 635162922Sariff device_printf(sc->dev, 636162922Sariff "%s: Unable to allocate memory resource\n", __func__); 637162922Sariff return (ENOMEM); 638162922Sariff } 639162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 640162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 641162922Sariff 642162922Sariff return (0); 643162922Sariff} 644162922Sariff 645162922Sariff/**************************************************************************** 646162922Sariff * void hdac_mem_free(struct hdac_softc *) 647162922Sariff * 648162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 649162922Sariff ****************************************************************************/ 650162922Sariffstatic void 651162922Sariffhdac_mem_free(struct hdac_softc *sc) 652162922Sariff{ 653162922Sariff struct hdac_mem *mem; 654162922Sariff 655162922Sariff mem = &sc->mem; 656162922Sariff if (mem->mem_res != NULL) 657162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 658162922Sariff mem->mem_res); 659164614Sariff mem->mem_res = NULL; 660162922Sariff} 661162922Sariff 662162922Sariff/**************************************************************************** 663162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 664162922Sariff * 665162922Sariff * Allocate and setup the resources necessary for interrupt handling. 666162922Sariff ****************************************************************************/ 667162922Sariffstatic int 668162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 669162922Sariff{ 670162922Sariff struct hdac_irq *irq; 671162922Sariff int result; 672162922Sariff 673162922Sariff irq = &sc->irq; 674162922Sariff irq->irq_rid = 0x0; 675171330Sariff 676230130Smav if ((sc->quirks_off & HDAC_QUIRK_MSI) == 0 && 677171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 678171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 679171330Sariff irq->irq_rid = 0x1; 680171330Sariff 681162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 682162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 683162922Sariff if (irq->irq_res == NULL) { 684162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 685162922Sariff __func__); 686167773Sariff goto hdac_irq_alloc_fail; 687162922Sariff } 688182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 689182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 690162922Sariff if (result != 0) { 691162922Sariff device_printf(sc->dev, 692162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 693162922Sariff __func__, result); 694167773Sariff goto hdac_irq_alloc_fail; 695162922Sariff } 696162922Sariff 697162922Sariff return (0); 698162922Sariff 699167773Sariffhdac_irq_alloc_fail: 700164614Sariff hdac_irq_free(sc); 701164614Sariff 702162922Sariff return (ENXIO); 703162922Sariff} 704162922Sariff 705162922Sariff/**************************************************************************** 706162922Sariff * void hdac_irq_free(struct hdac_softc *) 707162922Sariff * 708162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 709162922Sariff ****************************************************************************/ 710162922Sariffstatic void 711162922Sariffhdac_irq_free(struct hdac_softc *sc) 712162922Sariff{ 713162922Sariff struct hdac_irq *irq; 714162922Sariff 715162922Sariff irq = &sc->irq; 716164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 717162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 718162922Sariff if (irq->irq_res != NULL) 719162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 720162922Sariff irq->irq_res); 721188656Smav if (irq->irq_rid == 0x1) 722171330Sariff pci_release_msi(sc->dev); 723164614Sariff irq->irq_handle = NULL; 724164614Sariff irq->irq_res = NULL; 725171330Sariff irq->irq_rid = 0x0; 726162922Sariff} 727162922Sariff 728162922Sariff/**************************************************************************** 729162922Sariff * void hdac_corb_init(struct hdac_softc *) 730162922Sariff * 731162922Sariff * Initialize the corb registers for operations but do not start it up yet. 732162922Sariff * The CORB engine must not be running when this function is called. 733162922Sariff ****************************************************************************/ 734162922Sariffstatic void 735162922Sariffhdac_corb_init(struct hdac_softc *sc) 736162922Sariff{ 737162922Sariff uint8_t corbsize; 738162922Sariff uint64_t corbpaddr; 739162922Sariff 740162922Sariff /* Setup the CORB size. */ 741162922Sariff switch (sc->corb_size) { 742162922Sariff case 256: 743162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 744162922Sariff break; 745162922Sariff case 16: 746162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 747162922Sariff break; 748162922Sariff case 2: 749162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 750162922Sariff break; 751162922Sariff default: 752162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 753162922Sariff } 754162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 755162922Sariff 756162922Sariff /* Setup the CORB Address in the hdac */ 757162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 758162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 759162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 760162922Sariff 761162922Sariff /* Set the WP and RP */ 762162922Sariff sc->corb_wp = 0; 763162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 764162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 765162922Sariff /* 766162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 767162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 768162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 769162922Sariff * manually reset the bit to zero before continuing. 770162922Sariff */ 771162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 772162922Sariff 773162922Sariff /* Enable CORB error reporting */ 774162922Sariff#if 0 775162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 776162922Sariff#endif 777162922Sariff} 778162922Sariff 779162922Sariff/**************************************************************************** 780162922Sariff * void hdac_rirb_init(struct hdac_softc *) 781162922Sariff * 782162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 783162922Sariff * The RIRB engine must not be running when this function is called. 784162922Sariff ****************************************************************************/ 785162922Sariffstatic void 786162922Sariffhdac_rirb_init(struct hdac_softc *sc) 787162922Sariff{ 788162922Sariff uint8_t rirbsize; 789162922Sariff uint64_t rirbpaddr; 790162922Sariff 791162922Sariff /* Setup the RIRB size. */ 792162922Sariff switch (sc->rirb_size) { 793162922Sariff case 256: 794162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 795162922Sariff break; 796162922Sariff case 16: 797162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 798162922Sariff break; 799162922Sariff case 2: 800162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 801162922Sariff break; 802162922Sariff default: 803162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 804162922Sariff } 805162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 806162922Sariff 807162922Sariff /* Setup the RIRB Address in the hdac */ 808162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 809162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 810162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 811162922Sariff 812162922Sariff /* Setup the WP and RP */ 813162922Sariff sc->rirb_rp = 0; 814162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 815162922Sariff 816182999Smav /* Setup the interrupt threshold */ 817182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 818162922Sariff 819182999Smav /* Enable Overrun and response received reporting */ 820162922Sariff#if 0 821182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 822182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 823162922Sariff#else 824182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 825162922Sariff#endif 826162922Sariff 827169277Sariff#if 0 828162922Sariff /* 829162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 830162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 831162922Sariff * should be sufficient to do this only once as the rirb is purely 832162922Sariff * read-only from now on. 833162922Sariff */ 834162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 835162922Sariff BUS_DMASYNC_PREREAD); 836169277Sariff#endif 837162922Sariff} 838162922Sariff 839162922Sariff/**************************************************************************** 840162922Sariff * void hdac_corb_start(hdac_softc *) 841162922Sariff * 842162922Sariff * Startup the corb DMA engine 843162922Sariff ****************************************************************************/ 844162922Sariffstatic void 845162922Sariffhdac_corb_start(struct hdac_softc *sc) 846162922Sariff{ 847162922Sariff uint32_t corbctl; 848162922Sariff 849162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 850162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 851162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 852162922Sariff} 853162922Sariff 854162922Sariff/**************************************************************************** 855162922Sariff * void hdac_rirb_start(hdac_softc *) 856162922Sariff * 857162922Sariff * Startup the rirb DMA engine 858162922Sariff ****************************************************************************/ 859162922Sariffstatic void 860162922Sariffhdac_rirb_start(struct hdac_softc *sc) 861162922Sariff{ 862162922Sariff uint32_t rirbctl; 863162922Sariff 864162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 865162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 866162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 867162922Sariff} 868162922Sariff 869164614Sariffstatic int 870164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 871164614Sariff{ 872164614Sariff struct hdac_rirb *rirb_base, *rirb; 873164614Sariff nid_t cad; 874164614Sariff uint32_t resp; 875164614Sariff uint8_t rirbwp; 876171141Sariff int ret; 877164614Sariff 878164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 879164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 880169277Sariff#if 0 881164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 882164614Sariff BUS_DMASYNC_POSTREAD); 883169277Sariff#endif 884164614Sariff 885171141Sariff ret = 0; 886164614Sariff while (sc->rirb_rp != rirbwp) { 887164614Sariff sc->rirb_rp++; 888164614Sariff sc->rirb_rp %= sc->rirb_size; 889164614Sariff rirb = &rirb_base[sc->rirb_rp]; 890164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 891164614Sariff resp = rirb->response; 892164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 893230130Smav sc->unsolq[sc->unsolq_wp++] = resp; 894164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 895230130Smav sc->unsolq[sc->unsolq_wp++] = cad; 896230130Smav sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 897230130Smav } else if (sc->codecs[cad].pending <= 0) { 898230130Smav device_printf(sc->dev, "Unexpected unsolicited " 899230130Smav "response from address %d: %08x\n", cad, resp); 900230130Smav } else { 901230130Smav sc->codecs[cad].response = resp; 902230130Smav sc->codecs[cad].pending--; 903230130Smav } 904164614Sariff ret++; 905164614Sariff } 906164614Sariff return (ret); 907164614Sariff} 908164614Sariff 909164614Sariffstatic int 910164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 911164614Sariff{ 912230130Smav device_t child; 913164614Sariff nid_t cad; 914230130Smav uint32_t resp; 915164614Sariff int ret = 0; 916164614Sariff 917164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 918164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 919164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 920230130Smav resp = sc->unsolq[sc->unsolq_rp++]; 921164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 922230130Smav cad = sc->unsolq[sc->unsolq_rp++]; 923230130Smav sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 924230130Smav if ((child = sc->codecs[cad].dev) != NULL) 925230130Smav HDAC_UNSOL_INTR(child, resp); 926164614Sariff ret++; 927164614Sariff } 928164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 929164614Sariff } 930164614Sariff 931164614Sariff return (ret); 932164614Sariff} 933164614Sariff 934162922Sariff/**************************************************************************** 935162922Sariff * uint32_t hdac_command_sendone_internal 936162922Sariff * 937162922Sariff * Wrapper function that sends only one command to a given codec 938162922Sariff ****************************************************************************/ 939162922Sariffstatic uint32_t 940230130Smavhdac_send_command(struct hdac_softc *sc, nid_t cad, uint32_t verb) 941162922Sariff{ 942230130Smav int timeout; 943230130Smav uint32_t *corb; 944162922Sariff 945163057Sariff if (!hdac_lockowned(sc)) 946162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 947230130Smav verb &= ~HDA_CMD_CAD_MASK; 948230130Smav verb |= ((uint32_t)cad) << HDA_CMD_CAD_SHIFT; 949230130Smav sc->codecs[cad].response = HDA_INVALID; 950162922Sariff 951230130Smav sc->codecs[cad].pending++; 952230130Smav sc->corb_wp++; 953230130Smav sc->corb_wp %= sc->corb_size; 954162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 955169277Sariff#if 0 956230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 957230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 958169277Sariff#endif 959230130Smav corb[sc->corb_wp] = verb; 960169277Sariff#if 0 961230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 962230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 963169277Sariff#endif 964230130Smav HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 965162922Sariff 966230130Smav timeout = 10000; 967230130Smav do { 968230130Smav if (hdac_rirb_flush(sc) == 0) 969162922Sariff DELAY(10); 970230130Smav } while (sc->codecs[cad].pending != 0 && --timeout); 971162922Sariff 972230130Smav if (sc->codecs[cad].pending != 0) { 973230130Smav device_printf(sc->dev, "Command timeout on address %d\n", cad); 974230130Smav sc->codecs[cad].pending = 0; 975230130Smav } 976162922Sariff 977230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 978230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 979230130Smav return (sc->codecs[cad].response); 980162922Sariff} 981162922Sariff 982162922Sariff/**************************************************************************** 983162922Sariff * Device Methods 984162922Sariff ****************************************************************************/ 985162922Sariff 986162922Sariff/**************************************************************************** 987162922Sariff * int hdac_probe(device_t) 988162922Sariff * 989162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 990162922Sariff * match using the subclass of the device. 991162922Sariff ****************************************************************************/ 992162922Sariffstatic int 993162922Sariffhdac_probe(device_t dev) 994162922Sariff{ 995162922Sariff int i, result; 996163257Sariff uint32_t model; 997163257Sariff uint16_t class, subclass; 998162922Sariff char desc[64]; 999162922Sariff 1000162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 1001162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1002162922Sariff class = pci_get_class(dev); 1003162922Sariff subclass = pci_get_subclass(dev); 1004162922Sariff 1005162922Sariff bzero(desc, sizeof(desc)); 1006162922Sariff result = ENXIO; 1007162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1008162922Sariff if (hdac_devices[i].model == model) { 1009230331Smav strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1010230331Smav result = BUS_PROBE_DEFAULT; 1011162922Sariff break; 1012162922Sariff } 1013163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1014162922Sariff class == PCIC_MULTIMEDIA && 1015162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1016230331Smav snprintf(desc, sizeof(desc), 1017230331Smav "%s (0x%04x)", 1018230331Smav hdac_devices[i].desc, pci_get_device(dev)); 1019230331Smav result = BUS_PROBE_GENERIC; 1020162922Sariff break; 1021162922Sariff } 1022162922Sariff } 1023162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 1024162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1025230331Smav snprintf(desc, sizeof(desc), "Generic (0x%08x)", model); 1026230331Smav result = BUS_PROBE_GENERIC; 1027162922Sariff } 1028162922Sariff if (result != ENXIO) { 1029230331Smav strlcat(desc, " HDA Controller", sizeof(desc)); 1030162922Sariff device_set_desc_copy(dev, desc); 1031162922Sariff } 1032162922Sariff 1033162922Sariff return (result); 1034162922Sariff} 1035162922Sariff 1036162922Sariffstatic void 1037171141Sariffhdac_unsolq_task(void *context, int pending) 1038171141Sariff{ 1039171141Sariff struct hdac_softc *sc; 1040171141Sariff 1041171141Sariff sc = (struct hdac_softc *)context; 1042171141Sariff 1043171141Sariff hdac_lock(sc); 1044171141Sariff hdac_unsolq_flush(sc); 1045171141Sariff hdac_unlock(sc); 1046171141Sariff} 1047171141Sariff 1048162922Sariff/**************************************************************************** 1049162922Sariff * int hdac_attach(device_t) 1050162922Sariff * 1051162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 1052162922Sariff * when this function is called. Setup everything that doesn't require 1053162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 1054162922Sariff ****************************************************************************/ 1055162922Sariffstatic int 1056162922Sariffhdac_attach(device_t dev) 1057162922Sariff{ 1058162922Sariff struct hdac_softc *sc; 1059162922Sariff int result; 1060189086Smav int i, devid = -1; 1061189086Smav uint32_t model; 1062189086Smav uint16_t class, subclass; 1063169277Sariff uint16_t vendor; 1064169277Sariff uint8_t v; 1065162922Sariff 1066230130Smav sc = device_get_softc(dev); 1067223118Sjoel HDA_BOOTVERBOSE( 1068223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 1069223118Sjoel HDA_DRV_TEST_REV); 1070223118Sjoel ); 1071182999Smav 1072189086Smav model = (uint32_t)pci_get_device(dev) << 16; 1073189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1074189086Smav class = pci_get_class(dev); 1075189086Smav subclass = pci_get_subclass(dev); 1076189086Smav 1077189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1078189086Smav if (hdac_devices[i].model == model) { 1079189086Smav devid = i; 1080189086Smav break; 1081189086Smav } 1082189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1083189086Smav class == PCIC_MULTIMEDIA && 1084189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 1085189086Smav devid = i; 1086189086Smav break; 1087189086Smav } 1088189086Smav } 1089189086Smav 1090230130Smav sc->lock = snd_mtxcreate(device_get_nameunit(dev), "HDA driver mutex"); 1091162922Sariff sc->dev = dev; 1092230130Smav TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 1093230130Smav callout_init(&sc->poll_callout, CALLOUT_MPSAFE); 1094230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) 1095230130Smav sc->codecs[i].dev = NULL; 1096230130Smav if (devid >= 0) { 1097230130Smav sc->quirks_on = hdac_devices[devid].quirks_on; 1098230130Smav sc->quirks_off = hdac_devices[devid].quirks_off; 1099230130Smav } else { 1100230130Smav sc->quirks_on = 0; 1101230130Smav sc->quirks_off = 0; 1102165281Sariff } 1103169277Sariff if (resource_int_value(device_get_name(dev), 1104230130Smav device_get_unit(dev), "msi", &i) == 0) { 1105230130Smav if (i == 0) 1106230130Smav sc->quirks_off |= HDAC_QUIRK_MSI; 1107230130Smav else { 1108230130Smav sc->quirks_on |= HDAC_QUIRK_MSI; 1109230130Smav sc->quirks_off |= ~HDAC_QUIRK_MSI; 1110230130Smav } 1111230130Smav } 1112230130Smav hdac_config_fetch(sc, &sc->quirks_on, &sc->quirks_off); 1113230130Smav HDA_BOOTVERBOSE( 1114230130Smav device_printf(sc->dev, 1115230130Smav "Config options: on=0x%08x off=0x%08x\n", 1116230130Smav sc->quirks_on, sc->quirks_off); 1117230130Smav ); 1118230130Smav sc->poll_ival = hz; 1119230130Smav if (resource_int_value(device_get_name(dev), 1120169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 1121164614Sariff sc->polling = 1; 1122164614Sariff else 1123164614Sariff sc->polling = 0; 1124164614Sariff 1125162922Sariff pci_enable_busmaster(dev); 1126162922Sariff 1127230130Smav vendor = pci_get_vendor(dev); 1128169277Sariff if (vendor == INTEL_VENDORID) { 1129169277Sariff /* TCSEL -> TC0 */ 1130169277Sariff v = pci_read_config(dev, 0x44, 1); 1131169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 1132183097Smav HDA_BOOTHVERBOSE( 1133169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 1134169277Sariff pci_read_config(dev, 0x44, 1)); 1135169277Sariff ); 1136169277Sariff } 1137169277Sariff 1138169277Sariff#if defined(__i386__) || defined(__amd64__) 1139171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1140169277Sariff 1141169277Sariff if (resource_int_value(device_get_name(dev), 1142169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 1143169277Sariff#else 1144171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1145169277Sariff#endif 1146169277Sariff /* 1147169277Sariff * Try to enable PCIe snoop to avoid messing around with 1148169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 1149169277Sariff * config is pretty much vendor specific, there are no 1150169277Sariff * general solutions on how to enable it, forcing us (even 1151169277Sariff * Microsoft) to enable uncacheable or write combined DMA 1152169277Sariff * by default. 1153169277Sariff * 1154169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 1155169277Sariff */ 1156169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 1157169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 1158169277Sariff continue; 1159171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1160169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 1161169277Sariff break; 1162169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1163169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 1164169277Sariff hdac_pcie_snoop[i].enable) 1165169277Sariff break; 1166169277Sariff v &= hdac_pcie_snoop[i].mask; 1167169277Sariff v |= hdac_pcie_snoop[i].enable; 1168169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 1169169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1170169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 1171169277Sariff hdac_pcie_snoop[i].enable) { 1172169277Sariff HDA_BOOTVERBOSE( 1173169277Sariff device_printf(dev, 1174169277Sariff "WARNING: Failed to enable PCIe " 1175169277Sariff "snoop!\n"); 1176169277Sariff ); 1177169277Sariff#if defined(__i386__) || defined(__amd64__) 1178171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1179169277Sariff#endif 1180169277Sariff } 1181169277Sariff break; 1182169277Sariff } 1183169277Sariff#if defined(__i386__) || defined(__amd64__) 1184169277Sariff } 1185169277Sariff#endif 1186169277Sariff 1187183097Smav HDA_BOOTHVERBOSE( 1188169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 1189171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 1190171330Sariff "Uncacheable" : "PCIe snoop", vendor); 1191169277Sariff ); 1192169277Sariff 1193162922Sariff /* Allocate resources */ 1194162922Sariff result = hdac_mem_alloc(sc); 1195162922Sariff if (result != 0) 1196163057Sariff goto hdac_attach_fail; 1197162922Sariff result = hdac_irq_alloc(sc); 1198162922Sariff if (result != 0) 1199163057Sariff goto hdac_attach_fail; 1200162922Sariff 1201162922Sariff /* Get Capabilities */ 1202162922Sariff result = hdac_get_capabilities(sc); 1203162922Sariff if (result != 0) 1204163057Sariff goto hdac_attach_fail; 1205162922Sariff 1206230130Smav /* Allocate CORB, RIRB, POS and BDLs dma memory */ 1207162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 1208162922Sariff sc->corb_size * sizeof(uint32_t)); 1209162922Sariff if (result != 0) 1210163057Sariff goto hdac_attach_fail; 1211162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 1212162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 1213162922Sariff if (result != 0) 1214163057Sariff goto hdac_attach_fail; 1215230130Smav sc->streams = malloc(sizeof(struct hdac_stream) * sc->num_ss, 1216230130Smav M_HDAC, M_ZERO | M_WAITOK); 1217230130Smav for (i = 0; i < sc->num_ss; i++) { 1218230130Smav result = hdac_dma_alloc(sc, &sc->streams[i].bdl, 1219230130Smav sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1220230130Smav if (result != 0) 1221230130Smav goto hdac_attach_fail; 1222230130Smav } 1223230130Smav if (sc->quirks_on & HDAC_QUIRK_DMAPOS) { 1224230130Smav if (hdac_dma_alloc(sc, &sc->pos_dma, (sc->num_ss) * 8) != 0) { 1225230130Smav HDA_BOOTVERBOSE( 1226230130Smav device_printf(dev, "Failed to " 1227230130Smav "allocate DMA pos buffer " 1228230130Smav "(non-fatal)\n"); 1229230130Smav ); 1230230130Smav } else { 1231230130Smav uint64_t addr = sc->pos_dma.dma_paddr; 1232162922Sariff 1233230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, addr >> 32); 1234230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 1235230130Smav (addr & HDAC_DPLBASE_DPLBASE_MASK) | 1236230130Smav HDAC_DPLBASE_DPLBASE_DMAPBE); 1237230130Smav } 1238230130Smav } 1239230130Smav 1240194861Smav result = bus_dma_tag_create( 1241194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1242230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 1243194861Smav 0, /* boundary */ 1244194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1245194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1246194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 1247194861Smav NULL, /* filtfunc */ 1248194861Smav NULL, /* fistfuncarg */ 1249194861Smav HDA_BUFSZ_MAX, /* maxsize */ 1250194861Smav 1, /* nsegments */ 1251194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 1252194861Smav 0, /* flags */ 1253194861Smav NULL, /* lockfunc */ 1254194861Smav NULL, /* lockfuncarg */ 1255194861Smav &sc->chan_dmat); /* dmat */ 1256194861Smav if (result != 0) { 1257194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 1258194861Smav __func__, result); 1259194861Smav goto hdac_attach_fail; 1260194861Smav } 1261194861Smav 1262162922Sariff /* Quiesce everything */ 1263183097Smav HDA_BOOTHVERBOSE( 1264182999Smav device_printf(dev, "Reset controller...\n"); 1265182999Smav ); 1266182999Smav hdac_reset(sc, 1); 1267162922Sariff 1268162922Sariff /* Initialize the CORB and RIRB */ 1269162922Sariff hdac_corb_init(sc); 1270162922Sariff hdac_rirb_init(sc); 1271162922Sariff 1272162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 1273162922Sariff sc->intrhook.ich_func = hdac_attach2; 1274162922Sariff sc->intrhook.ich_arg = (void *)sc; 1275162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 1276162922Sariff sc->intrhook.ich_func = NULL; 1277162922Sariff hdac_attach2((void *)sc); 1278162922Sariff } 1279162922Sariff 1280163057Sariff return (0); 1281162922Sariff 1282163057Sariffhdac_attach_fail: 1283162922Sariff hdac_irq_free(sc); 1284230130Smav for (i = 0; i < sc->num_ss; i++) 1285230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1286230130Smav free(sc->streams, M_HDAC); 1287169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 1288169277Sariff hdac_dma_free(sc, &sc->corb_dma); 1289162922Sariff hdac_mem_free(sc); 1290162922Sariff snd_mtxfree(sc->lock); 1291162922Sariff 1292163057Sariff return (ENXIO); 1293162922Sariff} 1294162922Sariff 1295230130Smavstatic int 1296230130Smavsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 1297162922Sariff{ 1298230130Smav struct hdac_softc *sc; 1299230130Smav device_t *devlist; 1300230130Smav device_t dev; 1301230130Smav int devcount, i, err, val; 1302162922Sariff 1303230130Smav dev = oidp->oid_arg1; 1304230130Smav sc = device_get_softc(dev); 1305230130Smav if (sc == NULL) 1306230130Smav return (EINVAL); 1307230130Smav val = 0; 1308230130Smav err = sysctl_handle_int(oidp, &val, 0, req); 1309230130Smav if (err != 0 || req->newptr == NULL || val == 0) 1310230130Smav return (err); 1311162922Sariff 1312230130Smav /* XXX: Temporary. For debugging. */ 1313230130Smav if (val == 100) { 1314230130Smav hdac_suspend(dev); 1315182999Smav return (0); 1316230130Smav } else if (val == 101) { 1317230130Smav hdac_resume(dev); 1318182999Smav return (0); 1319182999Smav } 1320162922Sariff 1321230130Smav if ((err = device_get_children(dev, &devlist, &devcount)) != 0) 1322230130Smav return (err); 1323230130Smav hdac_lock(sc); 1324230130Smav for (i = 0; i < devcount; i++) 1325230130Smav HDAC_PINDUMP(devlist[i]); 1326230130Smav hdac_unlock(sc); 1327230130Smav free(devlist, M_TEMP); 1328182999Smav return (0); 1329162922Sariff} 1330162922Sariff 1331183097Smavstatic int 1332230326Smavhdac_mdata_rate(uint16_t fmt) 1333162922Sariff{ 1334230326Smav static const int mbits[8] = { 8, 16, 32, 32, 32, 32, 32, 32 }; 1335230326Smav int rate, bits; 1336162922Sariff 1337230130Smav if (fmt & (1 << 14)) 1338230130Smav rate = 44100; 1339230130Smav else 1340230130Smav rate = 48000; 1341230130Smav rate *= ((fmt >> 11) & 0x07) + 1; 1342230130Smav rate /= ((fmt >> 8) & 0x07) + 1; 1343230326Smav bits = mbits[(fmt >> 4) & 0x03]; 1344230326Smav bits *= (fmt & 0x0f) + 1; 1345230326Smav return (rate * bits); 1346182999Smav} 1347182999Smav 1348230326Smavstatic int 1349230326Smavhdac_bdata_rate(uint16_t fmt, int output) 1350230326Smav{ 1351230326Smav static const int bbits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 }; 1352230326Smav int rate, bits; 1353230326Smav 1354230326Smav rate = 48000; 1355230326Smav rate *= ((fmt >> 11) & 0x07) + 1; 1356230326Smav bits = bbits[(fmt >> 4) & 0x03]; 1357230326Smav bits *= (fmt & 0x0f) + 1; 1358230326Smav if (!output) 1359230326Smav bits = ((bits + 7) & ~0x07) + 10; 1360230326Smav return (rate * bits); 1361230326Smav} 1362230326Smav 1363182999Smavstatic void 1364230130Smavhdac_poll_reinit(struct hdac_softc *sc) 1365182999Smav{ 1366230130Smav int i, pollticks, min = 1000000; 1367230130Smav struct hdac_stream *s; 1368182999Smav 1369230130Smav if (sc->polling == 0) 1370230130Smav return; 1371230130Smav if (sc->unsol_registered > 0) 1372230130Smav min = hz / 2; 1373230130Smav for (i = 0; i < sc->num_ss; i++) { 1374230130Smav s = &sc->streams[i]; 1375230130Smav if (s->running == 0) 1376182999Smav continue; 1377230130Smav pollticks = ((uint64_t)hz * s->blksz) / 1378230326Smav (hdac_mdata_rate(s->format) / 8); 1379230130Smav pollticks >>= 1; 1380230130Smav if (pollticks > hz) 1381230130Smav pollticks = hz; 1382230130Smav if (pollticks < 1) { 1383182999Smav HDA_BOOTVERBOSE( 1384230130Smav device_printf(sc->dev, 1385230130Smav "poll interval < 1 tick !\n"); 1386182999Smav ); 1387230130Smav pollticks = 1; 1388162922Sariff } 1389230130Smav if (min > pollticks) 1390230130Smav min = pollticks; 1391162922Sariff } 1392202789Smav HDA_BOOTVERBOSE( 1393230130Smav device_printf(sc->dev, 1394230130Smav "poll interval %d -> %d ticks\n", 1395230130Smav sc->poll_ival, min); 1396202789Smav ); 1397230130Smav sc->poll_ival = min; 1398230130Smav if (min == 1000000) 1399230130Smav callout_stop(&sc->poll_callout); 1400182999Smav else 1401230130Smav callout_reset(&sc->poll_callout, 1, hdac_poll_callback, sc); 1402163057Sariff} 1403163057Sariff 1404164614Sariffstatic int 1405164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 1406164614Sariff{ 1407164614Sariff struct hdac_softc *sc; 1408164614Sariff device_t dev; 1409164614Sariff uint32_t ctl; 1410164614Sariff int err, val; 1411164614Sariff 1412164614Sariff dev = oidp->oid_arg1; 1413182999Smav sc = device_get_softc(dev); 1414182999Smav if (sc == NULL) 1415164614Sariff return (EINVAL); 1416164614Sariff hdac_lock(sc); 1417164614Sariff val = sc->polling; 1418164614Sariff hdac_unlock(sc); 1419170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 1420164614Sariff 1421169277Sariff if (err != 0 || req->newptr == NULL) 1422164614Sariff return (err); 1423164614Sariff if (val < 0 || val > 1) 1424164614Sariff return (EINVAL); 1425164614Sariff 1426164614Sariff hdac_lock(sc); 1427164614Sariff if (val != sc->polling) { 1428182999Smav if (val == 0) { 1429230130Smav callout_stop(&sc->poll_callout); 1430169277Sariff hdac_unlock(sc); 1431230130Smav callout_drain(&sc->poll_callout); 1432169277Sariff hdac_lock(sc); 1433164614Sariff sc->polling = 0; 1434182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1435182999Smav ctl |= HDAC_INTCTL_GIE; 1436182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1437164614Sariff } else { 1438182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1439182999Smav ctl &= ~HDAC_INTCTL_GIE; 1440182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1441164614Sariff sc->polling = 1; 1442182999Smav hdac_poll_reinit(sc); 1443164614Sariff } 1444164614Sariff } 1445164614Sariff hdac_unlock(sc); 1446164614Sariff 1447164614Sariff return (err); 1448164614Sariff} 1449169277Sariff 1450163057Sariffstatic void 1451162922Sariffhdac_attach2(void *arg) 1452162922Sariff{ 1453162922Sariff struct hdac_softc *sc; 1454230130Smav device_t child; 1455230130Smav uint32_t vendorid, revisionid; 1456230130Smav int i; 1457230130Smav uint16_t statests; 1458162922Sariff 1459162922Sariff sc = (struct hdac_softc *)arg; 1460162922Sariff 1461162922Sariff hdac_lock(sc); 1462162922Sariff 1463162922Sariff /* Remove ourselves from the config hooks */ 1464162922Sariff if (sc->intrhook.ich_func != NULL) { 1465162922Sariff config_intrhook_disestablish(&sc->intrhook); 1466162922Sariff sc->intrhook.ich_func = NULL; 1467162922Sariff } 1468162922Sariff 1469183097Smav HDA_BOOTHVERBOSE( 1470182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 1471162922Sariff ); 1472162922Sariff hdac_corb_start(sc); 1473183097Smav HDA_BOOTHVERBOSE( 1474182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 1475162922Sariff ); 1476162922Sariff hdac_rirb_start(sc); 1477183097Smav HDA_BOOTHVERBOSE( 1478162922Sariff device_printf(sc->dev, 1479182999Smav "Enabling controller interrupt...\n"); 1480162922Sariff ); 1481182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1482182999Smav HDAC_GCTL_UNSOL); 1483182999Smav if (sc->polling == 0) { 1484164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 1485164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1486182999Smav } 1487162922Sariff DELAY(1000); 1488162922Sariff 1489183097Smav HDA_BOOTHVERBOSE( 1490230130Smav device_printf(sc->dev, "Scanning HDA codecs ...\n"); 1491162922Sariff ); 1492230130Smav statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1493230130Smav hdac_unlock(sc); 1494230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1495230130Smav if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1496230130Smav HDA_BOOTHVERBOSE( 1497183097Smav device_printf(sc->dev, 1498230130Smav "Found CODEC at address %d\n", i); 1499183019Smav ); 1500230130Smav hdac_lock(sc); 1501230130Smav vendorid = hdac_send_command(sc, i, 1502230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_VENDOR_ID)); 1503230130Smav revisionid = hdac_send_command(sc, i, 1504230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_REVISION_ID)); 1505230130Smav hdac_unlock(sc); 1506230130Smav if (vendorid == HDA_INVALID && 1507230130Smav revisionid == HDA_INVALID) { 1508230130Smav device_printf(sc->dev, 1509230130Smav "CODEC is not responding!\n"); 1510182999Smav continue; 1511182999Smav } 1512230130Smav sc->codecs[i].vendor_id = 1513230130Smav HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1514230130Smav sc->codecs[i].device_id = 1515230130Smav HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1516230130Smav sc->codecs[i].revision_id = 1517230130Smav HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1518230130Smav sc->codecs[i].stepping_id = 1519230130Smav HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1520230130Smav child = device_add_child(sc->dev, "hdacc", -1); 1521230130Smav if (child == NULL) { 1522230130Smav device_printf(sc->dev, 1523230130Smav "Failed to add CODEC device\n"); 1524230130Smav continue; 1525182999Smav } 1526230130Smav device_set_ivars(child, (void *)(intptr_t)i); 1527230130Smav sc->codecs[i].dev = child; 1528182999Smav } 1529162922Sariff } 1530182999Smav bus_generic_attach(sc->dev); 1531182999Smav 1532182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1533182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1534230130Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1535230130Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 1536230130Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1537230130Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1538182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1539182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 1540182999Smav} 1541182999Smav 1542182999Smav/**************************************************************************** 1543182999Smav * int hdac_suspend(device_t) 1544182999Smav * 1545182999Smav * Suspend and power down HDA bus and codecs. 1546182999Smav ****************************************************************************/ 1547182999Smavstatic int 1548182999Smavhdac_suspend(device_t dev) 1549182999Smav{ 1550230130Smav struct hdac_softc *sc = device_get_softc(dev); 1551182999Smav 1552183097Smav HDA_BOOTHVERBOSE( 1553182999Smav device_printf(dev, "Suspend...\n"); 1554162922Sariff ); 1555230130Smav bus_generic_suspend(dev); 1556182999Smav 1557182999Smav hdac_lock(sc); 1558183097Smav HDA_BOOTHVERBOSE( 1559182999Smav device_printf(dev, "Reset controller...\n"); 1560162922Sariff ); 1561182999Smav hdac_reset(sc, 0); 1562182999Smav hdac_unlock(sc); 1563182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1564183097Smav HDA_BOOTHVERBOSE( 1565182999Smav device_printf(dev, "Suspend done\n"); 1566162922Sariff ); 1567182999Smav return (0); 1568182999Smav} 1569182999Smav 1570182999Smav/**************************************************************************** 1571182999Smav * int hdac_resume(device_t) 1572182999Smav * 1573182999Smav * Powerup and restore HDA bus and codecs state. 1574182999Smav ****************************************************************************/ 1575182999Smavstatic int 1576182999Smavhdac_resume(device_t dev) 1577182999Smav{ 1578230130Smav struct hdac_softc *sc = device_get_softc(dev); 1579230130Smav int error; 1580182999Smav 1581183097Smav HDA_BOOTHVERBOSE( 1582182999Smav device_printf(dev, "Resume...\n"); 1583162922Sariff ); 1584182999Smav hdac_lock(sc); 1585182999Smav 1586182999Smav /* Quiesce everything */ 1587183097Smav HDA_BOOTHVERBOSE( 1588182999Smav device_printf(dev, "Reset controller...\n"); 1589162922Sariff ); 1590182999Smav hdac_reset(sc, 1); 1591182999Smav 1592182999Smav /* Initialize the CORB and RIRB */ 1593182999Smav hdac_corb_init(sc); 1594182999Smav hdac_rirb_init(sc); 1595182999Smav 1596183097Smav HDA_BOOTHVERBOSE( 1597182999Smav device_printf(dev, "Starting CORB Engine...\n"); 1598162922Sariff ); 1599182999Smav hdac_corb_start(sc); 1600183097Smav HDA_BOOTHVERBOSE( 1601182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 1602162922Sariff ); 1603182999Smav hdac_rirb_start(sc); 1604183097Smav HDA_BOOTHVERBOSE( 1605230130Smav device_printf(dev, "Enabling controller interrupt...\n"); 1606162922Sariff ); 1607182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1608182999Smav HDAC_GCTL_UNSOL); 1609230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1610182999Smav DELAY(1000); 1611182999Smav hdac_unlock(sc); 1612182999Smav 1613230130Smav error = bus_generic_resume(dev); 1614183097Smav HDA_BOOTHVERBOSE( 1615182999Smav device_printf(dev, "Resume done\n"); 1616162922Sariff ); 1617230130Smav return (error); 1618230130Smav} 1619164614Sariff 1620162922Sariff/**************************************************************************** 1621162922Sariff * int hdac_detach(device_t) 1622162922Sariff * 1623162922Sariff * Detach and free up resources utilized by the hdac device. 1624162922Sariff ****************************************************************************/ 1625162922Sariffstatic int 1626162922Sariffhdac_detach(device_t dev) 1627162922Sariff{ 1628230130Smav struct hdac_softc *sc = device_get_softc(dev); 1629185177Smav device_t *devlist; 1630230130Smav int cad, i, devcount, error; 1631162922Sariff 1632185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 1633185177Smav return (error); 1634185177Smav for (i = 0; i < devcount; i++) { 1635230130Smav cad = (intptr_t)device_get_ivars(devlist[i]); 1636185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 1637185178Smav free(devlist, M_TEMP); 1638185178Smav return (error); 1639185178Smav } 1640230130Smav sc->codecs[cad].dev = NULL; 1641185177Smav } 1642185177Smav free(devlist, M_TEMP); 1643185177Smav 1644230130Smav hdac_lock(sc); 1645230130Smav hdac_reset(sc, 0); 1646230130Smav hdac_unlock(sc); 1647230130Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1648230130Smav hdac_irq_free(sc); 1649162922Sariff 1650230130Smav for (i = 0; i < sc->num_ss; i++) 1651230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1652230130Smav free(sc->streams, M_HDAC); 1653230130Smav hdac_dma_free(sc, &sc->pos_dma); 1654230130Smav hdac_dma_free(sc, &sc->rirb_dma); 1655230130Smav hdac_dma_free(sc, &sc->corb_dma); 1656230130Smav if (sc->chan_dmat != NULL) { 1657230130Smav bus_dma_tag_destroy(sc->chan_dmat); 1658230130Smav sc->chan_dmat = NULL; 1659230130Smav } 1660230130Smav hdac_mem_free(sc); 1661230130Smav snd_mtxfree(sc->lock); 1662162922Sariff return (0); 1663162922Sariff} 1664162922Sariff 1665230130Smavstatic bus_dma_tag_t 1666230130Smavhdac_get_dma_tag(device_t dev, device_t child) 1667230130Smav{ 1668230130Smav struct hdac_softc *sc = device_get_softc(dev); 1669230130Smav 1670230130Smav return (sc->chan_dmat); 1671230130Smav} 1672230130Smav 1673184095Smavstatic int 1674184095Smavhdac_print_child(device_t dev, device_t child) 1675184095Smav{ 1676184095Smav int retval; 1677184095Smav 1678184095Smav retval = bus_print_child_header(dev, child); 1679230130Smav retval += printf(" at cad %d", 1680230130Smav (int)(intptr_t)device_get_ivars(child)); 1681184095Smav retval += bus_print_child_footer(dev, child); 1682184095Smav 1683184095Smav return (retval); 1684184095Smav} 1685184095Smav 1686230130Smavstatic int 1687230130Smavhdac_child_location_str(device_t dev, device_t child, char *buf, 1688230130Smav size_t buflen) 1689230130Smav{ 1690162922Sariff 1691230130Smav snprintf(buf, buflen, "cad=%d", 1692230130Smav (int)(intptr_t)device_get_ivars(child)); 1693230130Smav return (0); 1694230130Smav} 1695162922Sariff 1696230130Smavstatic int 1697230130Smavhdac_child_pnpinfo_str_method(device_t dev, device_t child, char *buf, 1698230130Smav size_t buflen) 1699230130Smav{ 1700230130Smav struct hdac_softc *sc = device_get_softc(dev); 1701230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1702182999Smav 1703230130Smav snprintf(buf, buflen, "vendor=0x%04x device=0x%04x revision=0x%02x " 1704230130Smav "stepping=0x%02x", 1705230130Smav sc->codecs[cad].vendor_id, sc->codecs[cad].device_id, 1706230130Smav sc->codecs[cad].revision_id, sc->codecs[cad].stepping_id); 1707230130Smav return (0); 1708230130Smav} 1709182999Smav 1710182999Smavstatic int 1711230130Smavhdac_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1712182999Smav{ 1713230130Smav struct hdac_softc *sc = device_get_softc(dev); 1714230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1715182999Smav 1716230130Smav switch (which) { 1717230130Smav case HDA_IVAR_CODEC_ID: 1718230130Smav *result = cad; 1719230130Smav break; 1720230130Smav case HDA_IVAR_VENDOR_ID: 1721230130Smav *result = sc->codecs[cad].vendor_id; 1722230130Smav break; 1723230130Smav case HDA_IVAR_DEVICE_ID: 1724230130Smav *result = sc->codecs[cad].device_id; 1725230130Smav break; 1726230130Smav case HDA_IVAR_REVISION_ID: 1727230130Smav *result = sc->codecs[cad].revision_id; 1728230130Smav break; 1729230130Smav case HDA_IVAR_STEPPING_ID: 1730230130Smav *result = sc->codecs[cad].stepping_id; 1731230130Smav break; 1732230130Smav case HDA_IVAR_SUBVENDOR_ID: 1733230130Smav *result = pci_get_subvendor(dev); 1734230130Smav break; 1735230130Smav case HDA_IVAR_SUBDEVICE_ID: 1736230130Smav *result = pci_get_subdevice(dev); 1737230130Smav break; 1738230130Smav case HDA_IVAR_DMA_NOCACHE: 1739230130Smav *result = (sc->flags & HDAC_F_DMA_NOCACHE) != 0; 1740230130Smav break; 1741230130Smav default: 1742230130Smav return (ENOENT); 1743230130Smav } 1744182999Smav return (0); 1745182999Smav} 1746182999Smav 1747230130Smavstatic struct mtx * 1748230130Smavhdac_get_mtx(device_t dev, device_t child) 1749182999Smav{ 1750230130Smav struct hdac_softc *sc = device_get_softc(dev); 1751182999Smav 1752230130Smav return (sc->lock); 1753230130Smav} 1754182999Smav 1755230130Smavstatic uint32_t 1756230130Smavhdac_codec_command(device_t dev, device_t child, uint32_t verb) 1757230130Smav{ 1758182999Smav 1759230130Smav return (hdac_send_command(device_get_softc(dev), 1760230130Smav (intptr_t)device_get_ivars(child), verb)); 1761230130Smav} 1762182999Smav 1763230130Smavstatic int 1764230130Smavhdac_find_stream(struct hdac_softc *sc, int dir, int stream) 1765230130Smav{ 1766230130Smav int i, ss; 1767182999Smav 1768230130Smav ss = -1; 1769230130Smav /* Allocate ISS/BSS first. */ 1770230130Smav if (dir == 0) { 1771230130Smav for (i = 0; i < sc->num_iss; i++) { 1772230130Smav if (sc->streams[i].stream == stream) { 1773230130Smav ss = i; 1774230130Smav break; 1775230130Smav } 1776230130Smav } 1777230130Smav } else { 1778230130Smav for (i = 0; i < sc->num_oss; i++) { 1779230130Smav if (sc->streams[i + sc->num_iss].stream == stream) { 1780230130Smav ss = i + sc->num_iss; 1781230130Smav break; 1782230130Smav } 1783230130Smav } 1784230130Smav } 1785230130Smav /* Fallback to BSS. */ 1786230130Smav if (ss == -1) { 1787230130Smav for (i = 0; i < sc->num_bss; i++) { 1788230130Smav if (sc->streams[i + sc->num_iss + sc->num_oss].stream 1789230130Smav == stream) { 1790230130Smav ss = i + sc->num_iss + sc->num_oss; 1791230130Smav break; 1792230130Smav } 1793230130Smav } 1794230130Smav } 1795230130Smav return (ss); 1796230130Smav} 1797182999Smav 1798230130Smavstatic int 1799230326Smavhdac_stream_alloc(device_t dev, device_t child, int dir, int format, int stripe, 1800230130Smav uint32_t **dmapos) 1801230130Smav{ 1802230130Smav struct hdac_softc *sc = device_get_softc(dev); 1803230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1804230326Smav int stream, ss, bw, maxbw, prevbw; 1805182999Smav 1806230130Smav /* Look for empty stream. */ 1807230130Smav ss = hdac_find_stream(sc, dir, 0); 1808182999Smav 1809230130Smav /* Return if found nothing. */ 1810230130Smav if (ss < 0) 1811230130Smav return (0); 1812182999Smav 1813230326Smav /* Check bus bandwidth. */ 1814230326Smav bw = hdac_bdata_rate(format, dir); 1815230326Smav if (dir == 1) { 1816230326Smav bw *= 1 << (sc->num_sdo - stripe); 1817230326Smav prevbw = sc->sdo_bw_used; 1818230326Smav maxbw = 48000 * 960 * (1 << sc->num_sdo); 1819230326Smav } else { 1820230326Smav prevbw = sc->codecs[cad].sdi_bw_used; 1821230326Smav maxbw = 48000 * 464; 1822230326Smav } 1823230326Smav HDA_BOOTHVERBOSE( 1824230326Smav device_printf(dev, "%dKbps of %dKbps bandwidth used%s\n", 1825230326Smav (bw + prevbw) / 1000, maxbw / 1000, 1826230326Smav bw + prevbw > maxbw ? " -- OVERFLOW!" : ""); 1827230326Smav ); 1828230326Smav if (bw + prevbw > maxbw) 1829230326Smav return (0); 1830230326Smav if (dir == 1) 1831230326Smav sc->sdo_bw_used += bw; 1832230326Smav else 1833230326Smav sc->codecs[cad].sdi_bw_used += bw; 1834230326Smav 1835230130Smav /* Allocate stream number */ 1836230130Smav if (ss >= sc->num_iss + sc->num_oss) 1837230130Smav stream = 15 - (ss - sc->num_iss + sc->num_oss); 1838230130Smav else if (ss >= sc->num_iss) 1839230130Smav stream = ss - sc->num_iss + 1; 1840230130Smav else 1841230130Smav stream = ss + 1; 1842182999Smav 1843230130Smav sc->streams[ss].dev = child; 1844230130Smav sc->streams[ss].dir = dir; 1845230130Smav sc->streams[ss].stream = stream; 1846230326Smav sc->streams[ss].bw = bw; 1847230130Smav sc->streams[ss].format = format; 1848230326Smav sc->streams[ss].stripe = stripe; 1849230130Smav if (dmapos != NULL) { 1850230130Smav if (sc->pos_dma.dma_vaddr != NULL) 1851230130Smav *dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8); 1852230130Smav else 1853230130Smav *dmapos = NULL; 1854230130Smav } 1855230130Smav return (stream); 1856182999Smav} 1857182999Smav 1858230130Smavstatic void 1859230130Smavhdac_stream_free(device_t dev, device_t child, int dir, int stream) 1860230130Smav{ 1861230130Smav struct hdac_softc *sc = device_get_softc(dev); 1862230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1863230130Smav int ss; 1864230130Smav 1865230130Smav ss = hdac_find_stream(sc, dir, stream); 1866230130Smav KASSERT(ss >= 0, 1867230130Smav ("Free for not allocated stream (%d/%d)\n", dir, stream)); 1868230326Smav if (dir == 1) 1869230326Smav sc->sdo_bw_used -= sc->streams[ss].bw; 1870230326Smav else 1871230326Smav sc->codecs[cad].sdi_bw_used -= sc->streams[ss].bw; 1872230130Smav sc->streams[ss].stream = 0; 1873230130Smav sc->streams[ss].dev = NULL; 1874230130Smav} 1875230130Smav 1876182999Smavstatic int 1877230130Smavhdac_stream_start(device_t dev, device_t child, 1878230130Smav int dir, int stream, bus_addr_t buf, int blksz, int blkcnt) 1879182999Smav{ 1880230130Smav struct hdac_softc *sc = device_get_softc(dev); 1881230130Smav struct hdac_bdle *bdle; 1882230130Smav uint64_t addr; 1883230130Smav int i, ss, off; 1884230130Smav uint32_t ctl; 1885182999Smav 1886230130Smav ss = hdac_find_stream(sc, dir, stream); 1887230130Smav KASSERT(ss >= 0, 1888230130Smav ("Start for not allocated stream (%d/%d)\n", dir, stream)); 1889230130Smav 1890230130Smav addr = (uint64_t)buf; 1891230130Smav bdle = (struct hdac_bdle *)sc->streams[ss].bdl.dma_vaddr; 1892230130Smav for (i = 0; i < blkcnt; i++, bdle++) { 1893230130Smav bdle->addrl = (uint32_t)addr; 1894230130Smav bdle->addrh = (uint32_t)(addr >> 32); 1895230130Smav bdle->len = blksz; 1896230130Smav bdle->ioc = 1; 1897230130Smav addr += blksz; 1898182999Smav } 1899182999Smav 1900230130Smav off = ss << 5; 1901230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDCBL, blksz * blkcnt); 1902230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDLVI, blkcnt - 1); 1903230130Smav addr = sc->streams[ss].bdl.dma_paddr; 1904230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPL, (uint32_t)addr); 1905230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1906230130Smav 1907230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL2); 1908230130Smav if (dir) 1909230130Smav ctl |= HDAC_SDCTL2_DIR; 1910230130Smav else 1911230130Smav ctl &= ~HDAC_SDCTL2_DIR; 1912230130Smav ctl &= ~HDAC_SDCTL2_STRM_MASK; 1913230130Smav ctl |= stream << HDAC_SDCTL2_STRM_SHIFT; 1914230326Smav ctl &= ~HDAC_SDCTL2_STRIPE_MASK; 1915230326Smav ctl |= sc->streams[ss].stripe << HDAC_SDCTL2_STRIPE_SHIFT; 1916230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl); 1917230130Smav 1918230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format); 1919230130Smav 1920230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1921230130Smav ctl |= 1 << ss; 1922230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1923230130Smav 1924230807Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDSTS, 1925230807Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS); 1926230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1927230130Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1928230130Smav HDAC_SDCTL_RUN; 1929230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1930230130Smav 1931230130Smav sc->streams[ss].blksz = blksz; 1932230130Smav sc->streams[ss].running = 1; 1933230130Smav hdac_poll_reinit(sc); 1934182999Smav return (0); 1935182999Smav} 1936182999Smav 1937230130Smavstatic void 1938230130Smavhdac_stream_stop(device_t dev, device_t child, int dir, int stream) 1939230130Smav{ 1940230130Smav struct hdac_softc *sc = device_get_softc(dev); 1941230130Smav int ss, off; 1942230130Smav uint32_t ctl; 1943230130Smav 1944230130Smav ss = hdac_find_stream(sc, dir, stream); 1945230130Smav KASSERT(ss >= 0, 1946230130Smav ("Stop for not allocated stream (%d/%d)\n", dir, stream)); 1947230130Smav 1948230130Smav off = ss << 5; 1949230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1950230130Smav ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1951230130Smav HDAC_SDCTL_RUN); 1952230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1953230130Smav 1954230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1955230130Smav ctl &= ~(1 << ss); 1956230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1957230130Smav 1958230130Smav sc->streams[ss].running = 0; 1959230130Smav hdac_poll_reinit(sc); 1960230130Smav} 1961230130Smav 1962230130Smavstatic void 1963230130Smavhdac_stream_reset(device_t dev, device_t child, int dir, int stream) 1964230130Smav{ 1965230130Smav struct hdac_softc *sc = device_get_softc(dev); 1966230130Smav int timeout = 1000; 1967230130Smav int to = timeout; 1968230130Smav int ss, off; 1969230130Smav uint32_t ctl; 1970230130Smav 1971230130Smav ss = hdac_find_stream(sc, dir, stream); 1972230130Smav KASSERT(ss >= 0, 1973230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 1974230130Smav 1975230130Smav off = ss << 5; 1976230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1977230130Smav ctl |= HDAC_SDCTL_SRST; 1978230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1979230130Smav do { 1980230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1981230130Smav if (ctl & HDAC_SDCTL_SRST) 1982230130Smav break; 1983230130Smav DELAY(10); 1984230130Smav } while (--to); 1985230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 1986230130Smav device_printf(dev, "Reset setting timeout\n"); 1987230130Smav ctl &= ~HDAC_SDCTL_SRST; 1988230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1989230130Smav to = timeout; 1990230130Smav do { 1991230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1992230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 1993230130Smav break; 1994230130Smav DELAY(10); 1995230130Smav } while (--to); 1996230130Smav if (ctl & HDAC_SDCTL_SRST) 1997230130Smav device_printf(dev, "Reset timeout!\n"); 1998230130Smav} 1999230130Smav 2000230130Smavstatic uint32_t 2001230130Smavhdac_stream_getptr(device_t dev, device_t child, int dir, int stream) 2002230130Smav{ 2003230130Smav struct hdac_softc *sc = device_get_softc(dev); 2004230130Smav int ss, off; 2005230130Smav 2006230130Smav ss = hdac_find_stream(sc, dir, stream); 2007230130Smav KASSERT(ss >= 0, 2008230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 2009230130Smav 2010230130Smav off = ss << 5; 2011230130Smav return (HDAC_READ_4(&sc->mem, off + HDAC_SDLPIB)); 2012230130Smav} 2013230130Smav 2014230130Smavstatic int 2015230130Smavhdac_unsol_alloc(device_t dev, device_t child, int tag) 2016230130Smav{ 2017230130Smav struct hdac_softc *sc = device_get_softc(dev); 2018230130Smav 2019230130Smav sc->unsol_registered++; 2020230130Smav hdac_poll_reinit(sc); 2021230130Smav return (tag); 2022230130Smav} 2023230130Smav 2024230130Smavstatic void 2025230130Smavhdac_unsol_free(device_t dev, device_t child, int tag) 2026230130Smav{ 2027230130Smav struct hdac_softc *sc = device_get_softc(dev); 2028230130Smav 2029230130Smav sc->unsol_registered--; 2030230130Smav hdac_poll_reinit(sc); 2031230130Smav} 2032230130Smav 2033230130Smavstatic device_method_t hdac_methods[] = { 2034182999Smav /* device interface */ 2035230130Smav DEVMETHOD(device_probe, hdac_probe), 2036230130Smav DEVMETHOD(device_attach, hdac_attach), 2037230130Smav DEVMETHOD(device_detach, hdac_detach), 2038230130Smav DEVMETHOD(device_suspend, hdac_suspend), 2039230130Smav DEVMETHOD(device_resume, hdac_resume), 2040230130Smav /* Bus interface */ 2041230130Smav DEVMETHOD(bus_get_dma_tag, hdac_get_dma_tag), 2042230130Smav DEVMETHOD(bus_print_child, hdac_print_child), 2043230130Smav DEVMETHOD(bus_child_location_str, hdac_child_location_str), 2044230130Smav DEVMETHOD(bus_child_pnpinfo_str, hdac_child_pnpinfo_str_method), 2045230130Smav DEVMETHOD(bus_read_ivar, hdac_read_ivar), 2046230130Smav DEVMETHOD(hdac_get_mtx, hdac_get_mtx), 2047230130Smav DEVMETHOD(hdac_codec_command, hdac_codec_command), 2048230130Smav DEVMETHOD(hdac_stream_alloc, hdac_stream_alloc), 2049230130Smav DEVMETHOD(hdac_stream_free, hdac_stream_free), 2050230130Smav DEVMETHOD(hdac_stream_start, hdac_stream_start), 2051230130Smav DEVMETHOD(hdac_stream_stop, hdac_stream_stop), 2052230130Smav DEVMETHOD(hdac_stream_reset, hdac_stream_reset), 2053230130Smav DEVMETHOD(hdac_stream_getptr, hdac_stream_getptr), 2054230130Smav DEVMETHOD(hdac_unsol_alloc, hdac_unsol_alloc), 2055230130Smav DEVMETHOD(hdac_unsol_free, hdac_unsol_free), 2056182999Smav { 0, 0 } 2057182999Smav}; 2058182999Smav 2059230130Smavstatic driver_t hdac_driver = { 2060230130Smav "hdac", 2061230130Smav hdac_methods, 2062230130Smav sizeof(struct hdac_softc), 2063182999Smav}; 2064182999Smav 2065230130Smavstatic devclass_t hdac_devclass; 2066182999Smav 2067230130SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 2068