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