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