Merge branch 'fixes-rc1' into fixes
[linux-2.6-microblaze.git] / sound / soc / sof / core.c
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. All rights reserved.
7 //
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //
10
11 #include <linux/firmware.h>
12 #include <linux/module.h>
13 #include <sound/soc.h>
14 #include <sound/sof.h>
15 #include "sof-priv.h"
16 #include "ops.h"
17 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
18 #include "probe.h"
19 #endif
20
21 /* see SOF_DBG_ flags */
22 int sof_core_debug;
23 module_param_named(sof_debug, sof_core_debug, int, 0444);
24 MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)");
25
26 /* SOF defaults if not provided by the platform in ms */
27 #define TIMEOUT_DEFAULT_IPC_MS  500
28 #define TIMEOUT_DEFAULT_BOOT_MS 2000
29
30 /*
31  * FW Panic/fault handling.
32  */
33
34 struct sof_panic_msg {
35         u32 id;
36         const char *msg;
37 };
38
39 /* standard FW panic types */
40 static const struct sof_panic_msg panic_msg[] = {
41         {SOF_IPC_PANIC_MEM, "out of memory"},
42         {SOF_IPC_PANIC_WORK, "work subsystem init failed"},
43         {SOF_IPC_PANIC_IPC, "IPC subsystem init failed"},
44         {SOF_IPC_PANIC_ARCH, "arch init failed"},
45         {SOF_IPC_PANIC_PLATFORM, "platform init failed"},
46         {SOF_IPC_PANIC_TASK, "scheduler init failed"},
47         {SOF_IPC_PANIC_EXCEPTION, "runtime exception"},
48         {SOF_IPC_PANIC_DEADLOCK, "deadlock"},
49         {SOF_IPC_PANIC_STACK, "stack overflow"},
50         {SOF_IPC_PANIC_IDLE, "can't enter idle"},
51         {SOF_IPC_PANIC_WFI, "invalid wait state"},
52         {SOF_IPC_PANIC_ASSERT, "assertion failed"},
53 };
54
55 /*
56  * helper to be called from .dbg_dump callbacks. No error code is
57  * provided, it's left as an exercise for the caller of .dbg_dump
58  * (typically IPC or loader)
59  */
60 void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
61                         u32 tracep_code, void *oops,
62                         struct sof_ipc_panic_info *panic_info,
63                         void *stack, size_t stack_words)
64 {
65         u32 code;
66         int i;
67
68         /* is firmware dead ? */
69         if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) != SOF_IPC_PANIC_MAGIC) {
70                 dev_err(sdev->dev, "error: unexpected fault 0x%8.8x trace 0x%8.8x\n",
71                         panic_code, tracep_code);
72                 return; /* no fault ? */
73         }
74
75         code = panic_code & (SOF_IPC_PANIC_MAGIC_MASK | SOF_IPC_PANIC_CODE_MASK);
76
77         for (i = 0; i < ARRAY_SIZE(panic_msg); i++) {
78                 if (panic_msg[i].id == code) {
79                         dev_err(sdev->dev, "error: %s\n", panic_msg[i].msg);
80                         dev_err(sdev->dev, "error: trace point %8.8x\n",
81                                 tracep_code);
82                         goto out;
83                 }
84         }
85
86         /* unknown error */
87         dev_err(sdev->dev, "error: unknown reason %8.8x\n", panic_code);
88         dev_err(sdev->dev, "error: trace point %8.8x\n", tracep_code);
89
90 out:
91         dev_err(sdev->dev, "error: panic at %s:%d\n",
92                 panic_info->filename, panic_info->linenum);
93         sof_oops(sdev, oops);
94         sof_stack(sdev, oops, stack, stack_words);
95 }
96 EXPORT_SYMBOL(snd_sof_get_status);
97
98 /*
99  *                      FW Boot State Transition Diagram
100  *
101  *    +-----------------------------------------------------------------------+
102  *    |                                                                       |
103  * ------------------        ------------------                               |
104  * |                |        |                |                               |
105  * |   BOOT_FAILED  |        |  READY_FAILED  |-------------------------+     |
106  * |                |        |                |                         |     |
107  * ------------------        ------------------                         |     |
108  *      ^                           ^                                   |     |
109  *      |                           |                                   |     |
110  * (FW Boot Timeout)            (FW_READY FAIL)                         |     |
111  *      |                           |                                   |     |
112  *      |                           |                                   |     |
113  * ------------------               |              ------------------   |     |
114  * |                |               |              |                |   |     |
115  * |   IN_PROGRESS  |---------------+------------->|    COMPLETE    |   |     |
116  * |                | (FW Boot OK)   (FW_READY OK) |                |   |     |
117  * ------------------                              ------------------   |     |
118  *      ^                                               |               |     |
119  *      |                                               |               |     |
120  * (FW Loading OK)                             (System Suspend/Runtime Suspend)
121  *      |                                               |               |     |
122  *      |                                               |               |     |
123  * ------------------           ------------------      |               |     |
124  * |                |           |                |<-----+               |     |
125  * |   PREPARE      |           |   NOT_STARTED  |<---------------------+     |
126  * |                |           |                |<---------------------------+
127  * ------------------           ------------------
128  *    |     ^                       |      ^
129  *    |     |                       |      |
130  *    |     +-----------------------+      |
131  *    |         (DSP Probe OK)             |
132  *    |                                    |
133  *    |                                    |
134  *    +------------------------------------+
135  *      (System Suspend/Runtime Suspend)
136  */
137
138 static int sof_probe_continue(struct snd_sof_dev *sdev)
139 {
140         struct snd_sof_pdata *plat_data = sdev->pdata;
141         int ret;
142
143         /* probe the DSP hardware */
144         ret = snd_sof_probe(sdev);
145         if (ret < 0) {
146                 dev_err(sdev->dev, "error: failed to probe DSP %d\n", ret);
147                 return ret;
148         }
149
150         sdev->fw_state = SOF_FW_BOOT_PREPARE;
151
152         /* check machine info */
153         ret = sof_machine_check(sdev);
154         if (ret < 0) {
155                 dev_err(sdev->dev, "error: failed to get machine info %d\n",
156                         ret);
157                 goto dsp_err;
158         }
159
160         /* set up platform component driver */
161         snd_sof_new_platform_drv(sdev);
162
163         /* register any debug/trace capabilities */
164         ret = snd_sof_dbg_init(sdev);
165         if (ret < 0) {
166                 /*
167                  * debugfs issues are suppressed in snd_sof_dbg_init() since
168                  * we cannot rely on debugfs
169                  * here we trap errors due to memory allocation only.
170                  */
171                 dev_err(sdev->dev, "error: failed to init DSP trace/debug %d\n",
172                         ret);
173                 goto dbg_err;
174         }
175
176         /* init the IPC */
177         sdev->ipc = snd_sof_ipc_init(sdev);
178         if (!sdev->ipc) {
179                 ret = -ENOMEM;
180                 dev_err(sdev->dev, "error: failed to init DSP IPC %d\n", ret);
181                 goto ipc_err;
182         }
183
184         /* load the firmware */
185         ret = snd_sof_load_firmware(sdev);
186         if (ret < 0) {
187                 dev_err(sdev->dev, "error: failed to load DSP firmware %d\n",
188                         ret);
189                 goto fw_load_err;
190         }
191
192         sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS;
193
194         /*
195          * Boot the firmware. The FW boot status will be modified
196          * in snd_sof_run_firmware() depending on the outcome.
197          */
198         ret = snd_sof_run_firmware(sdev);
199         if (ret < 0) {
200                 dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n",
201                         ret);
202                 goto fw_run_err;
203         }
204
205         if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE) ||
206             (sof_core_debug & SOF_DBG_ENABLE_TRACE)) {
207                 sdev->dtrace_is_supported = true;
208
209                 /* init DMA trace */
210                 ret = snd_sof_init_trace(sdev);
211                 if (ret < 0) {
212                         /* non fatal */
213                         dev_warn(sdev->dev,
214                                  "warning: failed to initialize trace %d\n",
215                                  ret);
216                 }
217         } else {
218                 dev_dbg(sdev->dev, "SOF firmware trace disabled\n");
219         }
220
221         /* hereafter all FW boot flows are for PM reasons */
222         sdev->first_boot = false;
223
224         /* now register audio DSP platform driver and dai */
225         ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv,
226                                               sof_ops(sdev)->drv,
227                                               sof_ops(sdev)->num_drv);
228         if (ret < 0) {
229                 dev_err(sdev->dev,
230                         "error: failed to register DSP DAI driver %d\n", ret);
231                 goto fw_trace_err;
232         }
233
234         ret = snd_sof_machine_register(sdev, plat_data);
235         if (ret < 0) {
236                 dev_err(sdev->dev,
237                         "error: failed to register machine driver %d\n", ret);
238                 goto fw_trace_err;
239         }
240
241         /*
242          * Some platforms in SOF, ex: BYT, may not have their platform PM
243          * callbacks set. Increment the usage count so as to
244          * prevent the device from entering runtime suspend.
245          */
246         if (!sof_ops(sdev)->runtime_suspend || !sof_ops(sdev)->runtime_resume)
247                 pm_runtime_get_noresume(sdev->dev);
248
249         if (plat_data->sof_probe_complete)
250                 plat_data->sof_probe_complete(sdev->dev);
251
252         sdev->probe_completed = true;
253
254         return 0;
255
256 fw_trace_err:
257         snd_sof_free_trace(sdev);
258 fw_run_err:
259         snd_sof_fw_unload(sdev);
260 fw_load_err:
261         snd_sof_ipc_free(sdev);
262 ipc_err:
263 dbg_err:
264         snd_sof_free_debug(sdev);
265 dsp_err:
266         snd_sof_remove(sdev);
267
268         /* all resources freed, update state to match */
269         sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
270         sdev->first_boot = true;
271
272         return ret;
273 }
274
275 static void sof_probe_work(struct work_struct *work)
276 {
277         struct snd_sof_dev *sdev =
278                 container_of(work, struct snd_sof_dev, probe_work);
279         int ret;
280
281         ret = sof_probe_continue(sdev);
282         if (ret < 0) {
283                 /* errors cannot be propagated, log */
284                 dev_err(sdev->dev, "error: %s failed err: %d\n", __func__, ret);
285         }
286 }
287
288 int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
289 {
290         struct snd_sof_dev *sdev;
291
292         sdev = devm_kzalloc(dev, sizeof(*sdev), GFP_KERNEL);
293         if (!sdev)
294                 return -ENOMEM;
295
296         /* initialize sof device */
297         sdev->dev = dev;
298
299         /* initialize default DSP power state */
300         sdev->dsp_power_state.state = SOF_DSP_PM_D0;
301
302         sdev->pdata = plat_data;
303         sdev->first_boot = true;
304         sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
305 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
306         sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
307 #endif
308         dev_set_drvdata(dev, sdev);
309
310         /* check all mandatory ops */
311         if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run ||
312             !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write ||
313             !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware ||
314             !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params ||
315             !sof_ops(sdev)->fw_ready) {
316                 dev_err(dev, "error: missing mandatory ops\n");
317                 return -EINVAL;
318         }
319
320         INIT_LIST_HEAD(&sdev->pcm_list);
321         INIT_LIST_HEAD(&sdev->kcontrol_list);
322         INIT_LIST_HEAD(&sdev->widget_list);
323         INIT_LIST_HEAD(&sdev->dai_list);
324         INIT_LIST_HEAD(&sdev->route_list);
325         spin_lock_init(&sdev->ipc_lock);
326         spin_lock_init(&sdev->hw_lock);
327         mutex_init(&sdev->power_state_access);
328
329         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
330                 INIT_WORK(&sdev->probe_work, sof_probe_work);
331
332         /* set default timeouts if none provided */
333         if (plat_data->desc->ipc_timeout == 0)
334                 sdev->ipc_timeout = TIMEOUT_DEFAULT_IPC_MS;
335         else
336                 sdev->ipc_timeout = plat_data->desc->ipc_timeout;
337         if (plat_data->desc->boot_timeout == 0)
338                 sdev->boot_timeout = TIMEOUT_DEFAULT_BOOT_MS;
339         else
340                 sdev->boot_timeout = plat_data->desc->boot_timeout;
341
342         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
343                 schedule_work(&sdev->probe_work);
344                 return 0;
345         }
346
347         return sof_probe_continue(sdev);
348 }
349 EXPORT_SYMBOL(snd_sof_device_probe);
350
351 bool snd_sof_device_probe_completed(struct device *dev)
352 {
353         struct snd_sof_dev *sdev = dev_get_drvdata(dev);
354
355         return sdev->probe_completed;
356 }
357 EXPORT_SYMBOL(snd_sof_device_probe_completed);
358
359 int snd_sof_device_remove(struct device *dev)
360 {
361         struct snd_sof_dev *sdev = dev_get_drvdata(dev);
362         struct snd_sof_pdata *pdata = sdev->pdata;
363         int ret;
364
365         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
366                 cancel_work_sync(&sdev->probe_work);
367
368         if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) {
369                 ret = snd_sof_dsp_power_down_notify(sdev);
370                 if (ret < 0)
371                         dev_warn(dev, "error: %d failed to prepare DSP for device removal",
372                                  ret);
373
374                 snd_sof_fw_unload(sdev);
375                 snd_sof_ipc_free(sdev);
376                 snd_sof_free_debug(sdev);
377                 snd_sof_free_trace(sdev);
378         }
379
380         /*
381          * Unregister machine driver. This will unbind the snd_card which
382          * will remove the component driver and unload the topology
383          * before freeing the snd_card.
384          */
385         snd_sof_machine_unregister(sdev, pdata);
386
387         /*
388          * Unregistering the machine driver results in unloading the topology.
389          * Some widgets, ex: scheduler, attempt to power down the core they are
390          * scheduled on, when they are unloaded. Therefore, the DSP must be
391          * removed only after the topology has been unloaded.
392          */
393         if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED)
394                 snd_sof_remove(sdev);
395
396         /* release firmware */
397         release_firmware(pdata->fw);
398         pdata->fw = NULL;
399
400         return 0;
401 }
402 EXPORT_SYMBOL(snd_sof_device_remove);
403
404 int snd_sof_device_shutdown(struct device *dev)
405 {
406         struct snd_sof_dev *sdev = dev_get_drvdata(dev);
407
408         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
409                 cancel_work_sync(&sdev->probe_work);
410
411         if (sdev->fw_state == SOF_FW_BOOT_COMPLETE)
412                 return snd_sof_shutdown(sdev);
413
414         return 0;
415 }
416 EXPORT_SYMBOL(snd_sof_device_shutdown);
417
418 MODULE_AUTHOR("Liam Girdwood");
419 MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
420 MODULE_LICENSE("Dual BSD/GPL");
421 MODULE_ALIAS("platform:sof-audio");