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
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>
16 #include <trace/events/sof.h>
17 #include "sof-of-dev.h"
19 #include "sof-audio.h"
20 #include "sof-utils.h"
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
= snd_soc_substream_to_rtd(substream
);
29 struct snd_sof_pcm
*spcm
;
30 struct snd_dma_buffer
*dmab
= snd_pcm_get_dma_buf(substream
);
31 int stream
= substream
->stream
;
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
);
42 * sof pcm period elapse work
44 static void snd_sof_pcm_period_elapsed_work(struct work_struct
*work
)
46 struct snd_sof_pcm_stream
*sps
=
47 container_of(work
, struct snd_sof_pcm_stream
,
50 snd_pcm_period_elapsed(sps
->substream
);
53 void snd_sof_pcm_init_elapsed_work(struct work_struct
*work
)
55 INIT_WORK(work
, snd_sof_pcm_period_elapsed_work
);
59 * sof pcm period elapse, this could be called at irq thread context.
61 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream
*substream
)
63 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
64 struct snd_soc_component
*component
=
65 snd_soc_rtdcom_lookup(rtd
, SOF_AUDIO_PCM_DRV_NAME
);
66 struct snd_sof_pcm
*spcm
;
68 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
70 dev_err(component
->dev
,
71 "error: period elapsed for unknown stream!\n");
76 * snd_pcm_period_elapsed() can be called in interrupt context
77 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
78 * when the PCM is done draining or xrun happened, a STOP IPC will
79 * then be sent and this IPC will hit IPC timeout.
80 * To avoid sending IPC before the previous IPC is handled, we
81 * schedule delayed work here to call the snd_pcm_period_elapsed().
83 schedule_work(&spcm
->stream
[substream
->stream
].period_elapsed_work
);
85 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed
);
88 sof_pcm_setup_connected_widgets(struct snd_sof_dev
*sdev
, struct snd_soc_pcm_runtime
*rtd
,
89 struct snd_sof_pcm
*spcm
, struct snd_pcm_hw_params
*params
,
90 struct snd_sof_platform_stream_params
*platform_params
, int dir
)
92 struct snd_soc_dai
*dai
;
95 /* query DAPM for list of connected widgets and set them up */
96 for_each_rtd_cpu_dais(rtd
, j
, dai
) {
97 struct snd_soc_dapm_widget_list
*list
;
99 ret
= snd_soc_dapm_dai_get_connected_widgets(dai
, dir
, &list
,
100 dpcm_end_walk_at_be
);
102 dev_err(sdev
->dev
, "error: dai %s has no valid %s path\n", dai
->name
,
103 snd_pcm_direction_name(dir
));
107 spcm
->stream
[dir
].list
= list
;
109 ret
= sof_widget_list_setup(sdev
, spcm
, params
, platform_params
, dir
);
111 dev_err(sdev
->dev
, "error: failed widget list set up for pcm %d dir %d\n",
112 spcm
->pcm
.pcm_id
, dir
);
113 spcm
->stream
[dir
].list
= NULL
;
114 snd_soc_dapm_dai_free_widgets(&list
);
122 static int sof_pcm_hw_params(struct snd_soc_component
*component
,
123 struct snd_pcm_substream
*substream
,
124 struct snd_pcm_hw_params
*params
)
126 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
127 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
128 const struct sof_ipc_pcm_ops
*pcm_ops
= sof_ipc_get_ops(sdev
, pcm
);
129 struct snd_sof_platform_stream_params platform_params
= { 0 };
130 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
131 struct snd_sof_pcm
*spcm
;
134 /* nothing to do for BE */
135 if (rtd
->dai_link
->no_pcm
)
138 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
143 * Handle repeated calls to hw_params() without free_pcm() in
144 * between. At least ALSA OSS emulation depends on this.
146 if (pcm_ops
&& pcm_ops
->hw_free
&& spcm
->prepared
[substream
->stream
]) {
147 ret
= pcm_ops
->hw_free(component
, substream
);
151 spcm
->prepared
[substream
->stream
] = false;
154 dev_dbg(component
->dev
, "pcm: hw params stream %d dir %d\n",
155 spcm
->pcm
.pcm_id
, substream
->stream
);
157 ret
= snd_sof_pcm_platform_hw_params(sdev
, substream
, params
, &platform_params
);
159 dev_err(component
->dev
, "platform hw params failed\n");
163 /* if this is a repeated hw_params without hw_free, skip setting up widgets */
164 if (!spcm
->stream
[substream
->stream
].list
) {
165 ret
= sof_pcm_setup_connected_widgets(sdev
, rtd
, spcm
, params
, &platform_params
,
171 /* create compressed page table for audio firmware */
172 if (runtime
->buffer_changed
) {
173 ret
= create_page_table(component
, substream
, runtime
->dma_area
,
180 if (pcm_ops
&& pcm_ops
->hw_params
) {
181 ret
= pcm_ops
->hw_params(component
, substream
, params
, &platform_params
);
186 spcm
->prepared
[substream
->stream
] = true;
188 /* save pcm hw_params */
189 memcpy(&spcm
->params
[substream
->stream
], params
, sizeof(*params
));
194 static int sof_pcm_hw_free(struct snd_soc_component
*component
,
195 struct snd_pcm_substream
*substream
)
197 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
198 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
199 struct snd_sof_pcm
*spcm
;
202 /* nothing to do for BE */
203 if (rtd
->dai_link
->no_pcm
)
206 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
210 dev_dbg(component
->dev
, "pcm: free stream %d dir %d\n",
211 spcm
->pcm
.pcm_id
, substream
->stream
);
213 ret
= sof_pcm_stream_free(sdev
, substream
, spcm
, substream
->stream
, true);
215 cancel_work_sync(&spcm
->stream
[substream
->stream
].period_elapsed_work
);
220 static int sof_pcm_prepare(struct snd_soc_component
*component
,
221 struct snd_pcm_substream
*substream
)
223 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
224 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
225 struct snd_sof_pcm
*spcm
;
228 /* nothing to do for BE */
229 if (rtd
->dai_link
->no_pcm
)
232 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
236 if (spcm
->prepared
[substream
->stream
]) {
237 if (!spcm
->pending_stop
[substream
->stream
])
241 * this case should be reached in case of xruns where we absolutely
242 * want to free-up and reset all PCM/DMA resources
244 ret
= sof_pcm_stream_free(sdev
, substream
, spcm
, substream
->stream
, true);
249 dev_dbg(component
->dev
, "pcm: prepare stream %d dir %d\n",
250 spcm
->pcm
.pcm_id
, substream
->stream
);
253 ret
= sof_pcm_hw_params(component
,
254 substream
, &spcm
->params
[substream
->stream
]);
256 dev_err(component
->dev
,
257 "error: set pcm hw_params after resume\n");
265 * FE dai link trigger actions are always executed in non-atomic context because
266 * they involve IPC's.
268 static int sof_pcm_trigger(struct snd_soc_component
*component
,
269 struct snd_pcm_substream
*substream
, int cmd
)
271 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
272 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
273 const struct sof_ipc_pcm_ops
*pcm_ops
= sof_ipc_get_ops(sdev
, pcm
);
274 struct snd_sof_pcm
*spcm
;
275 bool reset_hw_params
= false;
276 bool ipc_first
= false;
279 /* nothing to do for BE */
280 if (rtd
->dai_link
->no_pcm
)
283 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
287 dev_dbg(component
->dev
, "pcm: trigger stream %d dir %d cmd %d\n",
288 spcm
->pcm
.pcm_id
, substream
->stream
, cmd
);
290 spcm
->pending_stop
[substream
->stream
] = false;
293 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
296 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
297 if (pcm_ops
&& pcm_ops
->ipc_first_on_start
)
300 case SNDRV_PCM_TRIGGER_START
:
301 if (spcm
->stream
[substream
->stream
].suspend_ignored
) {
303 * This case will be triggered when INFO_RESUME is
304 * not supported, no need to re-start streams that
305 * remained enabled in D0ix.
307 spcm
->stream
[substream
->stream
].suspend_ignored
= false;
311 if (pcm_ops
&& pcm_ops
->ipc_first_on_start
)
314 case SNDRV_PCM_TRIGGER_SUSPEND
:
316 * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
317 * D0I3-compatible streams to keep the firmware pipeline running
319 if (pcm_ops
&& pcm_ops
->d0i3_supported_in_s0ix
&&
320 sdev
->system_suspend_target
== SOF_SUSPEND_S0IX
&&
321 spcm
->stream
[substream
->stream
].d0i3_compatible
) {
322 spcm
->stream
[substream
->stream
].suspend_ignored
= true;
326 /* On suspend the DMA must be stopped in DSPless mode */
327 if (sdev
->dspless_mode_selected
)
328 reset_hw_params
= true;
331 case SNDRV_PCM_TRIGGER_STOP
:
333 if (pcm_ops
&& pcm_ops
->reset_hw_params_during_stop
)
334 reset_hw_params
= true;
337 dev_err(component
->dev
, "Unhandled trigger cmd %d\n", cmd
);
342 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
344 if (pcm_ops
&& pcm_ops
->trigger
)
345 ret
= pcm_ops
->trigger(component
, substream
, cmd
);
348 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
349 case SNDRV_PCM_TRIGGER_START
:
350 /* invoke platform trigger to start DMA only if pcm_ops is successful */
351 if (ipc_first
&& !ret
)
352 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
354 case SNDRV_PCM_TRIGGER_SUSPEND
:
355 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
356 case SNDRV_PCM_TRIGGER_STOP
:
357 /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */
358 if (!pcm_ops
|| !pcm_ops
->platform_stop_during_hw_free
)
359 snd_sof_pcm_platform_trigger(sdev
, substream
, cmd
);
362 * set the pending_stop flag to indicate that pipeline stop has been delayed.
363 * This will be used later to stop the pipelines during prepare when recovering
366 if (pcm_ops
&& pcm_ops
->platform_stop_during_hw_free
&&
367 cmd
== SNDRV_PCM_TRIGGER_STOP
)
368 spcm
->pending_stop
[substream
->stream
] = true;
374 /* free PCM if reset_hw_params is set and the STOP IPC is successful */
375 if (!ret
&& reset_hw_params
)
376 ret
= sof_pcm_stream_free(sdev
, substream
, spcm
, substream
->stream
, false);
381 static snd_pcm_uframes_t
sof_pcm_pointer(struct snd_soc_component
*component
,
382 struct snd_pcm_substream
*substream
)
384 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
385 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
386 const struct sof_ipc_pcm_ops
*pcm_ops
= sof_ipc_get_ops(sdev
, pcm
);
387 struct snd_sof_pcm
*spcm
;
388 snd_pcm_uframes_t host
, dai
;
389 int ret
= -EOPNOTSUPP
;
391 /* nothing to do for BE */
392 if (rtd
->dai_link
->no_pcm
)
395 if (pcm_ops
&& pcm_ops
->pointer
)
396 ret
= pcm_ops
->pointer(component
, substream
, &host
);
398 if (ret
!= -EOPNOTSUPP
)
399 return ret
? ret
: host
;
401 /* use dsp ops pointer callback directly if set */
402 if (sof_ops(sdev
)->pcm_pointer
)
403 return sof_ops(sdev
)->pcm_pointer(sdev
, substream
);
405 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
409 /* read position from DSP */
410 host
= bytes_to_frames(substream
->runtime
,
411 spcm
->stream
[substream
->stream
].posn
.host_posn
);
412 dai
= bytes_to_frames(substream
->runtime
,
413 spcm
->stream
[substream
->stream
].posn
.dai_posn
);
415 trace_sof_pcm_pointer_position(sdev
, spcm
, substream
, host
, dai
);
420 static int sof_pcm_open(struct snd_soc_component
*component
,
421 struct snd_pcm_substream
*substream
)
423 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
424 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
425 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
426 const struct snd_sof_dsp_ops
*ops
= sof_ops(sdev
);
427 struct snd_sof_pcm
*spcm
;
428 struct snd_soc_tplg_stream_caps
*caps
;
431 /* nothing to do for BE */
432 if (rtd
->dai_link
->no_pcm
)
435 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
439 dev_dbg(component
->dev
, "pcm: open stream %d dir %d\n",
440 spcm
->pcm
.pcm_id
, substream
->stream
);
443 caps
= &spcm
->pcm
.caps
[substream
->stream
];
445 /* set runtime config */
446 runtime
->hw
.info
= ops
->hw_info
; /* platform-specific */
448 /* set any runtime constraints based on topology */
449 runtime
->hw
.formats
= le64_to_cpu(caps
->formats
);
450 runtime
->hw
.period_bytes_min
= le32_to_cpu(caps
->period_size_min
);
451 runtime
->hw
.period_bytes_max
= le32_to_cpu(caps
->period_size_max
);
452 runtime
->hw
.periods_min
= le32_to_cpu(caps
->periods_min
);
453 runtime
->hw
.periods_max
= le32_to_cpu(caps
->periods_max
);
456 * caps->buffer_size_min is not used since the
457 * snd_pcm_hardware structure only defines buffer_bytes_max
459 runtime
->hw
.buffer_bytes_max
= le32_to_cpu(caps
->buffer_size_max
);
461 dev_dbg(component
->dev
, "period min %zd max %zd bytes\n",
462 runtime
->hw
.period_bytes_min
,
463 runtime
->hw
.period_bytes_max
);
464 dev_dbg(component
->dev
, "period count %d max %d\n",
465 runtime
->hw
.periods_min
,
466 runtime
->hw
.periods_max
);
467 dev_dbg(component
->dev
, "buffer max %zd bytes\n",
468 runtime
->hw
.buffer_bytes_max
);
470 /* set wait time - TODO: come from topology */
471 substream
->wait_time
= 500;
473 spcm
->stream
[substream
->stream
].posn
.host_posn
= 0;
474 spcm
->stream
[substream
->stream
].posn
.dai_posn
= 0;
475 spcm
->stream
[substream
->stream
].substream
= substream
;
476 spcm
->prepared
[substream
->stream
] = false;
478 ret
= snd_sof_pcm_platform_open(sdev
, substream
);
480 dev_err(component
->dev
, "error: pcm open failed %d\n", ret
);
485 static int sof_pcm_close(struct snd_soc_component
*component
,
486 struct snd_pcm_substream
*substream
)
488 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
489 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
490 struct snd_sof_pcm
*spcm
;
493 /* nothing to do for BE */
494 if (rtd
->dai_link
->no_pcm
)
497 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
501 dev_dbg(component
->dev
, "pcm: close stream %d dir %d\n",
502 spcm
->pcm
.pcm_id
, substream
->stream
);
504 err
= snd_sof_pcm_platform_close(sdev
, substream
);
506 dev_err(component
->dev
, "error: pcm close failed %d\n",
509 * keep going, no point in preventing the close
518 * Pre-allocate playback/capture audio buffer pages.
519 * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
520 * snd_pcm_lib_preallocate_free_for_all() is called by the core.
522 static int sof_pcm_new(struct snd_soc_component
*component
,
523 struct snd_soc_pcm_runtime
*rtd
)
525 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
526 struct snd_sof_pcm
*spcm
;
527 struct snd_pcm
*pcm
= rtd
->pcm
;
528 struct snd_soc_tplg_stream_caps
*caps
;
529 int stream
= SNDRV_PCM_STREAM_PLAYBACK
;
531 /* find SOF PCM for this RTD */
532 spcm
= snd_sof_find_spcm_dai(component
, rtd
);
534 dev_warn(component
->dev
, "warn: can't find PCM with DAI ID %d\n",
539 dev_dbg(component
->dev
, "creating new PCM %s\n", spcm
->pcm
.pcm_name
);
541 /* do we need to pre-allocate playback audio buffer pages */
542 if (!spcm
->pcm
.playback
)
545 caps
= &spcm
->pcm
.caps
[stream
];
547 /* pre-allocate playback audio buffer pages */
548 dev_dbg(component
->dev
,
549 "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
550 caps
->name
, caps
->buffer_size_min
, caps
->buffer_size_max
);
552 if (!pcm
->streams
[stream
].substream
) {
553 dev_err(component
->dev
, "error: NULL playback substream!\n");
557 snd_pcm_set_managed_buffer(pcm
->streams
[stream
].substream
,
558 SNDRV_DMA_TYPE_DEV_SG
, sdev
->dev
,
559 0, le32_to_cpu(caps
->buffer_size_max
));
561 stream
= SNDRV_PCM_STREAM_CAPTURE
;
563 /* do we need to pre-allocate capture audio buffer pages */
564 if (!spcm
->pcm
.capture
)
567 caps
= &spcm
->pcm
.caps
[stream
];
569 /* pre-allocate capture audio buffer pages */
570 dev_dbg(component
->dev
,
571 "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
572 caps
->name
, caps
->buffer_size_min
, caps
->buffer_size_max
);
574 if (!pcm
->streams
[stream
].substream
) {
575 dev_err(component
->dev
, "error: NULL capture substream!\n");
579 snd_pcm_set_managed_buffer(pcm
->streams
[stream
].substream
,
580 SNDRV_DMA_TYPE_DEV_SG
, sdev
->dev
,
581 0, le32_to_cpu(caps
->buffer_size_max
));
586 /* fixup the BE DAI link to match any values from topology */
587 int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime
*rtd
, struct snd_pcm_hw_params
*params
)
589 struct snd_interval
*rate
= hw_param_interval(params
,
590 SNDRV_PCM_HW_PARAM_RATE
);
591 struct snd_interval
*channels
= hw_param_interval(params
,
592 SNDRV_PCM_HW_PARAM_CHANNELS
);
593 struct snd_mask
*fmt
= hw_param_mask(params
, SNDRV_PCM_HW_PARAM_FORMAT
);
594 struct snd_soc_component
*component
=
595 snd_soc_rtdcom_lookup(rtd
, SOF_AUDIO_PCM_DRV_NAME
);
596 struct snd_sof_dai
*dai
=
597 snd_sof_find_dai(component
, (char *)rtd
->dai_link
->name
);
598 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
599 const struct sof_ipc_pcm_ops
*pcm_ops
= sof_ipc_get_ops(sdev
, pcm
);
601 /* no topology exists for this BE, try a common configuration */
603 dev_warn(component
->dev
,
604 "warning: no topology found for BE DAI %s config\n",
605 rtd
->dai_link
->name
);
607 /* set 48k, stereo, 16bits by default */
615 snd_mask_set_format(fmt
, SNDRV_PCM_FORMAT_S16_LE
);
620 if (pcm_ops
&& pcm_ops
->dai_link_fixup
)
621 return pcm_ops
->dai_link_fixup(rtd
, params
);
625 EXPORT_SYMBOL(sof_pcm_dai_link_fixup
);
627 static int sof_pcm_probe(struct snd_soc_component
*component
)
629 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
630 struct snd_sof_pdata
*plat_data
= sdev
->pdata
;
631 const char *tplg_filename
;
635 * make sure the device is pm_runtime_active before loading the
636 * topology and initiating IPC or bus transactions
638 ret
= pm_runtime_resume_and_get(component
->dev
);
639 if (ret
< 0 && ret
!= -EACCES
)
642 /* load the default topology */
643 sdev
->component
= component
;
645 tplg_filename
= devm_kasprintf(sdev
->dev
, GFP_KERNEL
,
647 plat_data
->tplg_filename_prefix
,
648 plat_data
->tplg_filename
);
649 if (!tplg_filename
) {
654 ret
= snd_sof_load_topology(component
, tplg_filename
);
656 dev_err(component
->dev
, "error: failed to load DSP topology %d\n",
660 pm_runtime_mark_last_busy(component
->dev
);
661 pm_runtime_put_autosuspend(component
->dev
);
666 static void sof_pcm_remove(struct snd_soc_component
*component
)
668 /* remove topology */
669 snd_soc_tplg_component_remove(component
);
672 static int sof_pcm_ack(struct snd_soc_component
*component
,
673 struct snd_pcm_substream
*substream
)
675 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
677 return snd_sof_pcm_platform_ack(sdev
, substream
);
680 static snd_pcm_sframes_t
sof_pcm_delay(struct snd_soc_component
*component
,
681 struct snd_pcm_substream
*substream
)
683 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(component
);
684 const struct sof_ipc_pcm_ops
*pcm_ops
= sof_ipc_get_ops(sdev
, pcm
);
686 if (pcm_ops
&& pcm_ops
->delay
)
687 return pcm_ops
->delay(component
, substream
);
692 void snd_sof_new_platform_drv(struct snd_sof_dev
*sdev
)
694 struct snd_soc_component_driver
*pd
= &sdev
->plat_drv
;
695 struct snd_sof_pdata
*plat_data
= sdev
->pdata
;
696 const char *drv_name
;
698 if (plat_data
->machine
)
699 drv_name
= plat_data
->machine
->drv_name
;
700 else if (plat_data
->of_machine
)
701 drv_name
= plat_data
->of_machine
->drv_name
;
705 pd
->name
= "sof-audio-component";
706 pd
->probe
= sof_pcm_probe
;
707 pd
->remove
= sof_pcm_remove
;
708 pd
->open
= sof_pcm_open
;
709 pd
->close
= sof_pcm_close
;
710 pd
->hw_params
= sof_pcm_hw_params
;
711 pd
->prepare
= sof_pcm_prepare
;
712 pd
->hw_free
= sof_pcm_hw_free
;
713 pd
->trigger
= sof_pcm_trigger
;
714 pd
->pointer
= sof_pcm_pointer
;
715 pd
->ack
= sof_pcm_ack
;
716 pd
->delay
= sof_pcm_delay
;
718 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
719 pd
->compress_ops
= &sof_compressed_ops
;
722 pd
->pcm_construct
= sof_pcm_new
;
723 pd
->ignore_machine
= drv_name
;
724 pd
->be_pcm_base
= SOF_BE_PCM_BASE
;
725 pd
->use_dai_pcm_id
= true;
726 pd
->topology_name_prefix
= "sof";
728 /* increment module refcount when a pcm is opened */
729 pd
->module_get_upon_open
= 1;
731 pd
->legacy_dai_naming
= 1;
734 * The fixup is only needed when the DSP is in use as with the DSPless
735 * mode we are directly using the audio interface
737 if (!sdev
->dspless_mode_selected
)
738 pd
->be_hw_params_fixup
= sof_pcm_dai_link_fixup
;