Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 473858ca authored by Hans de Goede's avatar Hans de Goede Committed by Mark Brown
Browse files

ASoC: Intel: sst: Add sst_realloc_stream() function



Move the struct snd_sst_alloc_mrfld alloc parameters from the stack
into struct stream_info and add a new sst_realloc_stream() function which
can re-alloc a stream with the same parameters as before.

This is a preparation patch for fixing suspend/resume issues with some
SST / DSP firmware versions.

Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent de983347
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -180,6 +180,7 @@ struct sst_block {
 * @status : stream current state
 * @status : stream current state
 * @prev : stream prev state
 * @prev : stream prev state
 * @lock : stream mutex for protecting state
 * @lock : stream mutex for protecting state
 * @alloc_param : parameters used for stream (re-)allocation
 * @pcm_substream : PCM substream
 * @pcm_substream : PCM substream
 * @period_elapsed : PCM period elapsed callback
 * @period_elapsed : PCM period elapsed callback
 * @sfreq : stream sampling freq
 * @sfreq : stream sampling freq
@@ -189,6 +190,7 @@ struct stream_info {
	unsigned int		status;
	unsigned int		status;
	unsigned int		prev;
	unsigned int		prev;
	struct mutex		lock;
	struct mutex		lock;
	struct snd_sst_alloc_mrfld alloc_param;


	void			*pcm_substream;
	void			*pcm_substream;
	void (*period_elapsed)(void *pcm_substream);
	void (*period_elapsed)(void *pcm_substream);
@@ -429,6 +431,7 @@ struct intel_sst_ops {
	void (*post_download)(struct intel_sst_drv *sst);
	void (*post_download)(struct intel_sst_drv *sst);
};
};


int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id);
int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int id);
+53 −35
Original line number Original line Diff line number Diff line
@@ -35,29 +35,31 @@


int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
{
{
	struct snd_sst_alloc_mrfld alloc_param;
	struct snd_pcm_params *pcm_params;
	struct snd_sst_params *str_params;
	struct snd_sst_params *str_params;
	struct snd_sst_tstamp fw_tstamp;
	struct snd_sst_tstamp fw_tstamp;
	struct stream_info *str_info;
	struct stream_info *str_info;
	struct snd_sst_alloc_response *response;
	int i, num_ch, str_id;
	unsigned int str_id, pipe_id, task_id;
	int i, num_ch, ret = 0;
	void *data = NULL;


	dev_dbg(sst_drv_ctx->dev, "Enter\n");
	dev_dbg(sst_drv_ctx->dev, "Enter\n");


	str_params = (struct snd_sst_params *)params;
	str_params = (struct snd_sst_params *)params;
	memset(&alloc_param, 0, sizeof(alloc_param));
	str_id = str_params->stream_id;
	alloc_param.operation = str_params->ops;
	str_info = get_stream_info(sst_drv_ctx, str_id);
	alloc_param.codec_type = str_params->codec;
	if (!str_info)
	alloc_param.sg_count = str_params->aparams.sg_count;
		return -EINVAL;
	alloc_param.ring_buf_info[0].addr =

	memset(&str_info->alloc_param, 0, sizeof(str_info->alloc_param));
	str_info->alloc_param.operation = str_params->ops;
	str_info->alloc_param.codec_type = str_params->codec;
	str_info->alloc_param.sg_count = str_params->aparams.sg_count;
	str_info->alloc_param.ring_buf_info[0].addr =
		str_params->aparams.ring_buf_info[0].addr;
		str_params->aparams.ring_buf_info[0].addr;
	alloc_param.ring_buf_info[0].size =
	str_info->alloc_param.ring_buf_info[0].size =
		str_params->aparams.ring_buf_info[0].size;
		str_params->aparams.ring_buf_info[0].size;
	alloc_param.frag_size = str_params->aparams.frag_size;
	str_info->alloc_param.frag_size = str_params->aparams.frag_size;


	memcpy(&alloc_param.codec_params, &str_params->sparams,
	memcpy(&str_info->alloc_param.codec_params, &str_params->sparams,
			sizeof(struct snd_sst_stream_params));
			sizeof(struct snd_sst_stream_params));


	/*
	/*
@@ -67,46 +69,62 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
	 * Currently hardcoding as per FW reqm.
	 * Currently hardcoding as per FW reqm.
	 */
	 */
	num_ch = sst_get_num_channel(str_params);
	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++) {
	for (i = 0; i < 8; i++) {
		if (i < num_ch)
		if (i < num_ch)
			alloc_param.codec_params.uc.pcm_params.channel_map[i] = i;
			pcm_params->channel_map[i] = i;
		else
		else
			alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF;
			pcm_params->channel_map[i] = 0xff;
	}
	}


	str_id = str_params->stream_id;
	str_info = get_stream_info(sst_drv_ctx, str_id);
	if (str_info == NULL) {
		dev_err(sst_drv_ctx->dev, "get stream info returned null\n");
		return -EINVAL;
	}

	pipe_id = str_params->device_type;
	task_id = str_params->task;
	sst_drv_ctx->streams[str_id].status = STREAM_INIT;
	sst_drv_ctx->streams[str_id].status = STREAM_INIT;
	sst_drv_ctx->streams[str_id].prev = STREAM_UN_INIT;
	sst_drv_ctx->streams[str_id].prev = STREAM_UN_INIT;
	sst_drv_ctx->streams[str_id].pipe_id = pipe_id;
	sst_drv_ctx->streams[str_id].pipe_id = str_params->device_type;
	sst_drv_ctx->streams[str_id].task_id = task_id;
	sst_drv_ctx->streams[str_id].task_id = str_params->task;
	sst_drv_ctx->streams[str_id].num_ch = num_ch;
	sst_drv_ctx->streams[str_id].num_ch = num_ch;


	if (sst_drv_ctx->info.lpe_viewpt_rqd)
	if (sst_drv_ctx->info.lpe_viewpt_rqd)
		alloc_param.ts = sst_drv_ctx->info.mailbox_start +
		str_info->alloc_param.ts = sst_drv_ctx->info.mailbox_start +
			sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
			sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
	else
	else
		alloc_param.ts = sst_drv_ctx->mailbox_add +
		str_info->alloc_param.ts = sst_drv_ctx->mailbox_add +
			sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
			sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));


	dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
	dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
			alloc_param.ts);
			str_info->alloc_param.ts);
	dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
	dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
			pipe_id, task_id);
			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;


	/* allocate device type context */
	dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
	dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
			str_id, pipe_id);
		str_id, str_info->pipe_id);
	ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,

			IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
	ret = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
			&alloc_param, &data, true, true, false, true);
			IPC_IA_ALLOC_STREAM_MRFLD, str_info->pipe_id,
			sizeof(str_info->alloc_param), &str_info->alloc_param,
			&data, true, true, false, true);


	if (ret < 0) {
	if (ret < 0) {
		dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
		dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);