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 return 0; 211 bad: 212 213 #if 0 214 device_printf(sc->dev,"hdspe is running\n"); 215 #endif 216 217 return 1; 218 } 219 220 static void 221 hdspe_start_audio(struct sc_info *sc) 222 { 223 224 sc->ctrl_register |= (HDSPE_AUDIO_INT_ENABLE | HDSPE_ENABLE); 225 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 226 } 227 228 static void 229 hdspe_stop_audio(struct sc_info *sc) 230 { 231 232 if (hdspe_running(sc) == 1) 233 return; 234 235 sc->ctrl_register &= ~(HDSPE_AUDIO_INT_ENABLE | HDSPE_ENABLE); 236 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 237 } 238 239 /* Multiplex / demultiplex: 2.0 <-> 2 x 1.0. */ 240 static void 241 buffer_copy(struct sc_chinfo *ch) 242 { 243 struct sc_pcminfo *scp = ch->parent; 244 struct sc_info *sc = scp->sc; 245 int length,src,dst; 246 int ssize, dsize; 247 int i; 248 249 length = sndbuf_getready(ch->buffer) / 250 (4 /* Bytes per sample. */ * 2 /* channels */); 251 252 if (ch->dir == PCMDIR_PLAY) { 253 src = sndbuf_getreadyptr(ch->buffer); 254 } else { 255 src = sndbuf_getfreeptr(ch->buffer); 256 } 257 258 src /= 4; /* Bytes per sample. */ 259 dst = src / 2; /* Destination buffer twice smaller. */ 260 261 ssize = ch->size / 4; 262 dsize = ch->size / 8; 263 264 /* 265 * Use two fragment buffer to avoid sound clipping. 266 */ 267 268 for (i = 0; i < sc->period * 2 /* fragments */; i++) { 269 if (ch->dir == PCMDIR_PLAY) { 270 sc->pbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->lslot] = 271 ch->data[src]; 272 sc->pbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->rslot] = 273 ch->data[src + 1]; 274 275 } else { 276 ch->data[src] = 277 sc->rbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->lslot]; 278 ch->data[src+1] = 279 sc->rbuf[dst + HDSPE_CHANBUF_SAMPLES * ch->rslot]; 280 } 281 282 dst+=1; 283 dst %= dsize; 284 src+=2; 285 src %= ssize; 286 } 287 } 288 289 static int 290 clean(struct sc_chinfo *ch){ 291 struct sc_pcminfo *scp = ch->parent; 292 struct sc_info *sc = scp->sc; 293 uint32_t *buf = sc->rbuf; 294 295 if (ch->dir == PCMDIR_PLAY) { 296 buf = sc->pbuf; 297 } 298 299 bzero(buf + HDSPE_CHANBUF_SAMPLES * ch->lslot, HDSPE_CHANBUF_SIZE); 300 bzero(buf + HDSPE_CHANBUF_SAMPLES * ch->rslot, HDSPE_CHANBUF_SIZE); 301 302 return 0; 303 } 304 305 306 /* Channel interface. */ 307 static void * 308 hdspechan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 309 struct pcm_channel *c, int dir) 310 { 311 struct sc_pcminfo *scp = devinfo; 312 struct sc_info *sc = scp->sc; 313 struct sc_chinfo *ch; 314 int num; 315 316 snd_mtxlock(sc->lock); 317 num = scp->chnum; 318 319 ch = &scp->chan[num]; 320 ch->lslot = scp->hc->left; 321 ch->rslot = scp->hc->right; 322 ch->run = 0; 323 ch->lvol = 0; 324 ch->rvol = 0; 325 326 ch->size = HDSPE_CHANBUF_SIZE * 2 /* slots */; 327 ch->data = malloc(ch->size, M_HDSPE, M_NOWAIT); 328 329 ch->buffer = b; 330 ch->channel = c; 331 ch->parent = scp; 332 333 ch->dir = dir; 334 335 snd_mtxunlock(sc->lock); 336 337 if (sndbuf_setup(ch->buffer, ch->data, ch->size) != 0) { 338 device_printf(scp->dev, "Can't setup sndbuf.\n"); 339 return NULL; 340 } 341 342 return ch; 343 } 344 345 static int 346 hdspechan_trigger(kobj_t obj, void *data, int go) 347 { 348 struct sc_chinfo *ch = data; 349 struct sc_pcminfo *scp = ch->parent; 350 struct sc_info *sc = scp->sc; 351 352 snd_mtxlock(sc->lock); 353 switch (go) { 354 case PCMTRIG_START: 355 #if 0 356 device_printf(scp->dev, "hdspechan_trigger(): start\n"); 357 #endif 358 hdspechan_enable(ch, 1); 359 hdspechan_setgain(ch); 360 hdspe_start_audio(sc); 361 break; 362 363 case PCMTRIG_STOP: 364 case PCMTRIG_ABORT: 365 #if 0 366 device_printf(scp->dev, "hdspechan_trigger(): stop or abort\n"); 367 #endif 368 clean(ch); 369 hdspechan_enable(ch, 0); 370 hdspe_stop_audio(sc); 371 break; 372 373 case PCMTRIG_EMLDMAWR: 374 case PCMTRIG_EMLDMARD: 375 if(ch->run) 376 buffer_copy(ch); 377 break; 378 } 379 380 snd_mtxunlock(sc->lock); 381 382 return 0; 383 } 384 385 static uint32_t 386 hdspechan_getptr(kobj_t obj, void *data) 387 { 388 struct sc_chinfo *ch = data; 389 struct sc_pcminfo *scp = ch->parent; 390 struct sc_info *sc = scp->sc; 391 uint32_t ret, pos; 392 393 snd_mtxlock(sc->lock); 394 ret = hdspe_read_2(sc, HDSPE_STATUS_REG); 395 snd_mtxunlock(sc->lock); 396 397 pos = ret & HDSPE_BUF_POSITION_MASK; 398 pos *= 2; /* Hardbuf twice bigger. */ 399 400 return pos; 401 } 402 403 static int 404 hdspechan_free(kobj_t obj, void *data) 405 { 406 struct sc_chinfo *ch = data; 407 struct sc_pcminfo *scp = ch->parent; 408 struct sc_info *sc = scp->sc; 409 410 #if 0 411 device_printf(scp->dev, "hdspechan_free()\n"); 412 #endif 413 snd_mtxlock(sc->lock); 414 if (ch->data != NULL) { 415 free(ch->data, M_HDSPE); 416 ch->data = NULL; 417 } 418 snd_mtxunlock(sc->lock); 419 420 return 0; 421 } 422 423 static int 424 hdspechan_setformat(kobj_t obj, void *data, uint32_t format) 425 { 426 struct sc_chinfo *ch = data; 427 428 #if 0 429 struct sc_pcminfo *scp = ch->parent; 430 device_printf(scp->dev, "hdspechan_setformat(%d)\n", format); 431 #endif 432 433 ch->format = format; 434 435 return 0; 436 } 437 438 static uint32_t 439 hdspechan_setspeed(kobj_t obj, void *data, uint32_t speed) 440 { 441 struct sc_chinfo *ch = data; 442 struct sc_pcminfo *scp = ch->parent; 443 struct sc_info *sc = scp->sc; 444 struct hdspe_rate *hr = NULL; 445 long long period; 446 int threshold; 447 int i; 448 449 #if 0 450 device_printf(scp->dev, "hdspechan_setspeed(%d)\n", speed); 451 #endif 452 453 if (hdspe_running(sc) == 1) 454 goto end; 455 456 /* First look for equal frequency. */ 457 for (i = 0; rate_map[i].speed != 0; i++) { 458 if (rate_map[i].speed == speed) 459 hr = &rate_map[i]; 460 } 461 462 /* If no match, just find nearest. */ 463 if (hr == NULL) { 464 for (i = 0; rate_map[i].speed != 0; i++) { 465 hr = &rate_map[i]; 466 threshold = hr->speed + ((rate_map[i + 1].speed != 0) ? 467 ((rate_map[i + 1].speed - hr->speed) >> 1) : 0); 468 if (speed < threshold) 469 break; 470 } 471 } 472 473 switch (sc->type) { 474 case RAYDAT: 475 case AIO: 476 period = HDSPE_FREQ_AIO; 477 break; 478 default: 479 /* Unsupported card. */ 480 goto end; 481 } 482 483 /* Write frequency on the device. */ 484 sc->ctrl_register &= ~HDSPE_FREQ_MASK; 485 sc->ctrl_register |= hr->reg; 486 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 487 488 speed = hr->speed; 489 if (speed > 96000) 490 speed /= 4; 491 else if (speed > 48000) 492 speed /= 2; 493 494 /* Set DDS value. */ 495 period /= speed; 496 hdspe_write_4(sc, HDSPE_FREQ_REG, period); 497 498 sc->speed = hr->speed; 499 end: 500 return sc->speed; 501 } 502 503 static uint32_t 504 hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 505 { 506 struct sc_chinfo *ch = data; 507 struct sc_pcminfo *scp = ch->parent; 508 struct sc_info *sc = scp->sc; 509 struct hdspe_latency *hl = NULL; 510 int threshold; 511 int i; 512 513 #if 0 514 device_printf(scp->dev, "hdspechan_setblocksize(%d)\n", blocksize); 515 #endif 516 517 if (hdspe_running(sc) == 1) 518 goto end; 519 520 if (blocksize > HDSPE_LAT_BYTES_MAX) 521 blocksize = HDSPE_LAT_BYTES_MAX; 522 else if (blocksize < HDSPE_LAT_BYTES_MIN) 523 blocksize = HDSPE_LAT_BYTES_MIN; 524 525 blocksize /= 4 /* samples */; 526 527 /* First look for equal latency. */ 528 for (i = 0; latency_map[i].period != 0; i++) { 529 if (latency_map[i].period == blocksize) { 530 hl = &latency_map[i]; 531 } 532 } 533 534 /* If no match, just find nearest. */ 535 if (hl == NULL) { 536 for (i = 0; latency_map[i].period != 0; i++) { 537 hl = &latency_map[i]; 538 threshold = hl->period + ((latency_map[i + 1].period != 0) ? 539 ((latency_map[i + 1].period - hl->period) >> 1) : 0); 540 if (blocksize < threshold) 541 break; 542 } 543 } 544 545 snd_mtxlock(sc->lock); 546 sc->ctrl_register &= ~HDSPE_LAT_MASK; 547 sc->ctrl_register |= hdspe_encode_latency(hl->n); 548 hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register); 549 sc->period = hl->period; 550 snd_mtxunlock(sc->lock); 551 552 #if 0 553 device_printf(scp->dev, "New period=%d\n", sc->period); 554 #endif 555 556 sndbuf_resize(ch->buffer, (HDSPE_CHANBUF_SIZE * 2) / (sc->period * 4), 557 (sc->period * 4)); 558 end: 559 return sndbuf_getblksz(ch->buffer); 560 } 561 562 static uint32_t hdspe_rfmt[] = { 563 SND_FORMAT(AFMT_S32_LE, 2, 0), 564 0 565 }; 566 567 static struct pcmchan_caps hdspe_rcaps = {32000, 192000, hdspe_rfmt, 0}; 568 569 static uint32_t hdspe_pfmt[] = { 570 SND_FORMAT(AFMT_S32_LE, 2, 0), 571 0 572 }; 573 574 static struct pcmchan_caps hdspe_pcaps = {32000, 192000, hdspe_pfmt, 0}; 575 576 static struct pcmchan_caps * 577 hdspechan_getcaps(kobj_t obj, void *data) 578 { 579 struct sc_chinfo *ch = data; 580 581 #if 0 582 struct sc_pcminfo *scl = ch->parent; 583 device_printf(scp->dev, "hdspechan_getcaps()\n"); 584 #endif 585 586 return (ch->dir == PCMDIR_PLAY) ? 587 &hdspe_pcaps : &hdspe_rcaps; 588 } 589 590 static kobj_method_t hdspechan_methods[] = { 591 KOBJMETHOD(channel_init, hdspechan_init), 592 KOBJMETHOD(channel_free, hdspechan_free), 593 KOBJMETHOD(channel_setformat, hdspechan_setformat), 594 KOBJMETHOD(channel_setspeed, hdspechan_setspeed), 595 KOBJMETHOD(channel_setblocksize, hdspechan_setblocksize), 596 KOBJMETHOD(channel_trigger, hdspechan_trigger), 597 KOBJMETHOD(channel_getptr, hdspechan_getptr), 598 KOBJMETHOD(channel_getcaps, hdspechan_getcaps), 599 KOBJMETHOD_END 600 }; 601 CHANNEL_DECLARE(hdspechan); 602 603 604 static int 605 hdspe_pcm_probe(device_t dev) 606 { 607 608 #if 0 609 device_printf(dev,"hdspe_pcm_probe()\n"); 610 #endif 611 612 return 0; 613 } 614 615 static uint32_t 616 hdspe_pcm_intr(struct sc_pcminfo *scp) { 617 struct sc_chinfo *ch; 618 struct sc_info *sc = scp->sc; 619 int i; 620 621 for (i = 0; i < scp->chnum; i++) { 622 ch = &scp->chan[i]; 623 snd_mtxunlock(sc->lock); 624 chn_intr(ch->channel); 625 snd_mtxlock(sc->lock); 626 } 627 628 return 0; 629 } 630 631 static int 632 hdspe_pcm_attach(device_t dev) 633 { 634 struct sc_pcminfo *scp; 635 char status[SND_STATUSLEN]; 636 char desc[64]; 637 int i, err; 638 639 scp = device_get_ivars(dev); 640 scp->ih = &hdspe_pcm_intr; 641 642 bzero(desc, sizeof(desc)); 643 snprintf(desc, sizeof(desc), "HDSPe AIO [%s]", scp->hc->descr); 644 device_set_desc_copy(dev, desc); 645 646 /* 647 * We don't register interrupt handler with snd_setup_intr 648 * in pcm device. Mark pcm device as MPSAFE manually. 649 */ 650 pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 651 652 err = pcm_register(dev, scp, scp->hc->play, scp->hc->rec); 653 if (err) { 654 device_printf(dev, "Can't register pcm.\n"); 655 return ENXIO; 656 } 657 658 scp->chnum = 0; 659 for (i = 0; i < scp->hc->play; i++) { 660 pcm_addchan(dev, PCMDIR_PLAY, &hdspechan_class, scp); 661 scp->chnum++; 662 } 663 664 for (i = 0; i < scp->hc->rec; i++) { 665 pcm_addchan(dev, PCMDIR_REC, &hdspechan_class, scp); 666 scp->chnum++; 667 } 668 669 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s", 670 rman_get_start(scp->sc->cs), 671 rman_get_start(scp->sc->irq), 672 PCM_KLDSTRING(snd_hdspe)); 673 pcm_setstatus(dev, status); 674 675 mixer_init(dev, &hdspemixer_class, scp); 676 677 return 0; 678 } 679 680 static int 681 hdspe_pcm_detach(device_t dev) 682 { 683 int err; 684 685 err = pcm_unregister(dev); 686 if (err) { 687 device_printf(dev, "Can't unregister device.\n"); 688 return err; 689 } 690 691 return 0; 692 } 693 694 static device_method_t hdspe_pcm_methods[] = { 695 DEVMETHOD(device_probe, hdspe_pcm_probe), 696 DEVMETHOD(device_attach, hdspe_pcm_attach), 697 DEVMETHOD(device_detach, hdspe_pcm_detach), 698 { 0, 0 } 699 }; 700 701 static driver_t hdspe_pcm_driver = { 702 "pcm", 703 hdspe_pcm_methods, 704 PCM_SOFTC_SIZE, 705 }; 706 707 DRIVER_MODULE(snd_hdspe_pcm, hdspe, hdspe_pcm_driver, pcm_devclass, 0, 0); 708 MODULE_DEPEND(snd_hdspe, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 709 MODULE_VERSION(snd_hdspe, 1); 710