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 struct bcm2835_audio_instance { 11 struct device *dev; 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; 16 int result; 17 unsigned int max_packet; 18 short peer_version; 19 }; 20 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"); 24 25 static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance) 26 { 27 mutex_lock(&instance->vchi_mutex); 28 vchi_service_use(instance->vchi_handle); 29 } 30 31 static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance) 32 { 33 vchi_service_release(instance->vchi_handle); 34 mutex_unlock(&instance->vchi_mutex); 35 } 36 37 static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance, 38 struct vc_audio_msg *m, bool wait) 39 { 40 int status; 41 42 if (wait) { 43 instance->result = -1; 44 init_completion(&instance->msg_avail_comp); 45 } 46 47 status = vchi_queue_kernel_message(instance->vchi_handle, 48 m, sizeof(*m)); 49 if (status) { 50 dev_err(instance->dev, 51 "vchi message queue failed: %d, msg=%d\n", 52 status, m->type); 53 return -EIO; 54 } 55 56 if (wait) { 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); 61 return -ETIMEDOUT; 62 } else if (instance->result) { 63 dev_err(instance->dev, 64 "vchi message response error:%d, msg=%d\n", 65 instance->result, m->type); 66 return -EIO; 67 } 68 } 69 70 return 0; 71 } 72 73 static int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance, 74 struct vc_audio_msg *m, bool wait) 75 { 76 int err; 77 78 bcm2835_audio_lock(instance); 79 err = bcm2835_audio_send_msg_locked(instance, m, wait); 80 bcm2835_audio_unlock(instance); 81 return err; 82 } 83 84 static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance, 85 int type, bool wait) 86 { 87 struct vc_audio_msg m = { .type = type }; 88 89 return bcm2835_audio_send_msg(instance, &m, wait); 90 } 91 92 static void audio_vchi_callback(void *param, 93 const enum vchi_callback_reason reason, 94 void *msg_handle) 95 { 96 struct bcm2835_audio_instance *instance = param; 97 struct vc_audio_msg m; 98 int msg_len; 99 int status; 100 101 if (reason != VCHI_CALLBACK_MSG_AVAILABLE) 102 return; 103 104 status = vchi_msg_dequeue(instance->vchi_handle, 105 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE); 106 if (status) 107 return; 108 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"); 116 else 117 bcm2835_playback_fifo(instance->alsa_stream, 118 m.complete.count); 119 } else { 120 dev_err(instance->dev, "unexpected callback type=%d\n", m.type); 121 } 122 } 123 124 static int 125 vc_vchi_audio_init(struct vchi_instance_handle *vchi_instance, 126 struct bcm2835_audio_instance *instance) 127 { 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, 133 }; 134 int status; 135 136 /* Open the VCHI service connections */ 137 status = vchi_service_open(vchi_instance, ¶ms, 138 &instance->vchi_handle); 139 140 if (status) { 141 dev_err(instance->dev, 142 "failed to open VCHI service connection (status=%d)\n", 143 status); 144 return -EPERM; 145 } 146 147 /* Finished with the service for now */ 148 vchi_service_release(instance->vchi_handle); 149 150 return 0; 151 } 152 153 static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance) 154 { 155 int status; 156 157 mutex_lock(&instance->vchi_mutex); 158 vchi_service_use(instance->vchi_handle); 159 160 /* Close all VCHI service connections */ 161 status = vchi_service_close(instance->vchi_handle); 162 if (status) { 163 dev_err(instance->dev, 164 "failed to close VCHI service connection (status=%d)\n", 165 status); 166 } 167 168 mutex_unlock(&instance->vchi_mutex); 169 } 170 171 int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx) 172 { 173 int ret; 174 175 /* Initialize and create a VCHI connection */ 176 ret = vchi_initialise(&vchi_ctx->vchi_instance); 177 if (ret) { 178 dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n", 179 ret); 180 return -EIO; 181 } 182 183 ret = vchi_connect(vchi_ctx->vchi_instance); 184 if (ret) { 185 dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n", 186 ret); 187 188 kfree(vchi_ctx->vchi_instance); 189 vchi_ctx->vchi_instance = NULL; 190 191 return -EIO; 192 } 193 194 return 0; 195 } 196 197 void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx) 198 { 199 /* Close the VCHI connection - it will also free vchi_instance */ 200 WARN_ON(vchi_disconnect(vchi_ctx->vchi_instance)); 201 202 vchi_ctx->vchi_instance = NULL; 203 } 204 205 int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) 206 { 207 struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx; 208 struct bcm2835_audio_instance *instance; 209 int err; 210 211 /* Allocate memory for this instance */ 212 instance = kzalloc(sizeof(*instance), GFP_KERNEL); 213 if (!instance) 214 return -ENOMEM; 215 mutex_init(&instance->vchi_mutex); 216 instance->dev = alsa_stream->chip->dev; 217 instance->alsa_stream = alsa_stream; 218 alsa_stream->instance = instance; 219 220 err = vc_vchi_audio_init(vchi_ctx->vchi_instance, 221 instance); 222 if (err < 0) 223 goto free_instance; 224 225 err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN, 226 false); 227 if (err < 0) 228 goto deinit; 229 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 */ 235 else 236 instance->max_packet = 4000; 237 238 return 0; 239 240 deinit: 241 vc_vchi_audio_deinit(instance); 242 free_instance: 243 alsa_stream->instance = NULL; 244 kfree(instance); 245 return err; 246 } 247 248 int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream) 249 { 250 struct bcm2835_chip *chip = alsa_stream->chip; 251 struct vc_audio_msg m = {}; 252 253 m.type = VC_AUDIO_MSG_TYPE_CONTROL; 254 m.control.dest = chip->dest; 255 if (!chip->mute) 256 m.control.volume = CHIP_MIN_VOLUME; 257 else 258 m.control.volume = alsa2chip(chip->volume); 259 260 return bcm2835_audio_send_msg(alsa_stream->instance, &m, true); 261 } 262 263 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream, 264 unsigned int channels, unsigned int samplerate, 265 unsigned int bps) 266 { 267 struct vc_audio_msg m = { 268 .type = VC_AUDIO_MSG_TYPE_CONFIG, 269 .config.channels = channels, 270 .config.samplerate = samplerate, 271 .config.bps = bps, 272 }; 273 int err; 274 275 /* resend ctls - alsa_stream may not have been open when first send */ 276 err = bcm2835_audio_set_ctls(alsa_stream); 277 if (err) 278 return err; 279 280 return bcm2835_audio_send_msg(alsa_stream->instance, &m, true); 281 } 282 283 int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream) 284 { 285 return bcm2835_audio_send_simple(alsa_stream->instance, 286 VC_AUDIO_MSG_TYPE_START, false); 287 } 288 289 int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream) 290 { 291 return bcm2835_audio_send_simple(alsa_stream->instance, 292 VC_AUDIO_MSG_TYPE_STOP, false); 293 } 294 295 /* FIXME: this doesn't seem working as expected for "draining" */ 296 int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream) 297 { 298 struct vc_audio_msg m = { 299 .type = VC_AUDIO_MSG_TYPE_STOP, 300 .stop.draining = 1, 301 }; 302 303 return bcm2835_audio_send_msg(alsa_stream->instance, &m, false); 304 } 305 306 int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream) 307 { 308 struct bcm2835_audio_instance *instance = alsa_stream->instance; 309 int err; 310 311 err = bcm2835_audio_send_simple(alsa_stream->instance, 312 VC_AUDIO_MSG_TYPE_CLOSE, true); 313 314 /* Stop the audio service */ 315 vc_vchi_audio_deinit(instance); 316 alsa_stream->instance = NULL; 317 kfree(instance); 318 319 return err; 320 } 321 322 int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream, 323 unsigned int size, void *src) 324 { 325 struct bcm2835_audio_instance *instance = alsa_stream->instance; 326 struct vc_audio_msg m = { 327 .type = VC_AUDIO_MSG_TYPE_WRITE, 328 .write.count = size, 329 .write.max_packet = instance->max_packet, 330 .write.cookie1 = VC_AUDIO_WRITE_COOKIE1, 331 .write.cookie2 = VC_AUDIO_WRITE_COOKIE2, 332 }; 333 unsigned int count; 334 int err, status; 335 336 if (!size) 337 return 0; 338 339 bcm2835_audio_lock(instance); 340 err = bcm2835_audio_send_msg_locked(instance, &m, false); 341 if (err < 0) 342 goto unlock; 343 344 count = size; 345 if (!instance->max_packet) { 346 /* Send the message to the videocore */ 347 status = vchi_bulk_queue_transmit(instance->vchi_handle, 348 src, count, 349 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, 350 NULL); 351 } else { 352 while (count > 0) { 353 int bytes = min(instance->max_packet, count); 354 355 status = vchi_queue_kernel_message(instance->vchi_handle, 356 src, bytes); 357 src += bytes; 358 count -= bytes; 359 } 360 } 361 362 if (status) { 363 dev_err(instance->dev, 364 "failed on %d bytes transfer (status=%d)\n", 365 size, status); 366 err = -EIO; 367 } 368 369 unlock: 370 bcm2835_audio_unlock(instance); 371 return err; 372 } 373