Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // This file is provided under a dual BSD/GPLv2 license.  When using or
0004 // redistributing this file, you may do so under either license.
0005 //
0006 // Copyright(c) 2018 Intel Corporation. All rights reserved.
0007 //
0008 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
0009 //
0010 // PCM Layer, interface between ALSA and IPC.
0011 //
0012 
0013 #include <linux/pm_runtime.h>
0014 #include <sound/pcm_params.h>
0015 #include <sound/sof.h>
0016 #include "sof-priv.h"
0017 #include "sof-audio.h"
0018 #include "sof-utils.h"
0019 #include "ops.h"
0020 
0021 /* Create DMA buffer page table for DSP */
0022 static int create_page_table(struct snd_soc_component *component,
0023                  struct snd_pcm_substream *substream,
0024                  unsigned char *dma_area, size_t size)
0025 {
0026     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0027     struct snd_sof_pcm *spcm;
0028     struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
0029     int stream = substream->stream;
0030 
0031     spcm = snd_sof_find_spcm_dai(component, rtd);
0032     if (!spcm)
0033         return -EINVAL;
0034 
0035     return snd_sof_create_page_table(component->dev, dmab,
0036         spcm->stream[stream].page_table.area, size);
0037 }
0038 
0039 /*
0040  * sof pcm period elapse work
0041  */
0042 static void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
0043 {
0044     struct snd_sof_pcm_stream *sps =
0045         container_of(work, struct snd_sof_pcm_stream,
0046                  period_elapsed_work);
0047 
0048     snd_pcm_period_elapsed(sps->substream);
0049 }
0050 
0051 void snd_sof_pcm_init_elapsed_work(struct work_struct *work)
0052 {
0053      INIT_WORK(work, snd_sof_pcm_period_elapsed_work);
0054 }
0055 
0056 /*
0057  * sof pcm period elapse, this could be called at irq thread context.
0058  */
0059 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
0060 {
0061     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0062     struct snd_soc_component *component =
0063         snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
0064     struct snd_sof_pcm *spcm;
0065 
0066     spcm = snd_sof_find_spcm_dai(component, rtd);
0067     if (!spcm) {
0068         dev_err(component->dev,
0069             "error: period elapsed for unknown stream!\n");
0070         return;
0071     }
0072 
0073     /*
0074      * snd_pcm_period_elapsed() can be called in interrupt context
0075      * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
0076      * when the PCM is done draining or xrun happened, a STOP IPC will
0077      * then be sent and this IPC will hit IPC timeout.
0078      * To avoid sending IPC before the previous IPC is handled, we
0079      * schedule delayed work here to call the snd_pcm_period_elapsed().
0080      */
0081     schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
0082 }
0083 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
0084 
0085 static int
0086 sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
0087                 struct snd_sof_pcm *spcm, struct snd_pcm_hw_params *params,
0088                 struct snd_sof_platform_stream_params *platform_params, int dir)
0089 {
0090     struct snd_soc_dai *dai;
0091     int ret, j;
0092 
0093     /* query DAPM for list of connected widgets and set them up */
0094     for_each_rtd_cpu_dais(rtd, j, dai) {
0095         struct snd_soc_dapm_widget_list *list;
0096 
0097         ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list,
0098                                  dpcm_end_walk_at_be);
0099         if (ret < 0) {
0100             dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name,
0101                 dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
0102             return ret;
0103         }
0104 
0105         spcm->stream[dir].list = list;
0106 
0107         ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir);
0108         if (ret < 0) {
0109             dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n",
0110                 spcm->pcm.pcm_id, dir);
0111             spcm->stream[dir].list = NULL;
0112             snd_soc_dapm_dai_free_widgets(&list);
0113             return ret;
0114         }
0115     }
0116 
0117     return 0;
0118 }
0119 
0120 static int sof_pcm_hw_params(struct snd_soc_component *component,
0121                  struct snd_pcm_substream *substream,
0122                  struct snd_pcm_hw_params *params)
0123 {
0124     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0125     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0126     struct snd_sof_platform_stream_params platform_params = { 0 };
0127     const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
0128     struct snd_pcm_runtime *runtime = substream->runtime;
0129     struct snd_sof_pcm *spcm;
0130     int ret;
0131 
0132     /* nothing to do for BE */
0133     if (rtd->dai_link->no_pcm)
0134         return 0;
0135 
0136     spcm = snd_sof_find_spcm_dai(component, rtd);
0137     if (!spcm)
0138         return -EINVAL;
0139 
0140     /*
0141      * Handle repeated calls to hw_params() without free_pcm() in
0142      * between. At least ALSA OSS emulation depends on this.
0143      */
0144     if (pcm_ops->hw_free && spcm->prepared[substream->stream]) {
0145         ret = pcm_ops->hw_free(component, substream);
0146         if (ret < 0)
0147             return ret;
0148 
0149         spcm->prepared[substream->stream] = false;
0150     }
0151 
0152     dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
0153         spcm->pcm.pcm_id, substream->stream);
0154 
0155     ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params);
0156     if (ret < 0) {
0157         dev_err(component->dev, "platform hw params failed\n");
0158         return ret;
0159     }
0160 
0161     /* if this is a repeated hw_params without hw_free, skip setting up widgets */
0162     if (!spcm->stream[substream->stream].list) {
0163         ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, &platform_params,
0164                               substream->stream);
0165         if (ret < 0)
0166             return ret;
0167     }
0168 
0169     /* create compressed page table for audio firmware */
0170     if (runtime->buffer_changed) {
0171         ret = create_page_table(component, substream, runtime->dma_area,
0172                     runtime->dma_bytes);
0173 
0174         if (ret < 0)
0175             return ret;
0176     }
0177 
0178     if (pcm_ops->hw_params) {
0179         ret = pcm_ops->hw_params(component, substream, params, &platform_params);
0180         if (ret < 0)
0181             return ret;
0182     }
0183 
0184     spcm->prepared[substream->stream] = true;
0185 
0186     /* save pcm hw_params */
0187     memcpy(&spcm->params[substream->stream], params, sizeof(*params));
0188 
0189     return 0;
0190 }
0191 
0192 static int sof_pcm_hw_free(struct snd_soc_component *component,
0193                struct snd_pcm_substream *substream)
0194 {
0195     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0196     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0197     const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
0198     struct snd_sof_pcm *spcm;
0199     int ret, err = 0;
0200 
0201     /* nothing to do for BE */
0202     if (rtd->dai_link->no_pcm)
0203         return 0;
0204 
0205     spcm = snd_sof_find_spcm_dai(component, rtd);
0206     if (!spcm)
0207         return -EINVAL;
0208 
0209     dev_dbg(component->dev, "pcm: free stream %d dir %d\n",
0210         spcm->pcm.pcm_id, substream->stream);
0211 
0212     /* free PCM in the DSP */
0213     if (pcm_ops->hw_free && spcm->prepared[substream->stream]) {
0214         ret = pcm_ops->hw_free(component, substream);
0215         if (ret < 0)
0216             err = ret;
0217 
0218         spcm->prepared[substream->stream] = false;
0219     }
0220 
0221     /* stop DMA */
0222     ret = snd_sof_pcm_platform_hw_free(sdev, substream);
0223     if (ret < 0) {
0224         dev_err(component->dev, "error: platform hw free failed\n");
0225         err = ret;
0226     }
0227 
0228     /* free the DAPM widget list */
0229     ret = sof_widget_list_free(sdev, spcm, substream->stream);
0230     if (ret < 0)
0231         err = ret;
0232 
0233     cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
0234 
0235     return err;
0236 }
0237 
0238 static int sof_pcm_prepare(struct snd_soc_component *component,
0239                struct snd_pcm_substream *substream)
0240 {
0241     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0242     struct snd_sof_pcm *spcm;
0243     int ret;
0244 
0245     /* nothing to do for BE */
0246     if (rtd->dai_link->no_pcm)
0247         return 0;
0248 
0249     spcm = snd_sof_find_spcm_dai(component, rtd);
0250     if (!spcm)
0251         return -EINVAL;
0252 
0253     if (spcm->prepared[substream->stream])
0254         return 0;
0255 
0256     dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n",
0257         spcm->pcm.pcm_id, substream->stream);
0258 
0259     /* set hw_params */
0260     ret = sof_pcm_hw_params(component,
0261                 substream, &spcm->params[substream->stream]);
0262     if (ret < 0) {
0263         dev_err(component->dev,
0264             "error: set pcm hw_params after resume\n");
0265         return ret;
0266     }
0267 
0268     return 0;
0269 }
0270 
0271 /*
0272  * FE dai link trigger actions are always executed in non-atomic context because
0273  * they involve IPC's.
0274  */
0275 static int sof_pcm_trigger(struct snd_soc_component *component,
0276                struct snd_pcm_substream *substream, int cmd)
0277 {
0278     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0279     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0280     const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
0281     struct snd_sof_pcm *spcm;
0282     bool reset_hw_params = false;
0283     bool free_widget_list = false;
0284     bool ipc_first = false;
0285     int ret = 0;
0286 
0287     /* nothing to do for BE */
0288     if (rtd->dai_link->no_pcm)
0289         return 0;
0290 
0291     spcm = snd_sof_find_spcm_dai(component, rtd);
0292     if (!spcm)
0293         return -EINVAL;
0294 
0295     dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n",
0296         spcm->pcm.pcm_id, substream->stream, cmd);
0297 
0298     switch (cmd) {
0299     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0300         ipc_first = true;
0301         break;
0302     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0303         break;
0304     case SNDRV_PCM_TRIGGER_START:
0305         if (spcm->stream[substream->stream].suspend_ignored) {
0306             /*
0307              * This case will be triggered when INFO_RESUME is
0308              * not supported, no need to re-start streams that
0309              * remained enabled in D0ix.
0310              */
0311             spcm->stream[substream->stream].suspend_ignored = false;
0312             return 0;
0313         }
0314         break;
0315     case SNDRV_PCM_TRIGGER_SUSPEND:
0316         if (sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
0317             spcm->stream[substream->stream].d0i3_compatible) {
0318             /*
0319              * trap the event, not sending trigger stop to
0320              * prevent the FW pipelines from being stopped,
0321              * and mark the flag to ignore the upcoming DAPM
0322              * PM events.
0323              */
0324             spcm->stream[substream->stream].suspend_ignored = true;
0325             return 0;
0326         }
0327         free_widget_list = true;
0328         fallthrough;
0329     case SNDRV_PCM_TRIGGER_STOP:
0330         ipc_first = true;
0331         reset_hw_params = true;
0332         break;
0333     default:
0334         dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd);
0335         return -EINVAL;
0336     }
0337 
0338     /*
0339      * DMA and IPC sequence is different for start and stop. Need to send
0340      * STOP IPC before stop DMA
0341      */
0342     if (!ipc_first)
0343         snd_sof_pcm_platform_trigger(sdev, substream, cmd);
0344 
0345     if (pcm_ops->trigger)
0346         ret = pcm_ops->trigger(component, substream, cmd);
0347 
0348     /* need to STOP DMA even if trigger IPC failed */
0349     if (ipc_first)
0350         snd_sof_pcm_platform_trigger(sdev, substream, cmd);
0351 
0352     /* free PCM if reset_hw_params is set and the STOP IPC is successful */
0353     if (!ret && reset_hw_params)
0354         ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream,
0355                       free_widget_list);
0356 
0357     return ret;
0358 }
0359 
0360 static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
0361                      struct snd_pcm_substream *substream)
0362 {
0363     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0364     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0365     struct snd_sof_pcm *spcm;
0366     snd_pcm_uframes_t host, dai;
0367 
0368     /* nothing to do for BE */
0369     if (rtd->dai_link->no_pcm)
0370         return 0;
0371 
0372     /* use dsp ops pointer callback directly if set */
0373     if (sof_ops(sdev)->pcm_pointer)
0374         return sof_ops(sdev)->pcm_pointer(sdev, substream);
0375 
0376     spcm = snd_sof_find_spcm_dai(component, rtd);
0377     if (!spcm)
0378         return -EINVAL;
0379 
0380     /* read position from DSP */
0381     host = bytes_to_frames(substream->runtime,
0382                    spcm->stream[substream->stream].posn.host_posn);
0383     dai = bytes_to_frames(substream->runtime,
0384                   spcm->stream[substream->stream].posn.dai_posn);
0385 
0386     dev_vdbg(component->dev,
0387          "PCM: stream %d dir %d DMA position %lu DAI position %lu\n",
0388          spcm->pcm.pcm_id, substream->stream, host, dai);
0389 
0390     return host;
0391 }
0392 
0393 static int sof_pcm_open(struct snd_soc_component *component,
0394             struct snd_pcm_substream *substream)
0395 {
0396     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0397     struct snd_pcm_runtime *runtime = substream->runtime;
0398     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0399     struct snd_sof_dsp_ops *ops = sof_ops(sdev);
0400     struct snd_sof_pcm *spcm;
0401     struct snd_soc_tplg_stream_caps *caps;
0402     int ret;
0403 
0404     /* nothing to do for BE */
0405     if (rtd->dai_link->no_pcm)
0406         return 0;
0407 
0408     spcm = snd_sof_find_spcm_dai(component, rtd);
0409     if (!spcm)
0410         return -EINVAL;
0411 
0412     dev_dbg(component->dev, "pcm: open stream %d dir %d\n",
0413         spcm->pcm.pcm_id, substream->stream);
0414 
0415 
0416     caps = &spcm->pcm.caps[substream->stream];
0417 
0418     /* set runtime config */
0419     runtime->hw.info = ops->hw_info; /* platform-specific */
0420 
0421     /* set any runtime constraints based on topology */
0422     runtime->hw.formats = le64_to_cpu(caps->formats);
0423     runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min);
0424     runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max);
0425     runtime->hw.periods_min = le32_to_cpu(caps->periods_min);
0426     runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
0427 
0428     /*
0429      * caps->buffer_size_min is not used since the
0430      * snd_pcm_hardware structure only defines buffer_bytes_max
0431      */
0432     runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
0433 
0434     dev_dbg(component->dev, "period min %zd max %zd bytes\n",
0435         runtime->hw.period_bytes_min,
0436         runtime->hw.period_bytes_max);
0437     dev_dbg(component->dev, "period count %d max %d\n",
0438         runtime->hw.periods_min,
0439         runtime->hw.periods_max);
0440     dev_dbg(component->dev, "buffer max %zd bytes\n",
0441         runtime->hw.buffer_bytes_max);
0442 
0443     /* set wait time - TODO: come from topology */
0444     substream->wait_time = 500;
0445 
0446     spcm->stream[substream->stream].posn.host_posn = 0;
0447     spcm->stream[substream->stream].posn.dai_posn = 0;
0448     spcm->stream[substream->stream].substream = substream;
0449     spcm->prepared[substream->stream] = false;
0450 
0451     ret = snd_sof_pcm_platform_open(sdev, substream);
0452     if (ret < 0)
0453         dev_err(component->dev, "error: pcm open failed %d\n", ret);
0454 
0455     return ret;
0456 }
0457 
0458 static int sof_pcm_close(struct snd_soc_component *component,
0459              struct snd_pcm_substream *substream)
0460 {
0461     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0462     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0463     struct snd_sof_pcm *spcm;
0464     int err;
0465 
0466     /* nothing to do for BE */
0467     if (rtd->dai_link->no_pcm)
0468         return 0;
0469 
0470     spcm = snd_sof_find_spcm_dai(component, rtd);
0471     if (!spcm)
0472         return -EINVAL;
0473 
0474     dev_dbg(component->dev, "pcm: close stream %d dir %d\n",
0475         spcm->pcm.pcm_id, substream->stream);
0476 
0477     err = snd_sof_pcm_platform_close(sdev, substream);
0478     if (err < 0) {
0479         dev_err(component->dev, "error: pcm close failed %d\n",
0480             err);
0481         /*
0482          * keep going, no point in preventing the close
0483          * from happening
0484          */
0485     }
0486 
0487     return 0;
0488 }
0489 
0490 /*
0491  * Pre-allocate playback/capture audio buffer pages.
0492  * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
0493  * snd_pcm_lib_preallocate_free_for_all() is called by the core.
0494  */
0495 static int sof_pcm_new(struct snd_soc_component *component,
0496                struct snd_soc_pcm_runtime *rtd)
0497 {
0498     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0499     struct snd_sof_pcm *spcm;
0500     struct snd_pcm *pcm = rtd->pcm;
0501     struct snd_soc_tplg_stream_caps *caps;
0502     int stream = SNDRV_PCM_STREAM_PLAYBACK;
0503 
0504     /* find SOF PCM for this RTD */
0505     spcm = snd_sof_find_spcm_dai(component, rtd);
0506     if (!spcm) {
0507         dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n",
0508              rtd->dai_link->id);
0509         return 0;
0510     }
0511 
0512     dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name);
0513 
0514     /* do we need to pre-allocate playback audio buffer pages */
0515     if (!spcm->pcm.playback)
0516         goto capture;
0517 
0518     caps = &spcm->pcm.caps[stream];
0519 
0520     /* pre-allocate playback audio buffer pages */
0521     dev_dbg(component->dev,
0522         "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
0523         caps->name, caps->buffer_size_min, caps->buffer_size_max);
0524 
0525     if (!pcm->streams[stream].substream) {
0526         dev_err(component->dev, "error: NULL playback substream!\n");
0527         return -EINVAL;
0528     }
0529 
0530     snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
0531                    SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
0532                    0, le32_to_cpu(caps->buffer_size_max));
0533 capture:
0534     stream = SNDRV_PCM_STREAM_CAPTURE;
0535 
0536     /* do we need to pre-allocate capture audio buffer pages */
0537     if (!spcm->pcm.capture)
0538         return 0;
0539 
0540     caps = &spcm->pcm.caps[stream];
0541 
0542     /* pre-allocate capture audio buffer pages */
0543     dev_dbg(component->dev,
0544         "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
0545         caps->name, caps->buffer_size_min, caps->buffer_size_max);
0546 
0547     if (!pcm->streams[stream].substream) {
0548         dev_err(component->dev, "error: NULL capture substream!\n");
0549         return -EINVAL;
0550     }
0551 
0552     snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
0553                    SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
0554                    0, le32_to_cpu(caps->buffer_size_max));
0555 
0556     return 0;
0557 }
0558 
0559 /* fixup the BE DAI link to match any values from topology */
0560 int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params)
0561 {
0562     struct snd_interval *rate = hw_param_interval(params,
0563             SNDRV_PCM_HW_PARAM_RATE);
0564     struct snd_interval *channels = hw_param_interval(params,
0565                         SNDRV_PCM_HW_PARAM_CHANNELS);
0566     struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
0567     struct snd_soc_component *component =
0568         snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
0569     struct snd_sof_dai *dai =
0570         snd_sof_find_dai(component, (char *)rtd->dai_link->name);
0571     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0572     const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
0573 
0574     /* no topology exists for this BE, try a common configuration */
0575     if (!dai) {
0576         dev_warn(component->dev,
0577              "warning: no topology found for BE DAI %s config\n",
0578              rtd->dai_link->name);
0579 
0580         /*  set 48k, stereo, 16bits by default */
0581         rate->min = 48000;
0582         rate->max = 48000;
0583 
0584         channels->min = 2;
0585         channels->max = 2;
0586 
0587         snd_mask_none(fmt);
0588         snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
0589 
0590         return 0;
0591     }
0592 
0593     if (pcm_ops->dai_link_fixup)
0594         return pcm_ops->dai_link_fixup(rtd, params);
0595 
0596     return 0;
0597 }
0598 EXPORT_SYMBOL(sof_pcm_dai_link_fixup);
0599 
0600 static int sof_pcm_probe(struct snd_soc_component *component)
0601 {
0602     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0603     struct snd_sof_pdata *plat_data = sdev->pdata;
0604     const char *tplg_filename;
0605     int ret;
0606 
0607     /*
0608      * make sure the device is pm_runtime_active before loading the
0609      * topology and initiating IPC or bus transactions
0610      */
0611     ret = pm_runtime_resume_and_get(component->dev);
0612     if (ret < 0 && ret != -EACCES)
0613         return ret;
0614 
0615     /* load the default topology */
0616     sdev->component = component;
0617 
0618     tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
0619                        "%s/%s",
0620                        plat_data->tplg_filename_prefix,
0621                        plat_data->tplg_filename);
0622     if (!tplg_filename)
0623         return -ENOMEM;
0624 
0625     ret = snd_sof_load_topology(component, tplg_filename);
0626     if (ret < 0) {
0627         dev_err(component->dev, "error: failed to load DSP topology %d\n",
0628             ret);
0629         return ret;
0630     }
0631 
0632     pm_runtime_mark_last_busy(component->dev);
0633     pm_runtime_put_autosuspend(component->dev);
0634 
0635     return ret;
0636 }
0637 
0638 static void sof_pcm_remove(struct snd_soc_component *component)
0639 {
0640     /* remove topology */
0641     snd_soc_tplg_component_remove(component);
0642 }
0643 
0644 static int sof_pcm_ack(struct snd_soc_component *component,
0645                struct snd_pcm_substream *substream)
0646 {
0647     struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0648 
0649     return snd_sof_pcm_platform_ack(sdev, substream);
0650 }
0651 
0652 void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)
0653 {
0654     struct snd_soc_component_driver *pd = &sdev->plat_drv;
0655     struct snd_sof_pdata *plat_data = sdev->pdata;
0656     const char *drv_name;
0657 
0658     drv_name = plat_data->machine->drv_name;
0659 
0660     pd->name = "sof-audio-component";
0661     pd->probe = sof_pcm_probe;
0662     pd->remove = sof_pcm_remove;
0663     pd->open = sof_pcm_open;
0664     pd->close = sof_pcm_close;
0665     pd->hw_params = sof_pcm_hw_params;
0666     pd->prepare = sof_pcm_prepare;
0667     pd->hw_free = sof_pcm_hw_free;
0668     pd->trigger = sof_pcm_trigger;
0669     pd->pointer = sof_pcm_pointer;
0670     pd->ack = sof_pcm_ack;
0671 
0672 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS)
0673     pd->compress_ops = &sof_compressed_ops;
0674 #endif
0675 
0676     pd->pcm_construct = sof_pcm_new;
0677     pd->ignore_machine = drv_name;
0678     pd->be_hw_params_fixup = sof_pcm_dai_link_fixup;
0679     pd->be_pcm_base = SOF_BE_PCM_BASE;
0680     pd->use_dai_pcm_id = true;
0681     pd->topology_name_prefix = "sof";
0682 
0683      /* increment module refcount when a pcm is opened */
0684     pd->module_get_upon_open = 1;
0685 
0686     pd->legacy_dai_naming = 1;
0687 }