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 36int 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_info(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 } 131out: 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*/ 143int 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 163int 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); 222out: 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 */ 234int 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 */ 278int 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 */ 323int 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*/ 356int 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 */ 393int 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 struct intel_sst_ops *ops; 398 399 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id); 400 401 mutex_lock(&sst_drv_ctx->sst_lock); 402 if (sst_drv_ctx->sst_state == SST_RESET) { 403 mutex_unlock(&sst_drv_ctx->sst_lock); 404 return -ENODEV; 405 } 406 mutex_unlock(&sst_drv_ctx->sst_lock); 407 str_info = get_stream_info(sst_drv_ctx, str_id); 408 if (!str_info) 409 return -EINVAL; 410 ops = sst_drv_ctx->ops; 411 412 mutex_lock(&str_info->lock); 413 if (str_info->status != STREAM_UN_INIT) { 414 str_info->prev = str_info->status; 415 str_info->status = STREAM_UN_INIT; 416 mutex_unlock(&str_info->lock); 417 418 dev_info(sst_drv_ctx->dev, "Free for str %d pipe %#x\n", 419 str_id, str_info->pipe_id); 420 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD, 421 IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0, 422 NULL, NULL, true, true, false, true); 423 424 dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n", 425 retval); 426 mutex_lock(&sst_drv_ctx->sst_lock); 427 sst_clean_stream(str_info); 428 mutex_unlock(&sst_drv_ctx->sst_lock); 429 dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n"); 430 } else { 431 mutex_unlock(&str_info->lock); 432 retval = -EBADRQC; 433 dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n"); 434 } 435 436 return retval; 437} 438