diff --git a/include/sound/sof.h b/include/sound/sof.h index eddea82c7b5a90..38d6c8cb5e832b 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -159,6 +159,9 @@ struct sof_dev_desc { /* The platform supports DSPless mode */ bool dspless_mode_supported; + /* On demand DSP booting is possible on the platform */ + bool on_demand_dsp_boot; + /* defaults paths for firmware, library and topology files */ const char *default_fw_path[SOF_IPC_TYPE_COUNT]; const char *default_lib_path[SOF_IPC_TYPE_COUNT]; diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index d7b044f33d7963..7b65d7ccab8c3c 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -195,6 +195,14 @@ static int sof_compr_set_params(struct snd_soc_component *component, if (sizeof(*pcm) + ext_data_size > sdev->ipc->max_payload_size) return -EINVAL; + /* + * Make sure that the DSP is booted up, which might not be the + * case if the on-demand DSP boot is used + */ + ret = snd_sof_boot_dsp_firmware(sdev); + if (ret) + return ret; + pcm = kzalloc(sizeof(*pcm) + ext_data_size, GFP_KERNEL); if (!pcm) return -ENOMEM; diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 463d418e72001b..6bca9daf4a4ea9 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -187,14 +187,23 @@ int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int _ const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); int ret, err; + /* ignore the ext_volatile_get call if the callbacks are not provided */ + if (!tplg_ops || !tplg_ops->control || + !tplg_ops->control->bytes_ext_volatile_get) + return 0; + ret = pm_runtime_resume_and_get(scomp->dev); if (ret < 0 && ret != -EACCES) { dev_err_ratelimited(scomp->dev, "%s: failed to resume %d\n", __func__, ret); return ret; } - if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_volatile_get) - ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, binary_data, size); + /* Make sure the DSP/firmware is booted up */ + ret = snd_sof_boot_dsp_firmware(sdev); + if (!ret) + ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, + binary_data, + size); pm_runtime_mark_last_busy(scomp->dev); err = pm_runtime_put_autosuspend(scomp->dev); diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 265f64dd2319b9..5fa8c40de5d9a1 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -694,6 +694,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) mutex_init(&sdev->power_state_access); mutex_init(&sdev->ipc_client_mutex); mutex_init(&sdev->client_event_handler_mutex); + mutex_init(&sdev->dsp_fw_boot_mutex); /* set default timeouts if none provided */ if (plat_data->desc->ipc_timeout == 0) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index ba99b777362f5e..f32ab454b610ce 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -216,7 +216,12 @@ static int memory_info_update(struct snd_sof_dev *sdev, char *buf, size_t buff_s goto error; } - ret = sof_ipc_tx_message(sdev->ipc, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE); + /* Make sure the DSP/firmware is booted up */ + ret = snd_sof_boot_dsp_firmware(sdev); + if (!ret) + ret = sof_ipc_tx_message(sdev->ipc, &msg, msg.size, reply, + SOF_IPC_MSG_MAX_SIZE); + pm_runtime_mark_last_busy(sdev->dev); pm_runtime_put_autosuspend(sdev->dev); if (ret < 0 || reply->rhdr.error < 0) { diff --git a/sound/soc/sof/intel/hda-sdw-bpt.c b/sound/soc/sof/intel/hda-sdw-bpt.c index 1327f1cad0bcd9..421ca71c5ddbad 100644 --- a/sound/soc/sof/intel/hda-sdw-bpt.c +++ b/sound/soc/sof/intel/hda-sdw-bpt.c @@ -97,6 +97,17 @@ static int hda_sdw_bpt_dma_prepare(struct device *dev, struct hdac_ext_stream ** struct hdac_ext_stream *bpt_stream; unsigned int format = HDA_CL_STREAM_FORMAT; + if (!sdev->dspless_mode_selected) { + int ret; + + /* + * Make sure that the DSP is booted up, which might not be the + * case if the on-demand DSP boot is used + */ + ret = snd_sof_boot_dsp_firmware(sdev); + if (ret) + return ret; + } /* * the baseline format needs to be adjusted to * bandwidth requirements diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index ae379c23f008f7..acb4429df9ecf6 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -40,6 +40,7 @@ static const struct sof_dev_desc lnl_desc = { .ipc_supported_mask = BIT(SOF_IPC_TYPE_4), .ipc_default = SOF_IPC_TYPE_4, .dspless_mode_supported = true, + .on_demand_dsp_boot = true, .default_fw_path = { [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl", }, diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c index 68f6a98416335e..9cb785ef763f63 100644 --- a/sound/soc/sof/intel/pci-ptl.c +++ b/sound/soc/sof/intel/pci-ptl.c @@ -38,6 +38,7 @@ static const struct sof_dev_desc ptl_desc = { .ipc_supported_mask = BIT(SOF_IPC_TYPE_4), .ipc_default = SOF_IPC_TYPE_4, .dspless_mode_supported = true, + .on_demand_dsp_boot = true, .default_fw_path = { [SOF_IPC_TYPE_4] = "intel/sof-ipc4/ptl", }, @@ -67,6 +68,7 @@ static const struct sof_dev_desc wcl_desc = { .ipc_supported_mask = BIT(SOF_IPC_TYPE_4), .ipc_default = SOF_IPC_TYPE_4, .dspless_mode_supported = true, + .on_demand_dsp_boot = true, .default_fw_path = { [SOF_IPC_TYPE_4] = "intel/sof-ipc4/wcl", }, diff --git a/sound/soc/sof/ipc3-dtrace.c b/sound/soc/sof/ipc3-dtrace.c index 744a91a150bc9c..1030350fc2a3a0 100644 --- a/sound/soc/sof/ipc3-dtrace.c +++ b/sound/soc/sof/ipc3-dtrace.c @@ -171,7 +171,12 @@ static int ipc3_trace_update_filter(struct snd_sof_dev *sdev, int num_elems, dev_err(sdev->dev, "enabling device failed: %d\n", ret); goto error; } - ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, msg->hdr.size); + + /* Make sure the DSP/firmware is booted up */ + ret = snd_sof_boot_dsp_firmware(sdev); + if (!ret) + ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, msg->hdr.size); + pm_runtime_mark_last_busy(sdev->dev); pm_runtime_put_autosuspend(sdev->dev); diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index 83847bcb65b791..ca2c39c1d03ade 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -184,7 +184,7 @@ static int sof_ipc4_load_library(struct snd_sof_dev *sdev, unsigned long lib_id, struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct sof_ipc4_fw_library *fw_lib; ssize_t payload_offset; - int ret, i, err; + int ret, i; if (!ipc4_data->load_library) { dev_err(sdev->dev, "Library loading is not supported on this platform\n"); @@ -232,25 +232,7 @@ static int sof_ipc4_load_library(struct snd_sof_dev *sdev, unsigned long lib_id, for (i = 0; i < fw_lib->num_modules; i++) fw_lib->modules[i].man4_module_entry.id |= (lib_id << SOF_IPC4_MOD_LIB_ID_SHIFT); - /* - * Make sure that the DSP is booted and stays up while attempting the - * loading the library for the first time - */ - ret = pm_runtime_resume_and_get(sdev->dev); - if (ret < 0 && ret != -EACCES) { - dev_err_ratelimited(sdev->dev, "%s: pm_runtime resume failed: %d\n", - __func__, ret); - goto release; - } - ret = ipc4_data->load_library(sdev, fw_lib, false); - - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, "%s: pm_runtime idle failed: %d\n", - __func__, err); - if (ret) goto release; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 6e73668261da7b..6f0403175db1ff 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -137,6 +137,16 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, spcm_dbg(spcm, substream->stream, "Entry: hw_params\n"); + if (!sdev->dspless_mode_selected) { + /* + * Make sure that the DSP is booted up, which might not be the + * case if the on-demand DSP boot is used + */ + ret = snd_sof_boot_dsp_firmware(sdev); + if (ret) + return ret; + } + /* * Handle repeated calls to hw_params() without free_pcm() in * between. At least ALSA OSS emulation depends on this. diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 7f3c42662e724e..99f64397f33a4e 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -70,67 +70,28 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev) } #endif -static int sof_resume(struct device *dev, bool runtime_resume) +int snd_sof_boot_dsp_firmware(struct snd_sof_dev *sdev) { - struct snd_sof_dev *sdev = dev_get_drvdata(dev); const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - u32 old_state = sdev->dsp_power_state.state; int ret; - /* do nothing if dsp resume callbacks are not set */ - if (!runtime_resume && !sof_ops(sdev)->resume) - return 0; - - if (runtime_resume && !sof_ops(sdev)->runtime_resume) - return 0; + guard(mutex)(&sdev->dsp_fw_boot_mutex); - /* DSP was never successfully started, nothing to resume */ - if (sdev->first_boot) + if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) { + /* Firmware already booted, just return */ return 0; - - /* - * if the runtime_resume flag is set, call the runtime_resume routine - * or else call the system resume routine - */ - if (runtime_resume) - ret = snd_sof_dsp_runtime_resume(sdev); - else - ret = snd_sof_dsp_resume(sdev); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to power up DSP after resume\n"); - return ret; } - if (sdev->dspless_mode_selected) { - sof_set_fw_state(sdev, SOF_DSPLESS_MODE); - return 0; - } - - /* - * Nothing further to be done for platforms that support the low power - * D0 substate. Resume trace and return when resuming from - * low-power D0 substate - */ - if (!runtime_resume && sof_ops(sdev)->set_power_state && - old_state == SOF_DSP_PM_D0) { - ret = sof_fw_trace_resume(sdev); - if (ret < 0) - /* non fatal */ - dev_warn(sdev->dev, - "failed to enable trace after resume %d\n", ret); - return 0; - } + dev_dbg(sdev->dev, "Booting DSP firmware\n"); sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE); /* load the firmware */ ret = snd_sof_load_firmware(sdev, NULL); if (ret < 0) { - dev_err(sdev->dev, - "error: failed to load DSP firmware after resume %d\n", - ret); + dev_err(sdev->dev, "%s: failed to load DSP firmware: %d\n", + __func__, ret); sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED); return ret; } @@ -143,9 +104,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) */ ret = snd_sof_run_firmware(sdev); if (ret < 0) { - dev_err(sdev->dev, - "error: failed to boot DSP firmware after resume %d\n", - ret); + dev_err(sdev->dev, "%s: failed to boot DSP firmware: %d\n", + __func__, ret); sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED); return ret; } @@ -154,16 +114,16 @@ static int sof_resume(struct device *dev, bool runtime_resume) ret = sof_fw_trace_resume(sdev); if (ret < 0) { /* non fatal */ - dev_warn(sdev->dev, - "warning: failed to init trace after resume %d\n", - ret); + dev_warn(sdev->dev, "%s: failed to resume trace: %d\n", + __func__, ret); } /* restore pipelines */ if (tplg_ops && tplg_ops->set_up_all_pipelines) { ret = tplg_ops->set_up_all_pipelines(sdev, false); if (ret < 0) { - dev_err(sdev->dev, "Failed to restore pipeline after resume %d\n", ret); + dev_err(sdev->dev, "%s: failed to restore pipeline: %d\n", + __func__, ret); goto setup_fail; } } @@ -175,7 +135,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) if (pm_ops && pm_ops->ctx_restore) { ret = pm_ops->ctx_restore(sdev); if (ret < 0) - dev_err(sdev->dev, "ctx_restore IPC error during resume: %d\n", ret); + dev_err(sdev->dev, "%s: ctx_restore IPC failed: %d\n", + __func__, ret); } setup_fail: @@ -192,6 +153,67 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } +EXPORT_SYMBOL(snd_sof_boot_dsp_firmware); + +static int sof_resume(struct device *dev, bool runtime_resume) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + u32 old_state = sdev->dsp_power_state.state; + int ret; + + /* do nothing if dsp resume callbacks are not set */ + if (!runtime_resume && !sof_ops(sdev)->resume) + return 0; + + if (runtime_resume && !sof_ops(sdev)->runtime_resume) + return 0; + + /* DSP was never successfully started, nothing to resume */ + if (sdev->first_boot) + return 0; + + /* + * if the runtime_resume flag is set, call the runtime_resume routine + * or else call the system resume routine + */ + if (runtime_resume) + ret = snd_sof_dsp_runtime_resume(sdev); + else + ret = snd_sof_dsp_resume(sdev); + if (ret < 0) { + dev_err(sdev->dev, + "error: failed to power up DSP after resume\n"); + return ret; + } + + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + return 0; + } + + /* + * Nothing further to be done for platforms that support the low power + * D0 substate. Resume trace and return when resuming from + * low-power D0 substate + */ + if (!runtime_resume && sof_ops(sdev)->set_power_state && + old_state == SOF_DSP_PM_D0) { + ret = sof_fw_trace_resume(sdev); + if (ret < 0) + /* non fatal */ + dev_warn(sdev->dev, + "failed to enable trace after resume %d\n", ret); + return 0; + } + + if (sdev->pdata->desc->on_demand_dsp_boot) { + /* Only change the fw_state to PREPARE but skip booting */ + sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE); + return 0; + } + + return snd_sof_boot_dsp_firmware(sdev); +} static int sof_suspend(struct device *dev, bool runtime_suspend) { @@ -297,8 +319,12 @@ int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev) { const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); - /* Notify DSP of upcoming power down */ - if (sof_ops(sdev)->remove && pm_ops && pm_ops->ctx_save) + /* + * Notify DSP of upcoming power down only if the firmware has been + * booted up + */ + if (sdev->fw_state == SOF_FW_BOOT_COMPLETE && sof_ops(sdev)->remove && + pm_ops && pm_ops->ctx_save) return pm_ops->ctx_save(sdev); return 0; diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c index 11b6f7da28826b..08d7cb42df0177 100644 --- a/sound/soc/sof/sof-client-ipc-flood-test.c +++ b/sound/soc/sof/sof-client-ipc-flood-test.c @@ -219,9 +219,10 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf goto out; } - /* flood test */ - ret = sof_debug_ipc_flood_test(cdev, flood_duration_test, - ipc_duration_ms, ipc_count); + ret = sof_client_boot_dsp(cdev); + if (!ret) + ret = sof_debug_ipc_flood_test(cdev, flood_duration_test, + ipc_duration_ms, ipc_count); pm_runtime_mark_last_busy(dev); err = pm_runtime_put_autosuspend(dev); diff --git a/sound/soc/sof/sof-client-ipc-kernel-injector.c b/sound/soc/sof/sof-client-ipc-kernel-injector.c index 8b28c3dc920cb0..b1377b2f96f643 100644 --- a/sound/soc/sof/sof-client-ipc-kernel-injector.c +++ b/sound/soc/sof/sof-client-ipc-kernel-injector.c @@ -63,7 +63,9 @@ static ssize_t sof_kernel_msg_inject_dfs_write(struct file *file, const char __u return ret; } - sof_client_ipc_rx_message(cdev, hdr, priv->kernel_buffer); + ret = sof_client_boot_dsp(cdev); + if (!ret) + sof_client_ipc_rx_message(cdev, hdr, priv->kernel_buffer); pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); diff --git a/sound/soc/sof/sof-client-ipc-msg-injector.c b/sound/soc/sof/sof-client-ipc-msg-injector.c index ba7ca1c5027ff0..7ade3e4f606fa8 100644 --- a/sound/soc/sof/sof-client-ipc-msg-injector.c +++ b/sound/soc/sof/sof-client-ipc-msg-injector.c @@ -131,11 +131,15 @@ static int sof_msg_inject_send_message(struct sof_client_dev *cdev) return ret; } - /* send the message */ - ret = sof_client_ipc_tx_message(cdev, priv->tx_buffer, priv->rx_buffer, - priv->max_msg_size); - if (ret) - dev_err(dev, "IPC message send failed: %d\n", ret); + ret = sof_client_boot_dsp(cdev); + if (!ret) { + /* send the message */ + ret = sof_client_ipc_tx_message(cdev, priv->tx_buffer, + priv->rx_buffer, + priv->max_msg_size); + if (ret) + dev_err(dev, "IPC message send failed: %d\n", ret); + } pm_runtime_mark_last_busy(dev); err = pm_runtime_put_autosuspend(dev); diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index f59ca49b0707be..8a0f49633eea75 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -123,6 +123,10 @@ static int sof_probes_compr_set_params(struct snd_compr_stream *cstream, if (ret) return ret; + ret = sof_client_boot_dsp(cdev); + if (ret) + return ret; + ret = ipc->init(cdev, priv->extractor_stream_tag, rtd->dma_bytes); if (ret < 0) { dev_err(dai->dev, "Failed to init probe: %d\n", ret); @@ -224,6 +228,10 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to, goto exit; } + ret = sof_client_boot_dsp(cdev); + if (ret) + goto pm_error; + ret = ipc->points_info(cdev, &desc, &num_desc, type); if (ret < 0) goto pm_error; @@ -313,9 +321,12 @@ sof_probes_dfs_points_write(struct file *file, const char __user *from, goto exit; } - ret = ipc->points_add(cdev, desc, bytes / sizeof(*desc)); - if (!ret) - ret = count; + ret = sof_client_boot_dsp(cdev); + if (!ret) { + ret = ipc->points_add(cdev, desc, bytes / sizeof(*desc)); + if (!ret) + ret = count; + } pm_runtime_mark_last_busy(dev); err = pm_runtime_put_autosuspend(dev); @@ -369,9 +380,12 @@ sof_probes_dfs_points_remove_write(struct file *file, const char __user *from, goto exit; } - ret = ipc->points_remove(cdev, &array[1], array[0]); - if (!ret) - ret = count; + ret = sof_client_boot_dsp(cdev); + if (!ret) { + ret = ipc->points_remove(cdev, &array[1], array[0]); + if (!ret) + ret = count; + } pm_runtime_mark_last_busy(dev); err = pm_runtime_put_autosuspend(dev); diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index 4d0acb8f85cde6..afc1a1bcbb55d6 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -451,6 +451,12 @@ enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev) } EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_type, "SND_SOC_SOF_CLIENT"); +int sof_client_boot_dsp(struct sof_client_dev *cdev) +{ + return snd_sof_boot_dsp_firmware(sof_client_dev_to_sof_dev(cdev)); +} +EXPORT_SYMBOL_NS_GPL(sof_client_boot_dsp, "SND_SOC_SOF_CLIENT"); + /* module refcount management of SOF core */ int sof_client_core_module_get(struct sof_client_dev *cdev) { diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h index c3741b92a26f0c..80bbb7635791b1 100644 --- a/sound/soc/sof/sof-client.h +++ b/sound/soc/sof/sof-client.h @@ -56,6 +56,9 @@ const struct sof_ipc_fw_version *sof_client_get_fw_version(struct sof_client_dev size_t sof_client_get_ipc_max_payload_size(struct sof_client_dev *cdev); enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev); +/* DSP/firmware boot request */ +int sof_client_boot_dsp(struct sof_client_dev *cdev); + /* module refcount management of SOF core */ int sof_client_core_module_get(struct sof_client_dev *cdev); void sof_client_core_module_put(struct sof_client_dev *cdev); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 17847114876886..9904fc42907221 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -591,6 +591,8 @@ struct snd_sof_dev { wait_queue_head_t boot_wait; enum sof_fw_state fw_state; bool first_boot; + /* mutex to protect DSP firmware boot (except initial, probe time boot */ + struct mutex dsp_fw_boot_mutex; /* work queue in case the probe is implemented in two steps */ struct work_struct probe_work; @@ -717,6 +719,7 @@ int snd_sof_suspend(struct device *dev); int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev); int snd_sof_prepare(struct device *dev); void snd_sof_complete(struct device *dev); +int snd_sof_boot_dsp_firmware(struct snd_sof_dev *sdev); void snd_sof_new_platform_drv(struct snd_sof_dev *sdev);