1 /* $NetBSD: hdaudio.c,v 1.4 2009/09/07 16:35:02 jmcneill Exp $ */
4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk>
5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
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
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
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>
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
,
65 extern struct cfdriver hdaudio_cd
;
67 #define HDAUDIOUNIT(x) minor((x))
70 hdaudio_stream_init(struct hdaudio_softc
*sc
, int nis
, int nos
, int nbidir
)
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;
100 hdaudio_codec_init(struct hdaudio_softc
*sc
)
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
;
111 hdaudio_init(struct hdaudio_softc
*sc
)
114 int nos
, nis
, nbidir
;
115 #if defined(HDAUDIO_DEBUG)
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
);
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;
140 hda_print(sc
, "OSS %d ISS %d BSS %d SDO %d%s\n",
141 nos
, nis
, nbidir
, nsdo
, addr64
? " 64-bit" : "");
146 hdaudio_codec_probe(struct hdaudio_softc
*sc
)
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
);
161 hdaudio_dma_alloc(struct hdaudio_softc
*sc
, struct hdaudio_dma
*dma
,
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
);
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
);
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
);
181 err
= bus_dmamap_load(sc
->sc_dmat
, dma
->dma_map
, dma
->dma_addr
,
182 dma
->dma_size
, NULL
, BUS_DMA_WAITOK
| flags
);
186 dma
->dma_valid
= true;
190 bus_dmamap_destroy(sc
->sc_dmat
, dma
->dma_map
);
192 bus_dmamem_unmap(sc
->sc_dmat
, dma
->dma_addr
, dma
->dma_size
);
194 bus_dmamem_free(sc
->sc_dmat
, dma
->dma_segs
, dma
->dma_nsegs
);
196 dma
->dma_valid
= false;
201 hdaudio_dma_free(struct hdaudio_softc
*sc
, struct hdaudio_dma
*dma
)
203 if (dma
->dma_valid
== false)
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;
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
);
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
)))
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
);
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
);
242 hdaudio_rirb_dequeue(struct hdaudio_softc
*sc
)
245 uint64_t *rirb
= DMA_KERNADDR(&sc
->sc_rirb
);
246 struct rirb_entry entry
;
250 retry
= HDAUDIO_RIRB_TIMEOUT
;
252 rirbwp
= hda_read2(sc
, HDAUDIO_MMIO_RIRBWP
);
253 while (--retry
> 0 && (rirbwp
& 0xff) == sc
->sc_rirbrp
) {
255 rirbwp
= hda_read2(sc
, HDAUDIO_MMIO_RIRBWP
);
258 hda_error(sc
, "RIRB timeout\n");
263 if (sc
->sc_rirbrp
>= (sc
->sc_rirb
.dma_size
/ sizeof(*rirb
)))
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
);
283 hdaudio_command(struct hdaudio_codec
*co
, int nid
, uint32_t control
,
286 struct hdaudio_softc
*sc
= co
->co_host
;
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
);
298 hdaudio_corb_setsize(struct hdaudio_softc
*sc
)
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
);
310 if ((corbsize
>> 4) & 0x4) {
313 } else if ((corbsize
>> 4) & 0x2) {
316 } else if ((corbsize
>> 4) & 0x1) {
320 hda_error(sc
, "couldn't configure CORB size\n");
324 #if defined(HDAUDIO_DEBUG)
325 hda_print(sc
, "using %d byte CORB (cap %X)\n",
326 (int)bufsize
, corbsize
>> 4);
329 sc
->sc_corb
.dma_size
= bufsize
;
330 sc
->sc_corb
.dma_sizereg
= corbsize
;
336 hdaudio_corb_config(struct hdaudio_softc
*sc
)
338 uint32_t corbubase
, corblbase
;
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);
354 corbrp
= hda_read2(sc
, HDAUDIO_MMIO_CORBRP
);
355 } while (--retry
> 0 && (corbrp
& HDAUDIO_CORBRP_RP_RESET
) != 0);
357 hda_error(sc
, "timeout resetting CORB\n");
360 hda_write2(sc
, HDAUDIO_MMIO_CORBWP
, 0);
366 hdaudio_corb_stop(struct hdaudio_softc
*sc
)
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
);
378 corbctl
= hda_read4(sc
, HDAUDIO_MMIO_CORBCTL
);
379 } while (--retry
> 0 && (corbctl
& HDAUDIO_CORBCTL_RUN
) != 0);
381 hda_error(sc
, "timeout stopping CORB\n");
390 hdaudio_corb_start(struct hdaudio_softc
*sc
)
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
);
402 corbctl
= hda_read4(sc
, HDAUDIO_MMIO_CORBCTL
);
403 } while (--retry
> 0 && (corbctl
& HDAUDIO_CORBCTL_RUN
) == 0);
405 hda_error(sc
, "timeout starting CORB\n");
414 hdaudio_rirb_stop(struct hdaudio_softc
*sc
)
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
);
426 rirbctl
= hda_read4(sc
, HDAUDIO_MMIO_RIRBCTL
);
427 } while (--retry
> 0 && (rirbctl
& HDAUDIO_RIRBCTL_RUN
) != 0);
429 hda_error(sc
, "timeout stopping RIRB\n");
438 hdaudio_rirb_start(struct hdaudio_softc
*sc
)
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
);
450 rirbctl
= hda_read4(sc
, HDAUDIO_MMIO_RIRBCTL
);
451 } while (--retry
> 0 && (rirbctl
& HDAUDIO_RIRBCTL_RUN
) == 0);
453 hda_error(sc
, "timeout starting RIRB\n");
462 hdaudio_rirb_setsize(struct hdaudio_softc
*sc
)
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
);
474 if ((rirbsize
>> 4) & 0x4) {
477 } else if ((rirbsize
>> 4) & 0x2) {
480 } else if ((rirbsize
>> 4) & 0x1) {
484 hda_error(sc
, "couldn't configure RIRB size\n");
488 #if defined(HDAUDIO_DEBUG)
489 hda_print(sc
, "using %d byte RIRB (cap %X)\n",
490 (int)bufsize
, rirbsize
>> 4);
493 sc
->sc_rirb
.dma_size
= bufsize
;
494 sc
->sc_rirb
.dma_sizereg
= rirbsize
;
500 hdaudio_rirb_config(struct hdaudio_softc
*sc
)
502 uint32_t rirbubase
, rirblbase
;
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);
518 rirbwp
= hda_read2(sc
, HDAUDIO_MMIO_RIRBWP
);
519 } while (--retry
> 0 && (rirbwp
& HDAUDIO_RIRBWP_WP_RESET
) != 0);
521 hda_error(sc
, "timeout resetting RIRB\n");
530 hdaudio_reset(struct hdaudio_softc
*sc
)
532 int retry
= HDAUDIO_RESET_TIMEOUT
;
536 if ((err
= hdaudio_rirb_stop(sc
)) != 0) {
537 hda_error(sc
, "couldn't reset because RIRB is busy\n");
540 if ((err
= hdaudio_corb_stop(sc
)) != 0) {
541 hda_error(sc
, "couldn't reset because CORB is busy\n");
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
);
564 gctl
= hda_read4(sc
, HDAUDIO_MMIO_GCTL
);
565 } while (--retry
> 0 && (gctl
& HDAUDIO_GCTL_CRST
) != 0);
567 hda_error(sc
, "timeout entering reset state\n");
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
);
577 gctl
= hda_read4(sc
, HDAUDIO_MMIO_GCTL
);
578 } while (--retry
> 0 && (gctl
& HDAUDIO_GCTL_CRST
) == 0);
580 hda_error(sc
, "timeout leaving reset state\n");
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
);
597 hdaudio_intr_disable(struct hdaudio_softc
*sc
)
599 hda_write4(sc
, HDAUDIO_MMIO_INTCTL
, 0);
603 hdaudio_config_print(void *opaque
, const char *pnp
)
605 prop_dictionary_t dict
= opaque
;
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
);
615 if (fgtype
== HDAUDIO_GROUP_TYPE_AFG
)
617 else if (fgtype
== HDAUDIO_GROUP_TYPE_VSM_FG
)
620 aprint_normal("%s at %s", type
, pnp
);
622 aprint_normal(" vendor 0x%04X product 0x%04X nid 0x%02X",
623 vendor
, product
, nid
);
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
;
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
);
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
);
654 hdaudio_codec_attach(struct hdaudio_codec
*co
)
657 struct hdaudio_softc
*sc
= co
->co_host
;
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)
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
);
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);
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
];
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
;
696 case 0x02: /* Vendor Specific Modem Function Group */
697 fg
->fg_type
= HDAUDIO_GROUP_TYPE_VSM_FG
;
700 /* Function group type not supported */
701 fg
->fg_type
= HDAUDIO_GROUP_TYPE_UNKNOWN
;
704 hdaudio_attach_fg(fg
, NULL
);
709 hdaudio_stream_tag(struct hdaudio_stream
*st
)
713 switch (st
->st_type
) {
714 case HDAUDIO_STREAM_ISS
:
717 case HDAUDIO_STREAM_OSS
:
720 case HDAUDIO_STREAM_BSS
:
729 hdaudio_attach(device_t dev
, struct hdaudio_softc
*sc
)
733 KASSERT(sc
->sc_memvalid
== true);
736 mutex_init(&sc
->sc_corb_mtx
, MUTEX_DEFAULT
, IPL_AUDIO
);
737 mutex_init(&sc
->sc_stream_mtx
, MUTEX_DEFAULT
, IPL_AUDIO
);
742 * Put the controller into a known state by entering and leaving
745 if ((err
= hdaudio_reset(sc
)) != 0)
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");
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)
781 if ((err
= hdaudio_dma_alloc(sc
, &sc
->sc_corb
, BUS_DMA_WRITE
)) != 0)
783 if ((err
= hdaudio_corb_config(sc
)) != 0)
787 * Initialize the RIRB.
789 if ((err
= hdaudio_rirb_setsize(sc
)) != 0)
791 if ((err
= hdaudio_dma_alloc(sc
, &sc
->sc_rirb
, BUS_DMA_READ
)) != 0)
793 if ((err
= hdaudio_rirb_config(sc
)) != 0)
797 * Start the CORB and RIRB
799 if ((err
= hdaudio_corb_start(sc
)) != 0)
801 if ((err
= hdaudio_rirb_start(sc
)) != 0)
805 * Identify and attach discovered codecs
807 for (i
= 0; i
< HDAUDIO_MAX_CODECS
; i
++)
808 hdaudio_codec_attach(&sc
->sc_codec
[i
]);
813 hdaudio_intr_enable(sc
);
817 hda_error(sc
, "device driver failed to attach\n");
822 hdaudio_detach(struct hdaudio_softc
*sc
, int flags
)
824 /* Disable interrupts */
825 hdaudio_intr_disable(sc
);
831 hdaudio_resume(struct hdaudio_softc
*sc
)
833 if (hdaudio_reset(sc
) != 0)
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)
851 if (hdaudio_rirb_config(sc
) != 0)
853 if (hdaudio_corb_start(sc
) != 0)
855 if (hdaudio_rirb_start(sc
) != 0)
858 hdaudio_intr_enable(sc
);
864 hdaudio_intr(struct hdaudio_softc
*sc
)
866 struct hdaudio_stream
*st
;
867 uint32_t intsts
, stream_mask
;
871 intsts
= hda_read4(sc
, HDAUDIO_MMIO_INTSTS
);
872 if (!(intsts
& HDAUDIO_INTSTS_GIS
))
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
) {
891 mutex_exit(&sc
->sc_stream_mtx
);
892 hda_write4(sc
, HDAUDIO_MMIO_INTSTS
, HDAUDIO_INTSTS_SIS_MASK
);
898 struct hdaudio_stream
*
899 hdaudio_stream_establish(struct hdaudio_softc
*sc
,
900 enum hdaudio_stream_type type
, int (*intr
)(struct hdaudio_stream
*),
903 struct hdaudio_stream
*st
;
904 struct hdaudio_dma dma
;
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
);
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)
917 if (st
->st_type
!= type
)
919 if (sc
->sc_stream_mask
& (1 << i
))
922 /* Allocate stream */
925 st
->st_cookie
= cookie
;
926 sc
->sc_stream_mask
|= (1 << i
);
927 mutex_exit(&sc
->sc_stream_mtx
);
930 mutex_exit(&sc
->sc_stream_mtx
);
932 /* No streams of requested type available */
933 hdaudio_dma_free(sc
, &dma
);
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
);
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
960 hdaudio_stream_param(struct hdaudio_stream
*st
, const audio_params_t
*param
)
964 switch (param
->sample_rate
) {
966 fmt
|= HDAUDIO_FMT_BASE_48
| HDAUDIO_FMT_MULT(1) |
970 fmt
|= HDAUDIO_FMT_BASE_44
| HDAUDIO_FMT_MULT(1) |
974 fmt
|= HDAUDIO_FMT_BASE_48
| HDAUDIO_FMT_MULT(1) |
978 fmt
|= HDAUDIO_FMT_BASE_44
| HDAUDIO_FMT_MULT(1) |
982 fmt
|= HDAUDIO_FMT_BASE_48
| HDAUDIO_FMT_MULT(2) |
986 fmt
|= HDAUDIO_FMT_BASE_44
| HDAUDIO_FMT_MULT(1);
989 fmt
|= HDAUDIO_FMT_BASE_48
| HDAUDIO_FMT_MULT(1);
992 fmt
|= HDAUDIO_FMT_BASE_44
| HDAUDIO_FMT_MULT(2);
995 fmt
|= HDAUDIO_FMT_BASE_48
| HDAUDIO_FMT_MULT(2);
998 fmt
|= HDAUDIO_FMT_BASE_44
| HDAUDIO_FMT_MULT(4);
1001 fmt
|= HDAUDIO_FMT_BASE_48
| HDAUDIO_FMT_MULT(4);
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
;
1024 hdaudio_stream_reset(struct hdaudio_stream
*st
)
1026 struct hdaudio_softc
*sc
= st
->st_host
;
1027 int snum
= st
->st_shift
;
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
;
1037 ctl0
= hda_read1(sc
, HDAUDIO_SD_CTL0(snum
));
1038 if (ctl0
& HDAUDIO_CTL_SRST
)
1041 } while (--retry
> 0);
1043 hda_error(sc
, "timeout entering stream reset state\n");
1047 ctl0
&= ~HDAUDIO_CTL_SRST
;
1048 hda_write1(sc
, HDAUDIO_SD_CTL0(snum
), ctl0
);
1050 retry
= HDAUDIO_RESET_TIMEOUT
;
1052 ctl0
= hda_read1(sc
, HDAUDIO_SD_CTL0(snum
));
1053 if (!(ctl0
& HDAUDIO_CTL_SRST
))
1056 } while (--retry
> 0);
1058 hda_error(sc
, "timeout leaving stream reset state\n");
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
;
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
;
1093 if (dmaaddr
>= DMA_DMAADDR(&st
->st_data
) + dmasize
) {
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
));
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
|
1144 hda_write1(sc
, HDAUDIO_SD_CTL0(snum
), ctl0
);
1148 hdaudio_stream_stop(struct hdaudio_stream
*st
)
1150 struct hdaudio_softc
*sc
= st
->st_host
;
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
|
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
1176 hdaudioioctl_fgrp_to_cstr(enum function_group_type type
)
1179 case HDAUDIO_GROUP_TYPE_AFG
:
1181 case HDAUDIO_GROUP_TYPE_VSM_FG
:
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
;
1195 if (codecid
< 0 || codecid
>= HDAUDIO_MAX_CODECS
)
1197 co
= &sc
->sc_codec
[codecid
];
1198 if (co
->co_valid
== false)
1201 for (i
= 0; i
< co
->co_nfg
; i
++)
1202 if (co
->co_fg
[i
].fg_nid
== nid
) {
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
;
1217 prop_dictionary_t dict
;
1220 array
= prop_array_create();
1224 for (codecid
= 0; codecid
< HDAUDIO_MAX_CODECS
; codecid
++) {
1225 co
= &sc
->sc_codec
[codecid
];
1226 if (co
->co_valid
== false)
1228 for (fgid
= 0; fgid
< co
->co_nfg
; fgid
++) {
1229 fg
= &co
->co_fg
[fgid
];
1230 dict
= prop_dictionary_create();
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",
1239 prop_dictionary_set_uint16(dict
, "product-id",
1241 prop_dictionary_set_uint32(dict
, "subsystem-id",
1244 prop_dictionary_set_cstring(dict
, "device",
1245 device_xname(fg
->fg_device
));
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
);
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
;
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
))
1272 fg
= hdaudioioctl_fgrp_lookup(sc
, codecid
, nid
);
1276 array
= prop_array_create();
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
)
1290 config
= hdaudio_command(fg
->fg_codec
, i
,
1291 CORB_GET_CONFIGURATION_DEFAULT
, 0);
1292 dict
= prop_dictionary_create();
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
);
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
;
1314 if (!prop_dictionary_get_int16(request
, "codecid", &codecid
) ||
1315 !prop_dictionary_get_int16(request
, "nid", &nid
))
1318 fg
= hdaudioioctl_fgrp_lookup(sc
, codecid
, nid
);
1322 if (fg
->fg_device
) {
1323 err
= config_detach(fg
->fg_device
, 0);
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
);
1335 hdaudio_attach_fg(fg
, config
);
1337 prop_object_release(config
);
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
;
1351 if (!prop_dictionary_get_int16(request
, "codecid", &codecid
) ||
1352 !prop_dictionary_get_int16(request
, "nid", &nid
))
1355 fg
= hdaudioioctl_fgrp_lookup(sc
, codecid
, nid
);
1358 fgrp_sc
= device_private(fg
->fg_device
);
1360 switch (fg
->fg_type
) {
1361 case HDAUDIO_GROUP_TYPE_AFG
:
1363 case HDAUDIO_FGRP_CODEC_INFO
:
1364 err
= hdaudio_afg_codec_info(fgrp_sc
,
1367 case HDAUDIO_FGRP_WIDGET_INFO
:
1368 err
= hdaudio_afg_widget_info(fgrp_sc
,
1385 hdaudioopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
1389 self
= device_lookup(&hdaudio_cd
, HDAUDIOUNIT(dev
));
1397 hdaudioclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
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
;
1410 sc
= device_lookup_private(&hdaudio_cd
, HDAUDIOUNIT(dev
));
1414 response
= prop_dictionary_create();
1415 if (response
== NULL
)
1418 err
= prop_dictionary_copyin_ioctl(pref
, cmd
, &request
);
1420 prop_object_release(response
);
1425 case HDAUDIO_FGRP_INFO
:
1426 err
= hdaudioioctl_fgrp_info(sc
, request
, response
);
1428 case HDAUDIO_FGRP_GETCONFIG
:
1429 err
= hdaudioioctl_fgrp_getconfig(sc
, request
, response
);
1431 case HDAUDIO_FGRP_SETCONFIG
:
1432 err
= hdaudioioctl_fgrp_setconfig(sc
, request
, response
);
1434 case HDAUDIO_FGRP_CODEC_INFO
:
1435 case HDAUDIO_FGRP_WIDGET_INFO
:
1436 err
= hdaudio_dispatch_fgrp_ioctl(sc
, cmd
, request
, response
);
1444 err
= prop_dictionary_copyout_ioctl(pref
, cmd
, response
);
1447 prop_object_release(response
);
1448 prop_object_release(request
);