1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * sst_stream.c - Intel SST Driver for audio engine 4 * 5 * Copyright (C) 2008-14 Intel Corp 6 * Authors: Vinod Koul <vinod.koul@intel.com> 7 * Harsha Priya <priya.harsha@intel.com> 8 * Dharageswari R <dharageswari.r@intel.com> 9 * KP Jeeja <jeeja.kp@intel.com> 10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 * 12 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13 */ 14 #include <linux/pci.h> 15 #include <linux/firmware.h> 16 #include <linux/sched.h> 17 #include <linux/delay.h> 18 #include <linux/pm_runtime.h> 19 #include <sound/core.h> 20 #include <sound/pcm.h> 21 #include <sound/soc.h> 22 #include <sound/compress_driver.h> 23 #include <asm/platform_sst_audio.h> 24 #include "../sst-mfld-platform.h" 25 #include "sst.h" 26 #include "../../common/sst-dsp.h" 27 28 int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params) 29 { 30 struct snd_pcm_params *pcm_params; 31 struct snd_sst_params *str_params; 32 struct snd_sst_tstamp fw_tstamp; 33 struct stream_info *str_info; 34 int i, num_ch, str_id; 35 36 dev_dbg(sst_drv_ctx->dev, "Enter\n"); 37 38 str_params = (struct snd_sst_params *)params; 39 str_id = str_params->stream_id; 40 str_info = get_stream_info(sst_drv_ctx, str_id); 41 if (!str_info) 42 return -EINVAL; 43 44 memset(&str_info->alloc_param, 0, sizeof(str_info->alloc_param)); 45 str_info->alloc_param.operation = str_params->ops; 46 str_info->alloc_param.codec_type = str_params->codec; 47 str_info->alloc_param.sg_count = str_params->aparams.sg_count; 48 str_info->alloc_param.ring_buf_info[0].addr = 49 str_params->aparams.ring_buf_info[0].addr; 50 str_info->alloc_param.ring_buf_info[0].size = 51 str_params->aparams.ring_buf_info[0].size; 52 str_info->alloc_param.frag_size = str_params->aparams.frag_size; 53 54 memcpy(&str_info->alloc_param.codec_params, &str_params->sparams, 55 sizeof(struct snd_sst_stream_params)); 56 57 /* 58 * fill channel map params for multichannel support. 59 * Ideally channel map should be received from upper layers 60 * for multichannel support. 61 * Currently hardcoding as per FW reqm. 62 */ 63 num_ch = sst_get_num_channel(str_params); 64 pcm_params = &str_info->alloc_param.codec_params.uc.pcm_params; 65 for (i = 0; i < 8; i++) { 66 if (i < num_ch) 67 pcm_params->channel_map[i] = i; 68 else 69 pcm_params->channel_map[i] = 0xff; 70 } 71 72 sst_drv_ctx->streams[str_id].status = STREAM_INIT; 73 sst_drv_ctx->streams[str_id].prev = STREAM_UN_INIT; 74 sst_drv_ctx->streams[str_id].pipe_id = str_params->device_type; 75 sst_drv_ctx->streams[str_id].task_id = str_params->task; 76 sst_drv_ctx->streams[str_id].num_ch = num_ch; 77 78 if (sst_drv_ctx->info.lpe_viewpt_rqd) 79 str_info->alloc_param.ts = sst_drv_ctx->info.mailbox_start + 80 sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp)); 81 else 82 str_info->alloc_param.ts = sst_drv_ctx->mailbox_add + 83 sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp)); 84 85 dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n", 86 str_info->alloc_param.ts); 87 dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n", 88 str_info->pipe_id, str_info->task_id); 89 90 return sst_realloc_stream(sst_drv_ctx, str_id); 91 } 92 93 /** 94 * sst_realloc_stream - Send msg for (re-)allocating a stream using the 95 * @sst_drv_ctx intel_sst_drv context pointer 96 * @str_id: stream ID 97 * 98 * Send a msg for (re-)allocating a stream using the parameters previously 99 * passed to sst_alloc_stream_mrfld() for the same stream ID. 100 * Return: 0 or negative errno value. 101 */ 102 int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) 103 { 104 struct snd_sst_alloc_response *response; 105 struct stream_info *str_info; 106 void *data = NULL; 107 int ret; 108 109 str_info = get_stream_info(sst_drv_ctx, str_id); 110 if (!str_info) 111 return -EINVAL; 112 113 dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n", 114 str_id, str_info->pipe_id); 115 116 ret = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD, 117 IPC_IA_ALLOC_STREAM_MRFLD, str_info->pipe_id, 118 sizeof(str_info->alloc_param), &str_info->alloc_param, 119 &data, true, true, false, true); 120 121 if (ret < 0) { 122 dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret); 123 /* alloc failed, so reset the state to uninit */ 124 str_info->status = STREAM_UN_INIT; 125 str_id = ret; 126 } else if (data) { 127 response = (struct snd_sst_alloc_response *)data; 128 ret = response->str_type.result; 129 if (!ret) 130 goto out; 131 dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret); 132 if (ret == SST_ERR_STREAM_IN_USE) { 133 dev_err(sst_drv_ctx->dev, 134 "FW not in clean state, send free for:%d\n", str_id); 135 sst_free_stream(sst_drv_ctx, str_id); 136 } 137 str_id = -ret; 138 } 139 out: 140 kfree(data); 141 return str_id; 142 } 143 144 /** 145 * sst_start_stream - Send msg for a starting stream 146 * @str_id: stream ID 147 * 148 * This function is called by any function which wants to start 149 * a stream. 150 */ 151 int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) 152 { 153 int retval = 0; 154 struct stream_info *str_info; 155 u16 data = 0; 156 157 dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id); 158 str_info = get_stream_info(sst_drv_ctx, str_id); 159 if (!str_info) 160 return -EINVAL; 161 if (str_info->status != STREAM_RUNNING) 162 return -EBADRQC; 163 164 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, 165 IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id, 166 sizeof(u16), &data, NULL, true, true, true, false); 167 168 return retval; 169 } 170 171 int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, 172 struct snd_sst_bytes_v2 *bytes) 173 { struct ipc_post *msg = NULL; 174 u32 length; 175 int pvt_id, ret = 0; 176 struct sst_block *block = NULL; 177 178 dev_dbg(sst_drv_ctx->dev, 179 "type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n", 180 bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id, 181 bytes->pipe_id, bytes->len); 182 183 if (sst_create_ipc_msg(&msg, true)) 184 return -ENOMEM; 185 186 pvt_id = sst_assign_pvt_id(sst_drv_ctx); 187 sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg, 188 bytes->task_id, 1, pvt_id); 189 msg->mrfld_header.p.header_high.part.res_rqd = bytes->block; 190 length = bytes->len; 191 msg->mrfld_header.p.header_low_payload = length; 192 dev_dbg(sst_drv_ctx->dev, "length is %d\n", length); 193 memcpy(msg->mailbox_data, &bytes->bytes, bytes->len); 194 if (bytes->block) { 195 block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id); 196 if (block == NULL) { 197 kfree(msg); 198 ret = -ENOMEM; 199 goto out; 200 } 201 } 202 203 sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg); 204 dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d", 205 msg->mrfld_header.p.header_low_payload); 206 207 if (bytes->block) { 208 ret = sst_wait_timeout(sst_drv_ctx, block); 209 if (ret) { 210 dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret); 211 sst_free_block(sst_drv_ctx, block); 212 goto out; 213 } 214 } 215 if (bytes->type == SND_SST_BYTES_GET) { 216 /* 217 * copy the reply and send back 218 * we need to update only sz and payload 219 */ 220 if (bytes->block) { 221 unsigned char *r = block->data; 222 223 dev_dbg(sst_drv_ctx->dev, "read back %d bytes", 224 bytes->len); 225 memcpy(bytes->bytes, r, bytes->len); 226 } 227 } 228 if (bytes->block) 229 sst_free_block(sst_drv_ctx, block); 230 out: 231 test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id); 232 return ret; 233 } 234 235 /** 236 * sst_pause_stream - Send msg for a pausing stream 237 * @str_id: stream ID 238 * 239 * This function is called by any function which wants to pause 240 * an already running stream. 241 */ 242 int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) 243 { 244 int retval = 0; 245 struct stream_info *str_info; 246 247 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id); 248 str_info = get_stream_info(sst_drv_ctx, str_id); 249 if (!str_info) 250 return -EINVAL; 251 if (str_info->status == STREAM_PAUSED) 252 return 0; 253 if (str_info->status == STREAM_RUNNING || 254 str_info->status == STREAM_INIT) { 255 if (str_info->prev == STREAM_UN_INIT) 256 return -EBADRQC; 257 258 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD, 259 IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id, 260 0, NULL, NULL, true, true, false, true); 261 262 if (retval == 0) { 263 str_info->prev = str_info->status; 264 str_info->status = STREAM_PAUSED; 265 } else if (retval == -SST_ERR_INVALID_STREAM_ID) { 266 retval = -EINVAL; 267 mutex_lock(&sst_drv_ctx->sst_lock); 268 sst_clean_stream(str_info); 269 mutex_unlock(&sst_drv_ctx->sst_lock); 270 } 271 } else { 272 retval = -EBADRQC; 273 dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n"); 274 } 275 276 return retval; 277 } 278 279 /** 280 * sst_resume_stream - Send msg for resuming stream 281 * @str_id: stream ID 282 * 283 * This function is called by any function which wants to resume 284 * an already paused stream. 285 */ 286 int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) 287 { 288 int retval = 0; 289 struct stream_info *str_info; 290 291 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id); 292 str_info = get_stream_info(sst_drv_ctx, str_id); 293 if (!str_info) 294 return -EINVAL; 295 if (str_info->status == STREAM_RUNNING) 296 return 0; 297 298 if (str_info->resume_status == STREAM_PAUSED && 299 str_info->resume_prev == STREAM_RUNNING) { 300 /* 301 * Stream was running before suspend and re-created on resume, 302 * start it to get back to running state. 303 */ 304 dev_dbg(sst_drv_ctx->dev, "restart recreated stream after resume\n"); 305 str_info->status = STREAM_RUNNING; 306 str_info->prev = STREAM_PAUSED; 307 retval = sst_start_stream(sst_drv_ctx, str_id); 308 str_info->resume_status = STREAM_UN_INIT; 309 } else if (str_info->resume_status == STREAM_PAUSED && 310 str_info->resume_prev == STREAM_INIT) { 311 /* 312 * Stream was idle before suspend and re-created on resume, 313 * keep it as is. 314 */ 315 dev_dbg(sst_drv_ctx->dev, "leaving recreated stream idle after resume\n"); 316 str_info->status = STREAM_INIT; 317 str_info->prev = STREAM_PAUSED; 318 str_info->resume_status = STREAM_UN_INIT; 319 } else if (str_info->status == STREAM_PAUSED) { 320 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, 321 IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD, 322 str_info->pipe_id, 0, NULL, NULL, 323 true, true, false, true); 324 325 if (!retval) { 326 if (str_info->prev == STREAM_RUNNING) 327 str_info->status = STREAM_RUNNING; 328 else 329 str_info->status = STREAM_INIT; 330 str_info->prev = STREAM_PAUSED; 331 } else if (retval == -SST_ERR_INVALID_STREAM_ID) { 332 retval = -EINVAL; 333 mutex_lock(&sst_drv_ctx->sst_lock); 334 sst_clean_stream(str_info); 335 mutex_unlock(&sst_drv_ctx->sst_lock); 336 } 337 } else { 338 retval = -EBADRQC; 339 dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n"); 340 } 341 342 return retval; 343 } 344 345 346 /** 347 * sst_drop_stream - Send msg for stopping stream 348 * @str_id: stream ID 349 * 350 * This function is called by any function which wants to stop 351 * a stream. 352 */ 353 int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) 354 { 355 int retval = 0; 356 struct stream_info *str_info; 357 358 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id); 359 str_info = get_stream_info(sst_drv_ctx, str_id); 360 if (!str_info) 361 return -EINVAL; 362 363 if (str_info->status != STREAM_UN_INIT) { 364 str_info->prev = STREAM_UN_INIT; 365 str_info->status = STREAM_INIT; 366 str_info->cumm_bytes = 0; 367 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, 368 IPC_CMD, IPC_IA_DROP_STREAM_MRFLD, 369 str_info->pipe_id, 0, NULL, NULL, 370 true, true, true, false); 371 } else { 372 retval = -EBADRQC; 373 dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n", 374 str_info->status); 375 } 376 return retval; 377 } 378 379 /** 380 * sst_drain_stream - Send msg for draining stream 381 * @str_id: stream ID 382 * 383 * This function is called by any function which wants to drain 384 * a stream. 385 */ 386 int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, 387 int str_id, bool partial_drain) 388 { 389 int retval = 0; 390 struct stream_info *str_info; 391 392 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id); 393 str_info = get_stream_info(sst_drv_ctx, str_id); 394 if (!str_info) 395 return -EINVAL; 396 if (str_info->status != STREAM_RUNNING && 397 str_info->status != STREAM_INIT && 398 str_info->status != STREAM_PAUSED) { 399 dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n", 400 str_info->status); 401 return -EBADRQC; 402 } 403 404 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD, 405 IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id, 406 sizeof(u8), &partial_drain, NULL, true, true, false, false); 407 /* 408 * with new non blocked drain implementation in core we dont need to 409 * wait for respsonse, and need to only invoke callback for drain 410 * complete 411 */ 412 413 return retval; 414 } 415 416 /** 417 * sst_free_stream - Frees a stream 418 * @str_id: stream ID 419 * 420 * This function is called by any function which wants to free 421 * a stream. 422 */ 423 int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) 424 { 425 int retval = 0; 426 struct stream_info *str_info; 427 428 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id); 429 430 mutex_lock(&sst_drv_ctx->sst_lock); 431 if (sst_drv_ctx->sst_state == SST_RESET) { 432 mutex_unlock(&sst_drv_ctx->sst_lock); 433 return -ENODEV; 434 } 435 mutex_unlock(&sst_drv_ctx->sst_lock); 436 str_info = get_stream_info(sst_drv_ctx, str_id); 437 if (!str_info) 438 return -EINVAL; 439 440 mutex_lock(&str_info->lock); 441 if (str_info->status != STREAM_UN_INIT) { 442 str_info->prev = str_info->status; 443 str_info->status = STREAM_UN_INIT; 444 mutex_unlock(&str_info->lock); 445 446 dev_dbg(sst_drv_ctx->dev, "Free for str %d pipe %#x\n", 447 str_id, str_info->pipe_id); 448 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD, 449 IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0, 450 NULL, NULL, true, true, false, true); 451 452 dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n", 453 retval); 454 mutex_lock(&sst_drv_ctx->sst_lock); 455 sst_clean_stream(str_info); 456 mutex_unlock(&sst_drv_ctx->sst_lock); 457 dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n"); 458 } else { 459 mutex_unlock(&str_info->lock); 460 retval = -EBADRQC; 461 dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n"); 462 } 463 464 return retval; 465 } 466