diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 5de30087ded6d7..fb6e9d742695c8 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -80,6 +80,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = { /* dsp core power up/down */ .core_power_up = hda_dsp_enable_core, .core_power_down = hda_dsp_core_reset_power_down, + .is_core_enabled = hda_dsp_core_is_enabled, /* trace callback */ .trace_init = hda_dsp_trace_init, diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index cf7438ce19eb20..585e6ba8820484 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -79,6 +79,15 @@ static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev, return 0; } +static inline int snd_sof_dsp_core_is_enabled(struct snd_sof_dev *sdev, + unsigned int core_mask) +{ + if (sdev->ops->is_core_enabled) + return sdev->ops->is_core_enabled(sdev, core_mask); + + return 0; +} + /* pre/post fw load */ static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 77388a36434bed..83a51d204de7d1 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -236,6 +236,15 @@ static int sof_resume(struct device *dev, bool runtime_resume) if (!sdev->ops->resume || !sdev->ops->runtime_resume) return 0; + /* + * If for some reason, the cores were not powered off + * during suspend, powering them up again will lead to + * DSP panic. So check if core 0 is powered off to make + * sure before proceeding further. + */ + if (snd_sof_dsp_core_is_enabled(sdev, BIT(0)) + return 0; + /* * if the runtime_resume flag is set, call the runtime_resume routine * or else call the system resume routine diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 1ada7eab46c887..effe732fb0b4ac 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -79,6 +79,8 @@ struct snd_sof_dsp_ops { unsigned int core_mask); int (*core_power_down)(struct snd_sof_dev *sof_dev, unsigned int core_mask); + bool (*is_core_enabled)(struct snd_sof_dev *sof_dev, + unsigned int core_mask); /* pre/post firmware run */ int (*pre_fw_run)(struct snd_sof_dev *sof_dev);