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