pm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  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.
  5. //
  6. // Copyright(c) 2018 Intel Corporation
  7. //
  8. // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
  9. //
  10. #include <linux/module.h>
  11. #include "ops.h"
  12. #include "sof-priv.h"
  13. #include "sof-audio.h"
  14. static int override_on_demand_boot = -1;
  15. module_param_named(on_demand_boot, override_on_demand_boot, int, 0444);
  16. MODULE_PARM_DESC(on_demand_boot, "Force on-demand DSP boot: 0 - disabled, 1 - enabled");
  17. /*
  18. * Helper function to determine the target DSP state during
  19. * system suspend. This function only cares about the device
  20. * D-states. Platform-specific substates, if any, should be
  21. * handled by the platform-specific parts.
  22. */
  23. static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev)
  24. {
  25. u32 target_dsp_state;
  26. switch (sdev->system_suspend_target) {
  27. case SOF_SUSPEND_S5:
  28. case SOF_SUSPEND_S4:
  29. /* DSP should be in D3 if the system is suspending to S3+ */
  30. case SOF_SUSPEND_S3:
  31. /* DSP should be in D3 if the system is suspending to S3 */
  32. target_dsp_state = SOF_DSP_PM_D3;
  33. break;
  34. case SOF_SUSPEND_S0IX:
  35. /*
  36. * Currently, the only criterion for retaining the DSP in D0
  37. * is that there are streams that ignored the suspend trigger.
  38. * Additional criteria such Soundwire clock-stop mode and
  39. * device suspend latency considerations will be added later.
  40. */
  41. if (snd_sof_stream_suspend_ignored(sdev))
  42. target_dsp_state = SOF_DSP_PM_D0;
  43. else
  44. target_dsp_state = SOF_DSP_PM_D3;
  45. break;
  46. default:
  47. /* This case would be during runtime suspend */
  48. target_dsp_state = SOF_DSP_PM_D3;
  49. break;
  50. }
  51. return target_dsp_state;
  52. }
  53. #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
  54. static void sof_cache_debugfs(struct snd_sof_dev *sdev)
  55. {
  56. struct snd_sof_dfsentry *dfse;
  57. list_for_each_entry(dfse, &sdev->dfsentry_list, list) {
  58. /* nothing to do if debugfs buffer is not IO mem */
  59. if (dfse->type == SOF_DFSENTRY_TYPE_BUF)
  60. continue;
  61. /* cache memory that is only accessible in D0 */
  62. if (dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY)
  63. memcpy_fromio(dfse->cache_buf, dfse->io_mem,
  64. dfse->size);
  65. }
  66. }
  67. #endif
  68. int snd_sof_boot_dsp_firmware(struct snd_sof_dev *sdev)
  69. {
  70. const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm);
  71. const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
  72. int ret;
  73. guard(mutex)(&sdev->dsp_fw_boot_mutex);
  74. if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
  75. /* Firmware already booted, just return */
  76. return 0;
  77. }
  78. dev_dbg(sdev->dev, "Booting DSP firmware\n");
  79. sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);
  80. /* load the firmware */
  81. ret = snd_sof_load_firmware(sdev);
  82. if (ret < 0) {
  83. dev_err(sdev->dev, "%s: failed to load DSP firmware: %d\n",
  84. __func__, ret);
  85. sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED);
  86. return ret;
  87. }
  88. sof_set_fw_state(sdev, SOF_FW_BOOT_IN_PROGRESS);
  89. /*
  90. * Boot the firmware. The FW boot status will be modified
  91. * in snd_sof_run_firmware() depending on the outcome.
  92. */
  93. ret = snd_sof_run_firmware(sdev);
  94. if (ret < 0) {
  95. dev_err(sdev->dev, "%s: failed to boot DSP firmware: %d\n",
  96. __func__, ret);
  97. sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED);
  98. return ret;
  99. }
  100. /* resume DMA trace */
  101. ret = sof_fw_trace_resume(sdev);
  102. if (ret < 0) {
  103. /* non fatal */
  104. dev_warn(sdev->dev, "%s: failed to resume trace: %d\n",
  105. __func__, ret);
  106. }
  107. /* restore pipelines */
  108. if (tplg_ops && tplg_ops->set_up_all_pipelines) {
  109. ret = tplg_ops->set_up_all_pipelines(sdev, false);
  110. if (ret < 0) {
  111. dev_err(sdev->dev, "%s: failed to restore pipeline: %d\n",
  112. __func__, ret);
  113. goto setup_fail;
  114. }
  115. }
  116. /* Notify clients not managed by pm framework about core resume */
  117. sof_resume_clients(sdev);
  118. /* notify DSP of system resume */
  119. if (pm_ops && pm_ops->ctx_restore) {
  120. ret = pm_ops->ctx_restore(sdev);
  121. if (ret < 0)
  122. dev_err(sdev->dev, "%s: ctx_restore IPC failed: %d\n",
  123. __func__, ret);
  124. }
  125. setup_fail:
  126. #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
  127. if (ret < 0) {
  128. /*
  129. * Debugfs cannot be read in runtime suspend, so cache
  130. * the contents upon failure. This allows to capture
  131. * possible DSP coredump information.
  132. */
  133. sof_cache_debugfs(sdev);
  134. }
  135. #endif
  136. return ret;
  137. }
  138. EXPORT_SYMBOL(snd_sof_boot_dsp_firmware);
  139. static int sof_resume(struct device *dev, bool runtime_resume)
  140. {
  141. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  142. u32 old_state = sdev->dsp_power_state.state;
  143. bool on_demand_boot;
  144. int ret;
  145. /* do nothing if dsp resume callbacks are not set */
  146. if (!runtime_resume && !sof_ops(sdev)->resume)
  147. return 0;
  148. if (runtime_resume && !sof_ops(sdev)->runtime_resume)
  149. return 0;
  150. /* DSP was never successfully started, nothing to resume */
  151. if (sdev->first_boot)
  152. return 0;
  153. /*
  154. * if the runtime_resume flag is set, call the runtime_resume routine
  155. * or else call the system resume routine
  156. */
  157. if (runtime_resume)
  158. ret = snd_sof_dsp_runtime_resume(sdev);
  159. else
  160. ret = snd_sof_dsp_resume(sdev);
  161. if (ret < 0) {
  162. dev_err(sdev->dev,
  163. "error: failed to power up DSP after resume\n");
  164. return ret;
  165. }
  166. if (sdev->dspless_mode_selected) {
  167. sof_set_fw_state(sdev, SOF_DSPLESS_MODE);
  168. return 0;
  169. }
  170. /*
  171. * Nothing further to be done for platforms that support the low power
  172. * D0 substate. Resume trace and return when resuming from
  173. * low-power D0 substate
  174. */
  175. if (!runtime_resume && sof_ops(sdev)->set_power_state &&
  176. old_state == SOF_DSP_PM_D0) {
  177. ret = sof_fw_trace_resume(sdev);
  178. if (ret < 0)
  179. /* non fatal */
  180. dev_warn(sdev->dev,
  181. "failed to enable trace after resume %d\n", ret);
  182. return 0;
  183. }
  184. if (override_on_demand_boot > -1)
  185. on_demand_boot = override_on_demand_boot ? true : false;
  186. else
  187. on_demand_boot = sdev->pdata->desc->on_demand_dsp_boot;
  188. if (on_demand_boot) {
  189. /* Only change the fw_state to PREPARE but skip booting */
  190. sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);
  191. return 0;
  192. }
  193. return snd_sof_boot_dsp_firmware(sdev);
  194. }
  195. static int sof_suspend(struct device *dev, bool runtime_suspend)
  196. {
  197. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  198. const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm);
  199. const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
  200. pm_message_t pm_state;
  201. u32 target_state = snd_sof_dsp_power_target(sdev);
  202. u32 old_state = sdev->dsp_power_state.state;
  203. int ret;
  204. /* do nothing if dsp suspend callback is not set */
  205. if (!runtime_suspend && !sof_ops(sdev)->suspend)
  206. return 0;
  207. if (runtime_suspend && !sof_ops(sdev)->runtime_suspend)
  208. return 0;
  209. /* we need to tear down pipelines only if the DSP hardware is
  210. * active, which happens for PCI devices. if the device is
  211. * suspended, it is brought back to full power and then
  212. * suspended again
  213. */
  214. if (tplg_ops && tplg_ops->tear_down_all_pipelines && (old_state == SOF_DSP_PM_D0))
  215. tplg_ops->tear_down_all_pipelines(sdev, false);
  216. if (sdev->fw_state != SOF_FW_BOOT_COMPLETE)
  217. goto suspend;
  218. /* prepare for streams to be resumed properly upon resume */
  219. if (!runtime_suspend) {
  220. ret = snd_sof_dsp_hw_params_upon_resume(sdev);
  221. if (ret < 0) {
  222. dev_err(sdev->dev,
  223. "error: setting hw_params flag during suspend %d\n",
  224. ret);
  225. return ret;
  226. }
  227. }
  228. pm_state.event = target_state;
  229. /* suspend DMA trace */
  230. sof_fw_trace_suspend(sdev, pm_state);
  231. /* Notify clients not managed by pm framework about core suspend */
  232. sof_suspend_clients(sdev, pm_state);
  233. /* Skip to platform-specific suspend if DSP is entering D0 */
  234. if (target_state == SOF_DSP_PM_D0)
  235. goto suspend;
  236. #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
  237. /* cache debugfs contents during runtime suspend */
  238. if (runtime_suspend)
  239. sof_cache_debugfs(sdev);
  240. #endif
  241. /* notify DSP of upcoming power down */
  242. if (pm_ops && pm_ops->ctx_save) {
  243. ret = pm_ops->ctx_save(sdev);
  244. if (ret == -EBUSY || ret == -EAGAIN) {
  245. /*
  246. * runtime PM has logic to handle -EBUSY/-EAGAIN so
  247. * pass these errors up
  248. */
  249. dev_err(sdev->dev, "ctx_save IPC error during suspend: %d\n", ret);
  250. return ret;
  251. } else if (ret < 0) {
  252. /* FW in unexpected state, continue to power down */
  253. dev_warn(sdev->dev, "ctx_save IPC error: %d, proceeding with suspend\n",
  254. ret);
  255. }
  256. }
  257. suspend:
  258. /* return if the DSP was not probed successfully */
  259. if (sdev->fw_state == SOF_FW_BOOT_NOT_STARTED)
  260. return 0;
  261. /* platform-specific suspend */
  262. if (runtime_suspend)
  263. ret = snd_sof_dsp_runtime_suspend(sdev);
  264. else
  265. ret = snd_sof_dsp_suspend(sdev, target_state);
  266. if (ret < 0)
  267. dev_err(sdev->dev,
  268. "error: failed to power down DSP during suspend %d\n",
  269. ret);
  270. /* Do not reset FW state if DSP is in D0 */
  271. if (target_state == SOF_DSP_PM_D0)
  272. return ret;
  273. /* reset FW state */
  274. sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
  275. sdev->enabled_cores_mask = 0;
  276. return ret;
  277. }
  278. int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev)
  279. {
  280. const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm);
  281. /*
  282. * Notify DSP of upcoming power down only if the firmware has been
  283. * booted up
  284. */
  285. if (sdev->fw_state == SOF_FW_BOOT_COMPLETE && sof_ops(sdev)->remove &&
  286. pm_ops && pm_ops->ctx_save)
  287. return pm_ops->ctx_save(sdev);
  288. return 0;
  289. }
  290. int snd_sof_runtime_suspend(struct device *dev)
  291. {
  292. return sof_suspend(dev, true);
  293. }
  294. EXPORT_SYMBOL(snd_sof_runtime_suspend);
  295. int snd_sof_runtime_idle(struct device *dev)
  296. {
  297. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  298. return snd_sof_dsp_runtime_idle(sdev);
  299. }
  300. EXPORT_SYMBOL(snd_sof_runtime_idle);
  301. int snd_sof_runtime_resume(struct device *dev)
  302. {
  303. return sof_resume(dev, true);
  304. }
  305. EXPORT_SYMBOL(snd_sof_runtime_resume);
  306. int snd_sof_resume(struct device *dev)
  307. {
  308. return sof_resume(dev, false);
  309. }
  310. EXPORT_SYMBOL(snd_sof_resume);
  311. int snd_sof_suspend(struct device *dev)
  312. {
  313. return sof_suspend(dev, false);
  314. }
  315. EXPORT_SYMBOL(snd_sof_suspend);
  316. int snd_sof_prepare(struct device *dev)
  317. {
  318. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  319. const struct sof_dev_desc *desc = sdev->pdata->desc;
  320. /* will suspend to S3 by default */
  321. sdev->system_suspend_target = SOF_SUSPEND_S3;
  322. /*
  323. * if the firmware is crashed or boot failed then we try to aim for S3
  324. * to reboot the firmware
  325. */
  326. if (sdev->fw_state == SOF_FW_CRASHED ||
  327. sdev->fw_state == SOF_FW_BOOT_FAILED)
  328. return 0;
  329. if (!desc->use_acpi_target_states)
  330. return 0;
  331. #if defined(CONFIG_ACPI)
  332. switch (acpi_target_system_state()) {
  333. case ACPI_STATE_S0:
  334. sdev->system_suspend_target = SOF_SUSPEND_S0IX;
  335. break;
  336. case ACPI_STATE_S1:
  337. case ACPI_STATE_S2:
  338. case ACPI_STATE_S3:
  339. sdev->system_suspend_target = SOF_SUSPEND_S3;
  340. break;
  341. case ACPI_STATE_S4:
  342. sdev->system_suspend_target = SOF_SUSPEND_S4;
  343. break;
  344. case ACPI_STATE_S5:
  345. sdev->system_suspend_target = SOF_SUSPEND_S5;
  346. break;
  347. default:
  348. break;
  349. }
  350. #endif
  351. return 0;
  352. }
  353. EXPORT_SYMBOL(snd_sof_prepare);
  354. void snd_sof_complete(struct device *dev)
  355. {
  356. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  357. sdev->system_suspend_target = SOF_SUSPEND_NONE;
  358. }
  359. EXPORT_SYMBOL(snd_sof_complete);