0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/pci.h>
0015 #include <linux/firmware.h>
0016 #include <linux/sched.h>
0017 #include <linux/delay.h>
0018 #include <linux/pm_runtime.h>
0019 #include <sound/core.h>
0020 #include <sound/pcm.h>
0021 #include <sound/soc.h>
0022 #include <sound/compress_driver.h>
0023 #include <asm/platform_sst_audio.h>
0024 #include "../sst-mfld-platform.h"
0025 #include "sst.h"
0026
0027 int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
0028 {
0029 struct snd_pcm_params *pcm_params;
0030 struct snd_sst_params *str_params;
0031 struct snd_sst_tstamp fw_tstamp;
0032 struct stream_info *str_info;
0033 int i, num_ch, str_id;
0034
0035 dev_dbg(sst_drv_ctx->dev, "Enter\n");
0036
0037 str_params = (struct snd_sst_params *)params;
0038 str_id = str_params->stream_id;
0039 str_info = get_stream_info(sst_drv_ctx, str_id);
0040 if (!str_info)
0041 return -EINVAL;
0042
0043 memset(&str_info->alloc_param, 0, sizeof(str_info->alloc_param));
0044 str_info->alloc_param.operation = str_params->ops;
0045 str_info->alloc_param.codec_type = str_params->codec;
0046 str_info->alloc_param.sg_count = str_params->aparams.sg_count;
0047 str_info->alloc_param.ring_buf_info[0].addr =
0048 str_params->aparams.ring_buf_info[0].addr;
0049 str_info->alloc_param.ring_buf_info[0].size =
0050 str_params->aparams.ring_buf_info[0].size;
0051 str_info->alloc_param.frag_size = str_params->aparams.frag_size;
0052
0053 memcpy(&str_info->alloc_param.codec_params, &str_params->sparams,
0054 sizeof(struct snd_sst_stream_params));
0055
0056
0057
0058
0059
0060
0061
0062 num_ch = sst_get_num_channel(str_params);
0063 pcm_params = &str_info->alloc_param.codec_params.uc.pcm_params;
0064 for (i = 0; i < 8; i++) {
0065 if (i < num_ch)
0066 pcm_params->channel_map[i] = i;
0067 else
0068 pcm_params->channel_map[i] = 0xff;
0069 }
0070
0071 sst_drv_ctx->streams[str_id].status = STREAM_INIT;
0072 sst_drv_ctx->streams[str_id].prev = STREAM_UN_INIT;
0073 sst_drv_ctx->streams[str_id].pipe_id = str_params->device_type;
0074 sst_drv_ctx->streams[str_id].task_id = str_params->task;
0075 sst_drv_ctx->streams[str_id].num_ch = num_ch;
0076
0077 if (sst_drv_ctx->info.lpe_viewpt_rqd)
0078 str_info->alloc_param.ts = sst_drv_ctx->info.mailbox_start +
0079 sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
0080 else
0081 str_info->alloc_param.ts = sst_drv_ctx->mailbox_add +
0082 sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
0083
0084 dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
0085 str_info->alloc_param.ts);
0086 dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
0087 str_info->pipe_id, str_info->task_id);
0088
0089 return sst_realloc_stream(sst_drv_ctx, str_id);
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
0102 {
0103 struct snd_sst_alloc_response *response;
0104 struct stream_info *str_info;
0105 void *data = NULL;
0106 int ret;
0107
0108 str_info = get_stream_info(sst_drv_ctx, str_id);
0109 if (!str_info)
0110 return -EINVAL;
0111
0112 dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
0113 str_id, str_info->pipe_id);
0114
0115 ret = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
0116 IPC_IA_ALLOC_STREAM_MRFLD, str_info->pipe_id,
0117 sizeof(str_info->alloc_param), &str_info->alloc_param,
0118 &data, true, true, false, true);
0119
0120 if (ret < 0) {
0121 dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
0122
0123 str_info->status = STREAM_UN_INIT;
0124 str_id = ret;
0125 } else if (data) {
0126 response = (struct snd_sst_alloc_response *)data;
0127 ret = response->str_type.result;
0128 if (!ret)
0129 goto out;
0130 dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
0131 if (ret == SST_ERR_STREAM_IN_USE) {
0132 dev_err(sst_drv_ctx->dev,
0133 "FW not in clean state, send free for:%d\n", str_id);
0134 sst_free_stream(sst_drv_ctx, str_id);
0135 }
0136 str_id = -ret;
0137 }
0138 out:
0139 kfree(data);
0140 return str_id;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
0152 {
0153 int retval = 0;
0154 struct stream_info *str_info;
0155 u16 data = 0;
0156
0157 dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
0158 str_info = get_stream_info(sst_drv_ctx, str_id);
0159 if (!str_info)
0160 return -EINVAL;
0161 if (str_info->status != STREAM_RUNNING)
0162 return -EBADRQC;
0163
0164 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
0165 IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id,
0166 sizeof(u16), &data, NULL, true, true, true, false);
0167
0168 return retval;
0169 }
0170
0171 int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
0172 struct snd_sst_bytes_v2 *bytes)
0173 { struct ipc_post *msg = NULL;
0174 u32 length;
0175 int pvt_id, ret = 0;
0176 struct sst_block *block = NULL;
0177
0178 dev_dbg(sst_drv_ctx->dev,
0179 "type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n",
0180 bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id,
0181 bytes->pipe_id, bytes->len);
0182
0183 if (sst_create_ipc_msg(&msg, true))
0184 return -ENOMEM;
0185
0186 pvt_id = sst_assign_pvt_id(sst_drv_ctx);
0187 sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg,
0188 bytes->task_id, 1, pvt_id);
0189 msg->mrfld_header.p.header_high.part.res_rqd = bytes->block;
0190 length = bytes->len;
0191 msg->mrfld_header.p.header_low_payload = length;
0192 dev_dbg(sst_drv_ctx->dev, "length is %d\n", length);
0193 memcpy(msg->mailbox_data, &bytes->bytes, bytes->len);
0194 if (bytes->block) {
0195 block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id);
0196 if (block == NULL) {
0197 kfree(msg);
0198 ret = -ENOMEM;
0199 goto out;
0200 }
0201 }
0202
0203 sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg);
0204 dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d",
0205 msg->mrfld_header.p.header_low_payload);
0206
0207 if (bytes->block) {
0208 ret = sst_wait_timeout(sst_drv_ctx, block);
0209 if (ret) {
0210 dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
0211 sst_free_block(sst_drv_ctx, block);
0212 goto out;
0213 }
0214 }
0215 if (bytes->type == SND_SST_BYTES_GET) {
0216
0217
0218
0219
0220 if (bytes->block) {
0221 unsigned char *r = block->data;
0222
0223 dev_dbg(sst_drv_ctx->dev, "read back %d bytes",
0224 bytes->len);
0225 memcpy(bytes->bytes, r, bytes->len);
0226 }
0227 }
0228 if (bytes->block)
0229 sst_free_block(sst_drv_ctx, block);
0230 out:
0231 test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
0232 return ret;
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
0244 {
0245 int retval = 0;
0246 struct stream_info *str_info;
0247
0248 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
0249 str_info = get_stream_info(sst_drv_ctx, str_id);
0250 if (!str_info)
0251 return -EINVAL;
0252 if (str_info->status == STREAM_PAUSED)
0253 return 0;
0254 if (str_info->status == STREAM_RUNNING ||
0255 str_info->status == STREAM_INIT) {
0256 if (str_info->prev == STREAM_UN_INIT)
0257 return -EBADRQC;
0258
0259 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
0260 IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id,
0261 0, NULL, NULL, true, true, false, true);
0262
0263 if (retval == 0) {
0264 str_info->prev = str_info->status;
0265 str_info->status = STREAM_PAUSED;
0266 } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
0267 retval = -EINVAL;
0268 mutex_lock(&sst_drv_ctx->sst_lock);
0269 sst_clean_stream(str_info);
0270 mutex_unlock(&sst_drv_ctx->sst_lock);
0271 }
0272 } else {
0273 retval = -EBADRQC;
0274 dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n");
0275 }
0276
0277 return retval;
0278 }
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
0289 {
0290 int retval = 0;
0291 struct stream_info *str_info;
0292
0293 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
0294 str_info = get_stream_info(sst_drv_ctx, str_id);
0295 if (!str_info)
0296 return -EINVAL;
0297 if (str_info->status == STREAM_RUNNING)
0298 return 0;
0299
0300 if (str_info->resume_status == STREAM_PAUSED &&
0301 str_info->resume_prev == STREAM_RUNNING) {
0302
0303
0304
0305
0306 dev_dbg(sst_drv_ctx->dev, "restart recreated stream after resume\n");
0307 str_info->status = STREAM_RUNNING;
0308 str_info->prev = STREAM_PAUSED;
0309 retval = sst_start_stream(sst_drv_ctx, str_id);
0310 str_info->resume_status = STREAM_UN_INIT;
0311 } else if (str_info->resume_status == STREAM_PAUSED &&
0312 str_info->resume_prev == STREAM_INIT) {
0313
0314
0315
0316
0317 dev_dbg(sst_drv_ctx->dev, "leaving recreated stream idle after resume\n");
0318 str_info->status = STREAM_INIT;
0319 str_info->prev = STREAM_PAUSED;
0320 str_info->resume_status = STREAM_UN_INIT;
0321 } else if (str_info->status == STREAM_PAUSED) {
0322 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
0323 IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
0324 str_info->pipe_id, 0, NULL, NULL,
0325 true, true, false, true);
0326
0327 if (!retval) {
0328 if (str_info->prev == STREAM_RUNNING)
0329 str_info->status = STREAM_RUNNING;
0330 else
0331 str_info->status = STREAM_INIT;
0332 str_info->prev = STREAM_PAUSED;
0333 } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
0334 retval = -EINVAL;
0335 mutex_lock(&sst_drv_ctx->sst_lock);
0336 sst_clean_stream(str_info);
0337 mutex_unlock(&sst_drv_ctx->sst_lock);
0338 }
0339 } else {
0340 retval = -EBADRQC;
0341 dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n");
0342 }
0343
0344 return retval;
0345 }
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
0357 {
0358 int retval = 0;
0359 struct stream_info *str_info;
0360
0361 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
0362 str_info = get_stream_info(sst_drv_ctx, str_id);
0363 if (!str_info)
0364 return -EINVAL;
0365
0366 if (str_info->status != STREAM_UN_INIT) {
0367 str_info->prev = STREAM_UN_INIT;
0368 str_info->status = STREAM_INIT;
0369 str_info->cumm_bytes = 0;
0370 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
0371 IPC_CMD, IPC_IA_DROP_STREAM_MRFLD,
0372 str_info->pipe_id, 0, NULL, NULL,
0373 true, true, true, false);
0374 } else {
0375 retval = -EBADRQC;
0376 dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n",
0377 str_info->status);
0378 }
0379 return retval;
0380 }
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391 int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
0392 int str_id, bool partial_drain)
0393 {
0394 int retval = 0;
0395 struct stream_info *str_info;
0396
0397 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
0398 str_info = get_stream_info(sst_drv_ctx, str_id);
0399 if (!str_info)
0400 return -EINVAL;
0401 if (str_info->status != STREAM_RUNNING &&
0402 str_info->status != STREAM_INIT &&
0403 str_info->status != STREAM_PAUSED) {
0404 dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
0405 str_info->status);
0406 return -EBADRQC;
0407 }
0408
0409 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
0410 IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id,
0411 sizeof(u8), &partial_drain, NULL, true, true, false, false);
0412
0413
0414
0415
0416
0417
0418 return retval;
0419 }
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429 int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
0430 {
0431 int retval = 0;
0432 struct stream_info *str_info;
0433
0434 dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
0435
0436 mutex_lock(&sst_drv_ctx->sst_lock);
0437 if (sst_drv_ctx->sst_state == SST_RESET) {
0438 mutex_unlock(&sst_drv_ctx->sst_lock);
0439 return -ENODEV;
0440 }
0441 mutex_unlock(&sst_drv_ctx->sst_lock);
0442 str_info = get_stream_info(sst_drv_ctx, str_id);
0443 if (!str_info)
0444 return -EINVAL;
0445
0446 mutex_lock(&str_info->lock);
0447 if (str_info->status != STREAM_UN_INIT) {
0448 str_info->prev = str_info->status;
0449 str_info->status = STREAM_UN_INIT;
0450 mutex_unlock(&str_info->lock);
0451
0452 dev_dbg(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
0453 str_id, str_info->pipe_id);
0454 retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
0455 IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
0456 NULL, NULL, true, true, false, true);
0457
0458 dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n",
0459 retval);
0460 mutex_lock(&sst_drv_ctx->sst_lock);
0461 sst_clean_stream(str_info);
0462 mutex_unlock(&sst_drv_ctx->sst_lock);
0463 dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n");
0464 } else {
0465 mutex_unlock(&str_info->lock);
0466 retval = -EBADRQC;
0467 dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n");
0468 }
0469
0470 return retval;
0471 }