1 /*- 2 * Copyright (c) 2012 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * RME HDSPe driver for FreeBSD (pcm-part). 29 * Supported cards: AIO, RayDAT. 30 */ 31 32 #include <dev/sound/pcm/sound.h> 33 #include <dev/sound/pci/hdspe.h> 34 #include <dev/sound/chip.h> 35 36 #include <dev/pci/pcireg.h> 37 #include <dev/pci/pcivar.h> 38 39 #include <mixer_if.h> 40 41 SND_DECLARE_FILE("$FreeBSD$"); 42 43 struct hdspe_latency { 44 uint32_t n; 45 uint32_t period; 46 float ms; 47 }; 48 49 static struct hdspe_latency latency_map[] = { 50 { 7, 32, 0.7 }, 51 { 0, 64, 1.5 }, 52 { 1, 128, 3 }, 53 { 2, 256, 6 }, 54 { 3, 512, 12 }, 55 { 4, 1024, 23 }, 56 { 5, 2048, 46 }, 57 { 6, 4096, 93 }, 58 59 { 0, 0, 0 }, 60 }; 61 62 struct hdspe_rate { 63 uint32_t speed; 64 uint32_t reg; 65 }; 66 67 static struct hdspe_rate rate_map[] = { 68 { 32000, (HDSPE_FREQ_32000) }, 69 { 44100, (HDSPE_FREQ_44100) }, 70 { 48000, (HDSPE_FREQ_48000) }, 71 { 64000, (HDSPE_FREQ_32000 | HDSPE_FREQ_DOUBLE) }, 72 { 88200, (HDSPE_FREQ_44100 | HDSPE_FREQ_DOUBLE) }, 73 { 96000, (HDSPE_FREQ_48000 | HDSPE_FREQ_DOUBLE) }, 74 { 128000, (HDSPE_FREQ_32000 | HDSPE_FREQ_QUAD) }, 75 { 176400, (HDSPE_FREQ_44100 | HDSPE_FREQ_QUAD) }, 76 { 192000, (HDSPE_FREQ_48000 | HDSPE_FREQ_QUAD) }, 77 78 { 0, 0 }, 79 }; 80 81 82 static int 83 hdspe_hw_mixer(struct sc_chinfo *ch, unsigned int dst, 84 unsigned int src, unsigned short data) 85 { 86 struct sc_pcminfo *scp = ch->parent; 87 struct sc_info *sc = scp->sc; 88 int offs = 0; 89 90 if (ch->dir == PCMDIR_PLAY) 91 offs = 64; 92 93 hdspe_write_4(sc, HDSPE_MIXER_BASE + 94 ((offs + src + 128 * dst) * sizeof(uint32_t)), 95 data & 0xFFFF); 96 97 return 0; 98 }; 99 100 static int 101 hdspechan_setgain(struct sc_chinfo *ch) 102 { 103 104 hdspe_hw_mixer(ch, ch->lslot, ch->lslot, 105 ch->lvol * HDSPE_MAX_GAIN / 100); 106 hdspe_hw_mixer(ch, ch->rslot, ch->rslot, 107 ch->rvol * HDSPE_MAX_GAIN / 100); 108 109 return 0; 110 } 111 112 static int 113 hdspemixer_init(struct snd_mixer *m) 114 { 115 struct sc_pcminfo *scp = mix_getdevinfo(m); 116 struct sc_info *sc = scp->sc; 117 int mask; 118 119 if (sc == NULL) 120 return -1; 121 122 mask = SOUND_MASK_PCM; 123 124 if (scp->hc->play) 125 mask |= SOUND_MASK_VOLUME; 126 127 if (scp->hc->rec) 128 mask |= SOUND_MASK_RECLEV; 129 130 snd_mtxlock(sc->lock); 131 pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL); 132 mix_setdevs(m, mask); 133 snd_mtxunlock(sc->lock); 134 135 return 0; 136 } 137 138 static int 139 hdspemixer_set(struct snd_mixer *m, unsigned dev, 140 unsigned left, unsigned right) 141 { 142 struct sc_pcminfo *scp = mix_getdevinfo(m); 143 struct sc_chinfo *ch; 144 int i; 145 146 #if 0 147 device_printf(scp->dev, "hdspemixer_set() %d %d\n", 148 left,right); 149 #endif 150 151 for (i = 0; i < scp->chnum; i++) { 152 ch = &scp->chan[i]; 153 if ((dev == SOUND_MIXER_VOLUME && ch->dir == PCMDIR_PLAY) || 154 (dev == SOUND_MIXER_RECLEV && ch->dir == PCMDIR_REC)) { 155 ch->lvol = left; 156 ch->rvol = right; 157 if (ch->run) 158 hdspechan_setgain(ch); 159 } 160 } 161 162 return 0; 163 } 164 165 static kobj_method_t hdspemixer_methods[] = { 166 KOBJMETHOD(mixer_init, hdspemixer_init), 167 KOBJMETHOD(mixer_set, hdspemixer_set), 168 KOBJMETHOD_END 169 }; 170 MIXER_DECLARE(hdspemixer); 171 172 static void 173 hdspechan_enable(struct sc_chinfo *ch, int value) 174 { 175 struct sc_pcminfo *scp = ch->parent; 176 struct sc_info *sc = scp->sc; 177 int reg; 178 179 if (ch->dir == PCMDIR_PLAY) 180 reg = HDSPE_OUT_ENABLE_BASE; 181 else 182 reg = HDSPE_IN_ENABLE_BASE; 183 184 ch->run = value; 185 186 hdspe_write_1(sc, reg + (4 * ch->lslot), value); 187 hdspe_write_1(sc, reg + (4 * ch->rslot), value); 188 } 189 190 static int 191 hdspe_running(struct sc_info *sc) 192 { 193 struct sc_pcminfo *scp; 194 struct sc_chinfo *ch; 195 int i, j, devcount, err; 196 device_t *devlist; 197 198 if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) 199 goto bad; 200 201 for (i = 0; i < devcount; i++) { 202 scp = device_get_ivars(devlist[i]); 203 for (j = 0; j < scp->chnum; j++) { 204 ch = &scp->chan[j]; 205 if (ch->run) 206 goto bad; 207 } 208 } 209 210 free(devlist, M_TEMP); 211 return 0; 212 bad: 213 214 #if 0 215 device_printf(sc->dev,"hdspe is running\n"); 216 #endif 217 218 free(devlist, M_TEMP); 219 return 1; 220 } 221 222 static void 223 hdspe_start_audio(struct sc_info *sc) 224 { 225 226 sc->ctrl_register |= (HDSPE_AUDIO_INT_ENABLE | HDSPE_ENABLE); 227 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 228 } 229 230 static void 231 hdspe_stop_audio(struct sc_info *sc) 232 { 233 234 if (hdspe_running(sc) == 1) 235 return; 236 237 sc->ctrl_register &= ~(HDSPE_AUDIO_INT_ENABLE | HDSPE_ENABLE); 238 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 239 } 240 241 /* Multiplex / demultiplex: 2.0 <-> 2 x 1.0. */ 242 static void 243 buffer_copy(struct sc_chinfo *ch) 244 { 245 struct sc_pcminfo *scp = ch->parent; 246 struct sc_info *sc = scp->sc; 247 int length,src,dst; 248 int ssize, dsize; 249 int i; 250 251 length = sndbuf_getready(ch->buffer) / 252 (4 /* Bytes per sample. */ * 2 /* channels */); 253 254 if (ch->dir == PCMDIR_PLAY) { 255 src = sndbuf_getreadyptr(ch->buffer); 256 } else { 257 src = sndbuf_getfreeptr(ch->buffer); 258 } 259 260 src /= 4; /* Bytes per sample. */ 261 dst = src / 2; /* Destination buffer twice smaller. */ 262 263 ssize = ch->size / 4; 264 dsize = ch->size / 8; 265 266 /* 267 * Use two fragment buffer to avoid sound clipping. 268 */ 269 270 for (i = 0; i < sc->period * 2 /* fragments */; i++) { 271 if (ch->dir == PCMDIR_PLAY) { 272 sc->pbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->lslot] = 273 ch->data[src]; 274 sc->pbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->rslot] = 275 ch->data[src + 1]; 276 277 } else { 278 ch->data[src] = 279 sc->rbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->lslot]; 280 ch->data[src+1] = 281 sc->rbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->rslot]; 282 } 283 284 dst+=1; 285 dst %= dsize; 286 src+=2; 287 src %= ssize; 288 } 289 } 290 291 static int 292 clean(struct sc_chinfo *ch){ 293 struct sc_pcminfo *scp = ch->parent; 294 struct sc_info *sc = scp->sc; 295 uint32_t *buf = sc->rbuf; 296 297 if (ch->dir == PCMDIR_PLAY) { 298 buf = sc->pbuf; 299 } 300 301 bzero(buf + HDSPE_CHANBUF_SAMPLES * ch->lslot, HDSPE_CHANBUF_SIZE); 302 bzero(buf + HDSPE_CHANBUF_SAMPLES * ch->rslot, HDSPE_CHANBUF_SIZE); 303 304 return 0; 305 } 306 307 308 /* Channel interface. */ 309 static void * 310 hdspechan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 311 struct pcm_channel *c, int dir) 312 { 313 struct sc_pcminfo *scp = devinfo; 314 struct sc_info *sc = scp->sc; 315 struct sc_chinfo *ch; 316 int num; 317 318 snd_mtxlock(sc->lock); 319 num = scp->chnum; 320 321 ch = &scp->chan[num]; 322 ch->lslot = scp->hc->left; 323 ch->rslot = scp->hc->right; 324 ch->run = 0; 325 ch->lvol = 0; 326 ch->rvol = 0; 327 328 ch->size = HDSPE_CHANBUF_SIZE * 2 /* slots */; 329 ch->data = malloc(ch->size, M_HDSPE, M_NOWAIT); 330 331 ch->buffer = b; 332 ch->channel = c; 333 ch->parent = scp; 334 335 ch->dir = dir; 336 337 snd_mtxunlock(sc->lock); 338 339 if (sndbuf_setup(ch->buffer, ch->data, ch->size) != 0) { 340 device_printf(scp->dev, "Can't setup sndbuf.\n"); 341 return NULL; 342 } 343 344 return ch; 345 } 346 347 static int 348 hdspechan_trigger(kobj_t obj, void *data, int go) 349 { 350 struct sc_chinfo *ch = data; 351 struct sc_pcminfo *scp = ch->parent; 352 struct sc_info *sc = scp->sc; 353 354 snd_mtxlock(sc->lock); 355 switch (go) { 356 case PCMTRIG_START: 357 #if 0 358 device_printf(scp->dev, "hdspechan_trigger(): start\n"); 359 #endif 360 hdspechan_enable(ch, 1); 361 hdspechan_setgain(ch); 362 hdspe_start_audio(sc); 363 break; 364 365 case PCMTRIG_STOP: 366 case PCMTRIG_ABORT: 367 #if 0 368 device_printf(scp->dev, "hdspechan_trigger(): stop or abort\n"); 369 #endif 370 clean(ch); 371 hdspechan_enable(ch, 0); 372 hdspe_stop_audio(sc); 373 break; 374 375 case PCMTRIG_EMLDMAWR: 376 case PCMTRIG_EMLDMARD: 377 if(ch->run) 378 buffer_copy(ch); 379 break; 380 } 381 382 snd_mtxunlock(sc->lock); 383 384 return 0; 385 } 386 387 static uint32_t 388 hdspechan_getptr(kobj_t obj, void *data) 389 { 390 struct sc_chinfo *ch = data; 391 struct sc_pcminfo *scp = ch->parent; 392 struct sc_info *sc = scp->sc; 393 uint32_t ret, pos; 394 395 snd_mtxlock(sc->lock); 396 ret = hdspe_read_2(sc, HDSPE_STATUS_REG); 397 snd_mtxunlock(sc->lock); 398 399 pos = ret & HDSPE_BUF_POSITION_MASK; 400 pos *= 2; /* Hardbuf twice bigger. */ 401 402 return pos; 403 } 404 405 static int 406 hdspechan_free(kobj_t obj, void *data) 407 { 408 struct sc_chinfo *ch = data; 409 struct sc_pcminfo *scp = ch->parent; 410 struct sc_info *sc = scp->sc; 411 412 #if 0 413 device_printf(scp->dev, "hdspechan_free()\n"); 414 #endif 415 snd_mtxlock(sc->lock); 416 if (ch->data != NULL) { 417 free(ch->data, M_HDSPE); 418 ch->data = NULL; 419 } 420 snd_mtxunlock(sc->lock); 421 422 return 0; 423 } 424 425 static int 426 hdspechan_setformat(kobj_t obj, void *data, uint32_t format) 427 { 428 struct sc_chinfo *ch = data; 429 430 #if 0 431 struct sc_pcminfo *scp = ch->parent; 432 device_printf(scp->dev, "hdspechan_setformat(%d)\n", format); 433 #endif 434 435 ch->format = format; 436 437 return 0; 438 } 439 440 static uint32_t 441 hdspechan_setspeed(kobj_t obj, void *data, uint32_t speed) 442 { 443 struct sc_chinfo *ch = data; 444 struct sc_pcminfo *scp = ch->parent; 445 struct sc_info *sc = scp->sc; 446 struct hdspe_rate *hr = NULL; 447 long long period; 448 int threshold; 449 int i; 450 451 #if 0 452 device_printf(scp->dev, "hdspechan_setspeed(%d)\n", speed); 453 #endif 454 455 if (hdspe_running(sc) == 1) 456 goto end; 457 458 /* First look for equal frequency. */ 459 for (i = 0; rate_map[i].speed != 0; i++) { 460 if (rate_map[i].speed == speed) 461 hr = &rate_map[i]; 462 } 463 464 /* If no match, just find nearest. */ 465 if (hr == NULL) { 466 for (i = 0; rate_map[i].speed != 0; i++) { 467 hr = &rate_map[i]; 468 threshold = hr->speed + ((rate_map[i + 1].speed != 0) ? 469 ((rate_map[i + 1].speed - hr->speed) >> 1) : 0); 470 if (speed < threshold) 471 break; 472 } 473 } 474 475 switch (sc->type) { 476 case RAYDAT: 477 case AIO: 478 period = HDSPE_FREQ_AIO; 479 break; 480 default: 481 /* Unsupported card. */ 482 goto end; 483 } 484 485 /* Write frequency on the device. */ 486 sc->ctrl_register &= ~HDSPE_FREQ_MASK; 487 sc->ctrl_register |= hr->reg; 488 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 489 490 speed = hr->speed; 491 if (speed > 96000) 492 speed /= 4; 493 else if (speed > 48000) 494 speed /= 2; 495 496 /* Set DDS value. */ 497 period /= speed; 498 hdspe_write_4(sc, HDSPE_FREQ_REG, period); 499 500 sc->speed = hr->speed; 501 end: 502 return sc->speed; 503 } 504 505 static uint32_t 506 hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 507 { 508 struct sc_chinfo *ch = data; 509 struct sc_pcminfo *scp = ch->parent; 510 struct sc_info *sc = scp->sc; 511 struct hdspe_latency *hl = NULL; 512 int threshold; 513 int i; 514 515 #if 0 516 device_printf(scp->dev, "hdspechan_setblocksize(%d)\n", blocksize); 517 #endif 518 519 if (hdspe_running(sc) == 1) 520 goto end; 521 522 if (blocksize > HDSPE_LAT_BYTES_MAX) 523 blocksize = HDSPE_LAT_BYTES_MAX; 524 else if (blocksize < HDSPE_LAT_BYTES_MIN) 525 blocksize = HDSPE_LAT_BYTES_MIN; 526 527 blocksize /= 4 /* samples */; 528 529 /* First look for equal latency. */ 530 for (i = 0; latency_map[i].period != 0; i++) { 531 if (latency_map[i].period == blocksize) { 532 hl = &latency_map[i]; 533 } 534 } 535 536 /* If no match, just find nearest. */ 537 if (hl == NULL) { 538 for (i = 0; latency_map[i].period != 0; i++) { 539 hl = &latency_map[i]; 540 threshold = hl->period + ((latency_map[i + 1].period != 0) ? 541 ((latency_map[i + 1].period - hl->period) >> 1) : 0); 542 if (blocksize < threshold) 543 break; 544 } 545 } 546 547 snd_mtxlock(sc->lock); 548 sc->ctrl_register &= ~HDSPE_LAT_MASK; 549 sc->ctrl_register |= hdspe_encode_latency(hl->n); 550 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 551 sc->period = hl->period; 552 snd_mtxunlock(sc->lock); 553 554 #if 0 555 device_printf(scp->dev, "New period=%d\n", sc->period); 556 #endif 557 558 sndbuf_resize(ch->buffer, (HDSPE_CHANBUF_SIZE * 2) / (sc->period * 4), 559 (sc->period * 4)); 560 end: 561 return sndbuf_getblksz(ch->buffer); 562 } 563 564 static uint32_t hdspe_rfmt[] = { 565 SND_FORMAT(AFMT_S32_LE, 2, 0), 566 0 567 }; 568 569 static struct pcmchan_caps hdspe_rcaps = {32000, 192000, hdspe_rfmt, 0}; 570 571 static uint32_t hdspe_pfmt[] = { 572 SND_FORMAT(AFMT_S32_LE, 2, 0), 573 0 574 }; 575 576 static struct pcmchan_caps hdspe_pcaps = {32000, 192000, hdspe_pfmt, 0}; 577 578 static struct pcmchan_caps * 579 hdspechan_getcaps(kobj_t obj, void *data) 580 { 581 struct sc_chinfo *ch = data; 582 583 #if 0 584 struct sc_pcminfo *scl = ch->parent; 585 device_printf(scp->dev, "hdspechan_getcaps()\n"); 586 #endif 587 588 return (ch->dir == PCMDIR_PLAY) ? 589 &hdspe_pcaps : &hdspe_rcaps; 590 } 591 592 static kobj_method_t hdspechan_methods[] = { 593 KOBJMETHOD(channel_init, hdspechan_init), 594 KOBJMETHOD(channel_free, hdspechan_free), 595 KOBJMETHOD(channel_setformat, hdspechan_setformat), 596 KOBJMETHOD(channel_setspeed, hdspechan_setspeed), 597 KOBJMETHOD(channel_setblocksize, hdspechan_setblocksize), 598 KOBJMETHOD(channel_trigger, hdspechan_trigger), 599 KOBJMETHOD(channel_getptr, hdspechan_getptr), 600 KOBJMETHOD(channel_getcaps, hdspechan_getcaps), 601 KOBJMETHOD_END 602 }; 603 CHANNEL_DECLARE(hdspechan); 604 605 606 static int 607 hdspe_pcm_probe(device_t dev) 608 { 609 610 #if 0 611 device_printf(dev,"hdspe_pcm_probe()\n"); 612 #endif 613 614 return 0; 615 } 616 617 static uint32_t 618 hdspe_pcm_intr(struct sc_pcminfo *scp) { 619 struct sc_chinfo *ch; 620 struct sc_info *sc = scp->sc; 621 int i; 622 623 for (i = 0; i < scp->chnum; i++) { 624 ch = &scp->chan[i]; 625 snd_mtxunlock(sc->lock); 626 chn_intr(ch->channel); 627 snd_mtxlock(sc->lock); 628 } 629 630 return 0; 631 } 632 633 static int 634 hdspe_pcm_attach(device_t dev) 635 { 636 struct sc_pcminfo *scp; 637 char status[SND_STATUSLEN]; 638 char desc[64]; 639 int i, err; 640 641 scp = device_get_ivars(dev); 642 scp->ih = &hdspe_pcm_intr; 643 644 bzero(desc, sizeof(desc)); 645 snprintf(desc, sizeof(desc), "HDSPe AIO [%s]", scp->hc->descr); 646 device_set_desc_copy(dev, desc); 647 648 /* 649 * We don't register interrupt handler with snd_setup_intr 650 * in pcm device. Mark pcm device as MPSAFE manually. 651 */ 652 pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 653 654 err = pcm_register(dev, scp, scp->hc->play, scp->hc->rec); 655 if (err) { 656 device_printf(dev, "Can't register pcm.\n"); 657 return ENXIO; 658 } 659 660 scp->chnum = 0; 661 for (i = 0; i < scp->hc->play; i++) { 662 pcm_addchan(dev, PCMDIR_PLAY, &hdspechan_class, scp); 663 scp->chnum++; 664 } 665 666 for (i = 0; i < scp->hc->rec; i++) { 667 pcm_addchan(dev, PCMDIR_REC, &hdspechan_class, scp); 668 scp->chnum++; 669 } 670 671 snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s", 672 rman_get_start(scp->sc->cs), 673 rman_get_start(scp->sc->irq), 674 PCM_KLDSTRING(snd_hdspe)); 675 pcm_setstatus(dev, status); 676 677 mixer_init(dev, &hdspemixer_class, scp); 678 679 return 0; 680 } 681 682 static int 683 hdspe_pcm_detach(device_t dev) 684 { 685 int err; 686 687 err = pcm_unregister(dev); 688 if (err) { 689 device_printf(dev, "Can't unregister device.\n"); 690 return err; 691 } 692 693 return 0; 694 } 695 696 static device_method_t hdspe_pcm_methods[] = { 697 DEVMETHOD(device_probe, hdspe_pcm_probe), 698 DEVMETHOD(device_attach, hdspe_pcm_attach), 699 DEVMETHOD(device_detach, hdspe_pcm_detach), 700 { 0, 0 } 701 }; 702 703 static driver_t hdspe_pcm_driver = { 704 "pcm", 705 hdspe_pcm_methods, 706 PCM_SOFTC_SIZE, 707 }; 708 709 DRIVER_MODULE(snd_hdspe_pcm, hdspe, hdspe_pcm_driver, pcm_devclass, 0, 0); 710 MODULE_DEPEND(snd_hdspe, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 711 MODULE_VERSION(snd_hdspe, 1); 712