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: stable/11/sys/dev/sound/pci/hda/hdac.c 359485 2020-03-31 15:28:31Z kib $"); 52162922Sariff 53162965Sariff#define hdac_lock(sc) snd_mtxlock((sc)->lock) 54162965Sariff#define hdac_unlock(sc) snd_mtxunlock((sc)->lock) 55163057Sariff#define hdac_lockassert(sc) snd_mtxassert((sc)->lock) 56163057Sariff#define hdac_lockowned(sc) mtx_owned((sc)->lock) 57162922Sariff 58230130Smav#define HDAC_QUIRK_64BIT (1 << 0) 59230130Smav#define HDAC_QUIRK_DMAPOS (1 << 1) 60230130Smav#define HDAC_QUIRK_MSI (1 << 2) 61162965Sariff 62163057Sariffstatic const struct { 63264832Smarius const char *key; 64163057Sariff uint32_t value; 65163057Sariff} hdac_quirks_tab[] = { 66230130Smav { "64bit", HDAC_QUIRK_DMAPOS }, 67230130Smav { "dmapos", HDAC_QUIRK_DMAPOS }, 68230130Smav { "msi", HDAC_QUIRK_MSI }, 69163057Sariff}; 70163057Sariff 71230130SmavMALLOC_DEFINE(M_HDAC, "hdac", "HDA Controller"); 72162922Sariff 73162922Sariffstatic const struct { 74162922Sariff uint32_t model; 75264832Smarius const char *desc; 76230130Smav char quirks_on; 77230130Smav char quirks_off; 78162922Sariff} hdac_devices[] = { 79258170Smav { HDA_INTEL_OAK, "Intel Oaktrail", 0, 0 }, 80258170Smav { HDA_INTEL_BAY, "Intel BayTrail", 0, 0 }, 81258170Smav { HDA_INTEL_HSW1, "Intel Haswell", 0, 0 }, 82258170Smav { HDA_INTEL_HSW2, "Intel Haswell", 0, 0 }, 83258170Smav { HDA_INTEL_HSW3, "Intel Haswell", 0, 0 }, 84281544Srpaulo { HDA_INTEL_BDW1, "Intel Broadwell", 0, 0 }, 85281544Srpaulo { HDA_INTEL_BDW2, "Intel Broadwell", 0, 0 }, 86230130Smav { HDA_INTEL_CPT, "Intel Cougar Point", 0, 0 }, 87230130Smav { HDA_INTEL_PATSBURG,"Intel Patsburg", 0, 0 }, 88230130Smav { HDA_INTEL_PPT1, "Intel Panther Point", 0, 0 }, 89244980Sjfv { HDA_INTEL_LPT1, "Intel Lynx Point", 0, 0 }, 90244980Sjfv { HDA_INTEL_LPT2, "Intel Lynx Point", 0, 0 }, 91275101Smav { HDA_INTEL_WCPT, "Intel Wildcat Point", 0, 0 }, 92258170Smav { HDA_INTEL_WELLS1, "Intel Wellsburg", 0, 0 }, 93258170Smav { HDA_INTEL_WELLS2, "Intel Wellsburg", 0, 0 }, 94258170Smav { HDA_INTEL_LPTLP1, "Intel Lynx Point-LP", 0, 0 }, 95258170Smav { HDA_INTEL_LPTLP2, "Intel Lynx Point-LP", 0, 0 }, 96298983Smav { HDA_INTEL_SRPTLP, "Intel Sunrise Point-LP", 0, 0 }, 97345822Smav { HDA_INTEL_KBLKLP, "Intel Kaby Lake-LP", 0, 0 }, 98298983Smav { HDA_INTEL_SRPT, "Intel Sunrise Point", 0, 0 }, 99345822Smav { HDA_INTEL_KBLK, "Intel Kaby Lake", 0, 0 }, 100345822Smav { HDA_INTEL_KBLKH, "Intel Kaby Lake-H", 0, 0 }, 101345822Smav { HDA_INTEL_CFLK, "Intel Coffee Lake", 0, 0 }, 102359114Sgonzo { HDA_INTEL_CNLK, "Intel Cannon Lake", 0, 0 }, 103230130Smav { HDA_INTEL_82801F, "Intel 82801F", 0, 0 }, 104230130Smav { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0, 0 }, 105230130Smav { HDA_INTEL_82801G, "Intel 82801G", 0, 0 }, 106230130Smav { HDA_INTEL_82801H, "Intel 82801H", 0, 0 }, 107230130Smav { HDA_INTEL_82801I, "Intel 82801I", 0, 0 }, 108230130Smav { HDA_INTEL_82801JI, "Intel 82801JI", 0, 0 }, 109230130Smav { HDA_INTEL_82801JD, "Intel 82801JD", 0, 0 }, 110322573Smav { HDA_INTEL_PCH, "Intel Ibex Peak", 0, 0 }, 111322573Smav { HDA_INTEL_PCH2, "Intel Ibex Peak", 0, 0 }, 112230130Smav { HDA_INTEL_SCH, "Intel SCH", 0, 0 }, 113230130Smav { HDA_NVIDIA_MCP51, "NVIDIA MCP51", 0, HDAC_QUIRK_MSI }, 114230130Smav { HDA_NVIDIA_MCP55, "NVIDIA MCP55", 0, HDAC_QUIRK_MSI }, 115230130Smav { HDA_NVIDIA_MCP61_1, "NVIDIA MCP61", 0, 0 }, 116230130Smav { HDA_NVIDIA_MCP61_2, "NVIDIA MCP61", 0, 0 }, 117230130Smav { HDA_NVIDIA_MCP65_1, "NVIDIA MCP65", 0, 0 }, 118230130Smav { HDA_NVIDIA_MCP65_2, "NVIDIA MCP65", 0, 0 }, 119230130Smav { HDA_NVIDIA_MCP67_1, "NVIDIA MCP67", 0, 0 }, 120230130Smav { HDA_NVIDIA_MCP67_2, "NVIDIA MCP67", 0, 0 }, 121230130Smav { HDA_NVIDIA_MCP73_1, "NVIDIA MCP73", 0, 0 }, 122230130Smav { HDA_NVIDIA_MCP73_2, "NVIDIA MCP73", 0, 0 }, 123230130Smav { HDA_NVIDIA_MCP78_1, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 124230130Smav { HDA_NVIDIA_MCP78_2, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 125230130Smav { HDA_NVIDIA_MCP78_3, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 126230130Smav { HDA_NVIDIA_MCP78_4, "NVIDIA MCP78", 0, HDAC_QUIRK_64BIT }, 127230130Smav { HDA_NVIDIA_MCP79_1, "NVIDIA MCP79", 0, 0 }, 128230130Smav { HDA_NVIDIA_MCP79_2, "NVIDIA MCP79", 0, 0 }, 129230130Smav { HDA_NVIDIA_MCP79_3, "NVIDIA MCP79", 0, 0 }, 130230130Smav { HDA_NVIDIA_MCP79_4, "NVIDIA MCP79", 0, 0 }, 131230130Smav { HDA_NVIDIA_MCP89_1, "NVIDIA MCP89", 0, 0 }, 132230130Smav { HDA_NVIDIA_MCP89_2, "NVIDIA MCP89", 0, 0 }, 133230130Smav { HDA_NVIDIA_MCP89_3, "NVIDIA MCP89", 0, 0 }, 134230130Smav { HDA_NVIDIA_MCP89_4, "NVIDIA MCP89", 0, 0 }, 135230331Smav { HDA_NVIDIA_0BE2, "NVIDIA (0x0be2)", 0, HDAC_QUIRK_MSI }, 136230331Smav { HDA_NVIDIA_0BE3, "NVIDIA (0x0be3)", 0, HDAC_QUIRK_MSI }, 137230331Smav { HDA_NVIDIA_0BE4, "NVIDIA (0x0be4)", 0, HDAC_QUIRK_MSI }, 138230312Smav { HDA_NVIDIA_GT100, "NVIDIA GT100", 0, HDAC_QUIRK_MSI }, 139230312Smav { HDA_NVIDIA_GT104, "NVIDIA GT104", 0, HDAC_QUIRK_MSI }, 140230312Smav { HDA_NVIDIA_GT106, "NVIDIA GT106", 0, HDAC_QUIRK_MSI }, 141230312Smav { HDA_NVIDIA_GT108, "NVIDIA GT108", 0, HDAC_QUIRK_MSI }, 142230312Smav { HDA_NVIDIA_GT116, "NVIDIA GT116", 0, HDAC_QUIRK_MSI }, 143230312Smav { HDA_NVIDIA_GF119, "NVIDIA GF119", 0, 0 }, 144230312Smav { HDA_NVIDIA_GF110_1, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 145230312Smav { HDA_NVIDIA_GF110_2, "NVIDIA GF110", 0, HDAC_QUIRK_MSI }, 146230130Smav { HDA_ATI_SB450, "ATI SB450", 0, 0 }, 147230130Smav { HDA_ATI_SB600, "ATI SB600", 0, 0 }, 148230130Smav { HDA_ATI_RS600, "ATI RS600", 0, 0 }, 149230130Smav { HDA_ATI_RS690, "ATI RS690", 0, 0 }, 150230130Smav { HDA_ATI_RS780, "ATI RS780", 0, 0 }, 151230130Smav { HDA_ATI_R600, "ATI R600", 0, 0 }, 152230130Smav { HDA_ATI_RV610, "ATI RV610", 0, 0 }, 153230130Smav { HDA_ATI_RV620, "ATI RV620", 0, 0 }, 154230130Smav { HDA_ATI_RV630, "ATI RV630", 0, 0 }, 155230130Smav { HDA_ATI_RV635, "ATI RV635", 0, 0 }, 156230130Smav { HDA_ATI_RV710, "ATI RV710", 0, 0 }, 157230130Smav { HDA_ATI_RV730, "ATI RV730", 0, 0 }, 158230130Smav { HDA_ATI_RV740, "ATI RV740", 0, 0 }, 159230130Smav { HDA_ATI_RV770, "ATI RV770", 0, 0 }, 160239908Smav { HDA_ATI_RV810, "ATI RV810", 0, 0 }, 161239908Smav { HDA_ATI_RV830, "ATI RV830", 0, 0 }, 162239908Smav { HDA_ATI_RV840, "ATI RV840", 0, 0 }, 163239908Smav { HDA_ATI_RV870, "ATI RV870", 0, 0 }, 164239908Smav { HDA_ATI_RV910, "ATI RV910", 0, 0 }, 165239908Smav { HDA_ATI_RV930, "ATI RV930", 0, 0 }, 166239908Smav { HDA_ATI_RV940, "ATI RV940", 0, 0 }, 167239908Smav { HDA_ATI_RV970, "ATI RV970", 0, 0 }, 168239908Smav { HDA_ATI_R1000, "ATI R1000", 0, 0 }, 169297387Smav { HDA_AMD_HUDSON2, "AMD Hudson-2", 0, 0 }, 170230130Smav { HDA_RDC_M3010, "RDC M3010", 0, 0 }, 171230130Smav { HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 }, 172230130Smav { HDA_SIS_966, "SiS 966", 0, 0 }, 173230130Smav { HDA_ULI_M5461, "ULI M5461", 0, 0 }, 174162922Sariff /* Unknown */ 175230331Smav { HDA_INTEL_ALL, "Intel", 0, 0 }, 176230331Smav { HDA_NVIDIA_ALL, "NVIDIA", 0, 0 }, 177230331Smav { HDA_ATI_ALL, "ATI", 0, 0 }, 178297387Smav { HDA_AMD_ALL, "AMD", 0, 0 }, 179324909Smav { HDA_CREATIVE_ALL, "Creative", 0, 0 }, 180230331Smav { HDA_VIA_ALL, "VIA", 0, 0 }, 181230331Smav { HDA_SIS_ALL, "SiS", 0, 0 }, 182230331Smav { HDA_ULI_ALL, "ULI", 0, 0 }, 183162922Sariff}; 184162922Sariff 185162922Sariffstatic const struct { 186169277Sariff uint16_t vendor; 187169277Sariff uint8_t reg; 188169277Sariff uint8_t mask; 189169277Sariff uint8_t enable; 190169277Sariff} hdac_pcie_snoop[] = { 191169277Sariff { INTEL_VENDORID, 0x00, 0x00, 0x00 }, 192169277Sariff { ATI_VENDORID, 0x42, 0xf8, 0x02 }, 193169277Sariff { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f }, 194169277Sariff}; 195169277Sariff 196162922Sariff/**************************************************************************** 197162922Sariff * Function prototypes 198162922Sariff ****************************************************************************/ 199162922Sariffstatic void hdac_intr_handler(void *); 200182999Smavstatic int hdac_reset(struct hdac_softc *, int); 201162922Sariffstatic int hdac_get_capabilities(struct hdac_softc *); 202162922Sariffstatic void hdac_dma_cb(void *, bus_dma_segment_t *, int, int); 203162922Sariffstatic int hdac_dma_alloc(struct hdac_softc *, 204162922Sariff struct hdac_dma *, bus_size_t); 205169277Sariffstatic void hdac_dma_free(struct hdac_softc *, struct hdac_dma *); 206162922Sariffstatic int hdac_mem_alloc(struct hdac_softc *); 207162922Sariffstatic void hdac_mem_free(struct hdac_softc *); 208162922Sariffstatic int hdac_irq_alloc(struct hdac_softc *); 209162922Sariffstatic void hdac_irq_free(struct hdac_softc *); 210162922Sariffstatic void hdac_corb_init(struct hdac_softc *); 211162922Sariffstatic void hdac_rirb_init(struct hdac_softc *); 212162922Sariffstatic void hdac_corb_start(struct hdac_softc *); 213162922Sariffstatic void hdac_rirb_start(struct hdac_softc *); 214162922Sariff 215162922Sariffstatic void hdac_attach2(void *); 216162922Sariff 217230130Smavstatic uint32_t hdac_send_command(struct hdac_softc *, nid_t, uint32_t); 218162922Sariff 219162922Sariffstatic int hdac_probe(device_t); 220162922Sariffstatic int hdac_attach(device_t); 221162922Sariffstatic int hdac_detach(device_t); 222182999Smavstatic int hdac_suspend(device_t); 223182999Smavstatic int hdac_resume(device_t); 224162922Sariff 225164614Sariffstatic int hdac_rirb_flush(struct hdac_softc *sc); 226164614Sariffstatic int hdac_unsolq_flush(struct hdac_softc *sc); 227164614Sariff 228162922Sariff#define hdac_command(a1, a2, a3) \ 229230130Smav hdac_send_command(a1, a3, a2) 230162922Sariff 231230130Smav/* This function surely going to make its way into upper level someday. */ 232162922Sariffstatic void 233230130Smavhdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off) 234162922Sariff{ 235230130Smav const char *res = NULL; 236230130Smav int i = 0, j, k, len, inv; 237162922Sariff 238230130Smav if (resource_string_value(device_get_name(sc->dev), 239230130Smav device_get_unit(sc->dev), "config", &res) != 0) 240162922Sariff return; 241230130Smav if (!(res != NULL && strlen(res) > 0)) 242230130Smav return; 243230130Smav HDA_BOOTVERBOSE( 244230130Smav device_printf(sc->dev, "Config options:"); 245230130Smav ); 246230130Smav for (;;) { 247230130Smav while (res[i] != '\0' && 248230130Smav (res[i] == ',' || isspace(res[i]) != 0)) 249230130Smav i++; 250230130Smav if (res[i] == '\0') { 251230130Smav HDA_BOOTVERBOSE( 252230130Smav printf("\n"); 253230130Smav ); 254230130Smav return; 255182999Smav } 256230130Smav j = i; 257230130Smav while (res[j] != '\0' && 258230130Smav !(res[j] == ',' || isspace(res[j]) != 0)) 259230130Smav j++; 260230130Smav len = j - i; 261230130Smav if (len > 2 && strncmp(res + i, "no", 2) == 0) 262230130Smav inv = 2; 263230130Smav else 264230130Smav inv = 0; 265264832Smarius for (k = 0; len > inv && k < nitems(hdac_quirks_tab); k++) { 266230130Smav if (strncmp(res + i + inv, 267230130Smav hdac_quirks_tab[k].key, len - inv) != 0) 268182999Smav continue; 269230130Smav if (len - inv != strlen(hdac_quirks_tab[k].key)) 270182999Smav continue; 271230130Smav HDA_BOOTVERBOSE( 272230130Smav printf(" %s%s", (inv != 0) ? "no" : "", 273230130Smav hdac_quirks_tab[k].key); 274230130Smav ); 275230130Smav if (inv == 0) { 276230130Smav *on |= hdac_quirks_tab[k].value; 277230130Smav *on &= ~hdac_quirks_tab[k].value; 278230130Smav } else if (inv != 0) { 279230130Smav *off |= hdac_quirks_tab[k].value; 280230130Smav *off &= ~hdac_quirks_tab[k].value; 281162922Sariff } 282162965Sariff break; 283182999Smav } 284230130Smav i = j; 285162922Sariff } 286162922Sariff} 287162922Sariff 288162922Sariff/**************************************************************************** 289162922Sariff * void hdac_intr_handler(void *) 290162922Sariff * 291162922Sariff * Interrupt handler. Processes interrupts received from the hdac. 292162922Sariff ****************************************************************************/ 293162922Sariffstatic void 294162922Sariffhdac_intr_handler(void *context) 295162922Sariff{ 296162922Sariff struct hdac_softc *sc; 297230130Smav device_t dev; 298162922Sariff uint32_t intsts; 299162922Sariff uint8_t rirbsts; 300182999Smav int i; 301162922Sariff 302162922Sariff sc = (struct hdac_softc *)context; 303162922Sariff hdac_lock(sc); 304171141Sariff 305162922Sariff /* Do we have anything to do? */ 306162922Sariff intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS); 307230130Smav if ((intsts & HDAC_INTSTS_GIS) == 0) { 308162922Sariff hdac_unlock(sc); 309162922Sariff return; 310162922Sariff } 311162922Sariff 312162922Sariff /* Was this a controller interrupt? */ 313230130Smav if (intsts & HDAC_INTSTS_CIS) { 314162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 315162922Sariff /* Get as many responses that we can */ 316230130Smav while (rirbsts & HDAC_RIRBSTS_RINTFL) { 317164614Sariff HDAC_WRITE_1(&sc->mem, 318164614Sariff HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL); 319230130Smav hdac_rirb_flush(sc); 320162922Sariff rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS); 321162922Sariff } 322230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 323230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 324162922Sariff } 325164614Sariff 326163057Sariff if (intsts & HDAC_INTSTS_SIS_MASK) { 327230130Smav for (i = 0; i < sc->num_ss; i++) { 328230130Smav if ((intsts & (1 << i)) == 0) 329230130Smav continue; 330230130Smav HDAC_WRITE_1(&sc->mem, (i << 5) + HDAC_SDSTS, 331230130Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS ); 332230130Smav if ((dev = sc->streams[i].dev) != NULL) { 333230130Smav HDAC_STREAM_INTR(dev, 334230130Smav sc->streams[i].dir, sc->streams[i].stream); 335230130Smav } 336182999Smav } 337162922Sariff } 338162922Sariff 339230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts); 340164614Sariff hdac_unlock(sc); 341230130Smav} 342162922Sariff 343230130Smavstatic void 344230130Smavhdac_poll_callback(void *arg) 345230130Smav{ 346230130Smav struct hdac_softc *sc = arg; 347230130Smav 348230130Smav if (sc == NULL) 349230130Smav return; 350230130Smav 351230130Smav hdac_lock(sc); 352230130Smav if (sc->polling == 0) { 353230130Smav hdac_unlock(sc); 354230130Smav return; 355182999Smav } 356230130Smav callout_reset(&sc->poll_callout, sc->poll_ival, 357230130Smav hdac_poll_callback, sc); 358230130Smav hdac_unlock(sc); 359230130Smav 360230130Smav hdac_intr_handler(sc); 361162922Sariff} 362162922Sariff 363162922Sariff/**************************************************************************** 364182999Smav * int hdac_reset(hdac_softc *, int) 365162922Sariff * 366162922Sariff * Reset the hdac to a quiescent and known state. 367162922Sariff ****************************************************************************/ 368162922Sariffstatic int 369182999Smavhdac_reset(struct hdac_softc *sc, int wakeup) 370162922Sariff{ 371162922Sariff uint32_t gctl; 372162922Sariff int count, i; 373162922Sariff 374162922Sariff /* 375162922Sariff * Stop all Streams DMA engine 376162922Sariff */ 377162922Sariff for (i = 0; i < sc->num_iss; i++) 378162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0); 379162922Sariff for (i = 0; i < sc->num_oss; i++) 380162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0); 381162922Sariff for (i = 0; i < sc->num_bss; i++) 382162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0); 383162922Sariff 384162922Sariff /* 385169277Sariff * Stop Control DMA engines. 386162922Sariff */ 387162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0); 388162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0); 389162922Sariff 390162922Sariff /* 391169277Sariff * Reset DMA position buffer. 392169277Sariff */ 393169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0); 394169277Sariff HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0); 395169277Sariff 396169277Sariff /* 397162922Sariff * Reset the controller. The reset must remain asserted for 398162922Sariff * a minimum of 100us. 399162922Sariff */ 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); 405162922Sariff if (!(gctl & HDAC_GCTL_CRST)) 406162922Sariff break; 407162922Sariff DELAY(10); 408162922Sariff } while (--count); 409162922Sariff if (gctl & HDAC_GCTL_CRST) { 410162922Sariff device_printf(sc->dev, "Unable to put hdac in reset\n"); 411162922Sariff return (ENXIO); 412162922Sariff } 413230130Smav 414182999Smav /* If wakeup is not requested - leave the controller in reset state. */ 415182999Smav if (!wakeup) 416182999Smav return (0); 417230130Smav 418162922Sariff DELAY(100); 419162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 420162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); 421162922Sariff count = 10000; 422162922Sariff do { 423162922Sariff gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); 424163057Sariff if (gctl & HDAC_GCTL_CRST) 425162922Sariff break; 426162922Sariff DELAY(10); 427162922Sariff } while (--count); 428162922Sariff if (!(gctl & HDAC_GCTL_CRST)) { 429162922Sariff device_printf(sc->dev, "Device stuck in reset\n"); 430162922Sariff return (ENXIO); 431162922Sariff } 432162922Sariff 433162922Sariff /* 434162922Sariff * Wait for codecs to finish their own reset sequence. The delay here 435162922Sariff * should be of 250us but for some reasons, on it's not enough on my 436162922Sariff * computer. Let's use twice as much as necessary to make sure that 437162922Sariff * it's reset properly. 438162922Sariff */ 439162922Sariff DELAY(1000); 440162922Sariff 441162922Sariff return (0); 442162922Sariff} 443162922Sariff 444162922Sariff 445162922Sariff/**************************************************************************** 446162922Sariff * int hdac_get_capabilities(struct hdac_softc *); 447162922Sariff * 448162922Sariff * Retreive the general capabilities of the hdac; 449162922Sariff * Number of Input Streams 450162922Sariff * Number of Output Streams 451162922Sariff * Number of bidirectional Streams 452162922Sariff * 64bit ready 453162922Sariff * CORB and RIRB sizes 454162922Sariff ****************************************************************************/ 455162922Sariffstatic int 456162922Sariffhdac_get_capabilities(struct hdac_softc *sc) 457162922Sariff{ 458162922Sariff uint16_t gcap; 459162922Sariff uint8_t corbsize, rirbsize; 460162922Sariff 461162922Sariff gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP); 462162922Sariff sc->num_iss = HDAC_GCAP_ISS(gcap); 463162922Sariff sc->num_oss = HDAC_GCAP_OSS(gcap); 464162922Sariff sc->num_bss = HDAC_GCAP_BSS(gcap); 465230130Smav sc->num_ss = sc->num_iss + sc->num_oss + sc->num_bss; 466196762Smav sc->num_sdo = HDAC_GCAP_NSDO(gcap); 467230130Smav sc->support_64bit = (gcap & HDAC_GCAP_64OK) != 0; 468230130Smav if (sc->quirks_on & HDAC_QUIRK_64BIT) 469230130Smav sc->support_64bit = 1; 470230130Smav else if (sc->quirks_off & HDAC_QUIRK_64BIT) 471230130Smav sc->support_64bit = 0; 472162922Sariff 473162922Sariff corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE); 474162922Sariff if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) == 475162922Sariff HDAC_CORBSIZE_CORBSZCAP_256) 476162922Sariff sc->corb_size = 256; 477162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) == 478162922Sariff HDAC_CORBSIZE_CORBSZCAP_16) 479162922Sariff sc->corb_size = 16; 480162922Sariff else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) == 481162922Sariff HDAC_CORBSIZE_CORBSZCAP_2) 482162922Sariff sc->corb_size = 2; 483162922Sariff else { 484162922Sariff device_printf(sc->dev, "%s: Invalid corb size (%x)\n", 485162922Sariff __func__, corbsize); 486162922Sariff return (ENXIO); 487162922Sariff } 488162922Sariff 489162922Sariff rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE); 490162922Sariff if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) == 491162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_256) 492162922Sariff sc->rirb_size = 256; 493162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) == 494162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_16) 495162922Sariff sc->rirb_size = 16; 496162922Sariff else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) == 497162922Sariff HDAC_RIRBSIZE_RIRBSZCAP_2) 498162922Sariff sc->rirb_size = 2; 499162922Sariff else { 500162922Sariff device_printf(sc->dev, "%s: Invalid rirb size (%x)\n", 501162922Sariff __func__, rirbsize); 502162922Sariff return (ENXIO); 503162922Sariff } 504162922Sariff 505196762Smav HDA_BOOTVERBOSE( 506196762Smav device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, " 507196762Smav "NSDO %d%s, CORB %d, RIRB %d\n", 508196762Smav sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo, 509196762Smav sc->support_64bit ? ", 64bit" : "", 510196762Smav sc->corb_size, sc->rirb_size); 511182999Smav ); 512182999Smav 513162922Sariff return (0); 514162922Sariff} 515162922Sariff 516162922Sariff 517162922Sariff/**************************************************************************** 518162922Sariff * void hdac_dma_cb 519162922Sariff * 520162922Sariff * This function is called by bus_dmamap_load when the mapping has been 521162922Sariff * established. We just record the physical address of the mapping into 522162922Sariff * the struct hdac_dma passed in. 523162922Sariff ****************************************************************************/ 524162922Sariffstatic void 525162922Sariffhdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error) 526162922Sariff{ 527162922Sariff struct hdac_dma *dma; 528162922Sariff 529162922Sariff if (error == 0) { 530162922Sariff dma = (struct hdac_dma *)callback_arg; 531162922Sariff dma->dma_paddr = segs[0].ds_addr; 532162922Sariff } 533162922Sariff} 534162922Sariff 535162922Sariff 536162922Sariff/**************************************************************************** 537162922Sariff * int hdac_dma_alloc 538162922Sariff * 539162922Sariff * This function allocate and setup a dma region (struct hdac_dma). 540162922Sariff * It must be freed by a corresponding hdac_dma_free. 541162922Sariff ****************************************************************************/ 542162922Sariffstatic int 543162922Sariffhdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size) 544162922Sariff{ 545169277Sariff bus_size_t roundsz; 546162922Sariff int result; 547162922Sariff 548230130Smav roundsz = roundup2(size, HDA_DMA_ALIGNMENT); 549162922Sariff bzero(dma, sizeof(*dma)); 550162922Sariff 551162922Sariff /* 552162922Sariff * Create a DMA tag 553162922Sariff */ 554194861Smav result = bus_dma_tag_create( 555194861Smav bus_get_dma_tag(sc->dev), /* parent */ 556230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 557162922Sariff 0, /* boundary */ 558194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 559194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 560162922Sariff BUS_SPACE_MAXADDR, /* highaddr */ 561162922Sariff NULL, /* filtfunc */ 562162922Sariff NULL, /* fistfuncarg */ 563169277Sariff roundsz, /* maxsize */ 564162922Sariff 1, /* nsegments */ 565169277Sariff roundsz, /* maxsegsz */ 566162922Sariff 0, /* flags */ 567162922Sariff NULL, /* lockfunc */ 568162922Sariff NULL, /* lockfuncarg */ 569162922Sariff &dma->dma_tag); /* dmat */ 570162922Sariff if (result != 0) { 571162922Sariff device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n", 572162922Sariff __func__, result); 573167773Sariff goto hdac_dma_alloc_fail; 574162922Sariff } 575162922Sariff 576162922Sariff /* 577162922Sariff * Allocate DMA memory 578162922Sariff */ 579162965Sariff result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 580169277Sariff BUS_DMA_NOWAIT | BUS_DMA_ZERO | 581171330Sariff ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), 582171330Sariff &dma->dma_map); 583162922Sariff if (result != 0) { 584162922Sariff device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n", 585162922Sariff __func__, result); 586167773Sariff goto hdac_dma_alloc_fail; 587162922Sariff } 588162922Sariff 589169277Sariff dma->dma_size = roundsz; 590169277Sariff 591162922Sariff /* 592162922Sariff * Map the memory 593162922Sariff */ 594162922Sariff result = bus_dmamap_load(dma->dma_tag, dma->dma_map, 595169277Sariff (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0); 596162922Sariff if (result != 0 || dma->dma_paddr == 0) { 597167773Sariff if (result == 0) 598167773Sariff result = ENOMEM; 599162922Sariff device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n", 600162922Sariff __func__, result); 601167773Sariff goto hdac_dma_alloc_fail; 602162922Sariff } 603162922Sariff 604183097Smav HDA_BOOTHVERBOSE( 605169277Sariff device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n", 606169277Sariff __func__, (uintmax_t)size, (uintmax_t)roundsz); 607169277Sariff ); 608169277Sariff 609162922Sariff return (0); 610169277Sariff 611167773Sariffhdac_dma_alloc_fail: 612169277Sariff hdac_dma_free(sc, dma); 613167773Sariff 614162922Sariff return (result); 615162922Sariff} 616162922Sariff 617162922Sariff 618162922Sariff/**************************************************************************** 619169277Sariff * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *) 620162922Sariff * 621162922Sariff * Free a struct dhac_dma that has been previously allocated via the 622162922Sariff * hdac_dma_alloc function. 623162922Sariff ****************************************************************************/ 624162922Sariffstatic void 625169277Sariffhdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) 626162922Sariff{ 627267581Sjhb if (dma->dma_paddr != 0) { 628169277Sariff#if 0 629162922Sariff /* Flush caches */ 630162922Sariff bus_dmamap_sync(dma->dma_tag, dma->dma_map, 631162922Sariff BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 632169277Sariff#endif 633162922Sariff bus_dmamap_unload(dma->dma_tag, dma->dma_map); 634267581Sjhb dma->dma_paddr = 0; 635167773Sariff } 636167773Sariff if (dma->dma_vaddr != NULL) { 637162922Sariff bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 638167773Sariff dma->dma_vaddr = NULL; 639167773Sariff } 640167773Sariff if (dma->dma_tag != NULL) { 641162922Sariff bus_dma_tag_destroy(dma->dma_tag); 642167773Sariff dma->dma_tag = NULL; 643162922Sariff } 644167773Sariff dma->dma_size = 0; 645162922Sariff} 646162922Sariff 647162922Sariff/**************************************************************************** 648162922Sariff * int hdac_mem_alloc(struct hdac_softc *) 649162922Sariff * 650162922Sariff * Allocate all the bus resources necessary to speak with the physical 651162922Sariff * controller. 652162922Sariff ****************************************************************************/ 653162922Sariffstatic int 654162922Sariffhdac_mem_alloc(struct hdac_softc *sc) 655162922Sariff{ 656162922Sariff struct hdac_mem *mem; 657162922Sariff 658162922Sariff mem = &sc->mem; 659162922Sariff mem->mem_rid = PCIR_BAR(0); 660162922Sariff mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, 661162922Sariff &mem->mem_rid, RF_ACTIVE); 662162922Sariff if (mem->mem_res == NULL) { 663162922Sariff device_printf(sc->dev, 664162922Sariff "%s: Unable to allocate memory resource\n", __func__); 665162922Sariff return (ENOMEM); 666162922Sariff } 667162922Sariff mem->mem_tag = rman_get_bustag(mem->mem_res); 668162922Sariff mem->mem_handle = rman_get_bushandle(mem->mem_res); 669162922Sariff 670162922Sariff return (0); 671162922Sariff} 672162922Sariff 673162922Sariff/**************************************************************************** 674162922Sariff * void hdac_mem_free(struct hdac_softc *) 675162922Sariff * 676162922Sariff * Free up resources previously allocated by hdac_mem_alloc. 677162922Sariff ****************************************************************************/ 678162922Sariffstatic void 679162922Sariffhdac_mem_free(struct hdac_softc *sc) 680162922Sariff{ 681162922Sariff struct hdac_mem *mem; 682162922Sariff 683162922Sariff mem = &sc->mem; 684162922Sariff if (mem->mem_res != NULL) 685162922Sariff bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid, 686162922Sariff mem->mem_res); 687164614Sariff mem->mem_res = NULL; 688162922Sariff} 689162922Sariff 690162922Sariff/**************************************************************************** 691162922Sariff * int hdac_irq_alloc(struct hdac_softc *) 692162922Sariff * 693162922Sariff * Allocate and setup the resources necessary for interrupt handling. 694162922Sariff ****************************************************************************/ 695162922Sariffstatic int 696162922Sariffhdac_irq_alloc(struct hdac_softc *sc) 697162922Sariff{ 698162922Sariff struct hdac_irq *irq; 699162922Sariff int result; 700162922Sariff 701162922Sariff irq = &sc->irq; 702162922Sariff irq->irq_rid = 0x0; 703171330Sariff 704230130Smav if ((sc->quirks_off & HDAC_QUIRK_MSI) == 0 && 705171330Sariff (result = pci_msi_count(sc->dev)) == 1 && 706171330Sariff pci_alloc_msi(sc->dev, &result) == 0) 707171330Sariff irq->irq_rid = 0x1; 708171330Sariff 709162922Sariff irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 710162922Sariff &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE); 711162922Sariff if (irq->irq_res == NULL) { 712162922Sariff device_printf(sc->dev, "%s: Unable to allocate irq\n", 713162922Sariff __func__); 714167773Sariff goto hdac_irq_alloc_fail; 715162922Sariff } 716182999Smav result = bus_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE | INTR_TYPE_AV, 717182999Smav NULL, hdac_intr_handler, sc, &irq->irq_handle); 718162922Sariff if (result != 0) { 719162922Sariff device_printf(sc->dev, 720162922Sariff "%s: Unable to setup interrupt handler (%x)\n", 721162922Sariff __func__, result); 722167773Sariff goto hdac_irq_alloc_fail; 723162922Sariff } 724162922Sariff 725162922Sariff return (0); 726162922Sariff 727167773Sariffhdac_irq_alloc_fail: 728164614Sariff hdac_irq_free(sc); 729164614Sariff 730162922Sariff return (ENXIO); 731162922Sariff} 732162922Sariff 733162922Sariff/**************************************************************************** 734162922Sariff * void hdac_irq_free(struct hdac_softc *) 735162922Sariff * 736162922Sariff * Free up resources previously allocated by hdac_irq_alloc. 737162922Sariff ****************************************************************************/ 738162922Sariffstatic void 739162922Sariffhdac_irq_free(struct hdac_softc *sc) 740162922Sariff{ 741162922Sariff struct hdac_irq *irq; 742162922Sariff 743162922Sariff irq = &sc->irq; 744164614Sariff if (irq->irq_res != NULL && irq->irq_handle != NULL) 745162922Sariff bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle); 746162922Sariff if (irq->irq_res != NULL) 747162922Sariff bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid, 748162922Sariff irq->irq_res); 749188656Smav if (irq->irq_rid == 0x1) 750171330Sariff pci_release_msi(sc->dev); 751164614Sariff irq->irq_handle = NULL; 752164614Sariff irq->irq_res = NULL; 753171330Sariff irq->irq_rid = 0x0; 754162922Sariff} 755162922Sariff 756162922Sariff/**************************************************************************** 757162922Sariff * void hdac_corb_init(struct hdac_softc *) 758162922Sariff * 759162922Sariff * Initialize the corb registers for operations but do not start it up yet. 760162922Sariff * The CORB engine must not be running when this function is called. 761162922Sariff ****************************************************************************/ 762162922Sariffstatic void 763162922Sariffhdac_corb_init(struct hdac_softc *sc) 764162922Sariff{ 765162922Sariff uint8_t corbsize; 766162922Sariff uint64_t corbpaddr; 767162922Sariff 768162922Sariff /* Setup the CORB size. */ 769162922Sariff switch (sc->corb_size) { 770162922Sariff case 256: 771162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256); 772162922Sariff break; 773162922Sariff case 16: 774162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16); 775162922Sariff break; 776162922Sariff case 2: 777162922Sariff corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2); 778162922Sariff break; 779162922Sariff default: 780162922Sariff panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size); 781162922Sariff } 782162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize); 783162922Sariff 784162922Sariff /* Setup the CORB Address in the hdac */ 785162922Sariff corbpaddr = (uint64_t)sc->corb_dma.dma_paddr; 786162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr); 787162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32)); 788162922Sariff 789162922Sariff /* Set the WP and RP */ 790162922Sariff sc->corb_wp = 0; 791162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 792162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST); 793162922Sariff /* 794162922Sariff * The HDA specification indicates that the CORBRPRST bit will always 795162922Sariff * read as zero. Unfortunately, it seems that at least the 82801G 796162922Sariff * doesn't reset the bit to zero, which stalls the corb engine. 797162922Sariff * manually reset the bit to zero before continuing. 798162922Sariff */ 799162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0); 800162922Sariff 801162922Sariff /* Enable CORB error reporting */ 802162922Sariff#if 0 803162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE); 804162922Sariff#endif 805162922Sariff} 806162922Sariff 807162922Sariff/**************************************************************************** 808162922Sariff * void hdac_rirb_init(struct hdac_softc *) 809162922Sariff * 810162922Sariff * Initialize the rirb registers for operations but do not start it up yet. 811162922Sariff * The RIRB engine must not be running when this function is called. 812162922Sariff ****************************************************************************/ 813162922Sariffstatic void 814162922Sariffhdac_rirb_init(struct hdac_softc *sc) 815162922Sariff{ 816162922Sariff uint8_t rirbsize; 817162922Sariff uint64_t rirbpaddr; 818162922Sariff 819162922Sariff /* Setup the RIRB size. */ 820162922Sariff switch (sc->rirb_size) { 821162922Sariff case 256: 822162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256); 823162922Sariff break; 824162922Sariff case 16: 825162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16); 826162922Sariff break; 827162922Sariff case 2: 828162922Sariff rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2); 829162922Sariff break; 830162922Sariff default: 831162922Sariff panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size); 832162922Sariff } 833162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize); 834162922Sariff 835162922Sariff /* Setup the RIRB Address in the hdac */ 836162922Sariff rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr; 837162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr); 838162922Sariff HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32)); 839162922Sariff 840162922Sariff /* Setup the WP and RP */ 841162922Sariff sc->rirb_rp = 0; 842162922Sariff HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST); 843162922Sariff 844182999Smav /* Setup the interrupt threshold */ 845182999Smav HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2); 846162922Sariff 847182999Smav /* Enable Overrun and response received reporting */ 848162922Sariff#if 0 849182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 850182999Smav HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL); 851162922Sariff#else 852182999Smav HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL); 853162922Sariff#endif 854162922Sariff 855169277Sariff#if 0 856162922Sariff /* 857162922Sariff * Make sure that the Host CPU cache doesn't contain any dirty 858162922Sariff * cache lines that falls in the rirb. If I understood correctly, it 859162922Sariff * should be sufficient to do this only once as the rirb is purely 860162922Sariff * read-only from now on. 861162922Sariff */ 862162922Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 863162922Sariff BUS_DMASYNC_PREREAD); 864169277Sariff#endif 865162922Sariff} 866162922Sariff 867162922Sariff/**************************************************************************** 868162922Sariff * void hdac_corb_start(hdac_softc *) 869162922Sariff * 870162922Sariff * Startup the corb DMA engine 871162922Sariff ****************************************************************************/ 872162922Sariffstatic void 873162922Sariffhdac_corb_start(struct hdac_softc *sc) 874162922Sariff{ 875162922Sariff uint32_t corbctl; 876162922Sariff 877162922Sariff corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL); 878162922Sariff corbctl |= HDAC_CORBCTL_CORBRUN; 879162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl); 880162922Sariff} 881162922Sariff 882162922Sariff/**************************************************************************** 883162922Sariff * void hdac_rirb_start(hdac_softc *) 884162922Sariff * 885162922Sariff * Startup the rirb DMA engine 886162922Sariff ****************************************************************************/ 887162922Sariffstatic void 888162922Sariffhdac_rirb_start(struct hdac_softc *sc) 889162922Sariff{ 890162922Sariff uint32_t rirbctl; 891162922Sariff 892162922Sariff rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL); 893162922Sariff rirbctl |= HDAC_RIRBCTL_RIRBDMAEN; 894162922Sariff HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl); 895162922Sariff} 896162922Sariff 897164614Sariffstatic int 898164614Sariffhdac_rirb_flush(struct hdac_softc *sc) 899164614Sariff{ 900164614Sariff struct hdac_rirb *rirb_base, *rirb; 901164614Sariff nid_t cad; 902164614Sariff uint32_t resp; 903164614Sariff uint8_t rirbwp; 904171141Sariff int ret; 905164614Sariff 906164614Sariff rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr; 907164614Sariff rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP); 908169277Sariff#if 0 909164614Sariff bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map, 910164614Sariff BUS_DMASYNC_POSTREAD); 911169277Sariff#endif 912164614Sariff 913171141Sariff ret = 0; 914164614Sariff while (sc->rirb_rp != rirbwp) { 915164614Sariff sc->rirb_rp++; 916164614Sariff sc->rirb_rp %= sc->rirb_size; 917164614Sariff rirb = &rirb_base[sc->rirb_rp]; 918164614Sariff cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex); 919164614Sariff resp = rirb->response; 920164614Sariff if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) { 921230130Smav sc->unsolq[sc->unsolq_wp++] = resp; 922164614Sariff sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 923230130Smav sc->unsolq[sc->unsolq_wp++] = cad; 924230130Smav sc->unsolq_wp %= HDAC_UNSOLQ_MAX; 925230130Smav } else if (sc->codecs[cad].pending <= 0) { 926230130Smav device_printf(sc->dev, "Unexpected unsolicited " 927230130Smav "response from address %d: %08x\n", cad, resp); 928230130Smav } else { 929230130Smav sc->codecs[cad].response = resp; 930230130Smav sc->codecs[cad].pending--; 931230130Smav } 932164614Sariff ret++; 933164614Sariff } 934164614Sariff return (ret); 935164614Sariff} 936164614Sariff 937164614Sariffstatic int 938164614Sariffhdac_unsolq_flush(struct hdac_softc *sc) 939164614Sariff{ 940230130Smav device_t child; 941164614Sariff nid_t cad; 942230130Smav uint32_t resp; 943164614Sariff int ret = 0; 944164614Sariff 945164614Sariff if (sc->unsolq_st == HDAC_UNSOLQ_READY) { 946164614Sariff sc->unsolq_st = HDAC_UNSOLQ_BUSY; 947164614Sariff while (sc->unsolq_rp != sc->unsolq_wp) { 948230130Smav resp = sc->unsolq[sc->unsolq_rp++]; 949164614Sariff sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 950230130Smav cad = sc->unsolq[sc->unsolq_rp++]; 951230130Smav sc->unsolq_rp %= HDAC_UNSOLQ_MAX; 952230130Smav if ((child = sc->codecs[cad].dev) != NULL) 953230130Smav HDAC_UNSOL_INTR(child, resp); 954164614Sariff ret++; 955164614Sariff } 956164614Sariff sc->unsolq_st = HDAC_UNSOLQ_READY; 957164614Sariff } 958164614Sariff 959164614Sariff return (ret); 960164614Sariff} 961164614Sariff 962162922Sariff/**************************************************************************** 963162922Sariff * uint32_t hdac_command_sendone_internal 964162922Sariff * 965162922Sariff * Wrapper function that sends only one command to a given codec 966162922Sariff ****************************************************************************/ 967162922Sariffstatic uint32_t 968230130Smavhdac_send_command(struct hdac_softc *sc, nid_t cad, uint32_t verb) 969162922Sariff{ 970230130Smav int timeout; 971230130Smav uint32_t *corb; 972162922Sariff 973163057Sariff if (!hdac_lockowned(sc)) 974162922Sariff device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n"); 975230130Smav verb &= ~HDA_CMD_CAD_MASK; 976230130Smav verb |= ((uint32_t)cad) << HDA_CMD_CAD_SHIFT; 977230130Smav sc->codecs[cad].response = HDA_INVALID; 978162922Sariff 979230130Smav sc->codecs[cad].pending++; 980230130Smav sc->corb_wp++; 981230130Smav sc->corb_wp %= sc->corb_size; 982162922Sariff corb = (uint32_t *)sc->corb_dma.dma_vaddr; 983169277Sariff#if 0 984230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 985230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE); 986169277Sariff#endif 987230130Smav corb[sc->corb_wp] = verb; 988169277Sariff#if 0 989230130Smav bus_dmamap_sync(sc->corb_dma.dma_tag, 990230130Smav sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE); 991169277Sariff#endif 992230130Smav HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp); 993162922Sariff 994230130Smav timeout = 10000; 995230130Smav do { 996230130Smav if (hdac_rirb_flush(sc) == 0) 997162922Sariff DELAY(10); 998230130Smav } while (sc->codecs[cad].pending != 0 && --timeout); 999162922Sariff 1000230130Smav if (sc->codecs[cad].pending != 0) { 1001230130Smav device_printf(sc->dev, "Command timeout on address %d\n", cad); 1002230130Smav sc->codecs[cad].pending = 0; 1003230130Smav } 1004162922Sariff 1005230130Smav if (sc->unsolq_rp != sc->unsolq_wp) 1006230130Smav taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task); 1007230130Smav return (sc->codecs[cad].response); 1008162922Sariff} 1009162922Sariff 1010162922Sariff/**************************************************************************** 1011162922Sariff * Device Methods 1012162922Sariff ****************************************************************************/ 1013162922Sariff 1014162922Sariff/**************************************************************************** 1015162922Sariff * int hdac_probe(device_t) 1016162922Sariff * 1017162922Sariff * Probe for the presence of an hdac. If none is found, check for a generic 1018162922Sariff * match using the subclass of the device. 1019162922Sariff ****************************************************************************/ 1020162922Sariffstatic int 1021162922Sariffhdac_probe(device_t dev) 1022162922Sariff{ 1023162922Sariff int i, result; 1024163257Sariff uint32_t model; 1025163257Sariff uint16_t class, subclass; 1026162922Sariff char desc[64]; 1027162922Sariff 1028162922Sariff model = (uint32_t)pci_get_device(dev) << 16; 1029162922Sariff model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1030162922Sariff class = pci_get_class(dev); 1031162922Sariff subclass = pci_get_subclass(dev); 1032162922Sariff 1033162922Sariff bzero(desc, sizeof(desc)); 1034162922Sariff result = ENXIO; 1035264832Smarius for (i = 0; i < nitems(hdac_devices); i++) { 1036162922Sariff if (hdac_devices[i].model == model) { 1037230331Smav strlcpy(desc, hdac_devices[i].desc, sizeof(desc)); 1038230331Smav result = BUS_PROBE_DEFAULT; 1039162922Sariff break; 1040162922Sariff } 1041163257Sariff if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1042162922Sariff class == PCIC_MULTIMEDIA && 1043162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1044230331Smav snprintf(desc, sizeof(desc), 1045230331Smav "%s (0x%04x)", 1046230331Smav hdac_devices[i].desc, pci_get_device(dev)); 1047230331Smav result = BUS_PROBE_GENERIC; 1048162922Sariff break; 1049162922Sariff } 1050162922Sariff } 1051162922Sariff if (result == ENXIO && class == PCIC_MULTIMEDIA && 1052162922Sariff subclass == PCIS_MULTIMEDIA_HDA) { 1053230331Smav snprintf(desc, sizeof(desc), "Generic (0x%08x)", model); 1054230331Smav result = BUS_PROBE_GENERIC; 1055162922Sariff } 1056162922Sariff if (result != ENXIO) { 1057230331Smav strlcat(desc, " HDA Controller", sizeof(desc)); 1058162922Sariff device_set_desc_copy(dev, desc); 1059162922Sariff } 1060162922Sariff 1061162922Sariff return (result); 1062162922Sariff} 1063162922Sariff 1064162922Sariffstatic void 1065171141Sariffhdac_unsolq_task(void *context, int pending) 1066171141Sariff{ 1067171141Sariff struct hdac_softc *sc; 1068171141Sariff 1069171141Sariff sc = (struct hdac_softc *)context; 1070171141Sariff 1071171141Sariff hdac_lock(sc); 1072171141Sariff hdac_unsolq_flush(sc); 1073171141Sariff hdac_unlock(sc); 1074171141Sariff} 1075171141Sariff 1076162922Sariff/**************************************************************************** 1077162922Sariff * int hdac_attach(device_t) 1078162922Sariff * 1079162922Sariff * Attach the device into the kernel. Interrupts usually won't be enabled 1080162922Sariff * when this function is called. Setup everything that doesn't require 1081162922Sariff * interrupts and defer probing of codecs until interrupts are enabled. 1082162922Sariff ****************************************************************************/ 1083162922Sariffstatic int 1084162922Sariffhdac_attach(device_t dev) 1085162922Sariff{ 1086162922Sariff struct hdac_softc *sc; 1087162922Sariff int result; 1088189086Smav int i, devid = -1; 1089189086Smav uint32_t model; 1090189086Smav uint16_t class, subclass; 1091169277Sariff uint16_t vendor; 1092169277Sariff uint8_t v; 1093162922Sariff 1094230130Smav sc = device_get_softc(dev); 1095223118Sjoel HDA_BOOTVERBOSE( 1096242352Smav device_printf(dev, "PCI card vendor: 0x%04x, device: 0x%04x\n", 1097242352Smav pci_get_subvendor(dev), pci_get_subdevice(dev)); 1098223118Sjoel device_printf(dev, "HDA Driver Revision: %s\n", 1099223118Sjoel HDA_DRV_TEST_REV); 1100223118Sjoel ); 1101182999Smav 1102189086Smav model = (uint32_t)pci_get_device(dev) << 16; 1103189086Smav model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff; 1104189086Smav class = pci_get_class(dev); 1105189086Smav subclass = pci_get_subclass(dev); 1106189086Smav 1107264832Smarius for (i = 0; i < nitems(hdac_devices); i++) { 1108189086Smav if (hdac_devices[i].model == model) { 1109189086Smav devid = i; 1110189086Smav break; 1111189086Smav } 1112189086Smav if (HDA_DEV_MATCH(hdac_devices[i].model, model) && 1113189086Smav class == PCIC_MULTIMEDIA && 1114189086Smav subclass == PCIS_MULTIMEDIA_HDA) { 1115189086Smav devid = i; 1116189086Smav break; 1117189086Smav } 1118189086Smav } 1119189086Smav 1120230130Smav sc->lock = snd_mtxcreate(device_get_nameunit(dev), "HDA driver mutex"); 1121162922Sariff sc->dev = dev; 1122230130Smav TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc); 1123283291Sjkim callout_init(&sc->poll_callout, 1); 1124230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) 1125230130Smav sc->codecs[i].dev = NULL; 1126230130Smav if (devid >= 0) { 1127230130Smav sc->quirks_on = hdac_devices[devid].quirks_on; 1128230130Smav sc->quirks_off = hdac_devices[devid].quirks_off; 1129230130Smav } else { 1130230130Smav sc->quirks_on = 0; 1131230130Smav sc->quirks_off = 0; 1132165281Sariff } 1133169277Sariff if (resource_int_value(device_get_name(dev), 1134230130Smav device_get_unit(dev), "msi", &i) == 0) { 1135230130Smav if (i == 0) 1136230130Smav sc->quirks_off |= HDAC_QUIRK_MSI; 1137230130Smav else { 1138230130Smav sc->quirks_on |= HDAC_QUIRK_MSI; 1139230130Smav sc->quirks_off |= ~HDAC_QUIRK_MSI; 1140230130Smav } 1141230130Smav } 1142230130Smav hdac_config_fetch(sc, &sc->quirks_on, &sc->quirks_off); 1143230130Smav HDA_BOOTVERBOSE( 1144230130Smav device_printf(sc->dev, 1145230130Smav "Config options: on=0x%08x off=0x%08x\n", 1146230130Smav sc->quirks_on, sc->quirks_off); 1147230130Smav ); 1148230130Smav sc->poll_ival = hz; 1149230130Smav if (resource_int_value(device_get_name(dev), 1150169277Sariff device_get_unit(dev), "polling", &i) == 0 && i != 0) 1151164614Sariff sc->polling = 1; 1152164614Sariff else 1153164614Sariff sc->polling = 0; 1154164614Sariff 1155162922Sariff pci_enable_busmaster(dev); 1156162922Sariff 1157230130Smav vendor = pci_get_vendor(dev); 1158169277Sariff if (vendor == INTEL_VENDORID) { 1159169277Sariff /* TCSEL -> TC0 */ 1160169277Sariff v = pci_read_config(dev, 0x44, 1); 1161169277Sariff pci_write_config(dev, 0x44, v & 0xf8, 1); 1162183097Smav HDA_BOOTHVERBOSE( 1163169277Sariff device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v, 1164169277Sariff pci_read_config(dev, 0x44, 1)); 1165169277Sariff ); 1166169277Sariff } 1167169277Sariff 1168169277Sariff#if defined(__i386__) || defined(__amd64__) 1169171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1170169277Sariff 1171169277Sariff if (resource_int_value(device_get_name(dev), 1172169277Sariff device_get_unit(dev), "snoop", &i) == 0 && i != 0) { 1173169277Sariff#else 1174171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1175169277Sariff#endif 1176169277Sariff /* 1177169277Sariff * Try to enable PCIe snoop to avoid messing around with 1178169277Sariff * uncacheable DMA attribute. Since PCIe snoop register 1179169277Sariff * config is pretty much vendor specific, there are no 1180169277Sariff * general solutions on how to enable it, forcing us (even 1181169277Sariff * Microsoft) to enable uncacheable or write combined DMA 1182169277Sariff * by default. 1183169277Sariff * 1184169277Sariff * http://msdn2.microsoft.com/en-us/library/ms790324.aspx 1185169277Sariff */ 1186264832Smarius for (i = 0; i < nitems(hdac_pcie_snoop); i++) { 1187169277Sariff if (hdac_pcie_snoop[i].vendor != vendor) 1188169277Sariff continue; 1189171330Sariff sc->flags &= ~HDAC_F_DMA_NOCACHE; 1190169277Sariff if (hdac_pcie_snoop[i].reg == 0x00) 1191169277Sariff break; 1192169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1193169277Sariff if ((v & hdac_pcie_snoop[i].enable) == 1194169277Sariff hdac_pcie_snoop[i].enable) 1195169277Sariff break; 1196169277Sariff v &= hdac_pcie_snoop[i].mask; 1197169277Sariff v |= hdac_pcie_snoop[i].enable; 1198169277Sariff pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1); 1199169277Sariff v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1); 1200169277Sariff if ((v & hdac_pcie_snoop[i].enable) != 1201169277Sariff hdac_pcie_snoop[i].enable) { 1202169277Sariff HDA_BOOTVERBOSE( 1203169277Sariff device_printf(dev, 1204169277Sariff "WARNING: Failed to enable PCIe " 1205169277Sariff "snoop!\n"); 1206169277Sariff ); 1207169277Sariff#if defined(__i386__) || defined(__amd64__) 1208171330Sariff sc->flags |= HDAC_F_DMA_NOCACHE; 1209169277Sariff#endif 1210169277Sariff } 1211169277Sariff break; 1212169277Sariff } 1213169277Sariff#if defined(__i386__) || defined(__amd64__) 1214169277Sariff } 1215169277Sariff#endif 1216169277Sariff 1217183097Smav HDA_BOOTHVERBOSE( 1218169277Sariff device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n", 1219171330Sariff (sc->flags & HDAC_F_DMA_NOCACHE) ? 1220171330Sariff "Uncacheable" : "PCIe snoop", vendor); 1221169277Sariff ); 1222169277Sariff 1223162922Sariff /* Allocate resources */ 1224162922Sariff result = hdac_mem_alloc(sc); 1225162922Sariff if (result != 0) 1226163057Sariff goto hdac_attach_fail; 1227162922Sariff result = hdac_irq_alloc(sc); 1228162922Sariff if (result != 0) 1229163057Sariff goto hdac_attach_fail; 1230162922Sariff 1231162922Sariff /* Get Capabilities */ 1232162922Sariff result = hdac_get_capabilities(sc); 1233162922Sariff if (result != 0) 1234163057Sariff goto hdac_attach_fail; 1235162922Sariff 1236230130Smav /* Allocate CORB, RIRB, POS and BDLs dma memory */ 1237162922Sariff result = hdac_dma_alloc(sc, &sc->corb_dma, 1238162922Sariff sc->corb_size * sizeof(uint32_t)); 1239162922Sariff if (result != 0) 1240163057Sariff goto hdac_attach_fail; 1241162922Sariff result = hdac_dma_alloc(sc, &sc->rirb_dma, 1242162922Sariff sc->rirb_size * sizeof(struct hdac_rirb)); 1243162922Sariff if (result != 0) 1244163057Sariff goto hdac_attach_fail; 1245230130Smav sc->streams = malloc(sizeof(struct hdac_stream) * sc->num_ss, 1246230130Smav M_HDAC, M_ZERO | M_WAITOK); 1247230130Smav for (i = 0; i < sc->num_ss; i++) { 1248230130Smav result = hdac_dma_alloc(sc, &sc->streams[i].bdl, 1249230130Smav sizeof(struct hdac_bdle) * HDA_BDL_MAX); 1250230130Smav if (result != 0) 1251230130Smav goto hdac_attach_fail; 1252230130Smav } 1253230130Smav if (sc->quirks_on & HDAC_QUIRK_DMAPOS) { 1254230130Smav if (hdac_dma_alloc(sc, &sc->pos_dma, (sc->num_ss) * 8) != 0) { 1255230130Smav HDA_BOOTVERBOSE( 1256230130Smav device_printf(dev, "Failed to " 1257230130Smav "allocate DMA pos buffer " 1258230130Smav "(non-fatal)\n"); 1259230130Smav ); 1260230130Smav } else { 1261230130Smav uint64_t addr = sc->pos_dma.dma_paddr; 1262162922Sariff 1263230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, addr >> 32); 1264230130Smav HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 1265230130Smav (addr & HDAC_DPLBASE_DPLBASE_MASK) | 1266230130Smav HDAC_DPLBASE_DPLBASE_DMAPBE); 1267230130Smav } 1268230130Smav } 1269230130Smav 1270194861Smav result = bus_dma_tag_create( 1271194861Smav bus_get_dma_tag(sc->dev), /* parent */ 1272230130Smav HDA_DMA_ALIGNMENT, /* alignment */ 1273194861Smav 0, /* boundary */ 1274194861Smav (sc->support_64bit) ? BUS_SPACE_MAXADDR : 1275194861Smav BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1276194861Smav BUS_SPACE_MAXADDR, /* highaddr */ 1277194861Smav NULL, /* filtfunc */ 1278194861Smav NULL, /* fistfuncarg */ 1279194861Smav HDA_BUFSZ_MAX, /* maxsize */ 1280194861Smav 1, /* nsegments */ 1281194861Smav HDA_BUFSZ_MAX, /* maxsegsz */ 1282194861Smav 0, /* flags */ 1283194861Smav NULL, /* lockfunc */ 1284194861Smav NULL, /* lockfuncarg */ 1285194861Smav &sc->chan_dmat); /* dmat */ 1286194861Smav if (result != 0) { 1287194861Smav device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n", 1288194861Smav __func__, result); 1289194861Smav goto hdac_attach_fail; 1290194861Smav } 1291194861Smav 1292162922Sariff /* Quiesce everything */ 1293183097Smav HDA_BOOTHVERBOSE( 1294182999Smav device_printf(dev, "Reset controller...\n"); 1295182999Smav ); 1296182999Smav hdac_reset(sc, 1); 1297162922Sariff 1298162922Sariff /* Initialize the CORB and RIRB */ 1299162922Sariff hdac_corb_init(sc); 1300162922Sariff hdac_rirb_init(sc); 1301162922Sariff 1302162922Sariff /* Defer remaining of initialization until interrupts are enabled */ 1303162922Sariff sc->intrhook.ich_func = hdac_attach2; 1304162922Sariff sc->intrhook.ich_arg = (void *)sc; 1305162922Sariff if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) { 1306162922Sariff sc->intrhook.ich_func = NULL; 1307162922Sariff hdac_attach2((void *)sc); 1308162922Sariff } 1309162922Sariff 1310163057Sariff return (0); 1311162922Sariff 1312163057Sariffhdac_attach_fail: 1313162922Sariff hdac_irq_free(sc); 1314230130Smav for (i = 0; i < sc->num_ss; i++) 1315230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1316230130Smav free(sc->streams, M_HDAC); 1317169277Sariff hdac_dma_free(sc, &sc->rirb_dma); 1318169277Sariff hdac_dma_free(sc, &sc->corb_dma); 1319162922Sariff hdac_mem_free(sc); 1320162922Sariff snd_mtxfree(sc->lock); 1321162922Sariff 1322163057Sariff return (ENXIO); 1323162922Sariff} 1324162922Sariff 1325230130Smavstatic int 1326230130Smavsysctl_hdac_pindump(SYSCTL_HANDLER_ARGS) 1327162922Sariff{ 1328230130Smav struct hdac_softc *sc; 1329230130Smav device_t *devlist; 1330230130Smav device_t dev; 1331230130Smav int devcount, i, err, val; 1332162922Sariff 1333230130Smav dev = oidp->oid_arg1; 1334230130Smav sc = device_get_softc(dev); 1335230130Smav if (sc == NULL) 1336230130Smav return (EINVAL); 1337230130Smav val = 0; 1338230130Smav err = sysctl_handle_int(oidp, &val, 0, req); 1339230130Smav if (err != 0 || req->newptr == NULL || val == 0) 1340230130Smav return (err); 1341162922Sariff 1342230130Smav /* XXX: Temporary. For debugging. */ 1343230130Smav if (val == 100) { 1344230130Smav hdac_suspend(dev); 1345182999Smav return (0); 1346230130Smav } else if (val == 101) { 1347230130Smav hdac_resume(dev); 1348182999Smav return (0); 1349182999Smav } 1350162922Sariff 1351230130Smav if ((err = device_get_children(dev, &devlist, &devcount)) != 0) 1352230130Smav return (err); 1353230130Smav hdac_lock(sc); 1354230130Smav for (i = 0; i < devcount; i++) 1355230130Smav HDAC_PINDUMP(devlist[i]); 1356230130Smav hdac_unlock(sc); 1357230130Smav free(devlist, M_TEMP); 1358182999Smav return (0); 1359162922Sariff} 1360162922Sariff 1361183097Smavstatic int 1362230326Smavhdac_mdata_rate(uint16_t fmt) 1363162922Sariff{ 1364230326Smav static const int mbits[8] = { 8, 16, 32, 32, 32, 32, 32, 32 }; 1365230326Smav int rate, bits; 1366162922Sariff 1367230130Smav if (fmt & (1 << 14)) 1368230130Smav rate = 44100; 1369230130Smav else 1370230130Smav rate = 48000; 1371230130Smav rate *= ((fmt >> 11) & 0x07) + 1; 1372230130Smav rate /= ((fmt >> 8) & 0x07) + 1; 1373230326Smav bits = mbits[(fmt >> 4) & 0x03]; 1374230326Smav bits *= (fmt & 0x0f) + 1; 1375230326Smav return (rate * bits); 1376182999Smav} 1377182999Smav 1378230326Smavstatic int 1379230326Smavhdac_bdata_rate(uint16_t fmt, int output) 1380230326Smav{ 1381230326Smav static const int bbits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 }; 1382230326Smav int rate, bits; 1383230326Smav 1384230326Smav rate = 48000; 1385230326Smav rate *= ((fmt >> 11) & 0x07) + 1; 1386230326Smav bits = bbits[(fmt >> 4) & 0x03]; 1387230326Smav bits *= (fmt & 0x0f) + 1; 1388230326Smav if (!output) 1389230326Smav bits = ((bits + 7) & ~0x07) + 10; 1390230326Smav return (rate * bits); 1391230326Smav} 1392230326Smav 1393182999Smavstatic void 1394230130Smavhdac_poll_reinit(struct hdac_softc *sc) 1395182999Smav{ 1396230130Smav int i, pollticks, min = 1000000; 1397230130Smav struct hdac_stream *s; 1398182999Smav 1399230130Smav if (sc->polling == 0) 1400230130Smav return; 1401230130Smav if (sc->unsol_registered > 0) 1402230130Smav min = hz / 2; 1403230130Smav for (i = 0; i < sc->num_ss; i++) { 1404230130Smav s = &sc->streams[i]; 1405230130Smav if (s->running == 0) 1406182999Smav continue; 1407230130Smav pollticks = ((uint64_t)hz * s->blksz) / 1408230326Smav (hdac_mdata_rate(s->format) / 8); 1409230130Smav pollticks >>= 1; 1410230130Smav if (pollticks > hz) 1411230130Smav pollticks = hz; 1412359485Skib if (pollticks < 1) 1413230130Smav pollticks = 1; 1414230130Smav if (min > pollticks) 1415230130Smav min = pollticks; 1416162922Sariff } 1417230130Smav sc->poll_ival = min; 1418230130Smav if (min == 1000000) 1419230130Smav callout_stop(&sc->poll_callout); 1420182999Smav else 1421230130Smav callout_reset(&sc->poll_callout, 1, hdac_poll_callback, sc); 1422163057Sariff} 1423163057Sariff 1424164614Sariffstatic int 1425164614Sariffsysctl_hdac_polling(SYSCTL_HANDLER_ARGS) 1426164614Sariff{ 1427164614Sariff struct hdac_softc *sc; 1428164614Sariff device_t dev; 1429164614Sariff uint32_t ctl; 1430164614Sariff int err, val; 1431164614Sariff 1432164614Sariff dev = oidp->oid_arg1; 1433182999Smav sc = device_get_softc(dev); 1434182999Smav if (sc == NULL) 1435164614Sariff return (EINVAL); 1436164614Sariff hdac_lock(sc); 1437164614Sariff val = sc->polling; 1438164614Sariff hdac_unlock(sc); 1439170289Sdwmalone err = sysctl_handle_int(oidp, &val, 0, req); 1440164614Sariff 1441169277Sariff if (err != 0 || req->newptr == NULL) 1442164614Sariff return (err); 1443164614Sariff if (val < 0 || val > 1) 1444164614Sariff return (EINVAL); 1445164614Sariff 1446164614Sariff hdac_lock(sc); 1447164614Sariff if (val != sc->polling) { 1448182999Smav if (val == 0) { 1449230130Smav callout_stop(&sc->poll_callout); 1450169277Sariff hdac_unlock(sc); 1451230130Smav callout_drain(&sc->poll_callout); 1452169277Sariff hdac_lock(sc); 1453164614Sariff sc->polling = 0; 1454182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1455182999Smav ctl |= HDAC_INTCTL_GIE; 1456182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1457164614Sariff } else { 1458182999Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1459182999Smav ctl &= ~HDAC_INTCTL_GIE; 1460182999Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1461164614Sariff sc->polling = 1; 1462182999Smav hdac_poll_reinit(sc); 1463164614Sariff } 1464164614Sariff } 1465164614Sariff hdac_unlock(sc); 1466164614Sariff 1467164614Sariff return (err); 1468164614Sariff} 1469169277Sariff 1470163057Sariffstatic void 1471162922Sariffhdac_attach2(void *arg) 1472162922Sariff{ 1473162922Sariff struct hdac_softc *sc; 1474230130Smav device_t child; 1475230130Smav uint32_t vendorid, revisionid; 1476230130Smav int i; 1477230130Smav uint16_t statests; 1478162922Sariff 1479162922Sariff sc = (struct hdac_softc *)arg; 1480162922Sariff 1481162922Sariff hdac_lock(sc); 1482162922Sariff 1483162922Sariff /* Remove ourselves from the config hooks */ 1484162922Sariff if (sc->intrhook.ich_func != NULL) { 1485162922Sariff config_intrhook_disestablish(&sc->intrhook); 1486162922Sariff sc->intrhook.ich_func = NULL; 1487162922Sariff } 1488162922Sariff 1489183097Smav HDA_BOOTHVERBOSE( 1490182999Smav device_printf(sc->dev, "Starting CORB Engine...\n"); 1491162922Sariff ); 1492162922Sariff hdac_corb_start(sc); 1493183097Smav HDA_BOOTHVERBOSE( 1494182999Smav device_printf(sc->dev, "Starting RIRB Engine...\n"); 1495162922Sariff ); 1496162922Sariff hdac_rirb_start(sc); 1497183097Smav HDA_BOOTHVERBOSE( 1498162922Sariff device_printf(sc->dev, 1499182999Smav "Enabling controller interrupt...\n"); 1500162922Sariff ); 1501182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1502182999Smav HDAC_GCTL_UNSOL); 1503182999Smav if (sc->polling == 0) { 1504164614Sariff HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 1505164614Sariff HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1506182999Smav } 1507162922Sariff DELAY(1000); 1508162922Sariff 1509183097Smav HDA_BOOTHVERBOSE( 1510230130Smav device_printf(sc->dev, "Scanning HDA codecs ...\n"); 1511162922Sariff ); 1512230130Smav statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS); 1513230130Smav hdac_unlock(sc); 1514230130Smav for (i = 0; i < HDAC_CODEC_MAX; i++) { 1515230130Smav if (HDAC_STATESTS_SDIWAKE(statests, i)) { 1516230130Smav HDA_BOOTHVERBOSE( 1517183097Smav device_printf(sc->dev, 1518230130Smav "Found CODEC at address %d\n", i); 1519183019Smav ); 1520230130Smav hdac_lock(sc); 1521230130Smav vendorid = hdac_send_command(sc, i, 1522230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_VENDOR_ID)); 1523230130Smav revisionid = hdac_send_command(sc, i, 1524230130Smav HDA_CMD_GET_PARAMETER(0, 0x0, HDA_PARAM_REVISION_ID)); 1525230130Smav hdac_unlock(sc); 1526230130Smav if (vendorid == HDA_INVALID && 1527230130Smav revisionid == HDA_INVALID) { 1528230130Smav device_printf(sc->dev, 1529230130Smav "CODEC is not responding!\n"); 1530182999Smav continue; 1531182999Smav } 1532230130Smav sc->codecs[i].vendor_id = 1533230130Smav HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid); 1534230130Smav sc->codecs[i].device_id = 1535230130Smav HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid); 1536230130Smav sc->codecs[i].revision_id = 1537230130Smav HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); 1538230130Smav sc->codecs[i].stepping_id = 1539230130Smav HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); 1540230130Smav child = device_add_child(sc->dev, "hdacc", -1); 1541230130Smav if (child == NULL) { 1542230130Smav device_printf(sc->dev, 1543230130Smav "Failed to add CODEC device\n"); 1544230130Smav continue; 1545182999Smav } 1546230130Smav device_set_ivars(child, (void *)(intptr_t)i); 1547230130Smav sc->codecs[i].dev = child; 1548182999Smav } 1549162922Sariff } 1550182999Smav bus_generic_attach(sc->dev); 1551182999Smav 1552182999Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1553182999Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1554230130Smav "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1555230130Smav sysctl_hdac_pindump, "I", "Dump pin states/data"); 1556230130Smav SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev), 1557230130Smav SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, 1558182999Smav "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), 1559182999Smav sysctl_hdac_polling, "I", "Enable polling mode"); 1560182999Smav} 1561182999Smav 1562182999Smav/**************************************************************************** 1563182999Smav * int hdac_suspend(device_t) 1564182999Smav * 1565182999Smav * Suspend and power down HDA bus and codecs. 1566182999Smav ****************************************************************************/ 1567182999Smavstatic int 1568182999Smavhdac_suspend(device_t dev) 1569182999Smav{ 1570230130Smav struct hdac_softc *sc = device_get_softc(dev); 1571182999Smav 1572183097Smav HDA_BOOTHVERBOSE( 1573182999Smav device_printf(dev, "Suspend...\n"); 1574162922Sariff ); 1575230130Smav bus_generic_suspend(dev); 1576182999Smav 1577182999Smav hdac_lock(sc); 1578183097Smav HDA_BOOTHVERBOSE( 1579182999Smav device_printf(dev, "Reset controller...\n"); 1580162922Sariff ); 1581233606Smav callout_stop(&sc->poll_callout); 1582182999Smav hdac_reset(sc, 0); 1583182999Smav hdac_unlock(sc); 1584233606Smav callout_drain(&sc->poll_callout); 1585182999Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1586183097Smav HDA_BOOTHVERBOSE( 1587182999Smav device_printf(dev, "Suspend done\n"); 1588162922Sariff ); 1589182999Smav return (0); 1590182999Smav} 1591182999Smav 1592182999Smav/**************************************************************************** 1593182999Smav * int hdac_resume(device_t) 1594182999Smav * 1595182999Smav * Powerup and restore HDA bus and codecs state. 1596182999Smav ****************************************************************************/ 1597182999Smavstatic int 1598182999Smavhdac_resume(device_t dev) 1599182999Smav{ 1600230130Smav struct hdac_softc *sc = device_get_softc(dev); 1601230130Smav int error; 1602182999Smav 1603183097Smav HDA_BOOTHVERBOSE( 1604182999Smav device_printf(dev, "Resume...\n"); 1605162922Sariff ); 1606182999Smav hdac_lock(sc); 1607182999Smav 1608182999Smav /* Quiesce everything */ 1609183097Smav HDA_BOOTHVERBOSE( 1610182999Smav device_printf(dev, "Reset controller...\n"); 1611162922Sariff ); 1612182999Smav hdac_reset(sc, 1); 1613182999Smav 1614182999Smav /* Initialize the CORB and RIRB */ 1615182999Smav hdac_corb_init(sc); 1616182999Smav hdac_rirb_init(sc); 1617182999Smav 1618183097Smav HDA_BOOTHVERBOSE( 1619182999Smav device_printf(dev, "Starting CORB Engine...\n"); 1620162922Sariff ); 1621182999Smav hdac_corb_start(sc); 1622183097Smav HDA_BOOTHVERBOSE( 1623182999Smav device_printf(dev, "Starting RIRB Engine...\n"); 1624162922Sariff ); 1625182999Smav hdac_rirb_start(sc); 1626183097Smav HDA_BOOTHVERBOSE( 1627230130Smav device_printf(dev, "Enabling controller interrupt...\n"); 1628162922Sariff ); 1629182999Smav HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) | 1630182999Smav HDAC_GCTL_UNSOL); 1631230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE); 1632182999Smav DELAY(1000); 1633233606Smav hdac_poll_reinit(sc); 1634182999Smav hdac_unlock(sc); 1635182999Smav 1636230130Smav error = bus_generic_resume(dev); 1637183097Smav HDA_BOOTHVERBOSE( 1638182999Smav device_printf(dev, "Resume done\n"); 1639162922Sariff ); 1640230130Smav return (error); 1641230130Smav} 1642164614Sariff 1643162922Sariff/**************************************************************************** 1644162922Sariff * int hdac_detach(device_t) 1645162922Sariff * 1646162922Sariff * Detach and free up resources utilized by the hdac device. 1647162922Sariff ****************************************************************************/ 1648162922Sariffstatic int 1649162922Sariffhdac_detach(device_t dev) 1650162922Sariff{ 1651230130Smav struct hdac_softc *sc = device_get_softc(dev); 1652185177Smav device_t *devlist; 1653230130Smav int cad, i, devcount, error; 1654162922Sariff 1655185177Smav if ((error = device_get_children(dev, &devlist, &devcount)) != 0) 1656185177Smav return (error); 1657185177Smav for (i = 0; i < devcount; i++) { 1658230130Smav cad = (intptr_t)device_get_ivars(devlist[i]); 1659185177Smav if ((error = device_delete_child(dev, devlist[i])) != 0) { 1660185178Smav free(devlist, M_TEMP); 1661185178Smav return (error); 1662185178Smav } 1663230130Smav sc->codecs[cad].dev = NULL; 1664185177Smav } 1665185177Smav free(devlist, M_TEMP); 1666185177Smav 1667230130Smav hdac_lock(sc); 1668230130Smav hdac_reset(sc, 0); 1669230130Smav hdac_unlock(sc); 1670230130Smav taskqueue_drain(taskqueue_thread, &sc->unsolq_task); 1671230130Smav hdac_irq_free(sc); 1672162922Sariff 1673230130Smav for (i = 0; i < sc->num_ss; i++) 1674230130Smav hdac_dma_free(sc, &sc->streams[i].bdl); 1675230130Smav free(sc->streams, M_HDAC); 1676230130Smav hdac_dma_free(sc, &sc->pos_dma); 1677230130Smav hdac_dma_free(sc, &sc->rirb_dma); 1678230130Smav hdac_dma_free(sc, &sc->corb_dma); 1679230130Smav if (sc->chan_dmat != NULL) { 1680230130Smav bus_dma_tag_destroy(sc->chan_dmat); 1681230130Smav sc->chan_dmat = NULL; 1682230130Smav } 1683230130Smav hdac_mem_free(sc); 1684230130Smav snd_mtxfree(sc->lock); 1685162922Sariff return (0); 1686162922Sariff} 1687162922Sariff 1688230130Smavstatic bus_dma_tag_t 1689230130Smavhdac_get_dma_tag(device_t dev, device_t child) 1690230130Smav{ 1691230130Smav struct hdac_softc *sc = device_get_softc(dev); 1692230130Smav 1693230130Smav return (sc->chan_dmat); 1694230130Smav} 1695230130Smav 1696184095Smavstatic int 1697184095Smavhdac_print_child(device_t dev, device_t child) 1698184095Smav{ 1699184095Smav int retval; 1700184095Smav 1701184095Smav retval = bus_print_child_header(dev, child); 1702230130Smav retval += printf(" at cad %d", 1703230130Smav (int)(intptr_t)device_get_ivars(child)); 1704184095Smav retval += bus_print_child_footer(dev, child); 1705184095Smav 1706184095Smav return (retval); 1707184095Smav} 1708184095Smav 1709230130Smavstatic int 1710230130Smavhdac_child_location_str(device_t dev, device_t child, char *buf, 1711230130Smav size_t buflen) 1712230130Smav{ 1713162922Sariff 1714230130Smav snprintf(buf, buflen, "cad=%d", 1715230130Smav (int)(intptr_t)device_get_ivars(child)); 1716230130Smav return (0); 1717230130Smav} 1718162922Sariff 1719230130Smavstatic int 1720230130Smavhdac_child_pnpinfo_str_method(device_t dev, device_t child, char *buf, 1721230130Smav size_t buflen) 1722230130Smav{ 1723230130Smav struct hdac_softc *sc = device_get_softc(dev); 1724230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1725182999Smav 1726230130Smav snprintf(buf, buflen, "vendor=0x%04x device=0x%04x revision=0x%02x " 1727230130Smav "stepping=0x%02x", 1728230130Smav sc->codecs[cad].vendor_id, sc->codecs[cad].device_id, 1729230130Smav sc->codecs[cad].revision_id, sc->codecs[cad].stepping_id); 1730230130Smav return (0); 1731230130Smav} 1732182999Smav 1733182999Smavstatic int 1734230130Smavhdac_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1735182999Smav{ 1736230130Smav struct hdac_softc *sc = device_get_softc(dev); 1737230130Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1738182999Smav 1739230130Smav switch (which) { 1740230130Smav case HDA_IVAR_CODEC_ID: 1741230130Smav *result = cad; 1742230130Smav break; 1743230130Smav case HDA_IVAR_VENDOR_ID: 1744230130Smav *result = sc->codecs[cad].vendor_id; 1745230130Smav break; 1746230130Smav case HDA_IVAR_DEVICE_ID: 1747230130Smav *result = sc->codecs[cad].device_id; 1748230130Smav break; 1749230130Smav case HDA_IVAR_REVISION_ID: 1750230130Smav *result = sc->codecs[cad].revision_id; 1751230130Smav break; 1752230130Smav case HDA_IVAR_STEPPING_ID: 1753230130Smav *result = sc->codecs[cad].stepping_id; 1754230130Smav break; 1755230130Smav case HDA_IVAR_SUBVENDOR_ID: 1756230130Smav *result = pci_get_subvendor(dev); 1757230130Smav break; 1758230130Smav case HDA_IVAR_SUBDEVICE_ID: 1759230130Smav *result = pci_get_subdevice(dev); 1760230130Smav break; 1761230130Smav case HDA_IVAR_DMA_NOCACHE: 1762230130Smav *result = (sc->flags & HDAC_F_DMA_NOCACHE) != 0; 1763230130Smav break; 1764317010Smmel case HDA_IVAR_STRIPES_MASK: 1765317010Smmel *result = (1 << (1 << sc->num_sdo)) - 1; 1766317010Smmel break; 1767230130Smav default: 1768230130Smav return (ENOENT); 1769230130Smav } 1770182999Smav return (0); 1771182999Smav} 1772182999Smav 1773230130Smavstatic struct mtx * 1774230130Smavhdac_get_mtx(device_t dev, device_t child) 1775182999Smav{ 1776230130Smav struct hdac_softc *sc = device_get_softc(dev); 1777182999Smav 1778230130Smav return (sc->lock); 1779230130Smav} 1780182999Smav 1781230130Smavstatic uint32_t 1782230130Smavhdac_codec_command(device_t dev, device_t child, uint32_t verb) 1783230130Smav{ 1784182999Smav 1785230130Smav return (hdac_send_command(device_get_softc(dev), 1786230130Smav (intptr_t)device_get_ivars(child), verb)); 1787230130Smav} 1788182999Smav 1789230130Smavstatic int 1790230130Smavhdac_find_stream(struct hdac_softc *sc, int dir, int stream) 1791230130Smav{ 1792230130Smav int i, ss; 1793182999Smav 1794230130Smav ss = -1; 1795327170Smav /* Allocate ISS/OSS first. */ 1796230130Smav if (dir == 0) { 1797230130Smav for (i = 0; i < sc->num_iss; i++) { 1798230130Smav if (sc->streams[i].stream == stream) { 1799230130Smav ss = i; 1800230130Smav break; 1801230130Smav } 1802230130Smav } 1803230130Smav } else { 1804230130Smav for (i = 0; i < sc->num_oss; i++) { 1805230130Smav if (sc->streams[i + sc->num_iss].stream == stream) { 1806230130Smav ss = i + sc->num_iss; 1807230130Smav break; 1808230130Smav } 1809230130Smav } 1810230130Smav } 1811230130Smav /* Fallback to BSS. */ 1812230130Smav if (ss == -1) { 1813230130Smav for (i = 0; i < sc->num_bss; i++) { 1814230130Smav if (sc->streams[i + sc->num_iss + sc->num_oss].stream 1815230130Smav == stream) { 1816230130Smav ss = i + sc->num_iss + sc->num_oss; 1817230130Smav break; 1818230130Smav } 1819230130Smav } 1820230130Smav } 1821230130Smav return (ss); 1822230130Smav} 1823182999Smav 1824230130Smavstatic int 1825230326Smavhdac_stream_alloc(device_t dev, device_t child, int dir, int format, int stripe, 1826230130Smav uint32_t **dmapos) 1827230130Smav{ 1828230130Smav struct hdac_softc *sc = device_get_softc(dev); 1829230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1830230326Smav int stream, ss, bw, maxbw, prevbw; 1831182999Smav 1832230130Smav /* Look for empty stream. */ 1833230130Smav ss = hdac_find_stream(sc, dir, 0); 1834182999Smav 1835230130Smav /* Return if found nothing. */ 1836230130Smav if (ss < 0) 1837230130Smav return (0); 1838182999Smav 1839230326Smav /* Check bus bandwidth. */ 1840230326Smav bw = hdac_bdata_rate(format, dir); 1841230326Smav if (dir == 1) { 1842230326Smav bw *= 1 << (sc->num_sdo - stripe); 1843230326Smav prevbw = sc->sdo_bw_used; 1844230326Smav maxbw = 48000 * 960 * (1 << sc->num_sdo); 1845230326Smav } else { 1846230326Smav prevbw = sc->codecs[cad].sdi_bw_used; 1847230326Smav maxbw = 48000 * 464; 1848230326Smav } 1849230326Smav HDA_BOOTHVERBOSE( 1850230326Smav device_printf(dev, "%dKbps of %dKbps bandwidth used%s\n", 1851230326Smav (bw + prevbw) / 1000, maxbw / 1000, 1852230326Smav bw + prevbw > maxbw ? " -- OVERFLOW!" : ""); 1853230326Smav ); 1854230326Smav if (bw + prevbw > maxbw) 1855230326Smav return (0); 1856230326Smav if (dir == 1) 1857230326Smav sc->sdo_bw_used += bw; 1858230326Smav else 1859230326Smav sc->codecs[cad].sdi_bw_used += bw; 1860230326Smav 1861230130Smav /* Allocate stream number */ 1862230130Smav if (ss >= sc->num_iss + sc->num_oss) 1863327170Smav stream = 15 - (ss - sc->num_iss - sc->num_oss); 1864230130Smav else if (ss >= sc->num_iss) 1865230130Smav stream = ss - sc->num_iss + 1; 1866230130Smav else 1867230130Smav stream = ss + 1; 1868182999Smav 1869230130Smav sc->streams[ss].dev = child; 1870230130Smav sc->streams[ss].dir = dir; 1871230130Smav sc->streams[ss].stream = stream; 1872230326Smav sc->streams[ss].bw = bw; 1873230130Smav sc->streams[ss].format = format; 1874230326Smav sc->streams[ss].stripe = stripe; 1875230130Smav if (dmapos != NULL) { 1876230130Smav if (sc->pos_dma.dma_vaddr != NULL) 1877230130Smav *dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8); 1878230130Smav else 1879230130Smav *dmapos = NULL; 1880230130Smav } 1881230130Smav return (stream); 1882182999Smav} 1883182999Smav 1884230130Smavstatic void 1885230130Smavhdac_stream_free(device_t dev, device_t child, int dir, int stream) 1886230130Smav{ 1887230130Smav struct hdac_softc *sc = device_get_softc(dev); 1888230326Smav nid_t cad = (uintptr_t)device_get_ivars(child); 1889230130Smav int ss; 1890230130Smav 1891230130Smav ss = hdac_find_stream(sc, dir, stream); 1892230130Smav KASSERT(ss >= 0, 1893230130Smav ("Free for not allocated stream (%d/%d)\n", dir, stream)); 1894230326Smav if (dir == 1) 1895230326Smav sc->sdo_bw_used -= sc->streams[ss].bw; 1896230326Smav else 1897230326Smav sc->codecs[cad].sdi_bw_used -= sc->streams[ss].bw; 1898230130Smav sc->streams[ss].stream = 0; 1899230130Smav sc->streams[ss].dev = NULL; 1900230130Smav} 1901230130Smav 1902182999Smavstatic int 1903230130Smavhdac_stream_start(device_t dev, device_t child, 1904230130Smav int dir, int stream, bus_addr_t buf, int blksz, int blkcnt) 1905182999Smav{ 1906230130Smav struct hdac_softc *sc = device_get_softc(dev); 1907230130Smav struct hdac_bdle *bdle; 1908230130Smav uint64_t addr; 1909230130Smav int i, ss, off; 1910230130Smav uint32_t ctl; 1911182999Smav 1912230130Smav ss = hdac_find_stream(sc, dir, stream); 1913230130Smav KASSERT(ss >= 0, 1914230130Smav ("Start for not allocated stream (%d/%d)\n", dir, stream)); 1915230130Smav 1916230130Smav addr = (uint64_t)buf; 1917230130Smav bdle = (struct hdac_bdle *)sc->streams[ss].bdl.dma_vaddr; 1918230130Smav for (i = 0; i < blkcnt; i++, bdle++) { 1919230130Smav bdle->addrl = (uint32_t)addr; 1920230130Smav bdle->addrh = (uint32_t)(addr >> 32); 1921230130Smav bdle->len = blksz; 1922230130Smav bdle->ioc = 1; 1923230130Smav addr += blksz; 1924182999Smav } 1925182999Smav 1926230130Smav off = ss << 5; 1927230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDCBL, blksz * blkcnt); 1928230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDLVI, blkcnt - 1); 1929230130Smav addr = sc->streams[ss].bdl.dma_paddr; 1930230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPL, (uint32_t)addr); 1931230130Smav HDAC_WRITE_4(&sc->mem, off + HDAC_SDBDPU, (uint32_t)(addr >> 32)); 1932230130Smav 1933230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL2); 1934230130Smav if (dir) 1935230130Smav ctl |= HDAC_SDCTL2_DIR; 1936230130Smav else 1937230130Smav ctl &= ~HDAC_SDCTL2_DIR; 1938230130Smav ctl &= ~HDAC_SDCTL2_STRM_MASK; 1939230130Smav ctl |= stream << HDAC_SDCTL2_STRM_SHIFT; 1940230326Smav ctl &= ~HDAC_SDCTL2_STRIPE_MASK; 1941230326Smav ctl |= sc->streams[ss].stripe << HDAC_SDCTL2_STRIPE_SHIFT; 1942230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl); 1943230130Smav 1944230130Smav HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format); 1945230130Smav 1946230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1947230130Smav ctl |= 1 << ss; 1948230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1949230130Smav 1950230807Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDSTS, 1951230807Smav HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS); 1952230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1953230130Smav ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1954230130Smav HDAC_SDCTL_RUN; 1955230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1956230130Smav 1957230130Smav sc->streams[ss].blksz = blksz; 1958230130Smav sc->streams[ss].running = 1; 1959230130Smav hdac_poll_reinit(sc); 1960182999Smav return (0); 1961182999Smav} 1962182999Smav 1963230130Smavstatic void 1964230130Smavhdac_stream_stop(device_t dev, device_t child, int dir, int stream) 1965230130Smav{ 1966230130Smav struct hdac_softc *sc = device_get_softc(dev); 1967230130Smav int ss, off; 1968230130Smav uint32_t ctl; 1969230130Smav 1970230130Smav ss = hdac_find_stream(sc, dir, stream); 1971230130Smav KASSERT(ss >= 0, 1972230130Smav ("Stop for not allocated stream (%d/%d)\n", dir, stream)); 1973230130Smav 1974230130Smav off = ss << 5; 1975230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 1976230130Smav ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE | 1977230130Smav HDAC_SDCTL_RUN); 1978230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 1979230130Smav 1980230130Smav ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL); 1981230130Smav ctl &= ~(1 << ss); 1982230130Smav HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl); 1983230130Smav 1984230130Smav sc->streams[ss].running = 0; 1985230130Smav hdac_poll_reinit(sc); 1986230130Smav} 1987230130Smav 1988230130Smavstatic void 1989230130Smavhdac_stream_reset(device_t dev, device_t child, int dir, int stream) 1990230130Smav{ 1991230130Smav struct hdac_softc *sc = device_get_softc(dev); 1992230130Smav int timeout = 1000; 1993230130Smav int to = timeout; 1994230130Smav int ss, off; 1995230130Smav uint32_t ctl; 1996230130Smav 1997230130Smav ss = hdac_find_stream(sc, dir, stream); 1998230130Smav KASSERT(ss >= 0, 1999230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 2000230130Smav 2001230130Smav off = ss << 5; 2002230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2003230130Smav ctl |= HDAC_SDCTL_SRST; 2004230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 2005230130Smav do { 2006230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2007230130Smav if (ctl & HDAC_SDCTL_SRST) 2008230130Smav break; 2009230130Smav DELAY(10); 2010230130Smav } while (--to); 2011230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2012230130Smav device_printf(dev, "Reset setting timeout\n"); 2013230130Smav ctl &= ~HDAC_SDCTL_SRST; 2014230130Smav HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL0, ctl); 2015230130Smav to = timeout; 2016230130Smav do { 2017230130Smav ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0); 2018230130Smav if (!(ctl & HDAC_SDCTL_SRST)) 2019230130Smav break; 2020230130Smav DELAY(10); 2021230130Smav } while (--to); 2022230130Smav if (ctl & HDAC_SDCTL_SRST) 2023230130Smav device_printf(dev, "Reset timeout!\n"); 2024230130Smav} 2025230130Smav 2026230130Smavstatic uint32_t 2027230130Smavhdac_stream_getptr(device_t dev, device_t child, int dir, int stream) 2028230130Smav{ 2029230130Smav struct hdac_softc *sc = device_get_softc(dev); 2030230130Smav int ss, off; 2031230130Smav 2032230130Smav ss = hdac_find_stream(sc, dir, stream); 2033230130Smav KASSERT(ss >= 0, 2034230130Smav ("Reset for not allocated stream (%d/%d)\n", dir, stream)); 2035230130Smav 2036230130Smav off = ss << 5; 2037230130Smav return (HDAC_READ_4(&sc->mem, off + HDAC_SDLPIB)); 2038230130Smav} 2039230130Smav 2040230130Smavstatic int 2041230130Smavhdac_unsol_alloc(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 return (tag); 2048230130Smav} 2049230130Smav 2050230130Smavstatic void 2051230130Smavhdac_unsol_free(device_t dev, device_t child, int tag) 2052230130Smav{ 2053230130Smav struct hdac_softc *sc = device_get_softc(dev); 2054230130Smav 2055230130Smav sc->unsol_registered--; 2056230130Smav hdac_poll_reinit(sc); 2057230130Smav} 2058230130Smav 2059230130Smavstatic device_method_t hdac_methods[] = { 2060182999Smav /* device interface */ 2061230130Smav DEVMETHOD(device_probe, hdac_probe), 2062230130Smav DEVMETHOD(device_attach, hdac_attach), 2063230130Smav DEVMETHOD(device_detach, hdac_detach), 2064230130Smav DEVMETHOD(device_suspend, hdac_suspend), 2065230130Smav DEVMETHOD(device_resume, hdac_resume), 2066230130Smav /* Bus interface */ 2067230130Smav DEVMETHOD(bus_get_dma_tag, hdac_get_dma_tag), 2068230130Smav DEVMETHOD(bus_print_child, hdac_print_child), 2069230130Smav DEVMETHOD(bus_child_location_str, hdac_child_location_str), 2070230130Smav DEVMETHOD(bus_child_pnpinfo_str, hdac_child_pnpinfo_str_method), 2071230130Smav DEVMETHOD(bus_read_ivar, hdac_read_ivar), 2072230130Smav DEVMETHOD(hdac_get_mtx, hdac_get_mtx), 2073230130Smav DEVMETHOD(hdac_codec_command, hdac_codec_command), 2074230130Smav DEVMETHOD(hdac_stream_alloc, hdac_stream_alloc), 2075230130Smav DEVMETHOD(hdac_stream_free, hdac_stream_free), 2076230130Smav DEVMETHOD(hdac_stream_start, hdac_stream_start), 2077230130Smav DEVMETHOD(hdac_stream_stop, hdac_stream_stop), 2078230130Smav DEVMETHOD(hdac_stream_reset, hdac_stream_reset), 2079230130Smav DEVMETHOD(hdac_stream_getptr, hdac_stream_getptr), 2080230130Smav DEVMETHOD(hdac_unsol_alloc, hdac_unsol_alloc), 2081230130Smav DEVMETHOD(hdac_unsol_free, hdac_unsol_free), 2082264832Smarius DEVMETHOD_END 2083182999Smav}; 2084182999Smav 2085230130Smavstatic driver_t hdac_driver = { 2086230130Smav "hdac", 2087230130Smav hdac_methods, 2088230130Smav sizeof(struct hdac_softc), 2089182999Smav}; 2090182999Smav 2091230130Smavstatic devclass_t hdac_devclass; 2092182999Smav 2093264832SmariusDRIVER_MODULE(snd_hda, pci, hdac_driver, hdac_devclass, NULL, NULL); 2094