/* * sst_wait_timeout - wait on event for timeout * * @sst_drv_ctx: Driver context * @block: Driver block to wait on * * This function waits with a timeout value (and is not interruptible) on a * given block event
*/ int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, struct sst_block *block)
{ int retval = 0;
/* * NOTE: * Observed that FW processes the alloc msg and replies even * before the alloc thread has finished execution
*/
dev_dbg(sst_drv_ctx->dev, "waiting for condition %x ipc %d drv_id %d\n",
block->condition, block->msg_id, block->drv_id); if (wait_event_timeout(sst_drv_ctx->wait_queue,
block->condition,
msecs_to_jiffies(SST_BLOCK_TIMEOUT))) { /* event wake */
dev_dbg(sst_drv_ctx->dev, "Event wake %x\n",
block->condition);
dev_dbg(sst_drv_ctx->dev, "message ret: %d\n",
block->ret_code);
retval = -block->ret_code;
} else {
block->on = false;
dev_err(sst_drv_ctx->dev, "Wait timed-out condition:%#x, msg_id:%#x fw_state %#x\n",
block->condition, block->msg_id, sst_drv_ctx->sst_state);
sst_drv_ctx->sst_state = SST_RESET;
retval = -EBUSY;
} return retval;
}
/* * sst_create_ipc_msg - create a IPC message * * @arg: ipc message * @large: large or short message * * this function allocates structures to send a large or short * message to the firmware
*/ int sst_create_ipc_msg(struct ipc_post **arg, bool large)
{ struct ipc_post *msg;
if (sync)
sst->ops->post_message(sst, msg, true); else
sst_add_to_dispatch_list_and_post(sst, msg);
if (response) {
ret = sst_wait_timeout(sst, block); if (ret < 0) goto out;
if (data && block->data) {
*data = kmemdup(block->data, block->size, GFP_KERNEL); if (!*data) {
ret = -ENOMEM; goto out;
}
}
}
out: if (response)
sst_free_block(sst, block);
test_and_clear_bit(pvt_id, &sst->pvt_id); return ret;
}
int sst_pm_runtime_put(struct intel_sst_drv *sst_drv)
{ int ret;
ret = pm_runtime_put_autosuspend(sst_drv->dev); if (ret < 0) return ret; return 0;
}
void sst_fill_header_mrfld(union ipc_header_mrfld *header, int msg, int task_id, int large, int drv_id)
{
header->full = 0;
header->p.header_high.part.msg_id = msg;
header->p.header_high.part.task_id = task_id;
header->p.header_high.part.large = large;
header->p.header_high.part.drv_id = drv_id;
header->p.header_high.part.done = 0;
header->p.header_high.part.busy = 1;
header->p.header_high.part.res_rqd = 1;
}
void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg, int pipe_id, int len)
{
dsp->cmd_id = msg;
dsp->mod_index_id = 0xff;
dsp->pipe_id = pipe_id;
dsp->length = len;
dsp->mod_id = 0;
}
#define SST_MAX_BLOCKS 15 /* * sst_assign_pvt_id - assign a pvt id for stream * * @sst_drv_ctx : driver context * * this function assigns a private id for calls that dont have stream * context yet, should be called with lock held * uses bits for the id, and finds first free bits and assigns that
*/ int sst_assign_pvt_id(struct intel_sst_drv *drv)
{ int local;
spin_lock(&drv->block_lock); /* find first zero index from lsb */
local = ffz(drv->pvt_id);
dev_dbg(drv->dev, "pvt_id assigned --> %d\n", local); if (local >= SST_MAX_BLOCKS){
spin_unlock(&drv->block_lock);
dev_err(drv->dev, "PVT _ID error: no free id blocks "); return -EINVAL;
} /* toggle the index */
change_bit(local, &drv->pvt_id);
spin_unlock(&drv->block_lock); return local;
}
int sst_validate_strid( struct intel_sst_drv *sst_drv_ctx, int str_id)
{ if (str_id <= 0 || str_id > sst_drv_ctx->info.max_streams) {
dev_err(sst_drv_ctx->dev, "SST ERR: invalid stream id : %d, max %d\n",
str_id, sst_drv_ctx->info.max_streams); return -EINVAL;
}
return 0;
}
struct stream_info *get_stream_info( struct intel_sst_drv *sst_drv_ctx, int str_id)
{ if (sst_validate_strid(sst_drv_ctx, str_id)) return NULL; return &sst_drv_ctx->streams[str_id];
}
int get_stream_id_mrfld(struct intel_sst_drv *sst_drv_ctx,
u32 pipe_id)
{ int i;
for (i = 1; i <= sst_drv_ctx->info.max_streams; i++) if (pipe_id == sst_drv_ctx->streams[i].pipe_id) return i;
dev_dbg(sst_drv_ctx->dev, "no such pipe_id(%u)", pipe_id); return -1;
}
u32 relocate_imr_addr_mrfld(u32 base_addr)
{ /* Get the difference from 512MB aligned base addr */ /* relocate the base */
base_addr = MRFLD_FW_VIRTUAL_BASE + (base_addr % (512 * 1024 * 1024)); return base_addr;
}
EXPORT_SYMBOL_GPL(relocate_imr_addr_mrfld);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.