xref: /freebsd/sys/dev/sound/pci/hdspe.c (revision c8e7f78a3d28ff6e6223ed136ada8e1e2f34965e)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2012-2016 Ruslan Bukin <br@bsdpad.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * RME HDSPe driver for FreeBSD.
31  * Supported cards: AIO, RayDAT.
32  */
33 
34 #include <sys/types.h>
35 #include <sys/sysctl.h>
36 
37 #include <dev/sound/pcm/sound.h>
38 #include <dev/sound/pci/hdspe.h>
39 #include <dev/sound/chip.h>
40 
41 #include <dev/pci/pcireg.h>
42 #include <dev/pci/pcivar.h>
43 
44 #include <mixer_if.h>
45 
46 static struct hdspe_clock_source hdspe_clock_source_table_rd[] = {
47 	{ "internal", 0 << 1 | 1, HDSPE_STATUS1_CLOCK(15),       0,       0 },
48 	{ "word",     0 << 1 | 0, HDSPE_STATUS1_CLOCK( 0), 1 << 24, 1 << 25 },
49 	{ "aes",      1 << 1 | 0, HDSPE_STATUS1_CLOCK( 1),  1 << 0,  1 << 8 },
50 	{ "spdif",    2 << 1 | 0, HDSPE_STATUS1_CLOCK( 2),  1 << 1,  1 << 9 },
51 	{ "adat1",    3 << 1 | 0, HDSPE_STATUS1_CLOCK( 3),  1 << 2, 1 << 10 },
52 	{ "adat2",    4 << 1 | 0, HDSPE_STATUS1_CLOCK( 4),  1 << 3, 1 << 11 },
53 	{ "adat3",    5 << 1 | 0, HDSPE_STATUS1_CLOCK( 5),  1 << 4, 1 << 12 },
54 	{ "adat4",    6 << 1 | 0, HDSPE_STATUS1_CLOCK( 6),  1 << 5, 1 << 13 },
55 	{ "tco",      9 << 1 | 0, HDSPE_STATUS1_CLOCK( 9), 1 << 26, 1 << 27 },
56 	{ "sync_in", 10 << 1 | 0, HDSPE_STATUS1_CLOCK(10),       0,       0 },
57 	{ NULL,       0 << 1 | 0, HDSPE_STATUS1_CLOCK( 0),       0,       0 },
58 };
59 
60 static struct hdspe_clock_source hdspe_clock_source_table_aio[] = {
61 	{ "internal", 0 << 1 | 1, HDSPE_STATUS1_CLOCK(15),       0,       0 },
62 	{ "word",     0 << 1 | 0, HDSPE_STATUS1_CLOCK( 0), 1 << 24, 1 << 25 },
63 	{ "aes",      1 << 1 | 0, HDSPE_STATUS1_CLOCK( 1),  1 << 0,  1 << 8 },
64 	{ "spdif",    2 << 1 | 0, HDSPE_STATUS1_CLOCK( 2),  1 << 1,  1 << 9 },
65 	{ "adat",     3 << 1 | 0, HDSPE_STATUS1_CLOCK( 3),  1 << 2, 1 << 10 },
66 	{ "tco",      9 << 1 | 0, HDSPE_STATUS1_CLOCK( 9), 1 << 26, 1 << 27 },
67 	{ "sync_in", 10 << 1 | 0, HDSPE_STATUS1_CLOCK(10),       0,       0 },
68 	{ NULL,       0 << 1 | 0, HDSPE_STATUS1_CLOCK( 0),       0,       0 },
69 };
70 
71 static struct hdspe_channel chan_map_aio[] = {
72 	{  0,  1,   "line", 1, 1 },
73 	{  6,  7,  "phone", 1, 0 },
74 	{  8,  9,    "aes", 1, 1 },
75 	{ 10, 11, "s/pdif", 1, 1 },
76 	{ 12, 16,   "adat", 1, 1 },
77 
78 	/* Single or double speed. */
79 	{ 14, 18,   "adat", 1, 1 },
80 
81 	/* Single speed only. */
82 	{ 13, 15,   "adat", 1, 1 },
83 	{ 17, 19,   "adat", 1, 1 },
84 
85 	{  0,  0,     NULL, 0, 0 },
86 };
87 
88 static struct hdspe_channel chan_map_rd[] = {
89 	{   0, 1,    "aes", 1, 1 },
90 	{   2, 3, "s/pdif", 1, 1 },
91 	{   4, 5,   "adat", 1, 1 },
92 	{   6, 7,   "adat", 1, 1 },
93 	{   8, 9,   "adat", 1, 1 },
94 	{ 10, 11,   "adat", 1, 1 },
95 
96 	/* Single or double speed. */
97 	{ 12, 13,   "adat", 1, 1 },
98 	{ 14, 15,   "adat", 1, 1 },
99 	{ 16, 17,   "adat", 1, 1 },
100 	{ 18, 19,   "adat", 1, 1 },
101 
102 	/* Single speed only. */
103 	{ 20, 21,   "adat", 1, 1 },
104 	{ 22, 23,   "adat", 1, 1 },
105 	{ 24, 25,   "adat", 1, 1 },
106 	{ 26, 27,   "adat", 1, 1 },
107 	{ 28, 29,   "adat", 1, 1 },
108 	{ 30, 31,   "adat", 1, 1 },
109 	{ 32, 33,   "adat", 1, 1 },
110 	{ 34, 35,   "adat", 1, 1 },
111 
112 	{ 0,  0,      NULL, 0, 0 },
113 };
114 
115 static void
116 hdspe_intr(void *p)
117 {
118 	struct sc_pcminfo *scp;
119 	struct sc_info *sc;
120 	device_t *devlist;
121 	int devcount;
122 	int status;
123 	int err;
124 	int i;
125 
126 	sc = (struct sc_info *)p;
127 
128 	snd_mtxlock(sc->lock);
129 
130 	status = hdspe_read_1(sc, HDSPE_STATUS_REG);
131 	if (status & HDSPE_AUDIO_IRQ_PENDING) {
132 		if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0)
133 			return;
134 
135 		for (i = 0; i < devcount; i++) {
136 			scp = device_get_ivars(devlist[i]);
137 			if (scp->ih != NULL)
138 				scp->ih(scp);
139 		}
140 
141 		hdspe_write_1(sc, HDSPE_INTERRUPT_ACK, 0);
142 		free(devlist, M_TEMP);
143 	}
144 
145 	snd_mtxunlock(sc->lock);
146 }
147 
148 static void
149 hdspe_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
150 {
151 #if 0
152 	device_printf(sc->dev, "hdspe_dmapsetmap()\n");
153 #endif
154 }
155 
156 static int
157 hdspe_alloc_resources(struct sc_info *sc)
158 {
159 
160 	/* Allocate resource. */
161 	sc->csid = PCIR_BAR(0);
162 	sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY,
163 	    &sc->csid, RF_ACTIVE);
164 
165 	if (!sc->cs) {
166 		device_printf(sc->dev, "Unable to map SYS_RES_MEMORY.\n");
167 		return (ENXIO);
168 	}
169 
170 	sc->cst = rman_get_bustag(sc->cs);
171 	sc->csh = rman_get_bushandle(sc->cs);
172 
173 	/* Allocate interrupt resource. */
174 	sc->irqid = 0;
175 	sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid,
176 	    RF_ACTIVE | RF_SHAREABLE);
177 
178 	if (!sc->irq ||
179 	    bus_setup_intr(sc->dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV,
180 		NULL, hdspe_intr, sc, &sc->ih)) {
181 		device_printf(sc->dev, "Unable to alloc interrupt resource.\n");
182 		return (ENXIO);
183 	}
184 
185 	/* Allocate DMA resources. */
186 	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
187 		/*alignment*/4,
188 		/*boundary*/0,
189 		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
190 		/*highaddr*/BUS_SPACE_MAXADDR,
191 		/*filter*/NULL,
192 		/*filterarg*/NULL,
193 		/*maxsize*/2 * HDSPE_DMASEGSIZE,
194 		/*nsegments*/2,
195 		/*maxsegsz*/HDSPE_DMASEGSIZE,
196 		/*flags*/0,
197 		/*lockfunc*/NULL,
198 		/*lockarg*/NULL,
199 		/*dmatag*/&sc->dmat) != 0) {
200 		device_printf(sc->dev, "Unable to create dma tag.\n");
201 		return (ENXIO);
202 	}
203 
204 	sc->bufsize = HDSPE_DMASEGSIZE;
205 
206 	/* pbuf (play buffer). */
207 	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_WAITOK,
208 	    &sc->pmap)) {
209 		device_printf(sc->dev, "Can't alloc pbuf.\n");
210 		return (ENXIO);
211 	}
212 
213 	if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize,
214 	    hdspe_dmapsetmap, sc, BUS_DMA_NOWAIT)) {
215 		device_printf(sc->dev, "Can't load pbuf.\n");
216 		return (ENXIO);
217 	}
218 
219 	/* rbuf (rec buffer). */
220 	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_WAITOK,
221 	    &sc->rmap)) {
222 		device_printf(sc->dev, "Can't alloc rbuf.\n");
223 		return (ENXIO);
224 	}
225 
226 	if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize,
227 	    hdspe_dmapsetmap, sc, BUS_DMA_NOWAIT)) {
228 		device_printf(sc->dev, "Can't load rbuf.\n");
229 		return (ENXIO);
230 	}
231 
232 	bzero(sc->pbuf, sc->bufsize);
233 	bzero(sc->rbuf, sc->bufsize);
234 
235 	return (0);
236 }
237 
238 static void
239 hdspe_map_dmabuf(struct sc_info *sc)
240 {
241 	uint32_t paddr, raddr;
242 	int i;
243 
244 	paddr = vtophys(sc->pbuf);
245 	raddr = vtophys(sc->rbuf);
246 
247 	for (i = 0; i < HDSPE_MAX_SLOTS * 16; i++) {
248 		hdspe_write_4(sc, HDSPE_PAGE_ADDR_BUF_OUT + 4 * i,
249                     paddr + i * 4096);
250 		hdspe_write_4(sc, HDSPE_PAGE_ADDR_BUF_IN + 4 * i,
251                     raddr + i * 4096);
252 	}
253 }
254 
255 static int
256 hdspe_sysctl_clock_preference(SYSCTL_HANDLER_ARGS)
257 {
258 	struct sc_info *sc;
259 	struct hdspe_clock_source *clock_table, *clock;
260 	char buf[16] = "invalid";
261 	int error;
262 	uint32_t setting;
263 
264 	sc = oidp->oid_arg1;
265 
266 	/* Select sync ports table for device type. */
267 	if (sc->type == HDSPE_AIO)
268 		clock_table = hdspe_clock_source_table_aio;
269 	else if (sc->type == HDSPE_RAYDAT)
270 		clock_table = hdspe_clock_source_table_rd;
271 	else
272 		return (ENXIO);
273 
274 	/* Extract preferred clock source from settings register. */
275 	setting = sc->settings_register & HDSPE_SETTING_CLOCK_MASK;
276 	for (clock = clock_table; clock->name != NULL; ++clock) {
277 		if (clock->setting == setting)
278 			break;
279 	}
280 	if (clock->name != NULL)
281 		strlcpy(buf, clock->name, sizeof(buf));
282 
283 	/* Process sysctl string request. */
284 	error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
285 	if (error != 0 || req->newptr == NULL)
286 		return (error);
287 
288 	/* Find clock source matching the sysctl string. */
289 	for (clock = clock_table; clock->name != NULL; ++clock) {
290 		if (strncasecmp(buf, clock->name, sizeof(buf)) == 0)
291 			break;
292 	}
293 
294 	/* Set preferred clock source in settings register. */
295 	if (clock->name != NULL) {
296 		setting = clock->setting & HDSPE_SETTING_CLOCK_MASK;
297 		snd_mtxlock(sc->lock);
298 		sc->settings_register &= ~HDSPE_SETTING_CLOCK_MASK;
299 		sc->settings_register |= setting;
300 		hdspe_write_4(sc, HDSPE_SETTINGS_REG, sc->settings_register);
301 		snd_mtxunlock(sc->lock);
302 	}
303 	return (0);
304 }
305 
306 static int
307 hdspe_sysctl_clock_source(SYSCTL_HANDLER_ARGS)
308 {
309 	struct sc_info *sc;
310 	struct hdspe_clock_source *clock_table, *clock;
311 	char buf[16] = "invalid";
312 	uint32_t status;
313 
314 	sc = oidp->oid_arg1;
315 
316 	/* Select sync ports table for device type. */
317 	if (sc->type == HDSPE_AIO)
318 		clock_table = hdspe_clock_source_table_aio;
319 	else if (sc->type == HDSPE_RAYDAT)
320 		clock_table = hdspe_clock_source_table_rd;
321 	else
322 		return (ENXIO);
323 
324 	/* Read current (autosync) clock source from status register. */
325 	snd_mtxlock(sc->lock);
326 	status = hdspe_read_4(sc, HDSPE_STATUS1_REG);
327 	status &= HDSPE_STATUS1_CLOCK_MASK;
328 	snd_mtxunlock(sc->lock);
329 
330 	/* Translate status register value to clock source. */
331 	for (clock = clock_table; clock->name != NULL; ++clock) {
332 		/* In clock master mode, override with internal clock source. */
333 		if (sc->settings_register & HDSPE_SETTING_MASTER) {
334 			if (clock->setting & HDSPE_SETTING_MASTER)
335 				break;
336 		} else if (clock->status == status)
337 			break;
338 	}
339 
340 	/* Process sysctl string request. */
341 	if (clock->name != NULL)
342 		strlcpy(buf, clock->name, sizeof(buf));
343 	return (sysctl_handle_string(oidp, buf, sizeof(buf), req));
344 }
345 
346 static int
347 hdspe_sysctl_clock_list(SYSCTL_HANDLER_ARGS)
348 {
349 	struct sc_info *sc;
350 	struct hdspe_clock_source *clock_table, *clock;
351 	char buf[256];
352 	int n;
353 
354 	sc = oidp->oid_arg1;
355 	n = 0;
356 
357 	/* Select clock source table for device type. */
358 	if (sc->type == HDSPE_AIO)
359 		clock_table = hdspe_clock_source_table_aio;
360 	else if (sc->type == HDSPE_RAYDAT)
361 		clock_table = hdspe_clock_source_table_rd;
362 	else
363 		return (ENXIO);
364 
365 	/* List available clock sources. */
366 	buf[0] = 0;
367 	for (clock = clock_table; clock->name != NULL; ++clock) {
368 		if (n > 0)
369 			n += strlcpy(buf + n, ",", sizeof(buf) - n);
370 		n += strlcpy(buf + n, clock->name, sizeof(buf) - n);
371 	}
372 	return (sysctl_handle_string(oidp, buf, sizeof(buf), req));
373 }
374 
375 static int
376 hdspe_sysctl_sync_status(SYSCTL_HANDLER_ARGS)
377 {
378 	struct sc_info *sc;
379 	struct hdspe_clock_source *clock_table, *clock;
380 	char buf[256];
381 	char *state;
382 	int n;
383 	uint32_t status;
384 
385 	sc = oidp->oid_arg1;
386 	n = 0;
387 
388 	/* Select sync ports table for device type. */
389 	if (sc->type == HDSPE_AIO)
390 		clock_table = hdspe_clock_source_table_aio;
391 	else if (sc->type == HDSPE_RAYDAT)
392 		clock_table = hdspe_clock_source_table_rd;
393 	else
394 		return (ENXIO);
395 
396 	/* Read current lock and sync bits from status register. */
397 	snd_mtxlock(sc->lock);
398 	status = hdspe_read_4(sc, HDSPE_STATUS1_REG);
399 	snd_mtxunlock(sc->lock);
400 
401 	/* List clock sources with lock and sync state. */
402 	for (clock = clock_table; clock->name != NULL; ++clock) {
403 		if (clock->sync_bit != 0) {
404 			if (n > 0)
405 				n += strlcpy(buf + n, ",", sizeof(buf) - n);
406 			state = "none";
407 			if ((clock->sync_bit & status) != 0)
408 				state = "sync";
409 			else if ((clock->lock_bit & status) != 0)
410 				state = "lock";
411 			n += snprintf(buf + n, sizeof(buf) - n, "%s(%s)",
412 			    clock->name, state);
413 		}
414 	}
415 	return (sysctl_handle_string(oidp, buf, sizeof(buf), req));
416 }
417 
418 static int
419 hdspe_probe(device_t dev)
420 {
421 	uint32_t rev;
422 
423 	if (pci_get_vendor(dev) == PCI_VENDOR_XILINX &&
424 	    pci_get_device(dev) == PCI_DEVICE_XILINX_HDSPE) {
425 		rev = pci_get_revid(dev);
426 		switch (rev) {
427 		case PCI_REVISION_AIO:
428 			device_set_desc(dev, "RME HDSPe AIO");
429 			return (0);
430 		case PCI_REVISION_RAYDAT:
431 			device_set_desc(dev, "RME HDSPe RayDAT");
432 			return (0);
433 		}
434 	}
435 
436 	return (ENXIO);
437 }
438 
439 static int
440 hdspe_init(struct sc_info *sc)
441 {
442 	long long period;
443 
444 	/* Set latency. */
445 	sc->period = 32;
446 	sc->ctrl_register = hdspe_encode_latency(7);
447 
448 	/* Set rate. */
449 	sc->speed = HDSPE_SPEED_DEFAULT;
450 	sc->ctrl_register &= ~HDSPE_FREQ_MASK;
451 	sc->ctrl_register |= HDSPE_FREQ_MASK_DEFAULT;
452 	hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register);
453 
454 	switch (sc->type) {
455 	case HDSPE_RAYDAT:
456 	case HDSPE_AIO:
457 		period = HDSPE_FREQ_AIO;
458 		break;
459 	default:
460 		return (ENXIO);
461 	}
462 
463 	/* Set DDS value. */
464 	period /= sc->speed;
465 	hdspe_write_4(sc, HDSPE_FREQ_REG, period);
466 
467 	/* Other settings. */
468 	sc->settings_register = 0;
469 	hdspe_write_4(sc, HDSPE_SETTINGS_REG, sc->settings_register);
470 
471 	return (0);
472 }
473 
474 static int
475 hdspe_attach(device_t dev)
476 {
477 	struct hdspe_channel *chan_map;
478 	struct sc_pcminfo *scp;
479 	struct sc_info *sc;
480 	uint32_t rev;
481 	int i, err;
482 
483 #if 0
484 	device_printf(dev, "hdspe_attach()\n");
485 #endif
486 
487 	sc = device_get_softc(dev);
488 	sc->lock = snd_mtxcreate(device_get_nameunit(dev),
489 	    "snd_hdspe softc");
490 	sc->dev = dev;
491 
492 	pci_enable_busmaster(dev);
493 	rev = pci_get_revid(dev);
494 	switch (rev) {
495 	case PCI_REVISION_AIO:
496 		sc->type = HDSPE_AIO;
497 		chan_map = chan_map_aio;
498 		break;
499 	case PCI_REVISION_RAYDAT:
500 		sc->type = HDSPE_RAYDAT;
501 		chan_map = chan_map_rd;
502 		break;
503 	default:
504 		return (ENXIO);
505 	}
506 
507 	/* Allocate resources. */
508 	err = hdspe_alloc_resources(sc);
509 	if (err) {
510 		device_printf(dev, "Unable to allocate system resources.\n");
511 		return (ENXIO);
512 	}
513 
514 	if (hdspe_init(sc) != 0)
515 		return (ENXIO);
516 
517 	for (i = 0; i < HDSPE_MAX_CHANS && chan_map[i].descr != NULL; i++) {
518 		scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
519 		scp->hc = &chan_map[i];
520 		scp->sc = sc;
521 		scp->dev = device_add_child(dev, "pcm", -1);
522 		device_set_ivars(scp->dev, scp);
523 	}
524 
525 	hdspe_map_dmabuf(sc);
526 
527 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
528 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
529 	    "sync_status", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
530 	    sc, 0, hdspe_sysctl_sync_status, "A",
531 	    "List clock source signal lock and sync status");
532 
533 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
534 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
535 	    "clock_source", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
536 	    sc, 0, hdspe_sysctl_clock_source, "A",
537 	    "Currently effective clock source");
538 
539 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
540 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
541 	    "clock_preference", CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
542 	    sc, 0, hdspe_sysctl_clock_preference, "A",
543 	    "Set 'internal' (master) or preferred autosync clock source");
544 
545 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
546 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
547 	    "clock_list", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
548 	    sc, 0, hdspe_sysctl_clock_list, "A",
549 	    "List of supported clock sources");
550 
551 	return (bus_generic_attach(dev));
552 }
553 
554 static void
555 hdspe_dmafree(struct sc_info *sc)
556 {
557 
558 	bus_dmamap_unload(sc->dmat, sc->rmap);
559 	bus_dmamap_unload(sc->dmat, sc->pmap);
560 	bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
561 	bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
562 	sc->rbuf = sc->pbuf = NULL;
563 }
564 
565 static int
566 hdspe_detach(device_t dev)
567 {
568 	struct sc_info *sc;
569 	int err;
570 
571 	sc = device_get_softc(dev);
572 	if (sc == NULL) {
573 		device_printf(dev,"Can't detach: softc is null.\n");
574 		return (0);
575 	}
576 
577 	err = device_delete_children(dev);
578 	if (err)
579 		return (err);
580 
581 	hdspe_dmafree(sc);
582 
583 	if (sc->ih)
584 		bus_teardown_intr(dev, sc->irq, sc->ih);
585 	if (sc->dmat)
586 		bus_dma_tag_destroy(sc->dmat);
587 	if (sc->irq)
588 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
589 	if (sc->cs)
590 		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), sc->cs);
591 	if (sc->lock)
592 		snd_mtxfree(sc->lock);
593 
594 	return (0);
595 }
596 
597 static device_method_t hdspe_methods[] = {
598 	DEVMETHOD(device_probe,     hdspe_probe),
599 	DEVMETHOD(device_attach,    hdspe_attach),
600 	DEVMETHOD(device_detach,    hdspe_detach),
601 	{ 0, 0 }
602 };
603 
604 static driver_t hdspe_driver = {
605 	"hdspe",
606 	hdspe_methods,
607 	PCM_SOFTC_SIZE,
608 };
609 
610 DRIVER_MODULE(snd_hdspe, pci, hdspe_driver, 0, 0);
611