Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / hdaudio / hdaudio.c
blob8e6818eeed8b6885d1d22868cd512b69650330cc
1 /* $NetBSD: hdaudio.c,v 1.4 2009/09/07 16:35:02 jmcneill Exp $ */
3 /*
4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk>
5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
6 * All rights reserved.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Precedence Technologies Ltd
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.4 2009/09/07 16:35:02 jmcneill Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/conf.h>
40 #include <sys/bus.h>
41 #include <sys/kmem.h>
43 #include <dev/pci/hdaudio/hdaudiovar.h>
44 #include <dev/pci/hdaudio/hdaudioreg.h>
45 #include <dev/pci/hdaudio/hdaudioio.h>
47 /* #define HDAUDIO_DEBUG */
49 #define HDAUDIO_RESET_TIMEOUT 5000
50 #define HDAUDIO_CORB_TIMEOUT 1000
51 #define HDAUDIO_RIRB_TIMEOUT 5000
53 #define HDAUDIO_CODEC_DELAY 1000 /* spec calls for 250 */
55 dev_type_open(hdaudioopen);
56 dev_type_close(hdaudioclose);
57 dev_type_ioctl(hdaudioioctl);
59 const struct cdevsw hdaudio_cdevsw = {
60 hdaudioopen, hdaudioclose, noread, nowrite, hdaudioioctl,
61 nostop, notty, nopoll, nommap, nokqfilter,
62 D_OTHER
65 extern struct cfdriver hdaudio_cd;
67 #define HDAUDIOUNIT(x) minor((x))
69 static void
70 hdaudio_stream_init(struct hdaudio_softc *sc, int nis, int nos, int nbidir)
72 int i, cnt = 0;
74 for (i = 0; i < nis && cnt < HDAUDIO_MAX_STREAMS; i++) {
75 sc->sc_stream[cnt].st_host = sc;
76 sc->sc_stream[cnt].st_enable = true;
77 sc->sc_stream[cnt].st_shift = cnt;
78 sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_ISS;
80 for (i = 0; i < nos && cnt < HDAUDIO_MAX_STREAMS; i++) {
81 sc->sc_stream[cnt].st_host = sc;
82 sc->sc_stream[cnt].st_enable = true;
83 sc->sc_stream[cnt].st_shift = cnt;
84 sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_OSS;
86 for (i = 0; i < nbidir && cnt < HDAUDIO_MAX_STREAMS; i++) {
87 sc->sc_stream[cnt].st_host = sc;
88 sc->sc_stream[cnt].st_enable = true;
89 sc->sc_stream[cnt].st_shift = cnt;
90 sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_BSS;
93 for (i = 0; i < cnt; i++)
94 hdaudio_stream_stop(&sc->sc_stream[i]);
96 sc->sc_stream_mask = 0;
99 static void
100 hdaudio_codec_init(struct hdaudio_softc *sc)
102 int i;
104 for (i = 0; i < HDAUDIO_MAX_CODECS; i++) {
105 sc->sc_codec[i].co_addr = i;
106 sc->sc_codec[i].co_host = sc;
110 static void
111 hdaudio_init(struct hdaudio_softc *sc)
113 uint16_t gcap;
114 int nos, nis, nbidir;
115 #if defined(HDAUDIO_DEBUG)
116 uint8_t vmin, vmaj;
117 int nsdo, addr64;
118 #endif
120 #if defined(HDAUDIO_DEBUG)
121 vmaj = hda_read1(sc, HDAUDIO_MMIO_VMAJ);
122 vmin = hda_read1(sc, HDAUDIO_MMIO_VMIN);
124 hda_print(sc, "High Definition Audio version %d.%d\n", vmaj, vmin);
125 #endif
127 gcap = hda_read2(sc, HDAUDIO_MMIO_GCAP);
128 nis = (gcap >> 8) & 0xf;
129 nos = (gcap >> 12) & 0xf;
130 nbidir = (gcap >> 3) & 0x1f;
132 /* Initialize codecs and streams */
133 hdaudio_codec_init(sc);
134 hdaudio_stream_init(sc, nis, nos, nbidir);
136 #if defined(HDAUDIO_DEBUG)
137 nsdo = (gcap >> 1) & 1;
138 addr64 = gcap & 1;
140 hda_print(sc, "OSS %d ISS %d BSS %d SDO %d%s\n",
141 nos, nis, nbidir, nsdo, addr64 ? " 64-bit" : "");
142 #endif
145 static int
146 hdaudio_codec_probe(struct hdaudio_softc *sc)
148 uint16_t statests;
149 int codecid;
151 statests = hda_read2(sc, HDAUDIO_MMIO_STATESTS);
152 for (codecid = 0; codecid < HDAUDIO_MAX_CODECS; codecid++)
153 if (statests & (1 << codecid))
154 sc->sc_codec[codecid].co_valid = true;
155 hda_write2(sc, HDAUDIO_MMIO_STATESTS, statests);
157 return statests;
161 hdaudio_dma_alloc(struct hdaudio_softc *sc, struct hdaudio_dma *dma,
162 int flags)
164 int err;
166 KASSERT(dma->dma_size > 0);
168 err = bus_dmamem_alloc(sc->sc_dmat, dma->dma_size, 128, 0,
169 dma->dma_segs, sizeof(dma->dma_segs) / sizeof(dma->dma_segs[0]),
170 &dma->dma_nsegs, BUS_DMA_WAITOK);
171 if (err)
172 return err;
173 err = bus_dmamem_map(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs,
174 dma->dma_size, &dma->dma_addr, BUS_DMA_WAITOK | flags);
175 if (err)
176 goto free;
177 err = bus_dmamap_create(sc->sc_dmat, dma->dma_size, dma->dma_nsegs,
178 dma->dma_size, 0, BUS_DMA_WAITOK, &dma->dma_map);
179 if (err)
180 goto unmap;
181 err = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_addr,
182 dma->dma_size, NULL, BUS_DMA_WAITOK | flags);
183 if (err)
184 goto destroy;
186 dma->dma_valid = true;
187 return 0;
189 destroy:
190 bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
191 unmap:
192 bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size);
193 free:
194 bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs);
196 dma->dma_valid = false;
197 return err;
200 void
201 hdaudio_dma_free(struct hdaudio_softc *sc, struct hdaudio_dma *dma)
203 if (dma->dma_valid == false)
204 return;
205 bus_dmamap_unload(sc->sc_dmat, dma->dma_map);
206 bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
207 bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size);
208 bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs);
209 dma->dma_valid = false;
212 static void
213 hdaudio_corb_enqueue(struct hdaudio_softc *sc, int addr, int nid,
214 uint32_t control, uint32_t param)
216 uint32_t *corb = DMA_KERNADDR(&sc->sc_corb);
217 uint32_t verb;
218 uint16_t corbrp;
219 int wp;
221 /* Build command */
222 verb = (addr << 28) | (nid << 20) | (control << 8) | param;
224 /* Fetch and update write pointer */
225 corbrp = hda_read2(sc, HDAUDIO_MMIO_CORBWP);
226 wp = (corbrp & 0xff) + 1;
227 if (wp >= (sc->sc_corb.dma_size / sizeof(*corb)))
228 wp = 0;
230 /* Enqueue command */
231 bus_dmamap_sync(sc->sc_dmat, sc->sc_corb.dma_map, 0,
232 sc->sc_corb.dma_size, BUS_DMASYNC_POSTWRITE);
233 corb[wp] = verb;
234 bus_dmamap_sync(sc->sc_dmat, sc->sc_corb.dma_map, 0,
235 sc->sc_corb.dma_size, BUS_DMASYNC_PREWRITE);
237 /* Commit updated write pointer */
238 hda_write2(sc, HDAUDIO_MMIO_CORBWP, wp);
241 static uint32_t
242 hdaudio_rirb_dequeue(struct hdaudio_softc *sc)
244 uint16_t rirbwp;
245 uint64_t *rirb = DMA_KERNADDR(&sc->sc_rirb);
246 struct rirb_entry entry;
247 int retry;
249 for (;;) {
250 retry = HDAUDIO_RIRB_TIMEOUT;
252 rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP);
253 while (--retry > 0 && (rirbwp & 0xff) == sc->sc_rirbrp) {
254 hda_delay(10);
255 rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP);
257 if (retry == 0) {
258 hda_error(sc, "RIRB timeout\n");
259 return 0xffffffff;
262 sc->sc_rirbrp++;
263 if (sc->sc_rirbrp >= (sc->sc_rirb.dma_size / sizeof(*rirb)))
264 sc->sc_rirbrp = 0;
266 bus_dmamap_sync(sc->sc_dmat, sc->sc_rirb.dma_map, 0,
267 sc->sc_rirb.dma_size, BUS_DMASYNC_POSTREAD);
268 entry = *(struct rirb_entry *)&rirb[sc->sc_rirbrp];
269 bus_dmamap_sync(sc->sc_dmat, sc->sc_rirb.dma_map, 0,
270 sc->sc_rirb.dma_size, BUS_DMASYNC_PREREAD);
272 if (RIRB_UNSOL(&entry)) {
273 hda_print(sc, "unsolicited response: %08X %08X\n",
274 entry.resp, entry.resp_ex);
275 continue;
278 return entry.resp;
282 uint32_t
283 hdaudio_command(struct hdaudio_codec *co, int nid, uint32_t control,
284 uint32_t param)
286 struct hdaudio_softc *sc = co->co_host;
287 uint32_t result;
289 mutex_enter(&sc->sc_corb_mtx);
290 hdaudio_corb_enqueue(sc, co->co_addr, nid, control, param);
291 result = hdaudio_rirb_dequeue(sc);
292 mutex_exit(&sc->sc_corb_mtx);
294 return result;
297 static int
298 hdaudio_corb_setsize(struct hdaudio_softc *sc)
300 uint8_t corbsize;
301 bus_size_t bufsize = 0;
304 * The size of the CORB is programmable to 2, 16, or 256 entries
305 * by using the CORBSIZE register. Choose a size based on the
306 * controller capabilities, preferring a larger size when possible.
308 corbsize = hda_read1(sc, HDAUDIO_MMIO_CORBSIZE);
309 corbsize &= ~0x3;
310 if ((corbsize >> 4) & 0x4) {
311 corbsize |= 0x2;
312 bufsize = 1024;
313 } else if ((corbsize >> 4) & 0x2) {
314 corbsize |= 0x1;
315 bufsize = 64;
316 } else if ((corbsize >> 4) & 0x1) {
317 corbsize |= 0x0;
318 bufsize = 8;
319 } else {
320 hda_error(sc, "couldn't configure CORB size\n");
321 return ENXIO;
324 #if defined(HDAUDIO_DEBUG)
325 hda_print(sc, "using %d byte CORB (cap %X)\n",
326 (int)bufsize, corbsize >> 4);
327 #endif
329 sc->sc_corb.dma_size = bufsize;
330 sc->sc_corb.dma_sizereg = corbsize;
332 return 0;
335 static int
336 hdaudio_corb_config(struct hdaudio_softc *sc)
338 uint32_t corbubase, corblbase;
339 uint16_t corbrp;
340 int retry = HDAUDIO_CORB_TIMEOUT;
342 /* Program command buffer base address and size */
343 corblbase = (uint32_t)DMA_DMAADDR(&sc->sc_corb);
344 corbubase = (uint32_t)(((uint64_t)DMA_DMAADDR(&sc->sc_corb)) >> 32);
345 hda_write4(sc, HDAUDIO_MMIO_CORBLBASE, corblbase);
346 hda_write4(sc, HDAUDIO_MMIO_CORBUBASE, corbubase);
347 hda_write1(sc, HDAUDIO_MMIO_CORBSIZE, sc->sc_corb.dma_sizereg);
349 /* Clear the read and write pointers */
350 hda_write2(sc, HDAUDIO_MMIO_CORBRP, HDAUDIO_CORBRP_RP_RESET);
351 hda_write2(sc, HDAUDIO_MMIO_CORBRP, 0);
352 do {
353 hda_delay(10);
354 corbrp = hda_read2(sc, HDAUDIO_MMIO_CORBRP);
355 } while (--retry > 0 && (corbrp & HDAUDIO_CORBRP_RP_RESET) != 0);
356 if (retry == 0) {
357 hda_error(sc, "timeout resetting CORB\n");
358 return ETIME;
360 hda_write2(sc, HDAUDIO_MMIO_CORBWP, 0);
362 return 0;
365 static int
366 hdaudio_corb_stop(struct hdaudio_softc *sc)
368 uint8_t corbctl;
369 int retry = HDAUDIO_CORB_TIMEOUT;
371 /* Stop the CORB if necessary */
372 corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL);
373 if (corbctl & HDAUDIO_CORBCTL_RUN) {
374 corbctl &= ~HDAUDIO_CORBCTL_RUN;
375 hda_write4(sc, HDAUDIO_MMIO_CORBCTL, corbctl);
376 do {
377 hda_delay(10);
378 corbctl = hda_read4(sc, HDAUDIO_MMIO_CORBCTL);
379 } while (--retry > 0 && (corbctl & HDAUDIO_CORBCTL_RUN) != 0);
380 if (retry == 0) {
381 hda_error(sc, "timeout stopping CORB\n");
382 return ETIME;
386 return 0;
389 static int
390 hdaudio_corb_start(struct hdaudio_softc *sc)
392 uint8_t corbctl;
393 int retry = HDAUDIO_CORB_TIMEOUT;
395 /* Start the CORB if necessary */
396 corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL);
397 if ((corbctl & HDAUDIO_CORBCTL_RUN) == 0) {
398 corbctl |= HDAUDIO_CORBCTL_RUN;
399 hda_write4(sc, HDAUDIO_MMIO_CORBCTL, corbctl);
400 do {
401 hda_delay(10);
402 corbctl = hda_read4(sc, HDAUDIO_MMIO_CORBCTL);
403 } while (--retry > 0 && (corbctl & HDAUDIO_CORBCTL_RUN) == 0);
404 if (retry == 0) {
405 hda_error(sc, "timeout starting CORB\n");
406 return ETIME;
410 return 0;
413 static int
414 hdaudio_rirb_stop(struct hdaudio_softc *sc)
416 uint8_t rirbctl;
417 int retry = HDAUDIO_RIRB_TIMEOUT;
419 /* Stop the RIRB if necessary */
420 rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL);
421 if (rirbctl & HDAUDIO_RIRBCTL_RUN) {
422 rirbctl &= ~HDAUDIO_RIRBCTL_RUN;
423 hda_write4(sc, HDAUDIO_MMIO_RIRBCTL, rirbctl);
424 do {
425 hda_delay(10);
426 rirbctl = hda_read4(sc, HDAUDIO_MMIO_RIRBCTL);
427 } while (--retry > 0 && (rirbctl & HDAUDIO_RIRBCTL_RUN) != 0);
428 if (retry == 0) {
429 hda_error(sc, "timeout stopping RIRB\n");
430 return ETIME;
434 return 0;
437 static int
438 hdaudio_rirb_start(struct hdaudio_softc *sc)
440 uint8_t rirbctl;
441 int retry = HDAUDIO_RIRB_TIMEOUT;
443 /* Start the RIRB if necessary */
444 rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL);
445 if ((rirbctl & HDAUDIO_RIRBCTL_RUN) == 0) {
446 rirbctl |= HDAUDIO_RIRBCTL_RUN;
447 hda_write4(sc, HDAUDIO_MMIO_RIRBCTL, rirbctl);
448 do {
449 hda_delay(10);
450 rirbctl = hda_read4(sc, HDAUDIO_MMIO_RIRBCTL);
451 } while (--retry > 0 && (rirbctl & HDAUDIO_RIRBCTL_RUN) == 0);
452 if (retry == 0) {
453 hda_error(sc, "timeout starting RIRB\n");
454 return ETIME;
458 return 0;
461 static int
462 hdaudio_rirb_setsize(struct hdaudio_softc *sc)
464 uint8_t rirbsize;
465 bus_size_t bufsize = 0;
468 * The size of the RIRB is programmable to 2, 16, or 256 entries
469 * by using the RIRBSIZE register. Choose a size based on the
470 * controller capabilities, preferring a larger size when possible.
472 rirbsize = hda_read1(sc, HDAUDIO_MMIO_RIRBSIZE);
473 rirbsize &= ~0x3;
474 if ((rirbsize >> 4) & 0x4) {
475 rirbsize |= 0x2;
476 bufsize = 2048;
477 } else if ((rirbsize >> 4) & 0x2) {
478 rirbsize |= 0x1;
479 bufsize = 128;
480 } else if ((rirbsize >> 4) & 0x1) {
481 rirbsize |= 0x0;
482 bufsize = 16;
483 } else {
484 hda_error(sc, "couldn't configure RIRB size\n");
485 return ENXIO;
488 #if defined(HDAUDIO_DEBUG)
489 hda_print(sc, "using %d byte RIRB (cap %X)\n",
490 (int)bufsize, rirbsize >> 4);
491 #endif
493 sc->sc_rirb.dma_size = bufsize;
494 sc->sc_rirb.dma_sizereg = rirbsize;
496 return 0;
499 static int
500 hdaudio_rirb_config(struct hdaudio_softc *sc)
502 uint32_t rirbubase, rirblbase;
503 uint32_t rirbwp;
504 int retry = HDAUDIO_RIRB_TIMEOUT;
506 /* Program command buffer base address and size */
507 rirblbase = (uint32_t)DMA_DMAADDR(&sc->sc_rirb);
508 rirbubase = (uint32_t)(((uint64_t)DMA_DMAADDR(&sc->sc_rirb)) >> 32);
509 hda_write4(sc, HDAUDIO_MMIO_RIRBLBASE, rirblbase);
510 hda_write4(sc, HDAUDIO_MMIO_RIRBUBASE, rirbubase);
511 hda_write1(sc, HDAUDIO_MMIO_RIRBSIZE, sc->sc_rirb.dma_sizereg);
513 /* Clear the write pointer */
514 hda_write2(sc, HDAUDIO_MMIO_RIRBWP, HDAUDIO_RIRBWP_WP_RESET);
515 hda_write2(sc, HDAUDIO_MMIO_RIRBWP, 0);
516 do {
517 hda_delay(10);
518 rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP);
519 } while (--retry > 0 && (rirbwp & HDAUDIO_RIRBWP_WP_RESET) != 0);
520 if (retry == 0) {
521 hda_error(sc, "timeout resetting RIRB\n");
522 return ETIME;
524 sc->sc_rirbrp = 0;
526 return 0;
529 static int
530 hdaudio_reset(struct hdaudio_softc *sc)
532 int retry = HDAUDIO_RESET_TIMEOUT;
533 uint32_t gctl;
534 int err;
536 if ((err = hdaudio_rirb_stop(sc)) != 0) {
537 hda_error(sc, "couldn't reset because RIRB is busy\n");
538 return err;
540 if ((err = hdaudio_corb_stop(sc)) != 0) {
541 hda_error(sc, "couldn't reset because CORB is busy\n");
542 return err;
545 /* Disable wake events */
546 hda_write2(sc, HDAUDIO_MMIO_WAKEEN, 0);
548 /* Disable interrupts */
549 hda_write4(sc, HDAUDIO_MMIO_INTCTL, 0);
551 /* Clear state change status register */
552 hda_write2(sc, HDAUDIO_MMIO_STATESTS,
553 hda_read2(sc, HDAUDIO_MMIO_STATESTS));
554 hda_write1(sc, HDAUDIO_MMIO_RIRBSTS,
555 hda_read1(sc, HDAUDIO_MMIO_RIRBSTS));
557 /* If the controller isn't in reset state, initiate the transition */
558 gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL);
559 if (gctl & HDAUDIO_GCTL_CRST) {
560 gctl &= ~HDAUDIO_GCTL_CRST;
561 hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl);
562 do {
563 hda_delay(10);
564 gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL);
565 } while (--retry > 0 && (gctl & HDAUDIO_GCTL_CRST) != 0);
566 if (retry == 0) {
567 hda_error(sc, "timeout entering reset state\n");
568 return ETIME;
572 /* Now the controller is in reset state, so bring it out */
573 retry = HDAUDIO_RESET_TIMEOUT;
574 hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl | HDAUDIO_GCTL_CRST);
575 do {
576 hda_delay(10);
577 gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL);
578 } while (--retry > 0 && (gctl & HDAUDIO_GCTL_CRST) == 0);
579 if (retry == 0) {
580 hda_error(sc, "timeout leaving reset state\n");
581 return ETIME;
584 return 0;
587 static void
588 hdaudio_intr_enable(struct hdaudio_softc *sc)
590 hda_write4(sc, HDAUDIO_MMIO_INTSTS,
591 hda_read4(sc, HDAUDIO_MMIO_INTSTS));
592 hda_write4(sc, HDAUDIO_MMIO_INTCTL,
593 HDAUDIO_INTCTL_GIE | HDAUDIO_INTCTL_CIE);
596 static void
597 hdaudio_intr_disable(struct hdaudio_softc *sc)
599 hda_write4(sc, HDAUDIO_MMIO_INTCTL, 0);
602 static int
603 hdaudio_config_print(void *opaque, const char *pnp)
605 prop_dictionary_t dict = opaque;
606 uint8_t fgtype, nid;
607 uint16_t vendor, product;
608 const char *type = "unknown";
610 prop_dictionary_get_uint8(dict, "function-group-type", &fgtype);
611 prop_dictionary_get_uint8(dict, "node-id", &nid);
612 prop_dictionary_get_uint16(dict, "vendor-id", &vendor);
613 prop_dictionary_get_uint16(dict, "product-id", &product);
614 if (pnp) {
615 if (fgtype == HDAUDIO_GROUP_TYPE_AFG)
616 type = "hdafg";
617 else if (fgtype == HDAUDIO_GROUP_TYPE_VSM_FG)
618 type = "hdvsmfg";
620 aprint_normal("%s at %s", type, pnp);
622 aprint_normal(" vendor 0x%04X product 0x%04X nid 0x%02X",
623 vendor, product, nid);
625 return UNCONF;
628 static void
629 hdaudio_attach_fg(struct hdaudio_function_group *fg, prop_array_t config)
631 struct hdaudio_codec *co = fg->fg_codec;
632 struct hdaudio_softc *sc = co->co_host;
633 prop_dictionary_t args = prop_dictionary_create();
634 uint64_t fgptr = (vaddr_t)fg;
635 int locs[1];
637 prop_dictionary_set_uint8(args, "function-group-type", fg->fg_type);
638 prop_dictionary_set_uint64(args, "function-group", fgptr);
639 prop_dictionary_set_uint8(args, "node-id", fg->fg_nid);
640 prop_dictionary_set_uint16(args, "vendor-id", fg->fg_vendor);
641 prop_dictionary_set_uint16(args, "product-id", fg->fg_product);
642 if (config)
643 prop_dictionary_set(args, "pin-config", config);
645 locs[0] = fg->fg_nid;
647 fg->fg_device = config_found_sm_loc(sc->sc_dev, "hdaudiobus",
648 locs, args, hdaudio_config_print, config_stdsubmatch);
650 prop_object_release(args);
653 static void
654 hdaudio_codec_attach(struct hdaudio_codec *co)
656 #ifdef HDAUDIO_DEBUG
657 struct hdaudio_softc *sc = co->co_host;
658 #endif
659 struct hdaudio_function_group *fg;
660 uint32_t vid, rid, snc, fgrp;
661 int starting_node, num_nodes, nid;
663 if (co->co_valid == false)
664 return;
666 vid = hdaudio_command(co, 0, CORB_GET_PARAMETER, COP_VENDOR_ID);
667 rid = hdaudio_command(co, 0, CORB_GET_PARAMETER, COP_REVISION_ID);
668 snc = hdaudio_command(co, 0, CORB_GET_PARAMETER,
669 COP_SUBORDINATE_NODE_COUNT);
671 #ifdef HDAUDIO_DEBUG
672 hda_print(sc, "Codec%02X: %04X:%04X HDA %d.%d rev %d stepping %d\n",
673 co->co_addr, vid >> 16, vid & 0xffff,
674 (rid >> 20) & 0xf, (rid >> 16) & 0xf,
675 (rid >> 8) & 0xff, rid & 0xff);
676 #endif
677 starting_node = (snc >> 16) & 0xff;
678 num_nodes = snc & 0xff;
680 co->co_nfg = num_nodes;
681 co->co_fg = kmem_zalloc(co->co_nfg * sizeof(*co->co_fg), KM_SLEEP);
683 for (nid = starting_node; nid < starting_node + num_nodes; nid++) {
684 fg = &co->co_fg[nid - starting_node];
685 fg->fg_codec = co;
686 fg->fg_nid = nid;
687 fg->fg_vendor = vid >> 16;
688 fg->fg_product = vid & 0xffff;
690 fgrp = hdaudio_command(co, nid, CORB_GET_PARAMETER,
691 COP_FUNCTION_GROUP_TYPE);
692 switch (fgrp & 0xff) {
693 case 0x01: /* Audio Function Group */
694 fg->fg_type = HDAUDIO_GROUP_TYPE_AFG;
695 break;
696 case 0x02: /* Vendor Specific Modem Function Group */
697 fg->fg_type = HDAUDIO_GROUP_TYPE_VSM_FG;
698 break;
699 default:
700 /* Function group type not supported */
701 fg->fg_type = HDAUDIO_GROUP_TYPE_UNKNOWN;
702 break;
704 hdaudio_attach_fg(fg, NULL);
709 hdaudio_stream_tag(struct hdaudio_stream *st)
711 int ret = 0;
713 switch (st->st_type) {
714 case HDAUDIO_STREAM_ISS:
715 ret = 1;
716 break;
717 case HDAUDIO_STREAM_OSS:
718 ret = 2;
719 break;
720 case HDAUDIO_STREAM_BSS:
721 ret = 3;
722 break;
725 return ret;
729 hdaudio_attach(device_t dev, struct hdaudio_softc *sc)
731 int err, i;
733 KASSERT(sc->sc_memvalid == true);
735 sc->sc_dev = dev;
736 mutex_init(&sc->sc_corb_mtx, MUTEX_DEFAULT, IPL_AUDIO);
737 mutex_init(&sc->sc_stream_mtx, MUTEX_DEFAULT, IPL_AUDIO);
739 hdaudio_init(sc);
742 * Put the controller into a known state by entering and leaving
743 * CRST as necessary.
745 if ((err = hdaudio_reset(sc)) != 0)
746 goto fail;
749 * From the spec:
751 * Must wait 250us after reading CRST as a 1 before assuming that
752 * codecs have all made status change requests and have been
753 * registered by the controller.
755 * In reality, we need to wait longer than this.
757 hda_delay(HDAUDIO_CODEC_DELAY);
758 if (hdaudio_codec_probe(sc) == 0) {
759 hda_error(sc, "no codecs found\n");
760 err = ENODEV;
761 goto fail;
765 * Ensure that the device is in a known state
767 hda_write2(sc, HDAUDIO_MMIO_STATESTS, HDAUDIO_STATESTS_SDIWAKE);
768 hda_write1(sc, HDAUDIO_MMIO_RIRBSTS,
769 HDAUDIO_RIRBSTS_RIRBOIS | HDAUDIO_RIRBSTS_RINTFL);
770 hda_write4(sc, HDAUDIO_MMIO_INTSTS,
771 hda_read4(sc, HDAUDIO_MMIO_INTSTS));
772 hda_write4(sc, HDAUDIO_MMIO_DPLBASE, 0);
773 hda_write4(sc, HDAUDIO_MMIO_DPUBASE, 0);
776 * Initialize the CORB. First negotiate a command buffer size,
777 * then allocate and configure it.
779 if ((err = hdaudio_corb_setsize(sc)) != 0)
780 goto fail;
781 if ((err = hdaudio_dma_alloc(sc, &sc->sc_corb, BUS_DMA_WRITE)) != 0)
782 goto fail;
783 if ((err = hdaudio_corb_config(sc)) != 0)
784 goto fail;
787 * Initialize the RIRB.
789 if ((err = hdaudio_rirb_setsize(sc)) != 0)
790 goto fail;
791 if ((err = hdaudio_dma_alloc(sc, &sc->sc_rirb, BUS_DMA_READ)) != 0)
792 goto fail;
793 if ((err = hdaudio_rirb_config(sc)) != 0)
794 goto fail;
797 * Start the CORB and RIRB
799 if ((err = hdaudio_corb_start(sc)) != 0)
800 goto fail;
801 if ((err = hdaudio_rirb_start(sc)) != 0)
802 goto fail;
805 * Identify and attach discovered codecs
807 for (i = 0; i < HDAUDIO_MAX_CODECS; i++)
808 hdaudio_codec_attach(&sc->sc_codec[i]);
811 * Enable interrupts
813 hdaudio_intr_enable(sc);
815 fail:
816 if (err)
817 hda_error(sc, "device driver failed to attach\n");
818 return err;
822 hdaudio_detach(struct hdaudio_softc *sc, int flags)
824 /* Disable interrupts */
825 hdaudio_intr_disable(sc);
827 return 0;
830 bool
831 hdaudio_resume(struct hdaudio_softc *sc)
833 if (hdaudio_reset(sc) != 0)
834 return false;
836 hda_delay(HDAUDIO_CODEC_DELAY);
839 * Ensure that the device is in a known state
841 hda_write2(sc, HDAUDIO_MMIO_STATESTS, HDAUDIO_STATESTS_SDIWAKE);
842 hda_write1(sc, HDAUDIO_MMIO_RIRBSTS,
843 HDAUDIO_RIRBSTS_RIRBOIS | HDAUDIO_RIRBSTS_RINTFL);
844 hda_write4(sc, HDAUDIO_MMIO_INTSTS,
845 hda_read4(sc, HDAUDIO_MMIO_INTSTS));
846 hda_write4(sc, HDAUDIO_MMIO_DPLBASE, 0);
847 hda_write4(sc, HDAUDIO_MMIO_DPUBASE, 0);
849 if (hdaudio_corb_config(sc) != 0)
850 return false;
851 if (hdaudio_rirb_config(sc) != 0)
852 return false;
853 if (hdaudio_corb_start(sc) != 0)
854 return false;
855 if (hdaudio_rirb_start(sc) != 0)
856 return false;
858 hdaudio_intr_enable(sc);
860 return true;
864 hdaudio_intr(struct hdaudio_softc *sc)
866 struct hdaudio_stream *st;
867 uint32_t intsts, stream_mask;
868 int streamid = 0;
869 uint32_t rirbsts;
871 intsts = hda_read4(sc, HDAUDIO_MMIO_INTSTS);
872 if (!(intsts & HDAUDIO_INTSTS_GIS))
873 return 0;
875 if (intsts & HDAUDIO_INTSTS_CIS) {
876 rirbsts = hda_read4(sc, HDAUDIO_MMIO_RIRBSTS);
877 if (rirbsts & (HDAUDIO_RIRBSTS_RIRBOIS|HDAUDIO_RIRBSTS_RINTFL))
878 hda_write4(sc, HDAUDIO_MMIO_RIRBSTS, rirbsts);
879 hda_write4(sc, HDAUDIO_MMIO_INTSTS, HDAUDIO_INTSTS_CIS);
881 if (intsts & HDAUDIO_INTSTS_SIS_MASK) {
882 mutex_enter(&sc->sc_stream_mtx);
883 stream_mask = intsts & sc->sc_stream_mask;
884 while (streamid < HDAUDIO_MAX_STREAMS && stream_mask != 0) {
885 st = &sc->sc_stream[streamid++];
886 if ((stream_mask & 1) != 0 && st->st_intr) {
887 st->st_intr(st);
889 stream_mask >>= 1;
891 mutex_exit(&sc->sc_stream_mtx);
892 hda_write4(sc, HDAUDIO_MMIO_INTSTS, HDAUDIO_INTSTS_SIS_MASK);
895 return 1;
898 struct hdaudio_stream *
899 hdaudio_stream_establish(struct hdaudio_softc *sc,
900 enum hdaudio_stream_type type, int (*intr)(struct hdaudio_stream *),
901 void *cookie)
903 struct hdaudio_stream *st;
904 struct hdaudio_dma dma;
905 int i, err;
907 dma.dma_size = sizeof(struct hdaudio_bdl_entry) * HDAUDIO_BDL_MAX;
908 err = hdaudio_dma_alloc(sc, &dma, BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
909 if (err)
910 return NULL;
912 mutex_enter(&sc->sc_stream_mtx);
913 for (i = 0; i < HDAUDIO_MAX_STREAMS; i++) {
914 st = &sc->sc_stream[i];
915 if (st->st_enable == false)
916 break;
917 if (st->st_type != type)
918 continue;
919 if (sc->sc_stream_mask & (1 << i))
920 continue;
922 /* Allocate stream */
923 st->st_bdl = dma;
924 st->st_intr = intr;
925 st->st_cookie = cookie;
926 sc->sc_stream_mask |= (1 << i);
927 mutex_exit(&sc->sc_stream_mtx);
928 return st;
930 mutex_exit(&sc->sc_stream_mtx);
932 /* No streams of requested type available */
933 hdaudio_dma_free(sc, &dma);
934 return NULL;
937 void
938 hdaudio_stream_disestablish(struct hdaudio_stream *st)
940 struct hdaudio_softc *sc = st->st_host;
942 KASSERT(sc->sc_stream_mask & (1 << st->st_shift));
944 mutex_enter(&sc->sc_stream_mtx);
945 sc->sc_stream_mask &= ~(1 << st->st_shift);
946 st->st_intr = NULL;
947 st->st_cookie = NULL;
948 hdaudio_dma_free(sc, &st->st_bdl);
949 mutex_exit(&sc->sc_stream_mtx);
953 * Convert most of audio_params_t to stream fmt descriptor; noticably missing
954 * is the # channels bits, as this is encoded differently in codec and
955 * stream descriptors.
957 * TODO: validate that the stream and selected codecs can handle the fmt
959 uint16_t
960 hdaudio_stream_param(struct hdaudio_stream *st, const audio_params_t *param)
962 uint16_t fmt = 0;
964 switch (param->sample_rate) {
965 case 8000:
966 fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) |
967 HDAUDIO_FMT_DIV(6);
968 break;
969 case 11025:
970 fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1) |
971 HDAUDIO_FMT_DIV(4);
972 break;
973 case 16000:
974 fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) |
975 HDAUDIO_FMT_DIV(3);
976 break;
977 case 22050:
978 fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1) |
979 HDAUDIO_FMT_DIV(2);
980 break;
981 case 32000:
982 fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(2) |
983 HDAUDIO_FMT_DIV(3);
984 break;
985 case 44100:
986 fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1);
987 break;
988 case 48000:
989 fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1);
990 break;
991 case 88200:
992 fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(2);
993 break;
994 case 96000:
995 fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(2);
996 break;
997 case 176400:
998 fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(4);
999 break;
1000 case 192000:
1001 fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(4);
1002 break;
1003 default:
1004 return 0;
1007 if (param->precision == 16 && param->validbits == 8)
1008 fmt |= HDAUDIO_FMT_BITS_8_16;
1009 else if (param->precision == 16 && param->validbits == 16)
1010 fmt |= HDAUDIO_FMT_BITS_16_16;
1011 else if (param->precision == 32 && param->validbits == 20)
1012 fmt |= HDAUDIO_FMT_BITS_20_32;
1013 else if (param->precision == 32 && param->validbits == 24)
1014 fmt |= HDAUDIO_FMT_BITS_24_32;
1015 else if (param->precision == 32 && param->validbits == 32)
1016 fmt |= HDAUDIO_FMT_BITS_32_32;
1017 else
1018 return 0;
1020 return fmt;
1023 void
1024 hdaudio_stream_reset(struct hdaudio_stream *st)
1026 struct hdaudio_softc *sc = st->st_host;
1027 int snum = st->st_shift;
1028 int retry;
1029 uint8_t ctl0;
1031 ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum));
1032 ctl0 |= HDAUDIO_CTL_SRST;
1033 hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0);
1035 retry = HDAUDIO_RESET_TIMEOUT;
1036 do {
1037 ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum));
1038 if (ctl0 & HDAUDIO_CTL_SRST)
1039 break;
1040 hda_delay(10);
1041 } while (--retry > 0);
1042 if (retry == 0) {
1043 hda_error(sc, "timeout entering stream reset state\n");
1044 return;
1047 ctl0 &= ~HDAUDIO_CTL_SRST;
1048 hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0);
1050 retry = HDAUDIO_RESET_TIMEOUT;
1051 do {
1052 ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum));
1053 if (!(ctl0 & HDAUDIO_CTL_SRST))
1054 break;
1055 hda_delay(10);
1056 } while (--retry > 0);
1057 if (retry == 0) {
1058 hda_error(sc, "timeout leaving stream reset state\n");
1059 return;
1063 void
1064 hdaudio_stream_start(struct hdaudio_stream *st, int blksize,
1065 bus_size_t dmasize, const audio_params_t *params)
1067 struct hdaudio_softc *sc = st->st_host;
1068 struct hdaudio_bdl_entry *bdl;
1069 uint64_t dmaaddr;
1070 uint32_t intctl;
1071 uint16_t fmt;
1072 uint8_t ctl0, ctl2;
1073 int cnt, snum = st->st_shift;
1075 KASSERT(sc->sc_stream_mask & (1 << st->st_shift));
1076 KASSERT(st->st_data.dma_valid == true);
1077 KASSERT(st->st_bdl.dma_valid == true);
1079 hdaudio_stream_stop(st);
1080 hdaudio_stream_reset(st);
1083 * Configure buffer descriptor list
1085 dmaaddr = DMA_DMAADDR(&st->st_data);
1086 bdl = DMA_KERNADDR(&st->st_bdl);
1087 for (cnt = 0; cnt < HDAUDIO_BDL_MAX; cnt++) {
1088 bdl[cnt].address_lo = (uint32_t)dmaaddr;
1089 bdl[cnt].address_hi = dmaaddr >> 32;
1090 bdl[cnt].length = blksize;
1091 bdl[cnt].flags = HDAUDIO_BDL_ENTRY_IOC;
1092 dmaaddr += blksize;
1093 if (dmaaddr >= DMA_DMAADDR(&st->st_data) + dmasize) {
1094 cnt++;
1095 break;
1100 * Program buffer descriptor list
1102 dmaaddr = DMA_DMAADDR(&st->st_bdl);
1103 hda_write4(sc, HDAUDIO_SD_BDPL(snum), (uint32_t)dmaaddr);
1104 hda_write4(sc, HDAUDIO_SD_BDPU(snum), (uint32_t)(dmaaddr >> 32));
1105 hda_write2(sc, HDAUDIO_SD_LVI(snum), (cnt - 1) & 0xff);
1108 * Program cyclic buffer length
1110 hda_write4(sc, HDAUDIO_SD_CBL(snum), dmasize);
1113 * Program stream number (tag). Although controller hardware is
1114 * capable of transmitting any stream number (0-15), by convention
1115 * stream 0 is reserved as unused by software, so that converters
1116 * whose stream numbers have been reset to 0 do not unintentionally
1117 * decode data not intended for them.
1119 ctl2 = hda_read1(sc, HDAUDIO_SD_CTL2(snum));
1120 ctl2 &= ~0xf0;
1121 ctl2 |= hdaudio_stream_tag(st) << 4;
1122 hda_write1(sc, HDAUDIO_SD_CTL2(snum), ctl2);
1125 * Program stream format
1127 fmt = hdaudio_stream_param(st, params) |
1128 HDAUDIO_FMT_CHAN(params->channels);
1129 hda_write2(sc, HDAUDIO_SD_FMT(snum), fmt);
1132 * Switch on interrupts for this stream
1134 intctl = hda_read4(sc, HDAUDIO_MMIO_INTCTL);
1135 intctl |= (1 << st->st_shift);
1136 hda_write4(sc, HDAUDIO_MMIO_INTCTL, intctl);
1139 * Start running the stream
1141 ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum));
1142 ctl0 |= HDAUDIO_CTL_DEIE | HDAUDIO_CTL_FEIE | HDAUDIO_CTL_IOCE |
1143 HDAUDIO_CTL_RUN;
1144 hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0);
1147 void
1148 hdaudio_stream_stop(struct hdaudio_stream *st)
1150 struct hdaudio_softc *sc = st->st_host;
1151 uint32_t intctl;
1152 uint8_t ctl0;
1153 int snum = st->st_shift;
1156 * Stop running the stream
1158 ctl0 = hda_read1(sc, HDAUDIO_SD_CTL0(snum));
1159 ctl0 &= ~(HDAUDIO_CTL_DEIE | HDAUDIO_CTL_FEIE | HDAUDIO_CTL_IOCE |
1160 HDAUDIO_CTL_RUN);
1161 hda_write1(sc, HDAUDIO_SD_CTL0(snum), ctl0);
1164 * Switch off interrupts for this stream
1166 intctl = hda_read4(sc, HDAUDIO_MMIO_INTCTL);
1167 intctl &= ~(1 << st->st_shift);
1168 hda_write4(sc, HDAUDIO_MMIO_INTCTL, intctl);
1172 * /dev/hdaudioN interface
1175 static const char *
1176 hdaudioioctl_fgrp_to_cstr(enum function_group_type type)
1178 switch (type) {
1179 case HDAUDIO_GROUP_TYPE_AFG:
1180 return "afg";
1181 case HDAUDIO_GROUP_TYPE_VSM_FG:
1182 return "vsmfg";
1183 default:
1184 return "unknown";
1188 static struct hdaudio_function_group *
1189 hdaudioioctl_fgrp_lookup(struct hdaudio_softc *sc, int codecid, int nid)
1191 struct hdaudio_codec *co;
1192 struct hdaudio_function_group *fg = NULL;
1193 int i;
1195 if (codecid < 0 || codecid >= HDAUDIO_MAX_CODECS)
1196 return NULL;
1197 co = &sc->sc_codec[codecid];
1198 if (co->co_valid == false)
1199 return NULL;
1201 for (i = 0; i < co->co_nfg; i++)
1202 if (co->co_fg[i].fg_nid == nid) {
1203 fg = &co->co_fg[i];
1204 break;
1207 return fg;
1210 static int
1211 hdaudioioctl_fgrp_info(struct hdaudio_softc *sc, prop_dictionary_t request,
1212 prop_dictionary_t response)
1214 struct hdaudio_codec *co;
1215 struct hdaudio_function_group *fg;
1216 prop_array_t array;
1217 prop_dictionary_t dict;
1218 int codecid, fgid;
1220 array = prop_array_create();
1221 if (array == NULL)
1222 return ENOMEM;
1224 for (codecid = 0; codecid < HDAUDIO_MAX_CODECS; codecid++) {
1225 co = &sc->sc_codec[codecid];
1226 if (co->co_valid == false)
1227 continue;
1228 for (fgid = 0; fgid < co->co_nfg; fgid++) {
1229 fg = &co->co_fg[fgid];
1230 dict = prop_dictionary_create();
1231 if (dict == NULL)
1232 return ENOMEM;
1233 prop_dictionary_set_cstring_nocopy(dict,
1234 "type", hdaudioioctl_fgrp_to_cstr(fg->fg_type));
1235 prop_dictionary_set_int16(dict, "nid", fg->fg_nid);
1236 prop_dictionary_set_int16(dict, "codecid", codecid);
1237 prop_dictionary_set_uint16(dict, "vendor-id",
1238 fg->fg_vendor);
1239 prop_dictionary_set_uint16(dict, "product-id",
1240 fg->fg_product);
1241 prop_dictionary_set_uint32(dict, "subsystem-id",
1242 sc->sc_subsystem);
1243 if (fg->fg_device)
1244 prop_dictionary_set_cstring(dict, "device",
1245 device_xname(fg->fg_device));
1246 else
1247 prop_dictionary_set_cstring_nocopy(dict,
1248 "device", "<none>");
1249 prop_array_add(array, dict);
1253 prop_dictionary_set(response, "function-group-info", array);
1254 return 0;
1257 static int
1258 hdaudioioctl_fgrp_getconfig(struct hdaudio_softc *sc,
1259 prop_dictionary_t request, prop_dictionary_t response)
1261 struct hdaudio_function_group *fg;
1262 prop_dictionary_t dict;
1263 prop_array_t array;
1264 uint32_t nodecnt, wcap, config;
1265 int16_t codecid, nid, i;
1266 int startnode, endnode;
1268 if (!prop_dictionary_get_int16(request, "codecid", &codecid) ||
1269 !prop_dictionary_get_int16(request, "nid", &nid))
1270 return EINVAL;
1272 fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid);
1273 if (fg == NULL)
1274 return ENODEV;
1276 array = prop_array_create();
1277 if (array == NULL)
1278 return ENOMEM;
1280 nodecnt = hdaudio_command(fg->fg_codec, fg->fg_nid,
1281 CORB_GET_PARAMETER, COP_SUBORDINATE_NODE_COUNT);
1282 startnode = COP_NODECNT_STARTNODE(nodecnt);
1283 endnode = startnode + COP_NODECNT_NUMNODES(nodecnt);
1285 for (i = startnode; i < endnode; i++) {
1286 wcap = hdaudio_command(fg->fg_codec, i,
1287 CORB_GET_PARAMETER, COP_AUDIO_WIDGET_CAPABILITIES);
1288 if (COP_AWCAP_TYPE(wcap) != COP_AWCAP_TYPE_PIN_COMPLEX)
1289 continue;
1290 config = hdaudio_command(fg->fg_codec, i,
1291 CORB_GET_CONFIGURATION_DEFAULT, 0);
1292 dict = prop_dictionary_create();
1293 if (dict == NULL)
1294 return ENOMEM;
1295 prop_dictionary_set_int16(dict, "nid", i);
1296 prop_dictionary_set_uint32(dict, "config", config);
1297 prop_array_add(array, dict);
1300 prop_dictionary_set(response, "pin-config", array);
1302 return 0;
1305 static int
1306 hdaudioioctl_fgrp_setconfig(struct hdaudio_softc *sc,
1307 prop_dictionary_t request, prop_dictionary_t response)
1309 struct hdaudio_function_group *fg;
1310 prop_array_t config;
1311 int16_t codecid, nid;
1312 int err;
1314 if (!prop_dictionary_get_int16(request, "codecid", &codecid) ||
1315 !prop_dictionary_get_int16(request, "nid", &nid))
1316 return EINVAL;
1318 fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid);
1319 if (fg == NULL)
1320 return ENODEV;
1322 if (fg->fg_device) {
1323 err = config_detach(fg->fg_device, 0);
1324 if (err)
1325 return err;
1326 fg->fg_device = NULL;
1329 /* "pin-config" may be NULL, this means "use BIOS configuration" */
1330 config = prop_dictionary_get(request, "pin-config");
1331 if (config && prop_object_type(config) != PROP_TYPE_ARRAY) {
1332 prop_object_release(config);
1333 return EINVAL;
1335 hdaudio_attach_fg(fg, config);
1336 if (config)
1337 prop_object_release(config);
1339 return 0;
1342 static int
1343 hdaudio_dispatch_fgrp_ioctl(struct hdaudio_softc *sc, u_long cmd,
1344 prop_dictionary_t request, prop_dictionary_t response)
1346 struct hdaudio_function_group *fg;
1347 int16_t codecid, nid;
1348 void *fgrp_sc;
1349 int err;
1351 if (!prop_dictionary_get_int16(request, "codecid", &codecid) ||
1352 !prop_dictionary_get_int16(request, "nid", &nid))
1353 return EINVAL;
1355 fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid);
1356 if (fg == NULL)
1357 return ENODEV;
1358 fgrp_sc = device_private(fg->fg_device);
1360 switch (fg->fg_type) {
1361 case HDAUDIO_GROUP_TYPE_AFG:
1362 switch (cmd) {
1363 case HDAUDIO_FGRP_CODEC_INFO:
1364 err = hdaudio_afg_codec_info(fgrp_sc,
1365 request, response);
1366 break;
1367 case HDAUDIO_FGRP_WIDGET_INFO:
1368 err = hdaudio_afg_widget_info(fgrp_sc,
1369 request, response);
1370 break;
1371 default:
1372 err = EINVAL;
1373 break;
1375 break;
1377 default:
1378 err = EINVAL;
1379 break;
1381 return err;
1385 hdaudioopen(dev_t dev, int flag, int mode, struct lwp *l)
1387 device_t self;
1389 self = device_lookup(&hdaudio_cd, HDAUDIOUNIT(dev));
1390 if (self == NULL)
1391 return ENXIO;
1393 return 0;
1397 hdaudioclose(dev_t dev, int flag, int mode, struct lwp *l)
1399 return 0;
1403 hdaudioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
1405 struct hdaudio_softc *sc;
1406 struct plistref *pref = addr;
1407 prop_dictionary_t request, response;
1408 int err;
1410 sc = device_lookup_private(&hdaudio_cd, HDAUDIOUNIT(dev));
1411 if (sc == NULL)
1412 return ENXIO;
1414 response = prop_dictionary_create();
1415 if (response == NULL)
1416 return ENOMEM;
1418 err = prop_dictionary_copyin_ioctl(pref, cmd, &request);
1419 if (err) {
1420 prop_object_release(response);
1421 return err;
1424 switch (cmd) {
1425 case HDAUDIO_FGRP_INFO:
1426 err = hdaudioioctl_fgrp_info(sc, request, response);
1427 break;
1428 case HDAUDIO_FGRP_GETCONFIG:
1429 err = hdaudioioctl_fgrp_getconfig(sc, request, response);
1430 break;
1431 case HDAUDIO_FGRP_SETCONFIG:
1432 err = hdaudioioctl_fgrp_setconfig(sc, request, response);
1433 break;
1434 case HDAUDIO_FGRP_CODEC_INFO:
1435 case HDAUDIO_FGRP_WIDGET_INFO:
1436 err = hdaudio_dispatch_fgrp_ioctl(sc, cmd, request, response);
1437 break;
1438 default:
1439 err = EINVAL;
1440 break;
1443 if (!err)
1444 err = prop_dictionary_copyout_ioctl(pref, cmd, response);
1446 if (response)
1447 prop_object_release(response);
1448 prop_object_release(request);
1449 return err;