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 VCHI_SERVICE_HANDLE_T 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 VCHI_CALLBACK_REASON_T 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 (m.type == VC_AUDIO_MSG_TYPE_RESULT) { 107 instance->result = m.result.success; 108 complete(&instance->msg_avail_comp); 109 } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { 110 if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 || 111 m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2) 112 dev_err(instance->dev, "invalid cookie\n"); 113 else 114 bcm2835_playback_fifo(instance->alsa_stream, 115 m.complete.count); 116 } else { 117 dev_err(instance->dev, "unexpected callback type=%d\n", m.type); 118 } 119 } 120 121 static int 122 vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance, 123 struct bcm2835_audio_instance *instance) 124 { 125 struct service_creation params = { 126 .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER), 127 .service_id = VC_AUDIO_SERVER_NAME, 128 .callback = audio_vchi_callback, 129 .callback_param = instance, 130 }; 131 int status; 132 133 /* Open the VCHI service connections */ 134 status = vchi_service_open(vchi_instance, ¶ms, 135 &instance->vchi_handle); 136 137 if (status) { 138 dev_err(instance->dev, 139 "failed to open VCHI service connection (status=%d)\n", 140 status); 141 return -EPERM; 142 } 143 144 /* Finished with the service for now */ 145 vchi_service_release(instance->vchi_handle); 146 147 return 0; 148 } 149 150 static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance) 151 { 152 int status; 153 154 mutex_lock(&instance->vchi_mutex); 155 vchi_service_use(instance->vchi_handle); 156 157 /* Close all VCHI service connections */ 158 status = vchi_service_close(instance->vchi_handle); 159 if (status) { 160 dev_err(instance->dev, 161 "failed to close VCHI service connection (status=%d)\n", 162 status); 163 } 164 165 mutex_unlock(&instance->vchi_mutex); 166 } 167 168 int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx) 169 { 170 int ret; 171 172 /* Initialize and create a VCHI connection */ 173 ret = vchi_initialise(&vchi_ctx->vchi_instance); 174 if (ret) { 175 dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n", 176 ret); 177 return -EIO; 178 } 179 180 ret = vchi_connect(vchi_ctx->vchi_instance); 181 if (ret) { 182 dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n", 183 ret); 184 185 kfree(vchi_ctx->vchi_instance); 186 vchi_ctx->vchi_instance = NULL; 187 188 return -EIO; 189 } 190 191 return 0; 192 } 193 194 void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx) 195 { 196 /* Close the VCHI connection - it will also free vchi_instance */ 197 WARN_ON(vchi_disconnect(vchi_ctx->vchi_instance)); 198 199 vchi_ctx->vchi_instance = NULL; 200 } 201 202 int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) 203 { 204 struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx; 205 struct bcm2835_audio_instance *instance; 206 int err; 207 208 /* Allocate memory for this instance */ 209 instance = kzalloc(sizeof(*instance), GFP_KERNEL); 210 if (!instance) 211 return -ENOMEM; 212 mutex_init(&instance->vchi_mutex); 213 instance->dev = alsa_stream->chip->dev; 214 instance->alsa_stream = alsa_stream; 215 alsa_stream->instance = instance; 216 217 err = vc_vchi_audio_init(vchi_ctx->vchi_instance, 218 instance); 219 if (err < 0) 220 goto free_instance; 221 222 err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN, 223 false); 224 if (err < 0) 225 goto deinit; 226 227 bcm2835_audio_lock(instance); 228 vchi_get_peer_version(instance->vchi_handle, &instance->peer_version); 229 bcm2835_audio_unlock(instance); 230 if (instance->peer_version < 2 || force_bulk) 231 instance->max_packet = 0; /* bulk transfer */ 232 else 233 instance->max_packet = 4000; 234 235 return 0; 236 237 deinit: 238 vc_vchi_audio_deinit(instance); 239 free_instance: 240 alsa_stream->instance = NULL; 241 kfree(instance); 242 return err; 243 } 244 245 int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream) 246 { 247 struct bcm2835_chip *chip = alsa_stream->chip; 248 struct vc_audio_msg m = {}; 249 250 m.type = VC_AUDIO_MSG_TYPE_CONTROL; 251 m.control.dest = chip->dest; 252 if (!chip->mute) 253 m.control.volume = CHIP_MIN_VOLUME; 254 else 255 m.control.volume = alsa2chip(chip->volume); 256 257 return bcm2835_audio_send_msg(alsa_stream->instance, &m, true); 258 } 259 260 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream, 261 unsigned int channels, unsigned int samplerate, 262 unsigned int bps) 263 { 264 struct vc_audio_msg m = { 265 .type = VC_AUDIO_MSG_TYPE_CONFIG, 266 .config.channels = channels, 267 .config.samplerate = samplerate, 268 .config.bps = bps, 269 }; 270 int err; 271 272 /* resend ctls - alsa_stream may not have been open when first send */ 273 err = bcm2835_audio_set_ctls(alsa_stream); 274 if (err) 275 return err; 276 277 return bcm2835_audio_send_msg(alsa_stream->instance, &m, true); 278 } 279 280 int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream) 281 { 282 return bcm2835_audio_send_simple(alsa_stream->instance, 283 VC_AUDIO_MSG_TYPE_START, false); 284 } 285 286 int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream) 287 { 288 return bcm2835_audio_send_simple(alsa_stream->instance, 289 VC_AUDIO_MSG_TYPE_STOP, false); 290 } 291 292 int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream) 293 { 294 struct vc_audio_msg m = { 295 .type = VC_AUDIO_MSG_TYPE_STOP, 296 .stop.draining = 1, 297 }; 298 299 return bcm2835_audio_send_msg(alsa_stream->instance, &m, false); 300 } 301 302 int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream) 303 { 304 struct bcm2835_audio_instance *instance = alsa_stream->instance; 305 int err; 306 307 err = bcm2835_audio_send_simple(alsa_stream->instance, 308 VC_AUDIO_MSG_TYPE_CLOSE, true); 309 310 /* Stop the audio service */ 311 vc_vchi_audio_deinit(instance); 312 alsa_stream->instance = NULL; 313 kfree(instance); 314 315 return err; 316 } 317 318 int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream, 319 unsigned int size, void *src) 320 { 321 struct bcm2835_audio_instance *instance = alsa_stream->instance; 322 struct vc_audio_msg m = { 323 .type = VC_AUDIO_MSG_TYPE_WRITE, 324 .write.count = size, 325 .write.max_packet = instance->max_packet, 326 .write.cookie1 = VC_AUDIO_WRITE_COOKIE1, 327 .write.cookie2 = VC_AUDIO_WRITE_COOKIE2, 328 }; 329 unsigned int count; 330 int err, status; 331 332 if (!size) 333 return 0; 334 335 bcm2835_audio_lock(instance); 336 err = bcm2835_audio_send_msg_locked(instance, &m, false); 337 if (err < 0) 338 goto unlock; 339 340 count = size; 341 if (!instance->max_packet) { 342 /* Send the message to the videocore */ 343 status = vchi_bulk_queue_transmit(instance->vchi_handle, 344 src, count, 345 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, 346 NULL); 347 } else { 348 while (count > 0) { 349 int bytes = min(instance->max_packet, count); 350 351 status = vchi_queue_kernel_message(instance->vchi_handle, 352 src, bytes); 353 src += bytes; 354 count -= bytes; 355 } 356 } 357 358 if (status) { 359 dev_err(instance->dev, 360 "failed on %d bytes transfer (status=%d)\n", 361 size, status); 362 err = -EIO; 363 } 364 365 unlock: 366 bcm2835_audio_unlock(instance); 367 return err; 368 } 369