2 * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
26 #ifdef HAVE_KERNEL_OPTION_HEADERS
30 #include <dev/sound/pcm/sound.h>
31 #include <dev/sound/chip.h>
35 #include "interface/compat/vchi_bsd.h"
36 #include "interface/vchi/vchi.h"
37 #include "interface/vchiq_arm/vchiq.h"
39 #include "vc_vchi_audioserv_defs.h"
41 SND_DECLARE_FILE("$FreeBSD$");
44 #define DEST_HEADPHONES 1
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 */
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)
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,
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),
76 static struct pcmchan_caps bcm2835_audio_playcaps = {8000, 48000, bcm2835_audio_playfmt, 0};
78 struct bcm2835_audio_info;
80 #define PLAYBACK_IDLE 0
81 #define PLAYBACK_STARTING 1
82 #define PLAYBACK_PLAYING 2
83 #define PLAYBACK_STOPPING 3
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;
91 uint32_t complete_pos;
93 uint32_t buffered_ptr;
98 struct bcm2835_audio_info {
101 struct bcm2835_audio_chinfo pch;
102 uint32_t dest, volume;
104 struct intr_config_hook intr_hook;
109 VCHI_INSTANCE_T vchi_instance;
110 VCHI_CONNECTION_T *vchi_connection;
111 VCHI_SERVICE_HANDLE_T vchi_handle;
113 struct sx worker_lock;
116 bool parameters_update_pending;
117 bool controls_update_pending;
119 /* Unloadign module */
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)
127 #define VCHIQ_VCHI_LOCK(sc) sx_xlock(&(sc)->vchi_lock)
128 #define VCHIQ_VCHI_UNLOCK(sc) sx_xunlock(&(sc)->vchi_lock)
131 dest_description(uint32_t dest)
138 case DEST_HEADPHONES:
152 bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle)
154 struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)param;
159 if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
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",
170 } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
171 struct bcm2835_audio_chinfo *ch = m.u.complete.cookie;
173 int count = m.u.complete.count & 0xffff;
174 int perr = (m.u.complete.count & (1U << 30)) != 0;
176 ch->complete_pos = (ch->complete_pos + count) % sndbuf_getsize(ch->buffer);
177 ch->free_buffer += count;
178 chn_intr(sc->pch.channel);
180 if (perr || ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE)
181 cv_signal(&sc->worker_cv);
183 printf("%s: unknown m.type: %d\n", __func__, m.type);
188 bcm2835_audio_init(struct bcm2835_audio_info *sc)
192 /* Initialize and create a VCHI connection */
193 status = vchi_initialise(&sc->vchi_instance);
195 printf("vchi_initialise failed: %d\n", status);
199 status = vchi_connect(NULL, 0, sc->vchi_instance);
201 printf("vchi_connect failed: %d\n", status);
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 */
215 0 /* want crc check on bulk transfers */
218 status = vchi_service_open(sc->vchi_instance, ¶ms,
222 /* Finished with the service for now */
223 vchi_service_release(sc->vchi_handle);
225 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
229 bcm2835_audio_release(struct bcm2835_audio_info *sc)
233 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
234 vchi_service_use(sc->vchi_handle);
235 success = vchi_service_close(sc->vchi_handle);
237 printf("vchi_service_close failed: %d\n", success);
238 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
241 vchi_disconnect(sc->vchi_instance);
245 bcm2835_audio_reset_channel(struct bcm2835_audio_chinfo *ch)
247 ch->free_buffer = VCHIQ_AUDIO_BUFFER_SIZE;
248 ch->playback_state = 0;
249 ch->buffered_ptr = 0;
250 ch->complete_pos = 0;
253 sndbuf_reset(ch->buffer);
257 bcm2835_audio_start(struct bcm2835_audio_chinfo *ch)
261 struct bcm2835_audio_info *sc = ch->parent;
264 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
265 vchi_service_use(sc->vchi_handle);
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);
272 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
274 vchi_service_release(sc->vchi_handle);
276 VCHIQ_VCHI_UNLOCK(sc);
281 bcm2835_audio_stop(struct bcm2835_audio_chinfo *ch)
285 struct bcm2835_audio_info *sc = ch->parent;
288 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
289 vchi_service_use(sc->vchi_handle);
291 m.type = VC_AUDIO_MSG_TYPE_STOP;
292 m.u.stop.draining = 0;
294 ret = vchi_msg_queue(sc->vchi_handle,
295 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
298 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
300 vchi_service_release(sc->vchi_handle);
302 VCHIQ_VCHI_UNLOCK(sc);
306 bcm2835_audio_open(struct bcm2835_audio_info *sc)
312 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
313 vchi_service_use(sc->vchi_handle);
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);
320 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
322 vchi_service_release(sc->vchi_handle);
324 VCHIQ_VCHI_UNLOCK(sc);
328 bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, uint32_t dest)
334 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
335 vchi_service_use(sc->vchi_handle);
337 m.type = VC_AUDIO_MSG_TYPE_CONTROL;
338 m.u.control.dest = dest;
341 db = db_levels[volume/5];
342 m.u.control.volume = VCHIQ_AUDIO_VOLUME(db);
344 ret = vchi_msg_queue(sc->vchi_handle,
345 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
348 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
350 vchi_service_release(sc->vchi_handle);
352 VCHIQ_VCHI_UNLOCK(sc);
356 bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_t speed)
362 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
363 vchi_service_use(sc->vchi_handle);
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);
370 ret = vchi_msg_queue(sc->vchi_handle,
371 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
374 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
376 vchi_service_release(sc->vchi_handle);
378 VCHIQ_VCHI_UNLOCK(sc);
381 static __inline uint32_t
382 vchiq_unbuffered_bytes(struct bcm2835_audio_chinfo *ch)
384 uint32_t size, ready, readyptr, readyend;
386 size = sndbuf_getsize(ch->buffer);
387 readyptr = sndbuf_getreadyptr(ch->buffer);
388 ready = sndbuf_getready(ch->buffer);
390 readyend = readyptr + ready;
392 if (ch->buffered_ptr >= readyptr) {
393 if (readyend > ch->buffered_ptr)
394 return readyend - ch->buffered_ptr;
398 else { /* buffered_ptr overflow */
399 if (readyend > ch->buffered_ptr + size)
400 return readyend - ch->buffered_ptr - size;
407 bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch)
409 struct bcm2835_audio_info *sc = ch->parent;
412 uint32_t count, size;
416 if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) {
417 VCHIQ_VCHI_UNLOCK(sc);
421 vchi_service_use(sc->vchi_handle);
423 size = sndbuf_getsize(ch->buffer);
424 count = vchiq_unbuffered_bytes(ch);
425 buf = (uint8_t*)sndbuf_getbuf(ch->buffer) + ch->buffered_ptr;
427 if (ch->buffered_ptr + count > size)
428 count = size - ch->buffered_ptr;
430 if (count < VCHIQ_AUDIO_PACKET_SIZE)
433 count = min(count, ch->free_buffer);
434 count -= count % VCHIQ_AUDIO_PACKET_SIZE;
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;
442 m.u.write.silence = 0;
444 m.u.write.silence = 1;
446 ret = vchi_msg_queue(sc->vchi_handle,
447 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
450 printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
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);
461 printf("%s: vchi_msg_queue failed: %d\n",
463 buf = (char *)buf + bytes;
469 vchi_service_release(sc->vchi_handle);
470 VCHIQ_VCHI_UNLOCK(sc);
474 bcm2835_audio_worker(void *data)
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;
482 sx_slock(&sc->worker_lock);
488 parameters_changed = false;
489 controls_changed = false;
490 bcm2835_audio_lock(sc);
491 if (sc->parameters_update_pending) {
492 /* TODO: update parameters */
495 sc->parameters_update_pending = false;
496 parameters_changed = true;
499 if (sc->controls_update_pending) {
502 sc->controls_update_pending = false;
503 controls_changed = true;
506 bcm2835_audio_unlock(sc);
508 if (parameters_changed) {
509 bcm2835_audio_update_params(sc, format, speed);
512 if (controls_changed) {
513 bcm2835_audio_update_controls(sc, volume, dest);
516 if (ch->playback_state == PLAYBACK_IDLE) {
517 cv_wait_sig(&sc->worker_cv, &sc->worker_lock);
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;
528 if (ch->free_buffer < vchiq_unbuffered_bytes(ch)) {
529 cv_timedwait_sig(&sc->worker_cv, &sc->worker_lock, 10);
533 bcm2835_audio_write_samples(ch);
535 if (ch->playback_state == PLAYBACK_STARTING) {
537 if (ch->prebuffered == VCHIQ_AUDIO_PREBUFFER) {
538 bcm2835_audio_start(ch);
539 ch->playback_state = PLAYBACK_PLAYING;
543 sx_sunlock(&sc->worker_lock);
549 bcm2835_audio_create_worker(struct bcm2835_audio_info *sc)
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");
559 /* -------------------------------------------------------------------- */
560 /* channel interface for VCHI audio */
562 bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
564 struct bcm2835_audio_info *sc = devinfo;
565 struct bcm2835_audio_chinfo *ch = &sc->pch;
568 if (dir == PCMDIR_REC)
577 ch->fmt = SND_FORMAT(AFMT_S16_LE, 2, 0);
578 ch->blksz = VCHIQ_AUDIO_PACKET_SIZE;
580 buffer = malloc(sc->bufsz, M_DEVBUF, M_WAITOK | M_ZERO);
582 if (sndbuf_setup(ch->buffer, buffer, sc->bufsz) != 0) {
583 device_printf(sc->dev, "sndbuf_setup failed\n");
584 free(buffer, M_DEVBUF);
588 sc->parameters_update_pending = true;
589 cv_signal(&sc->worker_cv);
595 bcmchan_free(kobj_t obj, void *data)
597 struct bcm2835_audio_chinfo *ch = data;
600 buffer = sndbuf_getbuf(ch->buffer);
602 free(buffer, M_DEVBUF);
608 bcmchan_setformat(kobj_t obj, void *data, uint32_t format)
610 struct bcm2835_audio_chinfo *ch = data;
611 struct bcm2835_audio_info *sc = ch->parent;
613 bcm2835_audio_lock(sc);
615 sc->parameters_update_pending = true;
616 bcm2835_audio_unlock(sc);
618 cv_signal(&sc->worker_cv);
624 bcmchan_setspeed(kobj_t obj, void *data, uint32_t speed)
626 struct bcm2835_audio_chinfo *ch = data;
627 struct bcm2835_audio_info *sc = ch->parent;
629 bcm2835_audio_lock(sc);
631 sc->parameters_update_pending = true;
632 bcm2835_audio_unlock(sc);
634 cv_signal(&sc->worker_cv);
640 bcmchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
642 struct bcm2835_audio_chinfo *ch = data;
648 bcmchan_trigger(kobj_t obj, void *data, int go)
650 struct bcm2835_audio_chinfo *ch = data;
651 struct bcm2835_audio_info *sc = ch->parent;
653 if (!PCMTRIG_COMMON(go))
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);
671 bcm2835_audio_lock(sc);
672 ch->playback_state = PLAYBACK_STOPPING;
673 bcm2835_audio_unlock(sc);
674 cv_signal(&sc->worker_cv);
684 bcmchan_getptr(kobj_t obj, void *data)
686 struct bcm2835_audio_chinfo *ch = data;
687 struct bcm2835_audio_info *sc = ch->parent;
690 bcm2835_audio_lock(sc);
692 ret = ch->complete_pos - (ch->complete_pos % VCHIQ_AUDIO_PACKET_SIZE);
694 bcm2835_audio_unlock(sc);
699 static struct pcmchan_caps *
700 bcmchan_getcaps(kobj_t obj, void *data)
703 return &bcm2835_audio_playcaps;
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),
717 CHANNEL_DECLARE(bcmchan);
719 /************************************************************/
722 bcmmix_init(struct snd_mixer *m)
725 mix_setdevs(m, SOUND_MASK_VOLUME);
731 bcmmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
733 struct bcm2835_audio_info *sc = mix_getdevinfo(m);
736 case SOUND_MIXER_VOLUME:
737 bcm2835_audio_lock(sc);
739 sc->controls_update_pending = true;
740 bcm2835_audio_unlock(sc);
741 cv_signal(&sc->worker_cv);
748 return left | (left << 8);
751 static kobj_method_t bcmmixer_methods[] = {
752 KOBJMETHOD(mixer_init, bcmmix_init),
753 KOBJMETHOD(mixer_set, bcmmix_set),
757 MIXER_DECLARE(bcmmixer);
760 sysctl_bcm2835_audio_dest(SYSCTL_HANDLER_ARGS)
762 struct bcm2835_audio_info *sc = arg1;
767 err = sysctl_handle_int(oidp, &val, 0, req);
768 if (err || !req->newptr) /* error || read request */
771 if ((val < 0) || (val > 2))
774 bcm2835_audio_lock(sc);
776 sc->controls_update_pending = true;
777 bcm2835_audio_unlock(sc);
779 cv_signal(&sc->worker_cv);
780 device_printf(sc->dev, "destination set to %s\n", dest_description(val));
786 vchi_audio_sysctl_init(struct bcm2835_audio_info *sc)
788 struct sysctl_ctx_list *ctx;
789 struct sysctl_oid *tree_node;
790 struct sysctl_oid_list *tree;
793 * Add system sysctl tree/handlers.
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");
805 bcm2835_audio_identify(driver_t *driver, device_t parent)
808 BUS_ADD_CHILD(parent, 0, "pcm", 0);
812 bcm2835_audio_probe(device_t dev)
815 device_set_desc(dev, "VCHIQ audio");
816 return (BUS_PROBE_DEFAULT);
821 bcm2835_audio_delayed_init(void *xsc)
823 struct bcm2835_audio_info *sc;
824 char status[SND_STATUSLEN];
828 config_intrhook_disestablish(&sc->intr_hook);
830 bcm2835_audio_init(sc);
831 bcm2835_audio_open(sc);
833 sc->dest = DEST_AUTO;
835 if (mixer_init(sc->dev, &bcmmixer_class, sc)) {
836 device_printf(sc->dev, "mixer_init failed\n");
840 if (pcm_register(sc->dev, sc, 1, 1)) {
841 device_printf(sc->dev, "pcm_register failed\n");
845 pcm_addchan(sc->dev, PCMDIR_PLAY, &bcmchan_class, sc);
846 snprintf(status, SND_STATUSLEN, "at VCHIQ");
847 pcm_setstatus(sc->dev, status);
849 bcm2835_audio_reset_channel(&sc->pch);
850 bcm2835_audio_create_worker(sc);
852 vchi_audio_sysctl_init(sc);
859 bcm2835_audio_attach(device_t dev)
861 struct bcm2835_audio_info *sc;
863 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
866 sc->bufsz = VCHIQ_AUDIO_BUFFER_SIZE;
868 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "bcm2835_audio softc");
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;
876 * We need interrupts enabled for VCHI to work properly,
877 * so delay initialization until it happens.
879 sc->intr_hook.ich_func = bcm2835_audio_delayed_init;
880 sc->intr_hook.ich_arg = sc;
882 if (config_intrhook_establish(&sc->intr_hook) != 0)
892 bcm2835_audio_detach(device_t dev)
895 struct bcm2835_audio_info *sc;
896 sc = pcm_getdevinfo(dev);
898 /* Stop worker thread */
899 sx_xlock(&sc->worker_lock);
901 sx_xunlock(&sc->worker_lock);
902 cv_signal(&sc->worker_cv);
904 r = pcm_unregister(dev);
908 sx_destroy(&sc->vchi_lock);
909 sx_destroy(&sc->worker_lock);
910 cv_destroy(&sc->worker_cv);
912 bcm2835_audio_release(sc);
915 snd_mtxfree(sc->lock);
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),
934 static driver_t bcm2835_audio_driver = {
936 bcm2835_audio_methods,
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);