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