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