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