@@ -70,67 +70,28 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev)
7070}
7171#endif
7272
73- static int sof_resume (struct device * dev , bool runtime_resume )
73+ int snd_sof_boot_dsp_firmware (struct snd_sof_dev * sdev )
7474{
75- struct snd_sof_dev * sdev = dev_get_drvdata (dev );
7675 const struct sof_ipc_pm_ops * pm_ops = sof_ipc_get_ops (sdev , pm );
7776 const struct sof_ipc_tplg_ops * tplg_ops = sof_ipc_get_ops (sdev , tplg );
78- u32 old_state = sdev -> dsp_power_state .state ;
7977 int ret ;
8078
81- /* do nothing if dsp resume callbacks are not set */
82- if (!runtime_resume && !sof_ops (sdev )-> resume )
83- return 0 ;
84-
85- if (runtime_resume && !sof_ops (sdev )-> runtime_resume )
86- return 0 ;
79+ guard (mutex )(& sdev -> dsp_fw_boot_mutex );
8780
88- /* DSP was never successfully started, nothing to resume */
89- if ( sdev -> first_boot )
81+ if ( sdev -> fw_state == SOF_FW_BOOT_COMPLETE ) {
82+ /* Firmware already booted, just return */
9083 return 0 ;
91-
92- /*
93- * if the runtime_resume flag is set, call the runtime_resume routine
94- * or else call the system resume routine
95- */
96- if (runtime_resume )
97- ret = snd_sof_dsp_runtime_resume (sdev );
98- else
99- ret = snd_sof_dsp_resume (sdev );
100- if (ret < 0 ) {
101- dev_err (sdev -> dev ,
102- "error: failed to power up DSP after resume\n" );
103- return ret ;
10484 }
10585
106- if (sdev -> dspless_mode_selected ) {
107- sof_set_fw_state (sdev , SOF_DSPLESS_MODE );
108- return 0 ;
109- }
110-
111- /*
112- * Nothing further to be done for platforms that support the low power
113- * D0 substate. Resume trace and return when resuming from
114- * low-power D0 substate
115- */
116- if (!runtime_resume && sof_ops (sdev )-> set_power_state &&
117- old_state == SOF_DSP_PM_D0 ) {
118- ret = sof_fw_trace_resume (sdev );
119- if (ret < 0 )
120- /* non fatal */
121- dev_warn (sdev -> dev ,
122- "failed to enable trace after resume %d\n" , ret );
123- return 0 ;
124- }
86+ dev_dbg (sdev -> dev , "Booting DSP firmware\n" );
12587
12688 sof_set_fw_state (sdev , SOF_FW_BOOT_PREPARE );
12789
12890 /* load the firmware */
12991 ret = snd_sof_load_firmware (sdev , NULL );
13092 if (ret < 0 ) {
131- dev_err (sdev -> dev ,
132- "error: failed to load DSP firmware after resume %d\n" ,
133- ret );
93+ dev_err (sdev -> dev , "%s: failed to load DSP firmware: %d\n" ,
94+ __func__ , ret );
13495 sof_set_fw_state (sdev , SOF_FW_BOOT_FAILED );
13596 return ret ;
13697 }
@@ -143,9 +104,8 @@ static int sof_resume(struct device *dev, bool runtime_resume)
143104 */
144105 ret = snd_sof_run_firmware (sdev );
145106 if (ret < 0 ) {
146- dev_err (sdev -> dev ,
147- "error: failed to boot DSP firmware after resume %d\n" ,
148- ret );
107+ dev_err (sdev -> dev , "%s: failed to boot DSP firmware: %d\n" ,
108+ __func__ , ret );
149109 sof_set_fw_state (sdev , SOF_FW_BOOT_FAILED );
150110 return ret ;
151111 }
@@ -154,16 +114,16 @@ static int sof_resume(struct device *dev, bool runtime_resume)
154114 ret = sof_fw_trace_resume (sdev );
155115 if (ret < 0 ) {
156116 /* non fatal */
157- dev_warn (sdev -> dev ,
158- "warning: failed to init trace after resume %d\n" ,
159- ret );
117+ dev_warn (sdev -> dev , "%s: failed to resume trace: %d\n" ,
118+ __func__ , ret );
160119 }
161120
162121 /* restore pipelines */
163122 if (tplg_ops && tplg_ops -> set_up_all_pipelines ) {
164123 ret = tplg_ops -> set_up_all_pipelines (sdev , false);
165124 if (ret < 0 ) {
166- dev_err (sdev -> dev , "Failed to restore pipeline after resume %d\n" , ret );
125+ dev_err (sdev -> dev , "%s: failed to restore pipeline: %d\n" ,
126+ __func__ , ret );
167127 goto setup_fail ;
168128 }
169129 }
@@ -175,7 +135,8 @@ static int sof_resume(struct device *dev, bool runtime_resume)
175135 if (pm_ops && pm_ops -> ctx_restore ) {
176136 ret = pm_ops -> ctx_restore (sdev );
177137 if (ret < 0 )
178- dev_err (sdev -> dev , "ctx_restore IPC error during resume: %d\n" , ret );
138+ dev_err (sdev -> dev , "%s: ctx_restore IPC failed: %d\n" ,
139+ __func__ , ret );
179140 }
180141
181142setup_fail :
@@ -192,6 +153,67 @@ static int sof_resume(struct device *dev, bool runtime_resume)
192153
193154 return ret ;
194155}
156+ EXPORT_SYMBOL (snd_sof_boot_dsp_firmware );
157+
158+ static int sof_resume (struct device * dev , bool runtime_resume )
159+ {
160+ struct snd_sof_dev * sdev = dev_get_drvdata (dev );
161+ u32 old_state = sdev -> dsp_power_state .state ;
162+ int ret ;
163+
164+ /* do nothing if dsp resume callbacks are not set */
165+ if (!runtime_resume && !sof_ops (sdev )-> resume )
166+ return 0 ;
167+
168+ if (runtime_resume && !sof_ops (sdev )-> runtime_resume )
169+ return 0 ;
170+
171+ /* DSP was never successfully started, nothing to resume */
172+ if (sdev -> first_boot )
173+ return 0 ;
174+
175+ /*
176+ * if the runtime_resume flag is set, call the runtime_resume routine
177+ * or else call the system resume routine
178+ */
179+ if (runtime_resume )
180+ ret = snd_sof_dsp_runtime_resume (sdev );
181+ else
182+ ret = snd_sof_dsp_resume (sdev );
183+ if (ret < 0 ) {
184+ dev_err (sdev -> dev ,
185+ "error: failed to power up DSP after resume\n" );
186+ return ret ;
187+ }
188+
189+ if (sdev -> dspless_mode_selected ) {
190+ sof_set_fw_state (sdev , SOF_DSPLESS_MODE );
191+ return 0 ;
192+ }
193+
194+ /*
195+ * Nothing further to be done for platforms that support the low power
196+ * D0 substate. Resume trace and return when resuming from
197+ * low-power D0 substate
198+ */
199+ if (!runtime_resume && sof_ops (sdev )-> set_power_state &&
200+ old_state == SOF_DSP_PM_D0 ) {
201+ ret = sof_fw_trace_resume (sdev );
202+ if (ret < 0 )
203+ /* non fatal */
204+ dev_warn (sdev -> dev ,
205+ "failed to enable trace after resume %d\n" , ret );
206+ return 0 ;
207+ }
208+
209+ if (sdev -> pdata -> desc -> on_demand_dsp_boot ) {
210+ /* Only change the fw_state to PREPARE but skip booting */
211+ sof_set_fw_state (sdev , SOF_FW_BOOT_PREPARE );
212+ return 0 ;
213+ }
214+
215+ return snd_sof_boot_dsp_firmware (sdev );
216+ }
195217
196218static int sof_suspend (struct device * dev , bool runtime_suspend )
197219{
@@ -297,8 +319,12 @@ int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev)
297319{
298320 const struct sof_ipc_pm_ops * pm_ops = sof_ipc_get_ops (sdev , pm );
299321
300- /* Notify DSP of upcoming power down */
301- if (sof_ops (sdev )-> remove && pm_ops && pm_ops -> ctx_save )
322+ /*
323+ * Notify DSP of upcoming power down only if the firmware has been
324+ * booted up
325+ */
326+ if (sdev -> fw_state == SOF_FW_BOOT_COMPLETE && sof_ops (sdev )-> remove &&
327+ pm_ops && pm_ops -> ctx_save )
302328 return pm_ops -> ctx_save (sdev );
303329
304330 return 0 ;
0 commit comments