hdac.c revision 239908
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 239908 2012-08-30 15:47:20Z 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 }, 141239908Smav { HDA_ATI_RV810, "ATI RV810", 0, 0 }, 142239908Smav { HDA_ATI_RV830, "ATI RV830", 0, 0 }, 143239908Smav { HDA_ATI_RV840, "ATI RV840", 0, 0 }, 144239908Smav { HDA_ATI_RV870, "ATI RV870", 0, 0 }, 145239908Smav { HDA_ATI_RV910, "ATI RV910", 0, 0 }, 146239908Smav { HDA_ATI_RV930, "ATI RV930", 0, 0 }, 147239908Smav { HDA_ATI_RV940, "ATI RV940", 0, 0 }, 148239908Smav { HDA_ATI_RV970, "ATI RV970", 0, 0 }, 149239908Smav { HDA_ATI_R1000, "ATI R1000", 0, 0 }, 150230130Smav { HDA_RDC_M3010, "RDC M3010", 0, 0 }, 151230130Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 }, 152230130Smav { HDA_SIS_966, "SiS 966", 0, 0 }, 153230130Smav { HDA_ULI_M5461, "ULI M5461", 0, 0 }, 154162922Sariff /* Unknown */ 155230331Smav { HDA_INTEL_ALL, "Intel", 0, 0 }, 156230331Smav { HDA_NVIDIA_ALL, "NVIDIA", 0, 0 }, 157230331Smav { HDA_ATI_ALL, "ATI", 0, 0 }, 158230331Smav { HDA_VIA_ALL, "VIA", 0, 0 }, 159230331Smav { HDA_SIS_ALL, "SiS", 0, 0 }, 160230331Smav { HDA_ULI_ALL, "ULI", 0, 0 }, 161162922Sariff}; 162162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 163162922Sariff 164162922Sariffstatic const struct { 165169277Sariff uint16_t vendor; 166169277Sariff uint8_t reg; 167169277Sariff uint8_t mask; 168169277Sariff uint8_t enable; 169169277Sariff} hdac_pcie_snoop[] = { 170169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 171169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 172169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 173169277Sariff}; 174169277Sariff#define HDAC_PCIESNOOP_LEN \ 175169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 176169277Sariff 177162922Sariff/**************************************************************************** 178162922Sariff * Function prototypes 179162922Sariff ****************************************************************************/ 180162922Sariffstatic void hdac_intr_handler(void *); 181182999Smavstatic int hdac_reset(struct hdac_softc *, int); 182162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 183162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 184162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 185162922Sariff struct hdac_dma *, bus_size_t); 186169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 187162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 188162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 189162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 190162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 191162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 192162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 193162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 194162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 195162922Sariff 196162922Sariffstatic void hdac_attach2(void *); 197162922Sariff 198230130Smavstatic uint32_t hdac_send_command(struct hdac_softc *, nid_t, uint32_t); 199162922Sariff 200162922Sariffstatic int hdac_probe(device_t); 201162922Sariffstatic int hdac_attach(device_t); 202162922Sariffstatic int hdac_detach(device_t); 203182999Smavstatic int hdac_suspend(device_t); 204182999Smavstatic int hdac_resume(device_t); 205162922Sariff 206164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 207164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 208164614Sariff 209162922Sariff#define hdac_command(a1, a2, a3) \ 210230130Smav hdac_send_command(a1, a3, a2) 211162922Sariff 212230130Smav/* This function surely going to make its way into upper level someday. */ 213162922Sariffstatic void 214230130Smavhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 215162922Sariff{ 216230130Smav const char *res = NULL; 217230130Smav int i = 0, j, k, len, inv; 218162922Sariff 219230130Smav if (resource_string_value(device_get_name(sc->dev), 220230130Smav device_get_unit(sc->dev), "config", &res) != 0) 221162922Sariff return; 222230130Smav if (!(res != NULL && strlen(res) > 0)) 223230130Smav return; 224230130Smav HDA_BOOTVERBOSE( 225230130Smav device_printf(sc->dev, "Config options:"); 226230130Smav ); 227230130Smav for (;;) { 228230130Smav while (res[i] != '\0' && 229230130Smav (res[i] == ',' || isspace(res[i]) != 0)) 230230130Smav i++; 231230130Smav if (res[i] == '\0') { 232230130Smav HDA_BOOTVERBOSE( 233230130Smav printf("\n"); 234230130Smav ); 235230130Smav return; 236182999Smav } 237230130Smav j = i; 238230130Smav while (res[j] != '\0' && 239230130Smav !(res[j] == ',' || isspace(res[j]) != 0)) 240230130Smav j++; 241230130Smav len = j - i; 242230130Smav if (len > 2 && strncmp(res + i, "no", 2) == 0) 243230130Smav inv = 2; 244230130Smav else 245230130Smav inv = 0; 246230130Smav for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 247230130Smav if (strncmp(res + i + inv, 248230130Smav hdac_quirks_tab[k].key, len - inv) != 0) 249182999Smav continue; 250230130Smav if (len - inv != strlen(hdac_quirks_tab[k].key)) 251182999Smav continue; 252230130Smav HDA_BOOTVERBOSE( 253230130Smav printf(" %s%s", (inv != 0) ? "no" : "", 254230130Smav hdac_quirks_tab[k].key); 255230130Smav ); 256230130Smav if (inv == 0) { 257230130Smav *on |= hdac_quirks_tab[k].value; 258230130Smav *on &= ~hdac_quirks_tab[k].value; 259230130Smav } else if (inv != 0) { 260230130Smav *off |= hdac_quirks_tab[k].value; 261230130Smav *off &= ~hdac_quirks_tab[k].value; 262162922Sariff } 263162965Sariff break; 264182999Smav } 265230130Smav i = j; 266162922Sariff } 267162922Sariff} 268162922Sariff 269162922Sariff/**************************************************************************** 270162922Sariff * void hdac_intr_handler(void *) 271162922Sariff * 272162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 273162922Sariff ****************************************************************************/ 274162922Sariffstatic void 275162922Sariffhdac_intr_handler(void *context) 276162922Sariff{ 277162922Sariff struct hdac_softc *sc; 278230130Smav device_t dev; 279162922Sariff uint32_t intsts; 280162922Sariff uint8_t rirbsts; 281182999Smav int i; 282162922Sariff 283162922Sariff sc = (struct hdac_softc *)context; 284162922Sariff hdac_lock(sc); 285171141Sariff 286162922Sariff /* Do we have anything to do? */ 287162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 288230130Smav if ((intsts & HDAC_INTSTS_GIS) == 0) { 289162922Sariff hdac_unlock(sc); 290162922Sariff return; 291162922Sariff } 292162922Sariff 293162922Sariff /* Was this a controller interrupt? */ 294230130Smav if (intsts & HDAC_INTSTS_CIS) { 295162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 296162922Sariff /* Get as many responses that we can */ 297230130Smav while (rirbsts & HDAC_RIRBSTS_RINTFL) { 298164614Sariff HDAC_WRITE_1(&sc->mem, 299164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 300230130Smav hdac_rirb_flush(sc); 301162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 302162922Sariff } 303230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 304230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 305162922Sariff } 306164614Sariff 307163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 308230130Smav for (i = 0; i < sc->num_ss; i++) { 309230130Smav if ((intsts & (1 << i)) == 0) 310230130Smav continue; 311230130Smav HDAC_WRITE_1(&sc->mem, (i << 5) + HDAC_SDSTS, 312230130Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 313230130Smav if ((dev = sc->streams[i].dev) != NULL) { 314230130Smav HDAC_STREAM_INTR(dev, 315230130Smav sc->streams[i].dir, sc->streams[i].stream); 316230130Smav } 317182999Smav } 318162922Sariff } 319162922Sariff 320230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts); 321164614Sariff hdac_unlock(sc); 322230130Smav} 323162922Sariff 324230130Smavstatic void 325230130Smavhdac_poll_callback(void *arg) 326230130Smav{ 327230130Smav struct hdac_softc *sc = arg; 328230130Smav 329230130Smav if (sc == NULL) 330230130Smav return; 331230130Smav 332230130Smav hdac_lock(sc); 333230130Smav if (sc->polling == 0) { 334230130Smav hdac_unlock(sc); 335230130Smav return; 336182999Smav } 337230130Smav callout_reset(&sc->poll_callout, sc->poll_ival, 338230130Smav hdac_poll_callback, sc); 339230130Smav hdac_unlock(sc); 340230130Smav 341230130Smav hdac_intr_handler(sc); 342162922Sariff} 343162922Sariff 344162922Sariff/**************************************************************************** 345182999Smav * int hdac_reset(hdac_softc *, int) 346162922Sariff * 347162922Sariff * Reset the hdac to a quiescent and known state. 348162922Sariff ****************************************************************************/ 349162922Sariffstatic int 350182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 351162922Sariff{ 352162922Sariff uint32_t gctl; 353162922Sariff int count, i; 354162922Sariff 355162922Sariff /* 356162922Sariff * Stop all Streams DMA engine 357162922Sariff */ 358162922Sariff for (i = 0; i < sc->num_iss; i++) 359162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 360162922Sariff for (i = 0; i < sc->num_oss; i++) 361162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 362162922Sariff for (i = 0; i < sc->num_bss; i++) 363162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 364162922Sariff 365162922Sariff /* 366169277Sariff * Stop Control DMA engines. 367162922Sariff */ 368162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 369162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 370162922Sariff 371162922Sariff /* 372169277Sariff * Reset DMA position buffer. 373169277Sariff */ 374169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 375169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 376169277Sariff 377169277Sariff /* 378162922Sariff * Reset the controller. The reset must remain asserted for 379162922Sariff * a minimum of 100us. 380162922Sariff */ 381162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 382162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 383162922Sariff count = 10000; 384162922Sariff do { 385162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 386162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 387162922Sariff break; 388162922Sariff DELAY(10); 389162922Sariff } while (--count); 390162922Sariff if (gctl & HDAC_GCTL_CRST) { 391162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 392162922Sariff return (ENXIO); 393162922Sariff } 394230130Smav 395182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 396182999Smav if (!wakeup) 397182999Smav return (0); 398230130Smav 399162922Sariff DELAY(100); 400162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 401162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 402162922Sariff count = 10000; 403162922Sariff do { 404162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 405163057Sariff if (gctl & HDAC_GCTL_CRST) 406162922Sariff break; 407162922Sariff DELAY(10); 408162922Sariff } while (--count); 409162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 410162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 411162922Sariff return (ENXIO); 412162922Sariff } 413162922Sariff 414162922Sariff /* 415162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 416162922Sariff * should be of 250us but for some reasons, on it's not enough on my 417162922Sariff * computer. Let's use twice as much as necessary to make sure that 418162922Sariff * it's reset properly. 419162922Sariff */ 420162922Sariff DELAY(1000); 421162922Sariff 422162922Sariff return (0); 423162922Sariff} 424162922Sariff 425162922Sariff 426162922Sariff/**************************************************************************** 427162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 428162922Sariff * 429162922Sariff * Retreive the general capabilities of the hdac; 430162922Sariff * Number of Input Streams 431162922Sariff * Number of Output Streams 432162922Sariff * Number of bidirectional Streams 433162922Sariff * 64bit ready 434162922Sariff * CORB and RIRB sizes 435162922Sariff ****************************************************************************/ 436162922Sariffstatic int 437162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 438162922Sariff{ 439162922Sariff uint16_t gcap; 440162922Sariff uint8_t corbsize, rirbsize; 441162922Sariff 442162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 443162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 444162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 445162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 446230130Smav sc->num_ss = sc->num_iss + sc->num_oss + sc->num_bss; 447196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 448230130Smav sc->support_64bit = (gcap & HDAC_GCAP_64OK) != 0; 449230130Smav if (sc->quirks_on & HDAC_QUIRK_64BIT) 450230130Smav sc->support_64bit = 1; 451230130Smav else if (sc->quirks_off & HDAC_QUIRK_64BIT) 452230130Smav sc->support_64bit = 0; 453162922Sariff 454162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 455162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 456162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 457162922Sariff sc->corb_size = 256; 458162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 459162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 460162922Sariff sc->corb_size = 16; 461162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 462162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 463162922Sariff sc->corb_size = 2; 464162922Sariff else { 465162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 466162922Sariff __func__, corbsize); 467162922Sariff return (ENXIO); 468162922Sariff } 469162922Sariff 470162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 471162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 472162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 473162922Sariff sc->rirb_size = 256; 474162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 475162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 476162922Sariff sc->rirb_size = 16; 477162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 478162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 479162922Sariff sc->rirb_size = 2; 480162922Sariff else { 481162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 482162922Sariff __func__, rirbsize); 483162922Sariff return (ENXIO); 484162922Sariff } 485162922Sariff 486196762Smav HDA_BOOTVERBOSE( 487196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 488196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 489196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 490196762Smav sc->support_64bit ? ", 64bit" : "", 491196762Smav sc->corb_size, sc->rirb_size); 492182999Smav ); 493182999Smav 494162922Sariff return (0); 495162922Sariff} 496162922Sariff 497162922Sariff 498162922Sariff/**************************************************************************** 499162922Sariff * void hdac_dma_cb 500162922Sariff * 501162922Sariff * This function is called by bus_dmamap_load when the mapping has been 502162922Sariff * established. We just record the physical address of the mapping into 503162922Sariff * the struct hdac_dma passed in. 504162922Sariff ****************************************************************************/ 505162922Sariffstatic void 506162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 507162922Sariff{ 508162922Sariff struct hdac_dma *dma; 509162922Sariff 510162922Sariff if (error == 0) { 511162922Sariff dma = (struct hdac_dma *)callback_arg; 512162922Sariff dma->dma_paddr = segs[0].ds_addr; 513162922Sariff } 514162922Sariff} 515162922Sariff 516162922Sariff 517162922Sariff/**************************************************************************** 518162922Sariff * int hdac_dma_alloc 519162922Sariff * 520162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 521162922Sariff * It must be freed by a corresponding hdac_dma_free. 522162922Sariff ****************************************************************************/ 523162922Sariffstatic int 524162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 525162922Sariff{ 526169277Sariff bus_size_t roundsz; 527162922Sariff int result; 528162922Sariff 529230130Smav roundsz = roundup2(size, HDA_DMA_ALIGNMENT); 530162922Sariff bzero(dma, sizeof(*dma)); 531162922Sariff 532162922Sariff /* 533162922Sariff * Create a DMA tag 534162922Sariff */ 535194861Smav result = bus_dma_tag_create( 536194861Smav bus_get_dma_tag(sc->dev), /* parent */ 537230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 538162922Sariff 0, /* boundary */ 539194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 540194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 541162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 542162922Sariff NULL, /* filtfunc */ 543162922Sariff NULL, /* fistfuncarg */ 544169277Sariff roundsz, /* maxsize */ 545162922Sariff 1, /* nsegments */ 546169277Sariff roundsz, /* maxsegsz */ 547162922Sariff 0, /* flags */ 548162922Sariff NULL, /* lockfunc */ 549162922Sariff NULL, /* lockfuncarg */ 550162922Sariff &dma->dma_tag); /* dmat */ 551162922Sariff if (result != 0) { 552162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 553162922Sariff __func__, result); 554167773Sariff goto hdac_dma_alloc_fail; 555162922Sariff } 556162922Sariff 557162922Sariff /* 558162922Sariff * Allocate DMA memory 559162922Sariff */ 560162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 561169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 562171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 563171330Sariff &dma->dma_map); 564162922Sariff if (result != 0) { 565162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 566162922Sariff __func__, result); 567167773Sariff goto hdac_dma_alloc_fail; 568162922Sariff } 569162922Sariff 570169277Sariff dma->dma_size = roundsz; 571169277Sariff 572162922Sariff /* 573162922Sariff * Map the memory 574162922Sariff */ 575162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 576169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 577162922Sariff if (result != 0 || dma->dma_paddr == 0) { 578167773Sariff if (result == 0) 579167773Sariff result = ENOMEM; 580162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 581162922Sariff __func__, result); 582167773Sariff goto hdac_dma_alloc_fail; 583162922Sariff } 584162922Sariff 585183097Smav HDA_BOOTHVERBOSE( 586169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 587169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 588169277Sariff ); 589169277Sariff 590162922Sariff return (0); 591169277Sariff 592167773Sariffhdac_dma_alloc_fail: 593169277Sariff hdac_dma_free(sc, dma); 594167773Sariff 595162922Sariff return (result); 596162922Sariff} 597162922Sariff 598162922Sariff 599162922Sariff/**************************************************************************** 600169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 601162922Sariff * 602162922Sariff * Free a struct dhac_dma that has been previously allocated via the 603162922Sariff * hdac_dma_alloc function. 604162922Sariff ****************************************************************************/ 605162922Sariffstatic void 606169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 607162922Sariff{ 608167773Sariff if (dma->dma_map != NULL) { 609169277Sariff#if 0 610162922Sariff /* Flush caches */ 611162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 612162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 613169277Sariff#endif 614162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 615167773Sariff } 616167773Sariff if (dma->dma_vaddr != NULL) { 617162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 618167773Sariff dma->dma_vaddr = NULL; 619167773Sariff } 620167773Sariff dma->dma_map = NULL; 621167773Sariff if (dma->dma_tag != NULL) { 622162922Sariff bus_dma_tag_destroy(dma->dma_tag); 623167773Sariff dma->dma_tag = NULL; 624162922Sariff } 625167773Sariff dma->dma_size = 0; 626162922Sariff} 627162922Sariff 628162922Sariff/**************************************************************************** 629162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 630162922Sariff * 631162922Sariff * Allocate all the bus resources necessary to speak with the physical 632162922Sariff * controller. 633162922Sariff ****************************************************************************/ 634162922Sariffstatic int 635162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 636162922Sariff{ 637162922Sariff struct hdac_mem *mem; 638162922Sariff 639162922Sariff mem = &sc->mem; 640162922Sariff mem->mem_rid = PCIR_BAR(0); 641162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 642162922Sariff &mem->mem_rid, RF_ACTIVE); 643162922Sariff if (mem->mem_res == NULL) { 644162922Sariff device_printf(sc->dev, 645162922Sariff "%s: Unable to allocate memory resource\n", __func__); 646162922Sariff return (ENOMEM); 647162922Sariff } 648162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 649162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 650162922Sariff 651162922Sariff return (0); 652162922Sariff} 653162922Sariff 654162922Sariff/**************************************************************************** 655162922Sariff * void hdac_mem_free(struct hdac_softc *) 656162922Sariff * 657162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 658162922Sariff ****************************************************************************/ 659162922Sariffstatic void 660162922Sariffhdac_mem_free(struct hdac_softc *sc) 661162922Sariff{ 662162922Sariff struct hdac_mem *mem; 663162922Sariff 664162922Sariff mem = &sc->mem; 665162922Sariff if (mem->mem_res != NULL) 666162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 667162922Sariff mem->mem_res); 668164614Sariff mem->mem_res = NULL; 669162922Sariff} 670162922Sariff 671162922Sariff/**************************************************************************** 672162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 673162922Sariff * 674162922Sariff * Allocate and setup the resources necessary for interrupt handling. 675162922Sariff ****************************************************************************/ 676162922Sariffstatic int 677162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 678162922Sariff{ 679162922Sariff struct hdac_irq *irq; 680162922Sariff int result; 681162922Sariff 682162922Sariff irq = &sc->irq; 683162922Sariff irq->irq_rid = 0x0; 684171330Sariff 685230130Smav if ((sc->quirks_off & HDAC_QUIRK_MSI) == 0 && 686171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 687171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 688171330Sariff irq->irq_rid = 0x1; 689171330Sariff 690162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 691162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 692162922Sariff if (irq->irq_res == NULL) { 693162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 694162922Sariff __func__); 695167773Sariff goto hdac_irq_alloc_fail; 696162922Sariff } 697182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 698182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 699162922Sariff if (result != 0) { 700162922Sariff device_printf(sc->dev, 701162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 702162922Sariff __func__, result); 703167773Sariff goto hdac_irq_alloc_fail; 704162922Sariff } 705162922Sariff 706162922Sariff return (0); 707162922Sariff 708167773Sariffhdac_irq_alloc_fail: 709164614Sariff hdac_irq_free(sc); 710164614Sariff 711162922Sariff return (ENXIO); 712162922Sariff} 713162922Sariff 714162922Sariff/**************************************************************************** 715162922Sariff * void hdac_irq_free(struct hdac_softc *) 716162922Sariff * 717162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 718162922Sariff ****************************************************************************/ 719162922Sariffstatic void 720162922Sariffhdac_irq_free(struct hdac_softc *sc) 721162922Sariff{ 722162922Sariff struct hdac_irq *irq; 723162922Sariff 724162922Sariff irq = &sc->irq; 725164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 726162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 727162922Sariff if (irq->irq_res != NULL) 728162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 729162922Sariff irq->irq_res); 730188656Smav if (irq->irq_rid == 0x1) 731171330Sariff pci_release_msi(sc->dev); 732164614Sariff irq->irq_handle = NULL; 733164614Sariff irq->irq_res = NULL; 734171330Sariff irq->irq_rid = 0x0; 735162922Sariff} 736162922Sariff 737162922Sariff/**************************************************************************** 738162922Sariff * void hdac_corb_init(struct hdac_softc *) 739162922Sariff * 740162922Sariff * Initialize the corb registers for operations but do not start it up yet. 741162922Sariff * The CORB engine must not be running when this function is called. 742162922Sariff ****************************************************************************/ 743162922Sariffstatic void 744162922Sariffhdac_corb_init(struct hdac_softc *sc) 745162922Sariff{ 746162922Sariff uint8_t corbsize; 747162922Sariff uint64_t corbpaddr; 748162922Sariff 749162922Sariff /* Setup the CORB size. */ 750162922Sariff switch (sc->corb_size) { 751162922Sariff case 256: 752162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 753162922Sariff break; 754162922Sariff case 16: 755162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 756162922Sariff break; 757162922Sariff case 2: 758162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 759162922Sariff break; 760162922Sariff default: 761162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 762162922Sariff } 763162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 764162922Sariff 765162922Sariff /* Setup the CORB Address in the hdac */ 766162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 767162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 768162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 769162922Sariff 770162922Sariff /* Set the WP and RP */ 771162922Sariff sc->corb_wp = 0; 772162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 773162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 774162922Sariff /* 775162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 776162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 777162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 778162922Sariff * manually reset the bit to zero before continuing. 779162922Sariff */ 780162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 781162922Sariff 782162922Sariff /* Enable CORB error reporting */ 783162922Sariff#if 0 784162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 785162922Sariff#endif 786162922Sariff} 787162922Sariff 788162922Sariff/**************************************************************************** 789162922Sariff * void hdac_rirb_init(struct hdac_softc *) 790162922Sariff * 791162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 792162922Sariff * The RIRB engine must not be running when this function is called. 793162922Sariff ****************************************************************************/ 794162922Sariffstatic void 795162922Sariffhdac_rirb_init(struct hdac_softc *sc) 796162922Sariff{ 797162922Sariff uint8_t rirbsize; 798162922Sariff uint64_t rirbpaddr; 799162922Sariff 800162922Sariff /* Setup the RIRB size. */ 801162922Sariff switch (sc->rirb_size) { 802162922Sariff case 256: 803162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 804162922Sariff break; 805162922Sariff case 16: 806162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 807162922Sariff break; 808162922Sariff case 2: 809162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 810162922Sariff break; 811162922Sariff default: 812162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 813162922Sariff } 814162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 815162922Sariff 816162922Sariff /* Setup the RIRB Address in the hdac */ 817162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 818162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 819162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 820162922Sariff 821162922Sariff /* Setup the WP and RP */ 822162922Sariff sc->rirb_rp = 0; 823162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 824162922Sariff 825182999Smav /* Setup the interrupt threshold */ 826182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 827162922Sariff 828182999Smav /* Enable Overrun and response received reporting */ 829162922Sariff#if 0 830182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 831182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 832162922Sariff#else 833182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 834162922Sariff#endif 835162922Sariff 836169277Sariff#if 0 837162922Sariff /* 838162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 839162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 840162922Sariff * should be sufficient to do this only once as the rirb is purely 841162922Sariff * read-only from now on. 842162922Sariff */ 843162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 844162922Sariff BUS_DMASYNC_PREREAD); 845169277Sariff#endif 846162922Sariff} 847162922Sariff 848162922Sariff/**************************************************************************** 849162922Sariff * void hdac_corb_start(hdac_softc *) 850162922Sariff * 851162922Sariff * Startup the corb DMA engine 852162922Sariff ****************************************************************************/ 853162922Sariffstatic void 854162922Sariffhdac_corb_start(struct hdac_softc *sc) 855162922Sariff{ 856162922Sariff uint32_t corbctl; 857162922Sariff 858162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 859162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 860162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 861162922Sariff} 862162922Sariff 863162922Sariff/**************************************************************************** 864162922Sariff * void hdac_rirb_start(hdac_softc *) 865162922Sariff * 866162922Sariff * Startup the rirb DMA engine 867162922Sariff ****************************************************************************/ 868162922Sariffstatic void 869162922Sariffhdac_rirb_start(struct hdac_softc *sc) 870162922Sariff{ 871162922Sariff uint32_t rirbctl; 872162922Sariff 873162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 874162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 875162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 876162922Sariff} 877162922Sariff 878164614Sariffstatic int 879164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 880164614Sariff{ 881164614Sariff struct hdac_rirb *rirb_base, *rirb; 882164614Sariff nid_t cad; 883164614Sariff uint32_t resp; 884164614Sariff uint8_t rirbwp; 885171141Sariff int ret; 886164614Sariff 887164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 888164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 889169277Sariff#if 0 890164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 891164614Sariff BUS_DMASYNC_POSTREAD); 892169277Sariff#endif 893164614Sariff 894171141Sariff ret = 0; 895164614Sariff while (sc->rirb_rp != rirbwp) { 896164614Sariff sc->rirb_rp++; 897164614Sariff sc->rirb_rp %= sc->rirb_size; 898164614Sariff rirb = &rirb_base[sc->rirb_rp]; 899164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 900164614Sariff resp = rirb->response; 901164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 902230130Smav sc->unsolq[sc->unsolq_wp++] = resp; 903164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 904230130Smav sc->unsolq[sc->unsolq_wp++] = cad; 905230130Smav sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 906230130Smav } else if (sc->codecs[cad].pending <= 0) { 907230130Smav device_printf(sc->dev, "Unexpected unsolicited " 908230130Smav "response from address %d: %08x\n", cad, resp); 909230130Smav } else { 910230130Smav sc->codecs[cad].response = resp; 911230130Smav sc->codecs[cad].pending--; 912230130Smav } 913164614Sariff ret++; 914164614Sariff } 915164614Sariff return (ret); 916164614Sariff} 917164614Sariff 918164614Sariffstatic int 919164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 920164614Sariff{ 921230130Smav device_t child; 922164614Sariff nid_t cad; 923230130Smav uint32_t resp; 924164614Sariff int ret = 0; 925164614Sariff 926164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 927164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 928164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 929230130Smav resp = sc->unsolq[sc->unsolq_rp++]; 930164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 931230130Smav cad = sc->unsolq[sc->unsolq_rp++]; 932230130Smav sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 933230130Smav if ((child = sc->codecs[cad].dev) != NULL) 934230130Smav HDAC_UNSOL_INTR(child, resp); 935164614Sariff ret++; 936164614Sariff } 937164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 938164614Sariff } 939164614Sariff 940164614Sariff return (ret); 941164614Sariff} 942164614Sariff 943162922Sariff/**************************************************************************** 944162922Sariff * uint32_t hdac_command_sendone_internal 945162922Sariff * 946162922Sariff * Wrapper function that sends only one command to a given codec 947162922Sariff ****************************************************************************/ 948162922Sariffstatic uint32_t 949230130Smavhdac_send_command(struct hdac_softc *sc, nid_t cad, uint32_t verb) 950162922Sariff{ 951230130Smav int timeout; 952230130Smav uint32_t *corb; 953162922Sariff 954163057Sariff if (!hdac_lockowned(sc)) 955162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 956230130Smav verb &= ~HDA_CMD_CAD_MASK; 957230130Smav verb |= ((uint32_t)cad) << HDA_CMD_CAD_SHIFT; 958230130Smav sc->codecs[cad].response = HDA_INVALID; 959162922Sariff 960230130Smav sc->codecs[cad].pending++; 961230130Smav sc->corb_wp++; 962230130Smav sc->corb_wp %= sc->corb_size; 963162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 964169277Sariff#if 0 965230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 966230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 967169277Sariff#endif 968230130Smav corb[sc->corb_wp] = verb; 969169277Sariff#if 0 970230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 971230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 972169277Sariff#endif 973230130Smav HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 974162922Sariff 975230130Smav timeout = 10000; 976230130Smav do { 977230130Smav if (hdac_rirb_flush(sc) == 0) 978162922Sariff DELAY(10); 979230130Smav } while (sc->codecs[cad].pending != 0 && --timeout); 980162922Sariff 981230130Smav if (sc->codecs[cad].pending != 0) { 982230130Smav device_printf(sc->dev, "Command timeout on address %d\n", cad); 983230130Smav sc->codecs[cad].pending = 0; 984230130Smav } 985162922Sariff 986230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 987230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 988230130Smav return (sc->codecs[cad].response); 989162922Sariff} 990162922Sariff 991162922Sariff/**************************************************************************** 992162922Sariff * Device Methods 993162922Sariff ****************************************************************************/ 994162922Sariff 995162922Sariff/**************************************************************************** 996162922Sariff * int hdac_probe(device_t) 997162922Sariff * 998162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 999162922Sariff * match using the subclass of the device. 1000162922Sariff ****************************************************************************/ 1001162922Sariffstatic int 1002162922Sariffhdac_probe(device_t dev) 1003162922Sariff{ 1004162922Sariff int i, result; 1005163257Sariff uint32_t model; 1006163257Sariff uint16_t class, subclass; 1007162922Sariff char desc[64]; 1008162922Sariff 1009162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 1010162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1011162922Sariff class = pci_get_class(dev); 1012162922Sariff subclass = pci_get_subclass(dev); 1013162922Sariff 1014162922Sariff bzero(desc, sizeof(desc)); 1015162922Sariff result = ENXIO; 1016162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1017162922Sariff if (hdac_devices[i].model == model) { 1018230331Smav strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1019230331Smav result = BUS_PROBE_DEFAULT; 1020162922Sariff break; 1021162922Sariff } 1022163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1023162922Sariff class == PCIC_MULTIMEDIA && 1024162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1025230331Smav snprintf(desc, sizeof(desc), 1026230331Smav "%s (0x%04x)", 1027230331Smav hdac_devices[i].desc, pci_get_device(dev)); 1028230331Smav result = BUS_PROBE_GENERIC; 1029162922Sariff break; 1030162922Sariff } 1031162922Sariff } 1032162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 1033162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1034230331Smav snprintf(desc, sizeof(desc), "Generic (0x%08x)", model); 1035230331Smav result = BUS_PROBE_GENERIC; 1036162922Sariff } 1037162922Sariff if (result != ENXIO) { 1038230331Smav strlcat(desc, " HDA Controller", sizeof(desc)); 1039162922Sariff device_set_desc_copy(dev, desc); 1040162922Sariff } 1041162922Sariff 1042162922Sariff return (result); 1043162922Sariff} 1044162922Sariff 1045162922Sariffstatic void 1046171141Sariffhdac_unsolq_task(void *context, int pending) 1047171141Sariff{ 1048171141Sariff struct hdac_softc *sc; 1049171141Sariff 1050171141Sariff sc = (struct hdac_softc *)context; 1051171141Sariff 1052171141Sariff hdac_lock(sc); 1053171141Sariff hdac_unsolq_flush(sc); 1054171141Sariff hdac_unlock(sc); 1055171141Sariff} 1056171141Sariff 1057162922Sariff/**************************************************************************** 1058162922Sariff * int hdac_attach(device_t) 1059162922Sariff * 1060162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 1061162922Sariff * when this function is called. Setup everything that doesn't require 1062162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 1063162922Sariff ****************************************************************************/ 1064162922Sariffstatic int 1065162922Sariffhdac_attach(device_t dev) 1066162922Sariff{ 1067162922Sariff struct hdac_softc *sc; 1068162922Sariff int result; 1069189086Smav int i, devid = -1; 1070189086Smav uint32_t model; 1071189086Smav uint16_t class, subclass; 1072169277Sariff uint16_t vendor; 1073169277Sariff uint8_t v; 1074162922Sariff 1075230130Smav sc = device_get_softc(dev); 1076223118Sjoel HDA_BOOTVERBOSE( 1077223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 1078223118Sjoel HDA_DRV_TEST_REV); 1079223118Sjoel ); 1080182999Smav 1081189086Smav model = (uint32_t)pci_get_device(dev) << 16; 1082189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1083189086Smav class = pci_get_class(dev); 1084189086Smav subclass = pci_get_subclass(dev); 1085189086Smav 1086189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1087189086Smav if (hdac_devices[i].model == model) { 1088189086Smav devid = i; 1089189086Smav break; 1090189086Smav } 1091189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1092189086Smav class == PCIC_MULTIMEDIA && 1093189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 1094189086Smav devid = i; 1095189086Smav break; 1096189086Smav } 1097189086Smav } 1098189086Smav 1099230130Smav sc->lock = snd_mtxcreate(device_get_nameunit(dev), "HDA driver mutex"); 1100162922Sariff sc->dev = dev; 1101230130Smav TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 1102230130Smav callout_init(&sc->poll_callout, CALLOUT_MPSAFE); 1103230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) 1104230130Smav sc->codecs[i].dev = NULL; 1105230130Smav if (devid >= 0) { 1106230130Smav sc->quirks_on = hdac_devices[devid].quirks_on; 1107230130Smav sc->quirks_off = hdac_devices[devid].quirks_off; 1108230130Smav } else { 1109230130Smav sc->quirks_on = 0; 1110230130Smav sc->quirks_off = 0; 1111165281Sariff } 1112169277Sariff if (resource_int_value(device_get_name(dev), 1113230130Smav device_get_unit(dev), "msi", &i) == 0) { 1114230130Smav if (i == 0) 1115230130Smav sc->quirks_off |= HDAC_QUIRK_MSI; 1116230130Smav else { 1117230130Smav sc->quirks_on |= HDAC_QUIRK_MSI; 1118230130Smav sc->quirks_off |= ~HDAC_QUIRK_MSI; 1119230130Smav } 1120230130Smav } 1121230130Smav hdac_config_fetch(sc, &sc->quirks_on, &sc->quirks_off); 1122230130Smav HDA_BOOTVERBOSE( 1123230130Smav device_printf(sc->dev, 1124230130Smav "Config options: on=0x%08x off=0x%08x\n", 1125230130Smav sc->quirks_on, sc->quirks_off); 1126230130Smav ); 1127230130Smav sc->poll_ival = hz; 1128230130Smav if (resource_int_value(device_get_name(dev), 1129169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 1130164614Sariff sc->polling = 1; 1131164614Sariff else 1132164614Sariff sc->polling = 0; 1133164614Sariff 1134162922Sariff pci_enable_busmaster(dev); 1135162922Sariff 1136230130Smav vendor = pci_get_vendor(dev); 1137169277Sariff if (vendor == INTEL_VENDORID) { 1138169277Sariff /* TCSEL -> TC0 */ 1139169277Sariff v = pci_read_config(dev, 0x44, 1); 1140169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 1141183097Smav HDA_BOOTHVERBOSE( 1142169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 1143169277Sariff pci_read_config(dev, 0x44, 1)); 1144169277Sariff ); 1145169277Sariff } 1146169277Sariff 1147169277Sariff#if defined(__i386__) || defined(__amd64__) 1148171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1149169277Sariff 1150169277Sariff if (resource_int_value(device_get_name(dev), 1151169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 1152169277Sariff#else 1153171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1154169277Sariff#endif 1155169277Sariff /* 1156169277Sariff * Try to enable PCIe snoop to avoid messing around with 1157169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 1158169277Sariff * config is pretty much vendor specific, there are no 1159169277Sariff * general solutions on how to enable it, forcing us (even 1160169277Sariff * Microsoft) to enable uncacheable or write combined DMA 1161169277Sariff * by default. 1162169277Sariff * 1163169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 1164169277Sariff */ 1165169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 1166169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 1167169277Sariff continue; 1168171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1169169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 1170169277Sariff break; 1171169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1172169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 1173169277Sariff hdac_pcie_snoop[i].enable) 1174169277Sariff break; 1175169277Sariff v &= hdac_pcie_snoop[i].mask; 1176169277Sariff v |= hdac_pcie_snoop[i].enable; 1177169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 1178169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1179169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 1180169277Sariff hdac_pcie_snoop[i].enable) { 1181169277Sariff HDA_BOOTVERBOSE( 1182169277Sariff device_printf(dev, 1183169277Sariff "WARNING: Failed to enable PCIe " 1184169277Sariff "snoop!\n"); 1185169277Sariff ); 1186169277Sariff#if defined(__i386__) || defined(__amd64__) 1187171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1188169277Sariff#endif 1189169277Sariff } 1190169277Sariff break; 1191169277Sariff } 1192169277Sariff#if defined(__i386__) || defined(__amd64__) 1193169277Sariff } 1194169277Sariff#endif 1195169277Sariff 1196183097Smav HDA_BOOTHVERBOSE( 1197169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 1198171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 1199171330Sariff "Uncacheable" : "PCIe snoop", vendor); 1200169277Sariff ); 1201169277Sariff 1202162922Sariff /* Allocate resources */ 1203162922Sariff result = hdac_mem_alloc(sc); 1204162922Sariff if (result != 0) 1205163057Sariff goto hdac_attach_fail; 1206162922Sariff result = hdac_irq_alloc(sc); 1207162922Sariff if (result != 0) 1208163057Sariff goto hdac_attach_fail; 1209162922Sariff 1210162922Sariff /* Get Capabilities */ 1211162922Sariff result = hdac_get_capabilities(sc); 1212162922Sariff if (result != 0) 1213163057Sariff goto hdac_attach_fail; 1214162922Sariff 1215230130Smav /* Allocate CORB, RIRB, POS and BDLs dma memory */ 1216162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 1217162922Sariff sc->corb_size * sizeof(uint32_t)); 1218162922Sariff if (result != 0) 1219163057Sariff goto hdac_attach_fail; 1220162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 1221162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 1222162922Sariff if (result != 0) 1223163057Sariff goto hdac_attach_fail; 1224230130Smav sc->streams = malloc(sizeof(struct hdac_stream) * sc->num_ss, 1225230130Smav M_HDAC, M_ZERO | M_WAITOK); 1226230130Smav for (i = 0; i < sc->num_ss; i++) { 1227230130Smav result = hdac_dma_alloc(sc, &sc->streams[i].bdl, 1228230130Smav sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1229230130Smav if (result != 0) 1230230130Smav goto hdac_attach_fail; 1231230130Smav } 1232230130Smav if (sc->quirks_on & HDAC_QUIRK_DMAPOS) { 1233230130Smav if (hdac_dma_alloc(sc, &sc->pos_dma, (sc->num_ss) * 8) != 0) { 1234230130Smav HDA_BOOTVERBOSE( 1235230130Smav device_printf(dev, "Failed to " 1236230130Smav "allocate DMA pos buffer " 1237230130Smav "(non-fatal)\n"); 1238230130Smav ); 1239230130Smav } else { 1240230130Smav uint64_t addr = sc->pos_dma.dma_paddr; 1241162922Sariff 1242230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, addr >> 32); 1243230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 1244230130Smav (addr & HDAC_DPLBASE_DPLBASE_MASK) | 1245230130Smav HDAC_DPLBASE_DPLBASE_DMAPBE); 1246230130Smav } 1247230130Smav } 1248230130Smav 1249194861Smav result = bus_dma_tag_create( 1250194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1251230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 1252194861Smav 0, /* boundary */ 1253194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1254194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1255194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 1256194861Smav NULL, /* filtfunc */ 1257194861Smav NULL, /* fistfuncarg */ 1258194861Smav HDA_BUFSZ_MAX, /* maxsize */ 1259194861Smav 1, /* nsegments */ 1260194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 1261194861Smav 0, /* flags */ 1262194861Smav NULL, /* lockfunc */ 1263194861Smav NULL, /* lockfuncarg */ 1264194861Smav &sc->chan_dmat); /* dmat */ 1265194861Smav if (result != 0) { 1266194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 1267194861Smav __func__, result); 1268194861Smav goto hdac_attach_fail; 1269194861Smav } 1270194861Smav 1271162922Sariff /* Quiesce everything */ 1272183097Smav HDA_BOOTHVERBOSE( 1273182999Smav device_printf(dev, "Reset controller...\n"); 1274182999Smav ); 1275182999Smav hdac_reset(sc, 1); 1276162922Sariff 1277162922Sariff /* Initialize the CORB and RIRB */ 1278162922Sariff hdac_corb_init(sc); 1279162922Sariff hdac_rirb_init(sc); 1280162922Sariff 1281162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 1282162922Sariff sc->intrhook.ich_func = hdac_attach2; 1283162922Sariff sc->intrhook.ich_arg = (void *)sc; 1284162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 1285162922Sariff sc->intrhook.ich_func = NULL; 1286162922Sariff hdac_attach2((void *)sc); 1287162922Sariff } 1288162922Sariff 1289163057Sariff return (0); 1290162922Sariff 1291163057Sariffhdac_attach_fail: 1292162922Sariff hdac_irq_free(sc); 1293230130Smav for (i = 0; i < sc->num_ss; i++) 1294230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1295230130Smav free(sc->streams, M_HDAC); 1296169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 1297169277Sariff hdac_dma_free(sc, &sc->corb_dma); 1298162922Sariff hdac_mem_free(sc); 1299162922Sariff snd_mtxfree(sc->lock); 1300162922Sariff 1301163057Sariff return (ENXIO); 1302162922Sariff} 1303162922Sariff 1304230130Smavstatic int 1305230130Smavsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 1306162922Sariff{ 1307230130Smav struct hdac_softc *sc; 1308230130Smav device_t *devlist; 1309230130Smav device_t dev; 1310230130Smav int devcount, i, err, val; 1311162922Sariff 1312230130Smav dev = oidp->oid_arg1; 1313230130Smav sc = device_get_softc(dev); 1314230130Smav if (sc == NULL) 1315230130Smav return (EINVAL); 1316230130Smav val = 0; 1317230130Smav err = sysctl_handle_int(oidp, &val, 0, req); 1318230130Smav if (err != 0 || req->newptr == NULL || val == 0) 1319230130Smav return (err); 1320162922Sariff 1321230130Smav /* XXX: Temporary. For debugging. */ 1322230130Smav if (val == 100) { 1323230130Smav hdac_suspend(dev); 1324182999Smav return (0); 1325230130Smav } else if (val == 101) { 1326230130Smav hdac_resume(dev); 1327182999Smav return (0); 1328182999Smav } 1329162922Sariff 1330230130Smav if ((err = device_get_children(dev, &devlist, &devcount)) != 0) 1331230130Smav return (err); 1332230130Smav hdac_lock(sc); 1333230130Smav for (i = 0; i < devcount; i++) 1334230130Smav HDAC_PINDUMP(devlist[i]); 1335230130Smav hdac_unlock(sc); 1336230130Smav free(devlist, M_TEMP); 1337182999Smav return (0); 1338162922Sariff} 1339162922Sariff 1340183097Smavstatic int 1341230326Smavhdac_mdata_rate(uint16_t fmt) 1342162922Sariff{ 1343230326Smav static const int mbits[8] = { 8, 16, 32, 32, 32, 32, 32, 32 }; 1344230326Smav int rate, bits; 1345162922Sariff 1346230130Smav if (fmt & (1 << 14)) 1347230130Smav rate = 44100; 1348230130Smav else 1349230130Smav rate = 48000; 1350230130Smav rate *= ((fmt >> 11) & 0x07) + 1; 1351230130Smav rate /= ((fmt >> 8) & 0x07) + 1; 1352230326Smav bits = mbits[(fmt >> 4) & 0x03]; 1353230326Smav bits *= (fmt & 0x0f) + 1; 1354230326Smav return (rate * bits); 1355182999Smav} 1356182999Smav 1357230326Smavstatic int 1358230326Smavhdac_bdata_rate(uint16_t fmt, int output) 1359230326Smav{ 1360230326Smav static const int bbits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 }; 1361230326Smav int rate, bits; 1362230326Smav 1363230326Smav rate = 48000; 1364230326Smav rate *= ((fmt >> 11) & 0x07) + 1; 1365230326Smav bits = bbits[(fmt >> 4) & 0x03]; 1366230326Smav bits *= (fmt & 0x0f) + 1; 1367230326Smav if (!output) 1368230326Smav bits = ((bits + 7) & ~0x07) + 10; 1369230326Smav return (rate * bits); 1370230326Smav} 1371230326Smav 1372182999Smavstatic void 1373230130Smavhdac_poll_reinit(struct hdac_softc *sc) 1374182999Smav{ 1375230130Smav int i, pollticks, min = 1000000; 1376230130Smav struct hdac_stream *s; 1377182999Smav 1378230130Smav if (sc->polling == 0) 1379230130Smav return; 1380230130Smav if (sc->unsol_registered > 0) 1381230130Smav min = hz / 2; 1382230130Smav for (i = 0; i < sc->num_ss; i++) { 1383230130Smav s = &sc->streams[i]; 1384230130Smav if (s->running == 0) 1385182999Smav continue; 1386230130Smav pollticks = ((uint64_t)hz * s->blksz) / 1387230326Smav (hdac_mdata_rate(s->format) / 8); 1388230130Smav pollticks >>= 1; 1389230130Smav if (pollticks > hz) 1390230130Smav pollticks = hz; 1391230130Smav if (pollticks < 1) { 1392182999Smav HDA_BOOTVERBOSE( 1393230130Smav device_printf(sc->dev, 1394230130Smav "poll interval < 1 tick !\n"); 1395182999Smav ); 1396230130Smav pollticks = 1; 1397162922Sariff } 1398230130Smav if (min > pollticks) 1399230130Smav min = pollticks; 1400162922Sariff } 1401202789Smav HDA_BOOTVERBOSE( 1402230130Smav device_printf(sc->dev, 1403230130Smav "poll interval %d -> %d ticks\n", 1404230130Smav sc->poll_ival, min); 1405202789Smav ); 1406230130Smav sc->poll_ival = min; 1407230130Smav if (min == 1000000) 1408230130Smav callout_stop(&sc->poll_callout); 1409182999Smav else 1410230130Smav callout_reset(&sc->poll_callout, 1, hdac_poll_callback, sc); 1411163057Sariff} 1412163057Sariff 1413164614Sariffstatic int 1414164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 1415164614Sariff{ 1416164614Sariff struct hdac_softc *sc; 1417164614Sariff device_t dev; 1418164614Sariff uint32_t ctl; 1419164614Sariff int err, val; 1420164614Sariff 1421164614Sariff dev = oidp->oid_arg1; 1422182999Smav sc = device_get_softc(dev); 1423182999Smav if (sc == NULL) 1424164614Sariff return (EINVAL); 1425164614Sariff hdac_lock(sc); 1426164614Sariff val = sc->polling; 1427164614Sariff hdac_unlock(sc); 1428170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 1429164614Sariff 1430169277Sariff if (err != 0 || req->newptr == NULL) 1431164614Sariff return (err); 1432164614Sariff if (val < 0 || val > 1) 1433164614Sariff return (EINVAL); 1434164614Sariff 1435164614Sariff hdac_lock(sc); 1436164614Sariff if (val != sc->polling) { 1437182999Smav if (val == 0) { 1438230130Smav callout_stop(&sc->poll_callout); 1439169277Sariff hdac_unlock(sc); 1440230130Smav callout_drain(&sc->poll_callout); 1441169277Sariff hdac_lock(sc); 1442164614Sariff sc->polling = 0; 1443182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1444182999Smav ctl |= HDAC_INTCTL_GIE; 1445182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1446164614Sariff } else { 1447182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1448182999Smav ctl &= ~HDAC_INTCTL_GIE; 1449182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1450164614Sariff sc->polling = 1; 1451182999Smav hdac_poll_reinit(sc); 1452164614Sariff } 1453164614Sariff } 1454164614Sariff hdac_unlock(sc); 1455164614Sariff 1456164614Sariff return (err); 1457164614Sariff} 1458169277Sariff 1459163057Sariffstatic void 1460162922Sariffhdac_attach2(void *arg) 1461162922Sariff{ 1462162922Sariff struct hdac_softc *sc; 1463230130Smav device_t child; 1464230130Smav uint32_t vendorid, revisionid; 1465230130Smav int i; 1466230130Smav uint16_t statests; 1467162922Sariff 1468162922Sariff sc = (struct hdac_softc *)arg; 1469162922Sariff 1470162922Sariff hdac_lock(sc); 1471162922Sariff 1472162922Sariff /* Remove ourselves from the config hooks */ 1473162922Sariff if (sc->intrhook.ich_func != NULL) { 1474162922Sariff config_intrhook_disestablish(&sc->intrhook); 1475162922Sariff sc->intrhook.ich_func = NULL; 1476162922Sariff } 1477162922Sariff 1478183097Smav HDA_BOOTHVERBOSE( 1479182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 1480162922Sariff ); 1481162922Sariff hdac_corb_start(sc); 1482183097Smav HDA_BOOTHVERBOSE( 1483182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 1484162922Sariff ); 1485162922Sariff hdac_rirb_start(sc); 1486183097Smav HDA_BOOTHVERBOSE( 1487162922Sariff device_printf(sc->dev, 1488182999Smav "Enabling controller interrupt...\n"); 1489162922Sariff ); 1490182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1491182999Smav HDAC_GCTL_UNSOL); 1492182999Smav if (sc->polling == 0) { 1493164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 1494164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1495182999Smav } 1496162922Sariff DELAY(1000); 1497162922Sariff 1498183097Smav HDA_BOOTHVERBOSE( 1499230130Smav device_printf(sc->dev, "Scanning HDA codecs ...\n"); 1500162922Sariff ); 1501230130Smav statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1502230130Smav hdac_unlock(sc); 1503230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1504230130Smav if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1505230130Smav HDA_BOOTHVERBOSE( 1506183097Smav device_printf(sc->dev, 1507230130Smav "Found CODEC at address %d\n", i); 1508183019Smav ); 1509230130Smav hdac_lock(sc); 1510230130Smav vendorid = hdac_send_command(sc, i, 1511230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_VENDOR_ID)); 1512230130Smav revisionid = hdac_send_command(sc, i, 1513230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_REVISION_ID)); 1514230130Smav hdac_unlock(sc); 1515230130Smav if (vendorid == HDA_INVALID && 1516230130Smav revisionid == HDA_INVALID) { 1517230130Smav device_printf(sc->dev, 1518230130Smav "CODEC is not responding!\n"); 1519182999Smav continue; 1520182999Smav } 1521230130Smav sc->codecs[i].vendor_id = 1522230130Smav HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1523230130Smav sc->codecs[i].device_id = 1524230130Smav HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1525230130Smav sc->codecs[i].revision_id = 1526230130Smav HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1527230130Smav sc->codecs[i].stepping_id = 1528230130Smav HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1529230130Smav child = device_add_child(sc->dev, "hdacc", -1); 1530230130Smav if (child == NULL) { 1531230130Smav device_printf(sc->dev, 1532230130Smav "Failed to add CODEC device\n"); 1533230130Smav continue; 1534182999Smav } 1535230130Smav device_set_ivars(child, (void *)(intptr_t)i); 1536230130Smav sc->codecs[i].dev = child; 1537182999Smav } 1538162922Sariff } 1539182999Smav bus_generic_attach(sc->dev); 1540182999Smav 1541182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1542182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1543230130Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1544230130Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 1545230130Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1546230130Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1547182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1548182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 1549182999Smav} 1550182999Smav 1551182999Smav/**************************************************************************** 1552182999Smav * int hdac_suspend(device_t) 1553182999Smav * 1554182999Smav * Suspend and power down HDA bus and codecs. 1555182999Smav ****************************************************************************/ 1556182999Smavstatic int 1557182999Smavhdac_suspend(device_t dev) 1558182999Smav{ 1559230130Smav struct hdac_softc *sc = device_get_softc(dev); 1560182999Smav 1561183097Smav HDA_BOOTHVERBOSE( 1562182999Smav device_printf(dev, "Suspend...\n"); 1563162922Sariff ); 1564230130Smav bus_generic_suspend(dev); 1565182999Smav 1566182999Smav hdac_lock(sc); 1567183097Smav HDA_BOOTHVERBOSE( 1568182999Smav device_printf(dev, "Reset controller...\n"); 1569162922Sariff ); 1570233606Smav callout_stop(&sc->poll_callout); 1571182999Smav hdac_reset(sc, 0); 1572182999Smav hdac_unlock(sc); 1573233606Smav callout_drain(&sc->poll_callout); 1574182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1575183097Smav HDA_BOOTHVERBOSE( 1576182999Smav device_printf(dev, "Suspend done\n"); 1577162922Sariff ); 1578182999Smav return (0); 1579182999Smav} 1580182999Smav 1581182999Smav/**************************************************************************** 1582182999Smav * int hdac_resume(device_t) 1583182999Smav * 1584182999Smav * Powerup and restore HDA bus and codecs state. 1585182999Smav ****************************************************************************/ 1586182999Smavstatic int 1587182999Smavhdac_resume(device_t dev) 1588182999Smav{ 1589230130Smav struct hdac_softc *sc = device_get_softc(dev); 1590230130Smav int error; 1591182999Smav 1592183097Smav HDA_BOOTHVERBOSE( 1593182999Smav device_printf(dev, "Resume...\n"); 1594162922Sariff ); 1595182999Smav hdac_lock(sc); 1596182999Smav 1597182999Smav /* Quiesce everything */ 1598183097Smav HDA_BOOTHVERBOSE( 1599182999Smav device_printf(dev, "Reset controller...\n"); 1600162922Sariff ); 1601182999Smav hdac_reset(sc, 1); 1602182999Smav 1603182999Smav /* Initialize the CORB and RIRB */ 1604182999Smav hdac_corb_init(sc); 1605182999Smav hdac_rirb_init(sc); 1606182999Smav 1607183097Smav HDA_BOOTHVERBOSE( 1608182999Smav device_printf(dev, "Starting CORB Engine...\n"); 1609162922Sariff ); 1610182999Smav hdac_corb_start(sc); 1611183097Smav HDA_BOOTHVERBOSE( 1612182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 1613162922Sariff ); 1614182999Smav hdac_rirb_start(sc); 1615183097Smav HDA_BOOTHVERBOSE( 1616230130Smav device_printf(dev, "Enabling controller interrupt...\n"); 1617162922Sariff ); 1618182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1619182999Smav HDAC_GCTL_UNSOL); 1620230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1621182999Smav DELAY(1000); 1622233606Smav hdac_poll_reinit(sc); 1623182999Smav hdac_unlock(sc); 1624182999Smav 1625230130Smav error = bus_generic_resume(dev); 1626183097Smav HDA_BOOTHVERBOSE( 1627182999Smav device_printf(dev, "Resume done\n"); 1628162922Sariff ); 1629230130Smav return (error); 1630230130Smav} 1631164614Sariff 1632162922Sariff/**************************************************************************** 1633162922Sariff * int hdac_detach(device_t) 1634162922Sariff * 1635162922Sariff * Detach and free up resources utilized by the hdac device. 1636162922Sariff ****************************************************************************/ 1637162922Sariffstatic int 1638162922Sariffhdac_detach(device_t dev) 1639162922Sariff{ 1640230130Smav struct hdac_softc *sc = device_get_softc(dev); 1641185177Smav device_t *devlist; 1642230130Smav int cad, i, devcount, error; 1643162922Sariff 1644185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 1645185177Smav return (error); 1646185177Smav for (i = 0; i < devcount; i++) { 1647230130Smav cad = (intptr_t)device_get_ivars(devlist[i]); 1648185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 1649185178Smav free(devlist, M_TEMP); 1650185178Smav return (error); 1651185178Smav } 1652230130Smav sc->codecs[cad].dev = NULL; 1653185177Smav } 1654185177Smav free(devlist, M_TEMP); 1655185177Smav 1656230130Smav hdac_lock(sc); 1657230130Smav hdac_reset(sc, 0); 1658230130Smav hdac_unlock(sc); 1659230130Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1660230130Smav hdac_irq_free(sc); 1661162922Sariff 1662230130Smav for (i = 0; i < sc->num_ss; i++) 1663230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1664230130Smav free(sc->streams, M_HDAC); 1665230130Smav hdac_dma_free(sc, &sc->pos_dma); 1666230130Smav hdac_dma_free(sc, &sc->rirb_dma); 1667230130Smav hdac_dma_free(sc, &sc->corb_dma); 1668230130Smav if (sc->chan_dmat != NULL) { 1669230130Smav bus_dma_tag_destroy(sc->chan_dmat); 1670230130Smav sc->chan_dmat = NULL; 1671230130Smav } 1672230130Smav hdac_mem_free(sc); 1673230130Smav snd_mtxfree(sc->lock); 1674162922Sariff return (0); 1675162922Sariff} 1676162922Sariff 1677230130Smavstatic bus_dma_tag_t 1678230130Smavhdac_get_dma_tag(device_t dev, device_t child) 1679230130Smav{ 1680230130Smav struct hdac_softc *sc = device_get_softc(dev); 1681230130Smav 1682230130Smav return (sc->chan_dmat); 1683230130Smav} 1684230130Smav 1685184095Smavstatic int 1686184095Smavhdac_print_child(device_t dev, device_t child) 1687184095Smav{ 1688184095Smav int retval; 1689184095Smav 1690184095Smav retval = bus_print_child_header(dev, child); 1691230130Smav retval += printf(" at cad %d", 1692230130Smav (int)(intptr_t)device_get_ivars(child)); 1693184095Smav retval += bus_print_child_footer(dev, child); 1694184095Smav 1695184095Smav return (retval); 1696184095Smav} 1697184095Smav 1698230130Smavstatic int 1699230130Smavhdac_child_location_str(device_t dev, device_t child, char *buf, 1700230130Smav size_t buflen) 1701230130Smav{ 1702162922Sariff 1703230130Smav snprintf(buf, buflen, "cad=%d", 1704230130Smav (int)(intptr_t)device_get_ivars(child)); 1705230130Smav return (0); 1706230130Smav} 1707162922Sariff 1708230130Smavstatic int 1709230130Smavhdac_child_pnpinfo_str_method(device_t dev, device_t child, char *buf, 1710230130Smav size_t buflen) 1711230130Smav{ 1712230130Smav struct hdac_softc *sc = device_get_softc(dev); 1713230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1714182999Smav 1715230130Smav snprintf(buf, buflen, "vendor=0x%04x device=0x%04x revision=0x%02x " 1716230130Smav "stepping=0x%02x", 1717230130Smav sc->codecs[cad].vendor_id, sc->codecs[cad].device_id, 1718230130Smav sc->codecs[cad].revision_id, sc->codecs[cad].stepping_id); 1719230130Smav return (0); 1720230130Smav} 1721182999Smav 1722182999Smavstatic int 1723230130Smavhdac_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1724182999Smav{ 1725230130Smav struct hdac_softc *sc = device_get_softc(dev); 1726230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1727182999Smav 1728230130Smav switch (which) { 1729230130Smav case HDA_IVAR_CODEC_ID: 1730230130Smav *result = cad; 1731230130Smav break; 1732230130Smav case HDA_IVAR_VENDOR_ID: 1733230130Smav *result = sc->codecs[cad].vendor_id; 1734230130Smav break; 1735230130Smav case HDA_IVAR_DEVICE_ID: 1736230130Smav *result = sc->codecs[cad].device_id; 1737230130Smav break; 1738230130Smav case HDA_IVAR_REVISION_ID: 1739230130Smav *result = sc->codecs[cad].revision_id; 1740230130Smav break; 1741230130Smav case HDA_IVAR_STEPPING_ID: 1742230130Smav *result = sc->codecs[cad].stepping_id; 1743230130Smav break; 1744230130Smav case HDA_IVAR_SUBVENDOR_ID: 1745230130Smav *result = pci_get_subvendor(dev); 1746230130Smav break; 1747230130Smav case HDA_IVAR_SUBDEVICE_ID: 1748230130Smav *result = pci_get_subdevice(dev); 1749230130Smav break; 1750230130Smav case HDA_IVAR_DMA_NOCACHE: 1751230130Smav *result = (sc->flags & HDAC_F_DMA_NOCACHE) != 0; 1752230130Smav break; 1753230130Smav default: 1754230130Smav return (ENOENT); 1755230130Smav } 1756182999Smav return (0); 1757182999Smav} 1758182999Smav 1759230130Smavstatic struct mtx * 1760230130Smavhdac_get_mtx(device_t dev, device_t child) 1761182999Smav{ 1762230130Smav struct hdac_softc *sc = device_get_softc(dev); 1763182999Smav 1764230130Smav return (sc->lock); 1765230130Smav} 1766182999Smav 1767230130Smavstatic uint32_t 1768230130Smavhdac_codec_command(device_t dev, device_t child, uint32_t verb) 1769230130Smav{ 1770182999Smav 1771230130Smav return (hdac_send_command(device_get_softc(dev), 1772230130Smav (intptr_t)device_get_ivars(child), verb)); 1773230130Smav} 1774182999Smav 1775230130Smavstatic int 1776230130Smavhdac_find_stream(struct hdac_softc *sc, int dir, int stream) 1777230130Smav{ 1778230130Smav int i, ss; 1779182999Smav 1780230130Smav ss = -1; 1781230130Smav /* Allocate ISS/BSS first. */ 1782230130Smav if (dir == 0) { 1783230130Smav for (i = 0; i < sc->num_iss; i++) { 1784230130Smav if (sc->streams[i].stream == stream) { 1785230130Smav ss = i; 1786230130Smav break; 1787230130Smav } 1788230130Smav } 1789230130Smav } else { 1790230130Smav for (i = 0; i < sc->num_oss; i++) { 1791230130Smav if (sc->streams[i + sc->num_iss].stream == stream) { 1792230130Smav ss = i + sc->num_iss; 1793230130Smav break; 1794230130Smav } 1795230130Smav } 1796230130Smav } 1797230130Smav /* Fallback to BSS. */ 1798230130Smav if (ss == -1) { 1799230130Smav for (i = 0; i < sc->num_bss; i++) { 1800230130Smav if (sc->streams[i + sc->num_iss + sc->num_oss].stream 1801230130Smav == stream) { 1802230130Smav ss = i + sc->num_iss + sc->num_oss; 1803230130Smav break; 1804230130Smav } 1805230130Smav } 1806230130Smav } 1807230130Smav return (ss); 1808230130Smav} 1809182999Smav 1810230130Smavstatic int 1811230326Smavhdac_stream_alloc(device_t dev, device_t child, int dir, int format, int stripe, 1812230130Smav uint32_t **dmapos) 1813230130Smav{ 1814230130Smav struct hdac_softc *sc = device_get_softc(dev); 1815230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1816230326Smav int stream, ss, bw, maxbw, prevbw; 1817182999Smav 1818230130Smav /* Look for empty stream. */ 1819230130Smav ss = hdac_find_stream(sc, dir, 0); 1820182999Smav 1821230130Smav /* Return if found nothing. */ 1822230130Smav if (ss < 0) 1823230130Smav return (0); 1824182999Smav 1825230326Smav /* Check bus bandwidth. */ 1826230326Smav bw = hdac_bdata_rate(format, dir); 1827230326Smav if (dir == 1) { 1828230326Smav bw *= 1 << (sc->num_sdo - stripe); 1829230326Smav prevbw = sc->sdo_bw_used; 1830230326Smav maxbw = 48000 * 960 * (1 << sc->num_sdo); 1831230326Smav } else { 1832230326Smav prevbw = sc->codecs[cad].sdi_bw_used; 1833230326Smav maxbw = 48000 * 464; 1834230326Smav } 1835230326Smav HDA_BOOTHVERBOSE( 1836230326Smav device_printf(dev, "%dKbps of %dKbps bandwidth used%s\n", 1837230326Smav (bw + prevbw) / 1000, maxbw / 1000, 1838230326Smav bw + prevbw > maxbw ? " -- OVERFLOW!" : ""); 1839230326Smav ); 1840230326Smav if (bw + prevbw > maxbw) 1841230326Smav return (0); 1842230326Smav if (dir == 1) 1843230326Smav sc->sdo_bw_used += bw; 1844230326Smav else 1845230326Smav sc->codecs[cad].sdi_bw_used += bw; 1846230326Smav 1847230130Smav /* Allocate stream number */ 1848230130Smav if (ss >= sc->num_iss + sc->num_oss) 1849230130Smav stream = 15 - (ss - sc->num_iss + sc->num_oss); 1850230130Smav else if (ss >= sc->num_iss) 1851230130Smav stream = ss - sc->num_iss + 1; 1852230130Smav else 1853230130Smav stream = ss + 1; 1854182999Smav 1855230130Smav sc->streams[ss].dev = child; 1856230130Smav sc->streams[ss].dir = dir; 1857230130Smav sc->streams[ss].stream = stream; 1858230326Smav sc->streams[ss].bw = bw; 1859230130Smav sc->streams[ss].format = format; 1860230326Smav sc->streams[ss].stripe = stripe; 1861230130Smav if (dmapos != NULL) { 1862230130Smav if (sc->pos_dma.dma_vaddr != NULL) 1863230130Smav *dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8); 1864230130Smav else 1865230130Smav *dmapos = NULL; 1866230130Smav } 1867230130Smav return (stream); 1868182999Smav} 1869182999Smav 1870230130Smavstatic void 1871230130Smavhdac_stream_free(device_t dev, device_t child, int dir, int stream) 1872230130Smav{ 1873230130Smav struct hdac_softc *sc = device_get_softc(dev); 1874230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1875230130Smav int ss; 1876230130Smav 1877230130Smav ss = hdac_find_stream(sc, dir, stream); 1878230130Smav KASSERT(ss >= 0, 1879230130Smav ("Free for not allocated stream (%d/%d)\n", dir, stream)); 1880230326Smav if (dir == 1) 1881230326Smav sc->sdo_bw_used -= sc->streams[ss].bw; 1882230326Smav else 1883230326Smav sc->codecs[cad].sdi_bw_used -= sc->streams[ss].bw; 1884230130Smav sc->streams[ss].stream = 0; 1885230130Smav sc->streams[ss].dev = NULL; 1886230130Smav} 1887230130Smav 1888182999Smavstatic int 1889230130Smavhdac_stream_start(device_t dev, device_t child, 1890230130Smav int dir, int stream, bus_addr_t buf, int blksz, int blkcnt) 1891182999Smav{ 1892230130Smav struct hdac_softc *sc = device_get_softc(dev); 1893230130Smav struct hdac_bdle *bdle; 1894230130Smav uint64_t addr; 1895230130Smav int i, ss, off; 1896230130Smav uint32_t ctl; 1897182999Smav 1898230130Smav ss = hdac_find_stream(sc, dir, stream); 1899230130Smav KASSERT(ss >= 0, 1900230130Smav ("Start for not allocated stream (%d/%d)\n", dir, stream)); 1901230130Smav 1902230130Smav addr = (uint64_t)buf; 1903230130Smav bdle = (struct hdac_bdle *)sc->streams[ss].bdl.dma_vaddr; 1904230130Smav for (i = 0; i < blkcnt; i++, bdle++) { 1905230130Smav bdle->addrl = (uint32_t)addr; 1906230130Smav bdle->addrh = (uint32_t)(addr >> 32); 1907230130Smav bdle->len = blksz; 1908230130Smav bdle->ioc = 1; 1909230130Smav addr += blksz; 1910182999Smav } 1911182999Smav 1912230130Smav off = ss << 5; 1913230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDCBL, blksz * blkcnt); 1914230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDLVI, blkcnt - 1); 1915230130Smav addr = sc->streams[ss].bdl.dma_paddr; 1916230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPL, (uint32_t)addr); 1917230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1918230130Smav 1919230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL2); 1920230130Smav if (dir) 1921230130Smav ctl |= HDAC_SDCTL2_DIR; 1922230130Smav else 1923230130Smav ctl &= ~HDAC_SDCTL2_DIR; 1924230130Smav ctl &= ~HDAC_SDCTL2_STRM_MASK; 1925230130Smav ctl |= stream << HDAC_SDCTL2_STRM_SHIFT; 1926230326Smav ctl &= ~HDAC_SDCTL2_STRIPE_MASK; 1927230326Smav ctl |= sc->streams[ss].stripe << HDAC_SDCTL2_STRIPE_SHIFT; 1928230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl); 1929230130Smav 1930230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format); 1931230130Smav 1932230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1933230130Smav ctl |= 1 << ss; 1934230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1935230130Smav 1936230807Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDSTS, 1937230807Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS); 1938230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1939230130Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1940230130Smav HDAC_SDCTL_RUN; 1941230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1942230130Smav 1943230130Smav sc->streams[ss].blksz = blksz; 1944230130Smav sc->streams[ss].running = 1; 1945230130Smav hdac_poll_reinit(sc); 1946182999Smav return (0); 1947182999Smav} 1948182999Smav 1949230130Smavstatic void 1950230130Smavhdac_stream_stop(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 uint32_t ctl; 1955230130Smav 1956230130Smav ss = hdac_find_stream(sc, dir, stream); 1957230130Smav KASSERT(ss >= 0, 1958230130Smav ("Stop for not allocated stream (%d/%d)\n", dir, stream)); 1959230130Smav 1960230130Smav off = ss << 5; 1961230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1962230130Smav ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1963230130Smav HDAC_SDCTL_RUN); 1964230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1965230130Smav 1966230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1967230130Smav ctl &= ~(1 << ss); 1968230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1969230130Smav 1970230130Smav sc->streams[ss].running = 0; 1971230130Smav hdac_poll_reinit(sc); 1972230130Smav} 1973230130Smav 1974230130Smavstatic void 1975230130Smavhdac_stream_reset(device_t dev, device_t child, int dir, int stream) 1976230130Smav{ 1977230130Smav struct hdac_softc *sc = device_get_softc(dev); 1978230130Smav int timeout = 1000; 1979230130Smav int to = timeout; 1980230130Smav int ss, off; 1981230130Smav uint32_t ctl; 1982230130Smav 1983230130Smav ss = hdac_find_stream(sc, dir, stream); 1984230130Smav KASSERT(ss >= 0, 1985230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 1986230130Smav 1987230130Smav off = ss << 5; 1988230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1989230130Smav ctl |= HDAC_SDCTL_SRST; 1990230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1991230130Smav do { 1992230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1993230130Smav if (ctl & HDAC_SDCTL_SRST) 1994230130Smav break; 1995230130Smav DELAY(10); 1996230130Smav } while (--to); 1997230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 1998230130Smav device_printf(dev, "Reset setting timeout\n"); 1999230130Smav ctl &= ~HDAC_SDCTL_SRST; 2000230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 2001230130Smav to = timeout; 2002230130Smav do { 2003230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2004230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2005230130Smav break; 2006230130Smav DELAY(10); 2007230130Smav } while (--to); 2008230130Smav if (ctl & HDAC_SDCTL_SRST) 2009230130Smav device_printf(dev, "Reset timeout!\n"); 2010230130Smav} 2011230130Smav 2012230130Smavstatic uint32_t 2013230130Smavhdac_stream_getptr(device_t dev, device_t child, int dir, int stream) 2014230130Smav{ 2015230130Smav struct hdac_softc *sc = device_get_softc(dev); 2016230130Smav int ss, off; 2017230130Smav 2018230130Smav ss = hdac_find_stream(sc, dir, stream); 2019230130Smav KASSERT(ss >= 0, 2020230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 2021230130Smav 2022230130Smav off = ss << 5; 2023230130Smav return (HDAC_READ_4(&sc->mem, off + HDAC_SDLPIB)); 2024230130Smav} 2025230130Smav 2026230130Smavstatic int 2027230130Smavhdac_unsol_alloc(device_t dev, device_t child, int tag) 2028230130Smav{ 2029230130Smav struct hdac_softc *sc = device_get_softc(dev); 2030230130Smav 2031230130Smav sc->unsol_registered++; 2032230130Smav hdac_poll_reinit(sc); 2033230130Smav return (tag); 2034230130Smav} 2035230130Smav 2036230130Smavstatic void 2037230130Smavhdac_unsol_free(device_t dev, device_t child, int tag) 2038230130Smav{ 2039230130Smav struct hdac_softc *sc = device_get_softc(dev); 2040230130Smav 2041230130Smav sc->unsol_registered--; 2042230130Smav hdac_poll_reinit(sc); 2043230130Smav} 2044230130Smav 2045230130Smavstatic device_method_t hdac_methods[] = { 2046182999Smav /* device interface */ 2047230130Smav DEVMETHOD(device_probe, hdac_probe), 2048230130Smav DEVMETHOD(device_attach, hdac_attach), 2049230130Smav DEVMETHOD(device_detach, hdac_detach), 2050230130Smav DEVMETHOD(device_suspend, hdac_suspend), 2051230130Smav DEVMETHOD(device_resume, hdac_resume), 2052230130Smav /* Bus interface */ 2053230130Smav DEVMETHOD(bus_get_dma_tag, hdac_get_dma_tag), 2054230130Smav DEVMETHOD(bus_print_child, hdac_print_child), 2055230130Smav DEVMETHOD(bus_child_location_str, hdac_child_location_str), 2056230130Smav DEVMETHOD(bus_child_pnpinfo_str, hdac_child_pnpinfo_str_method), 2057230130Smav DEVMETHOD(bus_read_ivar, hdac_read_ivar), 2058230130Smav DEVMETHOD(hdac_get_mtx, hdac_get_mtx), 2059230130Smav DEVMETHOD(hdac_codec_command, hdac_codec_command), 2060230130Smav DEVMETHOD(hdac_stream_alloc, hdac_stream_alloc), 2061230130Smav DEVMETHOD(hdac_stream_free, hdac_stream_free), 2062230130Smav DEVMETHOD(hdac_stream_start, hdac_stream_start), 2063230130Smav DEVMETHOD(hdac_stream_stop, hdac_stream_stop), 2064230130Smav DEVMETHOD(hdac_stream_reset, hdac_stream_reset), 2065230130Smav DEVMETHOD(hdac_stream_getptr, hdac_stream_getptr), 2066230130Smav DEVMETHOD(hdac_unsol_alloc, hdac_unsol_alloc), 2067230130Smav DEVMETHOD(hdac_unsol_free, hdac_unsol_free), 2068182999Smav { 0, 0 } 2069182999Smav}; 2070182999Smav 2071230130Smavstatic driver_t hdac_driver = { 2072230130Smav "hdac", 2073230130Smav hdac_methods, 2074230130Smav sizeof(struct hdac_softc), 2075182999Smav}; 2076182999Smav 2077230130Smavstatic devclass_t hdac_devclass; 2078182999Smav 2079230130SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 2080