hdaudio.c revision 1.14 1 1.14 thorpej /* $NetBSD: hdaudio.c,v 1.14 2021/04/24 23:36:54 thorpej 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.14 thorpej __KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.14 2021/04/24 23:36:54 thorpej 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.1 jmcneill
49 1.1 jmcneill /* #define HDAUDIO_DEBUG */
50 1.1 jmcneill
51 1.1 jmcneill #define HDAUDIO_RESET_TIMEOUT 5000
52 1.1 jmcneill #define HDAUDIO_CORB_TIMEOUT 1000
53 1.1 jmcneill #define HDAUDIO_RIRB_TIMEOUT 5000
54 1.1 jmcneill
55 1.1 jmcneill #define HDAUDIO_CODEC_DELAY 1000 /* spec calls for 250 */
56 1.1 jmcneill
57 1.1 jmcneill dev_type_open(hdaudioopen);
58 1.1 jmcneill dev_type_close(hdaudioclose);
59 1.1 jmcneill dev_type_ioctl(hdaudioioctl);
60 1.1 jmcneill
61 1.1 jmcneill const struct cdevsw hdaudio_cdevsw = {
62 1.1 jmcneill .d_open = hdaudioopen,
63 1.1 jmcneill .d_close = hdaudioclose,
64 1.1 jmcneill .d_read = noread,
65 1.1 jmcneill .d_write = nowrite,
66 1.1 jmcneill .d_ioctl = hdaudioioctl,
67 1.1 jmcneill .d_stop = nostop,
68 1.1 jmcneill .d_tty = notty,
69 1.1 jmcneill .d_poll = nopoll,
70 1.1 jmcneill .d_mmap = nommap,
71 1.1 jmcneill .d_kqfilter = nokqfilter,
72 1.1 jmcneill .d_discard = nodiscard,
73 1.1 jmcneill .d_flag = D_OTHER
74 1.1 jmcneill };
75 1.1 jmcneill
76 1.1 jmcneill extern struct cfdriver hdaudio_cd;
77 1.1 jmcneill
78 1.1 jmcneill #define HDAUDIOUNIT(x) minor((x))
79 1.1 jmcneill
80 1.1 jmcneill static void
81 1.1 jmcneill hdaudio_stream_init(struct hdaudio_softc *sc, int nis, int nos, int nbidir)
82 1.1 jmcneill {
83 1.1 jmcneill int i, cnt = 0;
84 1.1 jmcneill
85 1.1 jmcneill for (i = 0; i < nis && cnt < HDAUDIO_MAX_STREAMS; i++) {
86 1.1 jmcneill sc->sc_stream[cnt].st_host = sc;
87 1.1 jmcneill sc->sc_stream[cnt].st_enable = true;
88 1.1 jmcneill sc->sc_stream[cnt].st_shift = cnt;
89 1.1 jmcneill sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_ISS;
90 1.1 jmcneill }
91 1.1 jmcneill for (i = 0; i < nos && cnt < HDAUDIO_MAX_STREAMS; i++) {
92 1.1 jmcneill sc->sc_stream[cnt].st_host = sc;
93 1.1 jmcneill sc->sc_stream[cnt].st_enable = true;
94 1.1 jmcneill sc->sc_stream[cnt].st_shift = cnt;
95 1.1 jmcneill sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_OSS;
96 1.1 jmcneill }
97 1.1 jmcneill for (i = 0; i < nbidir && cnt < HDAUDIO_MAX_STREAMS; i++) {
98 1.1 jmcneill sc->sc_stream[cnt].st_host = sc;
99 1.1 jmcneill sc->sc_stream[cnt].st_enable = true;
100 1.1 jmcneill sc->sc_stream[cnt].st_shift = cnt;
101 1.1 jmcneill sc->sc_stream[cnt++].st_type = HDAUDIO_STREAM_BSS;
102 1.1 jmcneill }
103 1.1 jmcneill
104 1.1 jmcneill for (i = 0; i < cnt; i++)
105 1.1 jmcneill hdaudio_stream_stop(&sc->sc_stream[i]);
106 1.1 jmcneill
107 1.1 jmcneill sc->sc_stream_mask = 0;
108 1.1 jmcneill }
109 1.1 jmcneill
110 1.1 jmcneill static void
111 1.1 jmcneill hdaudio_codec_init(struct hdaudio_softc *sc)
112 1.1 jmcneill {
113 1.1 jmcneill int i;
114 1.1 jmcneill
115 1.1 jmcneill for (i = 0; i < HDAUDIO_MAX_CODECS; i++) {
116 1.1 jmcneill sc->sc_codec[i].co_addr = i;
117 1.1 jmcneill sc->sc_codec[i].co_host = sc;
118 1.1 jmcneill }
119 1.1 jmcneill }
120 1.1 jmcneill
121 1.1 jmcneill static void
122 1.1 jmcneill hdaudio_init(struct hdaudio_softc *sc)
123 1.1 jmcneill {
124 1.10 jmcneill const uint8_t vmaj = hda_read1(sc, HDAUDIO_MMIO_VMAJ);
125 1.10 jmcneill const uint8_t vmin = hda_read1(sc, HDAUDIO_MMIO_VMIN);
126 1.10 jmcneill const uint16_t gcap = hda_read2(sc, HDAUDIO_MMIO_GCAP);
127 1.10 jmcneill const int nis = HDAUDIO_GCAP_ISS(gcap);
128 1.10 jmcneill const int nos = HDAUDIO_GCAP_OSS(gcap);
129 1.10 jmcneill const int nbidir = HDAUDIO_GCAP_BSS(gcap);
130 1.10 jmcneill const int nsdo = HDAUDIO_GCAP_NSDO(gcap);
131 1.10 jmcneill const int addr64 = HDAUDIO_GCAP_64OK(gcap);
132 1.1 jmcneill
133 1.10 jmcneill hda_print(sc, "HDA ver. %d.%d, OSS %d, ISS %d, BSS %d, SDO %d%s\n",
134 1.10 jmcneill vmaj, vmin, nos, nis, nbidir, nsdo, addr64 ? ", 64-bit" : "");
135 1.1 jmcneill
136 1.1 jmcneill /* Initialize codecs and streams */
137 1.1 jmcneill hdaudio_codec_init(sc);
138 1.1 jmcneill hdaudio_stream_init(sc, nis, nos, nbidir);
139 1.1 jmcneill }
140 1.1 jmcneill
141 1.1 jmcneill static int
142 1.1 jmcneill hdaudio_codec_probe(struct hdaudio_softc *sc)
143 1.1 jmcneill {
144 1.1 jmcneill uint16_t statests;
145 1.1 jmcneill int codecid;
146 1.1 jmcneill
147 1.1 jmcneill statests = hda_read2(sc, HDAUDIO_MMIO_STATESTS);
148 1.1 jmcneill for (codecid = 0; codecid < HDAUDIO_MAX_CODECS; codecid++)
149 1.1 jmcneill if (statests & (1 << codecid))
150 1.1 jmcneill sc->sc_codec[codecid].co_valid = true;
151 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_STATESTS, statests);
152 1.1 jmcneill
153 1.1 jmcneill return statests;
154 1.1 jmcneill }
155 1.1 jmcneill
156 1.1 jmcneill int
157 1.1 jmcneill hdaudio_dma_alloc(struct hdaudio_softc *sc, struct hdaudio_dma *dma,
158 1.1 jmcneill int flags)
159 1.1 jmcneill {
160 1.1 jmcneill int err;
161 1.1 jmcneill
162 1.1 jmcneill KASSERT(dma->dma_size > 0);
163 1.1 jmcneill
164 1.1 jmcneill err = bus_dmamem_alloc(sc->sc_dmat, dma->dma_size, 128, 0,
165 1.1 jmcneill dma->dma_segs, sizeof(dma->dma_segs) / sizeof(dma->dma_segs[0]),
166 1.1 jmcneill &dma->dma_nsegs, BUS_DMA_WAITOK);
167 1.1 jmcneill if (err)
168 1.1 jmcneill return err;
169 1.1 jmcneill err = bus_dmamem_map(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs,
170 1.1 jmcneill dma->dma_size, &dma->dma_addr, BUS_DMA_WAITOK | flags);
171 1.1 jmcneill if (err)
172 1.1 jmcneill goto free;
173 1.1 jmcneill err = bus_dmamap_create(sc->sc_dmat, dma->dma_size, dma->dma_nsegs,
174 1.1 jmcneill dma->dma_size, 0, BUS_DMA_WAITOK, &dma->dma_map);
175 1.1 jmcneill if (err)
176 1.1 jmcneill goto unmap;
177 1.1 jmcneill err = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_addr,
178 1.1 jmcneill dma->dma_size, NULL, BUS_DMA_WAITOK | flags);
179 1.1 jmcneill if (err)
180 1.1 jmcneill goto destroy;
181 1.1 jmcneill
182 1.12 jmcneill memset(dma->dma_addr, 0, dma->dma_size);
183 1.12 jmcneill bus_dmamap_sync(sc->sc_dmat, dma->dma_map, 0, dma->dma_size,
184 1.12 jmcneill BUS_DMASYNC_PREWRITE);
185 1.12 jmcneill
186 1.1 jmcneill dma->dma_valid = true;
187 1.1 jmcneill return 0;
188 1.1 jmcneill
189 1.1 jmcneill destroy:
190 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
191 1.1 jmcneill unmap:
192 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size);
193 1.1 jmcneill free:
194 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs);
195 1.1 jmcneill
196 1.1 jmcneill dma->dma_valid = false;
197 1.1 jmcneill return err;
198 1.1 jmcneill }
199 1.1 jmcneill
200 1.1 jmcneill void
201 1.1 jmcneill hdaudio_dma_free(struct hdaudio_softc *sc, struct hdaudio_dma *dma)
202 1.1 jmcneill {
203 1.1 jmcneill if (dma->dma_valid == false)
204 1.1 jmcneill return;
205 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, dma->dma_map);
206 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
207 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size);
208 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs);
209 1.1 jmcneill dma->dma_valid = false;
210 1.1 jmcneill }
211 1.1 jmcneill
212 1.1 jmcneill static void
213 1.1 jmcneill hdaudio_corb_enqueue(struct hdaudio_softc *sc, int addr, int nid,
214 1.1 jmcneill uint32_t control, uint32_t param)
215 1.1 jmcneill {
216 1.1 jmcneill uint32_t *corb = DMA_KERNADDR(&sc->sc_corb);
217 1.1 jmcneill uint32_t verb;
218 1.1 jmcneill uint16_t corbrp;
219 1.1 jmcneill int wp;
220 1.1 jmcneill
221 1.1 jmcneill /* Build command */
222 1.1 jmcneill verb = (addr << 28) | (nid << 20) | (control << 8) | param;
223 1.1 jmcneill
224 1.1 jmcneill /* Fetch and update write pointer */
225 1.1 jmcneill corbrp = hda_read2(sc, HDAUDIO_MMIO_CORBWP);
226 1.1 jmcneill wp = (corbrp & 0xff) + 1;
227 1.1 jmcneill if (wp >= (sc->sc_corb.dma_size / sizeof(*corb)))
228 1.1 jmcneill wp = 0;
229 1.1 jmcneill
230 1.1 jmcneill /* Enqueue command */
231 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_corb.dma_map, 0,
232 1.1 jmcneill sc->sc_corb.dma_size, BUS_DMASYNC_POSTWRITE);
233 1.1 jmcneill corb[wp] = verb;
234 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_corb.dma_map, 0,
235 1.1 jmcneill sc->sc_corb.dma_size, BUS_DMASYNC_PREWRITE);
236 1.1 jmcneill
237 1.1 jmcneill /* Commit updated write pointer */
238 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBWP, wp);
239 1.1 jmcneill }
240 1.1 jmcneill
241 1.1 jmcneill static void
242 1.1 jmcneill hdaudio_rirb_unsol(struct hdaudio_softc *sc, struct rirb_entry *entry)
243 1.1 jmcneill {
244 1.1 jmcneill struct hdaudio_codec *co;
245 1.1 jmcneill struct hdaudio_function_group *fg;
246 1.1 jmcneill uint8_t codecid = RIRB_CODEC_ID(entry);
247 1.1 jmcneill unsigned int i;
248 1.1 jmcneill
249 1.1 jmcneill if (codecid >= HDAUDIO_MAX_CODECS) {
250 1.1 jmcneill hda_error(sc, "unsol: codec id 0x%02x out of range\n", codecid);
251 1.1 jmcneill return;
252 1.1 jmcneill }
253 1.1 jmcneill co = &sc->sc_codec[codecid];
254 1.1 jmcneill if (sc->sc_codec[codecid].co_valid == false) {
255 1.1 jmcneill hda_error(sc, "unsol: codec id 0x%02x not valid\n", codecid);
256 1.1 jmcneill return;
257 1.1 jmcneill }
258 1.1 jmcneill
259 1.1 jmcneill for (i = 0; i < co->co_nfg; i++) {
260 1.1 jmcneill fg = &co->co_fg[i];
261 1.1 jmcneill if (fg->fg_device && fg->fg_unsol)
262 1.1 jmcneill fg->fg_unsol(fg->fg_device, entry->resp);
263 1.1 jmcneill }
264 1.1 jmcneill }
265 1.1 jmcneill
266 1.1 jmcneill static uint32_t
267 1.1 jmcneill hdaudio_rirb_dequeue(struct hdaudio_softc *sc, bool unsol)
268 1.1 jmcneill {
269 1.1 jmcneill uint16_t rirbwp;
270 1.1 jmcneill uint64_t *rirb = DMA_KERNADDR(&sc->sc_rirb);
271 1.1 jmcneill struct rirb_entry entry;
272 1.1 jmcneill int retry;
273 1.1 jmcneill
274 1.1 jmcneill for (;;) {
275 1.1 jmcneill retry = HDAUDIO_RIRB_TIMEOUT;
276 1.1 jmcneill
277 1.1 jmcneill rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP);
278 1.1 jmcneill while (--retry > 0 && (rirbwp & 0xff) == sc->sc_rirbrp) {
279 1.1 jmcneill if (unsol) {
280 1.1 jmcneill /* don't wait for more unsol events */
281 1.1 jmcneill hda_trace(sc, "unsol: rirb empty\n");
282 1.1 jmcneill return 0xffffffff;
283 1.1 jmcneill }
284 1.1 jmcneill hda_delay(10);
285 1.1 jmcneill rirbwp = hda_read2(sc, HDAUDIO_MMIO_RIRBWP);
286 1.1 jmcneill }
287 1.1 jmcneill if (retry == 0) {
288 1.1 jmcneill hda_error(sc, "RIRB timeout\n");
289 1.1 jmcneill return 0xffffffff;
290 1.1 jmcneill }
291 1.1 jmcneill
292 1.1 jmcneill sc->sc_rirbrp++;
293 1.1 jmcneill if (sc->sc_rirbrp >= (sc->sc_rirb.dma_size / sizeof(*rirb)))
294 1.1 jmcneill sc->sc_rirbrp = 0;
295 1.1 jmcneill
296 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_rirb.dma_map, 0,
297 1.1 jmcneill sc->sc_rirb.dma_size, BUS_DMASYNC_POSTREAD);
298 1.1 jmcneill entry = *(struct rirb_entry *)&rirb[sc->sc_rirbrp];
299 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_rirb.dma_map, 0,
300 1.1 jmcneill sc->sc_rirb.dma_size, BUS_DMASYNC_PREREAD);
301 1.1 jmcneill
302 1.1 jmcneill hda_trace(sc, "%s: response %08X %08X\n",
303 1.1 jmcneill unsol ? "unsol" : "cmd ",
304 1.1 jmcneill entry.resp, entry.resp_ex);
305 1.1 jmcneill
306 1.1 jmcneill if (RIRB_UNSOL(&entry)) {
307 1.1 jmcneill hdaudio_rirb_unsol(sc, &entry);
308 1.1 jmcneill continue;
309 1.1 jmcneill }
310 1.1 jmcneill
311 1.1 jmcneill return entry.resp;
312 1.1 jmcneill }
313 1.1 jmcneill }
314 1.1 jmcneill
315 1.1 jmcneill uint32_t
316 1.1 jmcneill hdaudio_command(struct hdaudio_codec *co, int nid, uint32_t control,
317 1.1 jmcneill uint32_t param)
318 1.1 jmcneill {
319 1.1 jmcneill uint32_t result;
320 1.1 jmcneill struct hdaudio_softc *sc = co->co_host;
321 1.1 jmcneill mutex_enter(&sc->sc_corb_mtx);
322 1.1 jmcneill result = hdaudio_command_unlocked(co, nid, control, param);
323 1.1 jmcneill mutex_exit(&sc->sc_corb_mtx);
324 1.1 jmcneill return result;
325 1.1 jmcneill }
326 1.1 jmcneill
327 1.1 jmcneill uint32_t
328 1.1 jmcneill hdaudio_command_unlocked(struct hdaudio_codec *co, int nid, uint32_t control,
329 1.1 jmcneill uint32_t param)
330 1.1 jmcneill {
331 1.1 jmcneill struct hdaudio_softc *sc = co->co_host;
332 1.1 jmcneill uint32_t result;
333 1.1 jmcneill
334 1.1 jmcneill hda_trace(sc, "cmd : request %08X %08X (%02X)\n",
335 1.1 jmcneill control, param, nid);
336 1.1 jmcneill hdaudio_corb_enqueue(sc, co->co_addr, nid, control, param);
337 1.1 jmcneill result = hdaudio_rirb_dequeue(sc, false);
338 1.1 jmcneill
339 1.8 jmcneill /* Clear response interrupt status */
340 1.8 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS, hda_read1(sc, HDAUDIO_MMIO_RIRBSTS));
341 1.8 jmcneill
342 1.1 jmcneill return result;
343 1.1 jmcneill }
344 1.1 jmcneill
345 1.1 jmcneill static int
346 1.1 jmcneill hdaudio_corb_setsize(struct hdaudio_softc *sc)
347 1.1 jmcneill {
348 1.1 jmcneill uint8_t corbsize;
349 1.1 jmcneill bus_size_t bufsize = 0;
350 1.1 jmcneill
351 1.1 jmcneill /*
352 1.1 jmcneill * The size of the CORB is programmable to 2, 16, or 256 entries
353 1.1 jmcneill * by using the CORBSIZE register. Choose a size based on the
354 1.1 jmcneill * controller capabilities, preferring a larger size when possible.
355 1.1 jmcneill */
356 1.1 jmcneill corbsize = hda_read1(sc, HDAUDIO_MMIO_CORBSIZE);
357 1.1 jmcneill corbsize &= ~0x3;
358 1.1 jmcneill if ((corbsize >> 4) & 0x4) {
359 1.1 jmcneill corbsize |= 0x2;
360 1.1 jmcneill bufsize = 1024;
361 1.1 jmcneill } else if ((corbsize >> 4) & 0x2) {
362 1.1 jmcneill corbsize |= 0x1;
363 1.1 jmcneill bufsize = 64;
364 1.1 jmcneill } else if ((corbsize >> 4) & 0x1) {
365 1.1 jmcneill corbsize |= 0x0;
366 1.1 jmcneill bufsize = 8;
367 1.1 jmcneill } else {
368 1.1 jmcneill hda_error(sc, "couldn't configure CORB size\n");
369 1.1 jmcneill return ENXIO;
370 1.1 jmcneill }
371 1.1 jmcneill
372 1.1 jmcneill #if defined(HDAUDIO_DEBUG)
373 1.1 jmcneill hda_print(sc, "using %d byte CORB (cap %X)\n",
374 1.1 jmcneill (int)bufsize, corbsize >> 4);
375 1.1 jmcneill #endif
376 1.1 jmcneill
377 1.1 jmcneill sc->sc_corb.dma_size = bufsize;
378 1.1 jmcneill sc->sc_corb.dma_sizereg = corbsize;
379 1.1 jmcneill
380 1.1 jmcneill return 0;
381 1.1 jmcneill }
382 1.1 jmcneill
383 1.1 jmcneill static int
384 1.1 jmcneill hdaudio_corb_config(struct hdaudio_softc *sc)
385 1.1 jmcneill {
386 1.1 jmcneill uint32_t corbubase, corblbase;
387 1.1 jmcneill uint16_t corbrp;
388 1.1 jmcneill int retry = HDAUDIO_CORB_TIMEOUT;
389 1.1 jmcneill
390 1.1 jmcneill /* Program command buffer base address and size */
391 1.1 jmcneill corblbase = (uint32_t)DMA_DMAADDR(&sc->sc_corb);
392 1.1 jmcneill corbubase = (uint32_t)(((uint64_t)DMA_DMAADDR(&sc->sc_corb)) >> 32);
393 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_CORBLBASE, corblbase);
394 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_CORBUBASE, corbubase);
395 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_CORBSIZE, sc->sc_corb.dma_sizereg);
396 1.1 jmcneill
397 1.1 jmcneill /* Clear the read and write pointers */
398 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBRP, HDAUDIO_CORBRP_RP_RESET);
399 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBRP, 0);
400 1.1 jmcneill do {
401 1.1 jmcneill hda_delay(10);
402 1.1 jmcneill corbrp = hda_read2(sc, HDAUDIO_MMIO_CORBRP);
403 1.1 jmcneill } while (--retry > 0 && (corbrp & HDAUDIO_CORBRP_RP_RESET) != 0);
404 1.1 jmcneill if (retry == 0) {
405 1.1 jmcneill hda_error(sc, "timeout resetting CORB\n");
406 1.1 jmcneill return ETIME;
407 1.1 jmcneill }
408 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_CORBWP, 0);
409 1.1 jmcneill
410 1.1 jmcneill return 0;
411 1.1 jmcneill }
412 1.1 jmcneill
413 1.1 jmcneill static int
414 1.1 jmcneill hdaudio_corb_stop(struct hdaudio_softc *sc)
415 1.1 jmcneill {
416 1.1 jmcneill uint8_t corbctl;
417 1.1 jmcneill int retry = HDAUDIO_CORB_TIMEOUT;
418 1.1 jmcneill
419 1.1 jmcneill /* Stop the CORB if necessary */
420 1.1 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL);
421 1.1 jmcneill if (corbctl & HDAUDIO_CORBCTL_RUN) {
422 1.1 jmcneill corbctl &= ~HDAUDIO_CORBCTL_RUN;
423 1.7 jmcneill hda_write1(sc, HDAUDIO_MMIO_CORBCTL, corbctl);
424 1.1 jmcneill do {
425 1.1 jmcneill hda_delay(10);
426 1.7 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL);
427 1.1 jmcneill } while (--retry > 0 && (corbctl & HDAUDIO_CORBCTL_RUN) != 0);
428 1.1 jmcneill if (retry == 0) {
429 1.1 jmcneill hda_error(sc, "timeout stopping CORB\n");
430 1.1 jmcneill return ETIME;
431 1.1 jmcneill }
432 1.1 jmcneill }
433 1.1 jmcneill
434 1.1 jmcneill return 0;
435 1.1 jmcneill }
436 1.1 jmcneill
437 1.1 jmcneill static int
438 1.1 jmcneill hdaudio_corb_start(struct hdaudio_softc *sc)
439 1.1 jmcneill {
440 1.1 jmcneill uint8_t corbctl;
441 1.1 jmcneill int retry = HDAUDIO_CORB_TIMEOUT;
442 1.1 jmcneill
443 1.1 jmcneill /* Start the CORB if necessary */
444 1.1 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL);
445 1.1 jmcneill if ((corbctl & HDAUDIO_CORBCTL_RUN) == 0) {
446 1.1 jmcneill corbctl |= HDAUDIO_CORBCTL_RUN;
447 1.7 jmcneill hda_write1(sc, HDAUDIO_MMIO_CORBCTL, corbctl);
448 1.1 jmcneill do {
449 1.1 jmcneill hda_delay(10);
450 1.7 jmcneill corbctl = hda_read1(sc, HDAUDIO_MMIO_CORBCTL);
451 1.1 jmcneill } while (--retry > 0 && (corbctl & HDAUDIO_CORBCTL_RUN) == 0);
452 1.1 jmcneill if (retry == 0) {
453 1.1 jmcneill hda_error(sc, "timeout starting CORB\n");
454 1.1 jmcneill return ETIME;
455 1.1 jmcneill }
456 1.1 jmcneill }
457 1.1 jmcneill
458 1.1 jmcneill return 0;
459 1.1 jmcneill }
460 1.1 jmcneill
461 1.1 jmcneill static int
462 1.1 jmcneill hdaudio_rirb_stop(struct hdaudio_softc *sc)
463 1.1 jmcneill {
464 1.1 jmcneill uint8_t rirbctl;
465 1.1 jmcneill int retry = HDAUDIO_RIRB_TIMEOUT;
466 1.1 jmcneill
467 1.1 jmcneill /* Stop the RIRB if necessary */
468 1.1 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL);
469 1.1 jmcneill if (rirbctl & (HDAUDIO_RIRBCTL_RUN|HDAUDIO_RIRBCTL_ROI_EN)) {
470 1.1 jmcneill rirbctl &= ~HDAUDIO_RIRBCTL_RUN;
471 1.1 jmcneill rirbctl &= ~HDAUDIO_RIRBCTL_ROI_EN;
472 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBCTL, rirbctl);
473 1.1 jmcneill do {
474 1.1 jmcneill hda_delay(10);
475 1.1 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL);
476 1.1 jmcneill } while (--retry > 0 && (rirbctl & HDAUDIO_RIRBCTL_RUN) != 0);
477 1.1 jmcneill if (retry == 0) {
478 1.1 jmcneill hda_error(sc, "timeout stopping RIRB\n");
479 1.1 jmcneill return ETIME;
480 1.1 jmcneill }
481 1.1 jmcneill }
482 1.1 jmcneill
483 1.1 jmcneill return 0;
484 1.1 jmcneill }
485 1.1 jmcneill
486 1.1 jmcneill static int
487 1.1 jmcneill hdaudio_rirb_start(struct hdaudio_softc *sc)
488 1.1 jmcneill {
489 1.1 jmcneill uint8_t rirbctl;
490 1.1 jmcneill int retry = HDAUDIO_RIRB_TIMEOUT;
491 1.1 jmcneill
492 1.8 jmcneill /* Set the RIRB interrupt count */
493 1.8 jmcneill hda_write2(sc, HDAUDIO_MMIO_RINTCNT, 1);
494 1.8 jmcneill
495 1.8 jmcneill /* Start the RIRB */
496 1.1 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL);
497 1.8 jmcneill rirbctl |= HDAUDIO_RIRBCTL_RUN;
498 1.8 jmcneill rirbctl |= HDAUDIO_RIRBCTL_INT_EN;
499 1.8 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBCTL, rirbctl);
500 1.8 jmcneill do {
501 1.8 jmcneill hda_delay(10);
502 1.8 jmcneill rirbctl = hda_read1(sc, HDAUDIO_MMIO_RIRBCTL);
503 1.8 jmcneill } while (--retry > 0 && (rirbctl & HDAUDIO_RIRBCTL_RUN) == 0);
504 1.8 jmcneill if (retry == 0) {
505 1.8 jmcneill hda_error(sc, "timeout starting RIRB\n");
506 1.8 jmcneill return ETIME;
507 1.1 jmcneill }
508 1.1 jmcneill
509 1.1 jmcneill return 0;
510 1.1 jmcneill }
511 1.1 jmcneill
512 1.1 jmcneill static int
513 1.1 jmcneill hdaudio_rirb_setsize(struct hdaudio_softc *sc)
514 1.1 jmcneill {
515 1.1 jmcneill uint8_t rirbsize;
516 1.1 jmcneill bus_size_t bufsize = 0;
517 1.1 jmcneill
518 1.1 jmcneill /*
519 1.1 jmcneill * The size of the RIRB is programmable to 2, 16, or 256 entries
520 1.1 jmcneill * by using the RIRBSIZE register. Choose a size based on the
521 1.1 jmcneill * controller capabilities, preferring a larger size when possible.
522 1.1 jmcneill */
523 1.1 jmcneill rirbsize = hda_read1(sc, HDAUDIO_MMIO_RIRBSIZE);
524 1.1 jmcneill rirbsize &= ~0x3;
525 1.1 jmcneill if ((rirbsize >> 4) & 0x4) {
526 1.1 jmcneill rirbsize |= 0x2;
527 1.1 jmcneill bufsize = 2048;
528 1.1 jmcneill } else if ((rirbsize >> 4) & 0x2) {
529 1.1 jmcneill rirbsize |= 0x1;
530 1.1 jmcneill bufsize = 128;
531 1.1 jmcneill } else if ((rirbsize >> 4) & 0x1) {
532 1.1 jmcneill rirbsize |= 0x0;
533 1.1 jmcneill bufsize = 16;
534 1.1 jmcneill } else {
535 1.1 jmcneill hda_error(sc, "couldn't configure RIRB size\n");
536 1.1 jmcneill return ENXIO;
537 1.1 jmcneill }
538 1.1 jmcneill
539 1.1 jmcneill #if defined(HDAUDIO_DEBUG)
540 1.1 jmcneill hda_print(sc, "using %d byte RIRB (cap %X)\n",
541 1.1 jmcneill (int)bufsize, rirbsize >> 4);
542 1.1 jmcneill #endif
543 1.1 jmcneill
544 1.1 jmcneill sc->sc_rirb.dma_size = bufsize;
545 1.1 jmcneill sc->sc_rirb.dma_sizereg = rirbsize;
546 1.1 jmcneill
547 1.1 jmcneill return 0;
548 1.1 jmcneill }
549 1.1 jmcneill
550 1.1 jmcneill static int
551 1.1 jmcneill hdaudio_rirb_config(struct hdaudio_softc *sc)
552 1.1 jmcneill {
553 1.1 jmcneill uint32_t rirbubase, rirblbase;
554 1.1 jmcneill
555 1.1 jmcneill /* Program command buffer base address and size */
556 1.1 jmcneill rirblbase = (uint32_t)DMA_DMAADDR(&sc->sc_rirb);
557 1.1 jmcneill rirbubase = (uint32_t)(((uint64_t)DMA_DMAADDR(&sc->sc_rirb)) >> 32);
558 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_RIRBLBASE, rirblbase);
559 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_RIRBUBASE, rirbubase);
560 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSIZE, sc->sc_rirb.dma_sizereg);
561 1.1 jmcneill
562 1.1 jmcneill /* Clear the write pointer */
563 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_RIRBWP, HDAUDIO_RIRBWP_WP_RESET);
564 1.1 jmcneill sc->sc_rirbrp = 0;
565 1.1 jmcneill
566 1.1 jmcneill return 0;
567 1.1 jmcneill }
568 1.1 jmcneill
569 1.1 jmcneill static int
570 1.1 jmcneill hdaudio_reset(struct hdaudio_softc *sc)
571 1.1 jmcneill {
572 1.1 jmcneill int retry = HDAUDIO_RESET_TIMEOUT;
573 1.1 jmcneill uint32_t gctl;
574 1.1 jmcneill int err;
575 1.1 jmcneill
576 1.1 jmcneill if ((err = hdaudio_rirb_stop(sc)) != 0) {
577 1.1 jmcneill hda_error(sc, "couldn't reset because RIRB is busy\n");
578 1.1 jmcneill return err;
579 1.1 jmcneill }
580 1.1 jmcneill if ((err = hdaudio_corb_stop(sc)) != 0) {
581 1.1 jmcneill hda_error(sc, "couldn't reset because CORB is busy\n");
582 1.1 jmcneill return err;
583 1.1 jmcneill }
584 1.1 jmcneill
585 1.1 jmcneill /* Disable wake events */
586 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_WAKEEN, 0);
587 1.1 jmcneill
588 1.1 jmcneill /* Disable interrupts */
589 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, 0);
590 1.1 jmcneill
591 1.1 jmcneill /* Clear state change status register */
592 1.1 jmcneill hda_write2(sc, HDAUDIO_MMIO_STATESTS,
593 1.1 jmcneill hda_read2(sc, HDAUDIO_MMIO_STATESTS));
594 1.1 jmcneill hda_write1(sc, HDAUDIO_MMIO_RIRBSTS,
595 1.1 jmcneill hda_read1(sc, HDAUDIO_MMIO_RIRBSTS));
596 1.1 jmcneill
597 1.6 jmcneill /* Put the controller into reset state */
598 1.1 jmcneill gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL);
599 1.6 jmcneill gctl &= ~HDAUDIO_GCTL_CRST;
600 1.6 jmcneill hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl);
601 1.6 jmcneill do {
602 1.6 jmcneill hda_delay(10);
603 1.6 jmcneill gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL);
604 1.6 jmcneill } while (--retry > 0 && (gctl & HDAUDIO_GCTL_CRST) != 0);
605 1.6 jmcneill if (retry == 0) {
606 1.6 jmcneill hda_error(sc, "timeout entering reset state\n");
607 1.6 jmcneill return ETIME;
608 1.1 jmcneill }
609 1.1 jmcneill
610 1.6 jmcneill hda_delay(1000);
611 1.6 jmcneill
612 1.1 jmcneill /* Now the controller is in reset state, so bring it out */
613 1.1 jmcneill retry = HDAUDIO_RESET_TIMEOUT;
614 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl | HDAUDIO_GCTL_CRST);
615 1.1 jmcneill do {
616 1.1 jmcneill hda_delay(10);
617 1.1 jmcneill gctl = hda_read4(sc, HDAUDIO_MMIO_GCTL);
618 1.1 jmcneill } while (--retry > 0 && (gctl & HDAUDIO_GCTL_CRST) == 0);
619 1.1 jmcneill if (retry == 0) {
620 1.1 jmcneill hda_error(sc, "timeout leaving reset state\n");
621 1.1 jmcneill return ETIME;
622 1.1 jmcneill }
623 1.1 jmcneill
624 1.6 jmcneill hda_delay(2000);
625 1.6 jmcneill
626 1.1 jmcneill /* Accept unsolicited responses */
627 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_GCTL, gctl | HDAUDIO_GCTL_UNSOL_EN);
628 1.1 jmcneill
629 1.1 jmcneill return 0;
630 1.1 jmcneill }
631 1.1 jmcneill
632 1.1 jmcneill static void
633 1.1 jmcneill hdaudio_intr_enable(struct hdaudio_softc *sc)
634 1.1 jmcneill {
635 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTSTS,
636 1.1 jmcneill hda_read4(sc, HDAUDIO_MMIO_INTSTS));
637 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL,
638 1.1 jmcneill HDAUDIO_INTCTL_GIE | HDAUDIO_INTCTL_CIE);
639 1.1 jmcneill }
640 1.1 jmcneill
641 1.1 jmcneill static void
642 1.1 jmcneill hdaudio_intr_disable(struct hdaudio_softc *sc)
643 1.1 jmcneill {
644 1.1 jmcneill hda_write4(sc, HDAUDIO_MMIO_INTCTL, 0);
645 1.1 jmcneill }
646 1.1 jmcneill
647 1.1 jmcneill static int
648 1.1 jmcneill hdaudio_config_print(void *opaque, const char *pnp)
649 1.1 jmcneill {
650 1.1 jmcneill prop_dictionary_t dict = opaque;
651 1.1 jmcneill uint8_t fgtype, nid;
652 1.1 jmcneill uint16_t vendor, product;
653 1.1 jmcneill const char *type = "unknown";
654 1.1 jmcneill
655 1.1 jmcneill prop_dictionary_get_uint8(dict, "function-group-type", &fgtype);
656 1.1 jmcneill prop_dictionary_get_uint8(dict, "node-id", &nid);
657 1.1 jmcneill prop_dictionary_get_uint16(dict, "vendor-id", &vendor);
658 1.1 jmcneill prop_dictionary_get_uint16(dict, "product-id", &product);
659 1.1 jmcneill if (pnp) {
660 1.1 jmcneill if (fgtype == HDAUDIO_GROUP_TYPE_AFG)
661 1.1 jmcneill type = "hdafg";
662 1.1 jmcneill else if (fgtype == HDAUDIO_GROUP_TYPE_VSM_FG)
663 1.1 jmcneill type = "hdvsmfg";
664 1.1 jmcneill
665 1.1 jmcneill aprint_normal("%s at %s", type, pnp);
666 1.1 jmcneill }
667 1.1 jmcneill aprint_debug(" vendor 0x%04X product 0x%04X nid 0x%02X",
668 1.1 jmcneill vendor, product, nid);
669 1.1 jmcneill
670 1.1 jmcneill return UNCONF;
671 1.1 jmcneill }
672 1.1 jmcneill
673 1.1 jmcneill static void
674 1.1 jmcneill hdaudio_attach_fg(struct hdaudio_function_group *fg, prop_array_t config)
675 1.1 jmcneill {
676 1.1 jmcneill struct hdaudio_codec *co = fg->fg_codec;
677 1.1 jmcneill struct hdaudio_softc *sc = co->co_host;
678 1.1 jmcneill prop_dictionary_t args = prop_dictionary_create();
679 1.1 jmcneill uint64_t fgptr = (vaddr_t)fg;
680 1.1 jmcneill int locs[1];
681 1.1 jmcneill
682 1.1 jmcneill prop_dictionary_set_uint8(args, "function-group-type", fg->fg_type);
683 1.1 jmcneill prop_dictionary_set_uint64(args, "function-group", fgptr);
684 1.1 jmcneill prop_dictionary_set_uint8(args, "node-id", fg->fg_nid);
685 1.1 jmcneill prop_dictionary_set_uint16(args, "vendor-id", fg->fg_vendor);
686 1.1 jmcneill prop_dictionary_set_uint16(args, "product-id", fg->fg_product);
687 1.1 jmcneill if (config)
688 1.1 jmcneill prop_dictionary_set(args, "pin-config", config);
689 1.1 jmcneill
690 1.1 jmcneill locs[0] = fg->fg_nid;
691 1.1 jmcneill
692 1.14 thorpej fg->fg_device = config_found(sc->sc_dev, args, hdaudio_config_print,
693 1.14 thorpej CFARG_SUBMATCH, config_stdsubmatch,
694 1.14 thorpej CFARG_LOCATORS, locs,
695 1.14 thorpej CFARG_EOL);
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.1 jmcneill * Convert most of audio_params_t to stream fmt descriptor; noticably 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.5 pgoyette error = devsw_detach(NULL, &hdaudio_cdevsw);
1640 1.5 pgoyette if (error) {
1641 1.5 pgoyette config_cfdriver_attach(&hdaudio_cd);
1642 1.5 pgoyette break;
1643 1.5 pgoyette }
1644 1.1 jmcneill #endif
1645 1.5 pgoyette break;
1646 1.1 jmcneill default:
1647 1.5 pgoyette error = ENOTTY;
1648 1.5 pgoyette break;
1649 1.1 jmcneill }
1650 1.5 pgoyette return error;
1651 1.1 jmcneill }
1652 1.1 jmcneill
1653 1.1 jmcneill DEV_VERBOSE_DEFINE(hdaudio);
1654