1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
3 
4 #include <linux/slab.h>
5 #include <linux/module.h>
6 #include <linux/completion.h>
7 #include "bcm2835.h"
8 #include "vc_vchi_audioserv_defs.h"
9 
10 #include "../interface/vchiq_arm/vchiq_arm.h"
11 
12 struct bcm2835_audio_instance {
13 	struct device *dev;
14 	unsigned int service_handle;
15 	struct completion msg_avail_comp;
16 	struct mutex vchi_mutex; /* Serialize vchiq access */
17 	struct bcm2835_alsa_stream *alsa_stream;
18 	int result;
19 	unsigned int max_packet;
20 	short peer_version;
21 };
22 
23 static bool force_bulk;
24 module_param(force_bulk, bool, 0444);
25 MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
26 
bcm2835_audio_lock(struct bcm2835_audio_instance * instance)27 static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
28 {
29 	mutex_lock(&instance->vchi_mutex);
30 	vchiq_use_service(instance->alsa_stream->chip->vchi_ctx->instance,
31 			  instance->service_handle);
32 }
33 
bcm2835_audio_unlock(struct bcm2835_audio_instance * instance)34 static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
35 {
36 	vchiq_release_service(instance->alsa_stream->chip->vchi_ctx->instance,
37 			      instance->service_handle);
38 	mutex_unlock(&instance->vchi_mutex);
39 }
40 
bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance * instance,struct vc_audio_msg * m,bool wait)41 static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
42 					 struct vc_audio_msg *m, bool wait)
43 {
44 	int status;
45 
46 	if (wait) {
47 		instance->result = -1;
48 		init_completion(&instance->msg_avail_comp);
49 	}
50 
51 	status = vchiq_queue_kernel_message(instance->alsa_stream->chip->vchi_ctx->instance,
52 					    instance->service_handle, m, sizeof(*m));
53 	if (status) {
54 		dev_err(instance->dev,
55 			"vchi message queue failed: %d, msg=%d\n",
56 			status, m->type);
57 		return -EIO;
58 	}
59 
60 	if (wait) {
61 		if (!wait_for_completion_timeout(&instance->msg_avail_comp,
62 						 secs_to_jiffies(10))) {
63 			dev_err(instance->dev,
64 				"vchi message timeout, msg=%d\n", m->type);
65 			return -ETIMEDOUT;
66 		} else if (instance->result) {
67 			dev_err(instance->dev,
68 				"vchi message response error:%d, msg=%d\n",
69 				instance->result, m->type);
70 			return -EIO;
71 		}
72 	}
73 
74 	return 0;
75 }
76 
bcm2835_audio_send_msg(struct bcm2835_audio_instance * instance,struct vc_audio_msg * m,bool wait)77 static int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
78 				  struct vc_audio_msg *m, bool wait)
79 {
80 	int err;
81 
82 	bcm2835_audio_lock(instance);
83 	err = bcm2835_audio_send_msg_locked(instance, m, wait);
84 	bcm2835_audio_unlock(instance);
85 	return err;
86 }
87 
bcm2835_audio_send_simple(struct bcm2835_audio_instance * instance,int type,bool wait)88 static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
89 				     int type, bool wait)
90 {
91 	struct vc_audio_msg m = { .type = type };
92 
93 	return bcm2835_audio_send_msg(instance, &m, wait);
94 }
95 
audio_vchi_callback(struct vchiq_instance * vchiq_instance,enum vchiq_reason reason,struct vchiq_header * header,unsigned int handle,void * cb_data,void __user * cb_userdata)96 static int audio_vchi_callback(struct vchiq_instance *vchiq_instance,
97 			       enum vchiq_reason reason,
98 			       struct vchiq_header *header,
99 			       unsigned int handle,
100 			       void *cb_data, void __user *cb_userdata)
101 {
102 	struct bcm2835_audio_instance *instance = vchiq_get_service_userdata(vchiq_instance,
103 									     handle);
104 	struct vc_audio_msg *m;
105 
106 	if (reason != VCHIQ_MESSAGE_AVAILABLE)
107 		return 0;
108 
109 	m = (void *)header->data;
110 	if (m->type == VC_AUDIO_MSG_TYPE_RESULT) {
111 		instance->result = m->result.success;
112 		complete(&instance->msg_avail_comp);
113 	} else if (m->type == VC_AUDIO_MSG_TYPE_COMPLETE) {
114 		if (m->complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
115 		    m->complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
116 			dev_err(instance->dev, "invalid cookie\n");
117 		else
118 			bcm2835_playback_fifo(instance->alsa_stream,
119 					      m->complete.count);
120 	} else {
121 		dev_err(instance->dev, "unexpected callback type=%d\n", m->type);
122 	}
123 
124 	vchiq_release_message(vchiq_instance, instance->service_handle, header);
125 	return 0;
126 }
127 
128 static int
vc_vchi_audio_init(struct vchiq_instance * vchiq_instance,struct bcm2835_audio_instance * instance)129 vc_vchi_audio_init(struct vchiq_instance *vchiq_instance,
130 		   struct bcm2835_audio_instance *instance)
131 {
132 	struct vchiq_service_params_kernel params = {
133 		.version		= VC_AUDIOSERV_VER,
134 		.version_min		= VC_AUDIOSERV_MIN_VER,
135 		.fourcc			= VCHIQ_MAKE_FOURCC('A', 'U', 'D', 'S'),
136 		.callback		= audio_vchi_callback,
137 		.userdata		= instance,
138 	};
139 	int status;
140 
141 	/* Open the VCHI service connections */
142 	status = vchiq_open_service(vchiq_instance, &params,
143 				    &instance->service_handle);
144 
145 	if (status) {
146 		dev_err(instance->dev,
147 			"failed to open VCHI service connection (status=%d)\n",
148 			status);
149 		return -EPERM;
150 	}
151 
152 	/* Finished with the service for now */
153 	vchiq_release_service(instance->alsa_stream->chip->vchi_ctx->instance,
154 			      instance->service_handle);
155 
156 	return 0;
157 }
158 
vc_vchi_audio_deinit(struct bcm2835_audio_instance * instance)159 static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
160 {
161 	int status;
162 
163 	mutex_lock(&instance->vchi_mutex);
164 	vchiq_use_service(instance->alsa_stream->chip->vchi_ctx->instance,
165 			  instance->service_handle);
166 
167 	/* Close all VCHI service connections */
168 	status = vchiq_close_service(instance->alsa_stream->chip->vchi_ctx->instance,
169 				     instance->service_handle);
170 	if (status) {
171 		dev_err(instance->dev,
172 			"failed to close VCHI service connection (status=%d)\n",
173 			status);
174 	}
175 
176 	mutex_unlock(&instance->vchi_mutex);
177 }
178 
bcm2835_new_vchi_ctx(struct device * dev,struct bcm2835_vchi_ctx * vchi_ctx)179 int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
180 {
181 	struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(dev->parent);
182 	int ret;
183 
184 	/* Initialize and create a VCHI connection */
185 	ret = vchiq_initialise(&mgmt->state, &vchi_ctx->instance);
186 	if (ret) {
187 		dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
188 			ret);
189 		return -EIO;
190 	}
191 
192 	ret = vchiq_connect(vchi_ctx->instance);
193 	if (ret) {
194 		dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
195 			ret);
196 
197 		kfree(vchi_ctx->instance);
198 		vchi_ctx->instance = NULL;
199 
200 		return -EIO;
201 	}
202 
203 	return 0;
204 }
205 
bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx * vchi_ctx)206 void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
207 {
208 	/* Close the VCHI connection - it will also free vchi_ctx->instance */
209 	WARN_ON(vchiq_shutdown(vchi_ctx->instance));
210 
211 	vchi_ctx->instance = NULL;
212 }
213 
bcm2835_audio_open(struct bcm2835_alsa_stream * alsa_stream)214 int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
215 {
216 	struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
217 	struct bcm2835_audio_instance *instance;
218 	int err;
219 
220 	/* Allocate memory for this instance */
221 	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
222 	if (!instance)
223 		return -ENOMEM;
224 	mutex_init(&instance->vchi_mutex);
225 	instance->dev = alsa_stream->chip->dev;
226 	instance->alsa_stream = alsa_stream;
227 	alsa_stream->instance = instance;
228 
229 	err = vc_vchi_audio_init(vchi_ctx->instance,
230 				 instance);
231 	if (err < 0)
232 		goto free_instance;
233 
234 	err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
235 					false);
236 	if (err < 0)
237 		goto deinit;
238 
239 	bcm2835_audio_lock(instance);
240 	vchiq_get_peer_version(vchi_ctx->instance, instance->service_handle,
241 			       &instance->peer_version);
242 	bcm2835_audio_unlock(instance);
243 	if (instance->peer_version < 2 || force_bulk)
244 		instance->max_packet = 0; /* bulk transfer */
245 	else
246 		instance->max_packet = 4000;
247 
248 	return 0;
249 
250  deinit:
251 	vc_vchi_audio_deinit(instance);
252  free_instance:
253 	alsa_stream->instance = NULL;
254 	kfree(instance);
255 	return err;
256 }
257 
bcm2835_audio_set_ctls(struct bcm2835_alsa_stream * alsa_stream)258 int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
259 {
260 	struct bcm2835_chip *chip = alsa_stream->chip;
261 	struct vc_audio_msg m = {};
262 
263 	m.type = VC_AUDIO_MSG_TYPE_CONTROL;
264 	m.control.dest = chip->dest;
265 	if (!chip->mute)
266 		m.control.volume = CHIP_MIN_VOLUME;
267 	else
268 		m.control.volume = alsa2chip(chip->volume);
269 
270 	return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
271 }
272 
bcm2835_audio_set_params(struct bcm2835_alsa_stream * alsa_stream,unsigned int channels,unsigned int samplerate,unsigned int bps)273 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
274 			     unsigned int channels, unsigned int samplerate,
275 			     unsigned int bps)
276 {
277 	struct vc_audio_msg m = {
278 		 .type = VC_AUDIO_MSG_TYPE_CONFIG,
279 		 .config.channels = channels,
280 		 .config.samplerate = samplerate,
281 		 .config.bps = bps,
282 	};
283 	int err;
284 
285 	/* resend ctls - alsa_stream may not have been open when first send */
286 	err = bcm2835_audio_set_ctls(alsa_stream);
287 	if (err)
288 		return err;
289 
290 	return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
291 }
292 
bcm2835_audio_start(struct bcm2835_alsa_stream * alsa_stream)293 int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
294 {
295 	return bcm2835_audio_send_simple(alsa_stream->instance,
296 					 VC_AUDIO_MSG_TYPE_START, false);
297 }
298 
bcm2835_audio_stop(struct bcm2835_alsa_stream * alsa_stream)299 int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
300 {
301 	return bcm2835_audio_send_simple(alsa_stream->instance,
302 					 VC_AUDIO_MSG_TYPE_STOP, false);
303 }
304 
305 /* FIXME: this doesn't seem working as expected for "draining" */
bcm2835_audio_drain(struct bcm2835_alsa_stream * alsa_stream)306 int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
307 {
308 	struct vc_audio_msg m = {
309 		.type = VC_AUDIO_MSG_TYPE_STOP,
310 		.stop.draining = 1,
311 	};
312 
313 	return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
314 }
315 
bcm2835_audio_close(struct bcm2835_alsa_stream * alsa_stream)316 int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
317 {
318 	struct bcm2835_audio_instance *instance = alsa_stream->instance;
319 	int err;
320 
321 	err = bcm2835_audio_send_simple(alsa_stream->instance,
322 					VC_AUDIO_MSG_TYPE_CLOSE, true);
323 
324 	/* Stop the audio service */
325 	vc_vchi_audio_deinit(instance);
326 	alsa_stream->instance = NULL;
327 	kfree(instance);
328 
329 	return err;
330 }
331 
bcm2835_audio_write(struct bcm2835_alsa_stream * alsa_stream,unsigned int size,void * src)332 int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
333 			unsigned int size, void *src)
334 {
335 	struct bcm2835_audio_instance *instance = alsa_stream->instance;
336 	struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
337 	struct vchiq_instance *vchiq_instance = vchi_ctx->instance;
338 	struct vc_audio_msg m = {
339 		.type = VC_AUDIO_MSG_TYPE_WRITE,
340 		.write.count = size,
341 		.write.max_packet = instance->max_packet,
342 		.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
343 		.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
344 	};
345 	unsigned int count;
346 	int err, status;
347 
348 	if (!size)
349 		return 0;
350 
351 	bcm2835_audio_lock(instance);
352 	err = bcm2835_audio_send_msg_locked(instance, &m, false);
353 	if (err < 0)
354 		goto unlock;
355 
356 	count = size;
357 	if (!instance->max_packet) {
358 		/* Send the message to the videocore */
359 		status = vchiq_bulk_transmit(vchiq_instance, instance->service_handle, src, count,
360 					     NULL, VCHIQ_BULK_MODE_BLOCKING);
361 	} else {
362 		while (count > 0) {
363 			int bytes = min(instance->max_packet, count);
364 
365 			status = vchiq_queue_kernel_message(vchiq_instance,
366 							    instance->service_handle, src, bytes);
367 			src += bytes;
368 			count -= bytes;
369 		}
370 	}
371 
372 	if (status) {
373 		dev_err(instance->dev,
374 			"failed on %d bytes transfer (status=%d)\n",
375 			size, status);
376 		err = -EIO;
377 	}
378 
379  unlock:
380 	bcm2835_audio_unlock(instance);
381 	return err;
382 }
383