Merge tag 'drm-misc-fixes-2017-11-13' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.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                 ret = -1;
447                 goto exit;
448         }
449         instance = alsa_stream->instance;
450         LOG_DBG(" instance (%p)\n", instance);
451
452         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
453                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
454                 return -EINTR;
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 exit:
478         return ret;
479 }
480
481 static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
482                                        struct bcm2835_chip *chip)
483 {
484         struct vc_audio_msg m;
485         struct bcm2835_audio_instance *instance = alsa_stream->instance;
486         int status;
487         int ret;
488
489
490         LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
491                  chip->dest, chip->volume);
492
493         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
494                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
495                         instance->num_connections);
496                 return -EINTR;
497         }
498         vchi_service_use(instance->vchi_handle[0]);
499
500         instance->result = -1;
501
502         m.type = VC_AUDIO_MSG_TYPE_CONTROL;
503         m.u.control.dest = chip->dest;
504         m.u.control.volume = chip->volume;
505
506         /* Create the message available completion */
507         init_completion(&instance->msg_avail_comp);
508
509         /* Send the message to the videocore */
510         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
511                                         &m, sizeof(m));
512
513         if (status) {
514                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
515                         __func__, status);
516
517                 ret = -1;
518                 goto unlock;
519         }
520
521         /* We are expecting a reply from the videocore */
522         wait_for_completion(&instance->msg_avail_comp);
523
524         if (instance->result) {
525                 LOG_ERR("%s: result=%d\n", __func__, instance->result);
526
527                 ret = -1;
528                 goto unlock;
529         }
530
531         ret = 0;
532
533 unlock:
534         vchi_service_release(instance->vchi_handle[0]);
535         mutex_unlock(&instance->vchi_mutex);
536
537         return ret;
538 }
539
540 int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
541 {
542         int i;
543         int ret = 0;
544
545         LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
546
547         /* change ctls for all substreams */
548         for (i = 0; i < MAX_SUBSTREAMS; i++) {
549                 if (chip->avail_substreams & (1 << i)) {
550                         if (!chip->alsa_stream[i]) {
551                                 LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i, chip->alsa_stream[i], chip->avail_substreams);
552                                 ret = 0;
553                         } else if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
554                                 LOG_ERR("Couldn't set the controls for stream %d\n", i);
555                                 ret = -1;
556                         } else {
557                                 LOG_DBG(" Controls set for stream %d\n", i);
558                         }
559                 }
560         }
561         return ret;
562 }
563
564 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
565                              unsigned int channels, unsigned int samplerate,
566                              unsigned int bps)
567 {
568         struct vc_audio_msg m;
569         struct bcm2835_audio_instance *instance = alsa_stream->instance;
570         int status;
571         int ret;
572
573
574         LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
575                  channels, samplerate, bps);
576
577         /* resend ctls - alsa_stream may not have been open when first send */
578         ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
579         if (ret) {
580                 LOG_ERR(" Alsa controls not supported\n");
581                 return -EINVAL;
582         }
583
584         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
585                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
586                 return -EINTR;
587         }
588         vchi_service_use(instance->vchi_handle[0]);
589
590         instance->result = -1;
591
592         m.type = VC_AUDIO_MSG_TYPE_CONFIG;
593         m.u.config.channels = channels;
594         m.u.config.samplerate = samplerate;
595         m.u.config.bps = bps;
596
597         /* Create the message available completion */
598         init_completion(&instance->msg_avail_comp);
599
600         /* Send the message to the videocore */
601         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
602                                         &m, sizeof(m));
603
604         if (status) {
605                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
606                         __func__, status);
607
608                 ret = -1;
609                 goto unlock;
610         }
611
612         /* We are expecting a reply from the videocore */
613         wait_for_completion(&instance->msg_avail_comp);
614
615         if (instance->result) {
616                 LOG_ERR("%s: result=%d", __func__, instance->result);
617
618                 ret = -1;
619                 goto unlock;
620         }
621
622         ret = 0;
623
624 unlock:
625         vchi_service_release(instance->vchi_handle[0]);
626         mutex_unlock(&instance->vchi_mutex);
627
628         return ret;
629 }
630
631 int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
632 {
633
634
635         return 0;
636 }
637
638 static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
639 {
640         struct vc_audio_msg m;
641         struct bcm2835_audio_instance *instance = alsa_stream->instance;
642         int status;
643         int ret;
644
645
646         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
647                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
648                         instance->num_connections);
649                 return -EINTR;
650         }
651         vchi_service_use(instance->vchi_handle[0]);
652
653         m.type = VC_AUDIO_MSG_TYPE_START;
654
655         /* Send the message to the videocore */
656         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
657                                         &m, sizeof(m));
658
659         if (status) {
660                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
661                         __func__, status);
662
663                 ret = -1;
664                 goto unlock;
665         }
666
667         ret = 0;
668
669 unlock:
670         vchi_service_release(instance->vchi_handle[0]);
671         mutex_unlock(&instance->vchi_mutex);
672         return ret;
673 }
674
675 static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
676 {
677         struct vc_audio_msg m;
678         struct bcm2835_audio_instance *instance = alsa_stream->instance;
679         int status;
680         int ret;
681
682
683         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
684                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
685                         instance->num_connections);
686                 return -EINTR;
687         }
688         vchi_service_use(instance->vchi_handle[0]);
689
690         m.type = VC_AUDIO_MSG_TYPE_STOP;
691         m.u.stop.draining = alsa_stream->draining;
692
693         /* Send the message to the videocore */
694         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
695                                         &m, sizeof(m));
696
697         if (status) {
698                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
699                         __func__, status);
700
701                 ret = -1;
702                 goto unlock;
703         }
704
705         ret = 0;
706
707 unlock:
708         vchi_service_release(instance->vchi_handle[0]);
709         mutex_unlock(&instance->vchi_mutex);
710         return ret;
711 }
712
713 int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
714 {
715         struct vc_audio_msg m;
716         struct bcm2835_audio_instance *instance = alsa_stream->instance;
717         int status;
718         int ret;
719
720
721         my_workqueue_quit(alsa_stream);
722
723         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
724                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
725                         instance->num_connections);
726                 return -EINTR;
727         }
728         vchi_service_use(instance->vchi_handle[0]);
729
730         m.type = VC_AUDIO_MSG_TYPE_CLOSE;
731
732         /* Create the message available completion */
733         init_completion(&instance->msg_avail_comp);
734
735         /* Send the message to the videocore */
736         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
737                                         &m, sizeof(m));
738
739         if (status) {
740                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
741                         __func__, status);
742                 ret = -1;
743                 goto unlock;
744         }
745
746         /* We are expecting a reply from the videocore */
747         wait_for_completion(&instance->msg_avail_comp);
748
749         if (instance->result) {
750                 LOG_ERR("%s: failed result (result=%d)\n",
751                         __func__, instance->result);
752
753                 ret = -1;
754                 goto unlock;
755         }
756
757         ret = 0;
758
759 unlock:
760         vchi_service_release(instance->vchi_handle[0]);
761         mutex_unlock(&instance->vchi_mutex);
762
763         /* Stop the audio service */
764         vc_vchi_audio_deinit(instance);
765         alsa_stream->instance = NULL;
766
767         return ret;
768 }
769
770 static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
771                                       unsigned int count, void *src)
772 {
773         struct vc_audio_msg m;
774         struct bcm2835_audio_instance *instance = alsa_stream->instance;
775         int status;
776         int ret;
777
778
779         LOG_INFO(" Writing %d bytes from %p\n", count, src);
780
781         if (mutex_lock_interruptible(&instance->vchi_mutex)) {
782                 LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
783                         instance->num_connections);
784                 return -EINTR;
785         }
786         vchi_service_use(instance->vchi_handle[0]);
787
788         if (instance->peer_version == 0 &&
789             vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0)
790                 LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
791
792         m.type = VC_AUDIO_MSG_TYPE_WRITE;
793         m.u.write.count = count;
794         // old version uses bulk, new version uses control
795         m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0 : 4000;
796         m.u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1;
797         m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2;
798         m.u.write.silence = src == NULL;
799
800         /* Send the message to the videocore */
801         status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
802                                         &m, sizeof(m));
803
804         if (status) {
805                 LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
806                         __func__, status);
807
808                 ret = -1;
809                 goto unlock;
810         }
811         if (!m.u.write.silence) {
812                 if (!m.u.write.max_packet) {
813                         /* Send the message to the videocore */
814                         status = vchi_bulk_queue_transmit(instance->vchi_handle[0],
815                                                           src, count,
816                                                           0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
817                                                           +
818                                                           1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
819                                                           NULL);
820                 } else {
821                         while (count > 0) {
822                                 int bytes = min_t(int, m.u.write.max_packet, count);
823
824                                 status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
825                                                                 src, bytes);
826                                 src = (char *)src + bytes;
827                                 count -= bytes;
828                         }
829                 }
830                 if (status) {
831                         LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
832                                 __func__, status);
833
834                         ret = -1;
835                         goto unlock;
836                 }
837         }
838         ret = 0;
839
840 unlock:
841         vchi_service_release(instance->vchi_handle[0]);
842         mutex_unlock(&instance->vchi_mutex);
843         return ret;
844 }
845
846 /**
847  * Returns all buffers from arm->vc
848  */
849 void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream)
850 {
851 }
852
853 /**
854  * Forces VC to flush(drop) its filled playback buffers and
855  * return them the us. (VC->ARM)
856  */
857 void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
858 {
859 }
860
861 unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
862 {
863         unsigned int count = atomic_read(&alsa_stream->retrieved);
864
865         atomic_sub(count, &alsa_stream->retrieved);
866         return count;
867 }
868
869 module_param(force_bulk, bool, 0444);
870 MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");