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