0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/firmware.h>
0012 #include <linux/module.h>
0013 #include <sound/soc.h>
0014 #include <sound/sof.h>
0015 #include "sof-priv.h"
0016 #include "ops.h"
0017
0018
0019 static int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE);
0020 module_param_named(sof_debug, sof_core_debug, int, 0444);
0021 MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)");
0022
0023
0024 #define TIMEOUT_DEFAULT_IPC_MS 500
0025 #define TIMEOUT_DEFAULT_BOOT_MS 2000
0026
0027
0028
0029
0030
0031
0032
0033
0034 bool sof_debug_check_flag(int mask)
0035 {
0036 if ((sof_core_debug & mask) == mask)
0037 return true;
0038
0039 return false;
0040 }
0041 EXPORT_SYMBOL(sof_debug_check_flag);
0042
0043
0044
0045
0046
0047 struct sof_panic_msg {
0048 u32 id;
0049 const char *msg;
0050 };
0051
0052
0053 static const struct sof_panic_msg panic_msg[] = {
0054 {SOF_IPC_PANIC_MEM, "out of memory"},
0055 {SOF_IPC_PANIC_WORK, "work subsystem init failed"},
0056 {SOF_IPC_PANIC_IPC, "IPC subsystem init failed"},
0057 {SOF_IPC_PANIC_ARCH, "arch init failed"},
0058 {SOF_IPC_PANIC_PLATFORM, "platform init failed"},
0059 {SOF_IPC_PANIC_TASK, "scheduler init failed"},
0060 {SOF_IPC_PANIC_EXCEPTION, "runtime exception"},
0061 {SOF_IPC_PANIC_DEADLOCK, "deadlock"},
0062 {SOF_IPC_PANIC_STACK, "stack overflow"},
0063 {SOF_IPC_PANIC_IDLE, "can't enter idle"},
0064 {SOF_IPC_PANIC_WFI, "invalid wait state"},
0065 {SOF_IPC_PANIC_ASSERT, "assertion failed"},
0066 };
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 void sof_print_oops_and_stack(struct snd_sof_dev *sdev, const char *level,
0084 u32 panic_code, u32 tracep_code, void *oops,
0085 struct sof_ipc_panic_info *panic_info,
0086 void *stack, size_t stack_words)
0087 {
0088 u32 code;
0089 int i;
0090
0091
0092 if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) != SOF_IPC_PANIC_MAGIC) {
0093 dev_printk(level, sdev->dev, "unexpected fault %#010x trace %#010x\n",
0094 panic_code, tracep_code);
0095 return;
0096 }
0097
0098 code = panic_code & (SOF_IPC_PANIC_MAGIC_MASK | SOF_IPC_PANIC_CODE_MASK);
0099
0100 for (i = 0; i < ARRAY_SIZE(panic_msg); i++) {
0101 if (panic_msg[i].id == code) {
0102 dev_printk(level, sdev->dev, "reason: %s (%#x)\n",
0103 panic_msg[i].msg, code & SOF_IPC_PANIC_CODE_MASK);
0104 dev_printk(level, sdev->dev, "trace point: %#010x\n", tracep_code);
0105 goto out;
0106 }
0107 }
0108
0109
0110 dev_printk(level, sdev->dev, "unknown panic code: %#x\n",
0111 code & SOF_IPC_PANIC_CODE_MASK);
0112 dev_printk(level, sdev->dev, "trace point: %#010x\n", tracep_code);
0113
0114 out:
0115 dev_printk(level, sdev->dev, "panic at %s:%d\n", panic_info->filename,
0116 panic_info->linenum);
0117 sof_oops(sdev, level, oops);
0118 sof_stack(sdev, level, oops, stack, stack_words);
0119 }
0120 EXPORT_SYMBOL(sof_print_oops_and_stack);
0121
0122
0123 void sof_set_fw_state(struct snd_sof_dev *sdev, enum sof_fw_state new_state)
0124 {
0125 if (sdev->fw_state == new_state)
0126 return;
0127
0128 dev_dbg(sdev->dev, "fw_state change: %d -> %d\n", sdev->fw_state, new_state);
0129 sdev->fw_state = new_state;
0130
0131 switch (new_state) {
0132 case SOF_FW_BOOT_NOT_STARTED:
0133 case SOF_FW_BOOT_COMPLETE:
0134 case SOF_FW_CRASHED:
0135 sof_client_fw_state_dispatcher(sdev);
0136 fallthrough;
0137 default:
0138 break;
0139 }
0140 }
0141 EXPORT_SYMBOL(sof_set_fw_state);
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 static int sof_probe_continue(struct snd_sof_dev *sdev)
0184 {
0185 struct snd_sof_pdata *plat_data = sdev->pdata;
0186 int ret;
0187
0188
0189 ret = snd_sof_probe(sdev);
0190 if (ret < 0) {
0191 dev_err(sdev->dev, "error: failed to probe DSP %d\n", ret);
0192 goto probe_err;
0193 }
0194
0195 sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);
0196
0197
0198 ret = sof_machine_check(sdev);
0199 if (ret < 0) {
0200 dev_err(sdev->dev, "error: failed to get machine info %d\n",
0201 ret);
0202 goto dsp_err;
0203 }
0204
0205
0206 snd_sof_new_platform_drv(sdev);
0207
0208
0209 ret = snd_sof_dbg_init(sdev);
0210 if (ret < 0) {
0211
0212
0213
0214
0215
0216 dev_err(sdev->dev, "error: failed to init DSP trace/debug %d\n",
0217 ret);
0218 goto dbg_err;
0219 }
0220
0221
0222 sdev->ipc = snd_sof_ipc_init(sdev);
0223 if (!sdev->ipc) {
0224 ret = -ENOMEM;
0225 dev_err(sdev->dev, "error: failed to init DSP IPC %d\n", ret);
0226 goto ipc_err;
0227 }
0228
0229
0230 ret = snd_sof_load_firmware(sdev);
0231 if (ret < 0) {
0232 dev_err(sdev->dev, "error: failed to load DSP firmware %d\n",
0233 ret);
0234 sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED);
0235 goto fw_load_err;
0236 }
0237
0238 sof_set_fw_state(sdev, SOF_FW_BOOT_IN_PROGRESS);
0239
0240
0241
0242
0243
0244 ret = snd_sof_run_firmware(sdev);
0245 if (ret < 0) {
0246 dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n",
0247 ret);
0248 sof_set_fw_state(sdev, SOF_FW_BOOT_FAILED);
0249 goto fw_run_err;
0250 }
0251
0252 if (sof_debug_check_flag(SOF_DBG_ENABLE_TRACE)) {
0253 sdev->fw_trace_is_supported = true;
0254
0255
0256 ret = sof_fw_trace_init(sdev);
0257 if (ret < 0) {
0258
0259 dev_warn(sdev->dev, "failed to initialize firmware tracing %d\n",
0260 ret);
0261 }
0262 } else {
0263 dev_dbg(sdev->dev, "SOF firmware trace disabled\n");
0264 }
0265
0266
0267 sdev->first_boot = false;
0268
0269
0270 ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv,
0271 sof_ops(sdev)->drv,
0272 sof_ops(sdev)->num_drv);
0273 if (ret < 0) {
0274 dev_err(sdev->dev,
0275 "error: failed to register DSP DAI driver %d\n", ret);
0276 goto fw_trace_err;
0277 }
0278
0279 ret = snd_sof_machine_register(sdev, plat_data);
0280 if (ret < 0) {
0281 dev_err(sdev->dev,
0282 "error: failed to register machine driver %d\n", ret);
0283 goto fw_trace_err;
0284 }
0285
0286 ret = sof_register_clients(sdev);
0287 if (ret < 0) {
0288 dev_err(sdev->dev, "failed to register clients %d\n", ret);
0289 goto sof_machine_err;
0290 }
0291
0292
0293
0294
0295
0296
0297 if (!sof_ops(sdev)->runtime_suspend || !sof_ops(sdev)->runtime_resume)
0298 pm_runtime_get_noresume(sdev->dev);
0299
0300 if (plat_data->sof_probe_complete)
0301 plat_data->sof_probe_complete(sdev->dev);
0302
0303 sdev->probe_completed = true;
0304
0305 return 0;
0306
0307 sof_machine_err:
0308 snd_sof_machine_unregister(sdev, plat_data);
0309 fw_trace_err:
0310 sof_fw_trace_free(sdev);
0311 fw_run_err:
0312 snd_sof_fw_unload(sdev);
0313 fw_load_err:
0314 snd_sof_ipc_free(sdev);
0315 ipc_err:
0316 dbg_err:
0317 snd_sof_free_debug(sdev);
0318 dsp_err:
0319 snd_sof_remove(sdev);
0320 probe_err:
0321 sof_ops_free(sdev);
0322
0323
0324 sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
0325 sdev->first_boot = true;
0326
0327 return ret;
0328 }
0329
0330 static void sof_probe_work(struct work_struct *work)
0331 {
0332 struct snd_sof_dev *sdev =
0333 container_of(work, struct snd_sof_dev, probe_work);
0334 int ret;
0335
0336 ret = sof_probe_continue(sdev);
0337 if (ret < 0) {
0338
0339 dev_err(sdev->dev, "error: %s failed err: %d\n", __func__, ret);
0340 }
0341 }
0342
0343 int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
0344 {
0345 struct snd_sof_dev *sdev;
0346 int ret;
0347
0348 sdev = devm_kzalloc(dev, sizeof(*sdev), GFP_KERNEL);
0349 if (!sdev)
0350 return -ENOMEM;
0351
0352
0353 sdev->dev = dev;
0354
0355
0356 sdev->dsp_power_state.state = SOF_DSP_PM_D0;
0357
0358 sdev->pdata = plat_data;
0359 sdev->first_boot = true;
0360 dev_set_drvdata(dev, sdev);
0361
0362
0363 if (!(BIT(plat_data->ipc_type) & plat_data->desc->ipc_supported_mask)) {
0364 dev_err(dev, "ipc_type %d is not supported on this platform, mask is %#x\n",
0365 plat_data->ipc_type, plat_data->desc->ipc_supported_mask);
0366 return -EINVAL;
0367 }
0368
0369
0370 ret = sof_ops_init(sdev);
0371 if (ret < 0)
0372 return ret;
0373
0374
0375 if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run ||
0376 !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write ||
0377 !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware ||
0378 !sof_ops(sdev)->ipc_msg_data) {
0379 sof_ops_free(sdev);
0380 dev_err(dev, "error: missing mandatory ops\n");
0381 return -EINVAL;
0382 }
0383
0384 INIT_LIST_HEAD(&sdev->pcm_list);
0385 INIT_LIST_HEAD(&sdev->kcontrol_list);
0386 INIT_LIST_HEAD(&sdev->widget_list);
0387 INIT_LIST_HEAD(&sdev->dai_list);
0388 INIT_LIST_HEAD(&sdev->dai_link_list);
0389 INIT_LIST_HEAD(&sdev->route_list);
0390 INIT_LIST_HEAD(&sdev->ipc_client_list);
0391 INIT_LIST_HEAD(&sdev->ipc_rx_handler_list);
0392 INIT_LIST_HEAD(&sdev->fw_state_handler_list);
0393 spin_lock_init(&sdev->ipc_lock);
0394 spin_lock_init(&sdev->hw_lock);
0395 mutex_init(&sdev->power_state_access);
0396 mutex_init(&sdev->ipc_client_mutex);
0397 mutex_init(&sdev->client_event_handler_mutex);
0398
0399
0400 if (plat_data->desc->ipc_timeout == 0)
0401 sdev->ipc_timeout = TIMEOUT_DEFAULT_IPC_MS;
0402 else
0403 sdev->ipc_timeout = plat_data->desc->ipc_timeout;
0404 if (plat_data->desc->boot_timeout == 0)
0405 sdev->boot_timeout = TIMEOUT_DEFAULT_BOOT_MS;
0406 else
0407 sdev->boot_timeout = plat_data->desc->boot_timeout;
0408
0409 sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
0410
0411 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
0412 INIT_WORK(&sdev->probe_work, sof_probe_work);
0413 schedule_work(&sdev->probe_work);
0414 return 0;
0415 }
0416
0417 return sof_probe_continue(sdev);
0418 }
0419 EXPORT_SYMBOL(snd_sof_device_probe);
0420
0421 bool snd_sof_device_probe_completed(struct device *dev)
0422 {
0423 struct snd_sof_dev *sdev = dev_get_drvdata(dev);
0424
0425 return sdev->probe_completed;
0426 }
0427 EXPORT_SYMBOL(snd_sof_device_probe_completed);
0428
0429 int snd_sof_device_remove(struct device *dev)
0430 {
0431 struct snd_sof_dev *sdev = dev_get_drvdata(dev);
0432 struct snd_sof_pdata *pdata = sdev->pdata;
0433 int ret;
0434
0435 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
0436 cancel_work_sync(&sdev->probe_work);
0437
0438
0439
0440
0441
0442 sof_unregister_clients(sdev);
0443
0444
0445
0446
0447
0448
0449 snd_sof_machine_unregister(sdev, pdata);
0450
0451 if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) {
0452 sof_fw_trace_free(sdev);
0453 ret = snd_sof_dsp_power_down_notify(sdev);
0454 if (ret < 0)
0455 dev_warn(dev, "error: %d failed to prepare DSP for device removal",
0456 ret);
0457
0458 snd_sof_ipc_free(sdev);
0459 snd_sof_free_debug(sdev);
0460 snd_sof_remove(sdev);
0461 }
0462
0463 sof_ops_free(sdev);
0464
0465
0466 snd_sof_fw_unload(sdev);
0467
0468 return 0;
0469 }
0470 EXPORT_SYMBOL(snd_sof_device_remove);
0471
0472 int snd_sof_device_shutdown(struct device *dev)
0473 {
0474 struct snd_sof_dev *sdev = dev_get_drvdata(dev);
0475 struct snd_sof_pdata *pdata = sdev->pdata;
0476
0477 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
0478 cancel_work_sync(&sdev->probe_work);
0479
0480
0481
0482
0483
0484 sof_unregister_clients(sdev);
0485
0486 snd_sof_machine_unregister(sdev, pdata);
0487
0488 if (sdev->fw_state == SOF_FW_BOOT_COMPLETE)
0489 return snd_sof_shutdown(sdev);
0490
0491 return 0;
0492 }
0493 EXPORT_SYMBOL(snd_sof_device_shutdown);
0494
0495 MODULE_AUTHOR("Liam Girdwood");
0496 MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
0497 MODULE_LICENSE("Dual BSD/GPL");
0498 MODULE_ALIAS("platform:sof-audio");
0499 MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);