162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license. When using or 462306a36Sopenharmony_ci// redistributing this file, you may do so under either license. 562306a36Sopenharmony_ci// 662306a36Sopenharmony_ci// Copyright(c) 2018 Intel Corporation. All rights reserved. 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 962306a36Sopenharmony_ci// 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "ops.h" 1262306a36Sopenharmony_ci#include "sof-priv.h" 1362306a36Sopenharmony_ci#include "sof-audio.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* 1662306a36Sopenharmony_ci * Helper function to determine the target DSP state during 1762306a36Sopenharmony_ci * system suspend. This function only cares about the device 1862306a36Sopenharmony_ci * D-states. Platform-specific substates, if any, should be 1962306a36Sopenharmony_ci * handled by the platform-specific parts. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_cistatic u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci u32 target_dsp_state; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci switch (sdev->system_suspend_target) { 2662306a36Sopenharmony_ci case SOF_SUSPEND_S5: 2762306a36Sopenharmony_ci case SOF_SUSPEND_S4: 2862306a36Sopenharmony_ci /* DSP should be in D3 if the system is suspending to S3+ */ 2962306a36Sopenharmony_ci case SOF_SUSPEND_S3: 3062306a36Sopenharmony_ci /* DSP should be in D3 if the system is suspending to S3 */ 3162306a36Sopenharmony_ci target_dsp_state = SOF_DSP_PM_D3; 3262306a36Sopenharmony_ci break; 3362306a36Sopenharmony_ci case SOF_SUSPEND_S0IX: 3462306a36Sopenharmony_ci /* 3562306a36Sopenharmony_ci * Currently, the only criterion for retaining the DSP in D0 3662306a36Sopenharmony_ci * is that there are streams that ignored the suspend trigger. 3762306a36Sopenharmony_ci * Additional criteria such Soundwire clock-stop mode and 3862306a36Sopenharmony_ci * device suspend latency considerations will be added later. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci if (snd_sof_stream_suspend_ignored(sdev)) 4162306a36Sopenharmony_ci target_dsp_state = SOF_DSP_PM_D0; 4262306a36Sopenharmony_ci else 4362306a36Sopenharmony_ci target_dsp_state = SOF_DSP_PM_D3; 4462306a36Sopenharmony_ci break; 4562306a36Sopenharmony_ci default: 4662306a36Sopenharmony_ci /* This case would be during runtime suspend */ 4762306a36Sopenharmony_ci target_dsp_state = SOF_DSP_PM_D3; 4862306a36Sopenharmony_ci break; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci return target_dsp_state; 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) 5562306a36Sopenharmony_cistatic void sof_cache_debugfs(struct snd_sof_dev *sdev) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct snd_sof_dfsentry *dfse; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci list_for_each_entry(dfse, &sdev->dfsentry_list, list) { 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* nothing to do if debugfs buffer is not IO mem */ 6262306a36Sopenharmony_ci if (dfse->type == SOF_DFSENTRY_TYPE_BUF) 6362306a36Sopenharmony_ci continue; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* cache memory that is only accessible in D0 */ 6662306a36Sopenharmony_ci if (dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) 6762306a36Sopenharmony_ci memcpy_fromio(dfse->cache_buf, dfse->io_mem, 6862306a36Sopenharmony_ci dfse->size); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci#endif 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic int sof_resume(struct device *dev, bool runtime_resume) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci struct snd_sof_dev *sdev = dev_get_drvdata(dev); 7662306a36Sopenharmony_ci const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); 7762306a36Sopenharmony_ci const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 7862306a36Sopenharmony_ci u32 old_state = sdev->dsp_power_state.state; 7962306a36Sopenharmony_ci int ret; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* do nothing if dsp resume callbacks are not set */ 8262306a36Sopenharmony_ci if (!runtime_resume && !sof_ops(sdev)->resume) 8362306a36Sopenharmony_ci return 0; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (runtime_resume && !sof_ops(sdev)->runtime_resume) 8662306a36Sopenharmony_ci return 0; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* DSP was never successfully started, nothing to resume */ 8962306a36Sopenharmony_ci if (sdev->first_boot) 9062306a36Sopenharmony_ci return 0; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* 9362306a36Sopenharmony_ci * if the runtime_resume flag is set, call the runtime_resume routine 9462306a36Sopenharmony_ci * or else call the system resume routine 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci if (runtime_resume) 9762306a36Sopenharmony_ci ret = snd_sof_dsp_runtime_resume(sdev); 9862306a36Sopenharmony_ci else 9962306a36Sopenharmony_ci ret = snd_sof_dsp_resume(sdev); 10062306a36Sopenharmony_ci if (ret < 0) { 10162306a36Sopenharmony_ci dev_err(sdev->dev, 10262306a36Sopenharmony_ci "error: failed to power up DSP after resume\n"); 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (sdev->dspless_mode_selected) { 10762306a36Sopenharmony_ci sof_set_fw_state(sdev, SOF_DSPLESS_MODE); 10862306a36Sopenharmony_ci return 0; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* 11262306a36Sopenharmony_ci * Nothing further to be done for platforms that support the low power 11362306a36Sopenharmony_ci * D0 substate. Resume trace and return when resuming from 11462306a36Sopenharmony_ci * low-power D0 substate 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci if (!runtime_resume && sof_ops(sdev)->set_power_state && 11762306a36Sopenharmony_ci old_state == SOF_DSP_PM_D0) { 11862306a36Sopenharmony_ci ret = sof_fw_trace_resume(sdev); 11962306a36Sopenharmony_ci if (ret < 0) 12062306a36Sopenharmony_ci /* non fatal */ 12162306a36Sopenharmony_ci dev_warn(sdev->dev, 12262306a36Sopenharmony_ci "failed to enable trace after resume %d\n", ret); 12362306a36Sopenharmony_ci return 0; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* load the firmware */ 12962306a36Sopenharmony_ci ret = snd_sof_load_firmware(sdev); 13062306a36Sopenharmony_ci if (ret < 0) { 13162306a36Sopenharmony_ci dev_err(sdev->dev, 13262306a36Sopenharmony_ci "error: failed to load DSP firmware after resume %d\n", 13362306a36Sopenharmony_ci ret); 13462306a36Sopenharmony_ci sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED); 13562306a36Sopenharmony_ci return ret; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci sof_set_fw_state(sdev, SOF_FW_BOOT_IN_PROGRESS); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* 14162306a36Sopenharmony_ci * Boot the firmware. The FW boot status will be modified 14262306a36Sopenharmony_ci * in snd_sof_run_firmware() depending on the outcome. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci ret = snd_sof_run_firmware(sdev); 14562306a36Sopenharmony_ci if (ret < 0) { 14662306a36Sopenharmony_ci dev_err(sdev->dev, 14762306a36Sopenharmony_ci "error: failed to boot DSP firmware after resume %d\n", 14862306a36Sopenharmony_ci ret); 14962306a36Sopenharmony_ci sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED); 15062306a36Sopenharmony_ci return ret; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* resume DMA trace */ 15462306a36Sopenharmony_ci ret = sof_fw_trace_resume(sdev); 15562306a36Sopenharmony_ci if (ret < 0) { 15662306a36Sopenharmony_ci /* non fatal */ 15762306a36Sopenharmony_ci dev_warn(sdev->dev, 15862306a36Sopenharmony_ci "warning: failed to init trace after resume %d\n", 15962306a36Sopenharmony_ci ret); 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* restore pipelines */ 16362306a36Sopenharmony_ci if (tplg_ops && tplg_ops->set_up_all_pipelines) { 16462306a36Sopenharmony_ci ret = tplg_ops->set_up_all_pipelines(sdev, false); 16562306a36Sopenharmony_ci if (ret < 0) { 16662306a36Sopenharmony_ci dev_err(sdev->dev, "Failed to restore pipeline after resume %d\n", ret); 16762306a36Sopenharmony_ci goto setup_fail; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* Notify clients not managed by pm framework about core resume */ 17262306a36Sopenharmony_ci sof_resume_clients(sdev); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* notify DSP of system resume */ 17562306a36Sopenharmony_ci if (pm_ops && pm_ops->ctx_restore) { 17662306a36Sopenharmony_ci ret = pm_ops->ctx_restore(sdev); 17762306a36Sopenharmony_ci if (ret < 0) 17862306a36Sopenharmony_ci dev_err(sdev->dev, "ctx_restore IPC error during resume: %d\n", ret); 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cisetup_fail: 18262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) 18362306a36Sopenharmony_ci if (ret < 0) { 18462306a36Sopenharmony_ci /* 18562306a36Sopenharmony_ci * Debugfs cannot be read in runtime suspend, so cache 18662306a36Sopenharmony_ci * the contents upon failure. This allows to capture 18762306a36Sopenharmony_ci * possible DSP coredump information. 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ci sof_cache_debugfs(sdev); 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci#endif 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return ret; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic int sof_suspend(struct device *dev, bool runtime_suspend) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct snd_sof_dev *sdev = dev_get_drvdata(dev); 19962306a36Sopenharmony_ci const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); 20062306a36Sopenharmony_ci const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 20162306a36Sopenharmony_ci pm_message_t pm_state; 20262306a36Sopenharmony_ci u32 target_state = snd_sof_dsp_power_target(sdev); 20362306a36Sopenharmony_ci u32 old_state = sdev->dsp_power_state.state; 20462306a36Sopenharmony_ci int ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* do nothing if dsp suspend callback is not set */ 20762306a36Sopenharmony_ci if (!runtime_suspend && !sof_ops(sdev)->suspend) 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (runtime_suspend && !sof_ops(sdev)->runtime_suspend) 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* we need to tear down pipelines only if the DSP hardware is 21462306a36Sopenharmony_ci * active, which happens for PCI devices. if the device is 21562306a36Sopenharmony_ci * suspended, it is brought back to full power and then 21662306a36Sopenharmony_ci * suspended again 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_ci if (tplg_ops && tplg_ops->tear_down_all_pipelines && (old_state == SOF_DSP_PM_D0)) 21962306a36Sopenharmony_ci tplg_ops->tear_down_all_pipelines(sdev, false); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (sdev->fw_state != SOF_FW_BOOT_COMPLETE) 22262306a36Sopenharmony_ci goto suspend; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci /* prepare for streams to be resumed properly upon resume */ 22562306a36Sopenharmony_ci if (!runtime_suspend) { 22662306a36Sopenharmony_ci ret = snd_sof_dsp_hw_params_upon_resume(sdev); 22762306a36Sopenharmony_ci if (ret < 0) { 22862306a36Sopenharmony_ci dev_err(sdev->dev, 22962306a36Sopenharmony_ci "error: setting hw_params flag during suspend %d\n", 23062306a36Sopenharmony_ci ret); 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci pm_state.event = target_state; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* suspend DMA trace */ 23862306a36Sopenharmony_ci sof_fw_trace_suspend(sdev, pm_state); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* Notify clients not managed by pm framework about core suspend */ 24162306a36Sopenharmony_ci sof_suspend_clients(sdev, pm_state); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Skip to platform-specific suspend if DSP is entering D0 */ 24462306a36Sopenharmony_ci if (target_state == SOF_DSP_PM_D0) 24562306a36Sopenharmony_ci goto suspend; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) 24862306a36Sopenharmony_ci /* cache debugfs contents during runtime suspend */ 24962306a36Sopenharmony_ci if (runtime_suspend) 25062306a36Sopenharmony_ci sof_cache_debugfs(sdev); 25162306a36Sopenharmony_ci#endif 25262306a36Sopenharmony_ci /* notify DSP of upcoming power down */ 25362306a36Sopenharmony_ci if (pm_ops && pm_ops->ctx_save) { 25462306a36Sopenharmony_ci ret = pm_ops->ctx_save(sdev); 25562306a36Sopenharmony_ci if (ret == -EBUSY || ret == -EAGAIN) { 25662306a36Sopenharmony_ci /* 25762306a36Sopenharmony_ci * runtime PM has logic to handle -EBUSY/-EAGAIN so 25862306a36Sopenharmony_ci * pass these errors up 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci dev_err(sdev->dev, "ctx_save IPC error during suspend: %d\n", ret); 26162306a36Sopenharmony_ci return ret; 26262306a36Sopenharmony_ci } else if (ret < 0) { 26362306a36Sopenharmony_ci /* FW in unexpected state, continue to power down */ 26462306a36Sopenharmony_ci dev_warn(sdev->dev, "ctx_save IPC error: %d, proceeding with suspend\n", 26562306a36Sopenharmony_ci ret); 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cisuspend: 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* return if the DSP was not probed successfully */ 27262306a36Sopenharmony_ci if (sdev->fw_state == SOF_FW_BOOT_NOT_STARTED) 27362306a36Sopenharmony_ci return 0; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* platform-specific suspend */ 27662306a36Sopenharmony_ci if (runtime_suspend) 27762306a36Sopenharmony_ci ret = snd_sof_dsp_runtime_suspend(sdev); 27862306a36Sopenharmony_ci else 27962306a36Sopenharmony_ci ret = snd_sof_dsp_suspend(sdev, target_state); 28062306a36Sopenharmony_ci if (ret < 0) 28162306a36Sopenharmony_ci dev_err(sdev->dev, 28262306a36Sopenharmony_ci "error: failed to power down DSP during suspend %d\n", 28362306a36Sopenharmony_ci ret); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* Do not reset FW state if DSP is in D0 */ 28662306a36Sopenharmony_ci if (target_state == SOF_DSP_PM_D0) 28762306a36Sopenharmony_ci return ret; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* reset FW state */ 29062306a36Sopenharmony_ci sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED); 29162306a36Sopenharmony_ci sdev->enabled_cores_mask = 0; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci return ret; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ciint snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* Notify DSP of upcoming power down */ 30162306a36Sopenharmony_ci if (sof_ops(sdev)->remove && pm_ops && pm_ops->ctx_save) 30262306a36Sopenharmony_ci return pm_ops->ctx_save(sdev); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return 0; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ciint snd_sof_runtime_suspend(struct device *dev) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci return sof_suspend(dev, true); 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_runtime_suspend); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciint snd_sof_runtime_idle(struct device *dev) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci struct snd_sof_dev *sdev = dev_get_drvdata(dev); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci return snd_sof_dsp_runtime_idle(sdev); 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_runtime_idle); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ciint snd_sof_runtime_resume(struct device *dev) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci return sof_resume(dev, true); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_runtime_resume); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ciint snd_sof_resume(struct device *dev) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci return sof_resume(dev, false); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_resume); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ciint snd_sof_suspend(struct device *dev) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci return sof_suspend(dev, false); 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_suspend); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ciint snd_sof_prepare(struct device *dev) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct snd_sof_dev *sdev = dev_get_drvdata(dev); 34262306a36Sopenharmony_ci const struct sof_dev_desc *desc = sdev->pdata->desc; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* will suspend to S3 by default */ 34562306a36Sopenharmony_ci sdev->system_suspend_target = SOF_SUSPEND_S3; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* 34862306a36Sopenharmony_ci * if the firmware is crashed or boot failed then we try to aim for S3 34962306a36Sopenharmony_ci * to reboot the firmware 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci if (sdev->fw_state == SOF_FW_CRASHED || 35262306a36Sopenharmony_ci sdev->fw_state == SOF_FW_BOOT_FAILED) 35362306a36Sopenharmony_ci return 0; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (!desc->use_acpi_target_states) 35662306a36Sopenharmony_ci return 0; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci#if defined(CONFIG_ACPI) 35962306a36Sopenharmony_ci switch (acpi_target_system_state()) { 36062306a36Sopenharmony_ci case ACPI_STATE_S0: 36162306a36Sopenharmony_ci sdev->system_suspend_target = SOF_SUSPEND_S0IX; 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci case ACPI_STATE_S1: 36462306a36Sopenharmony_ci case ACPI_STATE_S2: 36562306a36Sopenharmony_ci case ACPI_STATE_S3: 36662306a36Sopenharmony_ci sdev->system_suspend_target = SOF_SUSPEND_S3; 36762306a36Sopenharmony_ci break; 36862306a36Sopenharmony_ci case ACPI_STATE_S4: 36962306a36Sopenharmony_ci sdev->system_suspend_target = SOF_SUSPEND_S4; 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci case ACPI_STATE_S5: 37262306a36Sopenharmony_ci sdev->system_suspend_target = SOF_SUSPEND_S5; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci default: 37562306a36Sopenharmony_ci break; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci#endif 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return 0; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_prepare); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_civoid snd_sof_complete(struct device *dev) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci struct snd_sof_dev *sdev = dev_get_drvdata(dev); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci sdev->system_suspend_target = SOF_SUSPEND_NONE; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ciEXPORT_SYMBOL(snd_sof_complete); 390