xref: /linux/sound/soc/sof/ipc3-pcm.c (revision 33e02dc69afbd8f1b85a51d74d72f139ba4ca623)
14123c24bSRanjani Sridharan // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
24123c24bSRanjani Sridharan //
34123c24bSRanjani Sridharan // This file is provided under a dual BSD/GPLv2 license.  When using or
44123c24bSRanjani Sridharan // redistributing this file, you may do so under either license.
54123c24bSRanjani Sridharan //
6*293ad281SPierre-Louis Bossart // Copyright(c) 2021 Intel Corporation
74123c24bSRanjani Sridharan //
84123c24bSRanjani Sridharan //
94123c24bSRanjani Sridharan 
104123c24bSRanjani Sridharan #include <sound/pcm_params.h>
11f80beaf6SPeter Ujfalusi #include "ipc3-priv.h"
124123c24bSRanjani Sridharan #include "ops.h"
134123c24bSRanjani Sridharan #include "sof-priv.h"
144123c24bSRanjani Sridharan #include "sof-audio.h"
154123c24bSRanjani Sridharan 
sof_ipc3_pcm_hw_free(struct snd_soc_component * component,struct snd_pcm_substream * substream)164123c24bSRanjani Sridharan static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component,
174123c24bSRanjani Sridharan 				struct snd_pcm_substream *substream)
184123c24bSRanjani Sridharan {
194123c24bSRanjani Sridharan 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
204d5f4119SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
214123c24bSRanjani Sridharan 	struct sof_ipc_stream stream;
224123c24bSRanjani Sridharan 	struct snd_sof_pcm *spcm;
234123c24bSRanjani Sridharan 
244123c24bSRanjani Sridharan 	spcm = snd_sof_find_spcm_dai(component, rtd);
254123c24bSRanjani Sridharan 	if (!spcm)
264123c24bSRanjani Sridharan 		return -EINVAL;
274123c24bSRanjani Sridharan 
284123c24bSRanjani Sridharan 	if (!spcm->prepared[substream->stream])
294123c24bSRanjani Sridharan 		return 0;
304123c24bSRanjani Sridharan 
314123c24bSRanjani Sridharan 	stream.hdr.size = sizeof(stream);
324123c24bSRanjani Sridharan 	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
334123c24bSRanjani Sridharan 	stream.comp_id = spcm->stream[substream->stream].comp_id;
344123c24bSRanjani Sridharan 
354123c24bSRanjani Sridharan 	/* send IPC to the DSP */
36367fd6ffSCurtis Malainey 	return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream));
374123c24bSRanjani Sridharan }
384123c24bSRanjani Sridharan 
sof_ipc3_pcm_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_sof_platform_stream_params * platform_params)39621fd48cSRanjani Sridharan static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
40621fd48cSRanjani Sridharan 				  struct snd_pcm_substream *substream,
41621fd48cSRanjani Sridharan 				  struct snd_pcm_hw_params *params,
42621fd48cSRanjani Sridharan 				  struct snd_sof_platform_stream_params *platform_params)
43621fd48cSRanjani Sridharan {
44621fd48cSRanjani Sridharan 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
454d5f4119SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
46621fd48cSRanjani Sridharan 	struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
47621fd48cSRanjani Sridharan 	struct snd_pcm_runtime *runtime = substream->runtime;
48621fd48cSRanjani Sridharan 	struct sof_ipc_pcm_params_reply ipc_params_reply;
49621fd48cSRanjani Sridharan 	struct sof_ipc_pcm_params pcm;
50621fd48cSRanjani Sridharan 	struct snd_sof_pcm *spcm;
51621fd48cSRanjani Sridharan 	int ret;
52621fd48cSRanjani Sridharan 
53621fd48cSRanjani Sridharan 	spcm = snd_sof_find_spcm_dai(component, rtd);
54621fd48cSRanjani Sridharan 	if (!spcm)
55621fd48cSRanjani Sridharan 		return -EINVAL;
56621fd48cSRanjani Sridharan 
57621fd48cSRanjani Sridharan 	memset(&pcm, 0, sizeof(pcm));
58621fd48cSRanjani Sridharan 
59621fd48cSRanjani Sridharan 	/* number of pages should be rounded up */
60621fd48cSRanjani Sridharan 	pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes);
61621fd48cSRanjani Sridharan 
62621fd48cSRanjani Sridharan 	/* set IPC PCM parameters */
63621fd48cSRanjani Sridharan 	pcm.hdr.size = sizeof(pcm);
64621fd48cSRanjani Sridharan 	pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
65621fd48cSRanjani Sridharan 	pcm.comp_id = spcm->stream[substream->stream].comp_id;
66621fd48cSRanjani Sridharan 	pcm.params.hdr.size = sizeof(pcm.params);
67621fd48cSRanjani Sridharan 	pcm.params.buffer.phy_addr = spcm->stream[substream->stream].page_table.addr;
68621fd48cSRanjani Sridharan 	pcm.params.buffer.size = runtime->dma_bytes;
69621fd48cSRanjani Sridharan 	pcm.params.direction = substream->stream;
70621fd48cSRanjani Sridharan 	pcm.params.sample_valid_bytes = params_width(params) >> 3;
71621fd48cSRanjani Sridharan 	pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
72621fd48cSRanjani Sridharan 	pcm.params.rate = params_rate(params);
73621fd48cSRanjani Sridharan 	pcm.params.channels = params_channels(params);
74621fd48cSRanjani Sridharan 	pcm.params.host_period_bytes = params_period_bytes(params);
75621fd48cSRanjani Sridharan 
76621fd48cSRanjani Sridharan 	/* container size */
77621fd48cSRanjani Sridharan 	ret = snd_pcm_format_physical_width(params_format(params));
78621fd48cSRanjani Sridharan 	if (ret < 0)
79621fd48cSRanjani Sridharan 		return ret;
80621fd48cSRanjani Sridharan 	pcm.params.sample_container_bytes = ret >> 3;
81621fd48cSRanjani Sridharan 
82621fd48cSRanjani Sridharan 	/* format */
83621fd48cSRanjani Sridharan 	switch (params_format(params)) {
84621fd48cSRanjani Sridharan 	case SNDRV_PCM_FORMAT_S16:
85621fd48cSRanjani Sridharan 		pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
86621fd48cSRanjani Sridharan 		break;
87621fd48cSRanjani Sridharan 	case SNDRV_PCM_FORMAT_S24:
88621fd48cSRanjani Sridharan 		pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
89621fd48cSRanjani Sridharan 		break;
90621fd48cSRanjani Sridharan 	case SNDRV_PCM_FORMAT_S32:
91621fd48cSRanjani Sridharan 		pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
92621fd48cSRanjani Sridharan 		break;
93621fd48cSRanjani Sridharan 	case SNDRV_PCM_FORMAT_FLOAT:
94621fd48cSRanjani Sridharan 		pcm.params.frame_fmt = SOF_IPC_FRAME_FLOAT;
95621fd48cSRanjani Sridharan 		break;
96621fd48cSRanjani Sridharan 	default:
97621fd48cSRanjani Sridharan 		return -EINVAL;
98621fd48cSRanjani Sridharan 	}
99621fd48cSRanjani Sridharan 
100621fd48cSRanjani Sridharan 	/* Update the IPC message with information from the platform */
101621fd48cSRanjani Sridharan 	pcm.params.stream_tag = platform_params->stream_tag;
102621fd48cSRanjani Sridharan 
103621fd48cSRanjani Sridharan 	if (platform_params->use_phy_address)
104621fd48cSRanjani Sridharan 		pcm.params.buffer.phy_addr = platform_params->phy_addr;
105621fd48cSRanjani Sridharan 
106621fd48cSRanjani Sridharan 	if (platform_params->no_ipc_position) {
107621fd48cSRanjani Sridharan 		/* For older ABIs set host_period_bytes to zero to inform
108621fd48cSRanjani Sridharan 		 * FW we don't want position updates. Newer versions use
109621fd48cSRanjani Sridharan 		 * no_stream_position for this purpose.
110621fd48cSRanjani Sridharan 		 */
111621fd48cSRanjani Sridharan 		if (v->abi_version < SOF_ABI_VER(3, 10, 0))
112621fd48cSRanjani Sridharan 			pcm.params.host_period_bytes = 0;
113621fd48cSRanjani Sridharan 		else
114621fd48cSRanjani Sridharan 			pcm.params.no_stream_position = 1;
115621fd48cSRanjani Sridharan 	}
116621fd48cSRanjani Sridharan 
117d95610a1SYC Hung 	if (platform_params->cont_update_posn)
118d95610a1SYC Hung 		pcm.params.cont_update_posn = 1;
119d95610a1SYC Hung 
120621fd48cSRanjani Sridharan 	dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
121621fd48cSRanjani Sridharan 
122621fd48cSRanjani Sridharan 	/* send hw_params IPC to the DSP */
1232a51c0f8SPeter Ujfalusi 	ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
124621fd48cSRanjani Sridharan 				 &ipc_params_reply, sizeof(ipc_params_reply));
125621fd48cSRanjani Sridharan 	if (ret < 0) {
126621fd48cSRanjani Sridharan 		dev_err(component->dev, "HW params ipc failed for stream %d\n",
127621fd48cSRanjani Sridharan 			pcm.params.stream_tag);
128621fd48cSRanjani Sridharan 		return ret;
129621fd48cSRanjani Sridharan 	}
130621fd48cSRanjani Sridharan 
131249f186dSDaniel Baluta 	ret = snd_sof_set_stream_data_offset(sdev, &spcm->stream[substream->stream],
132249f186dSDaniel Baluta 					     ipc_params_reply.posn_offset);
133621fd48cSRanjani Sridharan 	if (ret < 0) {
134621fd48cSRanjani Sridharan 		dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n",
135621fd48cSRanjani Sridharan 			__func__, spcm->pcm.pcm_id);
136621fd48cSRanjani Sridharan 		return ret;
137621fd48cSRanjani Sridharan 	}
138621fd48cSRanjani Sridharan 
139621fd48cSRanjani Sridharan 	return ret;
140621fd48cSRanjani Sridharan }
141621fd48cSRanjani Sridharan 
sof_ipc3_pcm_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)142beac3f4cSRanjani Sridharan static int sof_ipc3_pcm_trigger(struct snd_soc_component *component,
143beac3f4cSRanjani Sridharan 				struct snd_pcm_substream *substream, int cmd)
144beac3f4cSRanjani Sridharan {
1454d5f4119SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
146beac3f4cSRanjani Sridharan 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
147beac3f4cSRanjani Sridharan 	struct sof_ipc_stream stream;
148beac3f4cSRanjani Sridharan 	struct snd_sof_pcm *spcm;
149beac3f4cSRanjani Sridharan 
150beac3f4cSRanjani Sridharan 	spcm = snd_sof_find_spcm_dai(component, rtd);
151beac3f4cSRanjani Sridharan 	if (!spcm)
152beac3f4cSRanjani Sridharan 		return -EINVAL;
153beac3f4cSRanjani Sridharan 
154beac3f4cSRanjani Sridharan 	stream.hdr.size = sizeof(stream);
155beac3f4cSRanjani Sridharan 	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG;
156beac3f4cSRanjani Sridharan 	stream.comp_id = spcm->stream[substream->stream].comp_id;
157beac3f4cSRanjani Sridharan 
158beac3f4cSRanjani Sridharan 	switch (cmd) {
159beac3f4cSRanjani Sridharan 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
160beac3f4cSRanjani Sridharan 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE;
161beac3f4cSRanjani Sridharan 		break;
162beac3f4cSRanjani Sridharan 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
163beac3f4cSRanjani Sridharan 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
164beac3f4cSRanjani Sridharan 		break;
165beac3f4cSRanjani Sridharan 	case SNDRV_PCM_TRIGGER_START:
166beac3f4cSRanjani Sridharan 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;
167beac3f4cSRanjani Sridharan 		break;
168beac3f4cSRanjani Sridharan 	case SNDRV_PCM_TRIGGER_SUSPEND:
169beac3f4cSRanjani Sridharan 		fallthrough;
170beac3f4cSRanjani Sridharan 	case SNDRV_PCM_TRIGGER_STOP:
171beac3f4cSRanjani Sridharan 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
172beac3f4cSRanjani Sridharan 		break;
173beac3f4cSRanjani Sridharan 	default:
174beac3f4cSRanjani Sridharan 		dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd);
175beac3f4cSRanjani Sridharan 		return -EINVAL;
176beac3f4cSRanjani Sridharan 	}
177beac3f4cSRanjani Sridharan 
178beac3f4cSRanjani Sridharan 	/* send IPC to the DSP */
179367fd6ffSCurtis Malainey 	return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream));
180beac3f4cSRanjani Sridharan }
181beac3f4cSRanjani Sridharan 
ssp_dai_config_pcm_params_match(struct snd_sof_dev * sdev,const char * link_name,struct snd_pcm_hw_params * params)182b243b437SRanjani Sridharan static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name,
183b243b437SRanjani Sridharan 					    struct snd_pcm_hw_params *params)
184b243b437SRanjani Sridharan {
185b243b437SRanjani Sridharan 	struct sof_ipc_dai_config *config;
186b243b437SRanjani Sridharan 	struct snd_sof_dai *dai;
187b243b437SRanjani Sridharan 	int i;
188b243b437SRanjani Sridharan 
189b243b437SRanjani Sridharan 	/*
190b243b437SRanjani Sridharan 	 * Search for all matching DAIs as we can have both playback and capture DAI
191b243b437SRanjani Sridharan 	 * associated with the same link.
192b243b437SRanjani Sridharan 	 */
193b243b437SRanjani Sridharan 	list_for_each_entry(dai, &sdev->dai_list, list) {
194b243b437SRanjani Sridharan 		if (!dai->name || strcmp(link_name, dai->name))
195b243b437SRanjani Sridharan 			continue;
196b243b437SRanjani Sridharan 		for (i = 0; i < dai->number_configs; i++) {
197b243b437SRanjani Sridharan 			struct sof_dai_private_data *private = dai->private;
198b243b437SRanjani Sridharan 
199b243b437SRanjani Sridharan 			config = &private->dai_config[i];
200b243b437SRanjani Sridharan 			if (config->ssp.fsync_rate == params_rate(params)) {
201b243b437SRanjani Sridharan 				dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i);
202b243b437SRanjani Sridharan 				dai->current_config = i;
203b243b437SRanjani Sridharan 				break;
204b243b437SRanjani Sridharan 			}
205b243b437SRanjani Sridharan 		}
206b243b437SRanjani Sridharan 	}
207b243b437SRanjani Sridharan }
208b243b437SRanjani Sridharan 
sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)209b243b437SRanjani Sridharan static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
210b243b437SRanjani Sridharan 				       struct snd_pcm_hw_params *params)
211b243b437SRanjani Sridharan {
212b243b437SRanjani Sridharan 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
213b243b437SRanjani Sridharan 	struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
214b243b437SRanjani Sridharan 	struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name);
215b243b437SRanjani Sridharan 	struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
216b243b437SRanjani Sridharan 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
217b243b437SRanjani Sridharan 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
218b243b437SRanjani Sridharan 	struct sof_dai_private_data *private;
219b243b437SRanjani Sridharan 	struct snd_soc_dpcm *dpcm;
220b243b437SRanjani Sridharan 
221b243b437SRanjani Sridharan 	if (!dai) {
222b243b437SRanjani Sridharan 		dev_err(component->dev, "%s: No DAI found with name %s\n", __func__,
223b243b437SRanjani Sridharan 			rtd->dai_link->name);
224b243b437SRanjani Sridharan 		return -EINVAL;
225b243b437SRanjani Sridharan 	}
226b243b437SRanjani Sridharan 
227b243b437SRanjani Sridharan 	private = dai->private;
228b243b437SRanjani Sridharan 	if (!private) {
229b243b437SRanjani Sridharan 		dev_err(component->dev, "%s: No private data found for DAI %s\n", __func__,
230b243b437SRanjani Sridharan 			rtd->dai_link->name);
231b243b437SRanjani Sridharan 		return -EINVAL;
232b243b437SRanjani Sridharan 	}
233b243b437SRanjani Sridharan 
234b243b437SRanjani Sridharan 	/* read format from topology */
235b243b437SRanjani Sridharan 	snd_mask_none(fmt);
236b243b437SRanjani Sridharan 
237b243b437SRanjani Sridharan 	switch (private->comp_dai->config.frame_fmt) {
238b243b437SRanjani Sridharan 	case SOF_IPC_FRAME_S16_LE:
239b243b437SRanjani Sridharan 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
240b243b437SRanjani Sridharan 		break;
241b243b437SRanjani Sridharan 	case SOF_IPC_FRAME_S24_4LE:
242b243b437SRanjani Sridharan 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
243b243b437SRanjani Sridharan 		break;
244b243b437SRanjani Sridharan 	case SOF_IPC_FRAME_S32_LE:
245b243b437SRanjani Sridharan 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
246b243b437SRanjani Sridharan 		break;
247b243b437SRanjani Sridharan 	default:
248b243b437SRanjani Sridharan 		dev_err(component->dev, "No available DAI format!\n");
249b243b437SRanjani Sridharan 		return -EINVAL;
250b243b437SRanjani Sridharan 	}
251b243b437SRanjani Sridharan 
252b243b437SRanjani Sridharan 	/* read rate and channels from topology */
253b243b437SRanjani Sridharan 	switch (private->dai_config->type) {
254b243b437SRanjani Sridharan 	case SOF_DAI_INTEL_SSP:
255b243b437SRanjani Sridharan 		/* search for config to pcm params match, if not found use default */
256b243b437SRanjani Sridharan 		ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
257b243b437SRanjani Sridharan 
258b243b437SRanjani Sridharan 		rate->min = private->dai_config[dai->current_config].ssp.fsync_rate;
259b243b437SRanjani Sridharan 		rate->max = private->dai_config[dai->current_config].ssp.fsync_rate;
260b243b437SRanjani Sridharan 		channels->min = private->dai_config[dai->current_config].ssp.tdm_slots;
261b243b437SRanjani Sridharan 		channels->max = private->dai_config[dai->current_config].ssp.tdm_slots;
262b243b437SRanjani Sridharan 
263b243b437SRanjani Sridharan 		dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max);
264b243b437SRanjani Sridharan 		dev_dbg(component->dev, "channels_min: %d channels_max: %d\n",
265b243b437SRanjani Sridharan 			channels->min, channels->max);
266b243b437SRanjani Sridharan 
267b243b437SRanjani Sridharan 		break;
268b243b437SRanjani Sridharan 	case SOF_DAI_INTEL_DMIC:
269b243b437SRanjani Sridharan 		/* DMIC only supports 16 or 32 bit formats */
270b243b437SRanjani Sridharan 		if (private->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
271b243b437SRanjani Sridharan 			dev_err(component->dev, "Invalid fmt %d for DAI type %d\n",
272b243b437SRanjani Sridharan 				private->comp_dai->config.frame_fmt,
273b243b437SRanjani Sridharan 				private->dai_config->type);
274b243b437SRanjani Sridharan 		}
275b243b437SRanjani Sridharan 		break;
276b243b437SRanjani Sridharan 	case SOF_DAI_INTEL_HDA:
277b243b437SRanjani Sridharan 		/*
278b243b437SRanjani Sridharan 		 * HDAudio does not follow the default trigger
279b243b437SRanjani Sridharan 		 * sequence due to firmware implementation
280b243b437SRanjani Sridharan 		 */
281b243b437SRanjani Sridharan 		for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
282b243b437SRanjani Sridharan 			struct snd_soc_pcm_runtime *fe = dpcm->fe;
283b243b437SRanjani Sridharan 
284b243b437SRanjani Sridharan 			fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] =
285b243b437SRanjani Sridharan 				SND_SOC_DPCM_TRIGGER_POST;
286b243b437SRanjani Sridharan 		}
287b243b437SRanjani Sridharan 		break;
288b243b437SRanjani Sridharan 	case SOF_DAI_INTEL_ALH:
289b243b437SRanjani Sridharan 		/*
290b243b437SRanjani Sridharan 		 * Dai could run with different channel count compared with
291b243b437SRanjani Sridharan 		 * front end, so get dai channel count from topology
292b243b437SRanjani Sridharan 		 */
293b243b437SRanjani Sridharan 		channels->min = private->dai_config->alh.channels;
294b243b437SRanjani Sridharan 		channels->max = private->dai_config->alh.channels;
295b243b437SRanjani Sridharan 		break;
296b243b437SRanjani Sridharan 	case SOF_DAI_IMX_ESAI:
297b243b437SRanjani Sridharan 		rate->min = private->dai_config->esai.fsync_rate;
298b243b437SRanjani Sridharan 		rate->max = private->dai_config->esai.fsync_rate;
299b243b437SRanjani Sridharan 		channels->min = private->dai_config->esai.tdm_slots;
300b243b437SRanjani Sridharan 		channels->max = private->dai_config->esai.tdm_slots;
301b243b437SRanjani Sridharan 
302b243b437SRanjani Sridharan 		dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max);
303b243b437SRanjani Sridharan 		dev_dbg(component->dev, "channels_min: %d channels_max: %d\n",
304b243b437SRanjani Sridharan 			channels->min, channels->max);
305b243b437SRanjani Sridharan 		break;
306b243b437SRanjani Sridharan 	case SOF_DAI_MEDIATEK_AFE:
307b243b437SRanjani Sridharan 		rate->min = private->dai_config->afe.rate;
308b243b437SRanjani Sridharan 		rate->max = private->dai_config->afe.rate;
309b243b437SRanjani Sridharan 		channels->min = private->dai_config->afe.channels;
310b243b437SRanjani Sridharan 		channels->max = private->dai_config->afe.channels;
311b243b437SRanjani Sridharan 
312ed19c4a9STrevor Wu 		snd_mask_none(fmt);
313ed19c4a9STrevor Wu 
314ed19c4a9STrevor Wu 		switch (private->dai_config->afe.format) {
315ed19c4a9STrevor Wu 		case SOF_IPC_FRAME_S16_LE:
316ed19c4a9STrevor Wu 			snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
317ed19c4a9STrevor Wu 			break;
318ed19c4a9STrevor Wu 		case SOF_IPC_FRAME_S24_4LE:
319ed19c4a9STrevor Wu 			snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
320ed19c4a9STrevor Wu 			break;
321ed19c4a9STrevor Wu 		case SOF_IPC_FRAME_S32_LE:
322ed19c4a9STrevor Wu 			snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
323ed19c4a9STrevor Wu 			break;
324ed19c4a9STrevor Wu 		default:
325ed19c4a9STrevor Wu 			dev_err(component->dev, "Not available format!\n");
326ed19c4a9STrevor Wu 			return -EINVAL;
327ed19c4a9STrevor Wu 		}
328ed19c4a9STrevor Wu 
329b243b437SRanjani Sridharan 		dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max);
330b243b437SRanjani Sridharan 		dev_dbg(component->dev, "channels_min: %d channels_max: %d\n",
331b243b437SRanjani Sridharan 			channels->min, channels->max);
332b243b437SRanjani Sridharan 		break;
333b243b437SRanjani Sridharan 	case SOF_DAI_IMX_SAI:
334b243b437SRanjani Sridharan 		rate->min = private->dai_config->sai.fsync_rate;
335b243b437SRanjani Sridharan 		rate->max = private->dai_config->sai.fsync_rate;
336b243b437SRanjani Sridharan 		channels->min = private->dai_config->sai.tdm_slots;
337b243b437SRanjani Sridharan 		channels->max = private->dai_config->sai.tdm_slots;
338b243b437SRanjani Sridharan 
339b243b437SRanjani Sridharan 		dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max);
340b243b437SRanjani Sridharan 		dev_dbg(component->dev, "channels_min: %d channels_max: %d\n",
341b243b437SRanjani Sridharan 			channels->min, channels->max);
342b243b437SRanjani Sridharan 		break;
343b243b437SRanjani Sridharan 	case SOF_DAI_AMD_BT:
344b243b437SRanjani Sridharan 		rate->min = private->dai_config->acpbt.fsync_rate;
345b243b437SRanjani Sridharan 		rate->max = private->dai_config->acpbt.fsync_rate;
346b243b437SRanjani Sridharan 		channels->min = private->dai_config->acpbt.tdm_slots;
347b243b437SRanjani Sridharan 		channels->max = private->dai_config->acpbt.tdm_slots;
348b243b437SRanjani Sridharan 
349b243b437SRanjani Sridharan 		dev_dbg(component->dev,
350b243b437SRanjani Sridharan 			"AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max);
351b243b437SRanjani Sridharan 		dev_dbg(component->dev, "AMD_BT channels_min: %d channels_max: %d\n",
352b243b437SRanjani Sridharan 			channels->min, channels->max);
353b243b437SRanjani Sridharan 		break;
354b243b437SRanjani Sridharan 	case SOF_DAI_AMD_SP:
35575af4199SV sujith kumar Reddy 	case SOF_DAI_AMD_SP_VIRTUAL:
356b243b437SRanjani Sridharan 		rate->min = private->dai_config->acpsp.fsync_rate;
357b243b437SRanjani Sridharan 		rate->max = private->dai_config->acpsp.fsync_rate;
358b243b437SRanjani Sridharan 		channels->min = private->dai_config->acpsp.tdm_slots;
359b243b437SRanjani Sridharan 		channels->max = private->dai_config->acpsp.tdm_slots;
360b243b437SRanjani Sridharan 
361b243b437SRanjani Sridharan 		dev_dbg(component->dev,
362b243b437SRanjani Sridharan 			"AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max);
363b243b437SRanjani Sridharan 		dev_dbg(component->dev, "AMD_SP channels_min: %d channels_max: %d\n",
364b243b437SRanjani Sridharan 			channels->min, channels->max);
365b243b437SRanjani Sridharan 		break;
366ed2562c6SV sujith kumar Reddy 	case SOF_DAI_AMD_HS:
36775af4199SV sujith kumar Reddy 	case SOF_DAI_AMD_HS_VIRTUAL:
368ed2562c6SV sujith kumar Reddy 		rate->min = private->dai_config->acphs.fsync_rate;
369ed2562c6SV sujith kumar Reddy 		rate->max = private->dai_config->acphs.fsync_rate;
370ed2562c6SV sujith kumar Reddy 		channels->min = private->dai_config->acphs.tdm_slots;
371ed2562c6SV sujith kumar Reddy 		channels->max = private->dai_config->acphs.tdm_slots;
372ed2562c6SV sujith kumar Reddy 
373ed2562c6SV sujith kumar Reddy 		dev_dbg(component->dev,
374ed2562c6SV sujith kumar Reddy 			"AMD_HS channel_max: %d rate_max: %d\n", channels->max, rate->max);
375ed2562c6SV sujith kumar Reddy 		break;
376b243b437SRanjani Sridharan 	case SOF_DAI_AMD_DMIC:
377689614ceSAjit Kumar Pandey 		rate->min = private->dai_config->acpdmic.pdm_rate;
378689614ceSAjit Kumar Pandey 		rate->max = private->dai_config->acpdmic.pdm_rate;
379689614ceSAjit Kumar Pandey 		channels->min = private->dai_config->acpdmic.pdm_ch;
380689614ceSAjit Kumar Pandey 		channels->max = private->dai_config->acpdmic.pdm_ch;
381b243b437SRanjani Sridharan 
382b243b437SRanjani Sridharan 		dev_dbg(component->dev,
383b243b437SRanjani Sridharan 			"AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max);
384b243b437SRanjani Sridharan 		dev_dbg(component->dev, "AMD_DMIC channels_min: %d channels_max: %d\n",
385b243b437SRanjani Sridharan 			channels->min, channels->max);
386b243b437SRanjani Sridharan 		break;
38789ef4208SDaniel Baluta 	case SOF_DAI_IMX_MICFIL:
38889ef4208SDaniel Baluta 		rate->min = private->dai_config->micfil.pdm_rate;
38989ef4208SDaniel Baluta 		rate->max = private->dai_config->micfil.pdm_rate;
39089ef4208SDaniel Baluta 		channels->min = private->dai_config->micfil.pdm_ch;
39189ef4208SDaniel Baluta 		channels->max = private->dai_config->micfil.pdm_ch;
39289ef4208SDaniel Baluta 
39389ef4208SDaniel Baluta 		dev_dbg(component->dev,
39489ef4208SDaniel Baluta 			"MICFIL PDM rate_min: %d rate_max: %d\n", rate->min, rate->max);
39589ef4208SDaniel Baluta 		dev_dbg(component->dev, "MICFIL PDM channels_min: %d channels_max: %d\n",
39689ef4208SDaniel Baluta 			channels->min, channels->max);
39789ef4208SDaniel Baluta 		break;
39814d89e55SVijendar Mukunda 	case SOF_DAI_AMD_SDW:
39914d89e55SVijendar Mukunda 		/* change the default trigger sequence as per HW implementation */
40014d89e55SVijendar Mukunda 		for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
40114d89e55SVijendar Mukunda 			struct snd_soc_pcm_runtime *fe = dpcm->fe;
40214d89e55SVijendar Mukunda 
40314d89e55SVijendar Mukunda 			fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] =
40414d89e55SVijendar Mukunda 					SND_SOC_DPCM_TRIGGER_POST;
40514d89e55SVijendar Mukunda 		}
40614d89e55SVijendar Mukunda 
40714d89e55SVijendar Mukunda 		for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
40814d89e55SVijendar Mukunda 			struct snd_soc_pcm_runtime *fe = dpcm->fe;
40914d89e55SVijendar Mukunda 
41014d89e55SVijendar Mukunda 			fe->dai_link->trigger[SNDRV_PCM_STREAM_CAPTURE] =
41114d89e55SVijendar Mukunda 					SND_SOC_DPCM_TRIGGER_POST;
41214d89e55SVijendar Mukunda 		}
41314d89e55SVijendar Mukunda 		rate->min = private->dai_config->acp_sdw.rate;
41414d89e55SVijendar Mukunda 		rate->max = private->dai_config->acp_sdw.rate;
41514d89e55SVijendar Mukunda 		channels->min = private->dai_config->acp_sdw.channels;
41614d89e55SVijendar Mukunda 		channels->max = private->dai_config->acp_sdw.channels;
41714d89e55SVijendar Mukunda 
41814d89e55SVijendar Mukunda 		dev_dbg(component->dev,
41914d89e55SVijendar Mukunda 			"AMD_SDW rate_min: %d rate_max: %d\n", rate->min, rate->max);
42014d89e55SVijendar Mukunda 		dev_dbg(component->dev, "AMD_SDW channels_min: %d channels_max: %d\n",
42114d89e55SVijendar Mukunda 			channels->min, channels->max);
42214d89e55SVijendar Mukunda 		break;
423b243b437SRanjani Sridharan 	default:
424b243b437SRanjani Sridharan 		dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type);
425b243b437SRanjani Sridharan 		break;
426b243b437SRanjani Sridharan 	}
427b243b437SRanjani Sridharan 
428b243b437SRanjani Sridharan 	return 0;
429b243b437SRanjani Sridharan }
430b243b437SRanjani Sridharan 
4314123c24bSRanjani Sridharan const struct sof_ipc_pcm_ops ipc3_pcm_ops = {
432621fd48cSRanjani Sridharan 	.hw_params = sof_ipc3_pcm_hw_params,
4334123c24bSRanjani Sridharan 	.hw_free = sof_ipc3_pcm_hw_free,
434beac3f4cSRanjani Sridharan 	.trigger = sof_ipc3_pcm_trigger,
435b243b437SRanjani Sridharan 	.dai_link_fixup = sof_ipc3_pcm_dai_link_fixup,
4367d6f623cSRanjani Sridharan 	.reset_hw_params_during_stop = true,
43790a23530SRanjani Sridharan 	.d0i3_supported_in_s0ix = true,
4384123c24bSRanjani Sridharan };
439