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 50 #define VCHIQ_AUDIO_MAX_VOLUME 51 /* volume in terms of 0.01dB */ 52 #define VCHIQ_AUDIO_VOLUME_MIN -10239 53 #define VCHIQ_AUDIO_VOLUME(db100) (uint32_t)(-((db100) << 8)/100) 54 55 /* dB levels with 5% volume step */ 56 static int db_levels[] = { 57 VCHIQ_AUDIO_VOLUME_MIN, -4605, -3794, -3218, -2772, 58 -2407, -2099, -1832, -1597, -1386, 59 -1195, -1021, -861, -713, -575, 60 -446, -325, -210, -102, 0, 61 }; 62 63 static uint32_t bcm2835_audio_playfmt[] = { 64 SND_FORMAT(AFMT_U8, 1, 0), 65 SND_FORMAT(AFMT_U8, 2, 0), 66 SND_FORMAT(AFMT_S8, 1, 0), 67 SND_FORMAT(AFMT_S8, 2, 0), 68 SND_FORMAT(AFMT_S16_LE, 1, 0), 69 SND_FORMAT(AFMT_S16_LE, 2, 0), 70 SND_FORMAT(AFMT_U16_LE, 1, 0), 71 SND_FORMAT(AFMT_U16_LE, 2, 0), 72 0 73 }; 74 75 static struct pcmchan_caps bcm2835_audio_playcaps = {8000, 48000, bcm2835_audio_playfmt, 0}; 76 77 struct bcm2835_audio_info; 78 79 #define PLAYBACK_IDLE 0 80 #define PLAYBACK_STARTING 1 81 #define PLAYBACK_PLAYING 2 82 #define PLAYBACK_STOPPING 3 83 84 struct bcm2835_audio_chinfo { 85 struct bcm2835_audio_info *parent; 86 struct pcm_channel *channel; 87 struct snd_dbuf *buffer; 88 uint32_t fmt, spd, blksz; 89 90 uint32_t complete_pos; 91 uint32_t free_buffer; 92 uint32_t buffered_ptr; 93 int playback_state; 94 }; 95 96 struct bcm2835_audio_info { 97 device_t dev; 98 unsigned int bufsz; 99 struct bcm2835_audio_chinfo pch; 100 uint32_t dest, volume; 101 struct mtx *lock; 102 struct intr_config_hook intr_hook; 103 104 /* VCHI data */ 105 struct mtx vchi_lock; 106 107 /* MSG reply */ 108 struct mtx msg_avail_lock; 109 struct cv msg_avail_cv; 110 uint32_t msg_result; 111 112 VCHI_INSTANCE_T vchi_instance; 113 VCHI_CONNECTION_T *vchi_connection; 114 VCHI_SERVICE_HANDLE_T vchi_handle; 115 116 struct mtx data_lock; 117 struct cv data_cv; 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) mtx_lock(&(sc)->vchi_lock) 128 #define VCHIQ_VCHI_UNLOCK(sc) mtx_unlock(&(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 sc->msg_result = m.u.result.success; 166 cv_signal(&sc->msg_avail_cv); 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 176 if (perr || ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE) { 177 chn_intr(ch->channel); 178 cv_signal(&sc->data_cv); 179 } 180 } else 181 printf("%s: unknown m.type: %d\n", __func__, m.type); 182 } 183 184 /* VCHIQ stuff */ 185 static void 186 bcm2835_audio_init(struct bcm2835_audio_info *sc) 187 { 188 int status; 189 190 /* Initialize and create a VCHI connection */ 191 status = vchi_initialise(&sc->vchi_instance); 192 if (status != 0) { 193 printf("vchi_initialise failed: %d\n", status); 194 return; 195 } 196 197 status = vchi_connect(NULL, 0, sc->vchi_instance); 198 if (status != 0) { 199 printf("vchi_connect failed: %d\n", status); 200 return; 201 } 202 203 SERVICE_CREATION_T params = { 204 VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER), 205 VC_AUDIO_SERVER_NAME, /* 4cc service code */ 206 sc->vchi_connection, /* passed in fn pointers */ 207 0, /* rx fifo size */ 208 0, /* tx fifo size */ 209 bcm2835_audio_callback, /* service callback */ 210 sc, /* service callback parameter */ 211 1, 212 1, 213 0 /* want crc check on bulk transfers */ 214 }; 215 216 status = vchi_service_open(sc->vchi_instance, ¶ms, 217 &sc->vchi_handle); 218 219 if (status == 0) 220 /* Finished with the service for now */ 221 vchi_service_release(sc->vchi_handle); 222 else 223 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID; 224 } 225 226 static void 227 bcm2835_audio_release(struct bcm2835_audio_info *sc) 228 { 229 int success; 230 231 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 232 vchi_service_use(sc->vchi_handle); 233 success = vchi_service_close(sc->vchi_handle); 234 if (success != 0) 235 printf("vchi_service_close failed: %d\n", success); 236 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID; 237 } 238 239 vchi_disconnect(sc->vchi_instance); 240 } 241 242 static void 243 bcm2835_audio_reset_channel(struct bcm2835_audio_chinfo *ch) 244 { 245 ch->free_buffer = VCHIQ_AUDIO_BUFFER_SIZE; 246 ch->playback_state = 0; 247 ch->buffered_ptr = 0; 248 ch->complete_pos = 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 sc->msg_result = -1; 337 338 m.type = VC_AUDIO_MSG_TYPE_CONTROL; 339 m.u.control.dest = sc->dest; 340 if (sc->volume > 99) 341 sc->volume = 99; 342 db = db_levels[sc->volume/5]; 343 m.u.control.volume = VCHIQ_AUDIO_VOLUME(db); 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 mtx_lock(&sc->msg_avail_lock); 352 cv_wait_sig(&sc->msg_avail_cv, &sc->msg_avail_lock); 353 if (sc->msg_result) 354 printf("%s failed: %d\n", __func__, sc->msg_result); 355 mtx_unlock(&sc->msg_avail_lock); 356 357 vchi_service_release(sc->vchi_handle); 358 } 359 VCHIQ_VCHI_UNLOCK(sc); 360 } 361 362 static void 363 bcm2835_audio_update_params(struct bcm2835_audio_info *sc, struct bcm2835_audio_chinfo *ch) 364 { 365 VC_AUDIO_MSG_T m; 366 int ret; 367 368 VCHIQ_VCHI_LOCK(sc); 369 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { 370 vchi_service_use(sc->vchi_handle); 371 372 sc->msg_result = -1; 373 374 m.type = VC_AUDIO_MSG_TYPE_CONFIG; 375 m.u.config.channels = AFMT_CHANNEL(ch->fmt); 376 m.u.config.samplerate = ch->spd; 377 m.u.config.bps = AFMT_BIT(ch->fmt); 378 379 ret = vchi_msg_queue(sc->vchi_handle, 380 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 381 382 if (ret != 0) 383 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 384 385 mtx_lock(&sc->msg_avail_lock); 386 cv_wait_sig(&sc->msg_avail_cv, &sc->msg_avail_lock); 387 if (sc->msg_result) 388 printf("%s failed: %d\n", __func__, sc->msg_result); 389 mtx_unlock(&sc->msg_avail_lock); 390 391 vchi_service_release(sc->vchi_handle); 392 } 393 VCHIQ_VCHI_UNLOCK(sc); 394 } 395 396 static __inline uint32_t 397 vchiq_unbuffered_bytes(struct bcm2835_audio_chinfo *ch) 398 { 399 uint32_t size, ready, readyptr, readyend; 400 401 size = sndbuf_getsize(ch->buffer); 402 readyptr = sndbuf_getreadyptr(ch->buffer); 403 ready = sndbuf_getready(ch->buffer); 404 405 readyend = readyptr + ready; 406 /* Normal case */ 407 if (ch->buffered_ptr >= readyptr) { 408 if (readyend > ch->buffered_ptr) 409 return readyend - ch->buffered_ptr; 410 else 411 return 0; 412 } 413 else { /* buffered_ptr overflow */ 414 if (readyend > ch->buffered_ptr + size) 415 return readyend - ch->buffered_ptr - size; 416 else 417 return 0; 418 } 419 } 420 421 static void 422 bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch) 423 { 424 struct bcm2835_audio_info *sc = ch->parent; 425 VC_AUDIO_MSG_T m; 426 void *buf; 427 uint32_t count, size; 428 int ret; 429 430 VCHIQ_VCHI_LOCK(sc); 431 if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) { 432 VCHIQ_VCHI_UNLOCK(sc); 433 return; 434 } 435 436 vchi_service_use(sc->vchi_handle); 437 438 size = sndbuf_getsize(ch->buffer); 439 count = vchiq_unbuffered_bytes(ch); 440 buf = (uint8_t*)sndbuf_getbuf(ch->buffer) + ch->buffered_ptr; 441 442 if (ch->buffered_ptr + count > size) 443 count = size - ch->buffered_ptr; 444 445 if (count < VCHIQ_AUDIO_PACKET_SIZE) 446 goto done; 447 448 count = min(count, ch->free_buffer); 449 count -= count % VCHIQ_AUDIO_PACKET_SIZE; 450 451 m.type = VC_AUDIO_MSG_TYPE_WRITE; 452 m.u.write.count = count; 453 m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE; 454 m.u.write.callback = NULL; 455 m.u.write.cookie = ch; 456 if (buf) 457 m.u.write.silence = 0; 458 else 459 m.u.write.silence = 1; 460 461 ret = vchi_msg_queue(sc->vchi_handle, 462 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 463 464 if (ret != 0) 465 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); 466 467 if (buf) { 468 while (count > 0) { 469 int bytes = MIN((int)m.u.write.max_packet, (int)count); 470 ch->free_buffer -= bytes; 471 ch->buffered_ptr += bytes; 472 ch->buffered_ptr = ch->buffered_ptr % size; 473 ret = vchi_msg_queue(sc->vchi_handle, 474 buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); 475 if (ret != 0) 476 printf("%s: vchi_msg_queue failed: %d\n", 477 __func__, ret); 478 buf = (char *)buf + bytes; 479 count -= bytes; 480 } 481 } 482 done: 483 484 vchi_service_release(sc->vchi_handle); 485 VCHIQ_VCHI_UNLOCK(sc); 486 } 487 488 static void 489 bcm2835_audio_worker(void *data) 490 { 491 struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)data; 492 struct bcm2835_audio_chinfo *ch = &sc->pch; 493 mtx_lock(&sc->data_lock); 494 while(1) { 495 496 if (sc->unloading) 497 break; 498 499 if ((ch->playback_state == PLAYBACK_PLAYING) && 500 (vchiq_unbuffered_bytes(ch) >= VCHIQ_AUDIO_PACKET_SIZE) 501 && (ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE)) { 502 bcm2835_audio_write_samples(ch); 503 } else { 504 if (ch->playback_state == PLAYBACK_STOPPING) { 505 bcm2835_audio_reset_channel(&sc->pch); 506 ch->playback_state = PLAYBACK_IDLE; 507 } 508 509 cv_wait_sig(&sc->data_cv, &sc->data_lock); 510 511 if (ch->playback_state == PLAYBACK_STARTING) { 512 /* Give it initial kick */ 513 chn_intr(sc->pch.channel); 514 ch->playback_state = PLAYBACK_PLAYING; 515 } 516 } 517 } 518 mtx_unlock(&sc->data_lock); 519 520 kproc_exit(0); 521 } 522 523 static void 524 bcm2835_audio_create_worker(struct bcm2835_audio_info *sc) 525 { 526 struct proc *newp; 527 528 if (kproc_create(bcm2835_audio_worker, (void*)sc, &newp, 0, 0, 529 "bcm2835_audio_worker") != 0) { 530 printf("failed to create bcm2835_audio_worker\n"); 531 } 532 } 533 534 /* -------------------------------------------------------------------- */ 535 /* channel interface for ESS18xx */ 536 static void * 537 bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 538 { 539 struct bcm2835_audio_info *sc = devinfo; 540 struct bcm2835_audio_chinfo *ch = &sc->pch; 541 void *buffer; 542 543 if (dir == PCMDIR_REC) 544 return NULL; 545 546 ch->parent = sc; 547 ch->channel = c; 548 ch->buffer = b; 549 550 /* default values */ 551 ch->spd = 44100; 552 ch->fmt = SND_FORMAT(AFMT_S16_LE, 2, 0); 553 ch->blksz = VCHIQ_AUDIO_PACKET_SIZE; 554 555 buffer = malloc(sc->bufsz, M_DEVBUF, M_WAITOK | M_ZERO); 556 557 if (sndbuf_setup(ch->buffer, buffer, sc->bufsz) != 0) { 558 free(buffer, M_DEVBUF); 559 return NULL; 560 } 561 562 bcm2835_audio_update_params(sc, ch); 563 564 return ch; 565 } 566 567 static int 568 bcmchan_free(kobj_t obj, void *data) 569 { 570 struct bcm2835_audio_chinfo *ch = data; 571 void *buffer; 572 573 buffer = sndbuf_getbuf(ch->buffer); 574 if (buffer) 575 free(buffer, M_DEVBUF); 576 577 return (0); 578 } 579 580 static int 581 bcmchan_setformat(kobj_t obj, void *data, uint32_t format) 582 { 583 struct bcm2835_audio_chinfo *ch = data; 584 struct bcm2835_audio_info *sc = ch->parent; 585 586 bcm2835_audio_lock(sc); 587 588 ch->fmt = format; 589 bcm2835_audio_update_params(sc, ch); 590 591 bcm2835_audio_unlock(sc); 592 593 return 0; 594 } 595 596 static uint32_t 597 bcmchan_setspeed(kobj_t obj, void *data, uint32_t speed) 598 { 599 struct bcm2835_audio_chinfo *ch = data; 600 struct bcm2835_audio_info *sc = ch->parent; 601 602 bcm2835_audio_lock(sc); 603 604 ch->spd = speed; 605 bcm2835_audio_update_params(sc, ch); 606 607 bcm2835_audio_unlock(sc); 608 609 return ch->spd; 610 } 611 612 static uint32_t 613 bcmchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 614 { 615 struct bcm2835_audio_chinfo *ch = data; 616 617 return ch->blksz; 618 } 619 620 static int 621 bcmchan_trigger(kobj_t obj, void *data, int go) 622 { 623 struct bcm2835_audio_chinfo *ch = data; 624 struct bcm2835_audio_info *sc = ch->parent; 625 626 if (!PCMTRIG_COMMON(go)) 627 return (0); 628 629 bcm2835_audio_lock(sc); 630 631 switch (go) { 632 case PCMTRIG_START: 633 bcm2835_audio_start(ch); 634 ch->playback_state = PLAYBACK_STARTING; 635 /* wakeup worker thread */ 636 cv_signal(&sc->data_cv); 637 break; 638 639 case PCMTRIG_STOP: 640 case PCMTRIG_ABORT: 641 ch->playback_state = 1; 642 bcm2835_audio_stop(ch); 643 break; 644 645 default: 646 break; 647 } 648 649 bcm2835_audio_unlock(sc); 650 return 0; 651 } 652 653 static uint32_t 654 bcmchan_getptr(kobj_t obj, void *data) 655 { 656 struct bcm2835_audio_chinfo *ch = data; 657 struct bcm2835_audio_info *sc = ch->parent; 658 uint32_t ret; 659 660 bcm2835_audio_lock(sc); 661 662 ret = ch->complete_pos - (ch->complete_pos % VCHIQ_AUDIO_PACKET_SIZE); 663 664 bcm2835_audio_unlock(sc); 665 666 return ret; 667 } 668 669 static struct pcmchan_caps * 670 bcmchan_getcaps(kobj_t obj, void *data) 671 { 672 673 return &bcm2835_audio_playcaps; 674 } 675 676 static kobj_method_t bcmchan_methods[] = { 677 KOBJMETHOD(channel_init, bcmchan_init), 678 KOBJMETHOD(channel_free, bcmchan_free), 679 KOBJMETHOD(channel_setformat, bcmchan_setformat), 680 KOBJMETHOD(channel_setspeed, bcmchan_setspeed), 681 KOBJMETHOD(channel_setblocksize, bcmchan_setblocksize), 682 KOBJMETHOD(channel_trigger, bcmchan_trigger), 683 KOBJMETHOD(channel_getptr, bcmchan_getptr), 684 KOBJMETHOD(channel_getcaps, bcmchan_getcaps), 685 KOBJMETHOD_END 686 }; 687 CHANNEL_DECLARE(bcmchan); 688 689 /************************************************************/ 690 691 static int 692 bcmmix_init(struct snd_mixer *m) 693 { 694 695 mix_setdevs(m, SOUND_MASK_VOLUME); 696 697 return (0); 698 } 699 700 static int 701 bcmmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 702 { 703 struct bcm2835_audio_info *sc = mix_getdevinfo(m); 704 705 switch (dev) { 706 case SOUND_MIXER_VOLUME: 707 sc->volume = left; 708 bcm2835_audio_update_controls(sc); 709 break; 710 711 default: 712 break; 713 } 714 715 return left | (left << 8); 716 } 717 718 static kobj_method_t bcmmixer_methods[] = { 719 KOBJMETHOD(mixer_init, bcmmix_init), 720 KOBJMETHOD(mixer_set, bcmmix_set), 721 KOBJMETHOD_END 722 }; 723 724 MIXER_DECLARE(bcmmixer); 725 726 static int 727 sysctl_bcm2835_audio_dest(SYSCTL_HANDLER_ARGS) 728 { 729 struct bcm2835_audio_info *sc = arg1; 730 int val; 731 int err; 732 733 val = sc->dest; 734 err = sysctl_handle_int(oidp, &val, 0, req); 735 if (err || !req->newptr) /* error || read request */ 736 return (err); 737 738 if ((val < 0) || (val > 2)) 739 return (EINVAL); 740 741 sc->dest = val; 742 device_printf(sc->dev, "destination set to %s\n", dest_description(val)); 743 bcm2835_audio_update_controls(sc); 744 745 return (0); 746 } 747 748 static void 749 vchi_audio_sysctl_init(struct bcm2835_audio_info *sc) 750 { 751 struct sysctl_ctx_list *ctx; 752 struct sysctl_oid *tree_node; 753 struct sysctl_oid_list *tree; 754 755 /* 756 * Add system sysctl tree/handlers. 757 */ 758 ctx = device_get_sysctl_ctx(sc->dev); 759 tree_node = device_get_sysctl_tree(sc->dev); 760 tree = SYSCTL_CHILDREN(tree_node); 761 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "dest", 762 CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc), 763 sysctl_bcm2835_audio_dest, "IU", "audio destination, " 764 "0 - auto, 1 - headphones, 2 - HDMI"); 765 } 766 767 static void 768 bcm2835_audio_identify(driver_t *driver, device_t parent) 769 { 770 771 BUS_ADD_CHILD(parent, 0, "pcm", 0); 772 } 773 774 static int 775 bcm2835_audio_probe(device_t dev) 776 { 777 778 device_set_desc(dev, "VCHQI audio"); 779 return (BUS_PROBE_DEFAULT); 780 } 781 782 783 static void 784 bcm2835_audio_delayed_init(void *xsc) 785 { 786 struct bcm2835_audio_info *sc; 787 char status[SND_STATUSLEN]; 788 789 sc = xsc; 790 791 config_intrhook_disestablish(&sc->intr_hook); 792 793 bcm2835_audio_init(sc); 794 bcm2835_audio_open(sc); 795 sc->volume = 75; 796 sc->dest = DEST_AUTO; 797 798 if (mixer_init(sc->dev, &bcmmixer_class, sc)) { 799 device_printf(sc->dev, "mixer_init failed\n"); 800 goto no; 801 } 802 803 if (pcm_register(sc->dev, sc, 1, 1)) { 804 device_printf(sc->dev, "pcm_register failed\n"); 805 goto no; 806 } 807 808 pcm_addchan(sc->dev, PCMDIR_PLAY, &bcmchan_class, sc); 809 snprintf(status, SND_STATUSLEN, "at VCHIQ"); 810 pcm_setstatus(sc->dev, status); 811 812 bcm2835_audio_reset_channel(&sc->pch); 813 bcm2835_audio_create_worker(sc); 814 815 vchi_audio_sysctl_init(sc); 816 817 no: 818 ; 819 } 820 821 static int 822 bcm2835_audio_attach(device_t dev) 823 { 824 struct bcm2835_audio_info *sc; 825 826 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 827 828 sc->dev = dev; 829 sc->bufsz = VCHIQ_AUDIO_BUFFER_SIZE; 830 831 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "bcm2835_audio softc"); 832 833 mtx_init(&sc->vchi_lock, "bcm2835_audio", "vchi_lock", MTX_DEF); 834 mtx_init(&sc->msg_avail_lock, "msg_avail_mtx", "msg_avail_mtx", MTX_DEF); 835 cv_init(&sc->msg_avail_cv, "msg_avail_cv"); 836 mtx_init(&sc->data_lock, "data_mtx", "data_mtx", MTX_DEF); 837 cv_init(&sc->data_cv, "data_cv"); 838 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID; 839 840 /* 841 * We need interrupts enabled for VCHI to work properly, 842 * so delay intialization until it happens 843 */ 844 sc->intr_hook.ich_func = bcm2835_audio_delayed_init; 845 sc->intr_hook.ich_arg = sc; 846 847 if (config_intrhook_establish(&sc->intr_hook) != 0) 848 goto no; 849 850 return 0; 851 852 no: 853 return ENXIO; 854 } 855 856 static int 857 bcm2835_audio_detach(device_t dev) 858 { 859 int r; 860 struct bcm2835_audio_info *sc; 861 sc = pcm_getdevinfo(dev); 862 863 /* Stop worker thread */ 864 sc->unloading = 1; 865 cv_signal(&sc->data_cv); 866 867 r = pcm_unregister(dev); 868 if (r) 869 return r; 870 871 mtx_destroy(&sc->vchi_lock); 872 mtx_destroy(&sc->msg_avail_lock); 873 cv_destroy(&sc->msg_avail_cv); 874 mtx_destroy(&sc->data_lock); 875 cv_destroy(&sc->data_cv); 876 877 bcm2835_audio_release(sc); 878 879 if (sc->lock) { 880 snd_mtxfree(sc->lock); 881 sc->lock = NULL; 882 } 883 884 free(sc, M_DEVBUF); 885 886 return 0; 887 } 888 889 static device_method_t bcm2835_audio_methods[] = { 890 /* Device interface */ 891 DEVMETHOD(device_identify, bcm2835_audio_identify), 892 DEVMETHOD(device_probe, bcm2835_audio_probe), 893 DEVMETHOD(device_attach, bcm2835_audio_attach), 894 DEVMETHOD(device_detach, bcm2835_audio_detach), 895 896 { 0, 0 } 897 }; 898 899 static driver_t bcm2835_audio_driver = { 900 "pcm", 901 bcm2835_audio_methods, 902 PCM_SOFTC_SIZE, 903 }; 904 905 DRIVER_MODULE(bcm2835_audio, vchiq, bcm2835_audio_driver, pcm_devclass, 0, 0); 906 MODULE_DEPEND(bcm2835_audio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 907 MODULE_DEPEND(bcm2835_audio, vchiq, 1, 1, 1); 908 MODULE_VERSION(bcm2835_audio, 1); 909