1 1.18 andvar /* $NetBSD: hdaudio.c,v 1.18 2022/04/07 19:33:37 andvar Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /* 4 1.1 jmcneill * Copyright (c) 2009 Precedence Technologies Ltd <support (at) precedence.co.uk> 5 1.1 jmcneill * Copyright (c) 2009 Jared D. McNeill <jmcneill (at) invisible.ca> 6 1.1 jmcneill * All rights reserved. 7 1.1 jmcneill * 8 1.1 jmcneill * This code is derived from software contributed to The NetBSD Foundation 9 1.1 jmcneill * by Precedence Technologies Ltd 10 1.1 jmcneill * 11 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 12 1.1 jmcneill * modification, are permitted provided that the following conditions 13 1.1 jmcneill * are met: 14 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 15 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 16 1.1 jmcneill * 2. The name of the author may not be used to endorse or promote products 17 1.1 jmcneill * derived from this software without specific prior written permission. 18 1.1 jmcneill * 19 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 1.1 jmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 1.1 jmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 1.1 jmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 1.1 jmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 jmcneill * SUCH DAMAGE. 30 1.1 jmcneill */ 31 1.1 jmcneill 32 1.1 jmcneill #include <sys/cdefs.h> 33 1.18 andvar __KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.18 2022/04/07 19:33:37 andvar Exp $"); 34 1.1 jmcneill 35 1.1 jmcneill #include <sys/types.h> 36 1.1 jmcneill #include <sys/param.h> 37 1.1 jmcneill #include <sys/systm.h> 38 1.1 jmcneill #include <sys/device.h> 39 1.1 jmcneill #include <sys/conf.h> 40 1.1 jmcneill #include <sys/bus.h> 41 1.1 jmcneill #include <sys/kmem.h> 42 1.1 jmcneill #include <sys/module.h> 43 1.1 jmcneill 44 1.1 jmcneill #include "hdaudiovar.h" 45 1.1 jmcneill #include "hdaudioreg.h" 46 1.1 jmcneill #include "hdaudioio.h" 47 1.1 jmcneill #include "hdaudio_verbose.h" 48 1.15 pgoyette #include "hdaudiodevs.h" 49 1.1 jmcneill 50 1.1 jmcneill /* #define HDAUDIO_DEBUG */ 51 1.1 jmcneill 52 1.1 jmcneill #define HDAUDIO_RESET_TIMEOUT 5000 53 1.1 jmcneill #define HDAUDIO_CORB_TIMEOUT 1000 54 1.1 jmcneill #define HDAUDIO_RIRB_TIMEOUT 5000 55 1.1 jmcneill 56 1.1 jmcneill #define HDAUDIO_CODEC_DELAY 1000 /* spec calls for 250 */ 57 1.1 jmcneill 58 1.1 jmcneill dev_type_open(hdaudioopen); 59 1.1 jmcneill dev_type_close(hdaudioclose); 60 1.1 jmcneill dev_type_ioctl(hdaudioioctl); 61 1.1 jmcneill 62 1.1 jmcneill const struct cdevsw hdaudio_cdevsw = { 63 1.1 jmcneill .d_open = hdaudioopen, 64 1.1 jmcneill .d_close = hdaudioclose, 65 1.1 jmcneill .d_read = noread, 66 1.1 jmcneill .d_write = nowrite, 67 1.1 jmcneill .d_ioctl = hdaudioioctl, 68 1.1 jmcneill .d_stop = nostop, 69 1.1 jmcneill .d_tty = notty, 70 1.1 jmcneill .d_poll = nopoll, 71 1.1 jmcneill .d_mmap = nommap, 72 1.1 jmcneill .d_kqfilter = nokqfilter, 73 1.1 jmcneill .d_discard = nodiscard, 74 1.1 jmcneill .d_flag = D_OTHER 75 1.1 jmcneill }; 76 1.1 jmcneill 77 1.1 jmcneill extern struct cfdriver hdaudio_cd; 78 1.1 jmcneill 79 1.1 jmcneill #define HDAUDIOUNIT(x) minor((x)) 80 1.1 jmcneill 81 1.1 jmcneill static void 82 1.1 jmcneill hdaudio_stream_init(struct hdaudio_softc *sc, int nis, int nos, int nbidir) 83 1.1 jmcneill { 84 1.1 jmcneill int i, cnt = 0; 85 1.1 jmcneill 86 1.1 jmcneill for (i = 0; i < nis && cnt < HDAUDIO_MAX_STREAMS; i++) { 87 1.1 jmcneill sc->sc_stream[cnt].st_host = sc; 88 1.1 jmcneill sc->sc_stream[cnt].st_enable = true; 89 1.1 jmcneill sc->sc_stream[cnt].st_shift = cnt; 90 1.1 jmcneill sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_ISS; 91 1.1 jmcneill } 92 1.1 jmcneill for (i = 0; i < nos && cnt < HDAUDIO_MAX_STREAMS; i++) { 93 1.1 jmcneill sc->sc_stream[cnt].st_host = sc; 94 1.1 jmcneill sc->sc_stream[cnt].st_enable = true; 95 1.1 jmcneill sc->sc_stream[cnt].st_shift = cnt; 96 1.1 jmcneill sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_OSS; 97 1.1 jmcneill } 98 1.1 jmcneill for (i = 0; i < nbidir && cnt < HDAUDIO_MAX_STREAMS; i++) { 99 1.1 jmcneill sc->sc_stream[cnt].st_host = sc; 100 1.1 jmcneill sc->sc_stream[cnt].st_enable = true; 101 1.1 jmcneill sc->sc_stream[cnt].st_shift = cnt; 102 1.1 jmcneill sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_BSS; 103 1.1 jmcneill } 104 1.1 jmcneill 105 1.1 jmcneill for (i = 0; i < cnt; i++) 106 1.1 jmcneill hdaudio_stream_stop(&sc->sc_stream[i]); 107 1.1 jmcneill 108 1.1 jmcneill sc->sc_stream_mask = 0; 109 1.1 jmcneill } 110 1.1 jmcneill 111 1.1 jmcneill static void 112 1.1 jmcneill hdaudio_codec_init(struct hdaudio_softc *sc) 113 1.1 jmcneill { 114 1.1 jmcneill int i; 115 1.1 jmcneill 116 1.1 jmcneill for (i = 0; i < HDAUDIO_MAX_CODECS; i++) { 117 1.1 jmcneill sc->sc_codec[i].co_addr = i; 118 1.1 jmcneill sc->sc_codec[i].co_host = sc; 119 1.1 jmcneill } 120 1.1 jmcneill } 121 1.1 jmcneill 122 1.1 jmcneill static void 123 1.1 jmcneill hdaudio_init(struct hdaudio_softc *sc) 124 1.1 jmcneill { 125 1.10 jmcneill const uint8_t vmaj = hda_read1(sc, HDAUDIO_MMIO_VMAJ); 126 1.10 jmcneill const uint8_t vmin = hda_read1(sc, HDAUDIO_MMIO_VMIN); 127 1.10 jmcneill const uint16_t gcap = hda_read2(sc, HDAUDIO_MMIO_GCAP); 128 1.10 jmcneill const int nis = HDAUDIO_GCAP_ISS(gcap); 129 1.10 jmcneill const int nos = HDAUDIO_GCAP_OSS(gcap); 130 1.10 jmcneill const int nbidir = HDAUDIO_GCAP_BSS(gcap); 131 1.10 jmcneill const int nsdo = HDAUDIO_GCAP_NSDO(gcap); 132 1.10 jmcneill const int addr64 = HDAUDIO_GCAP_64OK(gcap); 133 1.1 jmcneill 134 1.10 jmcneill hda_print(sc, "HDA ver. %d.%d, OSS %d, ISS %d, BSS %d, SDO %d%s\n", 135 1.10 jmcneill vmaj, vmin, nos, nis, nbidir, nsdo, addr64 ? ", 64-bit" : ""); 136 1.1 jmcneill 137 1.1 jmcneill /* Initialize codecs and streams */ 138 1.1 jmcneill hdaudio_codec_init(sc); 139 1.1 jmcneill hdaudio_stream_init(sc, nis, nos, nbidir); 140 1.1 jmcneill } 141 1.1 jmcneill 142 1.1 jmcneill static int 143 1.1 jmcneill hdaudio_codec_probe(struct hdaudio_softc *sc) 144 1.1 jmcneill { 145 1.1 jmcneill uint16_t statests; 146 1.1 jmcneill int codecid; 147 1.1 jmcneill 148 1.1 jmcneill statests = hda_read2(sc, HDAUDIO_MMIO_STATESTS); 149 1.1 jmcneill for (codecid = 0; codecid < HDAUDIO_MAX_CODECS; codecid++) 150 1.1 jmcneill if (statests & (1 << codecid)) 151 1.1 jmcneill sc->sc_codec[codecid].co_valid = true; 152 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_STATESTS, statests); 153 1.1 jmcneill 154 1.1 jmcneill return statests; 155 1.1 jmcneill } 156 1.1 jmcneill 157 1.1 jmcneill int 158 1.1 jmcneill hdaudio_dma_alloc(struct hdaudio_softc *sc, struct hdaudio_dma *dma, 159 1.1 jmcneill int flags) 160 1.1 jmcneill { 161 1.1 jmcneill int err; 162 1.1 jmcneill 163 1.1 jmcneill KASSERT(dma->dma_size > 0); 164 1.1 jmcneill 165 1.1 jmcneill err = bus_dmamem_alloc(sc->sc_dmat, dma->dma_size, 128, 0, 166 1.1 jmcneill dma->dma_segs, sizeof(dma->dma_segs) / sizeof(dma->dma_segs[0]), 167 1.1 jmcneill &dma->dma_nsegs, BUS_DMA_WAITOK); 168 1.1 jmcneill if (err) 169 1.1 jmcneill return err; 170 1.1 jmcneill err = bus_dmamem_map(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs, 171 1.1 jmcneill dma->dma_size, &dma->dma_addr, BUS_DMA_WAITOK | flags); 172 1.1 jmcneill if (err) 173 1.1 jmcneill goto free; 174 1.1 jmcneill err = bus_dmamap_create(sc->sc_dmat, dma->dma_size, dma->dma_nsegs, 175 1.1 jmcneill dma->dma_size, 0, BUS_DMA_WAITOK, &dma->dma_map); 176 1.1 jmcneill if (err) 177 1.1 jmcneill goto unmap; 178 1.1 jmcneill err = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_addr, 179 1.1 jmcneill dma->dma_size, NULL, BUS_DMA_WAITOK | flags); 180 1.1 jmcneill if (err) 181 1.1 jmcneill goto destroy; 182 1.1 jmcneill 183 1.12 jmcneill memset(dma->dma_addr, 0, dma->dma_size); 184 1.12 jmcneill bus_dmamap_sync(sc->sc_dmat, dma->dma_map, 0, dma->dma_size, 185 1.12 jmcneill BUS_DMASYNC_PREWRITE); 186 1.12 jmcneill 187 1.1 jmcneill dma->dma_valid = true; 188 1.1 jmcneill return 0; 189 1.1 jmcneill 190 1.1 jmcneill destroy: 191 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, dma->dma_map); 192 1.1 jmcneill unmap: 193 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size); 194 1.1 jmcneill free: 195 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs); 196 1.1 jmcneill 197 1.1 jmcneill dma->dma_valid = false; 198 1.1 jmcneill return err; 199 1.1 jmcneill } 200 1.1 jmcneill 201 1.1 jmcneill void 202 1.1 jmcneill hdaudio_dma_free(struct hdaudio_softc *sc, struct hdaudio_dma *dma) 203 1.1 jmcneill { 204 1.1 jmcneill if (dma->dma_valid == false) 205 1.1 jmcneill return; 206 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, dma->dma_map); 207 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, dma->dma_map); 208 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size); 209 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs); 210 1.1 jmcneill dma->dma_valid = false; 211 1.1 jmcneill } 212 1.1 jmcneill 213 1.1 jmcneill static void 214 1.1 jmcneill hdaudio_corb_enqueue(struct hdaudio_softc *sc, int addr, int nid, 215 1.1 jmcneill uint32_t control, uint32_t param) 216 1.1 jmcneill { 217 1.1 jmcneill uint32_t *corb = DMA_KERNADDR(&sc->sc_corb); 218 1.1 jmcneill uint32_t verb; 219 1.1 jmcneill uint16_t corbrp; 220 1.1 jmcneill int wp; 221 1.1 jmcneill 222 1.1 jmcneill /* Build command */ 223 1.1 jmcneill verb = (addr << 28) | (nid << 20) | (control << 8) | param; 224 1.1 jmcneill 225 1.1 jmcneill /* Fetch and update write pointer */ 226 1.1 jmcneill corbrp = hda_read2(sc, HDAUDIO_MMIO_CORBWP); 227 1.1 jmcneill wp = (corbrp & 0xff) + 1; 228 1.1 jmcneill if (wp >= (sc->sc_corb.dma_size / sizeof(*corb))) 229 1.1 jmcneill wp = 0; 230 1.1 jmcneill 231 1.1 jmcneill /* Enqueue command */ 232 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_corb.dma_map, 0, 233 1.1 jmcneill sc->sc_corb.dma_size, BUS_DMASYNC_POSTWRITE); 234 1.1 jmcneill corb[wp] = verb; 235 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_corb.dma_map, 0, 236 1.1 jmcneill sc->sc_corb.dma_size, BUS_DMASYNC_PREWRITE); 237 1.1 jmcneill 238 1.1 jmcneill /* Commit updated write pointer */ 239 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBWP, wp); 240 1.1 jmcneill } 241 1.1 jmcneill 242 1.1 jmcneill static void 243 1.1 jmcneill hdaudio_rirb_unsol(struct hdaudio_softc *sc, struct rirb_entry *entry) 244 1.1 jmcneill { 245 1.1 jmcneill struct hdaudio_codec *co; 246 1.1 jmcneill struct hdaudio_function_group *fg; 247 1.1 jmcneill uint8_t codecid = RIRB_CODEC_ID(entry); 248 1.1 jmcneill unsigned int i; 249 1.1 jmcneill 250 1.1 jmcneill if (codecid >= HDAUDIO_MAX_CODECS) { 251 1.1 jmcneill hda_error(sc, "unsol: codec id 0x%02x out of range\n", codecid); 252 1.1 jmcneill return; 253 1.1 jmcneill } 254 1.1 jmcneill co = &sc->sc_codec[codecid]; 255 1.1 jmcneill if (sc->sc_codec[codecid].co_valid == false) { 256 1.1 jmcneill hda_error(sc, "unsol: codec id 0x%02x not valid\n", codecid); 257 1.1 jmcneill return; 258 1.1 jmcneill } 259 1.1 jmcneill 260 1.1 jmcneill for (i = 0; i < co->co_nfg; i++) { 261 1.1 jmcneill fg = &co->co_fg[i]; 262 1.1 jmcneill if (fg->fg_device && fg->fg_unsol) 263 1.1 jmcneill fg->fg_unsol(fg->fg_device, entry->resp); 264 1.1 jmcneill } 265 1.1 jmcneill } 266 1.1 jmcneill 267 1.1 jmcneill static uint32_t 268 1.1 jmcneill hdaudio_rirb_dequeue(struct hdaudio_softc *sc, bool unsol) 269 1.1 jmcneill { 270 1.1 jmcneill uint16_t rirbwp; 271 1.1 jmcneill uint64_t *rirb = DMA_KERNADDR(&sc->sc_rirb); 272 1.1 jmcneill struct rirb_entry entry; 273 1.1 jmcneill int retry; 274 1.1 jmcneill 275 1.1 jmcneill for (;;) { 276 1.1 jmcneill retry = HDAUDIO_RIRB_TIMEOUT; 277 1.1 jmcneill 278 1.1 jmcneill rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP); 279 1.1 jmcneill while (--retry > 0 && (rirbwp & 0xff) == sc->sc_rirbrp) { 280 1.1 jmcneill if (unsol) { 281 1.1 jmcneill /* don't wait for more unsol events */ 282 1.1 jmcneill hda_trace(sc, "unsol: rirb empty\n"); 283 1.1 jmcneill return 0xffffffff; 284 1.1 jmcneill } 285 1.1 jmcneill hda_delay(10); 286 1.1 jmcneill rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP); 287 1.1 jmcneill } 288 1.1 jmcneill if (retry == 0) { 289 1.1 jmcneill hda_error(sc, "RIRB timeout\n"); 290 1.1 jmcneill return 0xffffffff; 291 1.1 jmcneill } 292 1.1 jmcneill 293 1.1 jmcneill sc->sc_rirbrp++; 294 1.1 jmcneill if (sc->sc_rirbrp >= (sc->sc_rirb.dma_size / sizeof(*rirb))) 295 1.1 jmcneill sc->sc_rirbrp = 0; 296 1.1 jmcneill 297 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_rirb.dma_map, 0, 298 1.1 jmcneill sc->sc_rirb.dma_size, BUS_DMASYNC_POSTREAD); 299 1.1 jmcneill entry = *(struct rirb_entry *)&rirb[sc->sc_rirbrp]; 300 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_rirb.dma_map, 0, 301 1.1 jmcneill sc->sc_rirb.dma_size, BUS_DMASYNC_PREREAD); 302 1.1 jmcneill 303 1.1 jmcneill hda_trace(sc, "%s: response %08X %08X\n", 304 1.1 jmcneill unsol ? "unsol" : "cmd ", 305 1.1 jmcneill entry.resp, entry.resp_ex); 306 1.1 jmcneill 307 1.1 jmcneill if (RIRB_UNSOL(&entry)) { 308 1.1 jmcneill hdaudio_rirb_unsol(sc, &entry); 309 1.1 jmcneill continue; 310 1.1 jmcneill } 311 1.1 jmcneill 312 1.1 jmcneill return entry.resp; 313 1.1 jmcneill } 314 1.1 jmcneill } 315 1.1 jmcneill 316 1.1 jmcneill uint32_t 317 1.1 jmcneill hdaudio_command(struct hdaudio_codec *co, int nid, uint32_t control, 318 1.1 jmcneill uint32_t param) 319 1.1 jmcneill { 320 1.1 jmcneill uint32_t result; 321 1.1 jmcneill struct hdaudio_softc *sc = co->co_host; 322 1.1 jmcneill mutex_enter(&sc->sc_corb_mtx); 323 1.1 jmcneill result = hdaudio_command_unlocked(co, nid, control, param); 324 1.1 jmcneill mutex_exit(&sc->sc_corb_mtx); 325 1.1 jmcneill return result; 326 1.1 jmcneill } 327 1.1 jmcneill 328 1.1 jmcneill uint32_t 329 1.1 jmcneill hdaudio_command_unlocked(struct hdaudio_codec *co, int nid, uint32_t control, 330 1.1 jmcneill uint32_t param) 331 1.1 jmcneill { 332 1.1 jmcneill struct hdaudio_softc *sc = co->co_host; 333 1.1 jmcneill uint32_t result; 334 1.1 jmcneill 335 1.1 jmcneill hda_trace(sc, "cmd : request %08X %08X (%02X)\n", 336 1.1 jmcneill control, param, nid); 337 1.1 jmcneill hdaudio_corb_enqueue(sc, co->co_addr, nid, control, param); 338 1.1 jmcneill result = hdaudio_rirb_dequeue(sc, false); 339 1.1 jmcneill 340 1.8 jmcneill /* Clear response interrupt status */ 341 1.8 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS, hda_read1(sc, HDAUDIO_MMIO_RIRBSTS)); 342 1.8 jmcneill 343 1.1 jmcneill return result; 344 1.1 jmcneill } 345 1.1 jmcneill 346 1.1 jmcneill static int 347 1.1 jmcneill hdaudio_corb_setsize(struct hdaudio_softc *sc) 348 1.1 jmcneill { 349 1.1 jmcneill uint8_t corbsize; 350 1.1 jmcneill bus_size_t bufsize = 0; 351 1.1 jmcneill 352 1.1 jmcneill /* 353 1.1 jmcneill * The size of the CORB is programmable to 2, 16, or 256 entries 354 1.1 jmcneill * by using the CORBSIZE register. Choose a size based on the 355 1.1 jmcneill * controller capabilities, preferring a larger size when possible. 356 1.1 jmcneill */ 357 1.1 jmcneill corbsize = hda_read1(sc, HDAUDIO_MMIO_CORBSIZE); 358 1.1 jmcneill corbsize &= ~0x3; 359 1.1 jmcneill if ((corbsize >> 4) & 0x4) { 360 1.1 jmcneill corbsize |= 0x2; 361 1.1 jmcneill bufsize = 1024; 362 1.1 jmcneill } else if ((corbsize >> 4) & 0x2) { 363 1.1 jmcneill corbsize |= 0x1; 364 1.1 jmcneill bufsize = 64; 365 1.1 jmcneill } else if ((corbsize >> 4) & 0x1) { 366 1.1 jmcneill corbsize |= 0x0; 367 1.1 jmcneill bufsize = 8; 368 1.1 jmcneill } else { 369 1.1 jmcneill hda_error(sc, "couldn't configure CORB size\n"); 370 1.1 jmcneill return ENXIO; 371 1.1 jmcneill } 372 1.1 jmcneill 373 1.1 jmcneill #if defined(HDAUDIO_DEBUG) 374 1.1 jmcneill hda_print(sc, "using %d byte CORB (cap %X)\n", 375 1.1 jmcneill (int)bufsize, corbsize >> 4); 376 1.1 jmcneill #endif 377 1.1 jmcneill 378 1.1 jmcneill sc->sc_corb.dma_size = bufsize; 379 1.1 jmcneill sc->sc_corb.dma_sizereg = corbsize; 380 1.1 jmcneill 381 1.1 jmcneill return 0; 382 1.1 jmcneill } 383 1.1 jmcneill 384 1.1 jmcneill static int 385 1.1 jmcneill hdaudio_corb_config(struct hdaudio_softc *sc) 386 1.1 jmcneill { 387 1.1 jmcneill uint32_t corbubase, corblbase; 388 1.1 jmcneill uint16_t corbrp; 389 1.1 jmcneill int retry = HDAUDIO_CORB_TIMEOUT; 390 1.1 jmcneill 391 1.1 jmcneill /* Program command buffer base address and size */ 392 1.1 jmcneill corblbase = (uint32_t)DMA_DMAADDR(&sc->sc_corb); 393 1.1 jmcneill corbubase = (uint32_t)(((uint64_t)DMA_DMAADDR(&sc->sc_corb)) >> 32); 394 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_CORBLBASE, corblbase); 395 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_CORBUBASE, corbubase); 396 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_CORBSIZE, sc->sc_corb.dma_sizereg); 397 1.1 jmcneill 398 1.1 jmcneill /* Clear the read and write pointers */ 399 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBRP, HDAUDIO_CORBRP_RP_RESET); 400 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBRP, 0); 401 1.1 jmcneill do { 402 1.1 jmcneill hda_delay(10); 403 1.1 jmcneill corbrp = hda_read2(sc, HDAUDIO_MMIO_CORBRP); 404 1.1 jmcneill } while (--retry > 0 && (corbrp & HDAUDIO_CORBRP_RP_RESET) != 0); 405 1.1 jmcneill if (retry == 0) { 406 1.1 jmcneill hda_error(sc, "timeout resetting CORB\n"); 407 1.1 jmcneill return ETIME; 408 1.1 jmcneill } 409 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBWP, 0); 410 1.1 jmcneill 411 1.1 jmcneill return 0; 412 1.1 jmcneill } 413 1.1 jmcneill 414 1.1 jmcneill static int 415 1.1 jmcneill hdaudio_corb_stop(struct hdaudio_softc *sc) 416 1.1 jmcneill { 417 1.1 jmcneill uint8_t corbctl; 418 1.1 jmcneill int retry = HDAUDIO_CORB_TIMEOUT; 419 1.1 jmcneill 420 1.1 jmcneill /* Stop the CORB if necessary */ 421 1.1 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL); 422 1.1 jmcneill if (corbctl & HDAUDIO_CORBCTL_RUN) { 423 1.1 jmcneill corbctl &= ~HDAUDIO_CORBCTL_RUN; 424 1.7 jmcneill hda_write1(sc, HDAUDIO_MMIO_CORBCTL, corbctl); 425 1.1 jmcneill do { 426 1.1 jmcneill hda_delay(10); 427 1.7 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL); 428 1.1 jmcneill } while (--retry > 0 && (corbctl & HDAUDIO_CORBCTL_RUN) != 0); 429 1.1 jmcneill if (retry == 0) { 430 1.1 jmcneill hda_error(sc, "timeout stopping CORB\n"); 431 1.1 jmcneill return ETIME; 432 1.1 jmcneill } 433 1.1 jmcneill } 434 1.1 jmcneill 435 1.1 jmcneill return 0; 436 1.1 jmcneill } 437 1.1 jmcneill 438 1.1 jmcneill static int 439 1.1 jmcneill hdaudio_corb_start(struct hdaudio_softc *sc) 440 1.1 jmcneill { 441 1.1 jmcneill uint8_t corbctl; 442 1.1 jmcneill int retry = HDAUDIO_CORB_TIMEOUT; 443 1.1 jmcneill 444 1.1 jmcneill /* Start the CORB if necessary */ 445 1.1 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL); 446 1.1 jmcneill if ((corbctl & HDAUDIO_CORBCTL_RUN) == 0) { 447 1.1 jmcneill corbctl |= HDAUDIO_CORBCTL_RUN; 448 1.7 jmcneill hda_write1(sc, HDAUDIO_MMIO_CORBCTL, corbctl); 449 1.1 jmcneill do { 450 1.1 jmcneill hda_delay(10); 451 1.7 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL); 452 1.1 jmcneill } while (--retry > 0 && (corbctl & HDAUDIO_CORBCTL_RUN) == 0); 453 1.1 jmcneill if (retry == 0) { 454 1.1 jmcneill hda_error(sc, "timeout starting CORB\n"); 455 1.1 jmcneill return ETIME; 456 1.1 jmcneill } 457 1.1 jmcneill } 458 1.1 jmcneill 459 1.1 jmcneill return 0; 460 1.1 jmcneill } 461 1.1 jmcneill 462 1.1 jmcneill static int 463 1.1 jmcneill hdaudio_rirb_stop(struct hdaudio_softc *sc) 464 1.1 jmcneill { 465 1.1 jmcneill uint8_t rirbctl; 466 1.1 jmcneill int retry = HDAUDIO_RIRB_TIMEOUT; 467 1.1 jmcneill 468 1.1 jmcneill /* Stop the RIRB if necessary */ 469 1.1 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL); 470 1.1 jmcneill if (rirbctl & (HDAUDIO_RIRBCTL_RUN|HDAUDIO_RIRBCTL_ROI_EN)) { 471 1.1 jmcneill rirbctl &= ~HDAUDIO_RIRBCTL_RUN; 472 1.1 jmcneill rirbctl &= ~HDAUDIO_RIRBCTL_ROI_EN; 473 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBCTL, rirbctl); 474 1.1 jmcneill do { 475 1.1 jmcneill hda_delay(10); 476 1.1 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL); 477 1.1 jmcneill } while (--retry > 0 && (rirbctl & HDAUDIO_RIRBCTL_RUN) != 0); 478 1.1 jmcneill if (retry == 0) { 479 1.1 jmcneill hda_error(sc, "timeout stopping RIRB\n"); 480 1.1 jmcneill return ETIME; 481 1.1 jmcneill } 482 1.1 jmcneill } 483 1.1 jmcneill 484 1.1 jmcneill return 0; 485 1.1 jmcneill } 486 1.1 jmcneill 487 1.1 jmcneill static int 488 1.1 jmcneill hdaudio_rirb_start(struct hdaudio_softc *sc) 489 1.1 jmcneill { 490 1.1 jmcneill uint8_t rirbctl; 491 1.1 jmcneill int retry = HDAUDIO_RIRB_TIMEOUT; 492 1.1 jmcneill 493 1.8 jmcneill /* Set the RIRB interrupt count */ 494 1.8 jmcneill hda_write2(sc, HDAUDIO_MMIO_RINTCNT, 1); 495 1.8 jmcneill 496 1.8 jmcneill /* Start the RIRB */ 497 1.1 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL); 498 1.8 jmcneill rirbctl |= HDAUDIO_RIRBCTL_RUN; 499 1.8 jmcneill rirbctl |= HDAUDIO_RIRBCTL_INT_EN; 500 1.8 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBCTL, rirbctl); 501 1.8 jmcneill do { 502 1.8 jmcneill hda_delay(10); 503 1.8 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL); 504 1.8 jmcneill } while (--retry > 0 && (rirbctl & HDAUDIO_RIRBCTL_RUN) == 0); 505 1.8 jmcneill if (retry == 0) { 506 1.8 jmcneill hda_error(sc, "timeout starting RIRB\n"); 507 1.8 jmcneill return ETIME; 508 1.1 jmcneill } 509 1.1 jmcneill 510 1.1 jmcneill return 0; 511 1.1 jmcneill } 512 1.1 jmcneill 513 1.1 jmcneill static int 514 1.1 jmcneill hdaudio_rirb_setsize(struct hdaudio_softc *sc) 515 1.1 jmcneill { 516 1.1 jmcneill uint8_t rirbsize; 517 1.1 jmcneill bus_size_t bufsize = 0; 518 1.1 jmcneill 519 1.1 jmcneill /* 520 1.1 jmcneill * The size of the RIRB is programmable to 2, 16, or 256 entries 521 1.1 jmcneill * by using the RIRBSIZE register. Choose a size based on the 522 1.1 jmcneill * controller capabilities, preferring a larger size when possible. 523 1.1 jmcneill */ 524 1.1 jmcneill rirbsize = hda_read1(sc, HDAUDIO_MMIO_RIRBSIZE); 525 1.1 jmcneill rirbsize &= ~0x3; 526 1.1 jmcneill if ((rirbsize >> 4) & 0x4) { 527 1.1 jmcneill rirbsize |= 0x2; 528 1.1 jmcneill bufsize = 2048; 529 1.1 jmcneill } else if ((rirbsize >> 4) & 0x2) { 530 1.1 jmcneill rirbsize |= 0x1; 531 1.1 jmcneill bufsize = 128; 532 1.1 jmcneill } else if ((rirbsize >> 4) & 0x1) { 533 1.1 jmcneill rirbsize |= 0x0; 534 1.1 jmcneill bufsize = 16; 535 1.1 jmcneill } else { 536 1.1 jmcneill hda_error(sc, "couldn't configure RIRB size\n"); 537 1.1 jmcneill return ENXIO; 538 1.1 jmcneill } 539 1.1 jmcneill 540 1.1 jmcneill #if defined(HDAUDIO_DEBUG) 541 1.1 jmcneill hda_print(sc, "using %d byte RIRB (cap %X)\n", 542 1.1 jmcneill (int)bufsize, rirbsize >> 4); 543 1.1 jmcneill #endif 544 1.1 jmcneill 545 1.1 jmcneill sc->sc_rirb.dma_size = bufsize; 546 1.1 jmcneill sc->sc_rirb.dma_sizereg = rirbsize; 547 1.1 jmcneill 548 1.1 jmcneill return 0; 549 1.1 jmcneill } 550 1.1 jmcneill 551 1.1 jmcneill static int 552 1.1 jmcneill hdaudio_rirb_config(struct hdaudio_softc *sc) 553 1.1 jmcneill { 554 1.1 jmcneill uint32_t rirbubase, rirblbase; 555 1.1 jmcneill 556 1.1 jmcneill /* Program command buffer base address and size */ 557 1.1 jmcneill rirblbase = (uint32_t)DMA_DMAADDR(&sc->sc_rirb); 558 1.1 jmcneill rirbubase = (uint32_t)(((uint64_t)DMA_DMAADDR(&sc->sc_rirb)) >> 32); 559 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_RIRBLBASE, rirblbase); 560 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_RIRBUBASE, rirbubase); 561 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSIZE, sc->sc_rirb.dma_sizereg); 562 1.1 jmcneill 563 1.1 jmcneill /* Clear the write pointer */ 564 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_RIRBWP, HDAUDIO_RIRBWP_WP_RESET); 565 1.1 jmcneill sc->sc_rirbrp = 0; 566 1.1 jmcneill 567 1.1 jmcneill return 0; 568 1.1 jmcneill } 569 1.1 jmcneill 570 1.1 jmcneill static int 571 1.1 jmcneill hdaudio_reset(struct hdaudio_softc *sc) 572 1.1 jmcneill { 573 1.1 jmcneill int retry = HDAUDIO_RESET_TIMEOUT; 574 1.1 jmcneill uint32_t gctl; 575 1.1 jmcneill int err; 576 1.1 jmcneill 577 1.1 jmcneill if ((err = hdaudio_rirb_stop(sc)) != 0) { 578 1.1 jmcneill hda_error(sc, "couldn't reset because RIRB is busy\n"); 579 1.1 jmcneill return err; 580 1.1 jmcneill } 581 1.1 jmcneill if ((err = hdaudio_corb_stop(sc)) != 0) { 582 1.1 jmcneill hda_error(sc, "couldn't reset because CORB is busy\n"); 583 1.1 jmcneill return err; 584 1.1 jmcneill } 585 1.1 jmcneill 586 1.1 jmcneill /* Disable wake events */ 587 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_WAKEEN, 0); 588 1.1 jmcneill 589 1.1 jmcneill /* Disable interrupts */ 590 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, 0); 591 1.1 jmcneill 592 1.1 jmcneill /* Clear state change status register */ 593 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_STATESTS, 594 1.1 jmcneill hda_read2(sc, HDAUDIO_MMIO_STATESTS)); 595 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS, 596 1.1 jmcneill hda_read1(sc, HDAUDIO_MMIO_RIRBSTS)); 597 1.1 jmcneill 598 1.6 jmcneill /* Put the controller into reset state */ 599 1.1 jmcneill gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL); 600 1.6 jmcneill gctl &= ~HDAUDIO_GCTL_CRST; 601 1.6 jmcneill hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl); 602 1.6 jmcneill do { 603 1.6 jmcneill hda_delay(10); 604 1.6 jmcneill gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL); 605 1.6 jmcneill } while (--retry > 0 && (gctl & HDAUDIO_GCTL_CRST) != 0); 606 1.6 jmcneill if (retry == 0) { 607 1.6 jmcneill hda_error(sc, "timeout entering reset state\n"); 608 1.6 jmcneill return ETIME; 609 1.1 jmcneill } 610 1.1 jmcneill 611 1.6 jmcneill hda_delay(1000); 612 1.6 jmcneill 613 1.1 jmcneill /* Now the controller is in reset state, so bring it out */ 614 1.1 jmcneill retry = HDAUDIO_RESET_TIMEOUT; 615 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl | HDAUDIO_GCTL_CRST); 616 1.1 jmcneill do { 617 1.1 jmcneill hda_delay(10); 618 1.1 jmcneill gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL); 619 1.1 jmcneill } while (--retry > 0 && (gctl & HDAUDIO_GCTL_CRST) == 0); 620 1.1 jmcneill if (retry == 0) { 621 1.1 jmcneill hda_error(sc, "timeout leaving reset state\n"); 622 1.1 jmcneill return ETIME; 623 1.1 jmcneill } 624 1.1 jmcneill 625 1.6 jmcneill hda_delay(2000); 626 1.6 jmcneill 627 1.1 jmcneill /* Accept unsolicited responses */ 628 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl | HDAUDIO_GCTL_UNSOL_EN); 629 1.1 jmcneill 630 1.1 jmcneill return 0; 631 1.1 jmcneill } 632 1.1 jmcneill 633 1.1 jmcneill static void 634 1.1 jmcneill hdaudio_intr_enable(struct hdaudio_softc *sc) 635 1.1 jmcneill { 636 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTSTS, 637 1.1 jmcneill hda_read4(sc, HDAUDIO_MMIO_INTSTS)); 638 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, 639 1.1 jmcneill HDAUDIO_INTCTL_GIE | HDAUDIO_INTCTL_CIE); 640 1.1 jmcneill } 641 1.1 jmcneill 642 1.1 jmcneill static void 643 1.1 jmcneill hdaudio_intr_disable(struct hdaudio_softc *sc) 644 1.1 jmcneill { 645 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, 0); 646 1.1 jmcneill } 647 1.1 jmcneill 648 1.1 jmcneill static int 649 1.1 jmcneill hdaudio_config_print(void *opaque, const char *pnp) 650 1.1 jmcneill { 651 1.1 jmcneill prop_dictionary_t dict = opaque; 652 1.1 jmcneill uint8_t fgtype, nid; 653 1.1 jmcneill uint16_t vendor, product; 654 1.1 jmcneill const char *type = "unknown"; 655 1.1 jmcneill 656 1.1 jmcneill prop_dictionary_get_uint8(dict, "function-group-type", &fgtype); 657 1.1 jmcneill prop_dictionary_get_uint8(dict, "node-id", &nid); 658 1.1 jmcneill prop_dictionary_get_uint16(dict, "vendor-id", &vendor); 659 1.1 jmcneill prop_dictionary_get_uint16(dict, "product-id", &product); 660 1.1 jmcneill if (pnp) { 661 1.1 jmcneill if (fgtype == HDAUDIO_GROUP_TYPE_AFG) 662 1.1 jmcneill type = "hdafg"; 663 1.1 jmcneill else if (fgtype == HDAUDIO_GROUP_TYPE_VSM_FG) 664 1.1 jmcneill type = "hdvsmfg"; 665 1.1 jmcneill 666 1.1 jmcneill aprint_normal("%s at %s", type, pnp); 667 1.1 jmcneill } 668 1.1 jmcneill aprint_debug(" vendor 0x%04X product 0x%04X nid 0x%02X", 669 1.1 jmcneill vendor, product, nid); 670 1.1 jmcneill 671 1.1 jmcneill return UNCONF; 672 1.1 jmcneill } 673 1.1 jmcneill 674 1.1 jmcneill static void 675 1.1 jmcneill hdaudio_attach_fg(struct hdaudio_function_group *fg, prop_array_t config) 676 1.1 jmcneill { 677 1.1 jmcneill struct hdaudio_codec *co = fg->fg_codec; 678 1.1 jmcneill struct hdaudio_softc *sc = co->co_host; 679 1.1 jmcneill prop_dictionary_t args = prop_dictionary_create(); 680 1.1 jmcneill uint64_t fgptr = (vaddr_t)fg; 681 1.1 jmcneill int locs[1]; 682 1.1 jmcneill 683 1.1 jmcneill prop_dictionary_set_uint8(args, "function-group-type", fg->fg_type); 684 1.1 jmcneill prop_dictionary_set_uint64(args, "function-group", fgptr); 685 1.1 jmcneill prop_dictionary_set_uint8(args, "node-id", fg->fg_nid); 686 1.1 jmcneill prop_dictionary_set_uint16(args, "vendor-id", fg->fg_vendor); 687 1.1 jmcneill prop_dictionary_set_uint16(args, "product-id", fg->fg_product); 688 1.1 jmcneill if (config) 689 1.1 jmcneill prop_dictionary_set(args, "pin-config", config); 690 1.1 jmcneill 691 1.1 jmcneill locs[0] = fg->fg_nid; 692 1.1 jmcneill 693 1.14 thorpej fg->fg_device = config_found(sc->sc_dev, args, hdaudio_config_print, 694 1.16 thorpej CFARGS(.submatch = config_stdsubmatch, 695 1.16 thorpej .locators = locs)); 696 1.1 jmcneill 697 1.1 jmcneill prop_object_release(args); 698 1.1 jmcneill } 699 1.1 jmcneill 700 1.1 jmcneill static void 701 1.1 jmcneill hdaudio_codec_attach(struct hdaudio_codec *co) 702 1.1 jmcneill { 703 1.13 jmcneill struct hdaudio_softc *sc = co->co_host; 704 1.1 jmcneill struct hdaudio_function_group *fg; 705 1.1 jmcneill uint32_t vid, snc, fgrp; 706 1.1 jmcneill int starting_node, num_nodes, nid; 707 1.1 jmcneill 708 1.1 jmcneill if (co->co_valid == false) 709 1.1 jmcneill return; 710 1.1 jmcneill 711 1.1 jmcneill vid = hdaudio_command(co, 0, CORB_GET_PARAMETER, COP_VENDOR_ID); 712 1.1 jmcneill snc = hdaudio_command(co, 0, CORB_GET_PARAMETER, 713 1.1 jmcneill COP_SUBORDINATE_NODE_COUNT); 714 1.1 jmcneill 715 1.1 jmcneill /* make sure the vendor and product IDs are valid */ 716 1.1 jmcneill if (vid == 0xffffffff || vid == 0x00000000) 717 1.1 jmcneill return; 718 1.1 jmcneill 719 1.1 jmcneill #ifdef HDAUDIO_DEBUG 720 1.1 jmcneill uint32_t rid = hdaudio_command(co, 0, CORB_GET_PARAMETER, 721 1.1 jmcneill COP_REVISION_ID); 722 1.1 jmcneill hda_print(sc, "Codec%02X: %04X:%04X HDA %d.%d rev %d stepping %d\n", 723 1.1 jmcneill co->co_addr, vid >> 16, vid & 0xffff, 724 1.1 jmcneill (rid >> 20) & 0xf, (rid >> 16) & 0xf, 725 1.1 jmcneill (rid >> 8) & 0xff, rid & 0xff); 726 1.1 jmcneill #endif 727 1.1 jmcneill starting_node = (snc >> 16) & 0xff; 728 1.1 jmcneill num_nodes = snc & 0xff; 729 1.1 jmcneill 730 1.13 jmcneill /* 731 1.13 jmcneill * If the total number of nodes is 0, there's nothing we can do. 732 1.13 jmcneill * This shouldn't happen, so complain about it. 733 1.13 jmcneill */ 734 1.13 jmcneill if (num_nodes == 0) { 735 1.13 jmcneill hda_error(sc, "Codec%02X: No subordinate nodes found (%08x)\n", 736 1.13 jmcneill co->co_addr, snc); 737 1.13 jmcneill return; 738 1.13 jmcneill } 739 1.13 jmcneill 740 1.1 jmcneill co->co_nfg = num_nodes; 741 1.1 jmcneill co->co_fg = kmem_zalloc(co->co_nfg * sizeof(*co->co_fg), KM_SLEEP); 742 1.1 jmcneill 743 1.1 jmcneill for (nid = starting_node; nid < starting_node + num_nodes; nid++) { 744 1.1 jmcneill fg = &co->co_fg[nid - starting_node]; 745 1.1 jmcneill fg->fg_codec = co; 746 1.1 jmcneill fg->fg_nid = nid; 747 1.1 jmcneill fg->fg_vendor = vid >> 16; 748 1.1 jmcneill fg->fg_product = vid & 0xffff; 749 1.1 jmcneill 750 1.1 jmcneill fgrp = hdaudio_command(co, nid, CORB_GET_PARAMETER, 751 1.1 jmcneill COP_FUNCTION_GROUP_TYPE); 752 1.1 jmcneill switch (fgrp & 0xff) { 753 1.1 jmcneill case 0x01: /* Audio Function Group */ 754 1.1 jmcneill fg->fg_type = HDAUDIO_GROUP_TYPE_AFG; 755 1.1 jmcneill break; 756 1.1 jmcneill case 0x02: /* Vendor Specific Modem Function Group */ 757 1.1 jmcneill fg->fg_type = HDAUDIO_GROUP_TYPE_VSM_FG; 758 1.1 jmcneill break; 759 1.1 jmcneill default: 760 1.1 jmcneill /* Function group type not supported */ 761 1.1 jmcneill fg->fg_type = HDAUDIO_GROUP_TYPE_UNKNOWN; 762 1.1 jmcneill break; 763 1.1 jmcneill } 764 1.1 jmcneill hdaudio_attach_fg(fg, NULL); 765 1.1 jmcneill } 766 1.1 jmcneill } 767 1.1 jmcneill 768 1.1 jmcneill int 769 1.1 jmcneill hdaudio_stream_tag(struct hdaudio_stream *st) 770 1.1 jmcneill { 771 1.1 jmcneill int ret = 0; 772 1.1 jmcneill 773 1.1 jmcneill switch (st->st_type) { 774 1.1 jmcneill case HDAUDIO_STREAM_ISS: 775 1.1 jmcneill ret = 1; 776 1.1 jmcneill break; 777 1.1 jmcneill case HDAUDIO_STREAM_OSS: 778 1.1 jmcneill ret = 2; 779 1.1 jmcneill break; 780 1.1 jmcneill case HDAUDIO_STREAM_BSS: 781 1.1 jmcneill ret = 3; 782 1.1 jmcneill break; 783 1.1 jmcneill } 784 1.1 jmcneill 785 1.1 jmcneill return ret; 786 1.1 jmcneill } 787 1.1 jmcneill 788 1.1 jmcneill int 789 1.1 jmcneill hdaudio_attach(device_t dev, struct hdaudio_softc *sc) 790 1.1 jmcneill { 791 1.1 jmcneill int err, i; 792 1.1 jmcneill 793 1.1 jmcneill KASSERT(sc->sc_memvalid == true); 794 1.1 jmcneill 795 1.1 jmcneill sc->sc_dev = dev; 796 1.1 jmcneill mutex_init(&sc->sc_corb_mtx, MUTEX_DEFAULT, IPL_AUDIO); 797 1.1 jmcneill mutex_init(&sc->sc_stream_mtx, MUTEX_DEFAULT, IPL_AUDIO); 798 1.1 jmcneill 799 1.1 jmcneill /* 800 1.1 jmcneill * Put the controller into a known state by entering and leaving 801 1.1 jmcneill * CRST as necessary. 802 1.1 jmcneill */ 803 1.1 jmcneill if ((err = hdaudio_reset(sc)) != 0) 804 1.1 jmcneill goto fail; 805 1.1 jmcneill 806 1.1 jmcneill /* 807 1.1 jmcneill * From the spec: 808 1.1 jmcneill * 809 1.1 jmcneill * Must wait 250us after reading CRST as a 1 before assuming that 810 1.1 jmcneill * codecs have all made status change requests and have been 811 1.1 jmcneill * registered by the controller. 812 1.1 jmcneill * 813 1.1 jmcneill * In reality, we need to wait longer than this. 814 1.1 jmcneill */ 815 1.1 jmcneill hda_delay(HDAUDIO_CODEC_DELAY); 816 1.10 jmcneill 817 1.10 jmcneill /* 818 1.10 jmcneill * Read device capabilities 819 1.10 jmcneill */ 820 1.10 jmcneill hdaudio_init(sc); 821 1.10 jmcneill 822 1.10 jmcneill /* 823 1.10 jmcneill * Detect codecs 824 1.10 jmcneill */ 825 1.1 jmcneill if (hdaudio_codec_probe(sc) == 0) { 826 1.1 jmcneill hda_error(sc, "no codecs found\n"); 827 1.1 jmcneill err = ENODEV; 828 1.1 jmcneill goto fail; 829 1.1 jmcneill } 830 1.1 jmcneill 831 1.1 jmcneill /* 832 1.1 jmcneill * Ensure that the device is in a known state 833 1.1 jmcneill */ 834 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_STATESTS, HDAUDIO_STATESTS_SDIWAKE); 835 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS, 836 1.1 jmcneill HDAUDIO_RIRBSTS_RIRBOIS | HDAUDIO_RIRBSTS_RINTFL); 837 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTSTS, 838 1.1 jmcneill hda_read4(sc, HDAUDIO_MMIO_INTSTS)); 839 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_DPLBASE, 0); 840 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_DPUBASE, 0); 841 1.1 jmcneill 842 1.1 jmcneill /* 843 1.1 jmcneill * Initialize the CORB. First negotiate a command buffer size, 844 1.1 jmcneill * then allocate and configure it. 845 1.1 jmcneill */ 846 1.1 jmcneill if ((err = hdaudio_corb_setsize(sc)) != 0) 847 1.1 jmcneill goto fail; 848 1.1 jmcneill if ((err = hdaudio_dma_alloc(sc, &sc->sc_corb, BUS_DMA_WRITE)) != 0) 849 1.1 jmcneill goto fail; 850 1.1 jmcneill if ((err = hdaudio_corb_config(sc)) != 0) 851 1.1 jmcneill goto fail; 852 1.1 jmcneill 853 1.1 jmcneill /* 854 1.1 jmcneill * Initialize the RIRB. 855 1.1 jmcneill */ 856 1.1 jmcneill if ((err = hdaudio_rirb_setsize(sc)) != 0) 857 1.1 jmcneill goto fail; 858 1.1 jmcneill if ((err = hdaudio_dma_alloc(sc, &sc->sc_rirb, BUS_DMA_READ)) != 0) 859 1.1 jmcneill goto fail; 860 1.1 jmcneill if ((err = hdaudio_rirb_config(sc)) != 0) 861 1.1 jmcneill goto fail; 862 1.1 jmcneill 863 1.1 jmcneill /* 864 1.1 jmcneill * Start the CORB and RIRB 865 1.1 jmcneill */ 866 1.1 jmcneill if ((err = hdaudio_corb_start(sc)) != 0) 867 1.1 jmcneill goto fail; 868 1.1 jmcneill if ((err = hdaudio_rirb_start(sc)) != 0) 869 1.1 jmcneill goto fail; 870 1.1 jmcneill 871 1.1 jmcneill /* 872 1.1 jmcneill * Identify and attach discovered codecs 873 1.1 jmcneill */ 874 1.1 jmcneill for (i = 0; i < HDAUDIO_MAX_CODECS; i++) 875 1.1 jmcneill hdaudio_codec_attach(&sc->sc_codec[i]); 876 1.1 jmcneill 877 1.1 jmcneill /* 878 1.1 jmcneill * Enable interrupts 879 1.1 jmcneill */ 880 1.1 jmcneill hdaudio_intr_enable(sc); 881 1.1 jmcneill 882 1.1 jmcneill fail: 883 1.1 jmcneill if (err) 884 1.1 jmcneill hda_error(sc, "device driver failed to attach\n"); 885 1.1 jmcneill return err; 886 1.1 jmcneill } 887 1.1 jmcneill 888 1.1 jmcneill int 889 1.1 jmcneill hdaudio_detach(struct hdaudio_softc *sc, int flags) 890 1.1 jmcneill { 891 1.1 jmcneill int error; 892 1.1 jmcneill 893 1.1 jmcneill /* Disable interrupts */ 894 1.1 jmcneill hdaudio_intr_disable(sc); 895 1.1 jmcneill 896 1.1 jmcneill error = config_detach_children(sc->sc_dev, flags); 897 1.1 jmcneill if (error != 0) { 898 1.1 jmcneill hdaudio_intr_enable(sc); 899 1.1 jmcneill return error; 900 1.1 jmcneill } 901 1.1 jmcneill 902 1.1 jmcneill mutex_destroy(&sc->sc_corb_mtx); 903 1.1 jmcneill mutex_destroy(&sc->sc_stream_mtx); 904 1.1 jmcneill 905 1.1 jmcneill hdaudio_dma_free(sc, &sc->sc_corb); 906 1.1 jmcneill hdaudio_dma_free(sc, &sc->sc_rirb); 907 1.1 jmcneill 908 1.1 jmcneill return 0; 909 1.1 jmcneill } 910 1.1 jmcneill 911 1.1 jmcneill bool 912 1.1 jmcneill hdaudio_resume(struct hdaudio_softc *sc) 913 1.1 jmcneill { 914 1.1 jmcneill if (hdaudio_reset(sc) != 0) 915 1.1 jmcneill return false; 916 1.1 jmcneill 917 1.1 jmcneill hda_delay(HDAUDIO_CODEC_DELAY); 918 1.1 jmcneill 919 1.1 jmcneill /* 920 1.1 jmcneill * Ensure that the device is in a known state 921 1.1 jmcneill */ 922 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_STATESTS, HDAUDIO_STATESTS_SDIWAKE); 923 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS, 924 1.1 jmcneill HDAUDIO_RIRBSTS_RIRBOIS | HDAUDIO_RIRBSTS_RINTFL); 925 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTSTS, 926 1.1 jmcneill hda_read4(sc, HDAUDIO_MMIO_INTSTS)); 927 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_DPLBASE, 0); 928 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_DPUBASE, 0); 929 1.1 jmcneill 930 1.1 jmcneill if (hdaudio_corb_config(sc) != 0) 931 1.1 jmcneill return false; 932 1.1 jmcneill if (hdaudio_rirb_config(sc) != 0) 933 1.1 jmcneill return false; 934 1.1 jmcneill if (hdaudio_corb_start(sc) != 0) 935 1.1 jmcneill return false; 936 1.1 jmcneill if (hdaudio_rirb_start(sc) != 0) 937 1.1 jmcneill return false; 938 1.1 jmcneill 939 1.1 jmcneill hdaudio_intr_enable(sc); 940 1.1 jmcneill 941 1.1 jmcneill return true; 942 1.1 jmcneill } 943 1.1 jmcneill 944 1.1 jmcneill int 945 1.1 jmcneill hdaudio_rescan(struct hdaudio_softc *sc, const char *ifattr, const int *locs) 946 1.1 jmcneill { 947 1.1 jmcneill struct hdaudio_codec *co; 948 1.1 jmcneill struct hdaudio_function_group *fg; 949 1.1 jmcneill unsigned int codec; 950 1.1 jmcneill 951 1.1 jmcneill for (codec = 0; codec < HDAUDIO_MAX_CODECS; codec++) { 952 1.1 jmcneill co = &sc->sc_codec[codec]; 953 1.1 jmcneill fg = co->co_fg; 954 1.1 jmcneill if (!co->co_valid || fg == NULL) 955 1.1 jmcneill continue; 956 1.1 jmcneill if (fg->fg_device) 957 1.1 jmcneill continue; 958 1.1 jmcneill hdaudio_attach_fg(fg, NULL); 959 1.1 jmcneill } 960 1.1 jmcneill 961 1.1 jmcneill return 0; 962 1.1 jmcneill } 963 1.1 jmcneill 964 1.1 jmcneill void 965 1.1 jmcneill hdaudio_childdet(struct hdaudio_softc *sc, device_t child) 966 1.1 jmcneill { 967 1.1 jmcneill struct hdaudio_codec *co; 968 1.1 jmcneill struct hdaudio_function_group *fg; 969 1.1 jmcneill unsigned int codec; 970 1.1 jmcneill 971 1.1 jmcneill for (codec = 0; codec < HDAUDIO_MAX_CODECS; codec++) { 972 1.1 jmcneill co = &sc->sc_codec[codec]; 973 1.1 jmcneill fg = co->co_fg; 974 1.1 jmcneill if (!co->co_valid || fg == NULL) 975 1.1 jmcneill continue; 976 1.1 jmcneill if (fg->fg_device == child) 977 1.1 jmcneill fg->fg_device = NULL; 978 1.1 jmcneill } 979 1.1 jmcneill } 980 1.1 jmcneill 981 1.1 jmcneill int 982 1.1 jmcneill hdaudio_intr(struct hdaudio_softc *sc) 983 1.1 jmcneill { 984 1.1 jmcneill struct hdaudio_stream *st; 985 1.1 jmcneill uint32_t intsts, stream_mask; 986 1.1 jmcneill int streamid = 0; 987 1.1 jmcneill uint8_t rirbsts; 988 1.1 jmcneill 989 1.1 jmcneill intsts = hda_read4(sc, HDAUDIO_MMIO_INTSTS); 990 1.1 jmcneill if (!(intsts & HDAUDIO_INTSTS_GIS)) 991 1.1 jmcneill return 0; 992 1.1 jmcneill 993 1.1 jmcneill if (intsts & HDAUDIO_INTSTS_CIS) { 994 1.1 jmcneill rirbsts = hda_read1(sc, HDAUDIO_MMIO_RIRBSTS); 995 1.1 jmcneill if (rirbsts & HDAUDIO_RIRBSTS_RINTFL) { 996 1.1 jmcneill mutex_enter(&sc->sc_corb_mtx); 997 1.1 jmcneill hdaudio_rirb_dequeue(sc, true); 998 1.1 jmcneill mutex_exit(&sc->sc_corb_mtx); 999 1.1 jmcneill } 1000 1.1 jmcneill if (rirbsts & (HDAUDIO_RIRBSTS_RIRBOIS|HDAUDIO_RIRBSTS_RINTFL)) 1001 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS, rirbsts); 1002 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTSTS, HDAUDIO_INTSTS_CIS); 1003 1.1 jmcneill } 1004 1.1 jmcneill if (intsts & HDAUDIO_INTSTS_SIS_MASK) { 1005 1.1 jmcneill mutex_enter(&sc->sc_stream_mtx); 1006 1.1 jmcneill stream_mask = intsts & sc->sc_stream_mask; 1007 1.1 jmcneill while (streamid < HDAUDIO_MAX_STREAMS && stream_mask != 0) { 1008 1.1 jmcneill st = &sc->sc_stream[streamid++]; 1009 1.1 jmcneill if ((stream_mask & 1) != 0 && st->st_intr) { 1010 1.1 jmcneill st->st_intr(st); 1011 1.1 jmcneill } 1012 1.1 jmcneill stream_mask >>= 1; 1013 1.1 jmcneill } 1014 1.1 jmcneill mutex_exit(&sc->sc_stream_mtx); 1015 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTSTS, HDAUDIO_INTSTS_SIS_MASK); 1016 1.1 jmcneill } 1017 1.1 jmcneill 1018 1.1 jmcneill return 1; 1019 1.1 jmcneill } 1020 1.1 jmcneill 1021 1.1 jmcneill struct hdaudio_stream * 1022 1.1 jmcneill hdaudio_stream_establish(struct hdaudio_softc *sc, 1023 1.1 jmcneill enum hdaudio_stream_type type, int (*intr)(struct hdaudio_stream *), 1024 1.1 jmcneill void *cookie) 1025 1.1 jmcneill { 1026 1.1 jmcneill struct hdaudio_stream *st; 1027 1.1 jmcneill struct hdaudio_dma dma; 1028 1.1 jmcneill int i, err; 1029 1.1 jmcneill 1030 1.1 jmcneill dma.dma_size = sizeof(struct hdaudio_bdl_entry) * HDAUDIO_BDL_MAX; 1031 1.2 riastrad dma.dma_sizereg = 0; 1032 1.1 jmcneill err = hdaudio_dma_alloc(sc, &dma, BUS_DMA_COHERENT | BUS_DMA_NOCACHE); 1033 1.1 jmcneill if (err) 1034 1.1 jmcneill return NULL; 1035 1.1 jmcneill 1036 1.1 jmcneill mutex_enter(&sc->sc_stream_mtx); 1037 1.1 jmcneill for (i = 0; i < HDAUDIO_MAX_STREAMS; i++) { 1038 1.1 jmcneill st = &sc->sc_stream[i]; 1039 1.1 jmcneill if (st->st_enable == false) 1040 1.1 jmcneill break; 1041 1.1 jmcneill if (st->st_type != type) 1042 1.1 jmcneill continue; 1043 1.1 jmcneill if (sc->sc_stream_mask & (1 << i)) 1044 1.1 jmcneill continue; 1045 1.1 jmcneill 1046 1.1 jmcneill /* Allocate stream */ 1047 1.1 jmcneill st->st_bdl = dma; 1048 1.1 jmcneill st->st_intr = intr; 1049 1.1 jmcneill st->st_cookie = cookie; 1050 1.1 jmcneill sc->sc_stream_mask |= (1 << i); 1051 1.1 jmcneill mutex_exit(&sc->sc_stream_mtx); 1052 1.1 jmcneill return st; 1053 1.1 jmcneill } 1054 1.1 jmcneill mutex_exit(&sc->sc_stream_mtx); 1055 1.1 jmcneill 1056 1.1 jmcneill /* No streams of requested type available */ 1057 1.1 jmcneill hdaudio_dma_free(sc, &dma); 1058 1.1 jmcneill return NULL; 1059 1.1 jmcneill } 1060 1.1 jmcneill 1061 1.1 jmcneill void 1062 1.1 jmcneill hdaudio_stream_disestablish(struct hdaudio_stream *st) 1063 1.1 jmcneill { 1064 1.1 jmcneill struct hdaudio_softc *sc = st->st_host; 1065 1.1 jmcneill struct hdaudio_dma dma; 1066 1.1 jmcneill 1067 1.1 jmcneill KASSERT(sc->sc_stream_mask & (1 << st->st_shift)); 1068 1.1 jmcneill 1069 1.1 jmcneill mutex_enter(&sc->sc_stream_mtx); 1070 1.1 jmcneill sc->sc_stream_mask &= ~(1 << st->st_shift); 1071 1.1 jmcneill st->st_intr = NULL; 1072 1.1 jmcneill st->st_cookie = NULL; 1073 1.1 jmcneill dma = st->st_bdl; 1074 1.1 jmcneill st->st_bdl.dma_valid = false; 1075 1.1 jmcneill mutex_exit(&sc->sc_stream_mtx); 1076 1.1 jmcneill 1077 1.1 jmcneill /* Can't bus_dmamem_unmap while holding a mutex. */ 1078 1.1 jmcneill hdaudio_dma_free(sc, &dma); 1079 1.1 jmcneill } 1080 1.1 jmcneill 1081 1.1 jmcneill /* 1082 1.18 andvar * Convert most of audio_params_t to stream fmt descriptor; noticeably missing 1083 1.1 jmcneill * is the # channels bits, as this is encoded differently in codec and 1084 1.1 jmcneill * stream descriptors. 1085 1.1 jmcneill * 1086 1.1 jmcneill * TODO: validate that the stream and selected codecs can handle the fmt 1087 1.1 jmcneill */ 1088 1.1 jmcneill uint16_t 1089 1.1 jmcneill hdaudio_stream_param(struct hdaudio_stream *st, const audio_params_t *param) 1090 1.1 jmcneill { 1091 1.1 jmcneill uint16_t fmt = 0; 1092 1.1 jmcneill 1093 1.1 jmcneill switch (param->encoding) { 1094 1.1 jmcneill case AUDIO_ENCODING_AC3: 1095 1.1 jmcneill fmt |= HDAUDIO_FMT_TYPE_NONPCM; 1096 1.1 jmcneill break; 1097 1.1 jmcneill default: 1098 1.1 jmcneill fmt |= HDAUDIO_FMT_TYPE_PCM; 1099 1.1 jmcneill break; 1100 1.1 jmcneill } 1101 1.1 jmcneill 1102 1.1 jmcneill switch (param->sample_rate) { 1103 1.1 jmcneill case 8000: 1104 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) | 1105 1.1 jmcneill HDAUDIO_FMT_DIV(6); 1106 1.1 jmcneill break; 1107 1.1 jmcneill case 11025: 1108 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1) | 1109 1.1 jmcneill HDAUDIO_FMT_DIV(4); 1110 1.1 jmcneill break; 1111 1.1 jmcneill case 16000: 1112 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) | 1113 1.1 jmcneill HDAUDIO_FMT_DIV(3); 1114 1.1 jmcneill break; 1115 1.1 jmcneill case 22050: 1116 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1) | 1117 1.1 jmcneill HDAUDIO_FMT_DIV(2); 1118 1.1 jmcneill break; 1119 1.1 jmcneill case 32000: 1120 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(2) | 1121 1.1 jmcneill HDAUDIO_FMT_DIV(3); 1122 1.1 jmcneill break; 1123 1.1 jmcneill case 44100: 1124 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1); 1125 1.1 jmcneill break; 1126 1.1 jmcneill case 48000: 1127 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1); 1128 1.1 jmcneill break; 1129 1.1 jmcneill case 88200: 1130 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(2); 1131 1.1 jmcneill break; 1132 1.1 jmcneill case 96000: 1133 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(2); 1134 1.1 jmcneill break; 1135 1.1 jmcneill case 176400: 1136 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(4); 1137 1.1 jmcneill break; 1138 1.1 jmcneill case 192000: 1139 1.1 jmcneill fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(4); 1140 1.1 jmcneill break; 1141 1.1 jmcneill default: 1142 1.1 jmcneill return 0; 1143 1.1 jmcneill } 1144 1.1 jmcneill 1145 1.1 jmcneill if (param->precision == 16 && param->validbits == 8) 1146 1.1 jmcneill fmt |= HDAUDIO_FMT_BITS_8_16; 1147 1.1 jmcneill else if (param->precision == 16 && param->validbits == 16) 1148 1.1 jmcneill fmt |= HDAUDIO_FMT_BITS_16_16; 1149 1.1 jmcneill else if (param->precision == 32 && param->validbits == 20) 1150 1.1 jmcneill fmt |= HDAUDIO_FMT_BITS_20_32; 1151 1.1 jmcneill else if (param->precision == 32 && param->validbits == 24) 1152 1.1 jmcneill fmt |= HDAUDIO_FMT_BITS_24_32; 1153 1.1 jmcneill else if (param->precision == 32 && param->validbits == 32) 1154 1.1 jmcneill fmt |= HDAUDIO_FMT_BITS_32_32; 1155 1.1 jmcneill else 1156 1.1 jmcneill return 0; 1157 1.1 jmcneill 1158 1.1 jmcneill return fmt; 1159 1.1 jmcneill } 1160 1.1 jmcneill 1161 1.1 jmcneill void 1162 1.1 jmcneill hdaudio_stream_reset(struct hdaudio_stream *st) 1163 1.1 jmcneill { 1164 1.1 jmcneill struct hdaudio_softc *sc = st->st_host; 1165 1.1 jmcneill int snum = st->st_shift; 1166 1.1 jmcneill int retry; 1167 1.1 jmcneill uint8_t ctl0; 1168 1.1 jmcneill 1169 1.1 jmcneill ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum)); 1170 1.1 jmcneill ctl0 |= HDAUDIO_CTL_SRST; 1171 1.1 jmcneill hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0); 1172 1.1 jmcneill 1173 1.1 jmcneill retry = HDAUDIO_RESET_TIMEOUT; 1174 1.1 jmcneill do { 1175 1.1 jmcneill ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum)); 1176 1.1 jmcneill if (ctl0 & HDAUDIO_CTL_SRST) 1177 1.1 jmcneill break; 1178 1.1 jmcneill hda_delay(10); 1179 1.1 jmcneill } while (--retry > 0); 1180 1.1 jmcneill 1181 1.1 jmcneill ctl0 &= ~HDAUDIO_CTL_SRST; 1182 1.1 jmcneill hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0); 1183 1.1 jmcneill 1184 1.1 jmcneill retry = HDAUDIO_RESET_TIMEOUT; 1185 1.1 jmcneill do { 1186 1.1 jmcneill ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum)); 1187 1.1 jmcneill if (!(ctl0 & HDAUDIO_CTL_SRST)) 1188 1.1 jmcneill break; 1189 1.1 jmcneill hda_delay(10); 1190 1.1 jmcneill } while (--retry > 0); 1191 1.1 jmcneill if (retry == 0) { 1192 1.1 jmcneill hda_error(sc, "timeout leaving stream reset state\n"); 1193 1.1 jmcneill return; 1194 1.1 jmcneill } 1195 1.1 jmcneill } 1196 1.1 jmcneill 1197 1.1 jmcneill void 1198 1.1 jmcneill hdaudio_stream_start(struct hdaudio_stream *st, int blksize, 1199 1.1 jmcneill bus_size_t dmasize, const audio_params_t *params) 1200 1.1 jmcneill { 1201 1.1 jmcneill struct hdaudio_softc *sc = st->st_host; 1202 1.1 jmcneill struct hdaudio_bdl_entry *bdl; 1203 1.1 jmcneill uint64_t dmaaddr; 1204 1.1 jmcneill uint32_t intctl; 1205 1.1 jmcneill uint16_t fmt; 1206 1.1 jmcneill uint8_t ctl0, ctl2; 1207 1.1 jmcneill int cnt, snum = st->st_shift; 1208 1.1 jmcneill 1209 1.1 jmcneill KASSERT(sc->sc_stream_mask & (1 << st->st_shift)); 1210 1.1 jmcneill KASSERT(st->st_data.dma_valid == true); 1211 1.1 jmcneill KASSERT(st->st_bdl.dma_valid == true); 1212 1.1 jmcneill 1213 1.1 jmcneill hdaudio_stream_stop(st); 1214 1.4 jmcneill hdaudio_stream_reset(st); 1215 1.1 jmcneill 1216 1.1 jmcneill /* 1217 1.1 jmcneill * Configure buffer descriptor list 1218 1.1 jmcneill */ 1219 1.1 jmcneill dmaaddr = DMA_DMAADDR(&st->st_data); 1220 1.1 jmcneill bdl = DMA_KERNADDR(&st->st_bdl); 1221 1.1 jmcneill for (cnt = 0; cnt < HDAUDIO_BDL_MAX; cnt++) { 1222 1.1 jmcneill bdl[cnt].address_lo = (uint32_t)dmaaddr; 1223 1.1 jmcneill bdl[cnt].address_hi = dmaaddr >> 32; 1224 1.1 jmcneill bdl[cnt].length = blksize; 1225 1.1 jmcneill bdl[cnt].flags = HDAUDIO_BDL_ENTRY_IOC; 1226 1.1 jmcneill dmaaddr += blksize; 1227 1.1 jmcneill if (dmaaddr >= DMA_DMAADDR(&st->st_data) + dmasize) { 1228 1.1 jmcneill cnt++; 1229 1.1 jmcneill break; 1230 1.1 jmcneill } 1231 1.1 jmcneill } 1232 1.1 jmcneill 1233 1.1 jmcneill /* 1234 1.1 jmcneill * Program buffer descriptor list 1235 1.1 jmcneill */ 1236 1.1 jmcneill dmaaddr = DMA_DMAADDR(&st->st_bdl); 1237 1.1 jmcneill hda_write4(sc, HDAUDIO_SD_BDPL(snum), (uint32_t)dmaaddr); 1238 1.1 jmcneill hda_write4(sc, HDAUDIO_SD_BDPU(snum), (uint32_t)(dmaaddr >> 32)); 1239 1.1 jmcneill hda_write2(sc, HDAUDIO_SD_LVI(snum), (cnt - 1) & 0xff); 1240 1.1 jmcneill 1241 1.1 jmcneill /* 1242 1.1 jmcneill * Program cyclic buffer length 1243 1.1 jmcneill */ 1244 1.1 jmcneill hda_write4(sc, HDAUDIO_SD_CBL(snum), dmasize); 1245 1.1 jmcneill 1246 1.1 jmcneill /* 1247 1.1 jmcneill * Program stream number (tag). Although controller hardware is 1248 1.1 jmcneill * capable of transmitting any stream number (0-15), by convention 1249 1.1 jmcneill * stream 0 is reserved as unused by software, so that converters 1250 1.1 jmcneill * whose stream numbers have been reset to 0 do not unintentionally 1251 1.1 jmcneill * decode data not intended for them. 1252 1.1 jmcneill */ 1253 1.1 jmcneill ctl2 = hda_read1(sc, HDAUDIO_SD_CTL2(snum)); 1254 1.1 jmcneill ctl2 &= ~0xf0; 1255 1.1 jmcneill ctl2 |= hdaudio_stream_tag(st) << 4; 1256 1.1 jmcneill hda_write1(sc, HDAUDIO_SD_CTL2(snum), ctl2); 1257 1.1 jmcneill 1258 1.1 jmcneill /* 1259 1.1 jmcneill * Program stream format 1260 1.1 jmcneill */ 1261 1.1 jmcneill fmt = hdaudio_stream_param(st, params) | 1262 1.1 jmcneill HDAUDIO_FMT_CHAN(params->channels); 1263 1.1 jmcneill hda_write2(sc, HDAUDIO_SD_FMT(snum), fmt); 1264 1.1 jmcneill 1265 1.1 jmcneill /* 1266 1.1 jmcneill * Switch on interrupts for this stream 1267 1.1 jmcneill */ 1268 1.1 jmcneill intctl = hda_read4(sc, HDAUDIO_MMIO_INTCTL); 1269 1.1 jmcneill intctl |= (1 << st->st_shift); 1270 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, intctl); 1271 1.1 jmcneill 1272 1.1 jmcneill /* 1273 1.1 jmcneill * Start running the stream 1274 1.1 jmcneill */ 1275 1.1 jmcneill ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum)); 1276 1.1 jmcneill ctl0 |= HDAUDIO_CTL_DEIE | HDAUDIO_CTL_FEIE | HDAUDIO_CTL_IOCE | 1277 1.1 jmcneill HDAUDIO_CTL_RUN; 1278 1.1 jmcneill hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0); 1279 1.1 jmcneill } 1280 1.1 jmcneill 1281 1.1 jmcneill void 1282 1.1 jmcneill hdaudio_stream_stop(struct hdaudio_stream *st) 1283 1.1 jmcneill { 1284 1.1 jmcneill struct hdaudio_softc *sc = st->st_host; 1285 1.1 jmcneill uint32_t intctl; 1286 1.1 jmcneill uint8_t ctl0; 1287 1.1 jmcneill int snum = st->st_shift; 1288 1.1 jmcneill 1289 1.1 jmcneill /* 1290 1.1 jmcneill * Stop running the stream 1291 1.1 jmcneill */ 1292 1.1 jmcneill ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum)); 1293 1.1 jmcneill ctl0 &= ~(HDAUDIO_CTL_DEIE | HDAUDIO_CTL_FEIE | HDAUDIO_CTL_IOCE | 1294 1.1 jmcneill HDAUDIO_CTL_RUN); 1295 1.1 jmcneill hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0); 1296 1.1 jmcneill 1297 1.1 jmcneill /* 1298 1.1 jmcneill * Switch off interrupts for this stream 1299 1.1 jmcneill */ 1300 1.1 jmcneill intctl = hda_read4(sc, HDAUDIO_MMIO_INTCTL); 1301 1.1 jmcneill intctl &= ~(1 << st->st_shift); 1302 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, intctl); 1303 1.1 jmcneill } 1304 1.1 jmcneill 1305 1.1 jmcneill /* 1306 1.1 jmcneill * /dev/hdaudioN interface 1307 1.1 jmcneill */ 1308 1.1 jmcneill 1309 1.1 jmcneill static const char * 1310 1.1 jmcneill hdaudioioctl_fgrp_to_cstr(enum function_group_type type) 1311 1.1 jmcneill { 1312 1.1 jmcneill switch (type) { 1313 1.1 jmcneill case HDAUDIO_GROUP_TYPE_AFG: 1314 1.1 jmcneill return "afg"; 1315 1.1 jmcneill case HDAUDIO_GROUP_TYPE_VSM_FG: 1316 1.1 jmcneill return "vsmfg"; 1317 1.1 jmcneill default: 1318 1.1 jmcneill return "unknown"; 1319 1.1 jmcneill } 1320 1.1 jmcneill } 1321 1.1 jmcneill 1322 1.1 jmcneill static struct hdaudio_function_group * 1323 1.1 jmcneill hdaudioioctl_fgrp_lookup(struct hdaudio_softc *sc, int codecid, int nid) 1324 1.1 jmcneill { 1325 1.1 jmcneill struct hdaudio_codec *co; 1326 1.1 jmcneill struct hdaudio_function_group *fg = NULL; 1327 1.1 jmcneill int i; 1328 1.1 jmcneill 1329 1.1 jmcneill if (codecid < 0 || codecid >= HDAUDIO_MAX_CODECS) 1330 1.1 jmcneill return NULL; 1331 1.1 jmcneill co = &sc->sc_codec[codecid]; 1332 1.1 jmcneill if (co->co_valid == false) 1333 1.1 jmcneill return NULL; 1334 1.1 jmcneill 1335 1.1 jmcneill for (i = 0; i < co->co_nfg; i++) 1336 1.1 jmcneill if (co->co_fg[i].fg_nid == nid) { 1337 1.1 jmcneill fg = &co->co_fg[i]; 1338 1.1 jmcneill break; 1339 1.1 jmcneill } 1340 1.1 jmcneill 1341 1.1 jmcneill return fg; 1342 1.1 jmcneill } 1343 1.1 jmcneill 1344 1.1 jmcneill static int 1345 1.1 jmcneill hdaudioioctl_fgrp_info(struct hdaudio_softc *sc, prop_dictionary_t request, 1346 1.1 jmcneill prop_dictionary_t response) 1347 1.1 jmcneill { 1348 1.1 jmcneill struct hdaudio_codec *co; 1349 1.1 jmcneill struct hdaudio_function_group *fg; 1350 1.1 jmcneill prop_array_t array; 1351 1.1 jmcneill prop_dictionary_t dict; 1352 1.1 jmcneill int codecid, fgid; 1353 1.1 jmcneill 1354 1.1 jmcneill array = prop_array_create(); 1355 1.1 jmcneill if (array == NULL) 1356 1.1 jmcneill return ENOMEM; 1357 1.1 jmcneill 1358 1.1 jmcneill for (codecid = 0; codecid < HDAUDIO_MAX_CODECS; codecid++) { 1359 1.1 jmcneill co = &sc->sc_codec[codecid]; 1360 1.1 jmcneill if (co->co_valid == false) 1361 1.1 jmcneill continue; 1362 1.1 jmcneill for (fgid = 0; fgid < co->co_nfg; fgid++) { 1363 1.1 jmcneill fg = &co->co_fg[fgid]; 1364 1.1 jmcneill dict = prop_dictionary_create(); 1365 1.1 jmcneill if (dict == NULL) 1366 1.1 jmcneill return ENOMEM; 1367 1.11 thorpej prop_dictionary_set_string_nocopy(dict, 1368 1.1 jmcneill "type", hdaudioioctl_fgrp_to_cstr(fg->fg_type)); 1369 1.1 jmcneill prop_dictionary_set_int16(dict, "nid", fg->fg_nid); 1370 1.1 jmcneill prop_dictionary_set_int16(dict, "codecid", codecid); 1371 1.1 jmcneill prop_dictionary_set_uint16(dict, "vendor-id", 1372 1.1 jmcneill fg->fg_vendor); 1373 1.1 jmcneill prop_dictionary_set_uint16(dict, "product-id", 1374 1.1 jmcneill fg->fg_product); 1375 1.1 jmcneill prop_dictionary_set_uint32(dict, "subsystem-id", 1376 1.1 jmcneill sc->sc_subsystem); 1377 1.1 jmcneill if (fg->fg_device) 1378 1.11 thorpej prop_dictionary_set_string(dict, "device", 1379 1.1 jmcneill device_xname(fg->fg_device)); 1380 1.1 jmcneill else 1381 1.11 thorpej prop_dictionary_set_string_nocopy(dict, 1382 1.1 jmcneill "device", "<none>"); 1383 1.1 jmcneill prop_array_add(array, dict); 1384 1.1 jmcneill } 1385 1.1 jmcneill } 1386 1.1 jmcneill 1387 1.1 jmcneill prop_dictionary_set(response, "function-group-info", array); 1388 1.1 jmcneill return 0; 1389 1.1 jmcneill } 1390 1.1 jmcneill 1391 1.1 jmcneill static int 1392 1.1 jmcneill hdaudioioctl_fgrp_getconfig(struct hdaudio_softc *sc, 1393 1.1 jmcneill prop_dictionary_t request, prop_dictionary_t response) 1394 1.1 jmcneill { 1395 1.1 jmcneill struct hdaudio_function_group *fg; 1396 1.1 jmcneill prop_dictionary_t dict; 1397 1.1 jmcneill prop_array_t array; 1398 1.1 jmcneill uint32_t nodecnt, wcap, config; 1399 1.1 jmcneill int16_t codecid, nid, i; 1400 1.1 jmcneill int startnode, endnode; 1401 1.1 jmcneill 1402 1.1 jmcneill if (!prop_dictionary_get_int16(request, "codecid", &codecid) || 1403 1.1 jmcneill !prop_dictionary_get_int16(request, "nid", &nid)) 1404 1.1 jmcneill return EINVAL; 1405 1.1 jmcneill 1406 1.1 jmcneill fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid); 1407 1.1 jmcneill if (fg == NULL) 1408 1.1 jmcneill return ENODEV; 1409 1.1 jmcneill 1410 1.1 jmcneill array = prop_array_create(); 1411 1.1 jmcneill if (array == NULL) 1412 1.1 jmcneill return ENOMEM; 1413 1.1 jmcneill 1414 1.1 jmcneill nodecnt = hdaudio_command(fg->fg_codec, fg->fg_nid, 1415 1.1 jmcneill CORB_GET_PARAMETER, COP_SUBORDINATE_NODE_COUNT); 1416 1.1 jmcneill startnode = COP_NODECNT_STARTNODE(nodecnt); 1417 1.1 jmcneill endnode = startnode + COP_NODECNT_NUMNODES(nodecnt); 1418 1.1 jmcneill 1419 1.1 jmcneill for (i = startnode; i < endnode; i++) { 1420 1.1 jmcneill wcap = hdaudio_command(fg->fg_codec, i, 1421 1.1 jmcneill CORB_GET_PARAMETER, COP_AUDIO_WIDGET_CAPABILITIES); 1422 1.1 jmcneill if (COP_AWCAP_TYPE(wcap) != COP_AWCAP_TYPE_PIN_COMPLEX) 1423 1.1 jmcneill continue; 1424 1.1 jmcneill config = hdaudio_command(fg->fg_codec, i, 1425 1.1 jmcneill CORB_GET_CONFIGURATION_DEFAULT, 0); 1426 1.1 jmcneill dict = prop_dictionary_create(); 1427 1.1 jmcneill if (dict == NULL) 1428 1.1 jmcneill return ENOMEM; 1429 1.1 jmcneill prop_dictionary_set_int16(dict, "nid", i); 1430 1.1 jmcneill prop_dictionary_set_uint32(dict, "config", config); 1431 1.1 jmcneill prop_array_add(array, dict); 1432 1.1 jmcneill } 1433 1.1 jmcneill 1434 1.1 jmcneill prop_dictionary_set(response, "pin-config", array); 1435 1.1 jmcneill 1436 1.1 jmcneill return 0; 1437 1.1 jmcneill } 1438 1.1 jmcneill 1439 1.1 jmcneill static int 1440 1.1 jmcneill hdaudioioctl_fgrp_setconfig(struct hdaudio_softc *sc, 1441 1.1 jmcneill prop_dictionary_t request, prop_dictionary_t response) 1442 1.1 jmcneill { 1443 1.1 jmcneill struct hdaudio_function_group *fg; 1444 1.1 jmcneill prop_array_t config; 1445 1.1 jmcneill int16_t codecid, nid; 1446 1.1 jmcneill int err; 1447 1.1 jmcneill 1448 1.1 jmcneill if (!prop_dictionary_get_int16(request, "codecid", &codecid) || 1449 1.1 jmcneill !prop_dictionary_get_int16(request, "nid", &nid)) 1450 1.1 jmcneill return EINVAL; 1451 1.1 jmcneill 1452 1.1 jmcneill fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid); 1453 1.1 jmcneill if (fg == NULL) 1454 1.1 jmcneill return ENODEV; 1455 1.1 jmcneill 1456 1.1 jmcneill if (fg->fg_device) { 1457 1.1 jmcneill err = config_detach(fg->fg_device, 0); 1458 1.1 jmcneill if (err) 1459 1.1 jmcneill return err; 1460 1.1 jmcneill fg->fg_device = NULL; 1461 1.1 jmcneill } 1462 1.1 jmcneill 1463 1.1 jmcneill /* "pin-config" may be NULL, this means "use BIOS configuration" */ 1464 1.1 jmcneill config = prop_dictionary_get(request, "pin-config"); 1465 1.1 jmcneill if (config && prop_object_type(config) != PROP_TYPE_ARRAY) { 1466 1.1 jmcneill prop_object_release(config); 1467 1.1 jmcneill return EINVAL; 1468 1.1 jmcneill } 1469 1.1 jmcneill hdaudio_attach_fg(fg, config); 1470 1.1 jmcneill if (config) 1471 1.1 jmcneill prop_object_release(config); 1472 1.1 jmcneill 1473 1.1 jmcneill return 0; 1474 1.1 jmcneill } 1475 1.1 jmcneill 1476 1.1 jmcneill static int 1477 1.1 jmcneill hdaudio_dispatch_fgrp_ioctl(struct hdaudio_softc *sc, u_long cmd, 1478 1.1 jmcneill prop_dictionary_t request, prop_dictionary_t response) 1479 1.1 jmcneill { 1480 1.1 jmcneill struct hdaudio_function_group *fg; 1481 1.1 jmcneill int (*infocb)(void *, prop_dictionary_t, prop_dictionary_t); 1482 1.1 jmcneill prop_dictionary_t fgrp_dict; 1483 1.1 jmcneill uint64_t info_fn; 1484 1.1 jmcneill int16_t codecid, nid; 1485 1.1 jmcneill void *fgrp_sc; 1486 1.1 jmcneill bool rv; 1487 1.1 jmcneill int err; 1488 1.1 jmcneill 1489 1.1 jmcneill if (!prop_dictionary_get_int16(request, "codecid", &codecid) || 1490 1.1 jmcneill !prop_dictionary_get_int16(request, "nid", &nid)) 1491 1.1 jmcneill return EINVAL; 1492 1.1 jmcneill 1493 1.1 jmcneill fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid); 1494 1.1 jmcneill if (fg == NULL) 1495 1.1 jmcneill return ENODEV; 1496 1.1 jmcneill if (fg->fg_device == NULL) 1497 1.1 jmcneill return ENXIO; 1498 1.1 jmcneill fgrp_sc = device_private(fg->fg_device); 1499 1.1 jmcneill fgrp_dict = device_properties(fg->fg_device); 1500 1.1 jmcneill 1501 1.1 jmcneill switch (fg->fg_type) { 1502 1.1 jmcneill case HDAUDIO_GROUP_TYPE_AFG: 1503 1.1 jmcneill switch (cmd) { 1504 1.1 jmcneill case HDAUDIO_FGRP_CODEC_INFO: 1505 1.1 jmcneill rv = prop_dictionary_get_uint64(fgrp_dict, 1506 1.1 jmcneill "codecinfo-callback", &info_fn); 1507 1.1 jmcneill if (!rv) 1508 1.1 jmcneill return ENXIO; 1509 1.1 jmcneill infocb = (void *)(uintptr_t)info_fn; 1510 1.1 jmcneill err = infocb(fgrp_sc, request, response); 1511 1.1 jmcneill break; 1512 1.1 jmcneill case HDAUDIO_FGRP_WIDGET_INFO: 1513 1.1 jmcneill rv = prop_dictionary_get_uint64(fgrp_dict, 1514 1.1 jmcneill "widgetinfo-callback", &info_fn); 1515 1.1 jmcneill if (!rv) 1516 1.1 jmcneill return ENXIO; 1517 1.1 jmcneill infocb = (void *)(uintptr_t)info_fn; 1518 1.1 jmcneill err = infocb(fgrp_sc, request, response); 1519 1.1 jmcneill break; 1520 1.1 jmcneill default: 1521 1.1 jmcneill err = EINVAL; 1522 1.1 jmcneill break; 1523 1.1 jmcneill } 1524 1.1 jmcneill break; 1525 1.1 jmcneill 1526 1.1 jmcneill default: 1527 1.1 jmcneill err = EINVAL; 1528 1.1 jmcneill break; 1529 1.1 jmcneill } 1530 1.1 jmcneill return err; 1531 1.1 jmcneill } 1532 1.1 jmcneill 1533 1.1 jmcneill int 1534 1.1 jmcneill hdaudioopen(dev_t dev, int flag, int mode, struct lwp *l) 1535 1.1 jmcneill { 1536 1.1 jmcneill device_t self; 1537 1.1 jmcneill 1538 1.1 jmcneill self = device_lookup(&hdaudio_cd, HDAUDIOUNIT(dev)); 1539 1.1 jmcneill if (self == NULL) 1540 1.1 jmcneill return ENXIO; 1541 1.1 jmcneill 1542 1.1 jmcneill return 0; 1543 1.1 jmcneill } 1544 1.1 jmcneill 1545 1.1 jmcneill int 1546 1.1 jmcneill hdaudioclose(dev_t dev, int flag, int mode, struct lwp *l) 1547 1.1 jmcneill { 1548 1.1 jmcneill return 0; 1549 1.1 jmcneill } 1550 1.1 jmcneill 1551 1.1 jmcneill int 1552 1.1 jmcneill hdaudioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 1553 1.1 jmcneill { 1554 1.1 jmcneill struct hdaudio_softc *sc; 1555 1.1 jmcneill struct plistref *pref = addr; 1556 1.1 jmcneill prop_dictionary_t request, response; 1557 1.1 jmcneill int err; 1558 1.1 jmcneill 1559 1.1 jmcneill sc = device_lookup_private(&hdaudio_cd, HDAUDIOUNIT(dev)); 1560 1.1 jmcneill if (sc == NULL) 1561 1.1 jmcneill return ENXIO; 1562 1.1 jmcneill 1563 1.1 jmcneill response = prop_dictionary_create(); 1564 1.1 jmcneill if (response == NULL) 1565 1.1 jmcneill return ENOMEM; 1566 1.1 jmcneill 1567 1.1 jmcneill err = prop_dictionary_copyin_ioctl(pref, cmd, &request); 1568 1.1 jmcneill if (err) { 1569 1.1 jmcneill prop_object_release(response); 1570 1.1 jmcneill return err; 1571 1.1 jmcneill } 1572 1.1 jmcneill 1573 1.1 jmcneill switch (cmd) { 1574 1.1 jmcneill case HDAUDIO_FGRP_INFO: 1575 1.1 jmcneill err = hdaudioioctl_fgrp_info(sc, request, response); 1576 1.1 jmcneill break; 1577 1.1 jmcneill case HDAUDIO_FGRP_GETCONFIG: 1578 1.1 jmcneill err = hdaudioioctl_fgrp_getconfig(sc, request, response); 1579 1.1 jmcneill break; 1580 1.1 jmcneill case HDAUDIO_FGRP_SETCONFIG: 1581 1.1 jmcneill err = hdaudioioctl_fgrp_setconfig(sc, request, response); 1582 1.1 jmcneill break; 1583 1.1 jmcneill case HDAUDIO_FGRP_CODEC_INFO: 1584 1.1 jmcneill case HDAUDIO_FGRP_WIDGET_INFO: 1585 1.1 jmcneill err = hdaudio_dispatch_fgrp_ioctl(sc, cmd, request, response); 1586 1.1 jmcneill break; 1587 1.1 jmcneill default: 1588 1.1 jmcneill err = EINVAL; 1589 1.1 jmcneill break; 1590 1.1 jmcneill } 1591 1.1 jmcneill 1592 1.1 jmcneill if (!err) 1593 1.1 jmcneill err = prop_dictionary_copyout_ioctl(pref, cmd, response); 1594 1.1 jmcneill 1595 1.1 jmcneill if (response) 1596 1.1 jmcneill prop_object_release(response); 1597 1.1 jmcneill prop_object_release(request); 1598 1.1 jmcneill return err; 1599 1.1 jmcneill } 1600 1.1 jmcneill 1601 1.5 pgoyette MODULE(MODULE_CLASS_DRIVER, hdaudio, "audio"); 1602 1.5 pgoyette #ifdef _MODULE 1603 1.5 pgoyette static const struct cfiattrdata hdaudiobuscf_iattrdata = { 1604 1.5 pgoyette "hdaudiobus", 1, { 1605 1.5 pgoyette { "nid", "-1", -1 }, 1606 1.5 pgoyette } 1607 1.5 pgoyette }; 1608 1.5 pgoyette static const struct cfiattrdata * const hdaudio_attrs[] = { 1609 1.5 pgoyette &hdaudiobuscf_iattrdata, NULL 1610 1.5 pgoyette }; 1611 1.5 pgoyette CFDRIVER_DECL(hdaudio, DV_AUDIODEV, hdaudio_attrs); 1612 1.5 pgoyette #endif 1613 1.1 jmcneill 1614 1.1 jmcneill static int 1615 1.1 jmcneill hdaudio_modcmd(modcmd_t cmd, void *opaque) 1616 1.1 jmcneill { 1617 1.1 jmcneill int error = 0; 1618 1.1 jmcneill #ifdef _MODULE 1619 1.1 jmcneill int bmaj = -1, cmaj = -1; 1620 1.1 jmcneill #endif 1621 1.1 jmcneill 1622 1.1 jmcneill switch (cmd) { 1623 1.1 jmcneill case MODULE_CMD_INIT: 1624 1.1 jmcneill #ifdef _MODULE 1625 1.1 jmcneill error = devsw_attach("hdaudio", NULL, &bmaj, 1626 1.1 jmcneill &hdaudio_cdevsw, &cmaj); 1627 1.5 pgoyette if (error) 1628 1.5 pgoyette break; 1629 1.5 pgoyette error = config_cfdriver_attach(&hdaudio_cd); 1630 1.5 pgoyette if (error) 1631 1.5 pgoyette devsw_detach(NULL, &hdaudio_cdevsw); 1632 1.1 jmcneill #endif 1633 1.5 pgoyette break; 1634 1.1 jmcneill case MODULE_CMD_FINI: 1635 1.1 jmcneill #ifdef _MODULE 1636 1.5 pgoyette error = config_cfdriver_detach(&hdaudio_cd); 1637 1.5 pgoyette if (error) 1638 1.5 pgoyette break; 1639 1.17 riastrad devsw_detach(NULL, &hdaudio_cdevsw); 1640 1.1 jmcneill #endif 1641 1.5 pgoyette break; 1642 1.1 jmcneill default: 1643 1.5 pgoyette error = ENOTTY; 1644 1.5 pgoyette break; 1645 1.1 jmcneill } 1646 1.5 pgoyette return error; 1647 1.1 jmcneill } 1648 1.1 jmcneill 1649 1.1 jmcneill DEV_VERBOSE_DEFINE(hdaudio); 1650