/* * fill channel map params for multichannel support. * Ideally channel map should be received from upper layers * for multichannel support. * Currently hardcoding as per FW reqm.
*/
num_ch = sst_get_num_channel(str_params);
pcm_params = &str_info->alloc_param.codec_params.uc.pcm_params; for (i = 0; i < 8; i++) { if (i < num_ch)
pcm_params->channel_map[i] = i; else
pcm_params->channel_map[i] = 0xff;
}
dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
str_info->alloc_param.ts);
dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
str_info->pipe_id, str_info->task_id);
return sst_realloc_stream(sst_drv_ctx, str_id);
}
/** * sst_realloc_stream - Send msg for (re-)allocating a stream using the * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * * Send a msg for (re-)allocating a stream using the parameters previously * passed to sst_alloc_stream_mrfld() for the same stream ID. * Return: 0 or negative errno value.
*/ int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
{ struct snd_sst_alloc_response *response; struct stream_info *str_info; void *data = NULL; int ret;
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL;
dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
str_id, str_info->pipe_id);
if (ret < 0) {
dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret); /* alloc failed, so reset the state to uninit */
str_info->status = STREAM_UN_INIT;
str_id = ret;
} elseif (data) {
response = (struct snd_sst_alloc_response *)data;
ret = response->str_type.result; if (!ret) goto out;
dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret); if (ret == SST_ERR_STREAM_IN_USE) {
dev_err(sst_drv_ctx->dev, "FW not in clean state, send free for:%d\n", str_id);
sst_free_stream(sst_drv_ctx, str_id);
}
str_id = -ret;
}
out:
kfree(data); return str_id;
}
/** * sst_start_stream - Send msg for a starting stream * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * * This function is called by any function which wants to start * a stream.
*/ int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
{ int retval = 0; struct stream_info *str_info;
u16 data = 0;
dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL; if (str_info->status != STREAM_RUNNING) return -EBADRQC;
if (bytes_block) {
ret = sst_wait_timeout(sst_drv_ctx, block); if (ret) {
dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
sst_free_block(sst_drv_ctx, block); goto out;
}
} if (bytes->type == SND_SST_BYTES_GET) { /* * copy the reply and send back * we need to update only sz and payload
*/ if (bytes_block) { unsignedchar *r = block->data;
/** * sst_pause_stream - Send msg for a pausing stream * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * * This function is called by any function which wants to pause * an already running stream.
*/ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
{ int retval = 0; struct stream_info *str_info;
dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL; if (str_info->status == STREAM_PAUSED) return 0; if (str_info->status == STREAM_RUNNING ||
str_info->status == STREAM_INIT) { if (str_info->prev == STREAM_UN_INIT) return -EBADRQC;
/** * sst_resume_stream - Send msg for resuming stream * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * * This function is called by any function which wants to resume * an already paused stream.
*/ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
{ int retval = 0; struct stream_info *str_info;
dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL; if (str_info->status == STREAM_RUNNING) return 0;
if (str_info->resume_status == STREAM_PAUSED &&
str_info->resume_prev == STREAM_RUNNING) { /* * Stream was running before suspend and re-created on resume, * start it to get back to running state.
*/
dev_dbg(sst_drv_ctx->dev, "restart recreated stream after resume\n");
str_info->status = STREAM_RUNNING;
str_info->prev = STREAM_PAUSED;
retval = sst_start_stream(sst_drv_ctx, str_id);
str_info->resume_status = STREAM_UN_INIT;
} elseif (str_info->resume_status == STREAM_PAUSED &&
str_info->resume_prev == STREAM_INIT) { /* * Stream was idle before suspend and re-created on resume, * keep it as is.
*/
dev_dbg(sst_drv_ctx->dev, "leaving recreated stream idle after resume\n");
str_info->status = STREAM_INIT;
str_info->prev = STREAM_PAUSED;
str_info->resume_status = STREAM_UN_INIT;
} elseif (str_info->status == STREAM_PAUSED) {
retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
str_info->pipe_id, 0, NULL, NULL, true, true, false, true);
/** * sst_drop_stream - Send msg for stopping stream * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * * This function is called by any function which wants to stop * a stream.
*/ int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
{ int retval = 0; struct stream_info *str_info;
dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL;
/** * sst_drain_stream - Send msg for draining stream * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * @partial_drain: boolean indicating if a gapless transition is taking place * * This function is called by any function which wants to drain * a stream.
*/ int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, int str_id, bool partial_drain)
{ int retval = 0; struct stream_info *str_info;
dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL; if (str_info->status != STREAM_RUNNING &&
str_info->status != STREAM_INIT &&
str_info->status != STREAM_PAUSED) {
dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
str_info->status); return -EBADRQC;
}
retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id, sizeof(u8), &partial_drain, NULL, true, true, false, false); /* * with new non blocked drain implementation in core we dont need to * wait for respsonse, and need to only invoke callback for drain * complete
*/
return retval;
}
/** * sst_free_stream - Frees a stream * @sst_drv_ctx: intel_sst_drv context pointer * @str_id: stream ID * * This function is called by any function which wants to free * a stream.
*/ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
{ int retval = 0; struct stream_info *str_info;
dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
mutex_lock(&sst_drv_ctx->sst_lock); if (sst_drv_ctx->sst_state == SST_RESET) {
mutex_unlock(&sst_drv_ctx->sst_lock); return -ENODEV;
}
mutex_unlock(&sst_drv_ctx->sst_lock);
str_info = get_stream_info(sst_drv_ctx, str_id); if (!str_info) return -EINVAL;
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.