1 // SPDX-License-Identifier: (GPL-2.0-only 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"
19 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
23 /* Create DMA buffer page table for DSP */
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
)
28 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
29 struct snd_sof_pcm
*spcm
;
30 struct snd_dma_buffer
*dmab
= snd_pcm_get_dma_buf(substream
);
31 int stream
= substream
->stream
;
33 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
37 return snd_sof_create_page_table(component
->dev
, dmab
,
38 spcm
->stream
[stream
].page_table
.area
, size
);
41 static int sof_pcm_dsp_params(struct snd_sof_pcm
*spcm
, struct snd_pcm_substream
*substream
,
42 const struct sof_ipc_pcm_params_reply
*reply
)
44 struct snd_soc_component
*scomp
= spcm
->scomp
;
45 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
48 int ret
= snd_sof_ipc_pcm_params(sdev
, substream
, reply
);
51 dev_err(scomp
->dev
, "error: got wrong reply for PCM %d\n",
58 * sof pcm period elapse work
60 void snd_sof_pcm_period_elapsed_work(struct work_struct
*work
)
62 struct snd_sof_pcm_stream
*sps
=
63 container_of(work
, struct snd_sof_pcm_stream
,
66 snd_pcm_period_elapsed(sps
->substream
);
70 * sof pcm period elapse, this could be called at irq thread context.
72 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream
*substream
)
74 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
75 struct snd_soc_component
*component
=
76 snd_soc_rtdcom_lookup(rtd
, SOF_AUDIO_PCM_DRV_NAME
);
77 struct snd_sof_pcm
*spcm
;
79 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
81 dev_err(component
->dev
,
82 "error: period elapsed for unknown stream!\n");
87 * snd_pcm_period_elapsed() can be called in interrupt context
88 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
89 * when the PCM is done draining or xrun happened, a STOP IPC will
90 * then be sent and this IPC will hit IPC timeout.
91 * To avoid sending IPC before the previous IPC is handled, we
92 * schedule delayed work here to call the snd_pcm_period_elapsed().
94 schedule_work(&spcm
->stream
[substream
->stream
].period_elapsed_work
);
96 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed
);
98 static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream
*substream
,
99 struct snd_sof_dev
*sdev
,
100 struct snd_sof_pcm
*spcm
)
102 struct sof_ipc_stream stream
;
103 struct sof_ipc_reply reply
;
106 stream
.hdr
.size
= sizeof(stream
);
107 stream
.hdr
.cmd
= SOF_IPC_GLB_STREAM_MSG
| SOF_IPC_STREAM_PCM_FREE
;
108 stream
.comp_id
= spcm
->stream
[substream
->stream
].comp_id
;
110 /* send IPC to the DSP */
111 ret
= sof_ipc_tx_message(sdev
->ipc
, stream
.hdr
.cmd
, &stream
,
112 sizeof(stream
), &reply
, sizeof(reply
));
114 spcm
->prepared
[substream
->stream
] = false;
119 static int sof_pcm_hw_params(struct snd_soc_component
*component
,
120 struct snd_pcm_substream
*substream
,
121 struct snd_pcm_hw_params
*params
)
123 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
124 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
125 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
126 struct snd_sof_pcm
*spcm
;
127 struct sof_ipc_pcm_params pcm
;
128 struct sof_ipc_pcm_params_reply ipc_params_reply
;
131 /* nothing to do for BE */
132 if (rtd
->dai_link
->no_pcm
)
135 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
140 * Handle repeated calls to hw_params() without free_pcm() in
141 * between. At least ALSA OSS emulation depends on this.
143 if (spcm
->prepared
[substream
->stream
]) {
144 ret
= sof_pcm_dsp_pcm_free(substream
, sdev
, spcm
);
149 dev_dbg(component
->dev
, "pcm: hw params stream %d dir %d\n",
150 spcm
->pcm
.pcm_id
, substream
->stream
);
152 memset(&pcm
, 0, sizeof(pcm
));
154 /* create compressed page table for audio firmware */
155 if (runtime
->buffer_changed
) {
156 ret
= create_page_table(component
, substream
, runtime
->dma_area
,
162 /* number of pages should be rounded up */
163 pcm
.params
.buffer
.pages
= PFN_UP(runtime
->dma_bytes
);
165 /* set IPC PCM parameters */
166 pcm
.hdr
.size
= sizeof(pcm
);
167 pcm
.hdr
.cmd
= SOF_IPC_GLB_STREAM_MSG
| SOF_IPC_STREAM_PCM_PARAMS
;
168 pcm
.comp_id
= spcm
->stream
[substream
->stream
].comp_id
;
169 pcm
.params
.hdr
.size
= sizeof(pcm
.params
);
170 pcm
.params
.buffer
.phy_addr
=
171 spcm
->stream
[substream
->stream
].page_table
.addr
;
172 pcm
.params
.buffer
.size
= runtime
->dma_bytes
;
173 pcm
.params
.direction
= substream
->stream
;
174 pcm
.params
.sample_valid_bytes
= params_width(params
) >> 3;
175 pcm
.params
.buffer_fmt
= SOF_IPC_BUFFER_INTERLEAVED
;
176 pcm
.params
.rate
= params_rate(params
);
177 pcm
.params
.channels
= params_channels(params
);
178 pcm
.params
.host_period_bytes
= params_period_bytes(params
);
181 ret
= snd_pcm_format_physical_width(params_format(params
));
184 pcm
.params
.sample_container_bytes
= ret
>> 3;
187 switch (params_format(params
)) {
188 case SNDRV_PCM_FORMAT_S16
:
189 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S16_LE
;
191 case SNDRV_PCM_FORMAT_S24
:
192 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S24_4LE
;
194 case SNDRV_PCM_FORMAT_S32
:
195 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S32_LE
;
197 case SNDRV_PCM_FORMAT_FLOAT
:
198 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_FLOAT
;
204 /* firmware already configured host stream */
205 ret
= snd_sof_pcm_platform_hw_params(sdev
,
210 dev_err(component
->dev
, "error: platform hw params failed\n");
214 dev_dbg(component
->dev
, "stream_tag %d", pcm
.params
.stream_tag
);
216 /* send IPC to the DSP */
217 ret
= sof_ipc_tx_message(sdev
->ipc
, pcm
.hdr
.cmd
, &pcm
, sizeof(pcm
),
218 &ipc_params_reply
, sizeof(ipc_params_reply
));
220 dev_err(component
->dev
, "error: hw params ipc failed for stream %d\n",
221 pcm
.params
.stream_tag
);
225 ret
= sof_pcm_dsp_params(spcm
, substream
, &ipc_params_reply
);
229 spcm
->prepared
[substream
->stream
] = true;
231 /* save pcm hw_params */
232 memcpy(&spcm
->params
[substream
->stream
], params
, sizeof(*params
));
237 static int sof_pcm_hw_free(struct snd_soc_component
*component
,
238 struct snd_pcm_substream
*substream
)
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
;
245 /* nothing to do for BE */
246 if (rtd
->dai_link
->no_pcm
)
249 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
253 dev_dbg(component
->dev
, "pcm: free stream %d dir %d\n",
254 spcm
->pcm
.pcm_id
, substream
->stream
);
256 if (spcm
->prepared
[substream
->stream
]) {
257 ret
= sof_pcm_dsp_pcm_free(substream
, sdev
, spcm
);
262 cancel_work_sync(&spcm
->stream
[substream
->stream
].period_elapsed_work
);
264 ret
= snd_sof_pcm_platform_hw_free(sdev
, substream
);
266 dev_err(component
->dev
, "error: platform hw free failed\n");
273 static int sof_pcm_prepare(struct snd_soc_component
*component
,
274 struct snd_pcm_substream
*substream
)
276 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
277 struct snd_sof_pcm
*spcm
;
280 /* nothing to do for BE */
281 if (rtd
->dai_link
->no_pcm
)
284 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
288 if (spcm
->prepared
[substream
->stream
])
291 dev_dbg(component
->dev
, "pcm: prepare stream %d dir %d\n",
292 spcm
->pcm
.pcm_id
, substream
->stream
);
295 ret
= sof_pcm_hw_params(component
,
296 substream
, &spcm
->params
[substream
->stream
]);
298 dev_err(component
->dev
,
299 "error: set pcm hw_params after resume\n");
307 * FE dai link trigger actions are always executed in non-atomic context because
308 * they involve IPC's.
310 static int sof_pcm_trigger(struct snd_soc_component
*component
,
311 struct snd_pcm_substream
*substream
, int cmd
)
313 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
314 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
315 struct snd_sof_pcm
*spcm
;
316 struct sof_ipc_stream stream
;
317 struct sof_ipc_reply reply
;
318 bool reset_hw_params
= false;
319 bool ipc_first
= false;
322 /* nothing to do for BE */
323 if (rtd
->dai_link
->no_pcm
)
326 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
330 dev_dbg(component
->dev
, "pcm: trigger stream %d dir %d cmd %d\n",
331 spcm
->pcm
.pcm_id
, substream
->stream
, cmd
);
333 stream
.hdr
.size
= sizeof(stream
);
334 stream
.hdr
.cmd
= SOF_IPC_GLB_STREAM_MSG
;
335 stream
.comp_id
= spcm
->stream
[substream
->stream
].comp_id
;
338 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
339 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_PAUSE
;
342 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
343 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_RELEASE
;
345 case SNDRV_PCM_TRIGGER_RESUME
:
346 if (spcm
->stream
[substream
->stream
].suspend_ignored
) {
348 * this case will be triggered when INFO_RESUME is
349 * supported, no need to resume streams that remained
352 spcm
->stream
[substream
->stream
].suspend_ignored
= false;
356 /* set up hw_params */
357 ret
= sof_pcm_prepare(component
, substream
);
359 dev_err(component
->dev
,
360 "error: failed to set up hw_params upon resume\n");
365 case SNDRV_PCM_TRIGGER_START
:
366 if (spcm
->stream
[substream
->stream
].suspend_ignored
) {
368 * This case will be triggered when INFO_RESUME is
369 * not supported, no need to re-start streams that
370 * remained enabled in D0ix.
372 spcm
->stream
[substream
->stream
].suspend_ignored
= false;
375 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_START
;
377 case SNDRV_PCM_TRIGGER_SUSPEND
:
378 if (sdev
->system_suspend_target
== SOF_SUSPEND_S0IX
&&
379 spcm
->stream
[substream
->stream
].d0i3_compatible
) {
381 * trap the event, not sending trigger stop to
382 * prevent the FW pipelines from being stopped,
383 * and mark the flag to ignore the upcoming DAPM
386 spcm
->stream
[substream
->stream
].suspend_ignored
= true;
390 case SNDRV_PCM_TRIGGER_STOP
:
391 stream
.hdr
.cmd
|= SOF_IPC_STREAM_TRIG_STOP
;
393 reset_hw_params
= true;
396 dev_err(component
->dev
, "error: unhandled trigger cmd %d\n",
402 * DMA and IPC sequence is different for start and stop. Need to send
403 * STOP IPC before stop DMA
406 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
408 /* send IPC to the DSP */
409 ret
= sof_ipc_tx_message(sdev
->ipc
, stream
.hdr
.cmd
, &stream
,
410 sizeof(stream
), &reply
, sizeof(reply
));
412 /* need to STOP DMA even if STOP IPC failed */
414 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
416 /* free PCM if reset_hw_params is set and the STOP IPC is successful */
417 if (!ret
&& reset_hw_params
)
418 ret
= sof_pcm_dsp_pcm_free(substream
, sdev
, spcm
);
423 static snd_pcm_uframes_t
sof_pcm_pointer(struct snd_soc_component
*component
,
424 struct snd_pcm_substream
*substream
)
426 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
427 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
428 struct snd_sof_pcm
*spcm
;
429 snd_pcm_uframes_t host
, dai
;
431 /* nothing to do for BE */
432 if (rtd
->dai_link
->no_pcm
)
435 /* use dsp ops pointer callback directly if set */
436 if (sof_ops(sdev
)->pcm_pointer
)
437 return sof_ops(sdev
)->pcm_pointer(sdev
, substream
);
439 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
443 /* read position from DSP */
444 host
= bytes_to_frames(substream
->runtime
,
445 spcm
->stream
[substream
->stream
].posn
.host_posn
);
446 dai
= bytes_to_frames(substream
->runtime
,
447 spcm
->stream
[substream
->stream
].posn
.dai_posn
);
449 dev_dbg(component
->dev
,
450 "PCM: stream %d dir %d DMA position %lu DAI position %lu\n",
451 spcm
->pcm
.pcm_id
, substream
->stream
, host
, dai
);
456 static int sof_pcm_open(struct snd_soc_component
*component
,
457 struct snd_pcm_substream
*substream
)
459 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
460 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
461 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
462 const struct snd_sof_dsp_ops
*ops
= sof_ops(sdev
);
463 struct snd_sof_pcm
*spcm
;
464 struct snd_soc_tplg_stream_caps
*caps
;
467 /* nothing to do for BE */
468 if (rtd
->dai_link
->no_pcm
)
471 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
475 dev_dbg(component
->dev
, "pcm: open stream %d dir %d\n",
476 spcm
->pcm
.pcm_id
, substream
->stream
);
479 caps
= &spcm
->pcm
.caps
[substream
->stream
];
481 /* set any runtime constraints based on topology */
482 snd_pcm_hw_constraint_step(substream
->runtime
, 0,
483 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
484 le32_to_cpu(caps
->period_size_min
));
485 snd_pcm_hw_constraint_step(substream
->runtime
, 0,
486 SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
487 le32_to_cpu(caps
->period_size_min
));
489 /* set runtime config */
490 runtime
->hw
.info
= ops
->hw_info
; /* platform-specific */
492 runtime
->hw
.formats
= le64_to_cpu(caps
->formats
);
493 runtime
->hw
.period_bytes_min
= le32_to_cpu(caps
->period_size_min
);
494 runtime
->hw
.period_bytes_max
= le32_to_cpu(caps
->period_size_max
);
495 runtime
->hw
.periods_min
= le32_to_cpu(caps
->periods_min
);
496 runtime
->hw
.periods_max
= le32_to_cpu(caps
->periods_max
);
499 * caps->buffer_size_min is not used since the
500 * snd_pcm_hardware structure only defines buffer_bytes_max
502 runtime
->hw
.buffer_bytes_max
= le32_to_cpu(caps
->buffer_size_max
);
504 dev_dbg(component
->dev
, "period min %zd max %zd bytes\n",
505 runtime
->hw
.period_bytes_min
,
506 runtime
->hw
.period_bytes_max
);
507 dev_dbg(component
->dev
, "period count %d max %d\n",
508 runtime
->hw
.periods_min
,
509 runtime
->hw
.periods_max
);
510 dev_dbg(component
->dev
, "buffer max %zd bytes\n",
511 runtime
->hw
.buffer_bytes_max
);
513 /* set wait time - TODO: come from topology */
514 substream
->wait_time
= 500;
516 spcm
->stream
[substream
->stream
].posn
.host_posn
= 0;
517 spcm
->stream
[substream
->stream
].posn
.dai_posn
= 0;
518 spcm
->stream
[substream
->stream
].substream
= substream
;
519 spcm
->prepared
[substream
->stream
] = false;
521 ret
= snd_sof_pcm_platform_open(sdev
, substream
);
523 dev_err(component
->dev
, "error: pcm open failed %d\n", ret
);
528 static int sof_pcm_close(struct snd_soc_component
*component
,
529 struct snd_pcm_substream
*substream
)
531 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
532 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
533 struct snd_sof_pcm
*spcm
;
536 /* nothing to do for BE */
537 if (rtd
->dai_link
->no_pcm
)
540 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
544 dev_dbg(component
->dev
, "pcm: close stream %d dir %d\n",
545 spcm
->pcm
.pcm_id
, substream
->stream
);
547 err
= snd_sof_pcm_platform_close(sdev
, substream
);
549 dev_err(component
->dev
, "error: pcm close failed %d\n",
552 * keep going, no point in preventing the close
561 * Pre-allocate playback/capture audio buffer pages.
562 * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
563 * snd_pcm_lib_preallocate_free_for_all() is called by the core.
565 static int sof_pcm_new(struct snd_soc_component
*component
,
566 struct snd_soc_pcm_runtime
*rtd
)
568 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
569 struct snd_sof_pcm
*spcm
;
570 struct snd_pcm
*pcm
= rtd
->pcm
;
571 struct snd_soc_tplg_stream_caps
*caps
;
572 int stream
= SNDRV_PCM_STREAM_PLAYBACK
;
574 /* find SOF PCM for this RTD */
575 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
577 dev_warn(component
->dev
, "warn: can't find PCM with DAI ID %d\n",
582 dev_dbg(component
->dev
, "creating new PCM %s\n", spcm
->pcm
.pcm_name
);
584 /* do we need to pre-allocate playback audio buffer pages */
585 if (!spcm
->pcm
.playback
)
588 caps
= &spcm
->pcm
.caps
[stream
];
590 /* pre-allocate playback audio buffer pages */
591 dev_dbg(component
->dev
,
592 "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
593 caps
->name
, caps
->buffer_size_min
, caps
->buffer_size_max
);
595 if (!pcm
->streams
[stream
].substream
) {
596 dev_err(component
->dev
, "error: NULL playback substream!\n");
600 snd_pcm_set_managed_buffer(pcm
->streams
[stream
].substream
,
601 SNDRV_DMA_TYPE_DEV_SG
, sdev
->dev
,
602 0, le32_to_cpu(caps
->buffer_size_max
));
604 stream
= SNDRV_PCM_STREAM_CAPTURE
;
606 /* do we need to pre-allocate capture audio buffer pages */
607 if (!spcm
->pcm
.capture
)
610 caps
= &spcm
->pcm
.caps
[stream
];
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
);
617 if (!pcm
->streams
[stream
].substream
) {
618 dev_err(component
->dev
, "error: NULL capture substream!\n");
622 snd_pcm_set_managed_buffer(pcm
->streams
[stream
].substream
,
623 SNDRV_DMA_TYPE_DEV_SG
, sdev
->dev
,
624 0, le32_to_cpu(caps
->buffer_size_max
));
629 /* fixup the BE DAI link to match any values from topology */
630 static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime
*rtd
,
631 struct snd_pcm_hw_params
*params
)
633 struct snd_interval
*rate
= hw_param_interval(params
,
634 SNDRV_PCM_HW_PARAM_RATE
);
635 struct snd_interval
*channels
= hw_param_interval(params
,
636 SNDRV_PCM_HW_PARAM_CHANNELS
);
637 struct snd_mask
*fmt
= hw_param_mask(params
, SNDRV_PCM_HW_PARAM_FORMAT
);
638 struct snd_soc_component
*component
=
639 snd_soc_rtdcom_lookup(rtd
, SOF_AUDIO_PCM_DRV_NAME
);
640 struct snd_sof_dai
*dai
=
641 snd_sof_find_dai(component
, (char *)rtd
->dai_link
->name
);
642 struct snd_soc_dpcm
*dpcm
;
644 /* no topology exists for this BE, try a common configuration */
646 dev_warn(component
->dev
,
647 "warning: no topology found for BE DAI %s config\n",
648 rtd
->dai_link
->name
);
650 /* set 48k, stereo, 16bits by default */
658 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S16_LE
);
663 /* read format from topology */
666 switch (dai
->comp_dai
.config
.frame_fmt
) {
667 case SOF_IPC_FRAME_S16_LE
:
668 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S16_LE
);
670 case SOF_IPC_FRAME_S24_4LE
:
671 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S24_LE
);
673 case SOF_IPC_FRAME_S32_LE
:
674 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S32_LE
);
677 dev_err(component
->dev
, "error: No available DAI format!\n");
681 /* read rate and channels from topology */
682 switch (dai
->dai_config
->type
) {
683 case SOF_DAI_INTEL_SSP
:
684 rate
->min
= dai
->dai_config
->ssp
.fsync_rate
;
685 rate
->max
= dai
->dai_config
->ssp
.fsync_rate
;
686 channels
->min
= dai
->dai_config
->ssp
.tdm_slots
;
687 channels
->max
= dai
->dai_config
->ssp
.tdm_slots
;
689 dev_dbg(component
->dev
,
690 "rate_min: %d rate_max: %d\n", rate
->min
, rate
->max
);
691 dev_dbg(component
->dev
,
692 "channels_min: %d channels_max: %d\n",
693 channels
->min
, channels
->max
);
696 case SOF_DAI_INTEL_DMIC
:
697 /* DMIC only supports 16 or 32 bit formats */
698 if (dai
->comp_dai
.config
.frame_fmt
== SOF_IPC_FRAME_S24_4LE
) {
699 dev_err(component
->dev
,
700 "error: invalid fmt %d for DAI type %d\n",
701 dai
->comp_dai
.config
.frame_fmt
,
702 dai
->dai_config
->type
);
705 case SOF_DAI_INTEL_HDA
:
707 * HDaudio does not follow the default trigger
708 * sequence due to firmware implementation
710 for_each_dpcm_fe(rtd
, SNDRV_PCM_STREAM_PLAYBACK
, dpcm
) {
711 struct snd_soc_pcm_runtime
*fe
= dpcm
->fe
;
713 fe
->dai_link
->trigger
[SNDRV_PCM_STREAM_PLAYBACK
] =
714 SND_SOC_DPCM_TRIGGER_POST
;
717 case SOF_DAI_INTEL_ALH
:
718 /* do nothing for ALH dai_link */
720 case SOF_DAI_IMX_ESAI
:
721 rate
->min
= dai
->dai_config
->esai
.fsync_rate
;
722 rate
->max
= dai
->dai_config
->esai
.fsync_rate
;
723 channels
->min
= dai
->dai_config
->esai
.tdm_slots
;
724 channels
->max
= dai
->dai_config
->esai
.tdm_slots
;
726 dev_dbg(component
->dev
,
727 "rate_min: %d rate_max: %d\n", rate
->min
, rate
->max
);
728 dev_dbg(component
->dev
,
729 "channels_min: %d channels_max: %d\n",
730 channels
->min
, channels
->max
);
732 case SOF_DAI_IMX_SAI
:
733 rate
->min
= dai
->dai_config
->sai
.fsync_rate
;
734 rate
->max
= dai
->dai_config
->sai
.fsync_rate
;
735 channels
->min
= dai
->dai_config
->sai
.tdm_slots
;
736 channels
->max
= dai
->dai_config
->sai
.tdm_slots
;
738 dev_dbg(component
->dev
,
739 "rate_min: %d rate_max: %d\n", rate
->min
, rate
->max
);
740 dev_dbg(component
->dev
,
741 "channels_min: %d channels_max: %d\n",
742 channels
->min
, channels
->max
);
745 dev_err(component
->dev
, "error: invalid DAI type %d\n",
746 dai
->dai_config
->type
);
753 static int sof_pcm_probe(struct snd_soc_component
*component
)
755 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
756 struct snd_sof_pdata
*plat_data
= sdev
->pdata
;
757 const char *tplg_filename
;
760 /* load the default topology */
761 sdev
->component
= component
;
763 tplg_filename
= devm_kasprintf(sdev
->dev
, GFP_KERNEL
,
765 plat_data
->tplg_filename_prefix
,
766 plat_data
->tplg_filename
);
770 ret
= snd_sof_load_topology(component
, tplg_filename
);
772 dev_err(component
->dev
, "error: failed to load DSP topology %d\n",
780 static void sof_pcm_remove(struct snd_soc_component
*component
)
782 /* remove topology */
783 snd_soc_tplg_component_remove(component
, SND_SOC_TPLG_INDEX_ALL
);
786 void snd_sof_new_platform_drv(struct snd_sof_dev
*sdev
)
788 struct snd_soc_component_driver
*pd
= &sdev
->plat_drv
;
789 struct snd_sof_pdata
*plat_data
= sdev
->pdata
;
790 const char *drv_name
;
792 drv_name
= plat_data
->machine
->drv_name
;
794 pd
->name
= "sof-audio-component";
795 pd
->probe
= sof_pcm_probe
;
796 pd
->remove
= sof_pcm_remove
;
797 pd
->open
= sof_pcm_open
;
798 pd
->close
= sof_pcm_close
;
799 pd
->hw_params
= sof_pcm_hw_params
;
800 pd
->prepare
= sof_pcm_prepare
;
801 pd
->hw_free
= sof_pcm_hw_free
;
802 pd
->trigger
= sof_pcm_trigger
;
803 pd
->pointer
= sof_pcm_pointer
;
805 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
806 pd
->compress_ops
= &sof_compressed_ops
;
808 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
809 /* override cops when probe support is enabled */
810 pd
->compress_ops
= &sof_probe_compressed_ops
;
812 pd
->pcm_construct
= sof_pcm_new
;
813 pd
->ignore_machine
= drv_name
;
814 pd
->be_hw_params_fixup
= sof_pcm_dai_link_fixup
;
815 pd
->be_pcm_base
= SOF_BE_PCM_BASE
;
816 pd
->use_dai_pcm_id
= true;
817 pd
->topology_name_prefix
= "sof";
819 /* increment module refcount when a pcm is opened */
820 pd
->module_get_upon_open
= 1;