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