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