1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
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.
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
10 // PCM Layer, interface between ALSA and IPC.
13 #include <linux/pm_runtime.h>
14 #include <sound/pcm_params.h>
15 #include <sound/sof.h>
17 #include "sof-audio.h"
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
)
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
;
30 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
34 return snd_sof_create_page_table(component
->dev
, dmab
,
35 spcm
->stream
[stream
].page_table
.area
, size
);
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
)
41 struct snd_soc_component
*scomp
= spcm
->scomp
;
42 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
45 int ret
= snd_sof_ipc_pcm_params(sdev
, substream
, reply
);
48 dev_err(scomp
->dev
, "error: got wrong reply for PCM %d\n",
55 * sof pcm period elapse work
57 static void sof_pcm_period_elapsed_work(struct work_struct
*work
)
59 struct snd_sof_pcm_stream
*sps
=
60 container_of(work
, struct snd_sof_pcm_stream
,
63 snd_pcm_period_elapsed(sps
->substream
);
67 * sof pcm period elapse, this could be called at irq thread context.
69 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream
*substream
)
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
;
76 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
78 dev_err(component
->dev
,
79 "error: period elapsed for unknown stream!\n");
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().
91 schedule_work(&spcm
->stream
[substream
->stream
].period_elapsed_work
);
93 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed
);
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
)
99 struct sof_ipc_stream stream
;
100 struct sof_ipc_reply reply
;
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
;
107 /* send IPC to the DSP */
108 ret
= sof_ipc_tx_message(sdev
->ipc
, stream
.hdr
.cmd
, &stream
,
109 sizeof(stream
), &reply
, sizeof(reply
));
111 spcm
->prepared
[substream
->stream
] = false;
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
)
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
;
128 /* nothing to do for BE */
129 if (rtd
->dai_link
->no_pcm
)
132 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
137 * Handle repeated calls to hw_params() without free_pcm() in
138 * between. At least ALSA OSS emulation depends on this.
140 if (spcm
->prepared
[substream
->stream
]) {
141 ret
= sof_pcm_dsp_pcm_free(substream
, sdev
, spcm
);
146 dev_dbg(component
->dev
, "pcm: hw params stream %d dir %d\n",
147 spcm
->pcm
.pcm_id
, substream
->stream
);
149 memset(&pcm
, 0, sizeof(pcm
));
151 /* create compressed page table for audio firmware */
152 if (runtime
->buffer_changed
) {
153 ret
= create_page_table(component
, substream
, runtime
->dma_area
,
159 /* number of pages should be rounded up */
160 pcm
.params
.buffer
.pages
= PFN_UP(runtime
->dma_bytes
);
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
);
178 ret
= snd_pcm_format_physical_width(params_format(params
));
181 pcm
.params
.sample_container_bytes
= ret
>> 3;
184 switch (params_format(params
)) {
185 case SNDRV_PCM_FORMAT_S16
:
186 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S16_LE
;
188 case SNDRV_PCM_FORMAT_S24
:
189 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S24_4LE
;
191 case SNDRV_PCM_FORMAT_S32
:
192 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S32_LE
;
194 case SNDRV_PCM_FORMAT_FLOAT
:
195 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_FLOAT
;
201 /* firmware already configured host stream */
202 ret
= snd_sof_pcm_platform_hw_params(sdev
,
207 dev_err(component
->dev
, "error: platform hw params failed\n");
211 dev_dbg(component
->dev
, "stream_tag %d", pcm
.params
.stream_tag
);
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
));
217 dev_err(component
->dev
, "error: hw params ipc failed for stream %d\n",
218 pcm
.params
.stream_tag
);
222 ret
= sof_pcm_dsp_params(spcm
, substream
, &ipc_params_reply
);
226 spcm
->prepared
[substream
->stream
] = true;
228 /* save pcm hw_params */
229 memcpy(&spcm
->params
[substream
->stream
], params
, sizeof(*params
));
234 static int sof_pcm_hw_free(struct snd_soc_component
*component
,
235 struct snd_pcm_substream
*substream
)
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
;
242 /* nothing to do for BE */
243 if (rtd
->dai_link
->no_pcm
)
246 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
250 dev_dbg(component
->dev
, "pcm: free stream %d dir %d\n",
251 spcm
->pcm
.pcm_id
, substream
->stream
);
253 if (spcm
->prepared
[substream
->stream
]) {
254 ret
= sof_pcm_dsp_pcm_free(substream
, sdev
, spcm
);
259 cancel_work_sync(&spcm
->stream
[substream
->stream
].period_elapsed_work
);
261 ret
= snd_sof_pcm_platform_hw_free(sdev
, substream
);
263 dev_err(component
->dev
, "error: platform hw free failed\n");
270 static int sof_pcm_prepare(struct snd_soc_component
*component
,
271 struct snd_pcm_substream
*substream
)
273 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
274 struct snd_sof_pcm
*spcm
;
277 /* nothing to do for BE */
278 if (rtd
->dai_link
->no_pcm
)
281 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
285 if (spcm
->prepared
[substream
->stream
])
288 dev_dbg(component
->dev
, "pcm: prepare stream %d dir %d\n",
289 spcm
->pcm
.pcm_id
, substream
->stream
);
292 ret
= sof_pcm_hw_params(component
,
293 substream
, &spcm
->params
[substream
->stream
]);
295 dev_err(component
->dev
,
296 "error: set pcm hw_params after resume\n");
304 * FE dai link trigger actions are always executed in non-atomic context because
305 * they involve IPC's.
307 static int sof_pcm_trigger(struct snd_soc_component
*component
,
308 struct snd_pcm_substream
*substream
, int cmd
)
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;
319 /* nothing to do for BE */
320 if (rtd
->dai_link
->no_pcm
)
323 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
327 dev_dbg(component
->dev
, "pcm: trigger stream %d dir %d cmd %d\n",
328 spcm
->pcm
.pcm_id
, substream
->stream
, cmd
);
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
;
335 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
336 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_PAUSE
;
339 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
340 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_RELEASE
;
342 case SNDRV_PCM_TRIGGER_RESUME
:
343 if (spcm
->stream
[substream
->stream
].suspend_ignored
) {
345 * this case will be triggered when INFO_RESUME is
346 * supported, no need to resume streams that remained
349 spcm
->stream
[substream
->stream
].suspend_ignored
= false;
353 /* set up hw_params */
354 ret
= sof_pcm_prepare(component
, substream
);
356 dev_err(component
->dev
,
357 "error: failed to set up hw_params upon resume\n");
362 case SNDRV_PCM_TRIGGER_START
:
363 if (spcm
->stream
[substream
->stream
].suspend_ignored
) {
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.
369 spcm
->stream
[substream
->stream
].suspend_ignored
= false;
372 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_START
;
374 case SNDRV_PCM_TRIGGER_SUSPEND
:
375 if (sdev
->s0_suspend
&&
376 spcm
->stream
[substream
->stream
].d0i3_compatible
) {
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
383 spcm
->stream
[substream
->stream
].suspend_ignored
= true;
387 case SNDRV_PCM_TRIGGER_STOP
:
388 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_STOP
;
390 reset_hw_params
= true;
393 dev_err(component
->dev
, "error: unhandled trigger cmd %d\n",
399 * DMA and IPC sequence is different for start and stop. Need to send
400 * STOP IPC before stop DMA
403 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
405 /* send IPC to the DSP */
406 ret
= sof_ipc_tx_message(sdev
->ipc
, stream
.hdr
.cmd
, &stream
,
407 sizeof(stream
), &reply
, sizeof(reply
));
409 /* need to STOP DMA even if STOP IPC failed */
411 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
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
);
420 static snd_pcm_uframes_t
sof_pcm_pointer(struct snd_soc_component
*component
,
421 struct snd_pcm_substream
*substream
)
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
;
428 /* nothing to do for BE */
429 if (rtd
->dai_link
->no_pcm
)
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
);
436 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
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
);
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
);
453 static int sof_pcm_open(struct snd_soc_component
*component
,
454 struct snd_pcm_substream
*substream
)
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
;
464 /* nothing to do for BE */
465 if (rtd
->dai_link
->no_pcm
)
468 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
472 dev_dbg(component
->dev
, "pcm: open stream %d dir %d\n",
473 spcm
->pcm
.pcm_id
, substream
->stream
);
475 INIT_WORK(&spcm
->stream
[substream
->stream
].period_elapsed_work
,
476 sof_pcm_period_elapsed_work
);
478 caps
= &spcm
->pcm
.caps
[substream
->stream
];
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
));
488 /* set runtime config */
489 runtime
->hw
.info
= ops
->hw_info
; /* platform-specific */
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
);
498 * caps->buffer_size_min is not used since the
499 * snd_pcm_hardware structure only defines buffer_bytes_max
501 runtime
->hw
.buffer_bytes_max
= le32_to_cpu(caps
->buffer_size_max
);
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
);
512 /* set wait time - TODO: come from topology */
513 substream
->wait_time
= 500;
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;
520 ret
= snd_sof_pcm_platform_open(sdev
, substream
);
522 dev_err(component
->dev
, "error: pcm open failed %d\n", ret
);
527 static int sof_pcm_close(struct snd_soc_component
*component
,
528 struct snd_pcm_substream
*substream
)
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
;
535 /* nothing to do for BE */
536 if (rtd
->dai_link
->no_pcm
)
539 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
543 dev_dbg(component
->dev
, "pcm: close stream %d dir %d\n",
544 spcm
->pcm
.pcm_id
, substream
->stream
);
546 err
= snd_sof_pcm_platform_close(sdev
, substream
);
548 dev_err(component
->dev
, "error: pcm close failed %d\n",
551 * keep going, no point in preventing the close
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.
564 static int sof_pcm_new(struct snd_soc_component
*component
,
565 struct snd_soc_pcm_runtime
*rtd
)
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
;
573 /* find SOF PCM for this RTD */
574 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
576 dev_warn(component
->dev
, "warn: can't find PCM with DAI ID %d\n",
581 dev_dbg(component
->dev
, "creating new PCM %s\n", spcm
->pcm
.pcm_name
);
583 /* do we need to pre-allocate playback audio buffer pages */
584 if (!spcm
->pcm
.playback
)
587 caps
= &spcm
->pcm
.caps
[stream
];
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
);
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
));
599 stream
= SNDRV_PCM_STREAM_CAPTURE
;
601 /* do we need to pre-allocate capture audio buffer pages */
602 if (!spcm
->pcm
.capture
)
605 caps
= &spcm
->pcm
.caps
[stream
];
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
);
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
));
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
)
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
);
634 /* no topology exists for this BE, try a common configuration */
636 dev_warn(component
->dev
,
637 "warning: no topology found for BE DAI %s config\n",
638 rtd
->dai_link
->name
);
640 /* set 48k, stereo, 16bits by default */
648 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S16_LE
);
653 /* read format from topology */
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
);
660 case SOF_IPC_FRAME_S24_4LE
:
661 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S24_LE
);
663 case SOF_IPC_FRAME_S32_LE
:
664 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S32_LE
);
667 dev_err(component
->dev
, "error: No available DAI format!\n");
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
;
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
);
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
);
695 case SOF_DAI_INTEL_HDA
:
696 /* do nothing for HDA dai_link */
698 case SOF_DAI_INTEL_ALH
:
699 /* do nothing for ALH dai_link */
701 case SOF_DAI_IMX_ESAI
:
702 channels
->min
= dai
->dai_config
->esai
.tdm_slots
;
703 channels
->max
= dai
->dai_config
->esai
.tdm_slots
;
705 dev_dbg(component
->dev
,
706 "channels_min: %d channels_max: %d\n",
707 channels
->min
, channels
->max
);
709 case SOF_DAI_IMX_SAI
:
710 channels
->min
= dai
->dai_config
->sai
.tdm_slots
;
711 channels
->max
= dai
->dai_config
->sai
.tdm_slots
;
713 dev_dbg(component
->dev
,
714 "channels_min: %d channels_max: %d\n",
715 channels
->min
, channels
->max
);
718 dev_err(component
->dev
, "error: invalid DAI type %d\n",
719 dai
->dai_config
->type
);
726 static int sof_pcm_probe(struct snd_soc_component
*component
)
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
;
733 /* load the default topology */
734 sdev
->component
= component
;
736 tplg_filename
= devm_kasprintf(sdev
->dev
, GFP_KERNEL
,
738 plat_data
->tplg_filename_prefix
,
739 plat_data
->tplg_filename
);
743 ret
= snd_sof_load_topology(component
, tplg_filename
);
745 dev_err(component
->dev
, "error: failed to load DSP topology %d\n",
753 static void sof_pcm_remove(struct snd_soc_component
*component
)
755 /* remove topology */
756 snd_soc_tplg_component_remove(component
, SND_SOC_TPLG_INDEX_ALL
);
759 void snd_sof_new_platform_drv(struct snd_sof_dev
*sdev
)
761 struct snd_soc_component_driver
*pd
= &sdev
->plat_drv
;
762 struct snd_sof_pdata
*plat_data
= sdev
->pdata
;
763 const char *drv_name
;
765 drv_name
= plat_data
->machine
->drv_name
;
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
;
778 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
779 pd
->compr_ops
= &sof_compressed_ops
;
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";
788 /* increment module refcount when a pcm is opened */
789 pd
->module_get_upon_open
= 1;