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