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
32 #include "mixer_if.h"
33
34 #include "interface/compat/vchi_bsd.h"
35 #include "interface/vchi/vchi.h"
36 #include "interface/vchiq_arm/vchiq.h"
37
38 #include "vc_vchi_audioserv_defs.h"
39
40 /* Audio destination */
41 #define DEST_AUTO 0
42 #define DEST_HEADPHONES 1
43 #define DEST_HDMI 2
44
45 /* Playback state */
46 #define PLAYBACK_IDLE 0
47 #define PLAYBACK_PLAYING 1
48 #define PLAYBACK_STOPPING 2
49
50 /* Worker thread state */
51 #define WORKER_RUNNING 0
52 #define WORKER_STOPPING 1
53 #define WORKER_STOPPED 2
54
55 /*
56 * Worker thread flags, set to 1 in flags_pending
57 * when driver requests one or another operation
58 * from worker. Cleared to 0 once worker performs
59 * the operations.
60 */
61 #define AUDIO_PARAMS (1 << 0)
62 #define AUDIO_PLAY (1 << 1)
63 #define AUDIO_STOP (1 << 2)
64
65 #define VCHIQ_AUDIO_PACKET_SIZE 4000
66 #define VCHIQ_AUDIO_BUFFER_SIZE 10*VCHIQ_AUDIO_PACKET_SIZE
67
68 #define VCHIQ_AUDIO_MAX_VOLUME
69 /* volume in terms of 0.01dB */
70 #define VCHIQ_AUDIO_VOLUME_MIN -10239
71 #define VCHIQ_AUDIO_VOLUME(db100) (uint32_t)(-((db100) << 8)/100)
72
73 /* dB levels with 5% volume step */
74 static int db_levels[] = {
75 VCHIQ_AUDIO_VOLUME_MIN, -4605, -3794, -3218, -2772,
76 -2407, -2099, -1832, -1597, -1386,
77 -1195, -1021, -861, -713, -575,
78 -446, -325, -210, -102, 0,
79 };
80
81 static uint32_t bcm2835_audio_playfmt[] = {
82 SND_FORMAT(AFMT_U8, 1, 0),
83 SND_FORMAT(AFMT_U8, 2, 0),
84 SND_FORMAT(AFMT_S8, 1, 0),
85 SND_FORMAT(AFMT_S8, 2, 0),
86 SND_FORMAT(AFMT_S16_LE, 1, 0),
87 SND_FORMAT(AFMT_S16_LE, 2, 0),
88 SND_FORMAT(AFMT_U16_LE, 1, 0),
89 SND_FORMAT(AFMT_U16_LE, 2, 0),
90 0
91 };
92
93 static struct pcmchan_caps bcm2835_audio_playcaps = {8000, 48000, bcm2835_audio_playfmt, 0};
94
95 struct bcm2835_audio_info;
96
97 struct bcm2835_audio_chinfo {
98 struct bcm2835_audio_info *parent;
99 struct pcm_channel *channel;
100 struct snd_dbuf *buffer;
101 uint32_t fmt, spd, blksz;
102
103 /* Pointer to first unsubmitted sample */
104 uint32_t unsubmittedptr;
105 /*
106 * Number of bytes in "submitted but not played"
107 * pseudo-buffer
108 */
109 int available_space;
110 int playback_state;
111 uint64_t callbacks;
112 uint64_t submitted_samples;
113 uint64_t retrieved_samples;
114 uint64_t underruns;
115 int starved;
116 struct bcm_log_vars {
117 unsigned int bsize ;
118 int slept_for_lack_of_space ;
119 } log_vars;
120 #define DEFAULT_LOG_VALUES \
121 ((struct bcm_log_vars) { .bsize = 0 , .slept_for_lack_of_space = 0 })
122 };
123
124 struct bcm2835_audio_info {
125 device_t dev;
126 unsigned int bufsz;
127 struct bcm2835_audio_chinfo pch;
128 uint32_t dest, volume;
129 struct intr_config_hook intr_hook;
130
131 /* VCHI data */
132 VCHI_INSTANCE_T vchi_instance;
133 VCHI_CONNECTION_T *vchi_connection;
134 VCHI_SERVICE_HANDLE_T vchi_handle;
135
136 struct mtx lock;
137 struct cv worker_cv;
138
139 uint32_t flags_pending;
140
141 int verbose_trace;
142 /* Worker thread state */
143 int worker_state;
144 };
145
146 #define BCM2835_AUDIO_LOCK(sc) mtx_lock(&(sc)->lock)
147 #define BCM2835_AUDIO_LOCKED(sc) mtx_assert(&(sc)->lock, MA_OWNED)
148 #define BCM2835_AUDIO_UNLOCK(sc) mtx_unlock(&(sc)->lock)
149
150 #define BCM2835_LOG_ERROR(sc,...) \
151 do { \
152 device_printf((sc)->dev, __VA_ARGS__); \
153 } while(0)
154
155 #define BCM2835_LOG_INFO(sc,...) \
156 do { \
157 if (sc->verbose_trace > 0) \
158 device_printf((sc)->dev, __VA_ARGS__); \
159 } while(0)
160
161 #define BCM2835_LOG_WARN(sc,...) \
162 do { \
163 if (sc->verbose_trace > 1) \
164 device_printf((sc)->dev, __VA_ARGS__); \
165 } while(0)
166
167 #define BCM2835_LOG_TRACE(sc,...) \
168 do { \
169 if(sc->verbose_trace > 2) \
170 device_printf((sc)->dev, __VA_ARGS__); \
171 } while(0)
172
173 /* Useful for circular buffer calcs */
174 #define MOD_DIFF(front,rear,mod) (((mod) + (front) - (rear)) % (mod))
175
176
177 static const char *
dest_description(uint32_t dest)178 dest_description(uint32_t dest)
179 {
180 switch (dest) {
181 case DEST_AUTO:
182 return "AUTO";
183 break;
184
185 case DEST_HEADPHONES:
186 return "HEADPHONES";
187 break;
188
189 case DEST_HDMI:
190 return "HDMI";
191 break;
192 default:
193 return "UNKNOWN";
194 break;
195 }
196 }
197
198 static void
bcm2835_worker_update_params(struct bcm2835_audio_info * sc)199 bcm2835_worker_update_params(struct bcm2835_audio_info *sc)
200 {
201
202 BCM2835_AUDIO_LOCKED(sc);
203
204 sc->flags_pending |= AUDIO_PARAMS;
205 cv_signal(&sc->worker_cv);
206 }
207
208 static void
bcm2835_worker_play_start(struct bcm2835_audio_info * sc)209 bcm2835_worker_play_start(struct bcm2835_audio_info *sc)
210 {
211 BCM2835_AUDIO_LOCK(sc);
212 sc->flags_pending &= ~(AUDIO_STOP);
213 sc->flags_pending |= AUDIO_PLAY;
214 cv_signal(&sc->worker_cv);
215 BCM2835_AUDIO_UNLOCK(sc);
216 }
217
218 static void
bcm2835_worker_play_stop(struct bcm2835_audio_info * sc)219 bcm2835_worker_play_stop(struct bcm2835_audio_info *sc)
220 {
221 BCM2835_AUDIO_LOCK(sc);
222 sc->flags_pending &= ~(AUDIO_PLAY);
223 sc->flags_pending |= AUDIO_STOP;
224 cv_signal(&sc->worker_cv);
225 BCM2835_AUDIO_UNLOCK(sc);
226 }
227
228 static void
bcm2835_audio_callback(void * param,const VCHI_CALLBACK_REASON_T reason,void * msg_handle)229 bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle)
230 {
231 struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)param;
232 int32_t status;
233 uint32_t msg_len;
234 VC_AUDIO_MSG_T m;
235
236 if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
237 return;
238
239 status = vchi_msg_dequeue(sc->vchi_handle,
240 &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);
241 if (status != 0)
242 return;
243 if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
244 if (m.u.result.success) {
245 device_printf(sc->dev,
246 "msg type %08x failed\n",
247 m.type);
248 }
249 } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
250 unsigned int signaled = 0;
251 struct bcm2835_audio_chinfo *ch ;
252 #if defined(__aarch64__)
253 ch = (void *) ((((size_t)m.u.complete.callback) << 32)
254 | ((size_t)m.u.complete.cookie));
255 #else
256 ch = (void *) (m.u.complete.cookie);
257 #endif
258
259 int count = m.u.complete.count & 0xffff;
260 int perr = (m.u.complete.count & (1U << 30)) != 0;
261
262 BCM2835_LOG_TRACE(sc, "in:: count:0x%x perr:%d\n",
263 m.u.complete.count, perr);
264
265 ch->callbacks++;
266 if (perr)
267 ch->underruns++;
268
269 BCM2835_AUDIO_LOCK(sc);
270 if (ch->playback_state != PLAYBACK_IDLE) {
271 /* Prevent LOR */
272 BCM2835_AUDIO_UNLOCK(sc);
273 chn_intr(sc->pch.channel);
274 BCM2835_AUDIO_LOCK(sc);
275 }
276 /* We should check again, state might have changed */
277 if (ch->playback_state != PLAYBACK_IDLE) {
278 if (!perr) {
279 if ((ch->available_space + count)> VCHIQ_AUDIO_BUFFER_SIZE) {
280 device_printf(sc->dev, "inconsistent data in callback:\n");
281 device_printf(sc->dev, "available_space == %d, count = %d, perr=%d\n",
282 ch->available_space, count, perr);
283 device_printf(sc->dev,
284 "retrieved_samples = %ju, submitted_samples = %ju\n",
285 (uintmax_t)ch->retrieved_samples,
286 (uintmax_t)ch->submitted_samples);
287 }
288 }
289 ch->available_space += count;
290 ch->retrieved_samples += count;
291 /*
292 * XXXMDC
293 * Experimental: if VC says it's empty, believe it
294 * Has to come after the usual adjustments
295 */
296 if(perr){
297 ch->available_space = VCHIQ_AUDIO_BUFFER_SIZE;
298 perr = ch->retrieved_samples; // shd be != 0
299 }
300
301 if ((ch->available_space >= 1*VCHIQ_AUDIO_PACKET_SIZE)){
302 cv_signal(&sc->worker_cv);
303 signaled = 1;
304 }
305 }
306 BCM2835_AUDIO_UNLOCK(sc);
307 if(perr){
308 BCM2835_LOG_WARN(sc,
309 "VC starved; reported %u for a total of %u\n"
310 "worker %s\n", count, perr,
311 (signaled ? "signaled": "not signaled"));
312 }
313 } else
314 BCM2835_LOG_WARN(sc, "%s: unknown m.type: %d\n", __func__,
315 m.type);
316 }
317
318 /* VCHIQ stuff */
319 static void
bcm2835_audio_init(struct bcm2835_audio_info * sc)320 bcm2835_audio_init(struct bcm2835_audio_info *sc)
321 {
322 int status;
323
324 /* Initialize and create a VCHI connection */
325 status = vchi_initialise(&sc->vchi_instance);
326 if (status != 0) {
327 BCM2835_LOG_ERROR(sc, "vchi_initialise failed: %d\n", status);
328 return;
329 }
330
331 status = vchi_connect(NULL, 0, sc->vchi_instance);
332 if (status != 0) {
333 BCM2835_LOG_ERROR(sc, "vchi_connect failed: %d\n", status);
334 return;
335 }
336
337 SERVICE_CREATION_T params = {
338 VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
339 VC_AUDIO_SERVER_NAME, /* 4cc service code */
340 sc->vchi_connection, /* passed in fn pointers */
341 0, /* rx fifo size */
342 0, /* tx fifo size */
343 bcm2835_audio_callback, /* service callback */
344 sc, /* service callback parameter */
345 1,
346 1,
347 0 /* want crc check on bulk transfers */
348 };
349
350 status = vchi_service_open(sc->vchi_instance, ¶ms,
351 &sc->vchi_handle);
352
353 if (status != 0)
354 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
355 }
356
357 static void
bcm2835_audio_release(struct bcm2835_audio_info * sc)358 bcm2835_audio_release(struct bcm2835_audio_info *sc)
359 {
360 int success;
361
362 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
363 success = vchi_service_close(sc->vchi_handle);
364 if (success != 0)
365 BCM2835_LOG_ERROR(sc, "vchi_service_close failed: %d\n",
366 success);
367 vchi_service_release(sc->vchi_handle);
368 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
369 }
370
371 vchi_disconnect(sc->vchi_instance);
372 }
373
374 static void
bcm2835_audio_reset_channel(struct bcm2835_audio_chinfo * ch)375 bcm2835_audio_reset_channel(struct bcm2835_audio_chinfo *ch)
376 {
377
378 ch->available_space = VCHIQ_AUDIO_BUFFER_SIZE;
379 ch->unsubmittedptr = 0;
380 sndbuf_reset(ch->buffer);
381 }
382
383 static void
bcm2835_audio_start(struct bcm2835_audio_chinfo * ch)384 bcm2835_audio_start(struct bcm2835_audio_chinfo *ch)
385 {
386 VC_AUDIO_MSG_T m;
387 int ret;
388 struct bcm2835_audio_info *sc = ch->parent;
389
390 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
391 m.type = VC_AUDIO_MSG_TYPE_START;
392 ret = vchi_msg_queue(sc->vchi_handle,
393 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
394
395 if (ret != 0)
396 BCM2835_LOG_ERROR(sc,
397 "%s: vchi_msg_queue failed (err %d)\n", __func__,
398 ret);
399 }
400 }
401
402 static void
bcm2835_audio_stop(struct bcm2835_audio_chinfo * ch)403 bcm2835_audio_stop(struct bcm2835_audio_chinfo *ch)
404 {
405 VC_AUDIO_MSG_T m;
406 int ret;
407 struct bcm2835_audio_info *sc = ch->parent;
408
409 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
410 m.type = VC_AUDIO_MSG_TYPE_STOP;
411 m.u.stop.draining = 0;
412
413 BCM2835_LOG_INFO(sc,"sending stop\n");
414 ret = vchi_msg_queue(sc->vchi_handle,
415 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
416
417 if (ret != 0)
418 BCM2835_LOG_ERROR(sc,
419 "%s: vchi_msg_queue failed (err %d)\n", __func__,
420 ret);
421 }
422 }
423
424 static void
bcm2835_audio_open(struct bcm2835_audio_info * sc)425 bcm2835_audio_open(struct bcm2835_audio_info *sc)
426 {
427 VC_AUDIO_MSG_T m;
428 int ret;
429
430 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
431 m.type = VC_AUDIO_MSG_TYPE_OPEN;
432 ret = vchi_msg_queue(sc->vchi_handle,
433 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
434
435 if (ret != 0)
436 BCM2835_LOG_ERROR(sc,
437 "%s: vchi_msg_queue failed (err %d)\n", __func__,
438 ret);
439 }
440 }
441
442 static void
bcm2835_audio_update_controls(struct bcm2835_audio_info * sc,uint32_t volume,uint32_t dest)443 bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, uint32_t dest)
444 {
445 VC_AUDIO_MSG_T m;
446 int ret, db;
447
448 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
449 m.type = VC_AUDIO_MSG_TYPE_CONTROL;
450 m.u.control.dest = dest;
451 if (volume > 99)
452 volume = 99;
453 db = db_levels[volume/5];
454 m.u.control.volume = VCHIQ_AUDIO_VOLUME(db);
455
456 ret = vchi_msg_queue(sc->vchi_handle,
457 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
458
459 if (ret != 0)
460 BCM2835_LOG_ERROR(sc,
461 "%s: vchi_msg_queue failed (err %d)\n", __func__,
462 ret);
463 }
464 }
465
466 static void
bcm2835_audio_update_params(struct bcm2835_audio_info * sc,uint32_t fmt,uint32_t speed)467 bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_t speed)
468 {
469 VC_AUDIO_MSG_T m;
470 int ret;
471
472 if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
473 m.type = VC_AUDIO_MSG_TYPE_CONFIG;
474 m.u.config.channels = AFMT_CHANNEL(fmt);
475 m.u.config.samplerate = speed;
476 m.u.config.bps = AFMT_BIT(fmt);
477
478 ret = vchi_msg_queue(sc->vchi_handle,
479 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
480
481 if (ret != 0)
482 BCM2835_LOG_ERROR(sc,
483 "%s: vchi_msg_queue failed (err %d)\n", __func__,
484 ret);
485 }
486 }
487
488 static bool
bcm2835_audio_buffer_should_sleep(struct bcm2835_audio_chinfo * ch)489 bcm2835_audio_buffer_should_sleep(struct bcm2835_audio_chinfo *ch)
490 {
491
492 ch->log_vars.slept_for_lack_of_space = 0;
493 if (ch->playback_state != PLAYBACK_PLAYING)
494 return (true);
495
496 /* Not enough data */
497 /* XXXMDC Take unsubmitted stuff into account */
498 if (sndbuf_getready(ch->buffer)
499 - MOD_DIFF(
500 ch->unsubmittedptr,
501 sndbuf_getreadyptr(ch->buffer),
502 ch->buffer->bufsize
503 ) < VCHIQ_AUDIO_PACKET_SIZE) {
504 ch->starved++;
505 return (true);
506 }
507
508 /* Not enough free space */
509 if (ch->available_space < VCHIQ_AUDIO_PACKET_SIZE) {
510 ch->log_vars.slept_for_lack_of_space = 1;
511 return (true);
512 }
513
514 return (false);
515 }
516
517 static void
bcm2835_audio_write_samples(struct bcm2835_audio_chinfo * ch,void * buf,uint32_t count)518 bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch, void *buf, uint32_t count)
519 {
520 struct bcm2835_audio_info *sc = ch->parent;
521 VC_AUDIO_MSG_T m;
522 int ret;
523
524 if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) {
525 return;
526 }
527
528 m.type = VC_AUDIO_MSG_TYPE_WRITE;
529 m.u.write.count = count;
530 m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE;
531 #if defined(__aarch64__)
532 m.u.write.callback = (uint32_t)(((size_t) ch) >> 32) & 0xffffffff;
533 m.u.write.cookie = (uint32_t)(((size_t) ch) & 0xffffffff);
534 #else
535 m.u.write.callback = (uint32_t) NULL;
536 m.u.write.cookie = (uint32_t) ch;
537 #endif
538 m.u.write.silence = 0;
539
540 ret = vchi_msg_queue(sc->vchi_handle,
541 &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
542
543 if (ret != 0)
544 BCM2835_LOG_ERROR(sc, "%s: vchi_msg_queue failed (err %d)\n",
545 __func__, ret);
546
547 while (count > 0) {
548 int bytes = MIN((int)m.u.write.max_packet, (int)count);
549 ret = vchi_msg_queue(sc->vchi_handle,
550 buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
551 if (ret != 0)
552 BCM2835_LOG_ERROR(sc, "%s: vchi_msg_queue failed: %d\n",
553 __func__, ret);
554 buf = (char *)buf + bytes;
555 count -= bytes;
556 }
557 }
558
559 static void
bcm2835_audio_worker(void * data)560 bcm2835_audio_worker(void *data)
561 {
562 struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)data;
563 struct bcm2835_audio_chinfo *ch = &sc->pch;
564 uint32_t speed, format;
565 uint32_t volume, dest;
566 uint32_t flags;
567 uint32_t count, size, readyptr;
568 uint8_t *buf;
569
570 ch->playback_state = PLAYBACK_IDLE;
571
572 while (1) {
573 if (sc->worker_state != WORKER_RUNNING)
574 break;
575
576 BCM2835_AUDIO_LOCK(sc);
577 /*
578 * wait until there are flags set or buffer is ready
579 * to consume more samples
580 */
581 while ((sc->flags_pending == 0) &&
582 bcm2835_audio_buffer_should_sleep(ch)) {
583 cv_wait_sig(&sc->worker_cv, &sc->lock);
584 if ((sc->flags_pending == 0) &&
585 (ch->log_vars.slept_for_lack_of_space)) {
586 BCM2835_LOG_TRACE(sc,
587 "slept for lack of space\n");
588 }
589 }
590 flags = sc->flags_pending;
591 /* Clear pending flags */
592 sc->flags_pending = 0;
593 BCM2835_AUDIO_UNLOCK(sc);
594
595 /* Requested to change parameters */
596 if (flags & AUDIO_PARAMS) {
597 BCM2835_AUDIO_LOCK(sc);
598 speed = ch->spd;
599 format = ch->fmt;
600 volume = sc->volume;
601 dest = sc->dest;
602 BCM2835_AUDIO_UNLOCK(sc);
603 if (ch->playback_state == PLAYBACK_IDLE)
604 bcm2835_audio_update_params(sc, format, speed);
605 bcm2835_audio_update_controls(sc, volume, dest);
606 }
607
608 /* Requested to stop playback */
609 if ((flags & AUDIO_STOP) &&
610 (ch->playback_state == PLAYBACK_PLAYING)) {
611 bcm2835_audio_stop(ch);
612 BCM2835_AUDIO_LOCK(sc);
613 bcm2835_audio_reset_channel(&sc->pch);
614 ch->playback_state = PLAYBACK_IDLE;
615 long sub_total = ch->submitted_samples;
616 long retd = ch->retrieved_samples;
617 BCM2835_AUDIO_UNLOCK(sc);
618 BCM2835_LOG_INFO(sc,
619 "stopped audio. submitted a total of %lu "
620 "having been acked %lu\n", sub_total, retd);
621 continue;
622 }
623
624 /* Requested to start playback */
625 if ((flags & AUDIO_PLAY) &&
626 (ch->playback_state == PLAYBACK_IDLE)) {
627 BCM2835_LOG_INFO(sc, "starting audio\n");
628 unsigned int bsize = ch->buffer->bufsize;
629 BCM2835_AUDIO_LOCK(sc);
630 ch->playback_state = PLAYBACK_PLAYING;
631 ch->log_vars.bsize = bsize;
632 BCM2835_AUDIO_UNLOCK(sc);
633 BCM2835_LOG_INFO(sc, "buffer size is %u\n", bsize);
634 bcm2835_audio_start(ch);
635 }
636
637 if (ch->playback_state == PLAYBACK_IDLE)
638 continue;
639
640 if (sndbuf_getready(ch->buffer) == 0)
641 continue;
642
643 uint32_t i_count;
644
645 /* XXXMDC Take unsubmitted stuff into account */
646 count = i_count = sndbuf_getready(ch->buffer)
647 - MOD_DIFF(ch->unsubmittedptr,
648 sndbuf_getreadyptr(ch->buffer),
649 ch->buffer->bufsize);
650 size = ch->buffer->bufsize;
651 readyptr = ch->unsubmittedptr;
652
653 int size_changed = 0;
654 unsigned int available;
655
656 BCM2835_AUDIO_LOCK(sc);
657 if (size != ch->log_vars.bsize) {
658 ch->log_vars.bsize = size;
659 size_changed = 1;
660 }
661 available = ch->available_space;
662 /*
663 * XXXMDC
664 *
665 * On arm64, got into situations where
666 * readyptr was less than a packet away
667 * from the end of the buffer, which led
668 * to count being set to 0 and, inexorably, starvation.
669 * Code below tries to take that into account.
670 * The problem might have been fixed with some of the
671 * other changes that were made in the meantime,
672 * but for now this works fine.
673 */
674 if (readyptr + count > size) {
675 count = size - readyptr;
676 }
677 if(count > ch->available_space){
678 count = ch->available_space;
679 count -= (count % VCHIQ_AUDIO_PACKET_SIZE);
680 }else if (count > VCHIQ_AUDIO_PACKET_SIZE){
681 count -= (count % VCHIQ_AUDIO_PACKET_SIZE);
682 }else if (size > count + readyptr) {
683 count = 0;
684 }
685 BCM2835_AUDIO_UNLOCK(sc);
686
687 if (count % VCHIQ_AUDIO_PACKET_SIZE != 0) {
688 BCM2835_LOG_WARN(sc, "count: %u initial count: %u "
689 "size: %u readyptr: %u available: %u\n", count,
690 i_count,size,readyptr,available);
691 }
692 if (size_changed)
693 BCM2835_LOG_INFO(sc, "bsize changed to %u\n", size);
694
695 if (count == 0) {
696 BCM2835_LOG_WARN(sc,
697 "not enough room for a packet: count %d,"
698 " i_count %d, rptr %d, size %d\n",
699 count, i_count, readyptr, size);
700 continue;
701 }
702
703 buf = ch->buffer->buf + readyptr;
704
705 bcm2835_audio_write_samples(ch, buf, count);
706 BCM2835_AUDIO_LOCK(sc);
707 ch->unsubmittedptr = (ch->unsubmittedptr + count) %
708 ch->buffer->bufsize;
709 ch->available_space -= count;
710 ch->submitted_samples += count;
711 long sub = count;
712 long sub_total = ch->submitted_samples;
713 long retd = ch->retrieved_samples;
714 KASSERT(ch->available_space >= 0, ("ch->available_space == %d\n", ch->available_space));
715 BCM2835_AUDIO_UNLOCK(sc);
716
717 BCM2835_LOG_TRACE(sc,
718 "submitted %lu for a total of %lu having been acked %lu; "
719 "rptr %d, had %u available\n", sub, sub_total, retd,
720 readyptr, available);
721 }
722
723 BCM2835_AUDIO_LOCK(sc);
724 sc->worker_state = WORKER_STOPPED;
725 cv_signal(&sc->worker_cv);
726 BCM2835_AUDIO_UNLOCK(sc);
727
728 kproc_exit(0);
729 }
730
731 static void
bcm2835_audio_create_worker(struct bcm2835_audio_info * sc)732 bcm2835_audio_create_worker(struct bcm2835_audio_info *sc)
733 {
734 struct proc *newp;
735
736 sc->worker_state = WORKER_RUNNING;
737 if (kproc_create(bcm2835_audio_worker, (void*)sc, &newp, 0, 0,
738 "bcm2835_audio_worker") != 0) {
739 BCM2835_LOG_ERROR(sc,
740 "failed to create bcm2835_audio_worker\n");
741 }
742 }
743
744 /* -------------------------------------------------------------------- */
745 /* channel interface for VCHI audio */
746 static void *
bcmchan_init(kobj_t obj,void * devinfo,struct snd_dbuf * b,struct pcm_channel * c,int dir)747 bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
748 {
749 struct bcm2835_audio_info *sc = devinfo;
750 struct bcm2835_audio_chinfo *ch = &sc->pch;
751 void *buffer;
752
753 if (dir == PCMDIR_REC)
754 return NULL;
755
756 ch->parent = sc;
757 ch->channel = c;
758 ch->buffer = b;
759
760 /* default values */
761 ch->spd = 44100;
762 ch->fmt = SND_FORMAT(AFMT_S16_LE, 2, 0);
763 ch->blksz = VCHIQ_AUDIO_PACKET_SIZE;
764
765 buffer = malloc(sc->bufsz, M_DEVBUF, M_WAITOK | M_ZERO);
766
767 if (sndbuf_setup(ch->buffer, buffer, sc->bufsz) != 0) {
768 device_printf(sc->dev, "sndbuf_setup failed\n");
769 free(buffer, M_DEVBUF);
770 return NULL;
771 }
772
773 ch->log_vars = DEFAULT_LOG_VALUES;
774
775 BCM2835_AUDIO_LOCK(sc);
776 bcm2835_worker_update_params(sc);
777 BCM2835_AUDIO_UNLOCK(sc);
778
779 return ch;
780 }
781
782 static int
bcmchan_free(kobj_t obj,void * data)783 bcmchan_free(kobj_t obj, void *data)
784 {
785 struct bcm2835_audio_chinfo *ch = data;
786 void *buffer;
787
788 buffer = ch->buffer->buf;
789 if (buffer)
790 free(buffer, M_DEVBUF);
791
792 return (0);
793 }
794
795 static int
bcmchan_setformat(kobj_t obj,void * data,uint32_t format)796 bcmchan_setformat(kobj_t obj, void *data, uint32_t format)
797 {
798 struct bcm2835_audio_chinfo *ch = data;
799 struct bcm2835_audio_info *sc = ch->parent;
800
801 BCM2835_AUDIO_LOCK(sc);
802 ch->fmt = format;
803 bcm2835_worker_update_params(sc);
804 BCM2835_AUDIO_UNLOCK(sc);
805
806 return 0;
807 }
808
809 static uint32_t
bcmchan_setspeed(kobj_t obj,void * data,uint32_t speed)810 bcmchan_setspeed(kobj_t obj, void *data, uint32_t speed)
811 {
812 struct bcm2835_audio_chinfo *ch = data;
813 struct bcm2835_audio_info *sc = ch->parent;
814
815 BCM2835_AUDIO_LOCK(sc);
816 ch->spd = speed;
817 bcm2835_worker_update_params(sc);
818 BCM2835_AUDIO_UNLOCK(sc);
819
820 return ch->spd;
821 }
822
823 static uint32_t
bcmchan_setblocksize(kobj_t obj,void * data,uint32_t blocksize)824 bcmchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
825 {
826 struct bcm2835_audio_chinfo *ch = data;
827
828 return ch->blksz;
829 }
830
831 static int
bcmchan_trigger(kobj_t obj,void * data,int go)832 bcmchan_trigger(kobj_t obj, void *data, int go)
833 {
834 struct bcm2835_audio_chinfo *ch = data;
835 struct bcm2835_audio_info *sc = ch->parent;
836
837 if (!PCMTRIG_COMMON(go))
838 return (0);
839
840 switch (go) {
841 case PCMTRIG_START:
842 /* kickstart data flow */
843 chn_intr(sc->pch.channel);
844 ch->submitted_samples = 0;
845 ch->retrieved_samples = 0;
846 bcm2835_worker_play_start(sc);
847 break;
848
849 case PCMTRIG_STOP:
850 case PCMTRIG_ABORT:
851 bcm2835_worker_play_stop(sc);
852 break;
853
854 default:
855 break;
856 }
857 return 0;
858 }
859
860 static uint32_t
bcmchan_getptr(kobj_t obj,void * data)861 bcmchan_getptr(kobj_t obj, void *data)
862 {
863 struct bcm2835_audio_chinfo *ch = data;
864 struct bcm2835_audio_info *sc = ch->parent;
865 uint32_t ret;
866
867 BCM2835_AUDIO_LOCK(sc);
868 ret = ch->unsubmittedptr;
869 BCM2835_AUDIO_UNLOCK(sc);
870
871 return ret;
872 }
873
874 static struct pcmchan_caps *
bcmchan_getcaps(kobj_t obj,void * data)875 bcmchan_getcaps(kobj_t obj, void *data)
876 {
877
878 return &bcm2835_audio_playcaps;
879 }
880
881 static kobj_method_t bcmchan_methods[] = {
882 KOBJMETHOD(channel_init, bcmchan_init),
883 KOBJMETHOD(channel_free, bcmchan_free),
884 KOBJMETHOD(channel_setformat, bcmchan_setformat),
885 KOBJMETHOD(channel_setspeed, bcmchan_setspeed),
886 KOBJMETHOD(channel_setblocksize, bcmchan_setblocksize),
887 KOBJMETHOD(channel_trigger, bcmchan_trigger),
888 KOBJMETHOD(channel_getptr, bcmchan_getptr),
889 KOBJMETHOD(channel_getcaps, bcmchan_getcaps),
890 KOBJMETHOD_END
891 };
892 CHANNEL_DECLARE(bcmchan);
893
894 /************************************************************/
895
896 static int
bcmmix_init(struct snd_mixer * m)897 bcmmix_init(struct snd_mixer *m)
898 {
899
900 mix_setdevs(m, SOUND_MASK_VOLUME);
901
902 return (0);
903 }
904
905 static int
bcmmix_set(struct snd_mixer * m,unsigned dev,unsigned left,unsigned right)906 bcmmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
907 {
908 struct bcm2835_audio_info *sc = mix_getdevinfo(m);
909
910 switch (dev) {
911 case SOUND_MIXER_VOLUME:
912 BCM2835_AUDIO_LOCK(sc);
913 sc->volume = left;
914 bcm2835_worker_update_params(sc);
915 BCM2835_AUDIO_UNLOCK(sc);
916
917 break;
918
919 default:
920 break;
921 }
922
923 return left | (left << 8);
924 }
925
926 static kobj_method_t bcmmixer_methods[] = {
927 KOBJMETHOD(mixer_init, bcmmix_init),
928 KOBJMETHOD(mixer_set, bcmmix_set),
929 KOBJMETHOD_END
930 };
931
932 MIXER_DECLARE(bcmmixer);
933
934 static int
sysctl_bcm2835_audio_dest(SYSCTL_HANDLER_ARGS)935 sysctl_bcm2835_audio_dest(SYSCTL_HANDLER_ARGS)
936 {
937 struct bcm2835_audio_info *sc = arg1;
938 int val;
939 int err;
940
941 val = sc->dest;
942 err = sysctl_handle_int(oidp, &val, 0, req);
943 if (err || !req->newptr) /* error || read request */
944 return (err);
945
946 if ((val < 0) || (val > 2))
947 return (EINVAL);
948
949 BCM2835_AUDIO_LOCK(sc);
950 sc->dest = val;
951 bcm2835_worker_update_params(sc);
952 BCM2835_AUDIO_UNLOCK(sc);
953
954 if (bootverbose)
955 device_printf(sc->dev, "destination set to %s\n", dest_description(val));
956
957 return (0);
958 }
959
960 static void
vchi_audio_sysctl_init(struct bcm2835_audio_info * sc)961 vchi_audio_sysctl_init(struct bcm2835_audio_info *sc)
962 {
963 struct sysctl_ctx_list *ctx;
964 struct sysctl_oid *tree_node;
965 struct sysctl_oid_list *tree;
966
967 /*
968 * Add system sysctl tree/handlers.
969 */
970 ctx = device_get_sysctl_ctx(sc->dev);
971 tree_node = device_get_sysctl_tree(sc->dev);
972 tree = SYSCTL_CHILDREN(tree_node);
973 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "dest",
974 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, sizeof(*sc),
975 sysctl_bcm2835_audio_dest, "IU", "audio destination, "
976 "0 - auto, 1 - headphones, 2 - HDMI");
977 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "callbacks",
978 CTLFLAG_RD, &sc->pch.callbacks,
979 "callbacks total");
980 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "submitted",
981 CTLFLAG_RD, &sc->pch.submitted_samples,
982 "last play submitted samples");
983 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "retrieved",
984 CTLFLAG_RD, &sc->pch.retrieved_samples,
985 "last play retrieved samples");
986 SYSCTL_ADD_UQUAD(ctx, tree, OID_AUTO, "underruns",
987 CTLFLAG_RD, &sc->pch.underruns,
988 "callback underruns");
989 SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "freebuffer",
990 CTLFLAG_RD, &sc->pch.available_space,
991 sc->pch.available_space, "callbacks total");
992 SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "starved",
993 CTLFLAG_RD, &sc->pch.starved,
994 sc->pch.starved, "number of starved conditions");
995 SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "trace",
996 CTLFLAG_RW, &sc->verbose_trace,
997 sc->verbose_trace, "enable tracing of transfers");
998 }
999
1000 static void
bcm2835_audio_identify(driver_t * driver,device_t parent)1001 bcm2835_audio_identify(driver_t *driver, device_t parent)
1002 {
1003
1004 BUS_ADD_CHILD(parent, 0, "pcm", 0);
1005 }
1006
1007 static int
bcm2835_audio_probe(device_t dev)1008 bcm2835_audio_probe(device_t dev)
1009 {
1010
1011 device_set_desc(dev, "VCHIQ audio");
1012 return (BUS_PROBE_DEFAULT);
1013 }
1014
1015 static void
bcm2835_audio_delayed_init(void * xsc)1016 bcm2835_audio_delayed_init(void *xsc)
1017 {
1018 struct bcm2835_audio_info *sc;
1019 char status[SND_STATUSLEN];
1020
1021 sc = xsc;
1022
1023 config_intrhook_disestablish(&sc->intr_hook);
1024
1025 bcm2835_audio_init(sc);
1026 bcm2835_audio_open(sc);
1027 sc->volume = 75;
1028 sc->dest = DEST_AUTO;
1029 sc->verbose_trace = 0;
1030
1031 if (mixer_init(sc->dev, &bcmmixer_class, sc)) {
1032 device_printf(sc->dev, "mixer_init failed\n");
1033 goto no;
1034 }
1035
1036 pcm_init(sc->dev, sc);
1037
1038 pcm_addchan(sc->dev, PCMDIR_PLAY, &bcmchan_class, sc);
1039 snprintf(status, SND_STATUSLEN, "at VCHIQ");
1040 if (pcm_register(sc->dev, status)) {
1041 device_printf(sc->dev, "pcm_register failed\n");
1042 goto no;
1043 }
1044
1045 bcm2835_audio_reset_channel(&sc->pch);
1046 bcm2835_audio_create_worker(sc);
1047
1048 vchi_audio_sysctl_init(sc);
1049
1050 no:
1051 ;
1052 }
1053
1054 static int
bcm2835_audio_attach(device_t dev)1055 bcm2835_audio_attach(device_t dev)
1056 {
1057 struct bcm2835_audio_info *sc;
1058
1059 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
1060
1061 sc->dev = dev;
1062 sc->bufsz = VCHIQ_AUDIO_BUFFER_SIZE;
1063
1064 mtx_init(&sc->lock, device_get_nameunit(dev),
1065 "bcm_audio_lock", MTX_DEF);
1066 cv_init(&sc->worker_cv, "worker_cv");
1067 sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
1068
1069 /*
1070 * We need interrupts enabled for VCHI to work properly,
1071 * so delay initialization until it happens.
1072 */
1073 sc->intr_hook.ich_func = bcm2835_audio_delayed_init;
1074 sc->intr_hook.ich_arg = sc;
1075
1076 if (config_intrhook_establish(&sc->intr_hook) != 0)
1077 goto no;
1078
1079 return 0;
1080
1081 no:
1082 return ENXIO;
1083 }
1084
1085 static int
bcm2835_audio_detach(device_t dev)1086 bcm2835_audio_detach(device_t dev)
1087 {
1088 int r;
1089 struct bcm2835_audio_info *sc;
1090 sc = pcm_getdevinfo(dev);
1091
1092 /* Stop worker thread */
1093 BCM2835_AUDIO_LOCK(sc);
1094 sc->worker_state = WORKER_STOPPING;
1095 cv_signal(&sc->worker_cv);
1096 /* Wait for thread to exit */
1097 while (sc->worker_state != WORKER_STOPPED)
1098 cv_wait_sig(&sc->worker_cv, &sc->lock);
1099 BCM2835_AUDIO_UNLOCK(sc);
1100
1101 r = pcm_unregister(dev);
1102 if (r)
1103 return r;
1104
1105 mtx_destroy(&sc->lock);
1106 cv_destroy(&sc->worker_cv);
1107
1108 bcm2835_audio_release(sc);
1109
1110 free(sc, M_DEVBUF);
1111
1112 return 0;
1113 }
1114
1115 static device_method_t bcm2835_audio_methods[] = {
1116 /* Device interface */
1117 DEVMETHOD(device_identify, bcm2835_audio_identify),
1118 DEVMETHOD(device_probe, bcm2835_audio_probe),
1119 DEVMETHOD(device_attach, bcm2835_audio_attach),
1120 DEVMETHOD(device_detach, bcm2835_audio_detach),
1121 { 0, 0 }
1122 };
1123
1124 static driver_t bcm2835_audio_driver = {
1125 "pcm",
1126 bcm2835_audio_methods,
1127 PCM_SOFTC_SIZE,
1128 };
1129
1130 DRIVER_MODULE(bcm2835_audio, vchiq, bcm2835_audio_driver, 0, 0);
1131 MODULE_DEPEND(bcm2835_audio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1132 MODULE_DEPEND(bcm2835_audio, vchiq, 1, 1, 1);
1133 MODULE_VERSION(bcm2835_audio, 1);
1134