xref: /openbmc/linux/sound/soc/sof/pcm.c (revision 1372a51b)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
7 //
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //
10 // PCM Layer, interface between ALSA and IPC.
11 //
12 
13 #include <linux/pm_runtime.h>
14 #include <sound/pcm_params.h>
15 #include <sound/sof.h>
16 #include "sof-priv.h"
17 #include "ops.h"
18 
19 #define DRV_NAME	"sof-audio-component"
20 
21 /* Create DMA buffer page table for DSP */
22 static int create_page_table(struct snd_soc_component *component,
23 			     struct snd_pcm_substream *substream,
24 			     unsigned char *dma_area, size_t size)
25 {
26 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
27 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
28 	struct snd_sof_pcm *spcm;
29 	struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
30 	int stream = substream->stream;
31 
32 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
33 	if (!spcm)
34 		return -EINVAL;
35 
36 	return snd_sof_create_page_table(sdev, dmab,
37 		spcm->stream[stream].page_table.area, size);
38 }
39 
40 static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream,
41 			      const struct sof_ipc_pcm_params_reply *reply)
42 {
43 	struct snd_sof_dev *sdev = spcm->sdev;
44 	/* validate offset */
45 	int ret = snd_sof_ipc_pcm_params(sdev, substream, reply);
46 
47 	if (ret < 0)
48 		dev_err(sdev->dev, "error: got wrong reply for PCM %d\n",
49 			spcm->pcm.pcm_id);
50 
51 	return ret;
52 }
53 
54 /*
55  * sof pcm period elapse work
56  */
57 static void sof_pcm_period_elapsed_work(struct work_struct *work)
58 {
59 	struct snd_sof_pcm_stream *sps =
60 		container_of(work, struct snd_sof_pcm_stream,
61 			     period_elapsed_work);
62 
63 	snd_pcm_period_elapsed(sps->substream);
64 }
65 
66 /*
67  * sof pcm period elapse, this could be called at irq thread context.
68  */
69 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
70 {
71 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 	struct snd_soc_component *component =
73 		snd_soc_rtdcom_lookup(rtd, DRV_NAME);
74 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
75 	struct snd_sof_pcm *spcm;
76 
77 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
78 	if (!spcm) {
79 		dev_err(sdev->dev,
80 			"error: period elapsed for unknown stream!\n");
81 		return;
82 	}
83 
84 	/*
85 	 * snd_pcm_period_elapsed() can be called in interrupt context
86 	 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
87 	 * when the PCM is done draining or xrun happened, a STOP IPC will
88 	 * then be sent and this IPC will hit IPC timeout.
89 	 * To avoid sending IPC before the previous IPC is handled, we
90 	 * schedule delayed work here to call the snd_pcm_period_elapsed().
91 	 */
92 	schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
93 }
94 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
95 
96 /* this may get called several times by oss emulation */
97 static int sof_pcm_hw_params(struct snd_soc_component *component,
98 			     struct snd_pcm_substream *substream,
99 			     struct snd_pcm_hw_params *params)
100 {
101 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
102 	struct snd_pcm_runtime *runtime = substream->runtime;
103 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
104 	struct snd_sof_pcm *spcm;
105 	struct sof_ipc_pcm_params pcm;
106 	struct sof_ipc_pcm_params_reply ipc_params_reply;
107 	int ret;
108 
109 	/* nothing to do for BE */
110 	if (rtd->dai_link->no_pcm)
111 		return 0;
112 
113 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
114 	if (!spcm)
115 		return -EINVAL;
116 
117 	dev_dbg(sdev->dev, "pcm: hw params stream %d dir %d\n",
118 		spcm->pcm.pcm_id, substream->stream);
119 
120 	memset(&pcm, 0, sizeof(pcm));
121 
122 	/* allocate audio buffer pages */
123 	ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
124 	if (ret < 0) {
125 		dev_err(sdev->dev, "error: could not allocate %d bytes for PCM %d\n",
126 			params_buffer_bytes(params), spcm->pcm.pcm_id);
127 		return ret;
128 	}
129 	if (ret) {
130 		/*
131 		 * ret == 1 means the buffer is changed
132 		 * create compressed page table for audio firmware
133 		 * ret == 0 means the buffer is not changed
134 		 * so no need to regenerate the page table
135 		 */
136 		ret = create_page_table(component, substream, runtime->dma_area,
137 					runtime->dma_bytes);
138 		if (ret < 0)
139 			return ret;
140 	}
141 
142 	/* number of pages should be rounded up */
143 	pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes);
144 
145 	/* set IPC PCM parameters */
146 	pcm.hdr.size = sizeof(pcm);
147 	pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
148 	pcm.comp_id = spcm->stream[substream->stream].comp_id;
149 	pcm.params.hdr.size = sizeof(pcm.params);
150 	pcm.params.buffer.phy_addr =
151 		spcm->stream[substream->stream].page_table.addr;
152 	pcm.params.buffer.size = runtime->dma_bytes;
153 	pcm.params.direction = substream->stream;
154 	pcm.params.sample_valid_bytes = params_width(params) >> 3;
155 	pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
156 	pcm.params.rate = params_rate(params);
157 	pcm.params.channels = params_channels(params);
158 	pcm.params.host_period_bytes = params_period_bytes(params);
159 
160 	/* container size */
161 	ret = snd_pcm_format_physical_width(params_format(params));
162 	if (ret < 0)
163 		return ret;
164 	pcm.params.sample_container_bytes = ret >> 3;
165 
166 	/* format */
167 	switch (params_format(params)) {
168 	case SNDRV_PCM_FORMAT_S16:
169 		pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
170 		break;
171 	case SNDRV_PCM_FORMAT_S24:
172 		pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
173 		break;
174 	case SNDRV_PCM_FORMAT_S32:
175 		pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
176 		break;
177 	case SNDRV_PCM_FORMAT_FLOAT:
178 		pcm.params.frame_fmt = SOF_IPC_FRAME_FLOAT;
179 		break;
180 	default:
181 		return -EINVAL;
182 	}
183 
184 	/* firmware already configured host stream */
185 	ret = snd_sof_pcm_platform_hw_params(sdev,
186 					     substream,
187 					     params,
188 					     &pcm.params);
189 	if (ret < 0) {
190 		dev_err(sdev->dev, "error: platform hw params failed\n");
191 		return ret;
192 	}
193 
194 	dev_dbg(sdev->dev, "stream_tag %d", pcm.params.stream_tag);
195 
196 	/* send IPC to the DSP */
197 	ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
198 				 &ipc_params_reply, sizeof(ipc_params_reply));
199 	if (ret < 0) {
200 		dev_err(sdev->dev, "error: hw params ipc failed for stream %d\n",
201 			pcm.params.stream_tag);
202 		return ret;
203 	}
204 
205 	ret = sof_pcm_dsp_params(spcm, substream, &ipc_params_reply);
206 	if (ret < 0)
207 		return ret;
208 
209 	spcm->prepared[substream->stream] = true;
210 
211 	/* save pcm hw_params */
212 	memcpy(&spcm->params[substream->stream], params, sizeof(*params));
213 
214 	return ret;
215 }
216 
217 static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream,
218 				struct snd_sof_dev *sdev,
219 				struct snd_sof_pcm *spcm)
220 {
221 	struct sof_ipc_stream stream;
222 	struct sof_ipc_reply reply;
223 	int ret;
224 
225 	stream.hdr.size = sizeof(stream);
226 	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
227 	stream.comp_id = spcm->stream[substream->stream].comp_id;
228 
229 	/* send IPC to the DSP */
230 	ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
231 				 sizeof(stream), &reply, sizeof(reply));
232 	if (!ret)
233 		spcm->prepared[substream->stream] = false;
234 
235 	return ret;
236 }
237 
238 static int sof_pcm_hw_free(struct snd_soc_component *component,
239 			   struct snd_pcm_substream *substream)
240 {
241 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
242 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
243 	struct snd_sof_pcm *spcm;
244 	int ret, err = 0;
245 
246 	/* nothing to do for BE */
247 	if (rtd->dai_link->no_pcm)
248 		return 0;
249 
250 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
251 	if (!spcm)
252 		return -EINVAL;
253 
254 	dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id,
255 		substream->stream);
256 
257 	if (spcm->prepared[substream->stream]) {
258 		ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
259 		if (ret < 0)
260 			err = ret;
261 	}
262 
263 	snd_pcm_lib_free_pages(substream);
264 
265 	cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
266 
267 	ret = snd_sof_pcm_platform_hw_free(sdev, substream);
268 	if (ret < 0) {
269 		dev_err(sdev->dev, "error: platform hw free failed\n");
270 		err = ret;
271 	}
272 
273 	return err;
274 }
275 
276 static int sof_pcm_prepare(struct snd_soc_component *component,
277 			   struct snd_pcm_substream *substream)
278 {
279 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
280 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
281 	struct snd_sof_pcm *spcm;
282 	int ret;
283 
284 	/* nothing to do for BE */
285 	if (rtd->dai_link->no_pcm)
286 		return 0;
287 
288 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
289 	if (!spcm)
290 		return -EINVAL;
291 
292 	if (spcm->prepared[substream->stream])
293 		return 0;
294 
295 	dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id,
296 		substream->stream);
297 
298 	/* set hw_params */
299 	ret = sof_pcm_hw_params(component,
300 				substream, &spcm->params[substream->stream]);
301 	if (ret < 0) {
302 		dev_err(sdev->dev, "error: set pcm hw_params after resume\n");
303 		return ret;
304 	}
305 
306 	return 0;
307 }
308 
309 /*
310  * FE dai link trigger actions are always executed in non-atomic context because
311  * they involve IPC's.
312  */
313 static int sof_pcm_trigger(struct snd_soc_component *component,
314 			   struct snd_pcm_substream *substream, int cmd)
315 {
316 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
317 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
318 	struct snd_sof_pcm *spcm;
319 	struct sof_ipc_stream stream;
320 	struct sof_ipc_reply reply;
321 	bool reset_hw_params = false;
322 	bool ipc_first = false;
323 	int ret;
324 
325 	/* nothing to do for BE */
326 	if (rtd->dai_link->no_pcm)
327 		return 0;
328 
329 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
330 	if (!spcm)
331 		return -EINVAL;
332 
333 	dev_dbg(sdev->dev, "pcm: trigger stream %d dir %d cmd %d\n",
334 		spcm->pcm.pcm_id, substream->stream, cmd);
335 
336 	stream.hdr.size = sizeof(stream);
337 	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG;
338 	stream.comp_id = spcm->stream[substream->stream].comp_id;
339 
340 	switch (cmd) {
341 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
342 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE;
343 		ipc_first = true;
344 		break;
345 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
346 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
347 		break;
348 	case SNDRV_PCM_TRIGGER_RESUME:
349 		if (spcm->stream[substream->stream].suspend_ignored) {
350 			/*
351 			 * this case will be triggered when INFO_RESUME is
352 			 * supported, no need to resume streams that remained
353 			 * enabled in D0ix.
354 			 */
355 			spcm->stream[substream->stream].suspend_ignored = false;
356 			return 0;
357 		}
358 
359 		/* set up hw_params */
360 		ret = sof_pcm_prepare(component, substream);
361 		if (ret < 0) {
362 			dev_err(sdev->dev,
363 				"error: failed to set up hw_params upon resume\n");
364 			return ret;
365 		}
366 
367 		/* fallthrough */
368 	case SNDRV_PCM_TRIGGER_START:
369 		if (spcm->stream[substream->stream].suspend_ignored) {
370 			/*
371 			 * This case will be triggered when INFO_RESUME is
372 			 * not supported, no need to re-start streams that
373 			 * remained enabled in D0ix.
374 			 */
375 			spcm->stream[substream->stream].suspend_ignored = false;
376 			return 0;
377 		}
378 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;
379 		break;
380 	case SNDRV_PCM_TRIGGER_SUSPEND:
381 		if (sdev->s0_suspend &&
382 		    spcm->stream[substream->stream].d0i3_compatible) {
383 			/*
384 			 * trap the event, not sending trigger stop to
385 			 * prevent the FW pipelines from being stopped,
386 			 * and mark the flag to ignore the upcoming DAPM
387 			 * PM events.
388 			 */
389 			spcm->stream[substream->stream].suspend_ignored = true;
390 			return 0;
391 		}
392 		/* fallthrough */
393 	case SNDRV_PCM_TRIGGER_STOP:
394 		stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
395 		ipc_first = true;
396 		reset_hw_params = true;
397 		break;
398 	default:
399 		dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd);
400 		return -EINVAL;
401 	}
402 
403 	/*
404 	 * DMA and IPC sequence is different for start and stop. Need to send
405 	 * STOP IPC before stop DMA
406 	 */
407 	if (!ipc_first)
408 		snd_sof_pcm_platform_trigger(sdev, substream, cmd);
409 
410 	/* send IPC to the DSP */
411 	ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
412 				 sizeof(stream), &reply, sizeof(reply));
413 
414 	/* need to STOP DMA even if STOP IPC failed */
415 	if (ipc_first)
416 		snd_sof_pcm_platform_trigger(sdev, substream, cmd);
417 
418 	/* free PCM if reset_hw_params is set and the STOP IPC is successful */
419 	if (!ret && reset_hw_params)
420 		ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
421 
422 	return ret;
423 }
424 
425 static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
426 					 struct snd_pcm_substream *substream)
427 {
428 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
429 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
430 	struct snd_sof_pcm *spcm;
431 	snd_pcm_uframes_t host, dai;
432 
433 	/* nothing to do for BE */
434 	if (rtd->dai_link->no_pcm)
435 		return 0;
436 
437 	/* use dsp ops pointer callback directly if set */
438 	if (sof_ops(sdev)->pcm_pointer)
439 		return sof_ops(sdev)->pcm_pointer(sdev, substream);
440 
441 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
442 	if (!spcm)
443 		return -EINVAL;
444 
445 	/* read position from DSP */
446 	host = bytes_to_frames(substream->runtime,
447 			       spcm->stream[substream->stream].posn.host_posn);
448 	dai = bytes_to_frames(substream->runtime,
449 			      spcm->stream[substream->stream].posn.dai_posn);
450 
451 	dev_dbg(sdev->dev, "PCM: stream %d dir %d DMA position %lu DAI position %lu\n",
452 		spcm->pcm.pcm_id, substream->stream, host, dai);
453 
454 	return host;
455 }
456 
457 static int sof_pcm_open(struct snd_soc_component *component,
458 			struct snd_pcm_substream *substream)
459 {
460 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
461 	struct snd_pcm_runtime *runtime = substream->runtime;
462 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
463 	const struct snd_sof_dsp_ops *ops = sof_ops(sdev);
464 	struct snd_sof_pcm *spcm;
465 	struct snd_soc_tplg_stream_caps *caps;
466 	int ret;
467 
468 	/* nothing to do for BE */
469 	if (rtd->dai_link->no_pcm)
470 		return 0;
471 
472 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
473 	if (!spcm)
474 		return -EINVAL;
475 
476 	dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id,
477 		substream->stream);
478 
479 	INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
480 		  sof_pcm_period_elapsed_work);
481 
482 	caps = &spcm->pcm.caps[substream->stream];
483 
484 	/* set any runtime constraints based on topology */
485 	snd_pcm_hw_constraint_step(substream->runtime, 0,
486 				   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
487 				   le32_to_cpu(caps->period_size_min));
488 	snd_pcm_hw_constraint_step(substream->runtime, 0,
489 				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
490 				   le32_to_cpu(caps->period_size_min));
491 
492 	/* set runtime config */
493 	runtime->hw.info = ops->hw_info; /* platform-specific */
494 
495 	runtime->hw.formats = le64_to_cpu(caps->formats);
496 	runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min);
497 	runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max);
498 	runtime->hw.periods_min = le32_to_cpu(caps->periods_min);
499 	runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
500 
501 	/*
502 	 * caps->buffer_size_min is not used since the
503 	 * snd_pcm_hardware structure only defines buffer_bytes_max
504 	 */
505 	runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
506 
507 	dev_dbg(sdev->dev, "period min %zd max %zd bytes\n",
508 		runtime->hw.period_bytes_min,
509 		runtime->hw.period_bytes_max);
510 	dev_dbg(sdev->dev, "period count %d max %d\n",
511 		runtime->hw.periods_min,
512 		runtime->hw.periods_max);
513 	dev_dbg(sdev->dev, "buffer max %zd bytes\n",
514 		runtime->hw.buffer_bytes_max);
515 
516 	/* set wait time - TODO: come from topology */
517 	substream->wait_time = 500;
518 
519 	spcm->stream[substream->stream].posn.host_posn = 0;
520 	spcm->stream[substream->stream].posn.dai_posn = 0;
521 	spcm->stream[substream->stream].substream = substream;
522 	spcm->prepared[substream->stream] = false;
523 
524 	ret = snd_sof_pcm_platform_open(sdev, substream);
525 	if (ret < 0)
526 		dev_err(sdev->dev, "error: pcm open failed %d\n", ret);
527 
528 	return ret;
529 }
530 
531 static int sof_pcm_close(struct snd_soc_component *component,
532 			 struct snd_pcm_substream *substream)
533 {
534 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
535 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
536 	struct snd_sof_pcm *spcm;
537 	int err;
538 
539 	/* nothing to do for BE */
540 	if (rtd->dai_link->no_pcm)
541 		return 0;
542 
543 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
544 	if (!spcm)
545 		return -EINVAL;
546 
547 	dev_dbg(sdev->dev, "pcm: close stream %d dir %d\n", spcm->pcm.pcm_id,
548 		substream->stream);
549 
550 	err = snd_sof_pcm_platform_close(sdev, substream);
551 	if (err < 0) {
552 		dev_err(sdev->dev, "error: pcm close failed %d\n",
553 			err);
554 		/*
555 		 * keep going, no point in preventing the close
556 		 * from happening
557 		 */
558 	}
559 
560 	return 0;
561 }
562 
563 /*
564  * Pre-allocate playback/capture audio buffer pages.
565  * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
566  * snd_pcm_lib_preallocate_free_for_all() is called by the core.
567  */
568 static int sof_pcm_new(struct snd_soc_component *component,
569 		       struct snd_soc_pcm_runtime *rtd)
570 {
571 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
572 	struct snd_sof_pcm *spcm;
573 	struct snd_pcm *pcm = rtd->pcm;
574 	struct snd_soc_tplg_stream_caps *caps;
575 	int stream = SNDRV_PCM_STREAM_PLAYBACK;
576 
577 	/* find SOF PCM for this RTD */
578 	spcm = snd_sof_find_spcm_dai(sdev, rtd);
579 	if (!spcm) {
580 		dev_warn(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
581 			 rtd->dai_link->id);
582 		return 0;
583 	}
584 
585 	dev_dbg(sdev->dev, "creating new PCM %s\n", spcm->pcm.pcm_name);
586 
587 	/* do we need to pre-allocate playback audio buffer pages */
588 	if (!spcm->pcm.playback)
589 		goto capture;
590 
591 	caps = &spcm->pcm.caps[stream];
592 
593 	/* pre-allocate playback audio buffer pages */
594 	dev_dbg(sdev->dev, "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
595 		caps->name, caps->buffer_size_min, caps->buffer_size_max);
596 
597 	snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream,
598 				      SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
599 				      le32_to_cpu(caps->buffer_size_min),
600 				      le32_to_cpu(caps->buffer_size_max));
601 capture:
602 	stream = SNDRV_PCM_STREAM_CAPTURE;
603 
604 	/* do we need to pre-allocate capture audio buffer pages */
605 	if (!spcm->pcm.capture)
606 		return 0;
607 
608 	caps = &spcm->pcm.caps[stream];
609 
610 	/* pre-allocate capture audio buffer pages */
611 	dev_dbg(sdev->dev, "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
612 		caps->name, caps->buffer_size_min, caps->buffer_size_max);
613 
614 	snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream,
615 				      SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
616 				      le32_to_cpu(caps->buffer_size_min),
617 				      le32_to_cpu(caps->buffer_size_max));
618 
619 	return 0;
620 }
621 
622 /* fixup the BE DAI link to match any values from topology */
623 static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
624 				  struct snd_pcm_hw_params *params)
625 {
626 	struct snd_interval *rate = hw_param_interval(params,
627 			SNDRV_PCM_HW_PARAM_RATE);
628 	struct snd_interval *channels = hw_param_interval(params,
629 						SNDRV_PCM_HW_PARAM_CHANNELS);
630 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
631 	struct snd_soc_component *component =
632 		snd_soc_rtdcom_lookup(rtd, DRV_NAME);
633 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
634 	struct snd_sof_dai *dai =
635 		snd_sof_find_dai(sdev, (char *)rtd->dai_link->name);
636 
637 	/* no topology exists for this BE, try a common configuration */
638 	if (!dai) {
639 		dev_warn(sdev->dev, "warning: no topology found for BE DAI %s config\n",
640 			 rtd->dai_link->name);
641 
642 		/*  set 48k, stereo, 16bits by default */
643 		rate->min = 48000;
644 		rate->max = 48000;
645 
646 		channels->min = 2;
647 		channels->max = 2;
648 
649 		snd_mask_none(fmt);
650 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
651 
652 		return 0;
653 	}
654 
655 	/* read format from topology */
656 	snd_mask_none(fmt);
657 
658 	switch (dai->comp_dai.config.frame_fmt) {
659 	case SOF_IPC_FRAME_S16_LE:
660 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
661 		break;
662 	case SOF_IPC_FRAME_S24_4LE:
663 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
664 		break;
665 	case SOF_IPC_FRAME_S32_LE:
666 		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
667 		break;
668 	default:
669 		dev_err(sdev->dev, "error: No available DAI format!\n");
670 		return -EINVAL;
671 	}
672 
673 	/* read rate and channels from topology */
674 	switch (dai->dai_config->type) {
675 	case SOF_DAI_INTEL_SSP:
676 		rate->min = dai->dai_config->ssp.fsync_rate;
677 		rate->max = dai->dai_config->ssp.fsync_rate;
678 		channels->min = dai->dai_config->ssp.tdm_slots;
679 		channels->max = dai->dai_config->ssp.tdm_slots;
680 
681 		dev_dbg(sdev->dev,
682 			"rate_min: %d rate_max: %d\n", rate->min, rate->max);
683 		dev_dbg(sdev->dev,
684 			"channels_min: %d channels_max: %d\n",
685 			channels->min, channels->max);
686 
687 		break;
688 	case SOF_DAI_INTEL_DMIC:
689 		/* DMIC only supports 16 or 32 bit formats */
690 		if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
691 			dev_err(sdev->dev,
692 				"error: invalid fmt %d for DAI type %d\n",
693 				dai->comp_dai.config.frame_fmt,
694 				dai->dai_config->type);
695 		}
696 		break;
697 	case SOF_DAI_INTEL_HDA:
698 		/* do nothing for HDA dai_link */
699 		break;
700 	case SOF_DAI_INTEL_ALH:
701 		/* do nothing for ALH dai_link */
702 		break;
703 	case SOF_DAI_IMX_ESAI:
704 		channels->min = dai->dai_config->esai.tdm_slots;
705 		channels->max = dai->dai_config->esai.tdm_slots;
706 
707 		dev_dbg(sdev->dev,
708 			"channels_min: %d channels_max: %d\n",
709 			channels->min, channels->max);
710 		break;
711 	default:
712 		dev_err(sdev->dev, "error: invalid DAI type %d\n",
713 			dai->dai_config->type);
714 		break;
715 	}
716 
717 	return 0;
718 }
719 
720 static int sof_pcm_probe(struct snd_soc_component *component)
721 {
722 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
723 	struct snd_sof_pdata *plat_data = sdev->pdata;
724 	const char *tplg_filename;
725 	int ret;
726 
727 	/* load the default topology */
728 	sdev->component = component;
729 
730 	tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
731 				       "%s/%s",
732 				       plat_data->tplg_filename_prefix,
733 				       plat_data->tplg_filename);
734 	if (!tplg_filename)
735 		return -ENOMEM;
736 
737 	ret = snd_sof_load_topology(sdev, tplg_filename);
738 	if (ret < 0) {
739 		dev_err(sdev->dev, "error: failed to load DSP topology %d\n",
740 			ret);
741 		return ret;
742 	}
743 
744 	/*
745 	 * Some platforms in SOF, ex: BYT, may not have their platform PM
746 	 * callbacks set. Increment the usage count so as to
747 	 * prevent the device from entering runtime suspend.
748 	 */
749 	if (!sof_ops(sdev)->runtime_suspend || !sof_ops(sdev)->runtime_resume)
750 		pm_runtime_get_noresume(sdev->dev);
751 
752 	return ret;
753 }
754 
755 static void sof_pcm_remove(struct snd_soc_component *component)
756 {
757 	/* remove topology */
758 	snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL);
759 }
760 
761 void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)
762 {
763 	struct snd_soc_component_driver *pd = &sdev->plat_drv;
764 	struct snd_sof_pdata *plat_data = sdev->pdata;
765 	const char *drv_name;
766 
767 	drv_name = plat_data->machine->drv_name;
768 
769 	pd->name = "sof-audio-component";
770 	pd->probe = sof_pcm_probe;
771 	pd->remove = sof_pcm_remove;
772 	pd->open = sof_pcm_open;
773 	pd->close = sof_pcm_close;
774 	pd->ioctl = snd_soc_pcm_lib_ioctl;
775 	pd->hw_params = sof_pcm_hw_params;
776 	pd->prepare = sof_pcm_prepare;
777 	pd->hw_free = sof_pcm_hw_free;
778 	pd->trigger = sof_pcm_trigger;
779 	pd->pointer = sof_pcm_pointer;
780 
781 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
782 	pd->compr_ops = &sof_compressed_ops;
783 #endif
784 	pd->pcm_construct = sof_pcm_new;
785 	pd->ignore_machine = drv_name;
786 	pd->be_hw_params_fixup = sof_pcm_dai_link_fixup;
787 	pd->be_pcm_base = SOF_BE_PCM_BASE;
788 	pd->use_dai_pcm_id = true;
789 	pd->topology_name_prefix = "sof";
790 
791 	 /* increment module refcount when a pcm is opened */
792 	pd->module_get_upon_open = 1;
793 }
794