1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // Copyright(c) 2022 Mediatek Inc. All rights reserved. 4 // 5 // Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> 6 // Tinghan Shen <tinghan.shen@mediatek.com> 7 8 /* 9 * Hardware interface for audio DSP on mt8186 10 */ 11 12 #include <linux/delay.h> 13 #include <linux/firmware.h> 14 #include <linux/io.h> 15 #include <linux/of_address.h> 16 #include <linux/of_irq.h> 17 #include <linux/of_platform.h> 18 #include <linux/of_reserved_mem.h> 19 #include <linux/module.h> 20 21 #include <sound/sof.h> 22 #include <sound/sof/xtensa.h> 23 #include "../../ops.h" 24 #include "../../sof-of-dev.h" 25 #include "../adsp_helper.h" 26 #include "../mtk-adsp-common.h" 27 #include "mt8186.h" 28 #include "mt8186-clk.h" 29 30 static int mt8186_get_mailbox_offset(struct snd_sof_dev *sdev) 31 { 32 return MBOX_OFFSET; 33 } 34 35 static int mt8186_get_window_offset(struct snd_sof_dev *sdev, u32 id) 36 { 37 return MBOX_OFFSET; 38 } 39 40 static const struct mtk_adsp_ipc_ops dsp_ops = { 41 .handle_reply = mtk_adsp_handle_reply, 42 .handle_request = mtk_adsp_handle_request, 43 }; 44 45 static int platform_parse_resource(struct platform_device *pdev, void *data) 46 { 47 struct resource *mmio; 48 struct resource res; 49 struct device_node *mem_region; 50 struct device *dev = &pdev->dev; 51 struct mtk_adsp_chip_info *adsp = data; 52 int ret; 53 54 ret = of_reserved_mem_device_init(dev); 55 if (ret) { 56 dev_err(dev, "of_reserved_mem_device_init failed\n"); 57 return ret; 58 } 59 60 mem_region = of_parse_phandle(dev->of_node, "memory-region", 1); 61 if (!mem_region) { 62 dev_err(dev, "no memory-region sysmem phandle\n"); 63 return -ENODEV; 64 } 65 66 ret = of_address_to_resource(mem_region, 0, &res); 67 of_node_put(mem_region); 68 if (ret) { 69 dev_err(dev, "of_address_to_resource sysmem failed\n"); 70 return ret; 71 } 72 73 adsp->pa_dram = (phys_addr_t)res.start; 74 if (adsp->pa_dram & DRAM_REMAP_MASK) { 75 dev_err(dev, "adsp memory(%#x) is not 4K-aligned\n", 76 (u32)adsp->pa_dram); 77 return -EINVAL; 78 } 79 80 adsp->dramsize = resource_size(&res); 81 if (adsp->dramsize < TOTAL_SIZE_SHARED_DRAM_FROM_TAIL) { 82 dev_err(dev, "adsp memory(%#x) is not enough for share\n", 83 adsp->dramsize); 84 return -EINVAL; 85 } 86 87 dev_dbg(dev, "dram pbase=%pa size=%#x\n", &adsp->pa_dram, adsp->dramsize); 88 89 mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg"); 90 if (!mmio) { 91 dev_err(dev, "no ADSP-CFG register resource\n"); 92 return -ENXIO; 93 } 94 95 adsp->va_cfgreg = devm_ioremap_resource(dev, mmio); 96 if (IS_ERR(adsp->va_cfgreg)) 97 return PTR_ERR(adsp->va_cfgreg); 98 99 adsp->pa_cfgreg = (phys_addr_t)mmio->start; 100 adsp->cfgregsize = resource_size(mmio); 101 102 dev_dbg(dev, "cfgreg pbase=%pa size=%#x\n", &adsp->pa_cfgreg, adsp->cfgregsize); 103 104 mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram"); 105 if (!mmio) { 106 dev_err(dev, "no SRAM resource\n"); 107 return -ENXIO; 108 } 109 110 adsp->pa_sram = (phys_addr_t)mmio->start; 111 adsp->sramsize = resource_size(mmio); 112 113 dev_dbg(dev, "sram pbase=%pa size=%#x\n", &adsp->pa_sram, adsp->sramsize); 114 115 mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sec"); 116 if (!mmio) { 117 dev_err(dev, "no SEC register resource\n"); 118 return -ENXIO; 119 } 120 121 adsp->va_secreg = devm_ioremap_resource(dev, mmio); 122 if (IS_ERR(adsp->va_secreg)) 123 return PTR_ERR(adsp->va_secreg); 124 125 adsp->pa_secreg = (phys_addr_t)mmio->start; 126 adsp->secregsize = resource_size(mmio); 127 128 dev_dbg(dev, "secreg pbase=%pa size=%#x\n", &adsp->pa_secreg, adsp->secregsize); 129 130 mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bus"); 131 if (!mmio) { 132 dev_err(dev, "no BUS register resource\n"); 133 return -ENXIO; 134 } 135 136 adsp->va_busreg = devm_ioremap_resource(dev, mmio); 137 if (IS_ERR(adsp->va_busreg)) 138 return PTR_ERR(adsp->va_busreg); 139 140 adsp->pa_busreg = (phys_addr_t)mmio->start; 141 adsp->busregsize = resource_size(mmio); 142 143 dev_dbg(dev, "busreg pbase=%pa size=%#x\n", &adsp->pa_busreg, adsp->busregsize); 144 145 return 0; 146 } 147 148 static void adsp_sram_power_on(struct snd_sof_dev *sdev) 149 { 150 snd_sof_dsp_update_bits(sdev, DSP_BUSREG_BAR, ADSP_SRAM_POOL_CON, 151 DSP_SRAM_POOL_PD_MASK, 0); 152 } 153 154 static void adsp_sram_power_off(struct snd_sof_dev *sdev) 155 { 156 snd_sof_dsp_update_bits(sdev, DSP_BUSREG_BAR, ADSP_SRAM_POOL_CON, 157 DSP_SRAM_POOL_PD_MASK, DSP_SRAM_POOL_PD_MASK); 158 } 159 160 /* Init the basic DSP DRAM address */ 161 static int adsp_memory_remap_init(struct snd_sof_dev *sdev, struct mtk_adsp_chip_info *adsp) 162 { 163 u32 offset; 164 165 offset = adsp->pa_dram - DRAM_PHYS_BASE_FROM_DSP_VIEW; 166 adsp->dram_offset = offset; 167 offset >>= DRAM_REMAP_SHIFT; 168 169 dev_dbg(sdev->dev, "adsp->pa_dram %pa, offset %#x\n", &adsp->pa_dram, offset); 170 171 snd_sof_dsp_write(sdev, DSP_BUSREG_BAR, DSP_C0_EMI_MAP_ADDR, offset); 172 snd_sof_dsp_write(sdev, DSP_BUSREG_BAR, DSP_C0_DMAEMI_MAP_ADDR, offset); 173 174 if (offset != snd_sof_dsp_read(sdev, DSP_BUSREG_BAR, DSP_C0_EMI_MAP_ADDR) || 175 offset != snd_sof_dsp_read(sdev, DSP_BUSREG_BAR, DSP_C0_DMAEMI_MAP_ADDR)) { 176 dev_err(sdev->dev, "emi remap fail\n"); 177 return -EIO; 178 } 179 180 return 0; 181 } 182 183 static int mt8186_run(struct snd_sof_dev *sdev) 184 { 185 u32 adsp_bootup_addr; 186 187 adsp_bootup_addr = SRAM_PHYS_BASE_FROM_DSP_VIEW; 188 dev_dbg(sdev->dev, "HIFIxDSP boot from base : 0x%08X\n", adsp_bootup_addr); 189 mt8186_sof_hifixdsp_boot_sequence(sdev, adsp_bootup_addr); 190 191 return 0; 192 } 193 194 static int mt8186_dsp_probe(struct snd_sof_dev *sdev) 195 { 196 struct platform_device *pdev = to_platform_device(sdev->dev); 197 struct adsp_priv *priv; 198 int ret; 199 200 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 201 if (!priv) 202 return -ENOMEM; 203 204 sdev->pdata->hw_pdata = priv; 205 priv->dev = sdev->dev; 206 priv->sdev = sdev; 207 208 priv->adsp = devm_kzalloc(&pdev->dev, sizeof(struct mtk_adsp_chip_info), GFP_KERNEL); 209 if (!priv->adsp) 210 return -ENOMEM; 211 212 ret = platform_parse_resource(pdev, priv->adsp); 213 if (ret) 214 return ret; 215 216 sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, 217 priv->adsp->pa_sram, 218 priv->adsp->sramsize); 219 if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { 220 dev_err(sdev->dev, "failed to ioremap base %pa size %#x\n", 221 &priv->adsp->pa_sram, priv->adsp->sramsize); 222 return -ENOMEM; 223 } 224 225 priv->adsp->va_sram = sdev->bar[SOF_FW_BLK_TYPE_IRAM]; 226 227 sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap(sdev->dev, 228 priv->adsp->pa_dram, 229 priv->adsp->dramsize); 230 231 if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { 232 dev_err(sdev->dev, "failed to ioremap base %pa size %#x\n", 233 &priv->adsp->pa_dram, priv->adsp->dramsize); 234 return -ENOMEM; 235 } 236 237 priv->adsp->va_dram = sdev->bar[SOF_FW_BLK_TYPE_SRAM]; 238 239 sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg; 240 sdev->bar[DSP_SECREG_BAR] = priv->adsp->va_secreg; 241 sdev->bar[DSP_BUSREG_BAR] = priv->adsp->va_busreg; 242 243 sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM; 244 sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; 245 246 /* set default mailbox offset for FW ready message */ 247 sdev->dsp_box.offset = mt8186_get_mailbox_offset(sdev); 248 249 ret = adsp_memory_remap_init(sdev, priv->adsp); 250 if (ret) { 251 dev_err(sdev->dev, "adsp_memory_remap_init fail!\n"); 252 return ret; 253 } 254 255 /* enable adsp clock before touching registers */ 256 ret = mt8186_adsp_init_clock(sdev); 257 if (ret) { 258 dev_err(sdev->dev, "mt8186_adsp_init_clock failed\n"); 259 return ret; 260 } 261 262 ret = mt8186_adsp_clock_on(sdev); 263 if (ret) { 264 dev_err(sdev->dev, "mt8186_adsp_clock_on fail!\n"); 265 return ret; 266 } 267 268 adsp_sram_power_on(sdev); 269 270 priv->ipc_dev = platform_device_register_data(&pdev->dev, "mtk-adsp-ipc", 271 PLATFORM_DEVID_NONE, 272 pdev, sizeof(*pdev)); 273 if (IS_ERR(priv->ipc_dev)) { 274 ret = PTR_ERR(priv->ipc_dev); 275 dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n"); 276 goto err_adsp_off; 277 } 278 279 priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); 280 if (!priv->dsp_ipc) { 281 ret = -EPROBE_DEFER; 282 dev_err(sdev->dev, "failed to get drvdata\n"); 283 goto exit_pdev_unregister; 284 } 285 286 mtk_adsp_ipc_set_data(priv->dsp_ipc, priv); 287 priv->dsp_ipc->ops = &dsp_ops; 288 289 return 0; 290 291 exit_pdev_unregister: 292 platform_device_unregister(priv->ipc_dev); 293 err_adsp_off: 294 adsp_sram_power_off(sdev); 295 mt8186_adsp_clock_off(sdev); 296 297 return ret; 298 } 299 300 static void mt8186_dsp_remove(struct snd_sof_dev *sdev) 301 { 302 struct adsp_priv *priv = sdev->pdata->hw_pdata; 303 304 platform_device_unregister(priv->ipc_dev); 305 mt8186_sof_hifixdsp_shutdown(sdev); 306 adsp_sram_power_off(sdev); 307 mt8186_adsp_clock_off(sdev); 308 } 309 310 static int mt8186_dsp_shutdown(struct snd_sof_dev *sdev) 311 { 312 return snd_sof_suspend(sdev->dev); 313 } 314 315 static int mt8186_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) 316 { 317 mt8186_sof_hifixdsp_shutdown(sdev); 318 adsp_sram_power_off(sdev); 319 mt8186_adsp_clock_off(sdev); 320 321 return 0; 322 } 323 324 static int mt8186_dsp_resume(struct snd_sof_dev *sdev) 325 { 326 int ret; 327 328 ret = mt8186_adsp_clock_on(sdev); 329 if (ret) { 330 dev_err(sdev->dev, "mt8186_adsp_clock_on fail!\n"); 331 return ret; 332 } 333 334 adsp_sram_power_on(sdev); 335 336 return ret; 337 } 338 339 static void mt8186_adsp_dump(struct snd_sof_dev *sdev, u32 flags) 340 { 341 u32 dbg_pc, dbg_data, dbg_inst, dbg_ls0stat, dbg_status, faultinfo; 342 343 /* dump debug registers */ 344 dbg_pc = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGPC); 345 dbg_data = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGDATA); 346 dbg_inst = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGINST); 347 dbg_ls0stat = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGLS0STAT); 348 dbg_status = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGSTATUS); 349 faultinfo = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PFAULTINFO); 350 351 dev_info(sdev->dev, "adsp dump : pc %#x, data %#x, dbg_inst %#x,", 352 dbg_pc, dbg_data, dbg_inst); 353 dev_info(sdev->dev, "ls0stat %#x, status %#x, faultinfo %#x", 354 dbg_ls0stat, dbg_status, faultinfo); 355 356 mtk_adsp_dump(sdev, flags); 357 } 358 359 static struct snd_soc_dai_driver mt8186_dai[] = { 360 { 361 .name = "SOF_DL1", 362 .playback = { 363 .channels_min = 1, 364 .channels_max = 2, 365 }, 366 }, 367 { 368 .name = "SOF_DL2", 369 .playback = { 370 .channels_min = 1, 371 .channels_max = 2, 372 }, 373 }, 374 { 375 .name = "SOF_UL1", 376 .capture = { 377 .channels_min = 1, 378 .channels_max = 2, 379 }, 380 }, 381 { 382 .name = "SOF_UL2", 383 .capture = { 384 .channels_min = 1, 385 .channels_max = 2, 386 }, 387 }, 388 }; 389 390 /* mt8186 ops */ 391 static const struct snd_sof_dsp_ops sof_mt8186_ops = { 392 /* probe and remove */ 393 .probe = mt8186_dsp_probe, 394 .remove = mt8186_dsp_remove, 395 .shutdown = mt8186_dsp_shutdown, 396 397 /* DSP core boot */ 398 .run = mt8186_run, 399 400 /* Block IO */ 401 .block_read = sof_block_read, 402 .block_write = sof_block_write, 403 404 /* Mailbox IO */ 405 .mailbox_read = sof_mailbox_read, 406 .mailbox_write = sof_mailbox_write, 407 408 /* Register IO */ 409 .write = sof_io_write, 410 .read = sof_io_read, 411 .write64 = sof_io_write64, 412 .read64 = sof_io_read64, 413 414 /* ipc */ 415 .send_msg = mtk_adsp_send_msg, 416 .get_mailbox_offset = mt8186_get_mailbox_offset, 417 .get_window_offset = mt8186_get_window_offset, 418 .ipc_msg_data = sof_ipc_msg_data, 419 .set_stream_data_offset = sof_set_stream_data_offset, 420 421 /* misc */ 422 .get_bar_index = mtk_adsp_get_bar_index, 423 424 /* stream callbacks */ 425 .pcm_open = sof_stream_pcm_open, 426 .pcm_hw_params = mtk_adsp_stream_pcm_hw_params, 427 .pcm_pointer = mtk_adsp_stream_pcm_pointer, 428 .pcm_close = sof_stream_pcm_close, 429 430 /* firmware loading */ 431 .load_firmware = snd_sof_load_firmware_memcpy, 432 433 /* Firmware ops */ 434 .dsp_arch_ops = &sof_xtensa_arch_ops, 435 436 /* DAI drivers */ 437 .drv = mt8186_dai, 438 .num_drv = ARRAY_SIZE(mt8186_dai), 439 440 /* Debug information */ 441 .dbg_dump = mt8186_adsp_dump, 442 .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem, 443 444 /* PM */ 445 .suspend = mt8186_dsp_suspend, 446 .resume = mt8186_dsp_resume, 447 448 /* ALSA HW info flags */ 449 .hw_info = SNDRV_PCM_INFO_MMAP | 450 SNDRV_PCM_INFO_MMAP_VALID | 451 SNDRV_PCM_INFO_INTERLEAVED | 452 SNDRV_PCM_INFO_PAUSE | 453 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, 454 }; 455 456 static struct snd_sof_of_mach sof_mt8186_machs[] = { 457 { 458 .compatible = "mediatek,mt8186", 459 .sof_tplg_filename = "sof-mt8186.tplg", 460 }, 461 {} 462 }; 463 464 static const struct sof_dev_desc sof_of_mt8186_desc = { 465 .of_machines = sof_mt8186_machs, 466 .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), 467 .ipc_default = SOF_IPC_TYPE_3, 468 .default_fw_path = { 469 [SOF_IPC_TYPE_3] = "mediatek/sof", 470 }, 471 .default_tplg_path = { 472 [SOF_IPC_TYPE_3] = "mediatek/sof-tplg", 473 }, 474 .default_fw_filename = { 475 [SOF_IPC_TYPE_3] = "sof-mt8186.ri", 476 }, 477 .nocodec_tplg_filename = "sof-mt8186-nocodec.tplg", 478 .ops = &sof_mt8186_ops, 479 }; 480 481 /* 482 * DL2, DL3, UL4, UL5 are registered as SOF FE, so creating the corresponding 483 * SOF BE to complete the pipeline. 484 */ 485 static struct snd_soc_dai_driver mt8188_dai[] = { 486 { 487 .name = "SOF_DL2", 488 .playback = { 489 .channels_min = 1, 490 .channels_max = 2, 491 }, 492 }, 493 { 494 .name = "SOF_DL3", 495 .playback = { 496 .channels_min = 1, 497 .channels_max = 2, 498 }, 499 }, 500 { 501 .name = "SOF_UL4", 502 .capture = { 503 .channels_min = 1, 504 .channels_max = 2, 505 }, 506 }, 507 { 508 .name = "SOF_UL5", 509 .capture = { 510 .channels_min = 1, 511 .channels_max = 2, 512 }, 513 }, 514 }; 515 516 /* mt8188 ops */ 517 static struct snd_sof_dsp_ops sof_mt8188_ops; 518 519 static int sof_mt8188_ops_init(struct snd_sof_dev *sdev) 520 { 521 /* common defaults */ 522 memcpy(&sof_mt8188_ops, &sof_mt8186_ops, sizeof(sof_mt8188_ops)); 523 524 sof_mt8188_ops.drv = mt8188_dai; 525 sof_mt8188_ops.num_drv = ARRAY_SIZE(mt8188_dai); 526 527 return 0; 528 } 529 530 static struct snd_sof_of_mach sof_mt8188_machs[] = { 531 { 532 .compatible = "mediatek,mt8188", 533 .sof_tplg_filename = "sof-mt8188.tplg", 534 }, 535 {} 536 }; 537 538 static const struct sof_dev_desc sof_of_mt8188_desc = { 539 .of_machines = sof_mt8188_machs, 540 .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), 541 .ipc_default = SOF_IPC_TYPE_3, 542 .default_fw_path = { 543 [SOF_IPC_TYPE_3] = "mediatek/sof", 544 }, 545 .default_tplg_path = { 546 [SOF_IPC_TYPE_3] = "mediatek/sof-tplg", 547 }, 548 .default_fw_filename = { 549 [SOF_IPC_TYPE_3] = "sof-mt8188.ri", 550 }, 551 .nocodec_tplg_filename = "sof-mt8188-nocodec.tplg", 552 .ops = &sof_mt8188_ops, 553 .ops_init = sof_mt8188_ops_init, 554 }; 555 556 static const struct of_device_id sof_of_mt8186_ids[] = { 557 { .compatible = "mediatek,mt8186-dsp", .data = &sof_of_mt8186_desc}, 558 { .compatible = "mediatek,mt8188-dsp", .data = &sof_of_mt8188_desc}, 559 { } 560 }; 561 MODULE_DEVICE_TABLE(of, sof_of_mt8186_ids); 562 563 /* DT driver definition */ 564 static struct platform_driver snd_sof_of_mt8186_driver = { 565 .probe = sof_of_probe, 566 .remove = sof_of_remove, 567 .shutdown = sof_of_shutdown, 568 .driver = { 569 .name = "sof-audio-of-mt8186", 570 .pm = pm_ptr(&sof_of_pm), 571 .of_match_table = sof_of_mt8186_ids, 572 }, 573 }; 574 module_platform_driver(snd_sof_of_mt8186_driver); 575 576 MODULE_LICENSE("Dual BSD/GPL"); 577 MODULE_DESCRIPTION("SOF support for MT8186/MT8188 platforms"); 578 MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA"); 579 MODULE_IMPORT_NS("SND_SOC_SOF_MTK_COMMON"); 580