hdac.c revision 230130
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 49230130Smav#define HDA_DRV_TEST_REV "20120111_0001" 50162922Sariff 51162922SariffSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 230130 2012-01-15 13:21:36Z 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 73162922Sariff#define HDA_BDL_MIN 2 74162922Sariff#define HDA_BDL_MAX 256 75162922Sariff#define HDA_BDL_DEFAULT HDA_BDL_MIN 76162922Sariff 77230130Smav#define HDA_BLK_MIN HDA_DMA_ALIGNMENT 78167648Sariff#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1)) 79167648Sariff 80162922Sariff#define HDA_BUFSZ_MIN 4096 81162922Sariff#define HDA_BUFSZ_MAX 65536 82162922Sariff#define HDA_BUFSZ_DEFAULT 16384 83162922Sariff 84230130SmavMALLOC_DEFINE(M_HDAC, "hdac", "HDA Controller"); 85162922Sariff 86162922Sariffstatic const struct { 87162922Sariff uint32_t model; 88162922Sariff char *desc; 89230130Smav char quirks_on; 90230130Smav char quirks_off; 91162922Sariff} hdac_devices[] = { 92230130Smav { HDA_INTEL_CPT, "Intel Cougar Point", 0, 0 }, 93230130Smav { HDA_INTEL_PATSBURG,"Intel Patsburg", 0, 0 }, 94230130Smav { HDA_INTEL_PPT1, "Intel Panther Point", 0, 0 }, 95230130Smav { HDA_INTEL_82801F, "Intel 82801F", 0, 0 }, 96230130Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0, 0 }, 97230130Smav { HDA_INTEL_82801G, "Intel 82801G", 0, 0 }, 98230130Smav { HDA_INTEL_82801H, "Intel 82801H", 0, 0 }, 99230130Smav { HDA_INTEL_82801I, "Intel 82801I", 0, 0 }, 100230130Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0, 0 }, 101230130Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0, 0 }, 102230130Smav { HDA_INTEL_PCH, "Intel 5 Series/3400 Series", 0, 0 }, 103230130Smav { HDA_INTEL_PCH2, "Intel 5 Series/3400 Series", 0, 0 }, 104230130Smav { HDA_INTEL_SCH, "Intel SCH", 0, 0 }, 105230130Smav { HDA_NVIDIA_MCP51, "NVIDIA MCP51", 0, HDAC_QUIRK_MSI }, 106230130Smav { HDA_NVIDIA_MCP55, "NVIDIA MCP55", 0, HDAC_QUIRK_MSI }, 107230130Smav { HDA_NVIDIA_MCP61_1, "NVIDIA MCP61", 0, 0 }, 108230130Smav { HDA_NVIDIA_MCP61_2, "NVIDIA MCP61", 0, 0 }, 109230130Smav { HDA_NVIDIA_MCP65_1, "NVIDIA MCP65", 0, 0 }, 110230130Smav { HDA_NVIDIA_MCP65_2, "NVIDIA MCP65", 0, 0 }, 111230130Smav { HDA_NVIDIA_MCP67_1, "NVIDIA MCP67", 0, 0 }, 112230130Smav { HDA_NVIDIA_MCP67_2, "NVIDIA MCP67", 0, 0 }, 113230130Smav { HDA_NVIDIA_MCP73_1, "NVIDIA MCP73", 0, 0 }, 114230130Smav { HDA_NVIDIA_MCP73_2, "NVIDIA MCP73", 0, 0 }, 115230130Smav { HDA_NVIDIA_MCP78_1, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 116230130Smav { HDA_NVIDIA_MCP78_2, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 117230130Smav { HDA_NVIDIA_MCP78_3, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 118230130Smav { HDA_NVIDIA_MCP78_4, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 119230130Smav { HDA_NVIDIA_MCP79_1, "NVIDIA MCP79", 0, 0 }, 120230130Smav { HDA_NVIDIA_MCP79_2, "NVIDIA MCP79", 0, 0 }, 121230130Smav { HDA_NVIDIA_MCP79_3, "NVIDIA MCP79", 0, 0 }, 122230130Smav { HDA_NVIDIA_MCP79_4, "NVIDIA MCP79", 0, 0 }, 123230130Smav { HDA_NVIDIA_MCP89_1, "NVIDIA MCP89", 0, 0 }, 124230130Smav { HDA_NVIDIA_MCP89_2, "NVIDIA MCP89", 0, 0 }, 125230130Smav { HDA_NVIDIA_MCP89_3, "NVIDIA MCP89", 0, 0 }, 126230130Smav { HDA_NVIDIA_MCP89_4, "NVIDIA MCP89", 0, 0 }, 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 */ 146230130Smav { HDA_INTEL_ALL, "Intel (Unknown)", 0, 0 }, 147230130Smav { HDA_NVIDIA_ALL, "NVIDIA (Unknown)", 0, 0 }, 148230130Smav { HDA_ATI_ALL, "ATI (Unknown)", 0, 0 }, 149230130Smav { HDA_VIA_ALL, "VIA (Unknown)", 0, 0 }, 150230130Smav { HDA_SIS_ALL, "SiS (Unknown)", 0, 0 }, 151230130Smav { HDA_ULI_ALL, "ULI (Unknown)", 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) { 1009162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1010162922Sariff 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) { 1016162922Sariff strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1017162922Sariff result = BUS_PROBE_GENERIC; 1018162922Sariff break; 1019162922Sariff } 1020162922Sariff } 1021162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 1022162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1023162922Sariff strlcpy(desc, "Generic", sizeof(desc)); 1024162922Sariff result = BUS_PROBE_GENERIC; 1025162922Sariff } 1026162922Sariff if (result != ENXIO) { 1027230130Smav strlcat(desc, " HDA Controller", 1028162922Sariff sizeof(desc)); 1029162922Sariff device_set_desc_copy(dev, desc); 1030162922Sariff } 1031162922Sariff 1032162922Sariff return (result); 1033162922Sariff} 1034162922Sariff 1035162922Sariffstatic void 1036171141Sariffhdac_unsolq_task(void *context, int pending) 1037171141Sariff{ 1038171141Sariff struct hdac_softc *sc; 1039171141Sariff 1040171141Sariff sc = (struct hdac_softc *)context; 1041171141Sariff 1042171141Sariff hdac_lock(sc); 1043171141Sariff hdac_unsolq_flush(sc); 1044171141Sariff hdac_unlock(sc); 1045171141Sariff} 1046171141Sariff 1047162922Sariff/**************************************************************************** 1048162922Sariff * int hdac_attach(device_t) 1049162922Sariff * 1050162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 1051162922Sariff * when this function is called. Setup everything that doesn't require 1052162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 1053162922Sariff ****************************************************************************/ 1054162922Sariffstatic int 1055162922Sariffhdac_attach(device_t dev) 1056162922Sariff{ 1057162922Sariff struct hdac_softc *sc; 1058162922Sariff int result; 1059189086Smav int i, devid = -1; 1060189086Smav uint32_t model; 1061189086Smav uint16_t class, subclass; 1062169277Sariff uint16_t vendor; 1063169277Sariff uint8_t v; 1064162922Sariff 1065230130Smav sc = device_get_softc(dev); 1066223118Sjoel HDA_BOOTVERBOSE( 1067223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 1068223118Sjoel HDA_DRV_TEST_REV); 1069223118Sjoel ); 1070182999Smav 1071189086Smav model = (uint32_t)pci_get_device(dev) << 16; 1072189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1073189086Smav class = pci_get_class(dev); 1074189086Smav subclass = pci_get_subclass(dev); 1075189086Smav 1076189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1077189086Smav if (hdac_devices[i].model == model) { 1078189086Smav devid = i; 1079189086Smav break; 1080189086Smav } 1081189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1082189086Smav class == PCIC_MULTIMEDIA && 1083189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 1084189086Smav devid = i; 1085189086Smav break; 1086189086Smav } 1087189086Smav } 1088189086Smav 1089230130Smav sc->lock = snd_mtxcreate(device_get_nameunit(dev), "HDA driver mutex"); 1090162922Sariff sc->dev = dev; 1091230130Smav TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 1092230130Smav callout_init(&sc->poll_callout, CALLOUT_MPSAFE); 1093230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) 1094230130Smav sc->codecs[i].dev = NULL; 1095230130Smav if (devid >= 0) { 1096230130Smav sc->quirks_on = hdac_devices[devid].quirks_on; 1097230130Smav sc->quirks_off = hdac_devices[devid].quirks_off; 1098230130Smav } else { 1099230130Smav sc->quirks_on = 0; 1100230130Smav sc->quirks_off = 0; 1101165281Sariff } 1102169277Sariff if (resource_int_value(device_get_name(dev), 1103230130Smav device_get_unit(dev), "msi", &i) == 0) { 1104230130Smav if (i == 0) 1105230130Smav sc->quirks_off |= HDAC_QUIRK_MSI; 1106230130Smav else { 1107230130Smav sc->quirks_on |= HDAC_QUIRK_MSI; 1108230130Smav sc->quirks_off |= ~HDAC_QUIRK_MSI; 1109230130Smav } 1110230130Smav } 1111230130Smav hdac_config_fetch(sc, &sc->quirks_on, &sc->quirks_off); 1112230130Smav HDA_BOOTVERBOSE( 1113230130Smav device_printf(sc->dev, 1114230130Smav "Config options: on=0x%08x off=0x%08x\n", 1115230130Smav sc->quirks_on, sc->quirks_off); 1116230130Smav ); 1117230130Smav sc->poll_ival = hz; 1118230130Smav if (resource_int_value(device_get_name(dev), 1119169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 1120164614Sariff sc->polling = 1; 1121164614Sariff else 1122164614Sariff sc->polling = 0; 1123164614Sariff 1124162922Sariff pci_enable_busmaster(dev); 1125162922Sariff 1126230130Smav vendor = pci_get_vendor(dev); 1127169277Sariff if (vendor == INTEL_VENDORID) { 1128169277Sariff /* TCSEL -> TC0 */ 1129169277Sariff v = pci_read_config(dev, 0x44, 1); 1130169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 1131183097Smav HDA_BOOTHVERBOSE( 1132169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 1133169277Sariff pci_read_config(dev, 0x44, 1)); 1134169277Sariff ); 1135169277Sariff } 1136169277Sariff 1137169277Sariff#if defined(__i386__) || defined(__amd64__) 1138171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1139169277Sariff 1140169277Sariff if (resource_int_value(device_get_name(dev), 1141169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 1142169277Sariff#else 1143171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1144169277Sariff#endif 1145169277Sariff /* 1146169277Sariff * Try to enable PCIe snoop to avoid messing around with 1147169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 1148169277Sariff * config is pretty much vendor specific, there are no 1149169277Sariff * general solutions on how to enable it, forcing us (even 1150169277Sariff * Microsoft) to enable uncacheable or write combined DMA 1151169277Sariff * by default. 1152169277Sariff * 1153169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 1154169277Sariff */ 1155169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 1156169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 1157169277Sariff continue; 1158171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1159169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 1160169277Sariff break; 1161169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1162169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 1163169277Sariff hdac_pcie_snoop[i].enable) 1164169277Sariff break; 1165169277Sariff v &= hdac_pcie_snoop[i].mask; 1166169277Sariff v |= hdac_pcie_snoop[i].enable; 1167169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 1168169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1169169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 1170169277Sariff hdac_pcie_snoop[i].enable) { 1171169277Sariff HDA_BOOTVERBOSE( 1172169277Sariff device_printf(dev, 1173169277Sariff "WARNING: Failed to enable PCIe " 1174169277Sariff "snoop!\n"); 1175169277Sariff ); 1176169277Sariff#if defined(__i386__) || defined(__amd64__) 1177171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1178169277Sariff#endif 1179169277Sariff } 1180169277Sariff break; 1181169277Sariff } 1182169277Sariff#if defined(__i386__) || defined(__amd64__) 1183169277Sariff } 1184169277Sariff#endif 1185169277Sariff 1186183097Smav HDA_BOOTHVERBOSE( 1187169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 1188171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 1189171330Sariff "Uncacheable" : "PCIe snoop", vendor); 1190169277Sariff ); 1191169277Sariff 1192162922Sariff /* Allocate resources */ 1193162922Sariff result = hdac_mem_alloc(sc); 1194162922Sariff if (result != 0) 1195163057Sariff goto hdac_attach_fail; 1196162922Sariff result = hdac_irq_alloc(sc); 1197162922Sariff if (result != 0) 1198163057Sariff goto hdac_attach_fail; 1199162922Sariff 1200162922Sariff /* Get Capabilities */ 1201162922Sariff result = hdac_get_capabilities(sc); 1202162922Sariff if (result != 0) 1203163057Sariff goto hdac_attach_fail; 1204162922Sariff 1205230130Smav /* Allocate CORB, RIRB, POS and BDLs dma memory */ 1206162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 1207162922Sariff sc->corb_size * sizeof(uint32_t)); 1208162922Sariff if (result != 0) 1209163057Sariff goto hdac_attach_fail; 1210162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 1211162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 1212162922Sariff if (result != 0) 1213163057Sariff goto hdac_attach_fail; 1214230130Smav sc->streams = malloc(sizeof(struct hdac_stream) * sc->num_ss, 1215230130Smav M_HDAC, M_ZERO | M_WAITOK); 1216230130Smav for (i = 0; i < sc->num_ss; i++) { 1217230130Smav result = hdac_dma_alloc(sc, &sc->streams[i].bdl, 1218230130Smav sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1219230130Smav if (result != 0) 1220230130Smav goto hdac_attach_fail; 1221230130Smav } 1222230130Smav if (sc->quirks_on & HDAC_QUIRK_DMAPOS) { 1223230130Smav if (hdac_dma_alloc(sc, &sc->pos_dma, (sc->num_ss) * 8) != 0) { 1224230130Smav HDA_BOOTVERBOSE( 1225230130Smav device_printf(dev, "Failed to " 1226230130Smav "allocate DMA pos buffer " 1227230130Smav "(non-fatal)\n"); 1228230130Smav ); 1229230130Smav } else { 1230230130Smav uint64_t addr = sc->pos_dma.dma_paddr; 1231162922Sariff 1232230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, addr >> 32); 1233230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 1234230130Smav (addr & HDAC_DPLBASE_DPLBASE_MASK) | 1235230130Smav HDAC_DPLBASE_DPLBASE_DMAPBE); 1236230130Smav } 1237230130Smav } 1238230130Smav 1239194861Smav result = bus_dma_tag_create( 1240194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1241230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 1242194861Smav 0, /* boundary */ 1243194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1244194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1245194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 1246194861Smav NULL, /* filtfunc */ 1247194861Smav NULL, /* fistfuncarg */ 1248194861Smav HDA_BUFSZ_MAX, /* maxsize */ 1249194861Smav 1, /* nsegments */ 1250194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 1251194861Smav 0, /* flags */ 1252194861Smav NULL, /* lockfunc */ 1253194861Smav NULL, /* lockfuncarg */ 1254194861Smav &sc->chan_dmat); /* dmat */ 1255194861Smav if (result != 0) { 1256194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 1257194861Smav __func__, result); 1258194861Smav goto hdac_attach_fail; 1259194861Smav } 1260194861Smav 1261162922Sariff /* Quiesce everything */ 1262183097Smav HDA_BOOTHVERBOSE( 1263182999Smav device_printf(dev, "Reset controller...\n"); 1264182999Smav ); 1265182999Smav hdac_reset(sc, 1); 1266162922Sariff 1267162922Sariff /* Initialize the CORB and RIRB */ 1268162922Sariff hdac_corb_init(sc); 1269162922Sariff hdac_rirb_init(sc); 1270162922Sariff 1271162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 1272162922Sariff sc->intrhook.ich_func = hdac_attach2; 1273162922Sariff sc->intrhook.ich_arg = (void *)sc; 1274162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 1275162922Sariff sc->intrhook.ich_func = NULL; 1276162922Sariff hdac_attach2((void *)sc); 1277162922Sariff } 1278162922Sariff 1279163057Sariff return (0); 1280162922Sariff 1281163057Sariffhdac_attach_fail: 1282162922Sariff hdac_irq_free(sc); 1283230130Smav for (i = 0; i < sc->num_ss; i++) 1284230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1285230130Smav free(sc->streams, M_HDAC); 1286169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 1287169277Sariff hdac_dma_free(sc, &sc->corb_dma); 1288162922Sariff hdac_mem_free(sc); 1289162922Sariff snd_mtxfree(sc->lock); 1290162922Sariff 1291163057Sariff return (ENXIO); 1292162922Sariff} 1293162922Sariff 1294230130Smavstatic int 1295230130Smavsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 1296162922Sariff{ 1297230130Smav struct hdac_softc *sc; 1298230130Smav device_t *devlist; 1299230130Smav device_t dev; 1300230130Smav int devcount, i, err, val; 1301162922Sariff 1302230130Smav dev = oidp->oid_arg1; 1303230130Smav sc = device_get_softc(dev); 1304230130Smav if (sc == NULL) 1305230130Smav return (EINVAL); 1306230130Smav val = 0; 1307230130Smav err = sysctl_handle_int(oidp, &val, 0, req); 1308230130Smav if (err != 0 || req->newptr == NULL || val == 0) 1309230130Smav return (err); 1310162922Sariff 1311230130Smav /* XXX: Temporary. For debugging. */ 1312230130Smav if (val == 100) { 1313230130Smav hdac_suspend(dev); 1314182999Smav return (0); 1315230130Smav } else if (val == 101) { 1316230130Smav hdac_resume(dev); 1317182999Smav return (0); 1318182999Smav } 1319162922Sariff 1320230130Smav if ((err = device_get_children(dev, &devlist, &devcount)) != 0) 1321230130Smav return (err); 1322230130Smav hdac_lock(sc); 1323230130Smav for (i = 0; i < devcount; i++) 1324230130Smav HDAC_PINDUMP(devlist[i]); 1325230130Smav hdac_unlock(sc); 1326230130Smav free(devlist, M_TEMP); 1327182999Smav return (0); 1328162922Sariff} 1329162922Sariff 1330183097Smavstatic int 1331230130Smavhdac_data_rate(uint16_t fmt) 1332162922Sariff{ 1333230130Smav static const int bits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 }; 1334230130Smav int rate; 1335162922Sariff 1336230130Smav if (fmt & (1 << 14)) 1337230130Smav rate = 44100; 1338230130Smav else 1339230130Smav rate = 48000; 1340230130Smav rate *= ((fmt >> 11) & 0x07) + 1; 1341230130Smav rate /= ((fmt >> 8) & 0x07) + 1; 1342230130Smav rate *= ((bits[(fmt >> 4) & 0x03]) * ((fmt & 0x0f) + 1) + 7) / 8; 1343230130Smav return (rate); 1344182999Smav} 1345182999Smav 1346182999Smavstatic void 1347230130Smavhdac_poll_reinit(struct hdac_softc *sc) 1348182999Smav{ 1349230130Smav int i, pollticks, min = 1000000; 1350230130Smav struct hdac_stream *s; 1351182999Smav 1352230130Smav if (sc->polling == 0) 1353230130Smav return; 1354230130Smav if (sc->unsol_registered > 0) 1355230130Smav min = hz / 2; 1356230130Smav for (i = 0; i < sc->num_ss; i++) { 1357230130Smav s = &sc->streams[i]; 1358230130Smav if (s->running == 0) 1359182999Smav continue; 1360230130Smav pollticks = ((uint64_t)hz * s->blksz) / 1361230130Smav hdac_data_rate(s->format); 1362230130Smav pollticks >>= 1; 1363230130Smav if (pollticks > hz) 1364230130Smav pollticks = hz; 1365230130Smav if (pollticks < 1) { 1366182999Smav HDA_BOOTVERBOSE( 1367230130Smav device_printf(sc->dev, 1368230130Smav "poll interval < 1 tick !\n"); 1369182999Smav ); 1370230130Smav pollticks = 1; 1371162922Sariff } 1372230130Smav if (min > pollticks) 1373230130Smav min = pollticks; 1374162922Sariff } 1375202789Smav HDA_BOOTVERBOSE( 1376230130Smav device_printf(sc->dev, 1377230130Smav "poll interval %d -> %d ticks\n", 1378230130Smav sc->poll_ival, min); 1379202789Smav ); 1380230130Smav sc->poll_ival = min; 1381230130Smav if (min == 1000000) 1382230130Smav callout_stop(&sc->poll_callout); 1383182999Smav else 1384230130Smav callout_reset(&sc->poll_callout, 1, hdac_poll_callback, sc); 1385163057Sariff} 1386163057Sariff 1387164614Sariffstatic int 1388164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 1389164614Sariff{ 1390164614Sariff struct hdac_softc *sc; 1391164614Sariff device_t dev; 1392164614Sariff uint32_t ctl; 1393164614Sariff int err, val; 1394164614Sariff 1395164614Sariff dev = oidp->oid_arg1; 1396182999Smav sc = device_get_softc(dev); 1397182999Smav if (sc == NULL) 1398164614Sariff return (EINVAL); 1399164614Sariff hdac_lock(sc); 1400164614Sariff val = sc->polling; 1401164614Sariff hdac_unlock(sc); 1402170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 1403164614Sariff 1404169277Sariff if (err != 0 || req->newptr == NULL) 1405164614Sariff return (err); 1406164614Sariff if (val < 0 || val > 1) 1407164614Sariff return (EINVAL); 1408164614Sariff 1409164614Sariff hdac_lock(sc); 1410164614Sariff if (val != sc->polling) { 1411182999Smav if (val == 0) { 1412230130Smav callout_stop(&sc->poll_callout); 1413169277Sariff hdac_unlock(sc); 1414230130Smav callout_drain(&sc->poll_callout); 1415169277Sariff hdac_lock(sc); 1416164614Sariff sc->polling = 0; 1417182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1418182999Smav ctl |= HDAC_INTCTL_GIE; 1419182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1420164614Sariff } else { 1421182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1422182999Smav ctl &= ~HDAC_INTCTL_GIE; 1423182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1424164614Sariff sc->polling = 1; 1425182999Smav hdac_poll_reinit(sc); 1426164614Sariff } 1427164614Sariff } 1428164614Sariff hdac_unlock(sc); 1429164614Sariff 1430164614Sariff return (err); 1431164614Sariff} 1432169277Sariff 1433163057Sariffstatic void 1434162922Sariffhdac_attach2(void *arg) 1435162922Sariff{ 1436162922Sariff struct hdac_softc *sc; 1437230130Smav device_t child; 1438230130Smav uint32_t vendorid, revisionid; 1439230130Smav int i; 1440230130Smav uint16_t statests; 1441162922Sariff 1442162922Sariff sc = (struct hdac_softc *)arg; 1443162922Sariff 1444162922Sariff hdac_lock(sc); 1445162922Sariff 1446162922Sariff /* Remove ourselves from the config hooks */ 1447162922Sariff if (sc->intrhook.ich_func != NULL) { 1448162922Sariff config_intrhook_disestablish(&sc->intrhook); 1449162922Sariff sc->intrhook.ich_func = NULL; 1450162922Sariff } 1451162922Sariff 1452183097Smav HDA_BOOTHVERBOSE( 1453182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 1454162922Sariff ); 1455162922Sariff hdac_corb_start(sc); 1456183097Smav HDA_BOOTHVERBOSE( 1457182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 1458162922Sariff ); 1459162922Sariff hdac_rirb_start(sc); 1460183097Smav HDA_BOOTHVERBOSE( 1461162922Sariff device_printf(sc->dev, 1462182999Smav "Enabling controller interrupt...\n"); 1463162922Sariff ); 1464182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1465182999Smav HDAC_GCTL_UNSOL); 1466182999Smav if (sc->polling == 0) { 1467164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 1468164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1469182999Smav } 1470162922Sariff DELAY(1000); 1471162922Sariff 1472183097Smav HDA_BOOTHVERBOSE( 1473230130Smav device_printf(sc->dev, "Scanning HDA codecs ...\n"); 1474162922Sariff ); 1475230130Smav statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1476230130Smav hdac_unlock(sc); 1477230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1478230130Smav if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1479230130Smav HDA_BOOTHVERBOSE( 1480183097Smav device_printf(sc->dev, 1481230130Smav "Found CODEC at address %d\n", i); 1482183019Smav ); 1483230130Smav hdac_lock(sc); 1484230130Smav vendorid = hdac_send_command(sc, i, 1485230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_VENDOR_ID)); 1486230130Smav revisionid = hdac_send_command(sc, i, 1487230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_REVISION_ID)); 1488230130Smav hdac_unlock(sc); 1489230130Smav if (vendorid == HDA_INVALID && 1490230130Smav revisionid == HDA_INVALID) { 1491230130Smav device_printf(sc->dev, 1492230130Smav "CODEC is not responding!\n"); 1493182999Smav continue; 1494182999Smav } 1495230130Smav sc->codecs[i].vendor_id = 1496230130Smav HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1497230130Smav sc->codecs[i].device_id = 1498230130Smav HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1499230130Smav sc->codecs[i].revision_id = 1500230130Smav HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1501230130Smav sc->codecs[i].stepping_id = 1502230130Smav HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1503230130Smav child = device_add_child(sc->dev, "hdacc", -1); 1504230130Smav if (child == NULL) { 1505230130Smav device_printf(sc->dev, 1506230130Smav "Failed to add CODEC device\n"); 1507230130Smav continue; 1508182999Smav } 1509230130Smav device_set_ivars(child, (void *)(intptr_t)i); 1510230130Smav sc->codecs[i].dev = child; 1511182999Smav } 1512162922Sariff } 1513182999Smav bus_generic_attach(sc->dev); 1514182999Smav 1515182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1516182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1517230130Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1518230130Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 1519230130Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1520230130Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1521182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1522182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 1523182999Smav} 1524182999Smav 1525182999Smav/**************************************************************************** 1526182999Smav * int hdac_suspend(device_t) 1527182999Smav * 1528182999Smav * Suspend and power down HDA bus and codecs. 1529182999Smav ****************************************************************************/ 1530182999Smavstatic int 1531182999Smavhdac_suspend(device_t dev) 1532182999Smav{ 1533230130Smav struct hdac_softc *sc = device_get_softc(dev); 1534182999Smav 1535183097Smav HDA_BOOTHVERBOSE( 1536182999Smav device_printf(dev, "Suspend...\n"); 1537162922Sariff ); 1538230130Smav bus_generic_suspend(dev); 1539182999Smav 1540182999Smav hdac_lock(sc); 1541183097Smav HDA_BOOTHVERBOSE( 1542182999Smav device_printf(dev, "Reset controller...\n"); 1543162922Sariff ); 1544182999Smav hdac_reset(sc, 0); 1545182999Smav hdac_unlock(sc); 1546182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1547183097Smav HDA_BOOTHVERBOSE( 1548182999Smav device_printf(dev, "Suspend done\n"); 1549162922Sariff ); 1550182999Smav return (0); 1551182999Smav} 1552182999Smav 1553182999Smav/**************************************************************************** 1554182999Smav * int hdac_resume(device_t) 1555182999Smav * 1556182999Smav * Powerup and restore HDA bus and codecs state. 1557182999Smav ****************************************************************************/ 1558182999Smavstatic int 1559182999Smavhdac_resume(device_t dev) 1560182999Smav{ 1561230130Smav struct hdac_softc *sc = device_get_softc(dev); 1562230130Smav int error; 1563182999Smav 1564183097Smav HDA_BOOTHVERBOSE( 1565182999Smav device_printf(dev, "Resume...\n"); 1566162922Sariff ); 1567182999Smav hdac_lock(sc); 1568182999Smav 1569182999Smav /* Quiesce everything */ 1570183097Smav HDA_BOOTHVERBOSE( 1571182999Smav device_printf(dev, "Reset controller...\n"); 1572162922Sariff ); 1573182999Smav hdac_reset(sc, 1); 1574182999Smav 1575182999Smav /* Initialize the CORB and RIRB */ 1576182999Smav hdac_corb_init(sc); 1577182999Smav hdac_rirb_init(sc); 1578182999Smav 1579183097Smav HDA_BOOTHVERBOSE( 1580182999Smav device_printf(dev, "Starting CORB Engine...\n"); 1581162922Sariff ); 1582182999Smav hdac_corb_start(sc); 1583183097Smav HDA_BOOTHVERBOSE( 1584182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 1585162922Sariff ); 1586182999Smav hdac_rirb_start(sc); 1587183097Smav HDA_BOOTHVERBOSE( 1588230130Smav device_printf(dev, "Enabling controller interrupt...\n"); 1589162922Sariff ); 1590182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1591182999Smav HDAC_GCTL_UNSOL); 1592230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1593182999Smav DELAY(1000); 1594182999Smav hdac_unlock(sc); 1595182999Smav 1596230130Smav error = bus_generic_resume(dev); 1597183097Smav HDA_BOOTHVERBOSE( 1598182999Smav device_printf(dev, "Resume done\n"); 1599162922Sariff ); 1600230130Smav return (error); 1601230130Smav} 1602164614Sariff 1603162922Sariff/**************************************************************************** 1604162922Sariff * int hdac_detach(device_t) 1605162922Sariff * 1606162922Sariff * Detach and free up resources utilized by the hdac device. 1607162922Sariff ****************************************************************************/ 1608162922Sariffstatic int 1609162922Sariffhdac_detach(device_t dev) 1610162922Sariff{ 1611230130Smav struct hdac_softc *sc = device_get_softc(dev); 1612185177Smav device_t *devlist; 1613230130Smav int cad, i, devcount, error; 1614162922Sariff 1615185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 1616185177Smav return (error); 1617185177Smav for (i = 0; i < devcount; i++) { 1618230130Smav cad = (intptr_t)device_get_ivars(devlist[i]); 1619185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 1620185178Smav free(devlist, M_TEMP); 1621185178Smav return (error); 1622185178Smav } 1623230130Smav sc->codecs[cad].dev = NULL; 1624185177Smav } 1625185177Smav free(devlist, M_TEMP); 1626185177Smav 1627230130Smav hdac_lock(sc); 1628230130Smav hdac_reset(sc, 0); 1629230130Smav hdac_unlock(sc); 1630230130Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1631230130Smav hdac_irq_free(sc); 1632162922Sariff 1633230130Smav for (i = 0; i < sc->num_ss; i++) 1634230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1635230130Smav free(sc->streams, M_HDAC); 1636230130Smav hdac_dma_free(sc, &sc->pos_dma); 1637230130Smav hdac_dma_free(sc, &sc->rirb_dma); 1638230130Smav hdac_dma_free(sc, &sc->corb_dma); 1639230130Smav if (sc->chan_dmat != NULL) { 1640230130Smav bus_dma_tag_destroy(sc->chan_dmat); 1641230130Smav sc->chan_dmat = NULL; 1642230130Smav } 1643230130Smav hdac_mem_free(sc); 1644230130Smav snd_mtxfree(sc->lock); 1645162922Sariff return (0); 1646162922Sariff} 1647162922Sariff 1648230130Smavstatic bus_dma_tag_t 1649230130Smavhdac_get_dma_tag(device_t dev, device_t child) 1650230130Smav{ 1651230130Smav struct hdac_softc *sc = device_get_softc(dev); 1652230130Smav 1653230130Smav return (sc->chan_dmat); 1654230130Smav} 1655230130Smav 1656184095Smavstatic int 1657184095Smavhdac_print_child(device_t dev, device_t child) 1658184095Smav{ 1659184095Smav int retval; 1660184095Smav 1661184095Smav retval = bus_print_child_header(dev, child); 1662230130Smav retval += printf(" at cad %d", 1663230130Smav (int)(intptr_t)device_get_ivars(child)); 1664184095Smav retval += bus_print_child_footer(dev, child); 1665184095Smav 1666184095Smav return (retval); 1667184095Smav} 1668184095Smav 1669230130Smavstatic int 1670230130Smavhdac_child_location_str(device_t dev, device_t child, char *buf, 1671230130Smav size_t buflen) 1672230130Smav{ 1673162922Sariff 1674230130Smav snprintf(buf, buflen, "cad=%d", 1675230130Smav (int)(intptr_t)device_get_ivars(child)); 1676230130Smav return (0); 1677230130Smav} 1678162922Sariff 1679230130Smavstatic int 1680230130Smavhdac_child_pnpinfo_str_method(device_t dev, device_t child, char *buf, 1681230130Smav size_t buflen) 1682230130Smav{ 1683230130Smav struct hdac_softc *sc = device_get_softc(dev); 1684230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1685182999Smav 1686230130Smav snprintf(buf, buflen, "vendor=0x%04x device=0x%04x revision=0x%02x " 1687230130Smav "stepping=0x%02x", 1688230130Smav sc->codecs[cad].vendor_id, sc->codecs[cad].device_id, 1689230130Smav sc->codecs[cad].revision_id, sc->codecs[cad].stepping_id); 1690230130Smav return (0); 1691230130Smav} 1692182999Smav 1693182999Smavstatic int 1694230130Smavhdac_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1695182999Smav{ 1696230130Smav struct hdac_softc *sc = device_get_softc(dev); 1697230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1698182999Smav 1699230130Smav switch (which) { 1700230130Smav case HDA_IVAR_CODEC_ID: 1701230130Smav *result = cad; 1702230130Smav break; 1703230130Smav case HDA_IVAR_VENDOR_ID: 1704230130Smav *result = sc->codecs[cad].vendor_id; 1705230130Smav break; 1706230130Smav case HDA_IVAR_DEVICE_ID: 1707230130Smav *result = sc->codecs[cad].device_id; 1708230130Smav break; 1709230130Smav case HDA_IVAR_REVISION_ID: 1710230130Smav *result = sc->codecs[cad].revision_id; 1711230130Smav break; 1712230130Smav case HDA_IVAR_STEPPING_ID: 1713230130Smav *result = sc->codecs[cad].stepping_id; 1714230130Smav break; 1715230130Smav case HDA_IVAR_SUBVENDOR_ID: 1716230130Smav *result = pci_get_subvendor(dev); 1717230130Smav break; 1718230130Smav case HDA_IVAR_SUBDEVICE_ID: 1719230130Smav *result = pci_get_subdevice(dev); 1720230130Smav break; 1721230130Smav case HDA_IVAR_DMA_NOCACHE: 1722230130Smav *result = (sc->flags & HDAC_F_DMA_NOCACHE) != 0; 1723230130Smav break; 1724230130Smav default: 1725230130Smav return (ENOENT); 1726230130Smav } 1727182999Smav return (0); 1728182999Smav} 1729182999Smav 1730230130Smavstatic struct mtx * 1731230130Smavhdac_get_mtx(device_t dev, device_t child) 1732182999Smav{ 1733230130Smav struct hdac_softc *sc = device_get_softc(dev); 1734182999Smav 1735230130Smav return (sc->lock); 1736230130Smav} 1737182999Smav 1738230130Smavstatic uint32_t 1739230130Smavhdac_codec_command(device_t dev, device_t child, uint32_t verb) 1740230130Smav{ 1741182999Smav 1742230130Smav return (hdac_send_command(device_get_softc(dev), 1743230130Smav (intptr_t)device_get_ivars(child), verb)); 1744230130Smav} 1745182999Smav 1746230130Smavstatic int 1747230130Smavhdac_find_stream(struct hdac_softc *sc, int dir, int stream) 1748230130Smav{ 1749230130Smav int i, ss; 1750182999Smav 1751230130Smav ss = -1; 1752230130Smav /* Allocate ISS/BSS first. */ 1753230130Smav if (dir == 0) { 1754230130Smav for (i = 0; i < sc->num_iss; i++) { 1755230130Smav if (sc->streams[i].stream == stream) { 1756230130Smav ss = i; 1757230130Smav break; 1758230130Smav } 1759230130Smav } 1760230130Smav } else { 1761230130Smav for (i = 0; i < sc->num_oss; i++) { 1762230130Smav if (sc->streams[i + sc->num_iss].stream == stream) { 1763230130Smav ss = i + sc->num_iss; 1764230130Smav break; 1765230130Smav } 1766230130Smav } 1767230130Smav } 1768230130Smav /* Fallback to BSS. */ 1769230130Smav if (ss == -1) { 1770230130Smav for (i = 0; i < sc->num_bss; i++) { 1771230130Smav if (sc->streams[i + sc->num_iss + sc->num_oss].stream 1772230130Smav == stream) { 1773230130Smav ss = i + sc->num_iss + sc->num_oss; 1774230130Smav break; 1775230130Smav } 1776230130Smav } 1777230130Smav } 1778230130Smav return (ss); 1779230130Smav} 1780182999Smav 1781230130Smavstatic int 1782230130Smavhdac_stream_alloc(device_t dev, device_t child, int dir, int format, 1783230130Smav uint32_t **dmapos) 1784230130Smav{ 1785230130Smav struct hdac_softc *sc = device_get_softc(dev); 1786230130Smav int stream, ss; 1787182999Smav 1788230130Smav /* Look for empty stream. */ 1789230130Smav ss = hdac_find_stream(sc, dir, 0); 1790182999Smav 1791230130Smav /* Return if found nothing. */ 1792230130Smav if (ss < 0) 1793230130Smav return (0); 1794182999Smav 1795230130Smav /* Allocate stream number */ 1796230130Smav if (ss >= sc->num_iss + sc->num_oss) 1797230130Smav stream = 15 - (ss - sc->num_iss + sc->num_oss); 1798230130Smav else if (ss >= sc->num_iss) 1799230130Smav stream = ss - sc->num_iss + 1; 1800230130Smav else 1801230130Smav stream = ss + 1; 1802182999Smav 1803230130Smav sc->streams[ss].dev = child; 1804230130Smav sc->streams[ss].dir = dir; 1805230130Smav sc->streams[ss].stream = stream; 1806230130Smav sc->streams[ss].format = format; 1807230130Smav if (dmapos != NULL) { 1808230130Smav if (sc->pos_dma.dma_vaddr != NULL) 1809230130Smav *dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8); 1810230130Smav else 1811230130Smav *dmapos = NULL; 1812230130Smav } 1813230130Smav return (stream); 1814182999Smav} 1815182999Smav 1816230130Smavstatic void 1817230130Smavhdac_stream_free(device_t dev, device_t child, int dir, int stream) 1818230130Smav{ 1819230130Smav struct hdac_softc *sc = device_get_softc(dev); 1820230130Smav int ss; 1821230130Smav 1822230130Smav ss = hdac_find_stream(sc, dir, stream); 1823230130Smav KASSERT(ss >= 0, 1824230130Smav ("Free for not allocated stream (%d/%d)\n", dir, stream)); 1825230130Smav sc->streams[ss].stream = 0; 1826230130Smav sc->streams[ss].dev = NULL; 1827230130Smav} 1828230130Smav 1829182999Smavstatic int 1830230130Smavhdac_stream_start(device_t dev, device_t child, 1831230130Smav int dir, int stream, bus_addr_t buf, int blksz, int blkcnt) 1832182999Smav{ 1833230130Smav struct hdac_softc *sc = device_get_softc(dev); 1834230130Smav struct hdac_bdle *bdle; 1835230130Smav uint64_t addr; 1836230130Smav int i, ss, off; 1837230130Smav uint32_t ctl; 1838182999Smav 1839230130Smav ss = hdac_find_stream(sc, dir, stream); 1840230130Smav KASSERT(ss >= 0, 1841230130Smav ("Start for not allocated stream (%d/%d)\n", dir, stream)); 1842230130Smav 1843230130Smav addr = (uint64_t)buf; 1844230130Smav bdle = (struct hdac_bdle *)sc->streams[ss].bdl.dma_vaddr; 1845230130Smav for (i = 0; i < blkcnt; i++, bdle++) { 1846230130Smav bdle->addrl = (uint32_t)addr; 1847230130Smav bdle->addrh = (uint32_t)(addr >> 32); 1848230130Smav bdle->len = blksz; 1849230130Smav bdle->ioc = 1; 1850230130Smav addr += blksz; 1851182999Smav } 1852182999Smav 1853230130Smav off = ss << 5; 1854230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDCBL, blksz * blkcnt); 1855230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDLVI, blkcnt - 1); 1856230130Smav addr = sc->streams[ss].bdl.dma_paddr; 1857230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPL, (uint32_t)addr); 1858230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1859230130Smav 1860230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL2); 1861230130Smav if (dir) 1862230130Smav ctl |= HDAC_SDCTL2_DIR; 1863230130Smav else 1864230130Smav ctl &= ~HDAC_SDCTL2_DIR; 1865230130Smav ctl &= ~HDAC_SDCTL2_STRM_MASK; 1866230130Smav ctl |= stream << HDAC_SDCTL2_STRM_SHIFT; 1867230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl); 1868230130Smav 1869230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format); 1870230130Smav 1871230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1872230130Smav ctl |= 1 << ss; 1873230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1874230130Smav 1875230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1876230130Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1877230130Smav HDAC_SDCTL_RUN; 1878230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1879230130Smav 1880230130Smav sc->streams[ss].blksz = blksz; 1881230130Smav sc->streams[ss].running = 1; 1882230130Smav hdac_poll_reinit(sc); 1883182999Smav return (0); 1884182999Smav} 1885182999Smav 1886230130Smavstatic void 1887230130Smavhdac_stream_stop(device_t dev, device_t child, int dir, int stream) 1888230130Smav{ 1889230130Smav struct hdac_softc *sc = device_get_softc(dev); 1890230130Smav int ss, off; 1891230130Smav uint32_t ctl; 1892230130Smav 1893230130Smav ss = hdac_find_stream(sc, dir, stream); 1894230130Smav KASSERT(ss >= 0, 1895230130Smav ("Stop for not allocated stream (%d/%d)\n", dir, stream)); 1896230130Smav 1897230130Smav off = ss << 5; 1898230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1899230130Smav ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1900230130Smav HDAC_SDCTL_RUN); 1901230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1902230130Smav 1903230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1904230130Smav ctl &= ~(1 << ss); 1905230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1906230130Smav 1907230130Smav sc->streams[ss].running = 0; 1908230130Smav hdac_poll_reinit(sc); 1909230130Smav} 1910230130Smav 1911230130Smavstatic void 1912230130Smavhdac_stream_reset(device_t dev, device_t child, int dir, int stream) 1913230130Smav{ 1914230130Smav struct hdac_softc *sc = device_get_softc(dev); 1915230130Smav int timeout = 1000; 1916230130Smav int to = timeout; 1917230130Smav int ss, off; 1918230130Smav uint32_t ctl; 1919230130Smav 1920230130Smav ss = hdac_find_stream(sc, dir, stream); 1921230130Smav KASSERT(ss >= 0, 1922230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 1923230130Smav 1924230130Smav off = ss << 5; 1925230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1926230130Smav ctl |= HDAC_SDCTL_SRST; 1927230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1928230130Smav do { 1929230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1930230130Smav if (ctl & HDAC_SDCTL_SRST) 1931230130Smav break; 1932230130Smav DELAY(10); 1933230130Smav } while (--to); 1934230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 1935230130Smav device_printf(dev, "Reset setting timeout\n"); 1936230130Smav ctl &= ~HDAC_SDCTL_SRST; 1937230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1938230130Smav to = timeout; 1939230130Smav do { 1940230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1941230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 1942230130Smav break; 1943230130Smav DELAY(10); 1944230130Smav } while (--to); 1945230130Smav if (ctl & HDAC_SDCTL_SRST) 1946230130Smav device_printf(dev, "Reset timeout!\n"); 1947230130Smav} 1948230130Smav 1949230130Smavstatic uint32_t 1950230130Smavhdac_stream_getptr(device_t dev, device_t child, int dir, int stream) 1951230130Smav{ 1952230130Smav struct hdac_softc *sc = device_get_softc(dev); 1953230130Smav int ss, off; 1954230130Smav 1955230130Smav ss = hdac_find_stream(sc, dir, stream); 1956230130Smav KASSERT(ss >= 0, 1957230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 1958230130Smav 1959230130Smav off = ss << 5; 1960230130Smav return (HDAC_READ_4(&sc->mem, off + HDAC_SDLPIB)); 1961230130Smav} 1962230130Smav 1963230130Smavstatic int 1964230130Smavhdac_unsol_alloc(device_t dev, device_t child, int tag) 1965230130Smav{ 1966230130Smav struct hdac_softc *sc = device_get_softc(dev); 1967230130Smav 1968230130Smav sc->unsol_registered++; 1969230130Smav hdac_poll_reinit(sc); 1970230130Smav return (tag); 1971230130Smav} 1972230130Smav 1973230130Smavstatic void 1974230130Smavhdac_unsol_free(device_t dev, device_t child, int tag) 1975230130Smav{ 1976230130Smav struct hdac_softc *sc = device_get_softc(dev); 1977230130Smav 1978230130Smav sc->unsol_registered--; 1979230130Smav hdac_poll_reinit(sc); 1980230130Smav} 1981230130Smav 1982230130Smavstatic device_method_t hdac_methods[] = { 1983182999Smav /* device interface */ 1984230130Smav DEVMETHOD(device_probe, hdac_probe), 1985230130Smav DEVMETHOD(device_attach, hdac_attach), 1986230130Smav DEVMETHOD(device_detach, hdac_detach), 1987230130Smav DEVMETHOD(device_suspend, hdac_suspend), 1988230130Smav DEVMETHOD(device_resume, hdac_resume), 1989230130Smav /* Bus interface */ 1990230130Smav DEVMETHOD(bus_get_dma_tag, hdac_get_dma_tag), 1991230130Smav DEVMETHOD(bus_print_child, hdac_print_child), 1992230130Smav DEVMETHOD(bus_child_location_str, hdac_child_location_str), 1993230130Smav DEVMETHOD(bus_child_pnpinfo_str, hdac_child_pnpinfo_str_method), 1994230130Smav DEVMETHOD(bus_read_ivar, hdac_read_ivar), 1995230130Smav DEVMETHOD(hdac_get_mtx, hdac_get_mtx), 1996230130Smav DEVMETHOD(hdac_codec_command, hdac_codec_command), 1997230130Smav DEVMETHOD(hdac_stream_alloc, hdac_stream_alloc), 1998230130Smav DEVMETHOD(hdac_stream_free, hdac_stream_free), 1999230130Smav DEVMETHOD(hdac_stream_start, hdac_stream_start), 2000230130Smav DEVMETHOD(hdac_stream_stop, hdac_stream_stop), 2001230130Smav DEVMETHOD(hdac_stream_reset, hdac_stream_reset), 2002230130Smav DEVMETHOD(hdac_stream_getptr, hdac_stream_getptr), 2003230130Smav DEVMETHOD(hdac_unsol_alloc, hdac_unsol_alloc), 2004230130Smav DEVMETHOD(hdac_unsol_free, hdac_unsol_free), 2005182999Smav { 0, 0 } 2006182999Smav}; 2007182999Smav 2008230130Smavstatic driver_t hdac_driver = { 2009230130Smav "hdac", 2010230130Smav hdac_methods, 2011230130Smav sizeof(struct hdac_softc), 2012182999Smav}; 2013182999Smav 2014230130Smavstatic devclass_t hdac_devclass; 2015182999Smav 2016230130SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 2017