0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/kobject.h>
0015 #include <linux/pci.h>
0016 #include <linux/fs.h>
0017 #include <linux/firmware.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/sched.h>
0020 #include <linux/delay.h>
0021 #include <sound/asound.h>
0022 #include <sound/core.h>
0023 #include <sound/pcm.h>
0024 #include <sound/soc.h>
0025 #include <sound/compress_driver.h>
0026 #include <asm/platform_sst_audio.h>
0027 #include "../sst-mfld-platform.h"
0028 #include "sst.h"
0029
0030 int sst_shim_write(void __iomem *addr, int offset, int value)
0031 {
0032 writel(value, addr + offset);
0033 return 0;
0034 }
0035
0036 u32 sst_shim_read(void __iomem *addr, int offset)
0037 {
0038 return readl(addr + offset);
0039 }
0040
0041 u64 sst_reg_read64(void __iomem *addr, int offset)
0042 {
0043 u64 val = 0;
0044
0045 memcpy_fromio(&val, addr + offset, sizeof(val));
0046
0047 return val;
0048 }
0049
0050 int sst_shim_write64(void __iomem *addr, int offset, u64 value)
0051 {
0052 memcpy_toio(addr + offset, &value, sizeof(value));
0053 return 0;
0054 }
0055
0056 u64 sst_shim_read64(void __iomem *addr, int offset)
0057 {
0058 u64 val = 0;
0059
0060 memcpy_fromio(&val, addr + offset, sizeof(val));
0061 return val;
0062 }
0063
0064 void sst_set_fw_state_locked(
0065 struct intel_sst_drv *sst_drv_ctx, int sst_state)
0066 {
0067 mutex_lock(&sst_drv_ctx->sst_lock);
0068 sst_drv_ctx->sst_state = sst_state;
0069 mutex_unlock(&sst_drv_ctx->sst_lock);
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
0082 struct sst_block *block)
0083 {
0084 int retval = 0;
0085
0086 if (!wait_event_interruptible(sst_drv_ctx->wait_queue,
0087 block->condition)) {
0088
0089 if (block->ret_code < 0) {
0090 dev_err(sst_drv_ctx->dev,
0091 "stream failed %d\n", block->ret_code);
0092 retval = -EBUSY;
0093 } else {
0094 dev_dbg(sst_drv_ctx->dev, "event up\n");
0095 retval = 0;
0096 }
0097 } else {
0098 dev_err(sst_drv_ctx->dev, "signal interrupted\n");
0099 retval = -EINTR;
0100 }
0101 return retval;
0102
0103 }
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, struct sst_block *block)
0115 {
0116 int retval = 0;
0117
0118
0119
0120
0121
0122
0123 dev_dbg(sst_drv_ctx->dev,
0124 "waiting for condition %x ipc %d drv_id %d\n",
0125 block->condition, block->msg_id, block->drv_id);
0126 if (wait_event_timeout(sst_drv_ctx->wait_queue,
0127 block->condition,
0128 msecs_to_jiffies(SST_BLOCK_TIMEOUT))) {
0129
0130 dev_dbg(sst_drv_ctx->dev, "Event wake %x\n",
0131 block->condition);
0132 dev_dbg(sst_drv_ctx->dev, "message ret: %d\n",
0133 block->ret_code);
0134 retval = -block->ret_code;
0135 } else {
0136 block->on = false;
0137 dev_err(sst_drv_ctx->dev,
0138 "Wait timed-out condition:%#x, msg_id:%#x fw_state %#x\n",
0139 block->condition, block->msg_id, sst_drv_ctx->sst_state);
0140 sst_drv_ctx->sst_state = SST_RESET;
0141
0142 retval = -EBUSY;
0143 }
0144 return retval;
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 int sst_create_ipc_msg(struct ipc_post **arg, bool large)
0157 {
0158 struct ipc_post *msg;
0159
0160 msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
0161 if (!msg)
0162 return -ENOMEM;
0163 if (large) {
0164 msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
0165 if (!msg->mailbox_data) {
0166 kfree(msg);
0167 return -ENOMEM;
0168 }
0169 } else {
0170 msg->mailbox_data = NULL;
0171 }
0172 msg->is_large = large;
0173 *arg = msg;
0174 return 0;
0175 }
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large,
0187 struct intel_sst_drv *sst_drv_ctx, struct sst_block **block,
0188 u32 msg_id, u32 drv_id)
0189 {
0190 int retval;
0191
0192 retval = sst_create_ipc_msg(arg, large);
0193 if (retval)
0194 return retval;
0195 *block = sst_create_block(sst_drv_ctx, msg_id, drv_id);
0196 if (*block == NULL) {
0197 kfree(*arg);
0198 return -ENOMEM;
0199 }
0200 return 0;
0201 }
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 void sst_clean_stream(struct stream_info *stream)
0212 {
0213 stream->status = STREAM_UN_INIT;
0214 stream->prev = STREAM_UN_INIT;
0215 mutex_lock(&stream->lock);
0216 stream->cumm_bytes = 0;
0217 mutex_unlock(&stream->lock);
0218 }
0219
0220 int sst_prepare_and_post_msg(struct intel_sst_drv *sst,
0221 int task_id, int ipc_msg, int cmd_id, int pipe_id,
0222 size_t mbox_data_len, const void *mbox_data, void **data,
0223 bool large, bool fill_dsp, bool sync, bool response)
0224 {
0225 struct sst_block *block = NULL;
0226 struct ipc_post *msg = NULL;
0227 struct ipc_dsp_hdr dsp_hdr;
0228 int ret = 0, pvt_id;
0229
0230 pvt_id = sst_assign_pvt_id(sst);
0231 if (pvt_id < 0)
0232 return pvt_id;
0233
0234 if (response)
0235 ret = sst_create_block_and_ipc_msg(
0236 &msg, large, sst, &block, ipc_msg, pvt_id);
0237 else
0238 ret = sst_create_ipc_msg(&msg, large);
0239
0240 if (ret < 0) {
0241 test_and_clear_bit(pvt_id, &sst->pvt_id);
0242 return -ENOMEM;
0243 }
0244
0245 dev_dbg(sst->dev, "pvt_id = %d, pipe id = %d, task = %d ipc_msg: %d\n",
0246 pvt_id, pipe_id, task_id, ipc_msg);
0247 sst_fill_header_mrfld(&msg->mrfld_header, ipc_msg,
0248 task_id, large, pvt_id);
0249 msg->mrfld_header.p.header_low_payload = sizeof(dsp_hdr) + mbox_data_len;
0250 msg->mrfld_header.p.header_high.part.res_rqd = !sync;
0251 dev_dbg(sst->dev, "header:%x\n",
0252 msg->mrfld_header.p.header_high.full);
0253 dev_dbg(sst->dev, "response rqd: %x",
0254 msg->mrfld_header.p.header_high.part.res_rqd);
0255 dev_dbg(sst->dev, "msg->mrfld_header.p.header_low_payload:%d",
0256 msg->mrfld_header.p.header_low_payload);
0257 if (fill_dsp) {
0258 sst_fill_header_dsp(&dsp_hdr, cmd_id, pipe_id, mbox_data_len);
0259 memcpy(msg->mailbox_data, &dsp_hdr, sizeof(dsp_hdr));
0260 if (mbox_data_len) {
0261 memcpy(msg->mailbox_data + sizeof(dsp_hdr),
0262 mbox_data, mbox_data_len);
0263 }
0264 }
0265
0266 if (sync)
0267 sst->ops->post_message(sst, msg, true);
0268 else
0269 sst_add_to_dispatch_list_and_post(sst, msg);
0270
0271 if (response) {
0272 ret = sst_wait_timeout(sst, block);
0273 if (ret < 0)
0274 goto out;
0275
0276 if (data && block->data) {
0277 *data = kmemdup(block->data, block->size, GFP_KERNEL);
0278 if (!*data) {
0279 ret = -ENOMEM;
0280 goto out;
0281 }
0282 }
0283 }
0284 out:
0285 if (response)
0286 sst_free_block(sst, block);
0287 test_and_clear_bit(pvt_id, &sst->pvt_id);
0288 return ret;
0289 }
0290
0291 int sst_pm_runtime_put(struct intel_sst_drv *sst_drv)
0292 {
0293 int ret;
0294
0295 pm_runtime_mark_last_busy(sst_drv->dev);
0296 ret = pm_runtime_put_autosuspend(sst_drv->dev);
0297 if (ret < 0)
0298 return ret;
0299 return 0;
0300 }
0301
0302 void sst_fill_header_mrfld(union ipc_header_mrfld *header,
0303 int msg, int task_id, int large, int drv_id)
0304 {
0305 header->full = 0;
0306 header->p.header_high.part.msg_id = msg;
0307 header->p.header_high.part.task_id = task_id;
0308 header->p.header_high.part.large = large;
0309 header->p.header_high.part.drv_id = drv_id;
0310 header->p.header_high.part.done = 0;
0311 header->p.header_high.part.busy = 1;
0312 header->p.header_high.part.res_rqd = 1;
0313 }
0314
0315 void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg,
0316 int pipe_id, int len)
0317 {
0318 dsp->cmd_id = msg;
0319 dsp->mod_index_id = 0xff;
0320 dsp->pipe_id = pipe_id;
0321 dsp->length = len;
0322 dsp->mod_id = 0;
0323 }
0324
0325 #define SST_MAX_BLOCKS 15
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335 int sst_assign_pvt_id(struct intel_sst_drv *drv)
0336 {
0337 int local;
0338
0339 spin_lock(&drv->block_lock);
0340
0341 local = ffz(drv->pvt_id);
0342 dev_dbg(drv->dev, "pvt_id assigned --> %d\n", local);
0343 if (local >= SST_MAX_BLOCKS){
0344 spin_unlock(&drv->block_lock);
0345 dev_err(drv->dev, "PVT _ID error: no free id blocks ");
0346 return -EINVAL;
0347 }
0348
0349 change_bit(local, &drv->pvt_id);
0350 spin_unlock(&drv->block_lock);
0351 return local;
0352 }
0353
0354 int sst_validate_strid(
0355 struct intel_sst_drv *sst_drv_ctx, int str_id)
0356 {
0357 if (str_id <= 0 || str_id > sst_drv_ctx->info.max_streams) {
0358 dev_err(sst_drv_ctx->dev,
0359 "SST ERR: invalid stream id : %d, max %d\n",
0360 str_id, sst_drv_ctx->info.max_streams);
0361 return -EINVAL;
0362 }
0363
0364 return 0;
0365 }
0366
0367 struct stream_info *get_stream_info(
0368 struct intel_sst_drv *sst_drv_ctx, int str_id)
0369 {
0370 if (sst_validate_strid(sst_drv_ctx, str_id))
0371 return NULL;
0372 return &sst_drv_ctx->streams[str_id];
0373 }
0374
0375 int get_stream_id_mrfld(struct intel_sst_drv *sst_drv_ctx,
0376 u32 pipe_id)
0377 {
0378 int i;
0379
0380 for (i = 1; i <= sst_drv_ctx->info.max_streams; i++)
0381 if (pipe_id == sst_drv_ctx->streams[i].pipe_id)
0382 return i;
0383
0384 dev_dbg(sst_drv_ctx->dev, "no such pipe_id(%u)", pipe_id);
0385 return -1;
0386 }
0387
0388 u32 relocate_imr_addr_mrfld(u32 base_addr)
0389 {
0390
0391
0392 base_addr = MRFLD_FW_VIRTUAL_BASE + (base_addr % (512 * 1024 * 1024));
0393 return base_addr;
0394 }
0395 EXPORT_SYMBOL_GPL(relocate_imr_addr_mrfld);
0396
0397 void sst_add_to_dispatch_list_and_post(struct intel_sst_drv *sst,
0398 struct ipc_post *msg)
0399 {
0400 unsigned long irq_flags;
0401
0402 spin_lock_irqsave(&sst->ipc_spin_lock, irq_flags);
0403 list_add_tail(&msg->node, &sst->ipc_dispatch_list);
0404 spin_unlock_irqrestore(&sst->ipc_spin_lock, irq_flags);
0405 sst->ops->post_message(sst, NULL, false);
0406 }