]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/soc/sof/core.c
ASoC: SOF: trace: move to opt-in with Kconfig and module parameter
[linux.git] / sound / soc / sof / core.c
1 // SPDX-License-Identifier: (GPL-2.0 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 <asm/unaligned.h>
14 #include <sound/soc.h>
15 #include <sound/sof.h>
16 #include "sof-priv.h"
17 #include "ops.h"
18
19 /* see SOF_DBG_ flags */
20 int sof_core_debug;
21 module_param_named(sof_debug, sof_core_debug, int, 0444);
22 MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)");
23
24 /* SOF defaults if not provided by the platform in ms */
25 #define TIMEOUT_DEFAULT_IPC_MS  500
26 #define TIMEOUT_DEFAULT_BOOT_MS 2000
27
28 /*
29  * Generic object lookup APIs.
30  */
31
32 struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_sof_dev *sdev,
33                                            const char *name)
34 {
35         struct snd_sof_pcm *spcm;
36
37         list_for_each_entry(spcm, &sdev->pcm_list, list) {
38                 /* match with PCM dai name */
39                 if (strcmp(spcm->pcm.dai_name, name) == 0)
40                         return spcm;
41
42                 /* match with playback caps name if set */
43                 if (*spcm->pcm.caps[0].name &&
44                     !strcmp(spcm->pcm.caps[0].name, name))
45                         return spcm;
46
47                 /* match with capture caps name if set */
48                 if (*spcm->pcm.caps[1].name &&
49                     !strcmp(spcm->pcm.caps[1].name, name))
50                         return spcm;
51         }
52
53         return NULL;
54 }
55
56 struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev,
57                                            unsigned int comp_id,
58                                            int *direction)
59 {
60         struct snd_sof_pcm *spcm;
61
62         list_for_each_entry(spcm, &sdev->pcm_list, list) {
63                 if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id == comp_id) {
64                         *direction = SNDRV_PCM_STREAM_PLAYBACK;
65                         return spcm;
66                 }
67                 if (spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id == comp_id) {
68                         *direction = SNDRV_PCM_STREAM_CAPTURE;
69                         return spcm;
70                 }
71         }
72
73         return NULL;
74 }
75
76 struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_sof_dev *sdev,
77                                              unsigned int pcm_id)
78 {
79         struct snd_sof_pcm *spcm;
80
81         list_for_each_entry(spcm, &sdev->pcm_list, list) {
82                 if (le32_to_cpu(spcm->pcm.pcm_id) == pcm_id)
83                         return spcm;
84         }
85
86         return NULL;
87 }
88
89 struct snd_sof_widget *snd_sof_find_swidget(struct snd_sof_dev *sdev,
90                                             const char *name)
91 {
92         struct snd_sof_widget *swidget;
93
94         list_for_each_entry(swidget, &sdev->widget_list, list) {
95                 if (strcmp(name, swidget->widget->name) == 0)
96                         return swidget;
97         }
98
99         return NULL;
100 }
101
102 /* find widget by stream name and direction */
103 struct snd_sof_widget *snd_sof_find_swidget_sname(struct snd_sof_dev *sdev,
104                                                   const char *pcm_name, int dir)
105 {
106         struct snd_sof_widget *swidget;
107         enum snd_soc_dapm_type type;
108
109         if (dir == SNDRV_PCM_STREAM_PLAYBACK)
110                 type = snd_soc_dapm_aif_in;
111         else
112                 type = snd_soc_dapm_aif_out;
113
114         list_for_each_entry(swidget, &sdev->widget_list, list) {
115                 if (!strcmp(pcm_name, swidget->widget->sname) && swidget->id == type)
116                         return swidget;
117         }
118
119         return NULL;
120 }
121
122 struct snd_sof_dai *snd_sof_find_dai(struct snd_sof_dev *sdev,
123                                      const char *name)
124 {
125         struct snd_sof_dai *dai;
126
127         list_for_each_entry(dai, &sdev->dai_list, list) {
128                 if (dai->name && (strcmp(name, dai->name) == 0))
129                         return dai;
130         }
131
132         return NULL;
133 }
134
135 /*
136  * FW Panic/fault handling.
137  */
138
139 struct sof_panic_msg {
140         u32 id;
141         const char *msg;
142 };
143
144 /* standard FW panic types */
145 static const struct sof_panic_msg panic_msg[] = {
146         {SOF_IPC_PANIC_MEM, "out of memory"},
147         {SOF_IPC_PANIC_WORK, "work subsystem init failed"},
148         {SOF_IPC_PANIC_IPC, "IPC subsystem init failed"},
149         {SOF_IPC_PANIC_ARCH, "arch init failed"},
150         {SOF_IPC_PANIC_PLATFORM, "platform init failed"},
151         {SOF_IPC_PANIC_TASK, "scheduler init failed"},
152         {SOF_IPC_PANIC_EXCEPTION, "runtime exception"},
153         {SOF_IPC_PANIC_DEADLOCK, "deadlock"},
154         {SOF_IPC_PANIC_STACK, "stack overflow"},
155         {SOF_IPC_PANIC_IDLE, "can't enter idle"},
156         {SOF_IPC_PANIC_WFI, "invalid wait state"},
157         {SOF_IPC_PANIC_ASSERT, "assertion failed"},
158 };
159
160 /*
161  * helper to be called from .dbg_dump callbacks. No error code is
162  * provided, it's left as an exercise for the caller of .dbg_dump
163  * (typically IPC or loader)
164  */
165 void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
166                         u32 tracep_code, void *oops,
167                         struct sof_ipc_panic_info *panic_info,
168                         void *stack, size_t stack_words)
169 {
170         u32 code;
171         int i;
172
173         /* is firmware dead ? */
174         if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) != SOF_IPC_PANIC_MAGIC) {
175                 dev_err(sdev->dev, "error: unexpected fault 0x%8.8x trace 0x%8.8x\n",
176                         panic_code, tracep_code);
177                 return; /* no fault ? */
178         }
179
180         code = panic_code & (SOF_IPC_PANIC_MAGIC_MASK | SOF_IPC_PANIC_CODE_MASK);
181
182         for (i = 0; i < ARRAY_SIZE(panic_msg); i++) {
183                 if (panic_msg[i].id == code) {
184                         dev_err(sdev->dev, "error: %s\n", panic_msg[i].msg);
185                         dev_err(sdev->dev, "error: trace point %8.8x\n",
186                                 tracep_code);
187                         goto out;
188                 }
189         }
190
191         /* unknown error */
192         dev_err(sdev->dev, "error: unknown reason %8.8x\n", panic_code);
193         dev_err(sdev->dev, "error: trace point %8.8x\n", tracep_code);
194
195 out:
196         dev_err(sdev->dev, "error: panic at %s:%d\n",
197                 panic_info->filename, panic_info->linenum);
198         sof_oops(sdev, oops);
199         sof_stack(sdev, oops, stack, stack_words);
200 }
201 EXPORT_SYMBOL(snd_sof_get_status);
202
203 /*
204  * Generic buffer page table creation.
205  * Take the each physical page address and drop the least significant unused
206  * bits from each (based on PAGE_SIZE). Then pack valid page address bits
207  * into compressed page table.
208  */
209
210 int snd_sof_create_page_table(struct snd_sof_dev *sdev,
211                               struct snd_dma_buffer *dmab,
212                               unsigned char *page_table, size_t size)
213 {
214         int i, pages;
215
216         pages = snd_sgbuf_aligned_pages(size);
217
218         dev_dbg(sdev->dev, "generating page table for %p size 0x%zx pages %d\n",
219                 dmab->area, size, pages);
220
221         for (i = 0; i < pages; i++) {
222                 /*
223                  * The number of valid address bits for each page is 20.
224                  * idx determines the byte position within page_table
225                  * where the current page's address is stored
226                  * in the compressed page_table.
227                  * This can be calculated by multiplying the page number by 2.5.
228                  */
229                 u32 idx = (5 * i) >> 1;
230                 u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT;
231                 u8 *pg_table;
232
233                 dev_vdbg(sdev->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn);
234
235                 pg_table = (u8 *)(page_table + idx);
236
237                 /*
238                  * pagetable compression:
239                  * byte 0     byte 1     byte 2     byte 3     byte 4     byte 5
240                  * ___________pfn 0__________ __________pfn 1___________  _pfn 2...
241                  * .... ....  .... ....  .... ....  .... ....  .... ....  ....
242                  * It is created by:
243                  * 1. set current location to 0, PFN index i to 0
244                  * 2. put pfn[i] at current location in Little Endian byte order
245                  * 3. calculate an intermediate value as
246                  *    x = (pfn[i+1] << 4) | (pfn[i] & 0xf)
247                  * 4. put x at offset (current location + 2) in LE byte order
248                  * 5. increment current location by 5 bytes, increment i by 2
249                  * 6. continue to (2)
250                  */
251                 if (i & 1)
252                         put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4,
253                                            pg_table);
254                 else
255                         put_unaligned_le32(pfn, pg_table);
256         }
257
258         return pages;
259 }
260
261 /*
262  * SOF Driver enumeration.
263  */
264 static int sof_machine_check(struct snd_sof_dev *sdev)
265 {
266         struct snd_sof_pdata *plat_data = sdev->pdata;
267 #if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)
268         struct snd_soc_acpi_mach *machine;
269         int ret;
270 #endif
271
272         if (plat_data->machine)
273                 return 0;
274
275 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)
276         dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n");
277         return -ENODEV;
278 #else
279         /* fallback to nocodec mode */
280         dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n");
281         machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL);
282         if (!machine)
283                 return -ENOMEM;
284
285         ret = sof_nocodec_setup(sdev->dev, plat_data, machine,
286                                 plat_data->desc, plat_data->desc->ops);
287         if (ret < 0)
288                 return ret;
289
290         plat_data->machine = machine;
291
292         return 0;
293 #endif
294 }
295
296 static int sof_probe_continue(struct snd_sof_dev *sdev)
297 {
298         struct snd_sof_pdata *plat_data = sdev->pdata;
299         const char *drv_name;
300         const void *mach;
301         int size;
302         int ret;
303
304         /* probe the DSP hardware */
305         ret = snd_sof_probe(sdev);
306         if (ret < 0) {
307                 dev_err(sdev->dev, "error: failed to probe DSP %d\n", ret);
308                 return ret;
309         }
310
311         /* check machine info */
312         ret = sof_machine_check(sdev);
313         if (ret < 0) {
314                 dev_err(sdev->dev, "error: failed to get machine info %d\n",
315                         ret);
316                 goto dbg_err;
317         }
318
319         /* set up platform component driver */
320         snd_sof_new_platform_drv(sdev);
321
322         /* register any debug/trace capabilities */
323         ret = snd_sof_dbg_init(sdev);
324         if (ret < 0) {
325                 /*
326                  * debugfs issues are suppressed in snd_sof_dbg_init() since
327                  * we cannot rely on debugfs
328                  * here we trap errors due to memory allocation only.
329                  */
330                 dev_err(sdev->dev, "error: failed to init DSP trace/debug %d\n",
331                         ret);
332                 goto dbg_err;
333         }
334
335         /* init the IPC */
336         sdev->ipc = snd_sof_ipc_init(sdev);
337         if (!sdev->ipc) {
338                 dev_err(sdev->dev, "error: failed to init DSP IPC %d\n", ret);
339                 goto ipc_err;
340         }
341
342         /* load the firmware */
343         ret = snd_sof_load_firmware(sdev);
344         if (ret < 0) {
345                 dev_err(sdev->dev, "error: failed to load DSP firmware %d\n",
346                         ret);
347                 goto fw_load_err;
348         }
349
350         /* boot the firmware */
351         ret = snd_sof_run_firmware(sdev);
352         if (ret < 0) {
353                 dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n",
354                         ret);
355                 goto fw_run_err;
356         }
357
358         if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE) ||
359             (sof_core_debug & SOF_DBG_ENABLE_TRACE)) {
360                 sdev->dtrace_is_supported = true;
361
362                 /* init DMA trace */
363                 ret = snd_sof_init_trace(sdev);
364                 if (ret < 0) {
365                         /* non fatal */
366                         dev_warn(sdev->dev,
367                                  "warning: failed to initialize trace %d\n",
368                                  ret);
369                 }
370         } else {
371                 dev_dbg(sdev->dev, "SOF firmware trace disabled\n");
372         }
373
374         /* hereafter all FW boot flows are for PM reasons */
375         sdev->first_boot = false;
376
377         /* now register audio DSP platform driver and dai */
378         ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv,
379                                               sof_ops(sdev)->drv,
380                                               sof_ops(sdev)->num_drv);
381         if (ret < 0) {
382                 dev_err(sdev->dev,
383                         "error: failed to register DSP DAI driver %d\n", ret);
384                 goto fw_run_err;
385         }
386
387         drv_name = plat_data->machine->drv_name;
388         mach = (const void *)plat_data->machine;
389         size = sizeof(*plat_data->machine);
390
391         /* register machine driver, pass machine info as pdata */
392         plat_data->pdev_mach =
393                 platform_device_register_data(sdev->dev, drv_name,
394                                               PLATFORM_DEVID_NONE, mach, size);
395
396         if (IS_ERR(plat_data->pdev_mach)) {
397                 ret = PTR_ERR(plat_data->pdev_mach);
398                 goto fw_run_err;
399         }
400
401         dev_dbg(sdev->dev, "created machine %s\n",
402                 dev_name(&plat_data->pdev_mach->dev));
403
404         if (plat_data->sof_probe_complete)
405                 plat_data->sof_probe_complete(sdev->dev);
406
407         return 0;
408
409 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
410 fw_run_err:
411         snd_sof_fw_unload(sdev);
412 fw_load_err:
413         snd_sof_ipc_free(sdev);
414 ipc_err:
415         snd_sof_free_debug(sdev);
416 dbg_err:
417         snd_sof_remove(sdev);
418 #else
419
420         /*
421          * when the probe_continue is handled in a work queue, the
422          * probe does not fail so we don't release resources here.
423          * They will be released with an explicit call to
424          * snd_sof_device_remove() when the PCI/ACPI device is removed
425          */
426
427 fw_run_err:
428 fw_load_err:
429 ipc_err:
430 dbg_err:
431
432 #endif
433
434         return ret;
435 }
436
437 static void sof_probe_work(struct work_struct *work)
438 {
439         struct snd_sof_dev *sdev =
440                 container_of(work, struct snd_sof_dev, probe_work);
441         int ret;
442
443         ret = sof_probe_continue(sdev);
444         if (ret < 0) {
445                 /* errors cannot be propagated, log */
446                 dev_err(sdev->dev, "error: %s failed err: %d\n", __func__, ret);
447         }
448 }
449
450 int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
451 {
452         struct snd_sof_dev *sdev;
453
454         sdev = devm_kzalloc(dev, sizeof(*sdev), GFP_KERNEL);
455         if (!sdev)
456                 return -ENOMEM;
457
458         /* initialize sof device */
459         sdev->dev = dev;
460
461         sdev->pdata = plat_data;
462         sdev->first_boot = true;
463         dev_set_drvdata(dev, sdev);
464
465         /* check all mandatory ops */
466         if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run ||
467             !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write ||
468             !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware ||
469             !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params)
470                 return -EINVAL;
471
472         INIT_LIST_HEAD(&sdev->pcm_list);
473         INIT_LIST_HEAD(&sdev->kcontrol_list);
474         INIT_LIST_HEAD(&sdev->widget_list);
475         INIT_LIST_HEAD(&sdev->dai_list);
476         INIT_LIST_HEAD(&sdev->route_list);
477         spin_lock_init(&sdev->ipc_lock);
478         spin_lock_init(&sdev->hw_lock);
479
480         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
481                 INIT_WORK(&sdev->probe_work, sof_probe_work);
482
483         /* set default timeouts if none provided */
484         if (plat_data->desc->ipc_timeout == 0)
485                 sdev->ipc_timeout = TIMEOUT_DEFAULT_IPC_MS;
486         else
487                 sdev->ipc_timeout = plat_data->desc->ipc_timeout;
488         if (plat_data->desc->boot_timeout == 0)
489                 sdev->boot_timeout = TIMEOUT_DEFAULT_BOOT_MS;
490         else
491                 sdev->boot_timeout = plat_data->desc->boot_timeout;
492
493         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
494                 schedule_work(&sdev->probe_work);
495                 return 0;
496         }
497
498         return sof_probe_continue(sdev);
499 }
500 EXPORT_SYMBOL(snd_sof_device_probe);
501
502 int snd_sof_device_remove(struct device *dev)
503 {
504         struct snd_sof_dev *sdev = dev_get_drvdata(dev);
505         struct snd_sof_pdata *pdata = sdev->pdata;
506
507         if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
508                 cancel_work_sync(&sdev->probe_work);
509
510         snd_sof_fw_unload(sdev);
511         snd_sof_ipc_free(sdev);
512         snd_sof_free_debug(sdev);
513         snd_sof_free_trace(sdev);
514
515         /*
516          * Unregister machine driver. This will unbind the snd_card which
517          * will remove the component driver and unload the topology
518          * before freeing the snd_card.
519          */
520         if (!IS_ERR_OR_NULL(pdata->pdev_mach))
521                 platform_device_unregister(pdata->pdev_mach);
522
523         /*
524          * Unregistering the machine driver results in unloading the topology.
525          * Some widgets, ex: scheduler, attempt to power down the core they are
526          * scheduled on, when they are unloaded. Therefore, the DSP must be
527          * removed only after the topology has been unloaded.
528          */
529         snd_sof_remove(sdev);
530
531         /* release firmware */
532         release_firmware(pdata->fw);
533         pdata->fw = NULL;
534
535         return 0;
536 }
537 EXPORT_SYMBOL(snd_sof_device_remove);
538
539 MODULE_AUTHOR("Liam Girdwood");
540 MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
541 MODULE_LICENSE("Dual BSD/GPL");
542 MODULE_ALIAS("platform:sof-audio");