1 /*- 2 * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #ifdef HAVE_KERNEL_OPTION_HEADERS 27 #include "opt_snd.h" 28 #endif 29 30 #include <dev/sound/pcm/sound.h> 31 32 #include "mixer_if.h" 33 34 #include "interface/compat/vchi_bsd.h" 35 #include "interface/vchi/vchi.h" 36 #include "interface/vchiq_arm/vchiq.h" 37 38 #include "vc_vchi_audioserv_defs.h" 39 40 /* Audio destination */ 41 #define DEST_AUTO 0 42 #define DEST_HEADPHONES 1 43 #define DEST_HDMI 2 44 45 /* Playback state */ 46 #define PLAYBACK_IDLE 0 47 #define PLAYBACK_PLAYING 1 48 #define PLAYBACK_STOPPING 2 49 50 /* Worker thread state */ 51 #define WORKER_RUNNING 0 52 #define WORKER_STOPPING 1 53 #define WORKER_STOPPED 2 54 55 /* 56 * Worker thread flags, set to 1 in flags_pending 57 * when driver requests one or another operation 58 * from worker. Cleared to 0 once worker performs 59 * the operations. 60 */ 61 #define AUDIO_PARAMS (1 << 0) 62 #define AUDIO_PLAY (1 << 1) 63 #define AUDIO_STOP (1 << 2) 64 65 #define VCHIQ_AUDIO_PACKET_SIZE 4000 66 #define VCHIQ_AUDIO_BUFFER_SIZE 10*VCHIQ_AUDIO_PACKET_SIZE 67 68 #define VCHIQ_AUDIO_MAX_VOLUME 69 /* volume in terms of 0.01dB */ 70 #define VCHIQ_AUDIO_VOLUME_MIN -10239 71 #define VCHIQ_AUDIO_VOLUME(db100) (uint32_t)(-((db100) << 8)/100) 72 73 /* dB levels with 5% volume step */ 74 static int db_levels[] = { 75 VCHIQ_AUDIO_VOLUME_MIN, -4605, -3794, -3218, -2772, 76 -2407, -2099, -1832, -1597, -1386, 77 -1195, -1021, -861, -713, -575, 78 -446, -325, -210, -102, 0, 79 }; 80 81 static uint32_t bcm2835_audio_playfmt[] = { 82 SND_FORMAT(AFMT_U8, 1, 0), 83 SND_FORMAT(AFMT_U8, 2, 0), 84 SND_FORMAT(AFMT_S8, 1, 0), 85 SND_FORMAT(AFMT_S8, 2, 0), 86 SND_FORMAT(AFMT_S16_LE, 1, 0), 87 SND_FORMAT(AFMT_S16_LE, 2, 0), 88 SND_FORMAT(AFMT_U16_LE, 1, 0), 89 SND_FORMAT(AFMT_U16_LE, 2, 0), 90 0 91 }; 92 93 static struct pcmchan_caps bcm2835_audio_playcaps = {8000, 48000, bcm2835_audio_playfmt, 0}; 94 95 struct bcm2835_audio_info; 96 97 struct bcm2835_audio_chinfo { 98 struct bcm2835_audio_info *parent; 99 struct pcm_channel *channel; 100 struct snd_dbuf *buffer; 101 uint32_t fmt, spd, blksz; 102 103 /* Pointer to first unsubmitted sample */ 104 uint32_t unsubmittedptr; 105 /* 106 * Number of bytes in "submitted but not played" 107 * pseudo-buffer 108 */ 109 int available_space; 110 int playback_state; 111 uint64_t callbacks; 112 uint64_t submitted_samples; 113 uint64_t retrieved_samples; 114 uint64_t underruns; 115 int starved; 116 }; 117 118 struct bcm2835_audio_info { 119 device_t dev; 120 unsigned int bufsz; 121 struct bcm2835_audio_chinfo pch; 122 uint32_t dest, volume; 123 struct intr_config_hook intr_hook; 124 125 /* VCHI data */ 126 VCHI_INSTANCE_T vchi_instance; 127 VCHI_CONNECTION_T *vchi_connection; 128 VCHI_SERVICE_HANDLE_T vchi_handle; 129 130 struct mtx lock; 131 struct cv worker_cv; 132 133 uint32_t flags_pending; 134 135 /* Worker thread state */ 136 int worker_state; 137 }; 138 139 #define BCM2835_AUDIO_LOCK(sc) mtx_lock(&(sc)->lock) 140 #define BCM2835_AUDIO_LOCKED(sc) mtx_assert(&(sc)->lock, MA_OWNED) 141 #define BCM2835_AUDIO_UNLOCK(sc) mtx_unlock(&(sc)->lock) 142 143 static const char * 144 dest_description(uint32_t dest) 145 { 146 switch (dest) { 147 case DEST_AUTO: 148 return "AUTO"; 149 break; 150 151 case DEST_HEADPHONES: 152 return "HEADPHONES"; 153 break; 154 155 case DEST_HDMI: 156 return "HDMI"; 157 break; 158 default: 159 return "UNKNOWN"; 160 break; 161 } 162 } 163 164 static void 165 bcm2835_worker_update_params(struct bcm2835_audio_info *sc) 166 { 167 168 BCM2835_AUDIO_LOCKED(sc); 169 170 sc->flags_pending |= AUDIO_PARAMS; 171 cv_signal(&sc->worker_cv); 172 } 173 174 static void 175 bcm2835_worker_play_start(struct bcm2835_audio_info *sc) 176 { 177 BCM2835_AUDIO_LOCK(sc); 178 sc->flags_pending &= ~(AUDIO_STOP); 179 sc->flags_pending |= AUDIO_PLAY; 180 cv_signal(&sc->worker_cv); 181 BCM2835_AUDIO_UNLOCK(sc); 182 } 183 184 static void 185 bcm2835_worker_play_stop(struct bcm2835_audio_info *sc) 186 { 187 BCM2835_AUDIO_LOCK(sc); 188 sc->flags_pending &= ~(AUDIO_PLAY); 189 sc->flags_pending |= AUDIO_STOP; 190 cv_signal(&sc->worker_cv); 191 BCM2835_AUDIO_UNLOCK(sc); 192 } 193 194 static void 195 bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle) 196 { 197 struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)param; 198 int32_t status; 199 uint32_t msg_len; 200 VC_AUDIO_MSG_T m; 201 202 if (reason != VCHI_CALLBACK_MSG_AVAILABLE) 203 return; 204 205 status = vchi_msg_dequeue(sc->vchi_handle, 206 &m, sizeof m, &msg_len, VCHI_FLAGS_NONE); 207 if (status != 0) 208 return; 209 if (m.type == VC_AUDIO_MSG_TYPE_RESULT) { 210 if (m.u.result.success) { 211 device_printf(sc->dev, 212 "msg type %08x failed\n", 213 m.type); 214 } 215 } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { 216 struct bcm2835_audio_chinfo *ch = m.u.complete.cookie; 217 218 int count = m.u.complete.count & 0xffff; 219 int perr = (m.u.complete.count & (1U << 30)) != 0; 220 ch->callbacks++; 221 if (perr) 222 ch->underruns++; 223 224 BCM2835_AUDIO_LOCK(sc); 225 if (ch->playback_state != PLAYBACK_IDLE) { 226 /* Prevent LOR */ 227 BCM2835_AUDIO_UNLOCK(sc); 228 chn_intr(sc->pch.channel); 229 BCM2835_AUDIO_LOCK(sc); 230 } 231 /* We should check again, state might have changed */ 232 if (ch->playback_state != PLAYBACK_IDLE) { 233 if (!perr) { 234 if ((ch->available_space + count)> VCHIQ_AUDIO_BUFFER_SIZE) { 235 device_printf(sc->dev, "inconsistent data in callback:\n"); 236 device_printf(sc->dev, "available_space == %d, count = %d, perr=%d\n", 237 ch->available_space, count, perr); 238 device_printf(sc->dev, 239 "retrieved_samples = %lld, submitted_samples = %lld\n", 240 ch->retrieved_samples, ch->submitted_samples); 241 } 242 ch->available_space += count; 243 ch->retrieved_samples += count; 244 } 245 if (perr || (ch->available_space >= VCHIQ_AUDIO_PACKET_SIZE)) 246 cv_signal(&sc->worker_cv); 247 } 248 BCM2835_AUDIO_UNLOCK(sc); 249 } else 250 printf("%s: unknown m.type: %d\n", __func__, m.type); 251 } 252 253 /* VCHIQ stuff */ 254 static void 255 bcm2835_audio_init(struct bcm2835_audio_info *sc) 256 { 257 int status; 258 259 /* Initialize and create a VCHI connection */ 260 status = vchi_initialise(&sc->vchi_instance); 261 if (status != 0) { 262 printf("vchi_initialise failed: %d\n", status); 263 return; 264 } 265 266 status = vchi_connect(NULL, 0, sc->vchi_instance); 267 if (status != 0) { 268 printf("vchi_connect failed: %d\n", status); 269 return; 270 } 271 272 SERVICE_CREATION_T params = { 273 VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER), 274 VC_AUDIO_SERVER_NAME, /* 4cc service code */ 275 sc->vchi_connection, /* passed in fn pointers */ 276 0, /* rx fifo size */ 277 0, /* tx fifo size */ 278 bcm2835_audio_callback, /* service callback */ 279 sc, /* service callback parameter */ 280 1, 281 1, 282 0 /* want crc check on bulk transfers */ 283 }; 284 285 status = vchi_service_open(sc->vchi_instance, ¶ms, 286 &sc->vchi_handle); 287 288 if (status != 0) 289 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID; 290 } 291 292 static void 293 bcm2835_audio_release(struct bcm2835_audio_info *sc) 294 { 295 int success; 296 297 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 298 success = vchi_service_close(sc->vchi_handle); 299 if (success != 0) 300 printf("vchi_service_close failed: %d\n", success); 301 vchi_service_release(sc->vchi_handle); 302 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID; 303 } 304 305 vchi_disconnect(sc->vchi_instance); 306 } 307 308 static void 309 bcm2835_audio_reset_channel(struct bcm2835_audio_chinfo *ch) 310 { 311 312 ch->available_space = VCHIQ_AUDIO_BUFFER_SIZE; 313 ch->unsubmittedptr = 0; 314 sndbuf_reset(ch->buffer); 315 } 316 317 static void 318 bcm2835_audio_start(struct bcm2835_audio_chinfo *ch) 319 { 320 VC_AUDIO_MSG_T m; 321 int ret; 322 struct bcm2835_audio_info *sc = ch->parent; 323 324 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 325 m.type = VC_AUDIO_MSG_TYPE_START; 326 ret = vchi_msg_queue(sc->vchi_handle, 327 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 328 329 if (ret != 0) 330 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 331 } 332 } 333 334 static void 335 bcm2835_audio_stop(struct bcm2835_audio_chinfo *ch) 336 { 337 VC_AUDIO_MSG_T m; 338 int ret; 339 struct bcm2835_audio_info *sc = ch->parent; 340 341 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 342 m.type = VC_AUDIO_MSG_TYPE_STOP; 343 m.u.stop.draining = 0; 344 345 ret = vchi_msg_queue(sc->vchi_handle, 346 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 347 348 if (ret != 0) 349 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 350 } 351 } 352 353 static void 354 bcm2835_audio_open(struct bcm2835_audio_info *sc) 355 { 356 VC_AUDIO_MSG_T m; 357 int ret; 358 359 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 360 m.type = VC_AUDIO_MSG_TYPE_OPEN; 361 ret = vchi_msg_queue(sc->vchi_handle, 362 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 363 364 if (ret != 0) 365 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 366 } 367 } 368 369 static void 370 bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, uint32_t dest) 371 { 372 VC_AUDIO_MSG_T m; 373 int ret, db; 374 375 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 376 m.type = VC_AUDIO_MSG_TYPE_CONTROL; 377 m.u.control.dest = dest; 378 if (volume > 99) 379 volume = 99; 380 db = db_levels[volume/5]; 381 m.u.control.volume = VCHIQ_AUDIO_VOLUME(db); 382 383 ret = vchi_msg_queue(sc->vchi_handle, 384 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 385 386 if (ret != 0) 387 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 388 } 389 } 390 391 static void 392 bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_t speed) 393 { 394 VC_AUDIO_MSG_T m; 395 int ret; 396 397 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 398 m.type = VC_AUDIO_MSG_TYPE_CONFIG; 399 m.u.config.channels = AFMT_CHANNEL(fmt); 400 m.u.config.samplerate = speed; 401 m.u.config.bps = AFMT_BIT(fmt); 402 403 ret = vchi_msg_queue(sc->vchi_handle, 404 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 405 406 if (ret != 0) 407 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 408 } 409 } 410 411 static bool 412 bcm2835_audio_buffer_should_sleep(struct bcm2835_audio_chinfo *ch) 413 { 414 415 if (ch->playback_state != PLAYBACK_PLAYING) 416 return (true); 417 418 /* Not enough data */ 419 if (sndbuf_getready(ch->buffer) < VCHIQ_AUDIO_PACKET_SIZE) { 420 printf("starve\n"); 421 ch->starved++; 422 return (true); 423 } 424 425 /* Not enough free space */ 426 if (ch->available_space < VCHIQ_AUDIO_PACKET_SIZE) { 427 return (true); 428 } 429 430 return (false); 431 } 432 433 static void 434 bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch, void *buf, uint32_t count) 435 { 436 struct bcm2835_audio_info *sc = ch->parent; 437 VC_AUDIO_MSG_T m; 438 int ret; 439 440 if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) { 441 return; 442 } 443 444 m.type = VC_AUDIO_MSG_TYPE_WRITE; 445 m.u.write.count = count; 446 m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE; 447 m.u.write.callback = NULL; 448 m.u.write.cookie = ch; 449 m.u.write.silence = 0; 450 451 ret = vchi_msg_queue(sc->vchi_handle, 452 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 453 454 if (ret != 0) 455 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 456 457 while (count > 0) { 458 int bytes = MIN((int)m.u.write.max_packet, (int)count); 459 ret = vchi_msg_queue(sc->vchi_handle, 460 buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 461 if (ret != 0) 462 printf("%s: vchi_msg_queue failed: %d\n", 463 __func__, ret); 464 buf = (char *)buf + bytes; 465 count -= bytes; 466 } 467 } 468 469 static void 470 bcm2835_audio_worker(void *data) 471 { 472 struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)data; 473 struct bcm2835_audio_chinfo *ch = &sc->pch; 474 uint32_t speed, format; 475 uint32_t volume, dest; 476 uint32_t flags; 477 uint32_t count, size, readyptr; 478 uint8_t *buf; 479 480 ch->playback_state = PLAYBACK_IDLE; 481 482 while (1) { 483 if (sc->worker_state != WORKER_RUNNING) 484 break; 485 486 BCM2835_AUDIO_LOCK(sc); 487 /* 488 * wait until there are flags set or buffer is ready 489 * to consume more samples 490 */ 491 while ((sc->flags_pending == 0) && 492 bcm2835_audio_buffer_should_sleep(ch)) { 493 cv_wait_sig(&sc->worker_cv, &sc->lock); 494 } 495 flags = sc->flags_pending; 496 /* Clear pending flags */ 497 sc->flags_pending = 0; 498 BCM2835_AUDIO_UNLOCK(sc); 499 500 /* Requested to change parameters */ 501 if (flags & AUDIO_PARAMS) { 502 BCM2835_AUDIO_LOCK(sc); 503 speed = ch->spd; 504 format = ch->fmt; 505 volume = sc->volume; 506 dest = sc->dest; 507 BCM2835_AUDIO_UNLOCK(sc); 508 if (ch->playback_state == PLAYBACK_IDLE) 509 bcm2835_audio_update_params(sc, format, speed); 510 bcm2835_audio_update_controls(sc, volume, dest); 511 } 512 513 /* Requested to stop playback */ 514 if ((flags & AUDIO_STOP) && 515 (ch->playback_state == PLAYBACK_PLAYING)) { 516 bcm2835_audio_stop(ch); 517 BCM2835_AUDIO_LOCK(sc); 518 bcm2835_audio_reset_channel(&sc->pch); 519 ch->playback_state = PLAYBACK_IDLE; 520 BCM2835_AUDIO_UNLOCK(sc); 521 continue; 522 } 523 524 /* Requested to start playback */ 525 if ((flags & AUDIO_PLAY) && 526 (ch->playback_state == PLAYBACK_IDLE)) { 527 BCM2835_AUDIO_LOCK(sc); 528 ch->playback_state = PLAYBACK_PLAYING; 529 BCM2835_AUDIO_UNLOCK(sc); 530 bcm2835_audio_start(ch); 531 } 532 533 if (ch->playback_state == PLAYBACK_IDLE) 534 continue; 535 536 if (sndbuf_getready(ch->buffer) == 0) 537 continue; 538 539 count = sndbuf_getready(ch->buffer); 540 size = sndbuf_getsize(ch->buffer); 541 readyptr = sndbuf_getreadyptr(ch->buffer); 542 543 BCM2835_AUDIO_LOCK(sc); 544 if (readyptr + count > size) 545 count = size - readyptr; 546 count = min(count, ch->available_space); 547 count -= (count % VCHIQ_AUDIO_PACKET_SIZE); 548 BCM2835_AUDIO_UNLOCK(sc); 549 550 if (count < VCHIQ_AUDIO_PACKET_SIZE) 551 continue; 552 553 buf = (uint8_t*)sndbuf_getbuf(ch->buffer) + readyptr; 554 555 bcm2835_audio_write_samples(ch, buf, count); 556 BCM2835_AUDIO_LOCK(sc); 557 ch->unsubmittedptr = (ch->unsubmittedptr + count) % sndbuf_getsize(ch->buffer); 558 ch->available_space -= count; 559 ch->submitted_samples += count; 560 KASSERT(ch->available_space >= 0, ("ch->available_space == %d\n", ch->available_space)); 561 BCM2835_AUDIO_UNLOCK(sc); 562 } 563 564 BCM2835_AUDIO_LOCK(sc); 565 sc->worker_state = WORKER_STOPPED; 566 cv_signal(&sc->worker_cv); 567 BCM2835_AUDIO_UNLOCK(sc); 568 569 kproc_exit(0); 570 } 571 572 static void 573 bcm2835_audio_create_worker(struct bcm2835_audio_info *sc) 574 { 575 struct proc *newp; 576 577 sc->worker_state = WORKER_RUNNING; 578 if (kproc_create(bcm2835_audio_worker, (void*)sc, &newp, 0, 0, 579 "bcm2835_audio_worker") != 0) { 580 printf("failed to create bcm2835_audio_worker\n"); 581 } 582 } 583 584 /* -------------------------------------------------------------------- */ 585 /* channel interface for VCHI audio */ 586 static void * 587 bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 588 { 589 struct bcm2835_audio_info *sc = devinfo; 590 struct bcm2835_audio_chinfo *ch = &sc->pch; 591 void *buffer; 592 593 if (dir == PCMDIR_REC) 594 return NULL; 595 596 ch->parent = sc; 597 ch->channel = c; 598 ch->buffer = b; 599 600 /* default values */ 601 ch->spd = 44100; 602 ch->fmt = SND_FORMAT(AFMT_S16_LE, 2, 0); 603 ch->blksz = VCHIQ_AUDIO_PACKET_SIZE; 604 605 buffer = malloc(sc->bufsz, M_DEVBUF, M_WAITOK | M_ZERO); 606 607 if (sndbuf_setup(ch->buffer, buffer, sc->bufsz) != 0) { 608 device_printf(sc->dev, "sndbuf_setup failed\n"); 609 free(buffer, M_DEVBUF); 610 return NULL; 611 } 612 613 BCM2835_AUDIO_LOCK(sc); 614 bcm2835_worker_update_params(sc); 615 BCM2835_AUDIO_UNLOCK(sc); 616 617 return ch; 618 } 619 620 static int 621 bcmchan_free(kobj_t obj, void *data) 622 { 623 struct bcm2835_audio_chinfo *ch = data; 624 void *buffer; 625 626 buffer = sndbuf_getbuf(ch->buffer); 627 if (buffer) 628 free(buffer, M_DEVBUF); 629 630 return (0); 631 } 632 633 static int 634 bcmchan_setformat(kobj_t obj, void *data, uint32_t format) 635 { 636 struct bcm2835_audio_chinfo *ch = data; 637 struct bcm2835_audio_info *sc = ch->parent; 638 639 BCM2835_AUDIO_LOCK(sc); 640 ch->fmt = format; 641 bcm2835_worker_update_params(sc); 642 BCM2835_AUDIO_UNLOCK(sc); 643 644 return 0; 645 } 646 647 static uint32_t 648 bcmchan_setspeed(kobj_t obj, void *data, uint32_t speed) 649 { 650 struct bcm2835_audio_chinfo *ch = data; 651 struct bcm2835_audio_info *sc = ch->parent; 652 653 BCM2835_AUDIO_LOCK(sc); 654 ch->spd = speed; 655 bcm2835_worker_update_params(sc); 656 BCM2835_AUDIO_UNLOCK(sc); 657 658 return ch->spd; 659 } 660 661 static uint32_t 662 bcmchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 663 { 664 struct bcm2835_audio_chinfo *ch = data; 665 666 return ch->blksz; 667 } 668 669 static int 670 bcmchan_trigger(kobj_t obj, void *data, int go) 671 { 672 struct bcm2835_audio_chinfo *ch = data; 673 struct bcm2835_audio_info *sc = ch->parent; 674 675 if (!PCMTRIG_COMMON(go)) 676 return (0); 677 678 switch (go) { 679 case PCMTRIG_START: 680 /* kickstart data flow */ 681 chn_intr(sc->pch.channel); 682 ch->submitted_samples = 0; 683 ch->retrieved_samples = 0; 684 bcm2835_worker_play_start(sc); 685 break; 686 687 case PCMTRIG_STOP: 688 case PCMTRIG_ABORT: 689 bcm2835_worker_play_stop(sc); 690 break; 691 692 default: 693 break; 694 } 695 return 0; 696 } 697 698 static uint32_t 699 bcmchan_getptr(kobj_t obj, void *data) 700 { 701 struct bcm2835_audio_chinfo *ch = data; 702 struct bcm2835_audio_info *sc = ch->parent; 703 uint32_t ret; 704 705 BCM2835_AUDIO_LOCK(sc); 706 ret = ch->unsubmittedptr; 707 BCM2835_AUDIO_UNLOCK(sc); 708 709 return ret; 710 } 711 712 static struct pcmchan_caps * 713 bcmchan_getcaps(kobj_t obj, void *data) 714 { 715 716 return &bcm2835_audio_playcaps; 717 } 718 719 static kobj_method_t bcmchan_methods[] = { 720 KOBJMETHOD(channel_init, bcmchan_init), 721 KOBJMETHOD(channel_free, bcmchan_free), 722 KOBJMETHOD(channel_setformat, bcmchan_setformat), 723 KOBJMETHOD(channel_setspeed, bcmchan_setspeed), 724 KOBJMETHOD(channel_setblocksize, bcmchan_setblocksize), 725 KOBJMETHOD(channel_trigger, bcmchan_trigger), 726 KOBJMETHOD(channel_getptr, bcmchan_getptr), 727 KOBJMETHOD(channel_getcaps, bcmchan_getcaps), 728 KOBJMETHOD_END 729 }; 730 CHANNEL_DECLARE(bcmchan); 731 732 /************************************************************/ 733 734 static int 735 bcmmix_init(struct snd_mixer *m) 736 { 737 738 mix_setdevs(m, SOUND_MASK_VOLUME); 739 740 return (0); 741 } 742 743 static int 744 bcmmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 745 { 746 struct bcm2835_audio_info *sc = mix_getdevinfo(m); 747 748 switch (dev) { 749 case SOUND_MIXER_VOLUME: 750 BCM2835_AUDIO_LOCK(sc); 751 sc->volume = left; 752 bcm2835_worker_update_params(sc); 753 BCM2835_AUDIO_UNLOCK(sc); 754 755 break; 756 757 default: 758 break; 759 } 760 761 return left | (left << 8); 762 } 763 764 static kobj_method_t bcmmixer_methods[] = { 765 KOBJMETHOD(mixer_init, bcmmix_init), 766 KOBJMETHOD(mixer_set, bcmmix_set), 767 KOBJMETHOD_END 768 }; 769 770 MIXER_DECLARE(bcmmixer); 771 772 static int 773 sysctl_bcm2835_audio_dest(SYSCTL_HANDLER_ARGS) 774 { 775 struct bcm2835_audio_info *sc = arg1; 776 int val; 777 int err; 778 779 val = sc->dest; 780 err = sysctl_handle_int(oidp, &val, 0, req); 781 if (err || !req->newptr) /* error || read request */ 782 return (err); 783 784 if ((val < 0) || (val > 2)) 785 return (EINVAL); 786 787 BCM2835_AUDIO_LOCK(sc); 788 sc->dest = val; 789 bcm2835_worker_update_params(sc); 790 BCM2835_AUDIO_UNLOCK(sc); 791 792 if (bootverbose) 793 device_printf(sc->dev, "destination set to %s\n", dest_description(val)); 794 795 return (0); 796 } 797 798 static void 799 vchi_audio_sysctl_init(struct bcm2835_audio_info *sc) 800 { 801 struct sysctl_ctx_list *ctx; 802 struct sysctl_oid *tree_node; 803 struct sysctl_oid_list *tree; 804 805 /* 806 * Add system sysctl tree/handlers. 807 */ 808 ctx = device_get_sysctl_ctx(sc->dev); 809 tree_node = device_get_sysctl_tree(sc->dev); 810 tree = SYSCTL_CHILDREN(tree_node); 811 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "dest", 812 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, sizeof(*sc), 813 sysctl_bcm2835_audio_dest, "IU", "audio destination, " 814 "0 - auto, 1 - headphones, 2 - HDMI"); 815 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "callbacks", 816 CTLFLAG_RD, &sc->pch.callbacks, 817 "callbacks total"); 818 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "submitted", 819 CTLFLAG_RD, &sc->pch.submitted_samples, 820 "last play submitted samples"); 821 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "retrieved", 822 CTLFLAG_RD, &sc->pch.retrieved_samples, 823 "last play retrieved samples"); 824 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "underruns", 825 CTLFLAG_RD, &sc->pch.underruns, 826 "callback underruns"); 827 SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "freebuffer", 828 CTLFLAG_RD, &sc->pch.available_space, 829 sc->pch.available_space, "callbacks total"); 830 SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "starved", 831 CTLFLAG_RD, &sc->pch.starved, 832 sc->pch.starved, "number of starved conditions"); 833 } 834 835 static void 836 bcm2835_audio_identify(driver_t *driver, device_t parent) 837 { 838 839 BUS_ADD_CHILD(parent, 0, "pcm", 0); 840 } 841 842 static int 843 bcm2835_audio_probe(device_t dev) 844 { 845 846 device_set_desc(dev, "VCHIQ audio"); 847 return (BUS_PROBE_DEFAULT); 848 } 849 850 static void 851 bcm2835_audio_delayed_init(void *xsc) 852 { 853 struct bcm2835_audio_info *sc; 854 char status[SND_STATUSLEN]; 855 856 sc = xsc; 857 858 config_intrhook_disestablish(&sc->intr_hook); 859 860 bcm2835_audio_init(sc); 861 bcm2835_audio_open(sc); 862 sc->volume = 75; 863 sc->dest = DEST_AUTO; 864 865 if (mixer_init(sc->dev, &bcmmixer_class, sc)) { 866 device_printf(sc->dev, "mixer_init failed\n"); 867 goto no; 868 } 869 870 if (pcm_register(sc->dev, sc, 1, 0)) { 871 device_printf(sc->dev, "pcm_register failed\n"); 872 goto no; 873 } 874 875 pcm_addchan(sc->dev, PCMDIR_PLAY, &bcmchan_class, sc); 876 snprintf(status, SND_STATUSLEN, "at VCHIQ"); 877 pcm_setstatus(sc->dev, status); 878 879 bcm2835_audio_reset_channel(&sc->pch); 880 bcm2835_audio_create_worker(sc); 881 882 vchi_audio_sysctl_init(sc); 883 884 no: 885 ; 886 } 887 888 static int 889 bcm2835_audio_attach(device_t dev) 890 { 891 struct bcm2835_audio_info *sc; 892 893 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 894 895 sc->dev = dev; 896 sc->bufsz = VCHIQ_AUDIO_BUFFER_SIZE; 897 898 mtx_init(&sc->lock, device_get_nameunit(dev), 899 "bcm_audio_lock", MTX_DEF); 900 cv_init(&sc->worker_cv, "worker_cv"); 901 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID; 902 903 /* 904 * We need interrupts enabled for VCHI to work properly, 905 * so delay initialization until it happens. 906 */ 907 sc->intr_hook.ich_func = bcm2835_audio_delayed_init; 908 sc->intr_hook.ich_arg = sc; 909 910 if (config_intrhook_establish(&sc->intr_hook) != 0) 911 goto no; 912 913 return 0; 914 915 no: 916 return ENXIO; 917 } 918 919 static int 920 bcm2835_audio_detach(device_t dev) 921 { 922 int r; 923 struct bcm2835_audio_info *sc; 924 sc = pcm_getdevinfo(dev); 925 926 /* Stop worker thread */ 927 BCM2835_AUDIO_LOCK(sc); 928 sc->worker_state = WORKER_STOPPING; 929 cv_signal(&sc->worker_cv); 930 /* Wait for thread to exit */ 931 while (sc->worker_state != WORKER_STOPPED) 932 cv_wait_sig(&sc->worker_cv, &sc->lock); 933 BCM2835_AUDIO_UNLOCK(sc); 934 935 r = pcm_unregister(dev); 936 if (r) 937 return r; 938 939 mtx_destroy(&sc->lock); 940 cv_destroy(&sc->worker_cv); 941 942 bcm2835_audio_release(sc); 943 944 free(sc, M_DEVBUF); 945 946 return 0; 947 } 948 949 static device_method_t bcm2835_audio_methods[] = { 950 /* Device interface */ 951 DEVMETHOD(device_identify, bcm2835_audio_identify), 952 DEVMETHOD(device_probe, bcm2835_audio_probe), 953 DEVMETHOD(device_attach, bcm2835_audio_attach), 954 DEVMETHOD(device_detach, bcm2835_audio_detach), 955 { 0, 0 } 956 }; 957 958 static driver_t bcm2835_audio_driver = { 959 "pcm", 960 bcm2835_audio_methods, 961 PCM_SOFTC_SIZE, 962 }; 963 964 DRIVER_MODULE(bcm2835_audio, vchiq, bcm2835_audio_driver, 0, 0); 965 MODULE_DEPEND(bcm2835_audio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 966 MODULE_DEPEND(bcm2835_audio, vchiq, 1, 1, 1); 967 MODULE_VERSION(bcm2835_audio, 1); 968