1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation. All rights reserved. */
4 #include <linux/slab.h>
5 #include <linux/module.h>
6 #include <linux/completion.h>
8 #include "vc_vchi_audioserv_defs.h"
10 struct bcm2835_audio_instance {
12 struct vchi_service_handle *vchi_handle;
13 struct completion msg_avail_comp;
14 struct mutex vchi_mutex;
15 struct bcm2835_alsa_stream *alsa_stream;
17 unsigned int max_packet;
21 static bool force_bulk;
22 module_param(force_bulk, bool, 0444);
23 MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
25 static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
27 mutex_lock(&instance->vchi_mutex);
28 vchi_service_use(instance->vchi_handle);
31 static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
33 vchi_service_release(instance->vchi_handle);
34 mutex_unlock(&instance->vchi_mutex);
37 static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
38 struct vc_audio_msg *m, bool wait)
43 instance->result = -1;
44 init_completion(&instance->msg_avail_comp);
47 status = vchi_queue_kernel_message(instance->vchi_handle,
50 dev_err(instance->dev,
51 "vchi message queue failed: %d, msg=%d\n",
57 if (!wait_for_completion_timeout(&instance->msg_avail_comp,
58 msecs_to_jiffies(10 * 1000))) {
59 dev_err(instance->dev,
60 "vchi message timeout, msg=%d\n", m->type);
62 } else if (instance->result) {
63 dev_err(instance->dev,
64 "vchi message response error:%d, msg=%d\n",
65 instance->result, m->type);
73 static int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
74 struct vc_audio_msg *m, bool wait)
78 bcm2835_audio_lock(instance);
79 err = bcm2835_audio_send_msg_locked(instance, m, wait);
80 bcm2835_audio_unlock(instance);
84 static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
87 struct vc_audio_msg m = { .type = type };
89 return bcm2835_audio_send_msg(instance, &m, wait);
92 static void audio_vchi_callback(void *param,
93 const enum vchi_callback_reason reason,
96 struct bcm2835_audio_instance *instance = param;
97 struct vc_audio_msg m;
101 if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
104 status = vchi_msg_dequeue(instance->vchi_handle,
105 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
109 if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
110 instance->result = m.result.success;
111 complete(&instance->msg_avail_comp);
112 } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
113 if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
114 m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
115 dev_err(instance->dev, "invalid cookie\n");
117 bcm2835_playback_fifo(instance->alsa_stream,
120 dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
125 vc_vchi_audio_init(struct vchi_instance_handle *vchi_instance,
126 struct bcm2835_audio_instance *instance)
128 struct service_creation params = {
129 .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
130 .service_id = VC_AUDIO_SERVER_NAME,
131 .callback = audio_vchi_callback,
132 .callback_param = instance,
136 /* Open the VCHI service connections */
137 status = vchi_service_open(vchi_instance, ¶ms,
138 &instance->vchi_handle);
141 dev_err(instance->dev,
142 "failed to open VCHI service connection (status=%d)\n",
147 /* Finished with the service for now */
148 vchi_service_release(instance->vchi_handle);
153 static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
157 mutex_lock(&instance->vchi_mutex);
158 vchi_service_use(instance->vchi_handle);
160 /* Close all VCHI service connections */
161 status = vchi_service_close(instance->vchi_handle);
163 dev_err(instance->dev,
164 "failed to close VCHI service connection (status=%d)\n",
168 mutex_unlock(&instance->vchi_mutex);
171 int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
175 /* Initialize and create a VCHI connection */
176 ret = vchi_initialise(&vchi_ctx->vchi_instance);
178 dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
183 ret = vchi_connect(vchi_ctx->vchi_instance);
185 dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
188 kfree(vchi_ctx->vchi_instance);
189 vchi_ctx->vchi_instance = NULL;
197 void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
199 /* Close the VCHI connection - it will also free vchi_instance */
200 WARN_ON(vchi_disconnect(vchi_ctx->vchi_instance));
202 vchi_ctx->vchi_instance = NULL;
205 int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
207 struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
208 struct bcm2835_audio_instance *instance;
211 /* Allocate memory for this instance */
212 instance = kzalloc(sizeof(*instance), GFP_KERNEL);
215 mutex_init(&instance->vchi_mutex);
216 instance->dev = alsa_stream->chip->dev;
217 instance->alsa_stream = alsa_stream;
218 alsa_stream->instance = instance;
220 err = vc_vchi_audio_init(vchi_ctx->vchi_instance,
225 err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
230 bcm2835_audio_lock(instance);
231 vchi_get_peer_version(instance->vchi_handle, &instance->peer_version);
232 bcm2835_audio_unlock(instance);
233 if (instance->peer_version < 2 || force_bulk)
234 instance->max_packet = 0; /* bulk transfer */
236 instance->max_packet = 4000;
241 vc_vchi_audio_deinit(instance);
243 alsa_stream->instance = NULL;
248 int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
250 struct bcm2835_chip *chip = alsa_stream->chip;
251 struct vc_audio_msg m = {};
253 m.type = VC_AUDIO_MSG_TYPE_CONTROL;
254 m.control.dest = chip->dest;
256 m.control.volume = CHIP_MIN_VOLUME;
258 m.control.volume = alsa2chip(chip->volume);
260 return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
263 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
264 unsigned int channels, unsigned int samplerate,
267 struct vc_audio_msg m = {
268 .type = VC_AUDIO_MSG_TYPE_CONFIG,
269 .config.channels = channels,
270 .config.samplerate = samplerate,
275 /* resend ctls - alsa_stream may not have been open when first send */
276 err = bcm2835_audio_set_ctls(alsa_stream);
280 return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
283 int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
285 return bcm2835_audio_send_simple(alsa_stream->instance,
286 VC_AUDIO_MSG_TYPE_START, false);
289 int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
291 return bcm2835_audio_send_simple(alsa_stream->instance,
292 VC_AUDIO_MSG_TYPE_STOP, false);
295 /* FIXME: this doesn't seem working as expected for "draining" */
296 int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
298 struct vc_audio_msg m = {
299 .type = VC_AUDIO_MSG_TYPE_STOP,
303 return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
306 int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
308 struct bcm2835_audio_instance *instance = alsa_stream->instance;
311 err = bcm2835_audio_send_simple(alsa_stream->instance,
312 VC_AUDIO_MSG_TYPE_CLOSE, true);
314 /* Stop the audio service */
315 vc_vchi_audio_deinit(instance);
316 alsa_stream->instance = NULL;
322 int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
323 unsigned int size, void *src)
325 struct bcm2835_audio_instance *instance = alsa_stream->instance;
326 struct vc_audio_msg m = {
327 .type = VC_AUDIO_MSG_TYPE_WRITE,
329 .write.max_packet = instance->max_packet,
330 .write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
331 .write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
339 bcm2835_audio_lock(instance);
340 err = bcm2835_audio_send_msg_locked(instance, &m, false);
345 if (!instance->max_packet) {
346 /* Send the message to the videocore */
347 status = vchi_bulk_queue_transmit(instance->vchi_handle,
349 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
353 int bytes = min(instance->max_packet, count);
355 status = vchi_queue_kernel_message(instance->vchi_handle,
363 dev_err(instance->dev,
364 "failed on %d bytes transfer (status=%d)\n",
370 bcm2835_audio_unlock(instance);