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