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