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
bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,void * data,unsigned int size)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 
my_wq_function(struct work_struct * work)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 
bcm2835_audio_start(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_stop(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_write(struct bcm2835_alsa_stream * alsa_stream,unsigned int count,void * src)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 
my_workqueue_quit(struct bcm2835_alsa_stream * alsa_stream)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 
audio_vchi_callback(void * param,const VCHI_CALLBACK_REASON_T reason,void * msg_handle)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 *
vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,VCHI_CONNECTION_T ** vchi_connections,unsigned int num_connections)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 
vc_vchi_audio_deinit(struct bcm2835_audio_instance * instance)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 
bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx * vchi_ctx)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 
bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx * vchi_ctx)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 
bcm2835_audio_open_connection(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_open(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream * alsa_stream,struct bcm2835_chip * chip)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 
bcm2835_audio_set_ctls(struct bcm2835_chip * chip)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 
bcm2835_audio_set_params(struct bcm2835_alsa_stream * alsa_stream,unsigned int channels,unsigned int samplerate,unsigned int bps)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 
bcm2835_audio_setup(struct bcm2835_alsa_stream * alsa_stream)619 int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
620 {
621 
622 	return 0;
623 }
624 
bcm2835_audio_start_worker(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_stop_worker(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_close(struct bcm2835_alsa_stream * alsa_stream)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 
bcm2835_audio_write_worker(struct bcm2835_alsa_stream * alsa_stream,unsigned int count,void * src)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  */
bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream * alsa_stream)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  */
bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream * alsa_stream)840 void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
841 {
842 }
843 
bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream * alsa_stream)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");
854