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 bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev) 136 { 137 struct snd_sof_pcm *spcm; 138 139 list_for_each_entry(spcm, &sdev->pcm_list, list) { 140 if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored || 141 spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored) 142 return true; 143 } 144 145 return false; 146 } 147 148 /* 149 * FW Panic/fault handling. 150 */ 151 152 struct sof_panic_msg { 153 u32 id; 154 const char *msg; 155 }; 156 157 /* standard FW panic types */ 158 static const struct sof_panic_msg panic_msg[] = { 159 {SOF_IPC_PANIC_MEM, "out of memory"}, 160 {SOF_IPC_PANIC_WORK, "work subsystem init failed"}, 161 {SOF_IPC_PANIC_IPC, "IPC subsystem init failed"}, 162 {SOF_IPC_PANIC_ARCH, "arch init failed"}, 163 {SOF_IPC_PANIC_PLATFORM, "platform init failed"}, 164 {SOF_IPC_PANIC_TASK, "scheduler init failed"}, 165 {SOF_IPC_PANIC_EXCEPTION, "runtime exception"}, 166 {SOF_IPC_PANIC_DEADLOCK, "deadlock"}, 167 {SOF_IPC_PANIC_STACK, "stack overflow"}, 168 {SOF_IPC_PANIC_IDLE, "can't enter idle"}, 169 {SOF_IPC_PANIC_WFI, "invalid wait state"}, 170 {SOF_IPC_PANIC_ASSERT, "assertion failed"}, 171 }; 172 173 /* 174 * helper to be called from .dbg_dump callbacks. No error code is 175 * provided, it's left as an exercise for the caller of .dbg_dump 176 * (typically IPC or loader) 177 */ 178 void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code, 179 u32 tracep_code, void *oops, 180 struct sof_ipc_panic_info *panic_info, 181 void *stack, size_t stack_words) 182 { 183 u32 code; 184 int i; 185 186 /* is firmware dead ? */ 187 if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) != SOF_IPC_PANIC_MAGIC) { 188 dev_err(sdev->dev, "error: unexpected fault 0x%8.8x trace 0x%8.8x\n", 189 panic_code, tracep_code); 190 return; /* no fault ? */ 191 } 192 193 code = panic_code & (SOF_IPC_PANIC_MAGIC_MASK | SOF_IPC_PANIC_CODE_MASK); 194 195 for (i = 0; i < ARRAY_SIZE(panic_msg); i++) { 196 if (panic_msg[i].id == code) { 197 dev_err(sdev->dev, "error: %s\n", panic_msg[i].msg); 198 dev_err(sdev->dev, "error: trace point %8.8x\n", 199 tracep_code); 200 goto out; 201 } 202 } 203 204 /* unknown error */ 205 dev_err(sdev->dev, "error: unknown reason %8.8x\n", panic_code); 206 dev_err(sdev->dev, "error: trace point %8.8x\n", tracep_code); 207 208 out: 209 dev_err(sdev->dev, "error: panic at %s:%d\n", 210 panic_info->filename, panic_info->linenum); 211 sof_oops(sdev, oops); 212 sof_stack(sdev, oops, stack, stack_words); 213 } 214 EXPORT_SYMBOL(snd_sof_get_status); 215 216 /* 217 * Generic buffer page table creation. 218 * Take the each physical page address and drop the least significant unused 219 * bits from each (based on PAGE_SIZE). Then pack valid page address bits 220 * into compressed page table. 221 */ 222 223 int snd_sof_create_page_table(struct snd_sof_dev *sdev, 224 struct snd_dma_buffer *dmab, 225 unsigned char *page_table, size_t size) 226 { 227 int i, pages; 228 229 pages = snd_sgbuf_aligned_pages(size); 230 231 dev_dbg(sdev->dev, "generating page table for %p size 0x%zx pages %d\n", 232 dmab->area, size, pages); 233 234 for (i = 0; i < pages; i++) { 235 /* 236 * The number of valid address bits for each page is 20. 237 * idx determines the byte position within page_table 238 * where the current page's address is stored 239 * in the compressed page_table. 240 * This can be calculated by multiplying the page number by 2.5. 241 */ 242 u32 idx = (5 * i) >> 1; 243 u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT; 244 u8 *pg_table; 245 246 dev_vdbg(sdev->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); 247 248 pg_table = (u8 *)(page_table + idx); 249 250 /* 251 * pagetable compression: 252 * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 253 * ___________pfn 0__________ __________pfn 1___________ _pfn 2... 254 * .... .... .... .... .... .... .... .... .... .... .... 255 * It is created by: 256 * 1. set current location to 0, PFN index i to 0 257 * 2. put pfn[i] at current location in Little Endian byte order 258 * 3. calculate an intermediate value as 259 * x = (pfn[i+1] << 4) | (pfn[i] & 0xf) 260 * 4. put x at offset (current location + 2) in LE byte order 261 * 5. increment current location by 5 bytes, increment i by 2 262 * 6. continue to (2) 263 */ 264 if (i & 1) 265 put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4, 266 pg_table); 267 else 268 put_unaligned_le32(pfn, pg_table); 269 } 270 271 return pages; 272 } 273 274 /* 275 * SOF Driver enumeration. 276 */ 277 static int sof_machine_check(struct snd_sof_dev *sdev) 278 { 279 struct snd_sof_pdata *plat_data = sdev->pdata; 280 #if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) 281 struct snd_soc_acpi_mach *machine; 282 int ret; 283 #endif 284 285 if (plat_data->machine) 286 return 0; 287 288 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) 289 dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); 290 return -ENODEV; 291 #else 292 /* fallback to nocodec mode */ 293 dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n"); 294 machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL); 295 if (!machine) 296 return -ENOMEM; 297 298 ret = sof_nocodec_setup(sdev->dev, plat_data, machine, 299 plat_data->desc, plat_data->desc->ops); 300 if (ret < 0) 301 return ret; 302 303 plat_data->machine = machine; 304 305 return 0; 306 #endif 307 } 308 309 static int sof_probe_continue(struct snd_sof_dev *sdev) 310 { 311 struct snd_sof_pdata *plat_data = sdev->pdata; 312 const char *drv_name; 313 const void *mach; 314 int size; 315 int ret; 316 317 /* probe the DSP hardware */ 318 ret = snd_sof_probe(sdev); 319 if (ret < 0) { 320 dev_err(sdev->dev, "error: failed to probe DSP %d\n", ret); 321 return ret; 322 } 323 324 /* check machine info */ 325 ret = sof_machine_check(sdev); 326 if (ret < 0) { 327 dev_err(sdev->dev, "error: failed to get machine info %d\n", 328 ret); 329 goto dbg_err; 330 } 331 332 /* set up platform component driver */ 333 snd_sof_new_platform_drv(sdev); 334 335 /* register any debug/trace capabilities */ 336 ret = snd_sof_dbg_init(sdev); 337 if (ret < 0) { 338 /* 339 * debugfs issues are suppressed in snd_sof_dbg_init() since 340 * we cannot rely on debugfs 341 * here we trap errors due to memory allocation only. 342 */ 343 dev_err(sdev->dev, "error: failed to init DSP trace/debug %d\n", 344 ret); 345 goto dbg_err; 346 } 347 348 /* init the IPC */ 349 sdev->ipc = snd_sof_ipc_init(sdev); 350 if (!sdev->ipc) { 351 dev_err(sdev->dev, "error: failed to init DSP IPC %d\n", ret); 352 goto ipc_err; 353 } 354 355 /* load the firmware */ 356 ret = snd_sof_load_firmware(sdev); 357 if (ret < 0) { 358 dev_err(sdev->dev, "error: failed to load DSP firmware %d\n", 359 ret); 360 goto fw_load_err; 361 } 362 363 /* boot the firmware */ 364 ret = snd_sof_run_firmware(sdev); 365 if (ret < 0) { 366 dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n", 367 ret); 368 goto fw_run_err; 369 } 370 371 if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE) || 372 (sof_core_debug & SOF_DBG_ENABLE_TRACE)) { 373 sdev->dtrace_is_supported = true; 374 375 /* init DMA trace */ 376 ret = snd_sof_init_trace(sdev); 377 if (ret < 0) { 378 /* non fatal */ 379 dev_warn(sdev->dev, 380 "warning: failed to initialize trace %d\n", 381 ret); 382 } 383 } else { 384 dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); 385 } 386 387 /* hereafter all FW boot flows are for PM reasons */ 388 sdev->first_boot = false; 389 390 /* now register audio DSP platform driver and dai */ 391 ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv, 392 sof_ops(sdev)->drv, 393 sof_ops(sdev)->num_drv); 394 if (ret < 0) { 395 dev_err(sdev->dev, 396 "error: failed to register DSP DAI driver %d\n", ret); 397 goto fw_run_err; 398 } 399 400 drv_name = plat_data->machine->drv_name; 401 mach = (const void *)plat_data->machine; 402 size = sizeof(*plat_data->machine); 403 404 /* register machine driver, pass machine info as pdata */ 405 plat_data->pdev_mach = 406 platform_device_register_data(sdev->dev, drv_name, 407 PLATFORM_DEVID_NONE, mach, size); 408 409 if (IS_ERR(plat_data->pdev_mach)) { 410 ret = PTR_ERR(plat_data->pdev_mach); 411 goto fw_run_err; 412 } 413 414 dev_dbg(sdev->dev, "created machine %s\n", 415 dev_name(&plat_data->pdev_mach->dev)); 416 417 if (plat_data->sof_probe_complete) 418 plat_data->sof_probe_complete(sdev->dev); 419 420 return 0; 421 422 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 423 fw_run_err: 424 snd_sof_fw_unload(sdev); 425 fw_load_err: 426 snd_sof_ipc_free(sdev); 427 ipc_err: 428 snd_sof_free_debug(sdev); 429 dbg_err: 430 snd_sof_remove(sdev); 431 #else 432 433 /* 434 * when the probe_continue is handled in a work queue, the 435 * probe does not fail so we don't release resources here. 436 * They will be released with an explicit call to 437 * snd_sof_device_remove() when the PCI/ACPI device is removed 438 */ 439 440 fw_run_err: 441 fw_load_err: 442 ipc_err: 443 dbg_err: 444 445 #endif 446 447 return ret; 448 } 449 450 static void sof_probe_work(struct work_struct *work) 451 { 452 struct snd_sof_dev *sdev = 453 container_of(work, struct snd_sof_dev, probe_work); 454 int ret; 455 456 ret = sof_probe_continue(sdev); 457 if (ret < 0) { 458 /* errors cannot be propagated, log */ 459 dev_err(sdev->dev, "error: %s failed err: %d\n", __func__, ret); 460 } 461 } 462 463 int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) 464 { 465 struct snd_sof_dev *sdev; 466 467 sdev = devm_kzalloc(dev, sizeof(*sdev), GFP_KERNEL); 468 if (!sdev) 469 return -ENOMEM; 470 471 /* initialize sof device */ 472 sdev->dev = dev; 473 474 /* initialize default D0 sub-state */ 475 sdev->d0_substate = SOF_DSP_D0I0; 476 477 sdev->pdata = plat_data; 478 sdev->first_boot = true; 479 dev_set_drvdata(dev, sdev); 480 481 /* check all mandatory ops */ 482 if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run || 483 !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write || 484 !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware || 485 !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params || 486 !sof_ops(sdev)->fw_ready) 487 return -EINVAL; 488 489 INIT_LIST_HEAD(&sdev->pcm_list); 490 INIT_LIST_HEAD(&sdev->kcontrol_list); 491 INIT_LIST_HEAD(&sdev->widget_list); 492 INIT_LIST_HEAD(&sdev->dai_list); 493 INIT_LIST_HEAD(&sdev->route_list); 494 spin_lock_init(&sdev->ipc_lock); 495 spin_lock_init(&sdev->hw_lock); 496 497 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) 498 INIT_WORK(&sdev->probe_work, sof_probe_work); 499 500 /* set default timeouts if none provided */ 501 if (plat_data->desc->ipc_timeout == 0) 502 sdev->ipc_timeout = TIMEOUT_DEFAULT_IPC_MS; 503 else 504 sdev->ipc_timeout = plat_data->desc->ipc_timeout; 505 if (plat_data->desc->boot_timeout == 0) 506 sdev->boot_timeout = TIMEOUT_DEFAULT_BOOT_MS; 507 else 508 sdev->boot_timeout = plat_data->desc->boot_timeout; 509 510 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) { 511 schedule_work(&sdev->probe_work); 512 return 0; 513 } 514 515 return sof_probe_continue(sdev); 516 } 517 EXPORT_SYMBOL(snd_sof_device_probe); 518 519 int snd_sof_device_remove(struct device *dev) 520 { 521 struct snd_sof_dev *sdev = dev_get_drvdata(dev); 522 struct snd_sof_pdata *pdata = sdev->pdata; 523 524 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) 525 cancel_work_sync(&sdev->probe_work); 526 527 snd_sof_fw_unload(sdev); 528 snd_sof_ipc_free(sdev); 529 snd_sof_free_debug(sdev); 530 snd_sof_free_trace(sdev); 531 532 /* 533 * Unregister machine driver. This will unbind the snd_card which 534 * will remove the component driver and unload the topology 535 * before freeing the snd_card. 536 */ 537 if (!IS_ERR_OR_NULL(pdata->pdev_mach)) 538 platform_device_unregister(pdata->pdev_mach); 539 540 /* 541 * Unregistering the machine driver results in unloading the topology. 542 * Some widgets, ex: scheduler, attempt to power down the core they are 543 * scheduled on, when they are unloaded. Therefore, the DSP must be 544 * removed only after the topology has been unloaded. 545 */ 546 snd_sof_remove(sdev); 547 548 /* release firmware */ 549 release_firmware(pdata->fw); 550 pdata->fw = NULL; 551 552 return 0; 553 } 554 EXPORT_SYMBOL(snd_sof_device_remove); 555 556 MODULE_AUTHOR("Liam Girdwood"); 557 MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core"); 558 MODULE_LICENSE("Dual BSD/GPL"); 559 MODULE_ALIAS("platform:sof-audio"); 560