xref: /openbmc/linux/sound/soc/sof/pcm.c (revision d37cf9b63113f13d742713881ce691fc615d8b3b)
1  // SPDX-License-Identifier: (GPL-2.0-only 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 <trace/events/sof.h>
17  #include "sof-of-dev.h"
18  #include "sof-priv.h"
19  #include "sof-audio.h"
20  #include "sof-utils.h"
21  #include "ops.h"
22  
23  /* Create DMA buffer page table for DSP */
create_page_table(struct snd_soc_component * component,struct snd_pcm_substream * substream,unsigned char * dma_area,size_t size)24  static int create_page_table(struct snd_soc_component *component,
25  			     struct snd_pcm_substream *substream,
26  			     unsigned char *dma_area, size_t size)
27  {
28  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
29  	struct snd_sof_pcm *spcm;
30  	struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
31  	int stream = substream->stream;
32  
33  	spcm = snd_sof_find_spcm_dai(component, rtd);
34  	if (!spcm)
35  		return -EINVAL;
36  
37  	return snd_sof_create_page_table(component->dev, dmab,
38  		spcm->stream[stream].page_table.area, size);
39  }
40  
41  /*
42   * sof pcm period elapse work
43   */
snd_sof_pcm_period_elapsed_work(struct work_struct * work)44  static void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
45  {
46  	struct snd_sof_pcm_stream *sps =
47  		container_of(work, struct snd_sof_pcm_stream,
48  			     period_elapsed_work);
49  
50  	snd_pcm_period_elapsed(sps->substream);
51  }
52  
snd_sof_pcm_init_elapsed_work(struct work_struct * work)53  void snd_sof_pcm_init_elapsed_work(struct work_struct *work)
54  {
55  	 INIT_WORK(work, snd_sof_pcm_period_elapsed_work);
56  }
57  
58  /*
59   * sof pcm period elapse, this could be called at irq thread context.
60   */
snd_sof_pcm_period_elapsed(struct snd_pcm_substream * substream)61  void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
62  {
63  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
64  	struct snd_soc_component *component =
65  		snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
66  	struct snd_sof_pcm *spcm;
67  
68  	spcm = snd_sof_find_spcm_dai(component, rtd);
69  	if (!spcm) {
70  		dev_err(component->dev,
71  			"error: period elapsed for unknown stream!\n");
72  		return;
73  	}
74  
75  	/*
76  	 * snd_pcm_period_elapsed() can be called in interrupt context
77  	 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
78  	 * when the PCM is done draining or xrun happened, a STOP IPC will
79  	 * then be sent and this IPC will hit IPC timeout.
80  	 * To avoid sending IPC before the previous IPC is handled, we
81  	 * schedule delayed work here to call the snd_pcm_period_elapsed().
82  	 */
83  	schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
84  }
85  EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
86  
87  static int
sof_pcm_setup_connected_widgets(struct snd_sof_dev * sdev,struct snd_soc_pcm_runtime * rtd,struct snd_sof_pcm * spcm,struct snd_pcm_hw_params * params,struct snd_sof_platform_stream_params * platform_params,int dir)88  sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
89  				struct snd_sof_pcm *spcm, struct snd_pcm_hw_params *params,
90  				struct snd_sof_platform_stream_params *platform_params, int dir)
91  {
92  	struct snd_soc_dai *dai;
93  	int ret, j;
94  
95  	/* query DAPM for list of connected widgets and set them up */
96  	for_each_rtd_cpu_dais(rtd, j, dai) {
97  		struct snd_soc_dapm_widget_list *list;
98  
99  		ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list,
100  							     dpcm_end_walk_at_be);
101  		if (ret < 0) {
102  			dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name,
103  				dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
104  			return ret;
105  		}
106  
107  		spcm->stream[dir].list = list;
108  
109  		ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir);
110  		if (ret < 0) {
111  			dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n",
112  				spcm->pcm.pcm_id, dir);
113  			spcm->stream[dir].list = NULL;
114  			snd_soc_dapm_dai_free_widgets(&list);
115  			return ret;
116  		}
117  	}
118  
119  	return 0;
120  }
121  
sof_pcm_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)122  static int sof_pcm_hw_params(struct snd_soc_component *component,
123  			     struct snd_pcm_substream *substream,
124  			     struct snd_pcm_hw_params *params)
125  {
126  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
127  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
128  	const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
129  	struct snd_sof_platform_stream_params platform_params = { 0 };
130  	struct snd_pcm_runtime *runtime = substream->runtime;
131  	struct snd_sof_pcm *spcm;
132  	int ret;
133  
134  	/* nothing to do for BE */
135  	if (rtd->dai_link->no_pcm)
136  		return 0;
137  
138  	spcm = snd_sof_find_spcm_dai(component, rtd);
139  	if (!spcm)
140  		return -EINVAL;
141  
142  	/*
143  	 * Handle repeated calls to hw_params() without free_pcm() in
144  	 * between. At least ALSA OSS emulation depends on this.
145  	 */
146  	if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) {
147  		ret = pcm_ops->hw_free(component, substream);
148  		if (ret < 0)
149  			return ret;
150  
151  		spcm->prepared[substream->stream] = false;
152  	}
153  
154  	dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
155  		spcm->pcm.pcm_id, substream->stream);
156  
157  	ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params);
158  	if (ret < 0) {
159  		dev_err(component->dev, "platform hw params failed\n");
160  		return ret;
161  	}
162  
163  	/* if this is a repeated hw_params without hw_free, skip setting up widgets */
164  	if (!spcm->stream[substream->stream].list) {
165  		ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, &platform_params,
166  						      substream->stream);
167  		if (ret < 0)
168  			return ret;
169  	}
170  
171  	/* create compressed page table for audio firmware */
172  	if (runtime->buffer_changed) {
173  		ret = create_page_table(component, substream, runtime->dma_area,
174  					runtime->dma_bytes);
175  
176  		if (ret < 0)
177  			return ret;
178  	}
179  
180  	if (pcm_ops && pcm_ops->hw_params) {
181  		ret = pcm_ops->hw_params(component, substream, params, &platform_params);
182  		if (ret < 0)
183  			return ret;
184  	}
185  
186  	spcm->prepared[substream->stream] = true;
187  
188  	/* save pcm hw_params */
189  	memcpy(&spcm->params[substream->stream], params, sizeof(*params));
190  
191  	return 0;
192  }
193  
sof_pcm_hw_free(struct snd_soc_component * component,struct snd_pcm_substream * substream)194  static int sof_pcm_hw_free(struct snd_soc_component *component,
195  			   struct snd_pcm_substream *substream)
196  {
197  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
198  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
199  	const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
200  	struct snd_sof_pcm *spcm;
201  	int ret, err = 0;
202  
203  	/* nothing to do for BE */
204  	if (rtd->dai_link->no_pcm)
205  		return 0;
206  
207  	spcm = snd_sof_find_spcm_dai(component, rtd);
208  	if (!spcm)
209  		return -EINVAL;
210  
211  	dev_dbg(component->dev, "pcm: free stream %d dir %d\n",
212  		spcm->pcm.pcm_id, substream->stream);
213  
214  	if (spcm->prepared[substream->stream]) {
215  		/* stop DMA first if needed */
216  		if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
217  			snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
218  
219  		/* free PCM in the DSP */
220  		if (pcm_ops && pcm_ops->hw_free) {
221  			ret = pcm_ops->hw_free(component, substream);
222  			if (ret < 0)
223  				err = ret;
224  		}
225  
226  		spcm->prepared[substream->stream] = false;
227  	}
228  
229  	/* reset DMA */
230  	ret = snd_sof_pcm_platform_hw_free(sdev, substream);
231  	if (ret < 0) {
232  		dev_err(component->dev, "error: platform hw free failed\n");
233  		err = ret;
234  	}
235  
236  	/* free the DAPM widget list */
237  	ret = sof_widget_list_free(sdev, spcm, substream->stream);
238  	if (ret < 0)
239  		err = ret;
240  
241  	cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
242  
243  	return err;
244  }
245  
sof_pcm_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)246  static int sof_pcm_prepare(struct snd_soc_component *component,
247  			   struct snd_pcm_substream *substream)
248  {
249  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
250  	struct snd_sof_pcm *spcm;
251  	int ret;
252  
253  	/* nothing to do for BE */
254  	if (rtd->dai_link->no_pcm)
255  		return 0;
256  
257  	spcm = snd_sof_find_spcm_dai(component, rtd);
258  	if (!spcm)
259  		return -EINVAL;
260  
261  	if (spcm->prepared[substream->stream])
262  		return 0;
263  
264  	dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n",
265  		spcm->pcm.pcm_id, substream->stream);
266  
267  	/* set hw_params */
268  	ret = sof_pcm_hw_params(component,
269  				substream, &spcm->params[substream->stream]);
270  	if (ret < 0) {
271  		dev_err(component->dev,
272  			"error: set pcm hw_params after resume\n");
273  		return ret;
274  	}
275  
276  	return 0;
277  }
278  
279  /*
280   * FE dai link trigger actions are always executed in non-atomic context because
281   * they involve IPC's.
282   */
sof_pcm_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)283  static int sof_pcm_trigger(struct snd_soc_component *component,
284  			   struct snd_pcm_substream *substream, int cmd)
285  {
286  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
287  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
288  	const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
289  	struct snd_sof_pcm *spcm;
290  	bool reset_hw_params = false;
291  	bool ipc_first = false;
292  	int ret = 0;
293  
294  	/* nothing to do for BE */
295  	if (rtd->dai_link->no_pcm)
296  		return 0;
297  
298  	spcm = snd_sof_find_spcm_dai(component, rtd);
299  	if (!spcm)
300  		return -EINVAL;
301  
302  	dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n",
303  		spcm->pcm.pcm_id, substream->stream, cmd);
304  
305  	switch (cmd) {
306  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
307  		ipc_first = true;
308  		break;
309  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
310  		if (pcm_ops && pcm_ops->ipc_first_on_start)
311  			ipc_first = true;
312  		break;
313  	case SNDRV_PCM_TRIGGER_START:
314  		if (spcm->stream[substream->stream].suspend_ignored) {
315  			/*
316  			 * This case will be triggered when INFO_RESUME is
317  			 * not supported, no need to re-start streams that
318  			 * remained enabled in D0ix.
319  			 */
320  			spcm->stream[substream->stream].suspend_ignored = false;
321  			return 0;
322  		}
323  
324  		if (pcm_ops && pcm_ops->ipc_first_on_start)
325  			ipc_first = true;
326  		break;
327  	case SNDRV_PCM_TRIGGER_SUSPEND:
328  		/*
329  		 * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
330  		 * D0I3-compatible streams to keep the firmware pipeline running
331  		 */
332  		if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix &&
333  		    sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
334  		    spcm->stream[substream->stream].d0i3_compatible) {
335  			spcm->stream[substream->stream].suspend_ignored = true;
336  			return 0;
337  		}
338  
339  		/* On suspend the DMA must be stopped in DSPless mode */
340  		if (sdev->dspless_mode_selected)
341  			reset_hw_params = true;
342  
343  		fallthrough;
344  	case SNDRV_PCM_TRIGGER_STOP:
345  		ipc_first = true;
346  		if (pcm_ops && pcm_ops->reset_hw_params_during_stop)
347  			reset_hw_params = true;
348  		break;
349  	default:
350  		dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd);
351  		return -EINVAL;
352  	}
353  
354  	if (!ipc_first)
355  		snd_sof_pcm_platform_trigger(sdev, substream, cmd);
356  
357  	if (pcm_ops && pcm_ops->trigger)
358  		ret = pcm_ops->trigger(component, substream, cmd);
359  
360  	switch (cmd) {
361  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
362  	case SNDRV_PCM_TRIGGER_START:
363  		/* invoke platform trigger to start DMA only if pcm_ops is successful */
364  		if (ipc_first && !ret)
365  			snd_sof_pcm_platform_trigger(sdev, substream, cmd);
366  		break;
367  	case SNDRV_PCM_TRIGGER_SUSPEND:
368  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
369  	case SNDRV_PCM_TRIGGER_STOP:
370  		/* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */
371  		if (!pcm_ops || !pcm_ops->platform_stop_during_hw_free)
372  			snd_sof_pcm_platform_trigger(sdev, substream, cmd);
373  		break;
374  	default:
375  		break;
376  	}
377  
378  	/* free PCM if reset_hw_params is set and the STOP IPC is successful */
379  	if (!ret && reset_hw_params)
380  		ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, false);
381  
382  	return ret;
383  }
384  
sof_pcm_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)385  static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
386  					 struct snd_pcm_substream *substream)
387  {
388  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
389  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
390  	struct snd_sof_pcm *spcm;
391  	snd_pcm_uframes_t host, dai;
392  
393  	/* nothing to do for BE */
394  	if (rtd->dai_link->no_pcm)
395  		return 0;
396  
397  	/* use dsp ops pointer callback directly if set */
398  	if (sof_ops(sdev)->pcm_pointer)
399  		return sof_ops(sdev)->pcm_pointer(sdev, substream);
400  
401  	spcm = snd_sof_find_spcm_dai(component, rtd);
402  	if (!spcm)
403  		return -EINVAL;
404  
405  	/* read position from DSP */
406  	host = bytes_to_frames(substream->runtime,
407  			       spcm->stream[substream->stream].posn.host_posn);
408  	dai = bytes_to_frames(substream->runtime,
409  			      spcm->stream[substream->stream].posn.dai_posn);
410  
411  	trace_sof_pcm_pointer_position(sdev, spcm, substream, host, dai);
412  
413  	return host;
414  }
415  
sof_pcm_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)416  static int sof_pcm_open(struct snd_soc_component *component,
417  			struct snd_pcm_substream *substream)
418  {
419  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
420  	struct snd_pcm_runtime *runtime = substream->runtime;
421  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
422  	struct snd_sof_dsp_ops *ops = sof_ops(sdev);
423  	struct snd_sof_pcm *spcm;
424  	struct snd_soc_tplg_stream_caps *caps;
425  	int ret;
426  
427  	/* nothing to do for BE */
428  	if (rtd->dai_link->no_pcm)
429  		return 0;
430  
431  	spcm = snd_sof_find_spcm_dai(component, rtd);
432  	if (!spcm)
433  		return -EINVAL;
434  
435  	dev_dbg(component->dev, "pcm: open stream %d dir %d\n",
436  		spcm->pcm.pcm_id, substream->stream);
437  
438  
439  	caps = &spcm->pcm.caps[substream->stream];
440  
441  	/* set runtime config */
442  	runtime->hw.info = ops->hw_info; /* platform-specific */
443  
444  	/* set any runtime constraints based on topology */
445  	runtime->hw.formats = le64_to_cpu(caps->formats);
446  	runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min);
447  	runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max);
448  	runtime->hw.periods_min = le32_to_cpu(caps->periods_min);
449  	runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
450  
451  	/*
452  	 * caps->buffer_size_min is not used since the
453  	 * snd_pcm_hardware structure only defines buffer_bytes_max
454  	 */
455  	runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
456  
457  	dev_dbg(component->dev, "period min %zd max %zd bytes\n",
458  		runtime->hw.period_bytes_min,
459  		runtime->hw.period_bytes_max);
460  	dev_dbg(component->dev, "period count %d max %d\n",
461  		runtime->hw.periods_min,
462  		runtime->hw.periods_max);
463  	dev_dbg(component->dev, "buffer max %zd bytes\n",
464  		runtime->hw.buffer_bytes_max);
465  
466  	/* set wait time - TODO: come from topology */
467  	substream->wait_time = 500;
468  
469  	spcm->stream[substream->stream].posn.host_posn = 0;
470  	spcm->stream[substream->stream].posn.dai_posn = 0;
471  	spcm->stream[substream->stream].substream = substream;
472  	spcm->prepared[substream->stream] = false;
473  
474  	ret = snd_sof_pcm_platform_open(sdev, substream);
475  	if (ret < 0)
476  		dev_err(component->dev, "error: pcm open failed %d\n", ret);
477  
478  	return ret;
479  }
480  
sof_pcm_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)481  static int sof_pcm_close(struct snd_soc_component *component,
482  			 struct snd_pcm_substream *substream)
483  {
484  	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
485  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
486  	struct snd_sof_pcm *spcm;
487  	int err;
488  
489  	/* nothing to do for BE */
490  	if (rtd->dai_link->no_pcm)
491  		return 0;
492  
493  	spcm = snd_sof_find_spcm_dai(component, rtd);
494  	if (!spcm)
495  		return -EINVAL;
496  
497  	dev_dbg(component->dev, "pcm: close stream %d dir %d\n",
498  		spcm->pcm.pcm_id, substream->stream);
499  
500  	err = snd_sof_pcm_platform_close(sdev, substream);
501  	if (err < 0) {
502  		dev_err(component->dev, "error: pcm close failed %d\n",
503  			err);
504  		/*
505  		 * keep going, no point in preventing the close
506  		 * from happening
507  		 */
508  	}
509  
510  	spcm->stream[substream->stream].substream = NULL;
511  
512  	return 0;
513  }
514  
515  /*
516   * Pre-allocate playback/capture audio buffer pages.
517   * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
518   * snd_pcm_lib_preallocate_free_for_all() is called by the core.
519   */
sof_pcm_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)520  static int sof_pcm_new(struct snd_soc_component *component,
521  		       struct snd_soc_pcm_runtime *rtd)
522  {
523  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
524  	struct snd_sof_pcm *spcm;
525  	struct snd_pcm *pcm = rtd->pcm;
526  	struct snd_soc_tplg_stream_caps *caps;
527  	int stream = SNDRV_PCM_STREAM_PLAYBACK;
528  
529  	/* find SOF PCM for this RTD */
530  	spcm = snd_sof_find_spcm_dai(component, rtd);
531  	if (!spcm) {
532  		dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n",
533  			 rtd->dai_link->id);
534  		return 0;
535  	}
536  
537  	dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name);
538  
539  	/* do we need to pre-allocate playback audio buffer pages */
540  	if (!spcm->pcm.playback)
541  		goto capture;
542  
543  	caps = &spcm->pcm.caps[stream];
544  
545  	/* pre-allocate playback audio buffer pages */
546  	dev_dbg(component->dev,
547  		"spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
548  		caps->name, caps->buffer_size_min, caps->buffer_size_max);
549  
550  	if (!pcm->streams[stream].substream) {
551  		dev_err(component->dev, "error: NULL playback substream!\n");
552  		return -EINVAL;
553  	}
554  
555  	snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
556  				   SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
557  				   0, le32_to_cpu(caps->buffer_size_max));
558  capture:
559  	stream = SNDRV_PCM_STREAM_CAPTURE;
560  
561  	/* do we need to pre-allocate capture audio buffer pages */
562  	if (!spcm->pcm.capture)
563  		return 0;
564  
565  	caps = &spcm->pcm.caps[stream];
566  
567  	/* pre-allocate capture audio buffer pages */
568  	dev_dbg(component->dev,
569  		"spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
570  		caps->name, caps->buffer_size_min, caps->buffer_size_max);
571  
572  	if (!pcm->streams[stream].substream) {
573  		dev_err(component->dev, "error: NULL capture substream!\n");
574  		return -EINVAL;
575  	}
576  
577  	snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
578  				   SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
579  				   0, le32_to_cpu(caps->buffer_size_max));
580  
581  	return 0;
582  }
583  
584  /* fixup the BE DAI link to match any values from topology */
sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)585  int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params)
586  {
587  	struct snd_interval *rate = hw_param_interval(params,
588  			SNDRV_PCM_HW_PARAM_RATE);
589  	struct snd_interval *channels = hw_param_interval(params,
590  						SNDRV_PCM_HW_PARAM_CHANNELS);
591  	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
592  	struct snd_soc_component *component =
593  		snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
594  	struct snd_sof_dai *dai =
595  		snd_sof_find_dai(component, (char *)rtd->dai_link->name);
596  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
597  	const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
598  
599  	/* no topology exists for this BE, try a common configuration */
600  	if (!dai) {
601  		dev_warn(component->dev,
602  			 "warning: no topology found for BE DAI %s config\n",
603  			 rtd->dai_link->name);
604  
605  		/*  set 48k, stereo, 16bits by default */
606  		rate->min = 48000;
607  		rate->max = 48000;
608  
609  		channels->min = 2;
610  		channels->max = 2;
611  
612  		snd_mask_none(fmt);
613  		snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
614  
615  		return 0;
616  	}
617  
618  	if (pcm_ops && pcm_ops->dai_link_fixup)
619  		return pcm_ops->dai_link_fixup(rtd, params);
620  
621  	return 0;
622  }
623  EXPORT_SYMBOL(sof_pcm_dai_link_fixup);
624  
sof_pcm_probe(struct snd_soc_component * component)625  static int sof_pcm_probe(struct snd_soc_component *component)
626  {
627  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
628  	struct snd_sof_pdata *plat_data = sdev->pdata;
629  	const char *tplg_filename;
630  	int ret;
631  
632  	/*
633  	 * make sure the device is pm_runtime_active before loading the
634  	 * topology and initiating IPC or bus transactions
635  	 */
636  	ret = pm_runtime_resume_and_get(component->dev);
637  	if (ret < 0 && ret != -EACCES)
638  		return ret;
639  
640  	/* load the default topology */
641  	sdev->component = component;
642  
643  	tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
644  				       "%s/%s",
645  				       plat_data->tplg_filename_prefix,
646  				       plat_data->tplg_filename);
647  	if (!tplg_filename) {
648  		ret = -ENOMEM;
649  		goto pm_error;
650  	}
651  
652  	ret = snd_sof_load_topology(component, tplg_filename);
653  	if (ret < 0)
654  		dev_err(component->dev, "error: failed to load DSP topology %d\n",
655  			ret);
656  
657  pm_error:
658  	pm_runtime_mark_last_busy(component->dev);
659  	pm_runtime_put_autosuspend(component->dev);
660  
661  	return ret;
662  }
663  
sof_pcm_remove(struct snd_soc_component * component)664  static void sof_pcm_remove(struct snd_soc_component *component)
665  {
666  	/* remove topology */
667  	snd_soc_tplg_component_remove(component);
668  }
669  
sof_pcm_ack(struct snd_soc_component * component,struct snd_pcm_substream * substream)670  static int sof_pcm_ack(struct snd_soc_component *component,
671  		       struct snd_pcm_substream *substream)
672  {
673  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
674  
675  	return snd_sof_pcm_platform_ack(sdev, substream);
676  }
677  
sof_pcm_delay(struct snd_soc_component * component,struct snd_pcm_substream * substream)678  static snd_pcm_sframes_t sof_pcm_delay(struct snd_soc_component *component,
679  				       struct snd_pcm_substream *substream)
680  {
681  	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
682  	const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
683  
684  	if (pcm_ops && pcm_ops->delay)
685  		return pcm_ops->delay(component, substream);
686  
687  	return 0;
688  }
689  
snd_sof_new_platform_drv(struct snd_sof_dev * sdev)690  void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)
691  {
692  	struct snd_soc_component_driver *pd = &sdev->plat_drv;
693  	struct snd_sof_pdata *plat_data = sdev->pdata;
694  	const char *drv_name;
695  
696  	if (plat_data->machine)
697  		drv_name = plat_data->machine->drv_name;
698  	else if (plat_data->of_machine)
699  		drv_name = plat_data->of_machine->drv_name;
700  	else
701  		drv_name = NULL;
702  
703  	pd->name = "sof-audio-component";
704  	pd->probe = sof_pcm_probe;
705  	pd->remove = sof_pcm_remove;
706  	pd->open = sof_pcm_open;
707  	pd->close = sof_pcm_close;
708  	pd->hw_params = sof_pcm_hw_params;
709  	pd->prepare = sof_pcm_prepare;
710  	pd->hw_free = sof_pcm_hw_free;
711  	pd->trigger = sof_pcm_trigger;
712  	pd->pointer = sof_pcm_pointer;
713  	pd->ack = sof_pcm_ack;
714  	pd->delay = sof_pcm_delay;
715  
716  #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
717  	pd->compress_ops = &sof_compressed_ops;
718  #endif
719  
720  	pd->pcm_construct = sof_pcm_new;
721  	pd->ignore_machine = drv_name;
722  	pd->be_pcm_base = SOF_BE_PCM_BASE;
723  	pd->use_dai_pcm_id = true;
724  	pd->topology_name_prefix = "sof";
725  
726  	 /* increment module refcount when a pcm is opened */
727  	pd->module_get_upon_open = 1;
728  
729  	pd->legacy_dai_naming = 1;
730  
731  	/*
732  	 * The fixup is only needed when the DSP is in use as with the DSPless
733  	 * mode we are directly using the audio interface
734  	 */
735  	if (!sdev->dspless_mode_selected)
736  		pd->be_hw_params_fixup = sof_pcm_dai_link_fixup;
737  }
738