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
);
112 LOG_DBG(" .. IN %p:%d\n", w
->alsa_stream
, w
->cmd
);
114 case BCM2835_AUDIO_START
:
115 ret
= bcm2835_audio_start_worker(w
->alsa_stream
);
117 case BCM2835_AUDIO_STOP
:
118 ret
= bcm2835_audio_stop_worker(w
->alsa_stream
);
120 case BCM2835_AUDIO_WRITE
:
121 ret
= bcm2835_audio_write_worker(w
->alsa_stream
, w
->count
,
125 LOG_ERR(" Unexpected work: %p:%d\n", w
->alsa_stream
, w
->cmd
);
128 kfree((void *) work
);
129 LOG_DBG(" .. OUT %d\n", ret
);
132 int bcm2835_audio_start(struct bcm2835_alsa_stream
*alsa_stream
)
137 if (alsa_stream
->my_wq
) {
138 struct bcm2835_audio_work
*work
;
140 work
= kmalloc(sizeof(*work
), GFP_ATOMIC
);
141 /*--- Queue some work (item 1) ---*/
143 INIT_WORK(&work
->my_work
, my_wq_function
);
144 work
->alsa_stream
= alsa_stream
;
145 work
->cmd
= BCM2835_AUDIO_START
;
146 if (queue_work(alsa_stream
->my_wq
, &work
->my_work
))
149 LOG_ERR(" .. Error: NULL work kmalloc\n");
151 LOG_DBG(" .. OUT %d\n", ret
);
155 int bcm2835_audio_stop(struct bcm2835_alsa_stream
*alsa_stream
)
160 if (alsa_stream
->my_wq
) {
161 struct bcm2835_audio_work
*work
;
163 work
= kmalloc(sizeof(*work
), GFP_ATOMIC
);
164 /*--- Queue some work (item 1) ---*/
166 INIT_WORK(&work
->my_work
, my_wq_function
);
167 work
->alsa_stream
= alsa_stream
;
168 work
->cmd
= BCM2835_AUDIO_STOP
;
169 if (queue_work(alsa_stream
->my_wq
, &work
->my_work
))
172 LOG_ERR(" .. Error: NULL work kmalloc\n");
174 LOG_DBG(" .. OUT %d\n", ret
);
178 int bcm2835_audio_write(struct bcm2835_alsa_stream
*alsa_stream
,
179 unsigned int count
, void *src
)
184 if (alsa_stream
->my_wq
) {
185 struct bcm2835_audio_work
*work
;
187 work
= kmalloc(sizeof(*work
), GFP_ATOMIC
);
188 /*--- Queue some work (item 1) ---*/
190 INIT_WORK(&work
->my_work
, my_wq_function
);
191 work
->alsa_stream
= alsa_stream
;
192 work
->cmd
= BCM2835_AUDIO_WRITE
;
195 if (queue_work(alsa_stream
->my_wq
, &work
->my_work
))
198 LOG_ERR(" .. Error: NULL work kmalloc\n");
200 LOG_DBG(" .. OUT %d\n", ret
);
204 static void my_workqueue_init(struct bcm2835_alsa_stream
*alsa_stream
)
206 alsa_stream
->my_wq
= alloc_workqueue("my_queue", WQ_HIGHPRI
, 1);
210 static void my_workqueue_quit(struct bcm2835_alsa_stream
*alsa_stream
)
212 if (alsa_stream
->my_wq
) {
213 flush_workqueue(alsa_stream
->my_wq
);
214 destroy_workqueue(alsa_stream
->my_wq
);
215 alsa_stream
->my_wq
= NULL
;
220 static void audio_vchi_callback(void *param
,
221 const VCHI_CALLBACK_REASON_T reason
,
224 struct bcm2835_audio_instance
*instance
= param
;
227 struct vc_audio_msg m
;
229 LOG_DBG(" .. IN instance=%p, handle=%p, alsa=%p, reason=%d, handle=%p\n",
230 instance
, instance
? instance
->vchi_handle
[0] : NULL
, instance
? instance
->alsa_stream
: NULL
, reason
, msg_handle
);
232 if (reason
!= VCHI_CALLBACK_MSG_AVAILABLE
) {
236 LOG_ERR(" .. instance is null\n");
240 if (!instance
->vchi_handle
[0]) {
241 LOG_ERR(" .. instance->vchi_handle[0] is null\n");
245 status
= vchi_msg_dequeue(instance
->vchi_handle
[0],
246 &m
, sizeof(m
), &msg_len
, VCHI_FLAGS_NONE
);
247 if (m
.type
== VC_AUDIO_MSG_TYPE_RESULT
) {
248 LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
249 instance
, m
.u
.result
.success
);
250 instance
->result
= m
.u
.result
.success
;
251 complete(&instance
->msg_avail_comp
);
252 } else if (m
.type
== VC_AUDIO_MSG_TYPE_COMPLETE
) {
253 struct bcm2835_alsa_stream
*alsa_stream
= instance
->alsa_stream
;
255 LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
256 instance
, m
.u
.complete
.count
);
257 if (m
.u
.complete
.cookie1
!= BCM2835_AUDIO_WRITE_COOKIE1
||
258 m
.u
.complete
.cookie2
!= BCM2835_AUDIO_WRITE_COOKIE2
)
259 LOG_ERR(" .. response is corrupt\n");
260 else if (alsa_stream
) {
261 atomic_add(m
.u
.complete
.count
,
262 &alsa_stream
->retrieved
);
263 bcm2835_playback_fifo(alsa_stream
);
265 LOG_ERR(" .. unexpected alsa_stream=%p\n",
269 LOG_ERR(" .. unexpected m.type=%d\n", m
.type
);
271 LOG_DBG(" .. OUT\n");
274 static struct bcm2835_audio_instance
*
275 vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance
,
276 VCHI_CONNECTION_T
**vchi_connections
,
277 unsigned int num_connections
)
280 struct bcm2835_audio_instance
*instance
;
283 LOG_DBG("%s: start", __func__
);
285 if (num_connections
> VCHI_MAX_NUM_CONNECTIONS
) {
286 LOG_ERR("%s: unsupported number of connections %u (max=%u)\n",
287 __func__
, num_connections
, VCHI_MAX_NUM_CONNECTIONS
);
291 /* Allocate memory for this instance */
292 instance
= kmalloc(sizeof(*instance
), GFP_KERNEL
);
296 memset(instance
, 0, sizeof(*instance
));
297 instance
->num_connections
= num_connections
;
299 /* Create a lock for exclusive, serialized VCHI connection access */
300 mutex_init(&instance
->vchi_mutex
);
301 /* Open the VCHI service connections */
302 for (i
= 0; i
< num_connections
; i
++) {
303 SERVICE_CREATION_T params
= {
304 VCHI_VERSION_EX(VC_AUDIOSERV_VER
, VC_AUDIOSERV_MIN_VER
),
305 VC_AUDIO_SERVER_NAME
, // 4cc service code
306 vchi_connections
[i
], // passed in fn pointers
307 0, // rx fifo size (unused)
308 0, // tx fifo size (unused)
309 audio_vchi_callback
, // service callback
310 instance
, // service callback parameter
311 1, //TODO: remove VCOS_FALSE, // unaligned bulk recieves
312 1, //TODO: remove VCOS_FALSE, // unaligned bulk transmits
313 0 // want crc check on bulk transfers
316 LOG_DBG("%s: about to open %i\n", __func__
, i
);
317 status
= vchi_service_open(vchi_instance
, ¶ms
,
318 &instance
->vchi_handle
[i
]);
319 LOG_DBG("%s: opened %i: %p=%d\n", __func__
, i
, instance
->vchi_handle
[i
], status
);
321 LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
324 goto err_close_services
;
326 /* Finished with the service for now */
327 vchi_service_release(instance
->vchi_handle
[i
]);
330 LOG_DBG("%s: okay\n", __func__
);
334 for (i
= 0; i
< instance
->num_connections
; i
++) {
335 LOG_ERR("%s: closing %i: %p\n", __func__
, i
, instance
->vchi_handle
[i
]);
336 if (instance
->vchi_handle
[i
])
337 vchi_service_close(instance
->vchi_handle
[i
]);
341 LOG_ERR("%s: error\n", __func__
);
346 static int vc_vchi_audio_deinit(struct bcm2835_audio_instance
*instance
)
353 LOG_ERR("%s: invalid handle %p\n", __func__
, instance
);
358 LOG_DBG(" .. about to lock (%d)\n", instance
->num_connections
);
359 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
360 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
361 instance
->num_connections
);
365 /* Close all VCHI service connections */
366 for (i
= 0; i
< instance
->num_connections
; i
++) {
369 LOG_DBG(" .. %i:closing %p\n", i
, instance
->vchi_handle
[i
]);
370 vchi_service_use(instance
->vchi_handle
[i
]);
372 status
= vchi_service_close(instance
->vchi_handle
[i
]);
374 LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
379 mutex_unlock(&instance
->vchi_mutex
);
383 LOG_DBG(" .. OUT\n");
388 static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream
*alsa_stream
)
390 static VCHI_INSTANCE_T vchi_instance
;
391 static VCHI_CONNECTION_T
*vchi_connection
;
393 struct bcm2835_audio_instance
*instance
=
394 (struct bcm2835_audio_instance
*)alsa_stream
->instance
;
399 LOG_INFO("%s: start\n", __func__
);
402 LOG_ERR("%s: VCHI instance already open (%p)\n",
404 instance
->alsa_stream
= alsa_stream
;
405 alsa_stream
->instance
= instance
;
406 ret
= 0; // xxx todo -1;
410 /* Initialize and create a VCHI connection */
412 ret
= vchi_initialise(&vchi_instance
);
414 LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
420 ret
= vchi_connect(NULL
, 0, vchi_instance
);
422 LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
431 /* Initialize an instance of the audio service */
432 instance
= vc_vchi_audio_init(vchi_instance
, &vchi_connection
, 1);
435 LOG_ERR("%s: failed to initialize audio service\n", __func__
);
441 instance
->alsa_stream
= alsa_stream
;
442 alsa_stream
->instance
= instance
;
444 LOG_DBG(" success !\n");
447 LOG_DBG(" .. OUT\n");
452 int bcm2835_audio_open(struct bcm2835_alsa_stream
*alsa_stream
)
454 struct bcm2835_audio_instance
*instance
;
455 struct vc_audio_msg m
;
461 my_workqueue_init(alsa_stream
);
463 ret
= bcm2835_audio_open_connection(alsa_stream
);
468 instance
= alsa_stream
->instance
;
469 LOG_DBG(" instance (%p)\n", instance
);
471 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
472 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance
->num_connections
);
475 vchi_service_use(instance
->vchi_handle
[0]);
477 m
.type
= VC_AUDIO_MSG_TYPE_OPEN
;
479 /* Send the message to the videocore */
480 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
484 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
494 vchi_service_release(instance
->vchi_handle
[0]);
495 mutex_unlock(&instance
->vchi_mutex
);
497 LOG_DBG(" .. OUT\n");
501 static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream
*alsa_stream
,
502 struct bcm2835_chip
*chip
)
504 struct vc_audio_msg m
;
505 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
511 LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
512 chip
->dest
, chip
->volume
);
514 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
515 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
516 instance
->num_connections
);
519 vchi_service_use(instance
->vchi_handle
[0]);
521 instance
->result
= -1;
523 m
.type
= VC_AUDIO_MSG_TYPE_CONTROL
;
524 m
.u
.control
.dest
= chip
->dest
;
525 m
.u
.control
.volume
= chip
->volume
;
527 /* Create the message available completion */
528 init_completion(&instance
->msg_avail_comp
);
530 /* Send the message to the videocore */
531 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
535 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
542 /* We are expecting a reply from the videocore */
543 wait_for_completion(&instance
->msg_avail_comp
);
545 if (instance
->result
) {
546 LOG_ERR("%s: result=%d\n", __func__
, instance
->result
);
555 vchi_service_release(instance
->vchi_handle
[0]);
556 mutex_unlock(&instance
->vchi_mutex
);
558 LOG_DBG(" .. OUT\n");
562 int bcm2835_audio_set_ctls(struct bcm2835_chip
*chip
)
568 LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip
->dest
, chip
->volume
);
570 /* change ctls for all substreams */
571 for (i
= 0; i
< MAX_SUBSTREAMS
; i
++) {
572 if (chip
->avail_substreams
& (1 << i
)) {
573 if (!chip
->alsa_stream
[i
]) {
574 LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i
, chip
->alsa_stream
[i
], chip
->avail_substreams
);
576 } else if (bcm2835_audio_set_ctls_chan(chip
->alsa_stream
[i
], chip
) != 0) {
577 LOG_ERR("Couldn't set the controls for stream %d\n", i
);
580 LOG_DBG(" Controls set for stream %d\n", i
);
584 LOG_DBG(" .. OUT ret=%d\n", ret
);
588 int bcm2835_audio_set_params(struct bcm2835_alsa_stream
*alsa_stream
,
589 unsigned int channels
, unsigned int samplerate
,
592 struct vc_audio_msg m
;
593 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
599 LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
600 channels
, samplerate
, bps
);
602 /* resend ctls - alsa_stream may not have been open when first send */
603 ret
= bcm2835_audio_set_ctls_chan(alsa_stream
, alsa_stream
->chip
);
605 LOG_ERR(" Alsa controls not supported\n");
609 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
610 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance
->num_connections
);
613 vchi_service_use(instance
->vchi_handle
[0]);
615 instance
->result
= -1;
617 m
.type
= VC_AUDIO_MSG_TYPE_CONFIG
;
618 m
.u
.config
.channels
= channels
;
619 m
.u
.config
.samplerate
= samplerate
;
620 m
.u
.config
.bps
= bps
;
622 /* Create the message available completion */
623 init_completion(&instance
->msg_avail_comp
);
625 /* Send the message to the videocore */
626 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
630 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
637 /* We are expecting a reply from the videocore */
638 wait_for_completion(&instance
->msg_avail_comp
);
640 if (instance
->result
) {
641 LOG_ERR("%s: result=%d", __func__
, instance
->result
);
650 vchi_service_release(instance
->vchi_handle
[0]);
651 mutex_unlock(&instance
->vchi_mutex
);
653 LOG_DBG(" .. OUT\n");
657 int bcm2835_audio_setup(struct bcm2835_alsa_stream
*alsa_stream
)
661 LOG_DBG(" .. OUT\n");
666 static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream
*alsa_stream
)
668 struct vc_audio_msg m
;
669 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
675 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
676 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
677 instance
->num_connections
);
680 vchi_service_use(instance
->vchi_handle
[0]);
682 m
.type
= VC_AUDIO_MSG_TYPE_START
;
684 /* Send the message to the videocore */
685 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
689 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
699 vchi_service_release(instance
->vchi_handle
[0]);
700 mutex_unlock(&instance
->vchi_mutex
);
701 LOG_DBG(" .. OUT\n");
705 static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream
*alsa_stream
)
707 struct vc_audio_msg m
;
708 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
714 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
715 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
716 instance
->num_connections
);
719 vchi_service_use(instance
->vchi_handle
[0]);
721 m
.type
= VC_AUDIO_MSG_TYPE_STOP
;
722 m
.u
.stop
.draining
= alsa_stream
->draining
;
724 /* Send the message to the videocore */
725 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
729 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
739 vchi_service_release(instance
->vchi_handle
[0]);
740 mutex_unlock(&instance
->vchi_mutex
);
741 LOG_DBG(" .. OUT\n");
745 int bcm2835_audio_close(struct bcm2835_alsa_stream
*alsa_stream
)
747 struct vc_audio_msg m
;
748 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
754 my_workqueue_quit(alsa_stream
);
756 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
757 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
758 instance
->num_connections
);
761 vchi_service_use(instance
->vchi_handle
[0]);
763 m
.type
= VC_AUDIO_MSG_TYPE_CLOSE
;
765 /* Create the message available completion */
766 init_completion(&instance
->msg_avail_comp
);
768 /* Send the message to the videocore */
769 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
773 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
779 /* We are expecting a reply from the videocore */
780 wait_for_completion(&instance
->msg_avail_comp
);
782 if (instance
->result
) {
783 LOG_ERR("%s: failed result (result=%d)\n",
784 __func__
, instance
->result
);
793 vchi_service_release(instance
->vchi_handle
[0]);
794 mutex_unlock(&instance
->vchi_mutex
);
796 /* Stop the audio service */
797 vc_vchi_audio_deinit(instance
);
798 alsa_stream
->instance
= NULL
;
800 LOG_DBG(" .. OUT\n");
804 static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream
*alsa_stream
,
805 unsigned int count
, void *src
)
807 struct vc_audio_msg m
;
808 struct bcm2835_audio_instance
*instance
= alsa_stream
->instance
;
814 LOG_INFO(" Writing %d bytes from %p\n", count
, src
);
816 if (mutex_lock_interruptible(&instance
->vchi_mutex
)) {
817 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
818 instance
->num_connections
);
821 vchi_service_use(instance
->vchi_handle
[0]);
823 if (instance
->peer_version
== 0 && vchi_get_peer_version(instance
->vchi_handle
[0], &instance
->peer_version
) == 0) {
824 LOG_DBG("%s: client version %d connected\n", __func__
, instance
->peer_version
);
826 m
.type
= VC_AUDIO_MSG_TYPE_WRITE
;
827 m
.u
.write
.count
= count
;
828 // old version uses bulk, new version uses control
829 m
.u
.write
.max_packet
= instance
->peer_version
< 2 || force_bulk
? 0 : 4000;
830 m
.u
.write
.cookie1
= BCM2835_AUDIO_WRITE_COOKIE1
;
831 m
.u
.write
.cookie2
= BCM2835_AUDIO_WRITE_COOKIE2
;
832 m
.u
.write
.silence
= src
== NULL
;
834 /* Send the message to the videocore */
835 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
839 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
845 if (!m
.u
.write
.silence
) {
846 if (!m
.u
.write
.max_packet
) {
847 /* Send the message to the videocore */
848 status
= vchi_bulk_queue_transmit(instance
->vchi_handle
[0],
851 VCHI_FLAGS_BLOCK_UNTIL_QUEUED
854 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ
,
858 int bytes
= min((int) m
.u
.write
.max_packet
, (int) count
);
860 status
= bcm2835_vchi_msg_queue(instance
->vchi_handle
[0],
862 src
= (char *)src
+ bytes
;
867 LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
877 vchi_service_release(instance
->vchi_handle
[0]);
878 mutex_unlock(&instance
->vchi_mutex
);
879 LOG_DBG(" .. OUT\n");
884 * Returns all buffers from arm->vc
886 void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream
*alsa_stream
)
889 LOG_DBG(" .. OUT\n");
894 * Forces VC to flush(drop) its filled playback buffers and
895 * return them the us. (VC->ARM)
897 void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream
*alsa_stream
)
900 LOG_DBG(" .. OUT\n");
903 unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream
*alsa_stream
)
905 unsigned int count
= atomic_read(&alsa_stream
->retrieved
);
907 atomic_sub(count
, &alsa_stream
->retrieved
);
911 module_param(force_bulk
, bool, 0444);
912 MODULE_PARM_DESC(force_bulk
, "Force use of vchiq bulk for audio");