hdac.c revision 244980
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 244980 2013-01-02 21:56:58Z jfv $"); 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 }, 84244980Sjfv { HDA_INTEL_LPT1, "Intel Lynx Point", 0, 0 }, 85244980Sjfv { HDA_INTEL_LPT2, "Intel Lynx Point", 0, 0 }, 86230130Smav { HDA_INTEL_82801F, "Intel 82801F", 0, 0 }, 87230130Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0, 0 }, 88230130Smav { HDA_INTEL_82801G, "Intel 82801G", 0, 0 }, 89230130Smav { HDA_INTEL_82801H, "Intel 82801H", 0, 0 }, 90230130Smav { HDA_INTEL_82801I, "Intel 82801I", 0, 0 }, 91230130Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0, 0 }, 92230130Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0, 0 }, 93230130Smav { HDA_INTEL_PCH, "Intel 5 Series/3400 Series", 0, 0 }, 94230130Smav { HDA_INTEL_PCH2, "Intel 5 Series/3400 Series", 0, 0 }, 95230130Smav { HDA_INTEL_SCH, "Intel SCH", 0, 0 }, 96230130Smav { HDA_NVIDIA_MCP51, "NVIDIA MCP51", 0, HDAC_QUIRK_MSI }, 97230130Smav { HDA_NVIDIA_MCP55, "NVIDIA MCP55", 0, HDAC_QUIRK_MSI }, 98230130Smav { HDA_NVIDIA_MCP61_1, "NVIDIA MCP61", 0, 0 }, 99230130Smav { HDA_NVIDIA_MCP61_2, "NVIDIA MCP61", 0, 0 }, 100230130Smav { HDA_NVIDIA_MCP65_1, "NVIDIA MCP65", 0, 0 }, 101230130Smav { HDA_NVIDIA_MCP65_2, "NVIDIA MCP65", 0, 0 }, 102230130Smav { HDA_NVIDIA_MCP67_1, "NVIDIA MCP67", 0, 0 }, 103230130Smav { HDA_NVIDIA_MCP67_2, "NVIDIA MCP67", 0, 0 }, 104230130Smav { HDA_NVIDIA_MCP73_1, "NVIDIA MCP73", 0, 0 }, 105230130Smav { HDA_NVIDIA_MCP73_2, "NVIDIA MCP73", 0, 0 }, 106230130Smav { HDA_NVIDIA_MCP78_1, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 107230130Smav { HDA_NVIDIA_MCP78_2, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 108230130Smav { HDA_NVIDIA_MCP78_3, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 109230130Smav { HDA_NVIDIA_MCP78_4, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 110230130Smav { HDA_NVIDIA_MCP79_1, "NVIDIA MCP79", 0, 0 }, 111230130Smav { HDA_NVIDIA_MCP79_2, "NVIDIA MCP79", 0, 0 }, 112230130Smav { HDA_NVIDIA_MCP79_3, "NVIDIA MCP79", 0, 0 }, 113230130Smav { HDA_NVIDIA_MCP79_4, "NVIDIA MCP79", 0, 0 }, 114230130Smav { HDA_NVIDIA_MCP89_1, "NVIDIA MCP89", 0, 0 }, 115230130Smav { HDA_NVIDIA_MCP89_2, "NVIDIA MCP89", 0, 0 }, 116230130Smav { HDA_NVIDIA_MCP89_3, "NVIDIA MCP89", 0, 0 }, 117230130Smav { HDA_NVIDIA_MCP89_4, "NVIDIA MCP89", 0, 0 }, 118230331Smav { HDA_NVIDIA_0BE2, "NVIDIA (0x0be2)", 0, HDAC_QUIRK_MSI }, 119230331Smav { HDA_NVIDIA_0BE3, "NVIDIA (0x0be3)", 0, HDAC_QUIRK_MSI }, 120230331Smav { HDA_NVIDIA_0BE4, "NVIDIA (0x0be4)", 0, HDAC_QUIRK_MSI }, 121230312Smav { HDA_NVIDIA_GT100, "NVIDIA GT100", 0, HDAC_QUIRK_MSI }, 122230312Smav { HDA_NVIDIA_GT104, "NVIDIA GT104", 0, HDAC_QUIRK_MSI }, 123230312Smav { HDA_NVIDIA_GT106, "NVIDIA GT106", 0, HDAC_QUIRK_MSI }, 124230312Smav { HDA_NVIDIA_GT108, "NVIDIA GT108", 0, HDAC_QUIRK_MSI }, 125230312Smav { HDA_NVIDIA_GT116, "NVIDIA GT116", 0, HDAC_QUIRK_MSI }, 126230312Smav { HDA_NVIDIA_GF119, "NVIDIA GF119", 0, 0 }, 127230312Smav { HDA_NVIDIA_GF110_1, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 128230312Smav { HDA_NVIDIA_GF110_2, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 129230130Smav { HDA_ATI_SB450, "ATI SB450", 0, 0 }, 130230130Smav { HDA_ATI_SB600, "ATI SB600", 0, 0 }, 131230130Smav { HDA_ATI_RS600, "ATI RS600", 0, 0 }, 132230130Smav { HDA_ATI_RS690, "ATI RS690", 0, 0 }, 133230130Smav { HDA_ATI_RS780, "ATI RS780", 0, 0 }, 134230130Smav { HDA_ATI_R600, "ATI R600", 0, 0 }, 135230130Smav { HDA_ATI_RV610, "ATI RV610", 0, 0 }, 136230130Smav { HDA_ATI_RV620, "ATI RV620", 0, 0 }, 137230130Smav { HDA_ATI_RV630, "ATI RV630", 0, 0 }, 138230130Smav { HDA_ATI_RV635, "ATI RV635", 0, 0 }, 139230130Smav { HDA_ATI_RV710, "ATI RV710", 0, 0 }, 140230130Smav { HDA_ATI_RV730, "ATI RV730", 0, 0 }, 141230130Smav { HDA_ATI_RV740, "ATI RV740", 0, 0 }, 142230130Smav { HDA_ATI_RV770, "ATI RV770", 0, 0 }, 143239908Smav { HDA_ATI_RV810, "ATI RV810", 0, 0 }, 144239908Smav { HDA_ATI_RV830, "ATI RV830", 0, 0 }, 145239908Smav { HDA_ATI_RV840, "ATI RV840", 0, 0 }, 146239908Smav { HDA_ATI_RV870, "ATI RV870", 0, 0 }, 147239908Smav { HDA_ATI_RV910, "ATI RV910", 0, 0 }, 148239908Smav { HDA_ATI_RV930, "ATI RV930", 0, 0 }, 149239908Smav { HDA_ATI_RV940, "ATI RV940", 0, 0 }, 150239908Smav { HDA_ATI_RV970, "ATI RV970", 0, 0 }, 151239908Smav { HDA_ATI_R1000, "ATI R1000", 0, 0 }, 152230130Smav { HDA_RDC_M3010, "RDC M3010", 0, 0 }, 153230130Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 }, 154230130Smav { HDA_SIS_966, "SiS 966", 0, 0 }, 155230130Smav { HDA_ULI_M5461, "ULI M5461", 0, 0 }, 156162922Sariff /* Unknown */ 157230331Smav { HDA_INTEL_ALL, "Intel", 0, 0 }, 158230331Smav { HDA_NVIDIA_ALL, "NVIDIA", 0, 0 }, 159230331Smav { HDA_ATI_ALL, "ATI", 0, 0 }, 160230331Smav { HDA_VIA_ALL, "VIA", 0, 0 }, 161230331Smav { HDA_SIS_ALL, "SiS", 0, 0 }, 162230331Smav { HDA_ULI_ALL, "ULI", 0, 0 }, 163162922Sariff}; 164162922Sariff#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0])) 165162922Sariff 166162922Sariffstatic const struct { 167169277Sariff uint16_t vendor; 168169277Sariff uint8_t reg; 169169277Sariff uint8_t mask; 170169277Sariff uint8_t enable; 171169277Sariff} hdac_pcie_snoop[] = { 172169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 173169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 174169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 175169277Sariff}; 176169277Sariff#define HDAC_PCIESNOOP_LEN \ 177169277Sariff (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0])) 178169277Sariff 179162922Sariff/**************************************************************************** 180162922Sariff * Function prototypes 181162922Sariff ****************************************************************************/ 182162922Sariffstatic void hdac_intr_handler(void *); 183182999Smavstatic int hdac_reset(struct hdac_softc *, int); 184162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 185162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 186162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 187162922Sariff struct hdac_dma *, bus_size_t); 188169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 189162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 190162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 191162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 192162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 193162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 194162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 195162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 196162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 197162922Sariff 198162922Sariffstatic void hdac_attach2(void *); 199162922Sariff 200230130Smavstatic uint32_t hdac_send_command(struct hdac_softc *, nid_t, uint32_t); 201162922Sariff 202162922Sariffstatic int hdac_probe(device_t); 203162922Sariffstatic int hdac_attach(device_t); 204162922Sariffstatic int hdac_detach(device_t); 205182999Smavstatic int hdac_suspend(device_t); 206182999Smavstatic int hdac_resume(device_t); 207162922Sariff 208164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 209164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 210164614Sariff 211162922Sariff#define hdac_command(a1, a2, a3) \ 212230130Smav hdac_send_command(a1, a3, a2) 213162922Sariff 214230130Smav/* This function surely going to make its way into upper level someday. */ 215162922Sariffstatic void 216230130Smavhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 217162922Sariff{ 218230130Smav const char *res = NULL; 219230130Smav int i = 0, j, k, len, inv; 220162922Sariff 221230130Smav if (resource_string_value(device_get_name(sc->dev), 222230130Smav device_get_unit(sc->dev), "config", &res) != 0) 223162922Sariff return; 224230130Smav if (!(res != NULL && strlen(res) > 0)) 225230130Smav return; 226230130Smav HDA_BOOTVERBOSE( 227230130Smav device_printf(sc->dev, "Config options:"); 228230130Smav ); 229230130Smav for (;;) { 230230130Smav while (res[i] != '\0' && 231230130Smav (res[i] == ',' || isspace(res[i]) != 0)) 232230130Smav i++; 233230130Smav if (res[i] == '\0') { 234230130Smav HDA_BOOTVERBOSE( 235230130Smav printf("\n"); 236230130Smav ); 237230130Smav return; 238182999Smav } 239230130Smav j = i; 240230130Smav while (res[j] != '\0' && 241230130Smav !(res[j] == ',' || isspace(res[j]) != 0)) 242230130Smav j++; 243230130Smav len = j - i; 244230130Smav if (len > 2 && strncmp(res + i, "no", 2) == 0) 245230130Smav inv = 2; 246230130Smav else 247230130Smav inv = 0; 248230130Smav for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) { 249230130Smav if (strncmp(res + i + inv, 250230130Smav hdac_quirks_tab[k].key, len - inv) != 0) 251182999Smav continue; 252230130Smav if (len - inv != strlen(hdac_quirks_tab[k].key)) 253182999Smav continue; 254230130Smav HDA_BOOTVERBOSE( 255230130Smav printf(" %s%s", (inv != 0) ? "no" : "", 256230130Smav hdac_quirks_tab[k].key); 257230130Smav ); 258230130Smav if (inv == 0) { 259230130Smav *on |= hdac_quirks_tab[k].value; 260230130Smav *on &= ~hdac_quirks_tab[k].value; 261230130Smav } else if (inv != 0) { 262230130Smav *off |= hdac_quirks_tab[k].value; 263230130Smav *off &= ~hdac_quirks_tab[k].value; 264162922Sariff } 265162965Sariff break; 266182999Smav } 267230130Smav i = j; 268162922Sariff } 269162922Sariff} 270162922Sariff 271162922Sariff/**************************************************************************** 272162922Sariff * void hdac_intr_handler(void *) 273162922Sariff * 274162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 275162922Sariff ****************************************************************************/ 276162922Sariffstatic void 277162922Sariffhdac_intr_handler(void *context) 278162922Sariff{ 279162922Sariff struct hdac_softc *sc; 280230130Smav device_t dev; 281162922Sariff uint32_t intsts; 282162922Sariff uint8_t rirbsts; 283182999Smav int i; 284162922Sariff 285162922Sariff sc = (struct hdac_softc *)context; 286162922Sariff hdac_lock(sc); 287171141Sariff 288162922Sariff /* Do we have anything to do? */ 289162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 290230130Smav if ((intsts & HDAC_INTSTS_GIS) == 0) { 291162922Sariff hdac_unlock(sc); 292162922Sariff return; 293162922Sariff } 294162922Sariff 295162922Sariff /* Was this a controller interrupt? */ 296230130Smav if (intsts & HDAC_INTSTS_CIS) { 297162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 298162922Sariff /* Get as many responses that we can */ 299230130Smav while (rirbsts & HDAC_RIRBSTS_RINTFL) { 300164614Sariff HDAC_WRITE_1(&sc->mem, 301164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 302230130Smav hdac_rirb_flush(sc); 303162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 304162922Sariff } 305230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 306230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 307162922Sariff } 308164614Sariff 309163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 310230130Smav for (i = 0; i < sc->num_ss; i++) { 311230130Smav if ((intsts & (1 << i)) == 0) 312230130Smav continue; 313230130Smav HDAC_WRITE_1(&sc->mem, (i << 5) + HDAC_SDSTS, 314230130Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 315230130Smav if ((dev = sc->streams[i].dev) != NULL) { 316230130Smav HDAC_STREAM_INTR(dev, 317230130Smav sc->streams[i].dir, sc->streams[i].stream); 318230130Smav } 319182999Smav } 320162922Sariff } 321162922Sariff 322230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts); 323164614Sariff hdac_unlock(sc); 324230130Smav} 325162922Sariff 326230130Smavstatic void 327230130Smavhdac_poll_callback(void *arg) 328230130Smav{ 329230130Smav struct hdac_softc *sc = arg; 330230130Smav 331230130Smav if (sc == NULL) 332230130Smav return; 333230130Smav 334230130Smav hdac_lock(sc); 335230130Smav if (sc->polling == 0) { 336230130Smav hdac_unlock(sc); 337230130Smav return; 338182999Smav } 339230130Smav callout_reset(&sc->poll_callout, sc->poll_ival, 340230130Smav hdac_poll_callback, sc); 341230130Smav hdac_unlock(sc); 342230130Smav 343230130Smav hdac_intr_handler(sc); 344162922Sariff} 345162922Sariff 346162922Sariff/**************************************************************************** 347182999Smav * int hdac_reset(hdac_softc *, int) 348162922Sariff * 349162922Sariff * Reset the hdac to a quiescent and known state. 350162922Sariff ****************************************************************************/ 351162922Sariffstatic int 352182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 353162922Sariff{ 354162922Sariff uint32_t gctl; 355162922Sariff int count, i; 356162922Sariff 357162922Sariff /* 358162922Sariff * Stop all Streams DMA engine 359162922Sariff */ 360162922Sariff for (i = 0; i < sc->num_iss; i++) 361162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 362162922Sariff for (i = 0; i < sc->num_oss; i++) 363162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 364162922Sariff for (i = 0; i < sc->num_bss; i++) 365162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 366162922Sariff 367162922Sariff /* 368169277Sariff * Stop Control DMA engines. 369162922Sariff */ 370162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 371162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 372162922Sariff 373162922Sariff /* 374169277Sariff * Reset DMA position buffer. 375169277Sariff */ 376169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 377169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 378169277Sariff 379169277Sariff /* 380162922Sariff * Reset the controller. The reset must remain asserted for 381162922Sariff * a minimum of 100us. 382162922Sariff */ 383162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 384162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST); 385162922Sariff count = 10000; 386162922Sariff do { 387162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 388162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 389162922Sariff break; 390162922Sariff DELAY(10); 391162922Sariff } while (--count); 392162922Sariff if (gctl & HDAC_GCTL_CRST) { 393162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 394162922Sariff return (ENXIO); 395162922Sariff } 396230130Smav 397182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 398182999Smav if (!wakeup) 399182999Smav return (0); 400230130Smav 401162922Sariff DELAY(100); 402162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 403162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 404162922Sariff count = 10000; 405162922Sariff do { 406162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 407163057Sariff if (gctl & HDAC_GCTL_CRST) 408162922Sariff break; 409162922Sariff DELAY(10); 410162922Sariff } while (--count); 411162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 412162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 413162922Sariff return (ENXIO); 414162922Sariff } 415162922Sariff 416162922Sariff /* 417162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 418162922Sariff * should be of 250us but for some reasons, on it's not enough on my 419162922Sariff * computer. Let's use twice as much as necessary to make sure that 420162922Sariff * it's reset properly. 421162922Sariff */ 422162922Sariff DELAY(1000); 423162922Sariff 424162922Sariff return (0); 425162922Sariff} 426162922Sariff 427162922Sariff 428162922Sariff/**************************************************************************** 429162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 430162922Sariff * 431162922Sariff * Retreive the general capabilities of the hdac; 432162922Sariff * Number of Input Streams 433162922Sariff * Number of Output Streams 434162922Sariff * Number of bidirectional Streams 435162922Sariff * 64bit ready 436162922Sariff * CORB and RIRB sizes 437162922Sariff ****************************************************************************/ 438162922Sariffstatic int 439162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 440162922Sariff{ 441162922Sariff uint16_t gcap; 442162922Sariff uint8_t corbsize, rirbsize; 443162922Sariff 444162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 445162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 446162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 447162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 448230130Smav sc->num_ss = sc->num_iss + sc->num_oss + sc->num_bss; 449196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 450230130Smav sc->support_64bit = (gcap & HDAC_GCAP_64OK) != 0; 451230130Smav if (sc->quirks_on & HDAC_QUIRK_64BIT) 452230130Smav sc->support_64bit = 1; 453230130Smav else if (sc->quirks_off & HDAC_QUIRK_64BIT) 454230130Smav sc->support_64bit = 0; 455162922Sariff 456162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 457162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 458162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 459162922Sariff sc->corb_size = 256; 460162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 461162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 462162922Sariff sc->corb_size = 16; 463162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 464162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 465162922Sariff sc->corb_size = 2; 466162922Sariff else { 467162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 468162922Sariff __func__, corbsize); 469162922Sariff return (ENXIO); 470162922Sariff } 471162922Sariff 472162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 473162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 474162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 475162922Sariff sc->rirb_size = 256; 476162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 477162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 478162922Sariff sc->rirb_size = 16; 479162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 480162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 481162922Sariff sc->rirb_size = 2; 482162922Sariff else { 483162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 484162922Sariff __func__, rirbsize); 485162922Sariff return (ENXIO); 486162922Sariff } 487162922Sariff 488196762Smav HDA_BOOTVERBOSE( 489196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 490196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 491196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 492196762Smav sc->support_64bit ? ", 64bit" : "", 493196762Smav sc->corb_size, sc->rirb_size); 494182999Smav ); 495182999Smav 496162922Sariff return (0); 497162922Sariff} 498162922Sariff 499162922Sariff 500162922Sariff/**************************************************************************** 501162922Sariff * void hdac_dma_cb 502162922Sariff * 503162922Sariff * This function is called by bus_dmamap_load when the mapping has been 504162922Sariff * established. We just record the physical address of the mapping into 505162922Sariff * the struct hdac_dma passed in. 506162922Sariff ****************************************************************************/ 507162922Sariffstatic void 508162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 509162922Sariff{ 510162922Sariff struct hdac_dma *dma; 511162922Sariff 512162922Sariff if (error == 0) { 513162922Sariff dma = (struct hdac_dma *)callback_arg; 514162922Sariff dma->dma_paddr = segs[0].ds_addr; 515162922Sariff } 516162922Sariff} 517162922Sariff 518162922Sariff 519162922Sariff/**************************************************************************** 520162922Sariff * int hdac_dma_alloc 521162922Sariff * 522162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 523162922Sariff * It must be freed by a corresponding hdac_dma_free. 524162922Sariff ****************************************************************************/ 525162922Sariffstatic int 526162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 527162922Sariff{ 528169277Sariff bus_size_t roundsz; 529162922Sariff int result; 530162922Sariff 531230130Smav roundsz = roundup2(size, HDA_DMA_ALIGNMENT); 532162922Sariff bzero(dma, sizeof(*dma)); 533162922Sariff 534162922Sariff /* 535162922Sariff * Create a DMA tag 536162922Sariff */ 537194861Smav result = bus_dma_tag_create( 538194861Smav bus_get_dma_tag(sc->dev), /* parent */ 539230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 540162922Sariff 0, /* boundary */ 541194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 542194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 543162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 544162922Sariff NULL, /* filtfunc */ 545162922Sariff NULL, /* fistfuncarg */ 546169277Sariff roundsz, /* maxsize */ 547162922Sariff 1, /* nsegments */ 548169277Sariff roundsz, /* maxsegsz */ 549162922Sariff 0, /* flags */ 550162922Sariff NULL, /* lockfunc */ 551162922Sariff NULL, /* lockfuncarg */ 552162922Sariff &dma->dma_tag); /* dmat */ 553162922Sariff if (result != 0) { 554162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 555162922Sariff __func__, result); 556167773Sariff goto hdac_dma_alloc_fail; 557162922Sariff } 558162922Sariff 559162922Sariff /* 560162922Sariff * Allocate DMA memory 561162922Sariff */ 562162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 563169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 564171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 565171330Sariff &dma->dma_map); 566162922Sariff if (result != 0) { 567162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 568162922Sariff __func__, result); 569167773Sariff goto hdac_dma_alloc_fail; 570162922Sariff } 571162922Sariff 572169277Sariff dma->dma_size = roundsz; 573169277Sariff 574162922Sariff /* 575162922Sariff * Map the memory 576162922Sariff */ 577162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 578169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 579162922Sariff if (result != 0 || dma->dma_paddr == 0) { 580167773Sariff if (result == 0) 581167773Sariff result = ENOMEM; 582162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 583162922Sariff __func__, result); 584167773Sariff goto hdac_dma_alloc_fail; 585162922Sariff } 586162922Sariff 587183097Smav HDA_BOOTHVERBOSE( 588169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 589169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 590169277Sariff ); 591169277Sariff 592162922Sariff return (0); 593169277Sariff 594167773Sariffhdac_dma_alloc_fail: 595169277Sariff hdac_dma_free(sc, dma); 596167773Sariff 597162922Sariff return (result); 598162922Sariff} 599162922Sariff 600162922Sariff 601162922Sariff/**************************************************************************** 602169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 603162922Sariff * 604162922Sariff * Free a struct dhac_dma that has been previously allocated via the 605162922Sariff * hdac_dma_alloc function. 606162922Sariff ****************************************************************************/ 607162922Sariffstatic void 608169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 609162922Sariff{ 610167773Sariff if (dma->dma_map != NULL) { 611169277Sariff#if 0 612162922Sariff /* Flush caches */ 613162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 614162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 615169277Sariff#endif 616162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 617167773Sariff } 618167773Sariff if (dma->dma_vaddr != NULL) { 619162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 620167773Sariff dma->dma_vaddr = NULL; 621167773Sariff } 622167773Sariff dma->dma_map = NULL; 623167773Sariff if (dma->dma_tag != NULL) { 624162922Sariff bus_dma_tag_destroy(dma->dma_tag); 625167773Sariff dma->dma_tag = NULL; 626162922Sariff } 627167773Sariff dma->dma_size = 0; 628162922Sariff} 629162922Sariff 630162922Sariff/**************************************************************************** 631162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 632162922Sariff * 633162922Sariff * Allocate all the bus resources necessary to speak with the physical 634162922Sariff * controller. 635162922Sariff ****************************************************************************/ 636162922Sariffstatic int 637162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 638162922Sariff{ 639162922Sariff struct hdac_mem *mem; 640162922Sariff 641162922Sariff mem = &sc->mem; 642162922Sariff mem->mem_rid = PCIR_BAR(0); 643162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 644162922Sariff &mem->mem_rid, RF_ACTIVE); 645162922Sariff if (mem->mem_res == NULL) { 646162922Sariff device_printf(sc->dev, 647162922Sariff "%s: Unable to allocate memory resource\n", __func__); 648162922Sariff return (ENOMEM); 649162922Sariff } 650162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 651162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 652162922Sariff 653162922Sariff return (0); 654162922Sariff} 655162922Sariff 656162922Sariff/**************************************************************************** 657162922Sariff * void hdac_mem_free(struct hdac_softc *) 658162922Sariff * 659162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 660162922Sariff ****************************************************************************/ 661162922Sariffstatic void 662162922Sariffhdac_mem_free(struct hdac_softc *sc) 663162922Sariff{ 664162922Sariff struct hdac_mem *mem; 665162922Sariff 666162922Sariff mem = &sc->mem; 667162922Sariff if (mem->mem_res != NULL) 668162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 669162922Sariff mem->mem_res); 670164614Sariff mem->mem_res = NULL; 671162922Sariff} 672162922Sariff 673162922Sariff/**************************************************************************** 674162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 675162922Sariff * 676162922Sariff * Allocate and setup the resources necessary for interrupt handling. 677162922Sariff ****************************************************************************/ 678162922Sariffstatic int 679162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 680162922Sariff{ 681162922Sariff struct hdac_irq *irq; 682162922Sariff int result; 683162922Sariff 684162922Sariff irq = &sc->irq; 685162922Sariff irq->irq_rid = 0x0; 686171330Sariff 687230130Smav if ((sc->quirks_off & HDAC_QUIRK_MSI) == 0 && 688171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 689171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 690171330Sariff irq->irq_rid = 0x1; 691171330Sariff 692162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 693162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 694162922Sariff if (irq->irq_res == NULL) { 695162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 696162922Sariff __func__); 697167773Sariff goto hdac_irq_alloc_fail; 698162922Sariff } 699182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 700182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 701162922Sariff if (result != 0) { 702162922Sariff device_printf(sc->dev, 703162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 704162922Sariff __func__, result); 705167773Sariff goto hdac_irq_alloc_fail; 706162922Sariff } 707162922Sariff 708162922Sariff return (0); 709162922Sariff 710167773Sariffhdac_irq_alloc_fail: 711164614Sariff hdac_irq_free(sc); 712164614Sariff 713162922Sariff return (ENXIO); 714162922Sariff} 715162922Sariff 716162922Sariff/**************************************************************************** 717162922Sariff * void hdac_irq_free(struct hdac_softc *) 718162922Sariff * 719162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 720162922Sariff ****************************************************************************/ 721162922Sariffstatic void 722162922Sariffhdac_irq_free(struct hdac_softc *sc) 723162922Sariff{ 724162922Sariff struct hdac_irq *irq; 725162922Sariff 726162922Sariff irq = &sc->irq; 727164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 728162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 729162922Sariff if (irq->irq_res != NULL) 730162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 731162922Sariff irq->irq_res); 732188656Smav if (irq->irq_rid == 0x1) 733171330Sariff pci_release_msi(sc->dev); 734164614Sariff irq->irq_handle = NULL; 735164614Sariff irq->irq_res = NULL; 736171330Sariff irq->irq_rid = 0x0; 737162922Sariff} 738162922Sariff 739162922Sariff/**************************************************************************** 740162922Sariff * void hdac_corb_init(struct hdac_softc *) 741162922Sariff * 742162922Sariff * Initialize the corb registers for operations but do not start it up yet. 743162922Sariff * The CORB engine must not be running when this function is called. 744162922Sariff ****************************************************************************/ 745162922Sariffstatic void 746162922Sariffhdac_corb_init(struct hdac_softc *sc) 747162922Sariff{ 748162922Sariff uint8_t corbsize; 749162922Sariff uint64_t corbpaddr; 750162922Sariff 751162922Sariff /* Setup the CORB size. */ 752162922Sariff switch (sc->corb_size) { 753162922Sariff case 256: 754162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 755162922Sariff break; 756162922Sariff case 16: 757162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 758162922Sariff break; 759162922Sariff case 2: 760162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 761162922Sariff break; 762162922Sariff default: 763162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 764162922Sariff } 765162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 766162922Sariff 767162922Sariff /* Setup the CORB Address in the hdac */ 768162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 769162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 770162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 771162922Sariff 772162922Sariff /* Set the WP and RP */ 773162922Sariff sc->corb_wp = 0; 774162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 775162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 776162922Sariff /* 777162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 778162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 779162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 780162922Sariff * manually reset the bit to zero before continuing. 781162922Sariff */ 782162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 783162922Sariff 784162922Sariff /* Enable CORB error reporting */ 785162922Sariff#if 0 786162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 787162922Sariff#endif 788162922Sariff} 789162922Sariff 790162922Sariff/**************************************************************************** 791162922Sariff * void hdac_rirb_init(struct hdac_softc *) 792162922Sariff * 793162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 794162922Sariff * The RIRB engine must not be running when this function is called. 795162922Sariff ****************************************************************************/ 796162922Sariffstatic void 797162922Sariffhdac_rirb_init(struct hdac_softc *sc) 798162922Sariff{ 799162922Sariff uint8_t rirbsize; 800162922Sariff uint64_t rirbpaddr; 801162922Sariff 802162922Sariff /* Setup the RIRB size. */ 803162922Sariff switch (sc->rirb_size) { 804162922Sariff case 256: 805162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 806162922Sariff break; 807162922Sariff case 16: 808162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 809162922Sariff break; 810162922Sariff case 2: 811162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 812162922Sariff break; 813162922Sariff default: 814162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 815162922Sariff } 816162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 817162922Sariff 818162922Sariff /* Setup the RIRB Address in the hdac */ 819162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 820162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 821162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 822162922Sariff 823162922Sariff /* Setup the WP and RP */ 824162922Sariff sc->rirb_rp = 0; 825162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 826162922Sariff 827182999Smav /* Setup the interrupt threshold */ 828182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 829162922Sariff 830182999Smav /* Enable Overrun and response received reporting */ 831162922Sariff#if 0 832182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 833182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 834162922Sariff#else 835182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 836162922Sariff#endif 837162922Sariff 838169277Sariff#if 0 839162922Sariff /* 840162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 841162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 842162922Sariff * should be sufficient to do this only once as the rirb is purely 843162922Sariff * read-only from now on. 844162922Sariff */ 845162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 846162922Sariff BUS_DMASYNC_PREREAD); 847169277Sariff#endif 848162922Sariff} 849162922Sariff 850162922Sariff/**************************************************************************** 851162922Sariff * void hdac_corb_start(hdac_softc *) 852162922Sariff * 853162922Sariff * Startup the corb DMA engine 854162922Sariff ****************************************************************************/ 855162922Sariffstatic void 856162922Sariffhdac_corb_start(struct hdac_softc *sc) 857162922Sariff{ 858162922Sariff uint32_t corbctl; 859162922Sariff 860162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 861162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 862162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 863162922Sariff} 864162922Sariff 865162922Sariff/**************************************************************************** 866162922Sariff * void hdac_rirb_start(hdac_softc *) 867162922Sariff * 868162922Sariff * Startup the rirb DMA engine 869162922Sariff ****************************************************************************/ 870162922Sariffstatic void 871162922Sariffhdac_rirb_start(struct hdac_softc *sc) 872162922Sariff{ 873162922Sariff uint32_t rirbctl; 874162922Sariff 875162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 876162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 877162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 878162922Sariff} 879162922Sariff 880164614Sariffstatic int 881164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 882164614Sariff{ 883164614Sariff struct hdac_rirb *rirb_base, *rirb; 884164614Sariff nid_t cad; 885164614Sariff uint32_t resp; 886164614Sariff uint8_t rirbwp; 887171141Sariff int ret; 888164614Sariff 889164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 890164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 891169277Sariff#if 0 892164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 893164614Sariff BUS_DMASYNC_POSTREAD); 894169277Sariff#endif 895164614Sariff 896171141Sariff ret = 0; 897164614Sariff while (sc->rirb_rp != rirbwp) { 898164614Sariff sc->rirb_rp++; 899164614Sariff sc->rirb_rp %= sc->rirb_size; 900164614Sariff rirb = &rirb_base[sc->rirb_rp]; 901164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 902164614Sariff resp = rirb->response; 903164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 904230130Smav sc->unsolq[sc->unsolq_wp++] = resp; 905164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 906230130Smav sc->unsolq[sc->unsolq_wp++] = cad; 907230130Smav sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 908230130Smav } else if (sc->codecs[cad].pending <= 0) { 909230130Smav device_printf(sc->dev, "Unexpected unsolicited " 910230130Smav "response from address %d: %08x\n", cad, resp); 911230130Smav } else { 912230130Smav sc->codecs[cad].response = resp; 913230130Smav sc->codecs[cad].pending--; 914230130Smav } 915164614Sariff ret++; 916164614Sariff } 917164614Sariff return (ret); 918164614Sariff} 919164614Sariff 920164614Sariffstatic int 921164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 922164614Sariff{ 923230130Smav device_t child; 924164614Sariff nid_t cad; 925230130Smav uint32_t resp; 926164614Sariff int ret = 0; 927164614Sariff 928164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 929164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 930164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 931230130Smav resp = sc->unsolq[sc->unsolq_rp++]; 932164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 933230130Smav cad = sc->unsolq[sc->unsolq_rp++]; 934230130Smav sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 935230130Smav if ((child = sc->codecs[cad].dev) != NULL) 936230130Smav HDAC_UNSOL_INTR(child, resp); 937164614Sariff ret++; 938164614Sariff } 939164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 940164614Sariff } 941164614Sariff 942164614Sariff return (ret); 943164614Sariff} 944164614Sariff 945162922Sariff/**************************************************************************** 946162922Sariff * uint32_t hdac_command_sendone_internal 947162922Sariff * 948162922Sariff * Wrapper function that sends only one command to a given codec 949162922Sariff ****************************************************************************/ 950162922Sariffstatic uint32_t 951230130Smavhdac_send_command(struct hdac_softc *sc, nid_t cad, uint32_t verb) 952162922Sariff{ 953230130Smav int timeout; 954230130Smav uint32_t *corb; 955162922Sariff 956163057Sariff if (!hdac_lockowned(sc)) 957162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 958230130Smav verb &= ~HDA_CMD_CAD_MASK; 959230130Smav verb |= ((uint32_t)cad) << HDA_CMD_CAD_SHIFT; 960230130Smav sc->codecs[cad].response = HDA_INVALID; 961162922Sariff 962230130Smav sc->codecs[cad].pending++; 963230130Smav sc->corb_wp++; 964230130Smav sc->corb_wp %= sc->corb_size; 965162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 966169277Sariff#if 0 967230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 968230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 969169277Sariff#endif 970230130Smav corb[sc->corb_wp] = verb; 971169277Sariff#if 0 972230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 973230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 974169277Sariff#endif 975230130Smav HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 976162922Sariff 977230130Smav timeout = 10000; 978230130Smav do { 979230130Smav if (hdac_rirb_flush(sc) == 0) 980162922Sariff DELAY(10); 981230130Smav } while (sc->codecs[cad].pending != 0 && --timeout); 982162922Sariff 983230130Smav if (sc->codecs[cad].pending != 0) { 984230130Smav device_printf(sc->dev, "Command timeout on address %d\n", cad); 985230130Smav sc->codecs[cad].pending = 0; 986230130Smav } 987162922Sariff 988230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 989230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 990230130Smav return (sc->codecs[cad].response); 991162922Sariff} 992162922Sariff 993162922Sariff/**************************************************************************** 994162922Sariff * Device Methods 995162922Sariff ****************************************************************************/ 996162922Sariff 997162922Sariff/**************************************************************************** 998162922Sariff * int hdac_probe(device_t) 999162922Sariff * 1000162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 1001162922Sariff * match using the subclass of the device. 1002162922Sariff ****************************************************************************/ 1003162922Sariffstatic int 1004162922Sariffhdac_probe(device_t dev) 1005162922Sariff{ 1006162922Sariff int i, result; 1007163257Sariff uint32_t model; 1008163257Sariff uint16_t class, subclass; 1009162922Sariff char desc[64]; 1010162922Sariff 1011162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 1012162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1013162922Sariff class = pci_get_class(dev); 1014162922Sariff subclass = pci_get_subclass(dev); 1015162922Sariff 1016162922Sariff bzero(desc, sizeof(desc)); 1017162922Sariff result = ENXIO; 1018162922Sariff for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1019162922Sariff if (hdac_devices[i].model == model) { 1020230331Smav strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1021230331Smav result = BUS_PROBE_DEFAULT; 1022162922Sariff break; 1023162922Sariff } 1024163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1025162922Sariff class == PCIC_MULTIMEDIA && 1026162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1027230331Smav snprintf(desc, sizeof(desc), 1028230331Smav "%s (0x%04x)", 1029230331Smav hdac_devices[i].desc, pci_get_device(dev)); 1030230331Smav result = BUS_PROBE_GENERIC; 1031162922Sariff break; 1032162922Sariff } 1033162922Sariff } 1034162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 1035162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1036230331Smav snprintf(desc, sizeof(desc), "Generic (0x%08x)", model); 1037230331Smav result = BUS_PROBE_GENERIC; 1038162922Sariff } 1039162922Sariff if (result != ENXIO) { 1040230331Smav strlcat(desc, " HDA Controller", sizeof(desc)); 1041162922Sariff device_set_desc_copy(dev, desc); 1042162922Sariff } 1043162922Sariff 1044162922Sariff return (result); 1045162922Sariff} 1046162922Sariff 1047162922Sariffstatic void 1048171141Sariffhdac_unsolq_task(void *context, int pending) 1049171141Sariff{ 1050171141Sariff struct hdac_softc *sc; 1051171141Sariff 1052171141Sariff sc = (struct hdac_softc *)context; 1053171141Sariff 1054171141Sariff hdac_lock(sc); 1055171141Sariff hdac_unsolq_flush(sc); 1056171141Sariff hdac_unlock(sc); 1057171141Sariff} 1058171141Sariff 1059162922Sariff/**************************************************************************** 1060162922Sariff * int hdac_attach(device_t) 1061162922Sariff * 1062162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 1063162922Sariff * when this function is called. Setup everything that doesn't require 1064162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 1065162922Sariff ****************************************************************************/ 1066162922Sariffstatic int 1067162922Sariffhdac_attach(device_t dev) 1068162922Sariff{ 1069162922Sariff struct hdac_softc *sc; 1070162922Sariff int result; 1071189086Smav int i, devid = -1; 1072189086Smav uint32_t model; 1073189086Smav uint16_t class, subclass; 1074169277Sariff uint16_t vendor; 1075169277Sariff uint8_t v; 1076162922Sariff 1077230130Smav sc = device_get_softc(dev); 1078223118Sjoel HDA_BOOTVERBOSE( 1079242352Smav device_printf(dev, "PCI card vendor: 0x%04x, device: 0x%04x\n", 1080242352Smav pci_get_subvendor(dev), pci_get_subdevice(dev)); 1081223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 1082223118Sjoel HDA_DRV_TEST_REV); 1083223118Sjoel ); 1084182999Smav 1085189086Smav model = (uint32_t)pci_get_device(dev) << 16; 1086189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1087189086Smav class = pci_get_class(dev); 1088189086Smav subclass = pci_get_subclass(dev); 1089189086Smav 1090189086Smav for (i = 0; i < HDAC_DEVICES_LEN; i++) { 1091189086Smav if (hdac_devices[i].model == model) { 1092189086Smav devid = i; 1093189086Smav break; 1094189086Smav } 1095189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1096189086Smav class == PCIC_MULTIMEDIA && 1097189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 1098189086Smav devid = i; 1099189086Smav break; 1100189086Smav } 1101189086Smav } 1102189086Smav 1103230130Smav sc->lock = snd_mtxcreate(device_get_nameunit(dev), "HDA driver mutex"); 1104162922Sariff sc->dev = dev; 1105230130Smav TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 1106230130Smav callout_init(&sc->poll_callout, CALLOUT_MPSAFE); 1107230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) 1108230130Smav sc->codecs[i].dev = NULL; 1109230130Smav if (devid >= 0) { 1110230130Smav sc->quirks_on = hdac_devices[devid].quirks_on; 1111230130Smav sc->quirks_off = hdac_devices[devid].quirks_off; 1112230130Smav } else { 1113230130Smav sc->quirks_on = 0; 1114230130Smav sc->quirks_off = 0; 1115165281Sariff } 1116169277Sariff if (resource_int_value(device_get_name(dev), 1117230130Smav device_get_unit(dev), "msi", &i) == 0) { 1118230130Smav if (i == 0) 1119230130Smav sc->quirks_off |= HDAC_QUIRK_MSI; 1120230130Smav else { 1121230130Smav sc->quirks_on |= HDAC_QUIRK_MSI; 1122230130Smav sc->quirks_off |= ~HDAC_QUIRK_MSI; 1123230130Smav } 1124230130Smav } 1125230130Smav hdac_config_fetch(sc, &sc->quirks_on, &sc->quirks_off); 1126230130Smav HDA_BOOTVERBOSE( 1127230130Smav device_printf(sc->dev, 1128230130Smav "Config options: on=0x%08x off=0x%08x\n", 1129230130Smav sc->quirks_on, sc->quirks_off); 1130230130Smav ); 1131230130Smav sc->poll_ival = hz; 1132230130Smav if (resource_int_value(device_get_name(dev), 1133169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 1134164614Sariff sc->polling = 1; 1135164614Sariff else 1136164614Sariff sc->polling = 0; 1137164614Sariff 1138162922Sariff pci_enable_busmaster(dev); 1139162922Sariff 1140230130Smav vendor = pci_get_vendor(dev); 1141169277Sariff if (vendor == INTEL_VENDORID) { 1142169277Sariff /* TCSEL -> TC0 */ 1143169277Sariff v = pci_read_config(dev, 0x44, 1); 1144169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 1145183097Smav HDA_BOOTHVERBOSE( 1146169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 1147169277Sariff pci_read_config(dev, 0x44, 1)); 1148169277Sariff ); 1149169277Sariff } 1150169277Sariff 1151169277Sariff#if defined(__i386__) || defined(__amd64__) 1152171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1153169277Sariff 1154169277Sariff if (resource_int_value(device_get_name(dev), 1155169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 1156169277Sariff#else 1157171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1158169277Sariff#endif 1159169277Sariff /* 1160169277Sariff * Try to enable PCIe snoop to avoid messing around with 1161169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 1162169277Sariff * config is pretty much vendor specific, there are no 1163169277Sariff * general solutions on how to enable it, forcing us (even 1164169277Sariff * Microsoft) to enable uncacheable or write combined DMA 1165169277Sariff * by default. 1166169277Sariff * 1167169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 1168169277Sariff */ 1169169277Sariff for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) { 1170169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 1171169277Sariff continue; 1172171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1173169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 1174169277Sariff break; 1175169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1176169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 1177169277Sariff hdac_pcie_snoop[i].enable) 1178169277Sariff break; 1179169277Sariff v &= hdac_pcie_snoop[i].mask; 1180169277Sariff v |= hdac_pcie_snoop[i].enable; 1181169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 1182169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1183169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 1184169277Sariff hdac_pcie_snoop[i].enable) { 1185169277Sariff HDA_BOOTVERBOSE( 1186169277Sariff device_printf(dev, 1187169277Sariff "WARNING: Failed to enable PCIe " 1188169277Sariff "snoop!\n"); 1189169277Sariff ); 1190169277Sariff#if defined(__i386__) || defined(__amd64__) 1191171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1192169277Sariff#endif 1193169277Sariff } 1194169277Sariff break; 1195169277Sariff } 1196169277Sariff#if defined(__i386__) || defined(__amd64__) 1197169277Sariff } 1198169277Sariff#endif 1199169277Sariff 1200183097Smav HDA_BOOTHVERBOSE( 1201169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 1202171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 1203171330Sariff "Uncacheable" : "PCIe snoop", vendor); 1204169277Sariff ); 1205169277Sariff 1206162922Sariff /* Allocate resources */ 1207162922Sariff result = hdac_mem_alloc(sc); 1208162922Sariff if (result != 0) 1209163057Sariff goto hdac_attach_fail; 1210162922Sariff result = hdac_irq_alloc(sc); 1211162922Sariff if (result != 0) 1212163057Sariff goto hdac_attach_fail; 1213162922Sariff 1214162922Sariff /* Get Capabilities */ 1215162922Sariff result = hdac_get_capabilities(sc); 1216162922Sariff if (result != 0) 1217163057Sariff goto hdac_attach_fail; 1218162922Sariff 1219230130Smav /* Allocate CORB, RIRB, POS and BDLs dma memory */ 1220162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 1221162922Sariff sc->corb_size * sizeof(uint32_t)); 1222162922Sariff if (result != 0) 1223163057Sariff goto hdac_attach_fail; 1224162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 1225162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 1226162922Sariff if (result != 0) 1227163057Sariff goto hdac_attach_fail; 1228230130Smav sc->streams = malloc(sizeof(struct hdac_stream) * sc->num_ss, 1229230130Smav M_HDAC, M_ZERO | M_WAITOK); 1230230130Smav for (i = 0; i < sc->num_ss; i++) { 1231230130Smav result = hdac_dma_alloc(sc, &sc->streams[i].bdl, 1232230130Smav sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1233230130Smav if (result != 0) 1234230130Smav goto hdac_attach_fail; 1235230130Smav } 1236230130Smav if (sc->quirks_on & HDAC_QUIRK_DMAPOS) { 1237230130Smav if (hdac_dma_alloc(sc, &sc->pos_dma, (sc->num_ss) * 8) != 0) { 1238230130Smav HDA_BOOTVERBOSE( 1239230130Smav device_printf(dev, "Failed to " 1240230130Smav "allocate DMA pos buffer " 1241230130Smav "(non-fatal)\n"); 1242230130Smav ); 1243230130Smav } else { 1244230130Smav uint64_t addr = sc->pos_dma.dma_paddr; 1245162922Sariff 1246230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, addr >> 32); 1247230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 1248230130Smav (addr & HDAC_DPLBASE_DPLBASE_MASK) | 1249230130Smav HDAC_DPLBASE_DPLBASE_DMAPBE); 1250230130Smav } 1251230130Smav } 1252230130Smav 1253194861Smav result = bus_dma_tag_create( 1254194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1255230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 1256194861Smav 0, /* boundary */ 1257194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1258194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1259194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 1260194861Smav NULL, /* filtfunc */ 1261194861Smav NULL, /* fistfuncarg */ 1262194861Smav HDA_BUFSZ_MAX, /* maxsize */ 1263194861Smav 1, /* nsegments */ 1264194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 1265194861Smav 0, /* flags */ 1266194861Smav NULL, /* lockfunc */ 1267194861Smav NULL, /* lockfuncarg */ 1268194861Smav &sc->chan_dmat); /* dmat */ 1269194861Smav if (result != 0) { 1270194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 1271194861Smav __func__, result); 1272194861Smav goto hdac_attach_fail; 1273194861Smav } 1274194861Smav 1275162922Sariff /* Quiesce everything */ 1276183097Smav HDA_BOOTHVERBOSE( 1277182999Smav device_printf(dev, "Reset controller...\n"); 1278182999Smav ); 1279182999Smav hdac_reset(sc, 1); 1280162922Sariff 1281162922Sariff /* Initialize the CORB and RIRB */ 1282162922Sariff hdac_corb_init(sc); 1283162922Sariff hdac_rirb_init(sc); 1284162922Sariff 1285162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 1286162922Sariff sc->intrhook.ich_func = hdac_attach2; 1287162922Sariff sc->intrhook.ich_arg = (void *)sc; 1288162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 1289162922Sariff sc->intrhook.ich_func = NULL; 1290162922Sariff hdac_attach2((void *)sc); 1291162922Sariff } 1292162922Sariff 1293163057Sariff return (0); 1294162922Sariff 1295163057Sariffhdac_attach_fail: 1296162922Sariff hdac_irq_free(sc); 1297230130Smav for (i = 0; i < sc->num_ss; i++) 1298230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1299230130Smav free(sc->streams, M_HDAC); 1300169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 1301169277Sariff hdac_dma_free(sc, &sc->corb_dma); 1302162922Sariff hdac_mem_free(sc); 1303162922Sariff snd_mtxfree(sc->lock); 1304162922Sariff 1305163057Sariff return (ENXIO); 1306162922Sariff} 1307162922Sariff 1308230130Smavstatic int 1309230130Smavsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 1310162922Sariff{ 1311230130Smav struct hdac_softc *sc; 1312230130Smav device_t *devlist; 1313230130Smav device_t dev; 1314230130Smav int devcount, i, err, val; 1315162922Sariff 1316230130Smav dev = oidp->oid_arg1; 1317230130Smav sc = device_get_softc(dev); 1318230130Smav if (sc == NULL) 1319230130Smav return (EINVAL); 1320230130Smav val = 0; 1321230130Smav err = sysctl_handle_int(oidp, &val, 0, req); 1322230130Smav if (err != 0 || req->newptr == NULL || val == 0) 1323230130Smav return (err); 1324162922Sariff 1325230130Smav /* XXX: Temporary. For debugging. */ 1326230130Smav if (val == 100) { 1327230130Smav hdac_suspend(dev); 1328182999Smav return (0); 1329230130Smav } else if (val == 101) { 1330230130Smav hdac_resume(dev); 1331182999Smav return (0); 1332182999Smav } 1333162922Sariff 1334230130Smav if ((err = device_get_children(dev, &devlist, &devcount)) != 0) 1335230130Smav return (err); 1336230130Smav hdac_lock(sc); 1337230130Smav for (i = 0; i < devcount; i++) 1338230130Smav HDAC_PINDUMP(devlist[i]); 1339230130Smav hdac_unlock(sc); 1340230130Smav free(devlist, M_TEMP); 1341182999Smav return (0); 1342162922Sariff} 1343162922Sariff 1344183097Smavstatic int 1345230326Smavhdac_mdata_rate(uint16_t fmt) 1346162922Sariff{ 1347230326Smav static const int mbits[8] = { 8, 16, 32, 32, 32, 32, 32, 32 }; 1348230326Smav int rate, bits; 1349162922Sariff 1350230130Smav if (fmt & (1 << 14)) 1351230130Smav rate = 44100; 1352230130Smav else 1353230130Smav rate = 48000; 1354230130Smav rate *= ((fmt >> 11) & 0x07) + 1; 1355230130Smav rate /= ((fmt >> 8) & 0x07) + 1; 1356230326Smav bits = mbits[(fmt >> 4) & 0x03]; 1357230326Smav bits *= (fmt & 0x0f) + 1; 1358230326Smav return (rate * bits); 1359182999Smav} 1360182999Smav 1361230326Smavstatic int 1362230326Smavhdac_bdata_rate(uint16_t fmt, int output) 1363230326Smav{ 1364230326Smav static const int bbits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 }; 1365230326Smav int rate, bits; 1366230326Smav 1367230326Smav rate = 48000; 1368230326Smav rate *= ((fmt >> 11) & 0x07) + 1; 1369230326Smav bits = bbits[(fmt >> 4) & 0x03]; 1370230326Smav bits *= (fmt & 0x0f) + 1; 1371230326Smav if (!output) 1372230326Smav bits = ((bits + 7) & ~0x07) + 10; 1373230326Smav return (rate * bits); 1374230326Smav} 1375230326Smav 1376182999Smavstatic void 1377230130Smavhdac_poll_reinit(struct hdac_softc *sc) 1378182999Smav{ 1379230130Smav int i, pollticks, min = 1000000; 1380230130Smav struct hdac_stream *s; 1381182999Smav 1382230130Smav if (sc->polling == 0) 1383230130Smav return; 1384230130Smav if (sc->unsol_registered > 0) 1385230130Smav min = hz / 2; 1386230130Smav for (i = 0; i < sc->num_ss; i++) { 1387230130Smav s = &sc->streams[i]; 1388230130Smav if (s->running == 0) 1389182999Smav continue; 1390230130Smav pollticks = ((uint64_t)hz * s->blksz) / 1391230326Smav (hdac_mdata_rate(s->format) / 8); 1392230130Smav pollticks >>= 1; 1393230130Smav if (pollticks > hz) 1394230130Smav pollticks = hz; 1395230130Smav if (pollticks < 1) { 1396182999Smav HDA_BOOTVERBOSE( 1397230130Smav device_printf(sc->dev, 1398230130Smav "poll interval < 1 tick !\n"); 1399182999Smav ); 1400230130Smav pollticks = 1; 1401162922Sariff } 1402230130Smav if (min > pollticks) 1403230130Smav min = pollticks; 1404162922Sariff } 1405202789Smav HDA_BOOTVERBOSE( 1406230130Smav device_printf(sc->dev, 1407230130Smav "poll interval %d -> %d ticks\n", 1408230130Smav sc->poll_ival, min); 1409202789Smav ); 1410230130Smav sc->poll_ival = min; 1411230130Smav if (min == 1000000) 1412230130Smav callout_stop(&sc->poll_callout); 1413182999Smav else 1414230130Smav callout_reset(&sc->poll_callout, 1, hdac_poll_callback, sc); 1415163057Sariff} 1416163057Sariff 1417164614Sariffstatic int 1418164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 1419164614Sariff{ 1420164614Sariff struct hdac_softc *sc; 1421164614Sariff device_t dev; 1422164614Sariff uint32_t ctl; 1423164614Sariff int err, val; 1424164614Sariff 1425164614Sariff dev = oidp->oid_arg1; 1426182999Smav sc = device_get_softc(dev); 1427182999Smav if (sc == NULL) 1428164614Sariff return (EINVAL); 1429164614Sariff hdac_lock(sc); 1430164614Sariff val = sc->polling; 1431164614Sariff hdac_unlock(sc); 1432170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 1433164614Sariff 1434169277Sariff if (err != 0 || req->newptr == NULL) 1435164614Sariff return (err); 1436164614Sariff if (val < 0 || val > 1) 1437164614Sariff return (EINVAL); 1438164614Sariff 1439164614Sariff hdac_lock(sc); 1440164614Sariff if (val != sc->polling) { 1441182999Smav if (val == 0) { 1442230130Smav callout_stop(&sc->poll_callout); 1443169277Sariff hdac_unlock(sc); 1444230130Smav callout_drain(&sc->poll_callout); 1445169277Sariff hdac_lock(sc); 1446164614Sariff sc->polling = 0; 1447182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1448182999Smav ctl |= HDAC_INTCTL_GIE; 1449182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1450164614Sariff } else { 1451182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1452182999Smav ctl &= ~HDAC_INTCTL_GIE; 1453182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1454164614Sariff sc->polling = 1; 1455182999Smav hdac_poll_reinit(sc); 1456164614Sariff } 1457164614Sariff } 1458164614Sariff hdac_unlock(sc); 1459164614Sariff 1460164614Sariff return (err); 1461164614Sariff} 1462169277Sariff 1463163057Sariffstatic void 1464162922Sariffhdac_attach2(void *arg) 1465162922Sariff{ 1466162922Sariff struct hdac_softc *sc; 1467230130Smav device_t child; 1468230130Smav uint32_t vendorid, revisionid; 1469230130Smav int i; 1470230130Smav uint16_t statests; 1471162922Sariff 1472162922Sariff sc = (struct hdac_softc *)arg; 1473162922Sariff 1474162922Sariff hdac_lock(sc); 1475162922Sariff 1476162922Sariff /* Remove ourselves from the config hooks */ 1477162922Sariff if (sc->intrhook.ich_func != NULL) { 1478162922Sariff config_intrhook_disestablish(&sc->intrhook); 1479162922Sariff sc->intrhook.ich_func = NULL; 1480162922Sariff } 1481162922Sariff 1482183097Smav HDA_BOOTHVERBOSE( 1483182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 1484162922Sariff ); 1485162922Sariff hdac_corb_start(sc); 1486183097Smav HDA_BOOTHVERBOSE( 1487182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 1488162922Sariff ); 1489162922Sariff hdac_rirb_start(sc); 1490183097Smav HDA_BOOTHVERBOSE( 1491162922Sariff device_printf(sc->dev, 1492182999Smav "Enabling controller interrupt...\n"); 1493162922Sariff ); 1494182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1495182999Smav HDAC_GCTL_UNSOL); 1496182999Smav if (sc->polling == 0) { 1497164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 1498164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1499182999Smav } 1500162922Sariff DELAY(1000); 1501162922Sariff 1502183097Smav HDA_BOOTHVERBOSE( 1503230130Smav device_printf(sc->dev, "Scanning HDA codecs ...\n"); 1504162922Sariff ); 1505230130Smav statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1506230130Smav hdac_unlock(sc); 1507230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1508230130Smav if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1509230130Smav HDA_BOOTHVERBOSE( 1510183097Smav device_printf(sc->dev, 1511230130Smav "Found CODEC at address %d\n", i); 1512183019Smav ); 1513230130Smav hdac_lock(sc); 1514230130Smav vendorid = hdac_send_command(sc, i, 1515230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_VENDOR_ID)); 1516230130Smav revisionid = hdac_send_command(sc, i, 1517230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_REVISION_ID)); 1518230130Smav hdac_unlock(sc); 1519230130Smav if (vendorid == HDA_INVALID && 1520230130Smav revisionid == HDA_INVALID) { 1521230130Smav device_printf(sc->dev, 1522230130Smav "CODEC is not responding!\n"); 1523182999Smav continue; 1524182999Smav } 1525230130Smav sc->codecs[i].vendor_id = 1526230130Smav HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1527230130Smav sc->codecs[i].device_id = 1528230130Smav HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1529230130Smav sc->codecs[i].revision_id = 1530230130Smav HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1531230130Smav sc->codecs[i].stepping_id = 1532230130Smav HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1533230130Smav child = device_add_child(sc->dev, "hdacc", -1); 1534230130Smav if (child == NULL) { 1535230130Smav device_printf(sc->dev, 1536230130Smav "Failed to add CODEC device\n"); 1537230130Smav continue; 1538182999Smav } 1539230130Smav device_set_ivars(child, (void *)(intptr_t)i); 1540230130Smav sc->codecs[i].dev = child; 1541182999Smav } 1542162922Sariff } 1543182999Smav bus_generic_attach(sc->dev); 1544182999Smav 1545182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1546182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1547230130Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1548230130Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 1549230130Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1550230130Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1551182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1552182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 1553182999Smav} 1554182999Smav 1555182999Smav/**************************************************************************** 1556182999Smav * int hdac_suspend(device_t) 1557182999Smav * 1558182999Smav * Suspend and power down HDA bus and codecs. 1559182999Smav ****************************************************************************/ 1560182999Smavstatic int 1561182999Smavhdac_suspend(device_t dev) 1562182999Smav{ 1563230130Smav struct hdac_softc *sc = device_get_softc(dev); 1564182999Smav 1565183097Smav HDA_BOOTHVERBOSE( 1566182999Smav device_printf(dev, "Suspend...\n"); 1567162922Sariff ); 1568230130Smav bus_generic_suspend(dev); 1569182999Smav 1570182999Smav hdac_lock(sc); 1571183097Smav HDA_BOOTHVERBOSE( 1572182999Smav device_printf(dev, "Reset controller...\n"); 1573162922Sariff ); 1574233606Smav callout_stop(&sc->poll_callout); 1575182999Smav hdac_reset(sc, 0); 1576182999Smav hdac_unlock(sc); 1577233606Smav callout_drain(&sc->poll_callout); 1578182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1579183097Smav HDA_BOOTHVERBOSE( 1580182999Smav device_printf(dev, "Suspend done\n"); 1581162922Sariff ); 1582182999Smav return (0); 1583182999Smav} 1584182999Smav 1585182999Smav/**************************************************************************** 1586182999Smav * int hdac_resume(device_t) 1587182999Smav * 1588182999Smav * Powerup and restore HDA bus and codecs state. 1589182999Smav ****************************************************************************/ 1590182999Smavstatic int 1591182999Smavhdac_resume(device_t dev) 1592182999Smav{ 1593230130Smav struct hdac_softc *sc = device_get_softc(dev); 1594230130Smav int error; 1595182999Smav 1596183097Smav HDA_BOOTHVERBOSE( 1597182999Smav device_printf(dev, "Resume...\n"); 1598162922Sariff ); 1599182999Smav hdac_lock(sc); 1600182999Smav 1601182999Smav /* Quiesce everything */ 1602183097Smav HDA_BOOTHVERBOSE( 1603182999Smav device_printf(dev, "Reset controller...\n"); 1604162922Sariff ); 1605182999Smav hdac_reset(sc, 1); 1606182999Smav 1607182999Smav /* Initialize the CORB and RIRB */ 1608182999Smav hdac_corb_init(sc); 1609182999Smav hdac_rirb_init(sc); 1610182999Smav 1611183097Smav HDA_BOOTHVERBOSE( 1612182999Smav device_printf(dev, "Starting CORB Engine...\n"); 1613162922Sariff ); 1614182999Smav hdac_corb_start(sc); 1615183097Smav HDA_BOOTHVERBOSE( 1616182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 1617162922Sariff ); 1618182999Smav hdac_rirb_start(sc); 1619183097Smav HDA_BOOTHVERBOSE( 1620230130Smav device_printf(dev, "Enabling controller interrupt...\n"); 1621162922Sariff ); 1622182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1623182999Smav HDAC_GCTL_UNSOL); 1624230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1625182999Smav DELAY(1000); 1626233606Smav hdac_poll_reinit(sc); 1627182999Smav hdac_unlock(sc); 1628182999Smav 1629230130Smav error = bus_generic_resume(dev); 1630183097Smav HDA_BOOTHVERBOSE( 1631182999Smav device_printf(dev, "Resume done\n"); 1632162922Sariff ); 1633230130Smav return (error); 1634230130Smav} 1635164614Sariff 1636162922Sariff/**************************************************************************** 1637162922Sariff * int hdac_detach(device_t) 1638162922Sariff * 1639162922Sariff * Detach and free up resources utilized by the hdac device. 1640162922Sariff ****************************************************************************/ 1641162922Sariffstatic int 1642162922Sariffhdac_detach(device_t dev) 1643162922Sariff{ 1644230130Smav struct hdac_softc *sc = device_get_softc(dev); 1645185177Smav device_t *devlist; 1646230130Smav int cad, i, devcount, error; 1647162922Sariff 1648185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 1649185177Smav return (error); 1650185177Smav for (i = 0; i < devcount; i++) { 1651230130Smav cad = (intptr_t)device_get_ivars(devlist[i]); 1652185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 1653185178Smav free(devlist, M_TEMP); 1654185178Smav return (error); 1655185178Smav } 1656230130Smav sc->codecs[cad].dev = NULL; 1657185177Smav } 1658185177Smav free(devlist, M_TEMP); 1659185177Smav 1660230130Smav hdac_lock(sc); 1661230130Smav hdac_reset(sc, 0); 1662230130Smav hdac_unlock(sc); 1663230130Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1664230130Smav hdac_irq_free(sc); 1665162922Sariff 1666230130Smav for (i = 0; i < sc->num_ss; i++) 1667230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1668230130Smav free(sc->streams, M_HDAC); 1669230130Smav hdac_dma_free(sc, &sc->pos_dma); 1670230130Smav hdac_dma_free(sc, &sc->rirb_dma); 1671230130Smav hdac_dma_free(sc, &sc->corb_dma); 1672230130Smav if (sc->chan_dmat != NULL) { 1673230130Smav bus_dma_tag_destroy(sc->chan_dmat); 1674230130Smav sc->chan_dmat = NULL; 1675230130Smav } 1676230130Smav hdac_mem_free(sc); 1677230130Smav snd_mtxfree(sc->lock); 1678162922Sariff return (0); 1679162922Sariff} 1680162922Sariff 1681230130Smavstatic bus_dma_tag_t 1682230130Smavhdac_get_dma_tag(device_t dev, device_t child) 1683230130Smav{ 1684230130Smav struct hdac_softc *sc = device_get_softc(dev); 1685230130Smav 1686230130Smav return (sc->chan_dmat); 1687230130Smav} 1688230130Smav 1689184095Smavstatic int 1690184095Smavhdac_print_child(device_t dev, device_t child) 1691184095Smav{ 1692184095Smav int retval; 1693184095Smav 1694184095Smav retval = bus_print_child_header(dev, child); 1695230130Smav retval += printf(" at cad %d", 1696230130Smav (int)(intptr_t)device_get_ivars(child)); 1697184095Smav retval += bus_print_child_footer(dev, child); 1698184095Smav 1699184095Smav return (retval); 1700184095Smav} 1701184095Smav 1702230130Smavstatic int 1703230130Smavhdac_child_location_str(device_t dev, device_t child, char *buf, 1704230130Smav size_t buflen) 1705230130Smav{ 1706162922Sariff 1707230130Smav snprintf(buf, buflen, "cad=%d", 1708230130Smav (int)(intptr_t)device_get_ivars(child)); 1709230130Smav return (0); 1710230130Smav} 1711162922Sariff 1712230130Smavstatic int 1713230130Smavhdac_child_pnpinfo_str_method(device_t dev, device_t child, char *buf, 1714230130Smav size_t buflen) 1715230130Smav{ 1716230130Smav struct hdac_softc *sc = device_get_softc(dev); 1717230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1718182999Smav 1719230130Smav snprintf(buf, buflen, "vendor=0x%04x device=0x%04x revision=0x%02x " 1720230130Smav "stepping=0x%02x", 1721230130Smav sc->codecs[cad].vendor_id, sc->codecs[cad].device_id, 1722230130Smav sc->codecs[cad].revision_id, sc->codecs[cad].stepping_id); 1723230130Smav return (0); 1724230130Smav} 1725182999Smav 1726182999Smavstatic int 1727230130Smavhdac_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1728182999Smav{ 1729230130Smav struct hdac_softc *sc = device_get_softc(dev); 1730230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1731182999Smav 1732230130Smav switch (which) { 1733230130Smav case HDA_IVAR_CODEC_ID: 1734230130Smav *result = cad; 1735230130Smav break; 1736230130Smav case HDA_IVAR_VENDOR_ID: 1737230130Smav *result = sc->codecs[cad].vendor_id; 1738230130Smav break; 1739230130Smav case HDA_IVAR_DEVICE_ID: 1740230130Smav *result = sc->codecs[cad].device_id; 1741230130Smav break; 1742230130Smav case HDA_IVAR_REVISION_ID: 1743230130Smav *result = sc->codecs[cad].revision_id; 1744230130Smav break; 1745230130Smav case HDA_IVAR_STEPPING_ID: 1746230130Smav *result = sc->codecs[cad].stepping_id; 1747230130Smav break; 1748230130Smav case HDA_IVAR_SUBVENDOR_ID: 1749230130Smav *result = pci_get_subvendor(dev); 1750230130Smav break; 1751230130Smav case HDA_IVAR_SUBDEVICE_ID: 1752230130Smav *result = pci_get_subdevice(dev); 1753230130Smav break; 1754230130Smav case HDA_IVAR_DMA_NOCACHE: 1755230130Smav *result = (sc->flags & HDAC_F_DMA_NOCACHE) != 0; 1756230130Smav break; 1757230130Smav default: 1758230130Smav return (ENOENT); 1759230130Smav } 1760182999Smav return (0); 1761182999Smav} 1762182999Smav 1763230130Smavstatic struct mtx * 1764230130Smavhdac_get_mtx(device_t dev, device_t child) 1765182999Smav{ 1766230130Smav struct hdac_softc *sc = device_get_softc(dev); 1767182999Smav 1768230130Smav return (sc->lock); 1769230130Smav} 1770182999Smav 1771230130Smavstatic uint32_t 1772230130Smavhdac_codec_command(device_t dev, device_t child, uint32_t verb) 1773230130Smav{ 1774182999Smav 1775230130Smav return (hdac_send_command(device_get_softc(dev), 1776230130Smav (intptr_t)device_get_ivars(child), verb)); 1777230130Smav} 1778182999Smav 1779230130Smavstatic int 1780230130Smavhdac_find_stream(struct hdac_softc *sc, int dir, int stream) 1781230130Smav{ 1782230130Smav int i, ss; 1783182999Smav 1784230130Smav ss = -1; 1785230130Smav /* Allocate ISS/BSS first. */ 1786230130Smav if (dir == 0) { 1787230130Smav for (i = 0; i < sc->num_iss; i++) { 1788230130Smav if (sc->streams[i].stream == stream) { 1789230130Smav ss = i; 1790230130Smav break; 1791230130Smav } 1792230130Smav } 1793230130Smav } else { 1794230130Smav for (i = 0; i < sc->num_oss; i++) { 1795230130Smav if (sc->streams[i + sc->num_iss].stream == stream) { 1796230130Smav ss = i + sc->num_iss; 1797230130Smav break; 1798230130Smav } 1799230130Smav } 1800230130Smav } 1801230130Smav /* Fallback to BSS. */ 1802230130Smav if (ss == -1) { 1803230130Smav for (i = 0; i < sc->num_bss; i++) { 1804230130Smav if (sc->streams[i + sc->num_iss + sc->num_oss].stream 1805230130Smav == stream) { 1806230130Smav ss = i + sc->num_iss + sc->num_oss; 1807230130Smav break; 1808230130Smav } 1809230130Smav } 1810230130Smav } 1811230130Smav return (ss); 1812230130Smav} 1813182999Smav 1814230130Smavstatic int 1815230326Smavhdac_stream_alloc(device_t dev, device_t child, int dir, int format, int stripe, 1816230130Smav uint32_t **dmapos) 1817230130Smav{ 1818230130Smav struct hdac_softc *sc = device_get_softc(dev); 1819230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1820230326Smav int stream, ss, bw, maxbw, prevbw; 1821182999Smav 1822230130Smav /* Look for empty stream. */ 1823230130Smav ss = hdac_find_stream(sc, dir, 0); 1824182999Smav 1825230130Smav /* Return if found nothing. */ 1826230130Smav if (ss < 0) 1827230130Smav return (0); 1828182999Smav 1829230326Smav /* Check bus bandwidth. */ 1830230326Smav bw = hdac_bdata_rate(format, dir); 1831230326Smav if (dir == 1) { 1832230326Smav bw *= 1 << (sc->num_sdo - stripe); 1833230326Smav prevbw = sc->sdo_bw_used; 1834230326Smav maxbw = 48000 * 960 * (1 << sc->num_sdo); 1835230326Smav } else { 1836230326Smav prevbw = sc->codecs[cad].sdi_bw_used; 1837230326Smav maxbw = 48000 * 464; 1838230326Smav } 1839230326Smav HDA_BOOTHVERBOSE( 1840230326Smav device_printf(dev, "%dKbps of %dKbps bandwidth used%s\n", 1841230326Smav (bw + prevbw) / 1000, maxbw / 1000, 1842230326Smav bw + prevbw > maxbw ? " -- OVERFLOW!" : ""); 1843230326Smav ); 1844230326Smav if (bw + prevbw > maxbw) 1845230326Smav return (0); 1846230326Smav if (dir == 1) 1847230326Smav sc->sdo_bw_used += bw; 1848230326Smav else 1849230326Smav sc->codecs[cad].sdi_bw_used += bw; 1850230326Smav 1851230130Smav /* Allocate stream number */ 1852230130Smav if (ss >= sc->num_iss + sc->num_oss) 1853230130Smav stream = 15 - (ss - sc->num_iss + sc->num_oss); 1854230130Smav else if (ss >= sc->num_iss) 1855230130Smav stream = ss - sc->num_iss + 1; 1856230130Smav else 1857230130Smav stream = ss + 1; 1858182999Smav 1859230130Smav sc->streams[ss].dev = child; 1860230130Smav sc->streams[ss].dir = dir; 1861230130Smav sc->streams[ss].stream = stream; 1862230326Smav sc->streams[ss].bw = bw; 1863230130Smav sc->streams[ss].format = format; 1864230326Smav sc->streams[ss].stripe = stripe; 1865230130Smav if (dmapos != NULL) { 1866230130Smav if (sc->pos_dma.dma_vaddr != NULL) 1867230130Smav *dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8); 1868230130Smav else 1869230130Smav *dmapos = NULL; 1870230130Smav } 1871230130Smav return (stream); 1872182999Smav} 1873182999Smav 1874230130Smavstatic void 1875230130Smavhdac_stream_free(device_t dev, device_t child, int dir, int stream) 1876230130Smav{ 1877230130Smav struct hdac_softc *sc = device_get_softc(dev); 1878230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1879230130Smav int ss; 1880230130Smav 1881230130Smav ss = hdac_find_stream(sc, dir, stream); 1882230130Smav KASSERT(ss >= 0, 1883230130Smav ("Free for not allocated stream (%d/%d)\n", dir, stream)); 1884230326Smav if (dir == 1) 1885230326Smav sc->sdo_bw_used -= sc->streams[ss].bw; 1886230326Smav else 1887230326Smav sc->codecs[cad].sdi_bw_used -= sc->streams[ss].bw; 1888230130Smav sc->streams[ss].stream = 0; 1889230130Smav sc->streams[ss].dev = NULL; 1890230130Smav} 1891230130Smav 1892182999Smavstatic int 1893230130Smavhdac_stream_start(device_t dev, device_t child, 1894230130Smav int dir, int stream, bus_addr_t buf, int blksz, int blkcnt) 1895182999Smav{ 1896230130Smav struct hdac_softc *sc = device_get_softc(dev); 1897230130Smav struct hdac_bdle *bdle; 1898230130Smav uint64_t addr; 1899230130Smav int i, ss, off; 1900230130Smav uint32_t ctl; 1901182999Smav 1902230130Smav ss = hdac_find_stream(sc, dir, stream); 1903230130Smav KASSERT(ss >= 0, 1904230130Smav ("Start for not allocated stream (%d/%d)\n", dir, stream)); 1905230130Smav 1906230130Smav addr = (uint64_t)buf; 1907230130Smav bdle = (struct hdac_bdle *)sc->streams[ss].bdl.dma_vaddr; 1908230130Smav for (i = 0; i < blkcnt; i++, bdle++) { 1909230130Smav bdle->addrl = (uint32_t)addr; 1910230130Smav bdle->addrh = (uint32_t)(addr >> 32); 1911230130Smav bdle->len = blksz; 1912230130Smav bdle->ioc = 1; 1913230130Smav addr += blksz; 1914182999Smav } 1915182999Smav 1916230130Smav off = ss << 5; 1917230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDCBL, blksz * blkcnt); 1918230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDLVI, blkcnt - 1); 1919230130Smav addr = sc->streams[ss].bdl.dma_paddr; 1920230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPL, (uint32_t)addr); 1921230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1922230130Smav 1923230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL2); 1924230130Smav if (dir) 1925230130Smav ctl |= HDAC_SDCTL2_DIR; 1926230130Smav else 1927230130Smav ctl &= ~HDAC_SDCTL2_DIR; 1928230130Smav ctl &= ~HDAC_SDCTL2_STRM_MASK; 1929230130Smav ctl |= stream << HDAC_SDCTL2_STRM_SHIFT; 1930230326Smav ctl &= ~HDAC_SDCTL2_STRIPE_MASK; 1931230326Smav ctl |= sc->streams[ss].stripe << HDAC_SDCTL2_STRIPE_SHIFT; 1932230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl); 1933230130Smav 1934230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format); 1935230130Smav 1936230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1937230130Smav ctl |= 1 << ss; 1938230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1939230130Smav 1940230807Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDSTS, 1941230807Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS); 1942230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1943230130Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1944230130Smav HDAC_SDCTL_RUN; 1945230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1946230130Smav 1947230130Smav sc->streams[ss].blksz = blksz; 1948230130Smav sc->streams[ss].running = 1; 1949230130Smav hdac_poll_reinit(sc); 1950182999Smav return (0); 1951182999Smav} 1952182999Smav 1953230130Smavstatic void 1954230130Smavhdac_stream_stop(device_t dev, device_t child, int dir, int stream) 1955230130Smav{ 1956230130Smav struct hdac_softc *sc = device_get_softc(dev); 1957230130Smav int ss, off; 1958230130Smav uint32_t ctl; 1959230130Smav 1960230130Smav ss = hdac_find_stream(sc, dir, stream); 1961230130Smav KASSERT(ss >= 0, 1962230130Smav ("Stop for not allocated stream (%d/%d)\n", dir, stream)); 1963230130Smav 1964230130Smav off = ss << 5; 1965230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1966230130Smav ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1967230130Smav HDAC_SDCTL_RUN); 1968230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1969230130Smav 1970230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1971230130Smav ctl &= ~(1 << ss); 1972230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1973230130Smav 1974230130Smav sc->streams[ss].running = 0; 1975230130Smav hdac_poll_reinit(sc); 1976230130Smav} 1977230130Smav 1978230130Smavstatic void 1979230130Smavhdac_stream_reset(device_t dev, device_t child, int dir, int stream) 1980230130Smav{ 1981230130Smav struct hdac_softc *sc = device_get_softc(dev); 1982230130Smav int timeout = 1000; 1983230130Smav int to = timeout; 1984230130Smav int ss, off; 1985230130Smav uint32_t ctl; 1986230130Smav 1987230130Smav ss = hdac_find_stream(sc, dir, stream); 1988230130Smav KASSERT(ss >= 0, 1989230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 1990230130Smav 1991230130Smav off = ss << 5; 1992230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1993230130Smav ctl |= HDAC_SDCTL_SRST; 1994230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1995230130Smav do { 1996230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1997230130Smav if (ctl & HDAC_SDCTL_SRST) 1998230130Smav break; 1999230130Smav DELAY(10); 2000230130Smav } while (--to); 2001230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2002230130Smav device_printf(dev, "Reset setting timeout\n"); 2003230130Smav ctl &= ~HDAC_SDCTL_SRST; 2004230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 2005230130Smav to = timeout; 2006230130Smav do { 2007230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2008230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2009230130Smav break; 2010230130Smav DELAY(10); 2011230130Smav } while (--to); 2012230130Smav if (ctl & HDAC_SDCTL_SRST) 2013230130Smav device_printf(dev, "Reset timeout!\n"); 2014230130Smav} 2015230130Smav 2016230130Smavstatic uint32_t 2017230130Smavhdac_stream_getptr(device_t dev, device_t child, int dir, int stream) 2018230130Smav{ 2019230130Smav struct hdac_softc *sc = device_get_softc(dev); 2020230130Smav int ss, off; 2021230130Smav 2022230130Smav ss = hdac_find_stream(sc, dir, stream); 2023230130Smav KASSERT(ss >= 0, 2024230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 2025230130Smav 2026230130Smav off = ss << 5; 2027230130Smav return (HDAC_READ_4(&sc->mem, off + HDAC_SDLPIB)); 2028230130Smav} 2029230130Smav 2030230130Smavstatic int 2031230130Smavhdac_unsol_alloc(device_t dev, device_t child, int tag) 2032230130Smav{ 2033230130Smav struct hdac_softc *sc = device_get_softc(dev); 2034230130Smav 2035230130Smav sc->unsol_registered++; 2036230130Smav hdac_poll_reinit(sc); 2037230130Smav return (tag); 2038230130Smav} 2039230130Smav 2040230130Smavstatic void 2041230130Smavhdac_unsol_free(device_t dev, device_t child, int tag) 2042230130Smav{ 2043230130Smav struct hdac_softc *sc = device_get_softc(dev); 2044230130Smav 2045230130Smav sc->unsol_registered--; 2046230130Smav hdac_poll_reinit(sc); 2047230130Smav} 2048230130Smav 2049230130Smavstatic device_method_t hdac_methods[] = { 2050182999Smav /* device interface */ 2051230130Smav DEVMETHOD(device_probe, hdac_probe), 2052230130Smav DEVMETHOD(device_attach, hdac_attach), 2053230130Smav DEVMETHOD(device_detach, hdac_detach), 2054230130Smav DEVMETHOD(device_suspend, hdac_suspend), 2055230130Smav DEVMETHOD(device_resume, hdac_resume), 2056230130Smav /* Bus interface */ 2057230130Smav DEVMETHOD(bus_get_dma_tag, hdac_get_dma_tag), 2058230130Smav DEVMETHOD(bus_print_child, hdac_print_child), 2059230130Smav DEVMETHOD(bus_child_location_str, hdac_child_location_str), 2060230130Smav DEVMETHOD(bus_child_pnpinfo_str, hdac_child_pnpinfo_str_method), 2061230130Smav DEVMETHOD(bus_read_ivar, hdac_read_ivar), 2062230130Smav DEVMETHOD(hdac_get_mtx, hdac_get_mtx), 2063230130Smav DEVMETHOD(hdac_codec_command, hdac_codec_command), 2064230130Smav DEVMETHOD(hdac_stream_alloc, hdac_stream_alloc), 2065230130Smav DEVMETHOD(hdac_stream_free, hdac_stream_free), 2066230130Smav DEVMETHOD(hdac_stream_start, hdac_stream_start), 2067230130Smav DEVMETHOD(hdac_stream_stop, hdac_stream_stop), 2068230130Smav DEVMETHOD(hdac_stream_reset, hdac_stream_reset), 2069230130Smav DEVMETHOD(hdac_stream_getptr, hdac_stream_getptr), 2070230130Smav DEVMETHOD(hdac_unsol_alloc, hdac_unsol_alloc), 2071230130Smav DEVMETHOD(hdac_unsol_free, hdac_unsol_free), 2072182999Smav { 0, 0 } 2073182999Smav}; 2074182999Smav 2075230130Smavstatic driver_t hdac_driver = { 2076230130Smav "hdac", 2077230130Smav hdac_methods, 2078230130Smav sizeof(struct hdac_softc), 2079182999Smav}; 2080182999Smav 2081230130Smavstatic devclass_t hdac_devclass; 2082182999Smav 2083230130SmavDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, 0, 0); 2084