GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / staging / vc04_services / bcm2835-audio / bcm2835-vchiq.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
3
4 #include <linux/device.h>
5 #include <sound/core.h>
6 #include <sound/initval.h>
7 #include <sound/pcm.h>
8 #include <linux/io.h>
9 #include <linux/interrupt.h>
10 #include <linux/fs.h>
11 #include <linux/file.h>
12 #include <linux/mm.h>
13 #include <linux/syscalls.h>
14 #include <linux/uaccess.h>
15 #include <linux/slab.h>
16 #include <linux/delay.h>
17 #include <linux/atomic.h>
18 #include <linux/module.h>
19 #include <linux/completion.h>
20
21 #include "bcm2835.h"
22
23 /* ---- Include Files -------------------------------------------------------- */
24
25 #include "vc_vchi_audioserv_defs.h"
26
27 /* ---- Private Constants and Types ------------------------------------------ */
28
29 #define BCM2835_AUDIO_STOP           0
30 #define BCM2835_AUDIO_START          1
31 #define BCM2835_AUDIO_WRITE          2
32
33 /* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
34 #ifdef AUDIO_DEBUG_ENABLE
35 #define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
36 #define LOG_WARN(fmt, arg...)  pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
37 #define LOG_INFO(fmt, arg...)  pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
38 #define LOG_DBG(fmt, arg...)   pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
39 #else
40 #define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
41 #define LOG_WARN(fmt, arg...)    no_printk(fmt, ##arg)
42 #define LOG_INFO(fmt, arg...)    no_printk(fmt, ##arg)
43 #define LOG_DBG(fmt, arg...)     no_printk(fmt, ##arg)
44 #endif
45
46 struct bcm2835_audio_instance {
47         unsigned int num_connections;
48         VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
49         struct completion msg_avail_comp;
50         struct mutex vchi_mutex;
51         struct bcm2835_alsa_stream *alsa_stream;
52         int result;
53         short peer_version;
54 };
55
56 static bool force_bulk;
57
58 /* ---- Private Variables ---------------------------------------------------- */
59
60 /* ---- Private Function Prototypes ------------------------------------------ */
61
62 /* ---- Private Functions ---------------------------------------------------- */
63
64 static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream);
65 static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream);
66 static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
67                                       unsigned int count, void *src);
68
69 // Routine to send a message across a service
70
71 static int
72 bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
73                        void *data,
74                        unsigned int size)
75 {
76         return vchi_queue_kernel_message(handle,
77                                          data,
78                                          size);
79 }
80
81 static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
82                                                 'M' << 8  | 'A');
83 static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
84                                                 'T' << 8  | 'A');
85
86 struct bcm2835_audio_work {
87         struct work_struct my_work;
88         struct bcm2835_alsa_stream *alsa_stream;
89         int cmd;
90         void *src;
91         unsigned int count;
92 };
93
94 static void my_wq_function(struct work_struct *work)
95 {
96         struct bcm2835_audio_work *w =
97                 container_of(work, struct bcm2835_audio_work, my_work);
98         int ret = -9;
99
100         switch (w->cmd) {
101         case BCM2835_AUDIO_START:
102                 ret = bcm2835_audio_start_worker(w->alsa_stream);
103                 break;
104         case BCM2835_AUDIO_STOP:
105                 ret = bcm2835_audio_stop_worker(w->alsa_stream);
106                 break;
107         case BCM2835_AUDIO_WRITE:
108                 ret = bcm2835_audio_write_worker(w->alsa_stream, w->count,
109                                                  w->src);
110                 break;
111         default:
112                 LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->cmd);
113                 break;
114         }
115         kfree((void *)work);
116 }
117
118 int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
119 {
120         struct bcm2835_audio_work *work;
121
122         work = kmalloc(sizeof(*work), GFP_ATOMIC);
123         /*--- Queue some work (item 1) ---*/
124         if (!work) {
125                 LOG_ERR(" .. Error: NULL work kmalloc\n");
126                 return -ENOMEM;
127         }
128         INIT_WORK(&work->my_work, my_wq_function);
129         work->alsa_stream = alsa_stream;
130         work->cmd = BCM2835_AUDIO_START;
131         if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
132                 kfree(work);
133                 return -EBUSY;
134         }
135         return 0;
136 }
137
138 int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
139 {
140         struct bcm2835_audio_work *work;
141
142         work = kmalloc(sizeof(*work), GFP_ATOMIC);
143         /*--- Queue some work (item 1) ---*/
144         if (!work) {
145                 LOG_ERR(" .. Error: NULL work kmalloc\n");
146                 return -ENOMEM;
147         }
148         INIT_WORK(&work->my_work, my_wq_function);
149         work->alsa_stream = alsa_stream;
150         work->cmd = BCM2835_AUDIO_STOP;
151         if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
152                 kfree(work);
153                 return -EBUSY;
154         }
155         return 0;
156 }
157
158 int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
159                         unsigned int count, void *src)
160 {
161         struct bcm2835_audio_work *work;
162
163         work = kmalloc(sizeof(*work), GFP_ATOMIC);
164         /*--- Queue some work (item 1) ---*/
165         if (!work) {
166                 LOG_ERR(" .. Error: NULL work kmalloc\n");
167                 return -ENOMEM;
168         }
169         INIT_WORK(&work->my_work, my_wq_function);
170         work->alsa_stream = alsa_stream;
171         work->cmd = BCM2835_AUDIO_WRITE;
172         work->src = src;
173         work->count = count;
174         if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
175                 kfree(work);
176                 return -EBUSY;
177         }
178         return 0;
179 }
180
181 static void my_workqueue_quit(struct bcm2835_alsa_stream *alsa_stream)
182 {
183         flush_workqueue(alsa_stream->my_wq);
184         destroy_workqueue(alsa_stream->my_wq);
185         alsa_stream->my_wq = NULL;
186 }
187
188 static void audio_vchi_callback(void *param,
189                                 const VCHI_CALLBACK_REASON_T reason,
190                                 void *msg_handle)
191 {
192         struct bcm2835_audio_instance *instance = param;
193         int status;
194         int msg_len;
195         struct vc_audio_msg m;
196
197         if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
198                 return;
199
200         if (!instance) {
201                 LOG_ERR(" .. instance is null\n");
202                 BUG();
203                 return;
204         }
205         if (!instance->vchi_handle[0]) {
206                 LOG_ERR(" .. instance->vchi_handle[0] is null\n");
207                 BUG();
208                 return;
209         }
210         status = vchi_msg_dequeue(instance->vchi_handle[0],
211                                   &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
212         if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
213                 LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
214                         instance, m.u.result.success);
215                 instance->result = m.u.result.success;
216                 complete(&instance->msg_avail_comp);
217         } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
218                 struct bcm2835_alsa_stream *alsa_stream = instance->alsa_stream;
219
220                 LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
221                         instance, m.u.complete.count);
222                 if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
223                     m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
224                         LOG_ERR(" .. response is corrupt\n");
225                 else if (alsa_stream) {
226                         atomic_add(m.u.complete.count,
227                                    &alsa_stream->retrieved);
228                         bcm2835_playback_fifo(alsa_stream);
229                 } else {
230                         LOG_ERR(" .. unexpected alsa_stream=%p\n",
231                                 alsa_stream);
232                 }
233         } else {
234                 LOG_ERR(" .. unexpected m.type=%d\n", m.type);
235         }
236 }
237
238 static struct bcm2835_audio_instance *
239 vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
240                    VCHI_CONNECTION_T **vchi_connections,
241                    unsigned int num_connections)
242 {
243         unsigned int i;
244         struct bcm2835_audio_instance *instance;
245         int status;
246         int ret;
247
248         LOG_DBG("%s: start", __func__);
249
250         if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
251                 LOG_ERR("%s: unsupported number of connections %u (max=%u)\n",
252                         __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
253
254                 return ERR_PTR(-EINVAL);
255         }
256         /* Allocate memory for this instance */
257         instance = kzalloc(sizeof(*instance), GFP_KERNEL);
258         if (!instance)
259                 return ERR_PTR(-ENOMEM);
260
261         instance->num_connections = num_connections;
262
263         /* Create a lock for exclusive, serialized VCHI connection access */
264         mutex_init(&instance->vchi_mutex);
265         /* Open the VCHI service connections */
266         for (i = 0; i < num_connections; i++) {
267                 SERVICE_CREATION_T params = {
268                         .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
269                         .service_id             = VC_AUDIO_SERVER_NAME,
270                         .connection             = vchi_connections[i],
271                         .rx_fifo_size           = 0,
272                         .tx_fifo_size           = 0,
273                         .callback               = audio_vchi_callback,
274                         .callback_param         = instance,
275                         .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
276                         .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
277                         .want_crc               = 0
278                 };
279
280                 LOG_DBG("%s: about to open %i\n", __func__, i);
281                 status = vchi_service_open(vchi_instance, &params,
282                                            &instance->vchi_handle[i]);
283
284                 LOG_DBG("%s: opened %i: %p=%d\n", __func__, i, instance->vchi_handle[i], status);
285                 if (status) {
286                         LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
287                                 __func__, status);
288                         ret = -EPERM;
289                         goto err_close_services;
290                 }
291                 /* Finished with the service for now */
292                 vchi_service_release(instance->vchi_handle[i]);
293         }
294
295         LOG_DBG("%s: okay\n", __func__);
296         return instance;
297
298 err_close_services:
299         for (i = 0; i < instance->num_connections; i++) {
300                 LOG_ERR("%s: closing %i: %p\n", __func__, i, instance->vchi_handle[i]);
301                 if (instance->vchi_handle[i])
302                         vchi_service_close(instance->vchi_handle[i]);
303         }
304
305         kfree(instance);
306         LOG_ERR("%s: error\n", __func__);
307
308         return ERR_PTR(ret);
309 }
310
311 static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
312 {
313         unsigned int i;
314
315         if (!instance) {
316                 LOG_ERR("%s: invalid handle %p\n", __func__, instance);
317
318                 return -1;
319         }
320
321         LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
322         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
323                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
324                         instance->num_connections);
325                 return -EINTR;
326         }
327
328         /* Close all VCHI service connections */
329         for (i = 0; i < instance->num_connections; i++) {
330                 int status;
331
332                 LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);
333                 vchi_service_use(instance->vchi_handle[i]);
334
335                 status = vchi_service_close(instance->vchi_handle[i]);
336                 if (status) {
337                         LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
338                                 __func__, status);
339                 }
340         }
341
342         mutex_unlock(&instance->vchi_mutex);
343
344         kfree(instance);
345
346         return 0;
347 }
348
349 int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
350 {
351         int ret;
352
353         /* Initialize and create a VCHI connection */
354         ret = vchi_initialise(&vchi_ctx->vchi_instance);
355         if (ret) {
356                 LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
357                         __func__, ret);
358
359                 return -EIO;
360         }
361
362         ret = vchi_connect(NULL, 0, vchi_ctx->vchi_instance);
363         if (ret) {
364                 LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
365                         __func__, ret);
366
367                 kfree(vchi_ctx->vchi_instance);
368                 vchi_ctx->vchi_instance = NULL;
369
370                 return -EIO;
371         }
372
373         return 0;
374 }
375
376 void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
377 {
378         /* Close the VCHI connection - it will also free vchi_instance */
379         WARN_ON(vchi_disconnect(vchi_ctx->vchi_instance));
380
381         vchi_ctx->vchi_instance = NULL;
382 }
383
384 static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream)
385 {
386         struct bcm2835_audio_instance *instance =
387                 (struct bcm2835_audio_instance *)alsa_stream->instance;
388         struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
389
390         LOG_INFO("%s: start\n", __func__);
391         BUG_ON(instance);
392         if (instance) {
393                 LOG_ERR("%s: VCHI instance already open (%p)\n",
394                         __func__, instance);
395                 instance->alsa_stream = alsa_stream;
396                 alsa_stream->instance = instance;
397                 return 0;
398         }
399
400         /* Initialize an instance of the audio service */
401         instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
402                                       &vhci_ctx->vchi_connection, 1);
403
404         if (IS_ERR(instance)) {
405                 LOG_ERR("%s: failed to initialize audio service\n", __func__);
406
407                 /* vchi_instance is retained for use the next time. */
408                 return PTR_ERR(instance);
409         }
410
411         instance->alsa_stream = alsa_stream;
412         alsa_stream->instance = instance;
413
414         LOG_DBG(" success !\n");
415
416         return 0;
417 }
418
419 int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
420 {
421         struct bcm2835_audio_instance *instance;
422         struct vc_audio_msg m;
423         int status;
424         int ret;
425
426         alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
427         if (!alsa_stream->my_wq)
428                 return -ENOMEM;
429
430         ret = bcm2835_audio_open_connection(alsa_stream);
431         if (ret)
432                 goto free_wq;
433
434         instance = alsa_stream->instance;
435         LOG_DBG(" instance (%p)\n", instance);
436
437         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
438                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
439                 ret = -EINTR;
440                 goto free_wq;
441         }
442         vchi_service_use(instance->vchi_handle[0]);
443
444         m.type = VC_AUDIO_MSG_TYPE_OPEN;
445
446         /* Send the message to the videocore */
447         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
448                                         &m, sizeof(m));
449
450         if (status) {
451                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
452                         __func__, status);
453
454                 ret = -1;
455                 goto unlock;
456         }
457
458         ret = 0;
459
460 unlock:
461         vchi_service_release(instance->vchi_handle[0]);
462         mutex_unlock(&instance->vchi_mutex);
463
464 free_wq:
465         if (ret)
466                 destroy_workqueue(alsa_stream->my_wq);
467
468         return ret;
469 }
470
471 static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
472                                        struct bcm2835_chip *chip)
473 {
474         struct vc_audio_msg m;
475         struct bcm2835_audio_instance *instance = alsa_stream->instance;
476         int status;
477         int ret;
478
479         LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
480                  chip->dest, chip->volume);
481
482         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
483                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
484                         instance->num_connections);
485                 return -EINTR;
486         }
487         vchi_service_use(instance->vchi_handle[0]);
488
489         instance->result = -1;
490
491         m.type = VC_AUDIO_MSG_TYPE_CONTROL;
492         m.u.control.dest = chip->dest;
493         m.u.control.volume = chip->volume;
494
495         /* Create the message available completion */
496         init_completion(&instance->msg_avail_comp);
497
498         /* Send the message to the videocore */
499         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
500                                         &m, sizeof(m));
501
502         if (status) {
503                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
504                         __func__, status);
505
506                 ret = -1;
507                 goto unlock;
508         }
509
510         /* We are expecting a reply from the videocore */
511         wait_for_completion(&instance->msg_avail_comp);
512
513         if (instance->result) {
514                 LOG_ERR("%s: result=%d\n", __func__, instance->result);
515
516                 ret = -1;
517                 goto unlock;
518         }
519
520         ret = 0;
521
522 unlock:
523         vchi_service_release(instance->vchi_handle[0]);
524         mutex_unlock(&instance->vchi_mutex);
525
526         return ret;
527 }
528
529 int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
530 {
531         int i;
532         int ret = 0;
533
534         LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
535
536         /* change ctls for all substreams */
537         for (i = 0; i < MAX_SUBSTREAMS; i++) {
538                 if (chip->avail_substreams & (1 << i)) {
539                         if (!chip->alsa_stream[i]) {
540                                 LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i, chip->alsa_stream[i], chip->avail_substreams);
541                                 ret = 0;
542                         } else if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
543                                 LOG_ERR("Couldn't set the controls for stream %d\n", i);
544                                 ret = -1;
545                         } else {
546                                 LOG_DBG(" Controls set for stream %d\n", i);
547                         }
548                 }
549         }
550         return ret;
551 }
552
553 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
554                              unsigned int channels, unsigned int samplerate,
555                              unsigned int bps)
556 {
557         struct vc_audio_msg m;
558         struct bcm2835_audio_instance *instance = alsa_stream->instance;
559         int status;
560         int ret;
561
562         LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
563                  channels, samplerate, bps);
564
565         /* resend ctls - alsa_stream may not have been open when first send */
566         ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
567         if (ret) {
568                 LOG_ERR(" Alsa controls not supported\n");
569                 return -EINVAL;
570         }
571
572         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
573                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
574                 return -EINTR;
575         }
576         vchi_service_use(instance->vchi_handle[0]);
577
578         instance->result = -1;
579
580         m.type = VC_AUDIO_MSG_TYPE_CONFIG;
581         m.u.config.channels = channels;
582         m.u.config.samplerate = samplerate;
583         m.u.config.bps = bps;
584
585         /* Create the message available completion */
586         init_completion(&instance->msg_avail_comp);
587
588         /* Send the message to the videocore */
589         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
590                                         &m, sizeof(m));
591
592         if (status) {
593                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
594                         __func__, status);
595
596                 ret = -1;
597                 goto unlock;
598         }
599
600         /* We are expecting a reply from the videocore */
601         wait_for_completion(&instance->msg_avail_comp);
602
603         if (instance->result) {
604                 LOG_ERR("%s: result=%d", __func__, instance->result);
605
606                 ret = -1;
607                 goto unlock;
608         }
609
610         ret = 0;
611
612 unlock:
613         vchi_service_release(instance->vchi_handle[0]);
614         mutex_unlock(&instance->vchi_mutex);
615
616         return ret;
617 }
618
619 int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
620 {
621
622         return 0;
623 }
624
625 static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
626 {
627         struct vc_audio_msg m;
628         struct bcm2835_audio_instance *instance = alsa_stream->instance;
629         int status;
630         int ret;
631
632         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
633                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
634                         instance->num_connections);
635                 return -EINTR;
636         }
637         vchi_service_use(instance->vchi_handle[0]);
638
639         m.type = VC_AUDIO_MSG_TYPE_START;
640
641         /* Send the message to the videocore */
642         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
643                                         &m, sizeof(m));
644
645         if (status) {
646                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
647                         __func__, status);
648
649                 ret = -1;
650                 goto unlock;
651         }
652
653         ret = 0;
654
655 unlock:
656         vchi_service_release(instance->vchi_handle[0]);
657         mutex_unlock(&instance->vchi_mutex);
658         return ret;
659 }
660
661 static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
662 {
663         struct vc_audio_msg m;
664         struct bcm2835_audio_instance *instance = alsa_stream->instance;
665         int status;
666         int ret;
667
668         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
669                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
670                         instance->num_connections);
671                 return -EINTR;
672         }
673         vchi_service_use(instance->vchi_handle[0]);
674
675         m.type = VC_AUDIO_MSG_TYPE_STOP;
676         m.u.stop.draining = alsa_stream->draining;
677
678         /* Send the message to the videocore */
679         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
680                                         &m, sizeof(m));
681
682         if (status) {
683                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
684                         __func__, status);
685
686                 ret = -1;
687                 goto unlock;
688         }
689
690         ret = 0;
691
692 unlock:
693         vchi_service_release(instance->vchi_handle[0]);
694         mutex_unlock(&instance->vchi_mutex);
695         return ret;
696 }
697
698 int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
699 {
700         struct vc_audio_msg m;
701         struct bcm2835_audio_instance *instance = alsa_stream->instance;
702         int status;
703         int ret;
704
705         my_workqueue_quit(alsa_stream);
706
707         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
708                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
709                         instance->num_connections);
710                 return -EINTR;
711         }
712         vchi_service_use(instance->vchi_handle[0]);
713
714         m.type = VC_AUDIO_MSG_TYPE_CLOSE;
715
716         /* Create the message available completion */
717         init_completion(&instance->msg_avail_comp);
718
719         /* Send the message to the videocore */
720         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
721                                         &m, sizeof(m));
722
723         if (status) {
724                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
725                         __func__, status);
726                 ret = -1;
727                 goto unlock;
728         }
729
730         /* We are expecting a reply from the videocore */
731         wait_for_completion(&instance->msg_avail_comp);
732
733         if (instance->result) {
734                 LOG_ERR("%s: failed result (result=%d)\n",
735                         __func__, instance->result);
736
737                 ret = -1;
738                 goto unlock;
739         }
740
741         ret = 0;
742
743 unlock:
744         vchi_service_release(instance->vchi_handle[0]);
745         mutex_unlock(&instance->vchi_mutex);
746
747         /* Stop the audio service */
748         vc_vchi_audio_deinit(instance);
749         alsa_stream->instance = NULL;
750
751         return ret;
752 }
753
754 static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
755                                       unsigned int count, void *src)
756 {
757         struct vc_audio_msg m;
758         struct bcm2835_audio_instance *instance = alsa_stream->instance;
759         int status;
760         int ret;
761
762         LOG_INFO(" Writing %d bytes from %p\n", count, src);
763
764         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
765                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
766                         instance->num_connections);
767                 return -EINTR;
768         }
769         vchi_service_use(instance->vchi_handle[0]);
770
771         if (instance->peer_version == 0 &&
772             vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0)
773                 LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
774
775         m.type = VC_AUDIO_MSG_TYPE_WRITE;
776         m.u.write.count = count;
777         // old version uses bulk, new version uses control
778         m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0 : 4000;
779         m.u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1;
780         m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2;
781         m.u.write.silence = src == NULL;
782
783         /* Send the message to the videocore */
784         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
785                                         &m, sizeof(m));
786
787         if (status) {
788                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
789                         __func__, status);
790
791                 ret = -1;
792                 goto unlock;
793         }
794         if (!m.u.write.silence) {
795                 if (!m.u.write.max_packet) {
796                         /* Send the message to the videocore */
797                         status = vchi_bulk_queue_transmit(instance->vchi_handle[0],
798                                                           src, count,
799                                                           0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
800                                                           +
801                                                           1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
802                                                           NULL);
803                 } else {
804                         while (count > 0) {
805                                 int bytes = min_t(int, m.u.write.max_packet, count);
806
807                                 status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
808                                                                 src, bytes);
809                                 src = (char *)src + bytes;
810                                 count -= bytes;
811                         }
812                 }
813                 if (status) {
814                         LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
815                                 __func__, status);
816
817                         ret = -1;
818                         goto unlock;
819                 }
820         }
821         ret = 0;
822
823 unlock:
824         vchi_service_release(instance->vchi_handle[0]);
825         mutex_unlock(&instance->vchi_mutex);
826         return ret;
827 }
828
829 /**
830  * Returns all buffers from arm->vc
831  */
832 void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream)
833 {
834 }
835
836 /**
837  * Forces VC to flush(drop) its filled playback buffers and
838  * return them the us. (VC->ARM)
839  */
840 void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
841 {
842 }
843
844 unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
845 {
846         unsigned int count = atomic_read(&alsa_stream->retrieved);
847
848         atomic_sub(count, &alsa_stream->retrieved);
849         return count;
850 }
851
852 module_param(force_bulk, bool, 0444);
853 MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");