1 /*****************************************************************************
2 * Copyright 2011 Broadcom Corporation. All rights reserved.
4 * Unless you and Broadcom execute a separate written software license
5 * agreement governing use of this software, this software is licensed to you
6 * under the terms of the GNU General Public License version 2, available at
7 * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
9 * Notwithstanding the above, under no circumstances may you combine this
10 * software in any way with any other Broadcom software provided under a
11 * license other than the GPL, without Broadcom's express prior written
13 *****************************************************************************/
15 #include <linux/device.h>
16 #include <sound/core.h>
17 #include <sound/initval.h>
18 #include <sound/pcm.h>
20 #include <linux/interrupt.h>
22 #include <linux/file.h>
24 #include <linux/syscalls.h>
25 #include <linux/uaccess.h>
26 #include <linux/slab.h>
27 #include <linux/delay.h>
28 #include <linux/atomic.h>
29 #include <linux/module.h>
30 #include <linux/completion.h>
34 /* ---- Include Files -------------------------------------------------------- */
36 #include "interface/vchi/vchi.h"
37 #include "vc_vchi_audioserv_defs.h"
39 /* ---- Private Constants and Types ------------------------------------------ */
41 #define BCM2835_AUDIO_STOP 0
42 #define BCM2835_AUDIO_START 1
43 #define BCM2835_AUDIO_WRITE 2
45 /* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
46 #ifdef AUDIO_DEBUG_ENABLE
47 #define LOG_ERR(fmt, arg...) pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
48 #define LOG_WARN(fmt, arg...) pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
49 #define LOG_INFO(fmt, arg...) pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
50 #define LOG_DBG(fmt, arg...) pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
52 #define LOG_ERR(fmt, arg...) pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
53 #define LOG_WARN(fmt, arg...) no_printk(fmt, ##arg)
54 #define LOG_INFO(fmt, arg...) no_printk(fmt, ##arg)
55 #define LOG_DBG(fmt, arg...) no_printk(fmt, ##arg)
58 struct bcm2835_audio_instance
{
59 unsigned int num_connections
;
60 VCHI_SERVICE_HANDLE_T vchi_handle
[VCHI_MAX_NUM_CONNECTIONS
];
61 struct completion msg_avail_comp
;
62 struct mutex vchi_mutex
;
63 struct bcm2835_alsa_stream
*alsa_stream
;
68 static bool force_bulk
;
70 /* ---- Private Variables ---------------------------------------------------- */
72 /* ---- Private Function Prototypes ------------------------------------------ */
74 /* ---- Private Functions ---------------------------------------------------- */
76 static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream
*alsa_stream
);
77 static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream
*alsa_stream
);
78 static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream
*alsa_stream
,
79 unsigned int count
, void *src
);
81 // Routine to send a message across a service
84 bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle
,
88 return vchi_queue_kernel_message(handle
,
93 static const u32 BCM2835_AUDIO_WRITE_COOKIE1
= ('B' << 24 | 'C' << 16 |
95 static const u32 BCM2835_AUDIO_WRITE_COOKIE2
= ('D' << 24 | 'A' << 16 |
98 struct bcm2835_audio_work
{
99 struct work_struct my_work
;
100 struct bcm2835_alsa_stream
*alsa_stream
;
106 static void my_wq_function(struct work_struct
*work
)
108 struct bcm2835_audio_work
*w
=
109 container_of(work
, struct bcm2835_audio_work
, my_work
);
113 case BCM2835_AUDIO_START
:
114 ret
= bcm2835_audio_start_worker(w
->alsa_stream
);
116 case BCM2835_AUDIO_STOP
:
117 ret
= bcm2835_audio_stop_worker(w
->alsa_stream
);
119 case BCM2835_AUDIO_WRITE
:
120 ret
= bcm2835_audio_write_worker(w
->alsa_stream
, w
->count
,
124 LOG_ERR(" Unexpected work: %p:%d\n", w
->alsa_stream
, w
->cmd
);
130 int bcm2835_audio_start(struct bcm2835_alsa_stream
*alsa_stream
)
132 if (alsa_stream
->my_wq
) {
133 struct bcm2835_audio_work
*work
;
135 work
= kmalloc(sizeof(*work
), GFP_ATOMIC
);
136 /*--- Queue some work (item 1) ---*/
138 LOG_ERR(" .. Error: NULL work kmalloc\n");
141 INIT_WORK(&work
->my_work
, my_wq_function
);
142 work
->alsa_stream
= alsa_stream
;
143 work
->cmd
= BCM2835_AUDIO_START
;
144 if (!queue_work(alsa_stream
->my_wq
, &work
->my_work
)) {
152 int bcm2835_audio_stop(struct bcm2835_alsa_stream
*alsa_stream
)
154 if (alsa_stream
->my_wq
) {
155 struct bcm2835_audio_work
*work
;
157 work
= kmalloc(sizeof(*work
), GFP_ATOMIC
);
158 /*--- Queue some work (item 1) ---*/
160 LOG_ERR(" .. Error: NULL work kmalloc\n");
163 INIT_WORK(&work
->my_work
, my_wq_function
);
164 work
->alsa_stream
= alsa_stream
;
165 work
->cmd
= BCM2835_AUDIO_STOP
;
166 if (!queue_work(alsa_stream
->my_wq
, &work
->my_work
)) {
174 int bcm2835_audio_write(struct bcm2835_alsa_stream
*alsa_stream
,
175 unsigned int count
, void *src
)
177 if (alsa_stream
->my_wq
) {
178 struct bcm2835_audio_work
*work
;
180 work
= kmalloc(sizeof(*work
), GFP_ATOMIC
);
181 /*--- Queue some work (item 1) ---*/
183 LOG_ERR(" .. Error: NULL work kmalloc\n");
186 INIT_WORK(&work
->my_work
, my_wq_function
);
187 work
->alsa_stream
= alsa_stream
;
188 work
->cmd
= BCM2835_AUDIO_WRITE
;
191 if (!queue_work(alsa_stream
->my_wq
, &work
->my_work
)) {
199 static void my_workqueue_init(struct bcm2835_alsa_stream
*alsa_stream
)
201 alsa_stream
->my_wq
= alloc_workqueue("my_queue", WQ_HIGHPRI
, 1);
204 static void my_workqueue_quit(struct bcm2835_alsa_stream
*alsa_stream
)
206 if (alsa_stream
->my_wq
) {
207 flush_workqueue(alsa_stream
->my_wq
);
208 destroy_workqueue(alsa_stream
->my_wq
);
209 alsa_stream
->my_wq
= NULL
;
213 static void audio_vchi_callback(void *param
,
214 const VCHI_CALLBACK_REASON_T reason
,
217 struct bcm2835_audio_instance
*instance
= param
;
220 struct vc_audio_msg m
;
222 if (reason
!= VCHI_CALLBACK_MSG_AVAILABLE
)
226 LOG_ERR(" .. instance is null\n");
230 if (!instance
->vchi_handle
[0]) {
231 LOG_ERR(" .. instance->vchi_handle[0] is null\n");
235 status
= vchi_msg_dequeue(instance
->vchi_handle
[0],
236 &m
, sizeof(m
), &msg_len
, VCHI_FLAGS_NONE
);
237 if (m
.type
== VC_AUDIO_MSG_TYPE_RESULT
) {
238 LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
239 instance
, m
.u
.result
.success
);
240 instance
->result
= m
.u
.result
.success
;
241 complete(&instance
->msg_avail_comp
);
242 } else if (m
.type
== VC_AUDIO_MSG_TYPE_COMPLETE
) {
243 struct bcm2835_alsa_stream
*alsa_stream
= instance
->alsa_stream
;
245 LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
246 instance
, m
.u
.complete
.count
);
247 if (m
.u
.complete
.cookie1
!= BCM2835_AUDIO_WRITE_COOKIE1
||
248 m
.u
.complete
.cookie2
!= BCM2835_AUDIO_WRITE_COOKIE2
)
249 LOG_ERR(" .. response is corrupt\n");
250 else if (alsa_stream
) {
251 atomic_add(m
.u
.complete
.count
,
252 &alsa_stream
->retrieved
);
253 bcm2835_playback_fifo(alsa_stream
);
255 LOG_ERR(" .. unexpected alsa_stream=%p\n",
259 LOG_ERR(" .. unexpected m.type=%d\n", m
.type
);
263 static struct bcm2835_audio_instance
*
264 vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance
,
265 VCHI_CONNECTION_T
**vchi_connections
,
266 unsigned int num_connections
)
269 struct bcm2835_audio_instance
*instance
;
273 LOG_DBG("%s: start", __func__
);
275 if (num_connections
> VCHI_MAX_NUM_CONNECTIONS
) {
276 LOG_ERR("%s: unsupported number of connections %u (max=%u)\n",
277 __func__
, num_connections
, VCHI_MAX_NUM_CONNECTIONS
);
279 return ERR_PTR(-EINVAL
);
281 /* Allocate memory for this instance */
282 instance
= kzalloc(sizeof(*instance
), GFP_KERNEL
);
284 return ERR_PTR(-ENOMEM
);
286 instance
->num_connections
= num_connections
;
288 /* Create a lock for exclusive, serialized VCHI connection access */
289 mutex_init(&instance
->vchi_mutex
);
290 /* Open the VCHI service connections */
291 for (i
= 0; i
< num_connections
; i
++) {
292 SERVICE_CREATION_T params
= {
293 .version
= VCHI_VERSION_EX(VC_AUDIOSERV_VER
, VC_AUDIOSERV_MIN_VER
),
294 .service_id
= VC_AUDIO_SERVER_NAME
,
295 .connection
= vchi_connections
[i
],
298 .callback
= audio_vchi_callback
,
299 .callback_param
= instance
,
300 .want_unaligned_bulk_rx
= 1, //TODO: remove VCOS_FALSE
301 .want_unaligned_bulk_tx
= 1, //TODO: remove VCOS_FALSE
305 LOG_DBG("%s: about to open %i\n", __func__
, i
);
306 status
= vchi_service_open(vchi_instance
, ¶ms
,
307 &instance
->vchi_handle
[i
]);
309 LOG_DBG("%s: opened %i: %p=%d\n", __func__
, i
, instance
->vchi_handle
[i
], status
);
311 LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
314 goto err_close_services
;
316 /* Finished with the service for now */
317 vchi_service_release(instance
->vchi_handle
[i
]);
320 LOG_DBG("%s: okay\n", __func__
);
324 for (i
= 0; i
< instance
->num_connections
; i
++) {
325 LOG_ERR("%s: closing %i: %p\n", __func__
, i
, instance
->vchi_handle
[i
]);
326 if (instance
->vchi_handle
[i
])
327 vchi_service_close(instance
->vchi_handle
[i
]);
331 LOG_ERR("%s: error\n", __func__
);
336 static int vc_vchi_audio_deinit(struct bcm2835_audio_instance
*instance
)
342 LOG_ERR("%s: invalid handle %p\n", __func__
, instance
);
347 LOG_DBG(" .. about to lock (%d)\n", instance
->num_connections
);
348 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
349 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
350 instance
->num_connections
);
354 /* Close all VCHI service connections */
355 for (i
= 0; i
< instance
->num_connections
; i
++) {
358 LOG_DBG(" .. %i:closing %p\n", i
, instance
->vchi_handle
[i
]);
359 vchi_service_use(instance
->vchi_handle
[i
]);
361 status
= vchi_service_close(instance
->vchi_handle
[i
]);
363 LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
368 mutex_unlock(&instance
->vchi_mutex
);
376 static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream
*alsa_stream
)
378 static VCHI_INSTANCE_T vchi_instance
;
379 static VCHI_CONNECTION_T
*vchi_connection
;
381 struct bcm2835_audio_instance
*instance
=
382 (struct bcm2835_audio_instance
*)alsa_stream
->instance
;
386 LOG_INFO("%s: start\n", __func__
);
389 LOG_ERR("%s: VCHI instance already open (%p)\n",
391 instance
->alsa_stream
= alsa_stream
;
392 alsa_stream
->instance
= instance
;
393 ret
= 0; // xxx todo -1;
397 /* Initialize and create a VCHI connection */
399 ret
= vchi_initialise(&vchi_instance
);
401 LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
407 ret
= vchi_connect(NULL
, 0, vchi_instance
);
409 LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
418 /* Initialize an instance of the audio service */
419 instance
= vc_vchi_audio_init(vchi_instance
, &vchi_connection
, 1);
421 if (IS_ERR(instance
)) {
422 LOG_ERR("%s: failed to initialize audio service\n", __func__
);
424 ret
= PTR_ERR(instance
);
428 instance
->alsa_stream
= alsa_stream
;
429 alsa_stream
->instance
= instance
;
431 LOG_DBG(" success !\n");
434 kfree(vchi_instance
);
439 int bcm2835_audio_open(struct bcm2835_alsa_stream
*alsa_stream
)
441 struct bcm2835_audio_instance
*instance
;
442 struct vc_audio_msg m
;
447 my_workqueue_init(alsa_stream
);
449 ret
= bcm2835_audio_open_connection(alsa_stream
);
454 instance
= alsa_stream
->instance
;
455 LOG_DBG(" instance (%p)\n", instance
);
457 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
458 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance
->num_connections
);
461 vchi_service_use(instance
->vchi_handle
[0]);
463 m
.type
= VC_AUDIO_MSG_TYPE_OPEN
;
465 /* Send the message to the videocore */
466 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
470 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
480 vchi_service_release(instance
->vchi_handle
[0]);
481 mutex_unlock(&instance
->vchi_mutex
);
486 static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream
*alsa_stream
,
487 struct bcm2835_chip
*chip
)
489 struct vc_audio_msg m
;
490 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
495 LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
496 chip
->dest
, chip
->volume
);
498 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
499 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
500 instance
->num_connections
);
503 vchi_service_use(instance
->vchi_handle
[0]);
505 instance
->result
= -1;
507 m
.type
= VC_AUDIO_MSG_TYPE_CONTROL
;
508 m
.u
.control
.dest
= chip
->dest
;
509 m
.u
.control
.volume
= chip
->volume
;
511 /* Create the message available completion */
512 init_completion(&instance
->msg_avail_comp
);
514 /* Send the message to the videocore */
515 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
519 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
526 /* We are expecting a reply from the videocore */
527 wait_for_completion(&instance
->msg_avail_comp
);
529 if (instance
->result
) {
530 LOG_ERR("%s: result=%d\n", __func__
, instance
->result
);
539 vchi_service_release(instance
->vchi_handle
[0]);
540 mutex_unlock(&instance
->vchi_mutex
);
545 int bcm2835_audio_set_ctls(struct bcm2835_chip
*chip
)
550 LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip
->dest
, chip
->volume
);
552 /* change ctls for all substreams */
553 for (i
= 0; i
< MAX_SUBSTREAMS
; i
++) {
554 if (chip
->avail_substreams
& (1 << i
)) {
555 if (!chip
->alsa_stream
[i
]) {
556 LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i
, chip
->alsa_stream
[i
], chip
->avail_substreams
);
558 } else if (bcm2835_audio_set_ctls_chan(chip
->alsa_stream
[i
], chip
) != 0) {
559 LOG_ERR("Couldn't set the controls for stream %d\n", i
);
562 LOG_DBG(" Controls set for stream %d\n", i
);
569 int bcm2835_audio_set_params(struct bcm2835_alsa_stream
*alsa_stream
,
570 unsigned int channels
, unsigned int samplerate
,
573 struct vc_audio_msg m
;
574 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
579 LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
580 channels
, samplerate
, bps
);
582 /* resend ctls - alsa_stream may not have been open when first send */
583 ret
= bcm2835_audio_set_ctls_chan(alsa_stream
, alsa_stream
->chip
);
585 LOG_ERR(" Alsa controls not supported\n");
589 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
590 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance
->num_connections
);
593 vchi_service_use(instance
->vchi_handle
[0]);
595 instance
->result
= -1;
597 m
.type
= VC_AUDIO_MSG_TYPE_CONFIG
;
598 m
.u
.config
.channels
= channels
;
599 m
.u
.config
.samplerate
= samplerate
;
600 m
.u
.config
.bps
= bps
;
602 /* Create the message available completion */
603 init_completion(&instance
->msg_avail_comp
);
605 /* Send the message to the videocore */
606 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
610 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
617 /* We are expecting a reply from the videocore */
618 wait_for_completion(&instance
->msg_avail_comp
);
620 if (instance
->result
) {
621 LOG_ERR("%s: result=%d", __func__
, instance
->result
);
630 vchi_service_release(instance
->vchi_handle
[0]);
631 mutex_unlock(&instance
->vchi_mutex
);
636 int bcm2835_audio_setup(struct bcm2835_alsa_stream
*alsa_stream
)
643 static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream
*alsa_stream
)
645 struct vc_audio_msg m
;
646 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
651 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
652 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
653 instance
->num_connections
);
656 vchi_service_use(instance
->vchi_handle
[0]);
658 m
.type
= VC_AUDIO_MSG_TYPE_START
;
660 /* Send the message to the videocore */
661 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
665 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
675 vchi_service_release(instance
->vchi_handle
[0]);
676 mutex_unlock(&instance
->vchi_mutex
);
680 static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream
*alsa_stream
)
682 struct vc_audio_msg m
;
683 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
688 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
689 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
690 instance
->num_connections
);
693 vchi_service_use(instance
->vchi_handle
[0]);
695 m
.type
= VC_AUDIO_MSG_TYPE_STOP
;
696 m
.u
.stop
.draining
= alsa_stream
->draining
;
698 /* Send the message to the videocore */
699 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
703 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
713 vchi_service_release(instance
->vchi_handle
[0]);
714 mutex_unlock(&instance
->vchi_mutex
);
718 int bcm2835_audio_close(struct bcm2835_alsa_stream
*alsa_stream
)
720 struct vc_audio_msg m
;
721 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
726 my_workqueue_quit(alsa_stream
);
728 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
729 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
730 instance
->num_connections
);
733 vchi_service_use(instance
->vchi_handle
[0]);
735 m
.type
= VC_AUDIO_MSG_TYPE_CLOSE
;
737 /* Create the message available completion */
738 init_completion(&instance
->msg_avail_comp
);
740 /* Send the message to the videocore */
741 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
745 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
751 /* We are expecting a reply from the videocore */
752 wait_for_completion(&instance
->msg_avail_comp
);
754 if (instance
->result
) {
755 LOG_ERR("%s: failed result (result=%d)\n",
756 __func__
, instance
->result
);
765 vchi_service_release(instance
->vchi_handle
[0]);
766 mutex_unlock(&instance
->vchi_mutex
);
768 /* Stop the audio service */
769 vc_vchi_audio_deinit(instance
);
770 alsa_stream
->instance
= NULL
;
775 static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream
*alsa_stream
,
776 unsigned int count
, void *src
)
778 struct vc_audio_msg m
;
779 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
784 LOG_INFO(" Writing %d bytes from %p\n", count
, src
);
786 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
787 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
788 instance
->num_connections
);
791 vchi_service_use(instance
->vchi_handle
[0]);
793 if (instance
->peer_version
== 0 &&
794 vchi_get_peer_version(instance
->vchi_handle
[0], &instance
->peer_version
) == 0)
795 LOG_DBG("%s: client version %d connected\n", __func__
, instance
->peer_version
);
797 m
.type
= VC_AUDIO_MSG_TYPE_WRITE
;
798 m
.u
.write
.count
= count
;
799 // old version uses bulk, new version uses control
800 m
.u
.write
.max_packet
= instance
->peer_version
< 2 || force_bulk
? 0 : 4000;
801 m
.u
.write
.cookie1
= BCM2835_AUDIO_WRITE_COOKIE1
;
802 m
.u
.write
.cookie2
= BCM2835_AUDIO_WRITE_COOKIE2
;
803 m
.u
.write
.silence
= src
== NULL
;
805 /* Send the message to the videocore */
806 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
810 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
816 if (!m
.u
.write
.silence
) {
817 if (!m
.u
.write
.max_packet
) {
818 /* Send the message to the videocore */
819 status
= vchi_bulk_queue_transmit(instance
->vchi_handle
[0],
821 0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
823 1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ
,
827 int bytes
= min_t(int, m
.u
.write
.max_packet
, count
);
829 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
831 src
= (char *)src
+ bytes
;
836 LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
846 vchi_service_release(instance
->vchi_handle
[0]);
847 mutex_unlock(&instance
->vchi_mutex
);
852 * Returns all buffers from arm->vc
854 void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream
*alsa_stream
)
859 * Forces VC to flush(drop) its filled playback buffers and
860 * return them the us. (VC->ARM)
862 void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream
*alsa_stream
)
866 unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream
*alsa_stream
)
868 unsigned int count
= atomic_read(&alsa_stream
->retrieved
);
870 atomic_sub(count
, &alsa_stream
->retrieved
);
874 module_param(force_bulk
, bool, 0444);
875 MODULE_PARM_DESC(force_bulk
, "Force use of vchiq bulk for audio");