Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // Copyright 2019 NXP
0004 //
0005 // Author: Daniel Baluta <daniel.baluta@nxp.com>
0006 //
0007 // Hardware interface for audio DSP on i.MX8
0008 
0009 #include <linux/firmware.h>
0010 #include <linux/of_platform.h>
0011 #include <linux/of_address.h>
0012 #include <linux/of_irq.h>
0013 #include <linux/pm_domain.h>
0014 
0015 #include <linux/module.h>
0016 #include <sound/sof.h>
0017 #include <sound/sof/xtensa.h>
0018 #include <linux/firmware/imx/ipc.h>
0019 #include <linux/firmware/imx/dsp.h>
0020 
0021 #include <linux/firmware/imx/svc/misc.h>
0022 #include <dt-bindings/firmware/imx/rsrc.h>
0023 #include "../ops.h"
0024 #include "../sof-of-dev.h"
0025 #include "imx-common.h"
0026 
0027 /* DSP memories */
0028 #define IRAM_OFFSET     0x10000
0029 #define IRAM_SIZE       (2 * 1024)
0030 #define DRAM0_OFFSET        0x0
0031 #define DRAM0_SIZE      (32 * 1024)
0032 #define DRAM1_OFFSET        0x8000
0033 #define DRAM1_SIZE      (32 * 1024)
0034 #define SYSRAM_OFFSET       0x18000
0035 #define SYSRAM_SIZE     (256 * 1024)
0036 #define SYSROM_OFFSET       0x58000
0037 #define SYSROM_SIZE     (192 * 1024)
0038 
0039 #define RESET_VECTOR_VADDR  0x596f8000
0040 
0041 #define MBOX_OFFSET 0x800000
0042 #define MBOX_SIZE   0x1000
0043 
0044 /* DSP clocks */
0045 static struct clk_bulk_data imx8_dsp_clks[] = {
0046     { .id = "ipg" },
0047     { .id = "ocram" },
0048     { .id = "core" },
0049 };
0050 
0051 struct imx8_priv {
0052     struct device *dev;
0053     struct snd_sof_dev *sdev;
0054 
0055     /* DSP IPC handler */
0056     struct imx_dsp_ipc *dsp_ipc;
0057     struct platform_device *ipc_dev;
0058 
0059     /* System Controller IPC handler */
0060     struct imx_sc_ipc *sc_ipc;
0061 
0062     /* Power domain handling */
0063     int num_domains;
0064     struct device **pd_dev;
0065     struct device_link **link;
0066 
0067     struct imx_clocks *clks;
0068 };
0069 
0070 static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev)
0071 {
0072     return MBOX_OFFSET;
0073 }
0074 
0075 static int imx8_get_window_offset(struct snd_sof_dev *sdev, u32 id)
0076 {
0077     return MBOX_OFFSET;
0078 }
0079 
0080 static void imx8_dsp_handle_reply(struct imx_dsp_ipc *ipc)
0081 {
0082     struct imx8_priv *priv = imx_dsp_get_data(ipc);
0083     unsigned long flags;
0084 
0085     spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
0086     snd_sof_ipc_process_reply(priv->sdev, 0);
0087     spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
0088 }
0089 
0090 static void imx8_dsp_handle_request(struct imx_dsp_ipc *ipc)
0091 {
0092     struct imx8_priv *priv = imx_dsp_get_data(ipc);
0093     u32 p; /* panic code */
0094 
0095     /* Read the message from the debug box. */
0096     sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, &p, sizeof(p));
0097 
0098     /* Check to see if the message is a panic code (0x0dead***) */
0099     if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC)
0100         snd_sof_dsp_panic(priv->sdev, p, true);
0101     else
0102         snd_sof_ipc_msgs_rx(priv->sdev);
0103 }
0104 
0105 static struct imx_dsp_ops dsp_ops = {
0106     .handle_reply       = imx8_dsp_handle_reply,
0107     .handle_request     = imx8_dsp_handle_request,
0108 };
0109 
0110 static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0111 {
0112     struct imx8_priv *priv = sdev->pdata->hw_pdata;
0113 
0114     sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
0115               msg->msg_size);
0116     imx_dsp_ring_doorbell(priv->dsp_ipc, 0);
0117 
0118     return 0;
0119 }
0120 
0121 /*
0122  * DSP control.
0123  */
0124 static int imx8x_run(struct snd_sof_dev *sdev)
0125 {
0126     struct imx8_priv *dsp_priv = sdev->pdata->hw_pdata;
0127     int ret;
0128 
0129     ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
0130                       IMX_SC_C_OFS_SEL, 1);
0131     if (ret < 0) {
0132         dev_err(sdev->dev, "Error system address offset source select\n");
0133         return ret;
0134     }
0135 
0136     ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
0137                       IMX_SC_C_OFS_AUDIO, 0x80);
0138     if (ret < 0) {
0139         dev_err(sdev->dev, "Error system address offset of AUDIO\n");
0140         return ret;
0141     }
0142 
0143     ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
0144                       IMX_SC_C_OFS_PERIPH, 0x5A);
0145     if (ret < 0) {
0146         dev_err(sdev->dev, "Error system address offset of PERIPH %d\n",
0147             ret);
0148         return ret;
0149     }
0150 
0151     ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
0152                       IMX_SC_C_OFS_IRQ, 0x51);
0153     if (ret < 0) {
0154         dev_err(sdev->dev, "Error system address offset of IRQ\n");
0155         return ret;
0156     }
0157 
0158     imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true,
0159                 RESET_VECTOR_VADDR);
0160 
0161     return 0;
0162 }
0163 
0164 static int imx8_run(struct snd_sof_dev *sdev)
0165 {
0166     struct imx8_priv *dsp_priv = sdev->pdata->hw_pdata;
0167     int ret;
0168 
0169     ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
0170                       IMX_SC_C_OFS_SEL, 0);
0171     if (ret < 0) {
0172         dev_err(sdev->dev, "Error system address offset source select\n");
0173         return ret;
0174     }
0175 
0176     imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true,
0177                 RESET_VECTOR_VADDR);
0178 
0179     return 0;
0180 }
0181 
0182 static int imx8_probe(struct snd_sof_dev *sdev)
0183 {
0184     struct platform_device *pdev =
0185         container_of(sdev->dev, struct platform_device, dev);
0186     struct device_node *np = pdev->dev.of_node;
0187     struct device_node *res_node;
0188     struct resource *mmio;
0189     struct imx8_priv *priv;
0190     struct resource res;
0191     u32 base, size;
0192     int ret = 0;
0193     int i;
0194 
0195     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0196     if (!priv)
0197         return -ENOMEM;
0198 
0199     priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL);
0200     if (!priv->clks)
0201         return -ENOMEM;
0202 
0203     sdev->num_cores = 1;
0204     sdev->pdata->hw_pdata = priv;
0205     priv->dev = sdev->dev;
0206     priv->sdev = sdev;
0207 
0208     /* power up device associated power domains */
0209     priv->num_domains = of_count_phandle_with_args(np, "power-domains",
0210                                "#power-domain-cells");
0211     if (priv->num_domains < 0) {
0212         dev_err(sdev->dev, "no power-domains property in %pOF\n", np);
0213         return priv->num_domains;
0214     }
0215 
0216     priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains,
0217                       sizeof(*priv->pd_dev), GFP_KERNEL);
0218     if (!priv->pd_dev)
0219         return -ENOMEM;
0220 
0221     priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains,
0222                     sizeof(*priv->link), GFP_KERNEL);
0223     if (!priv->link)
0224         return -ENOMEM;
0225 
0226     for (i = 0; i < priv->num_domains; i++) {
0227         priv->pd_dev[i] = dev_pm_domain_attach_by_id(&pdev->dev, i);
0228         if (IS_ERR(priv->pd_dev[i])) {
0229             ret = PTR_ERR(priv->pd_dev[i]);
0230             goto exit_unroll_pm;
0231         }
0232         priv->link[i] = device_link_add(&pdev->dev, priv->pd_dev[i],
0233                         DL_FLAG_STATELESS |
0234                         DL_FLAG_PM_RUNTIME |
0235                         DL_FLAG_RPM_ACTIVE);
0236         if (!priv->link[i]) {
0237             ret = -ENOMEM;
0238             dev_pm_domain_detach(priv->pd_dev[i], false);
0239             goto exit_unroll_pm;
0240         }
0241     }
0242 
0243     ret = imx_scu_get_handle(&priv->sc_ipc);
0244     if (ret) {
0245         dev_err(sdev->dev, "Cannot obtain SCU handle (err = %d)\n",
0246             ret);
0247         goto exit_unroll_pm;
0248     }
0249 
0250     priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp",
0251                               PLATFORM_DEVID_NONE,
0252                               pdev, sizeof(*pdev));
0253     if (IS_ERR(priv->ipc_dev)) {
0254         ret = PTR_ERR(priv->ipc_dev);
0255         goto exit_unroll_pm;
0256     }
0257 
0258     priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev);
0259     if (!priv->dsp_ipc) {
0260         /* DSP IPC driver not probed yet, try later */
0261         ret = -EPROBE_DEFER;
0262         dev_err(sdev->dev, "Failed to get drvdata\n");
0263         goto exit_pdev_unregister;
0264     }
0265 
0266     imx_dsp_set_data(priv->dsp_ipc, priv);
0267     priv->dsp_ipc->ops = &dsp_ops;
0268 
0269     /* DSP base */
0270     mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0271     if (mmio) {
0272         base = mmio->start;
0273         size = resource_size(mmio);
0274     } else {
0275         dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n");
0276         ret = -EINVAL;
0277         goto exit_pdev_unregister;
0278     }
0279 
0280     sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size);
0281     if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) {
0282         dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n",
0283             base, size);
0284         ret = -ENODEV;
0285         goto exit_pdev_unregister;
0286     }
0287     sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM;
0288 
0289     res_node = of_parse_phandle(np, "memory-region", 0);
0290     if (!res_node) {
0291         dev_err(&pdev->dev, "failed to get memory region node\n");
0292         ret = -ENODEV;
0293         goto exit_pdev_unregister;
0294     }
0295 
0296     ret = of_address_to_resource(res_node, 0, &res);
0297     of_node_put(res_node);
0298     if (ret) {
0299         dev_err(&pdev->dev, "failed to get reserved region address\n");
0300         goto exit_pdev_unregister;
0301     }
0302 
0303     sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start,
0304                               resource_size(&res));
0305     if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) {
0306         dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n",
0307             base, size);
0308         ret = -ENOMEM;
0309         goto exit_pdev_unregister;
0310     }
0311     sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
0312 
0313     /* set default mailbox offset for FW ready message */
0314     sdev->dsp_box.offset = MBOX_OFFSET;
0315 
0316     /* init clocks info */
0317     priv->clks->dsp_clks = imx8_dsp_clks;
0318     priv->clks->num_dsp_clks = ARRAY_SIZE(imx8_dsp_clks);
0319 
0320     ret = imx8_parse_clocks(sdev, priv->clks);
0321     if (ret < 0)
0322         goto exit_pdev_unregister;
0323 
0324     ret = imx8_enable_clocks(sdev, priv->clks);
0325     if (ret < 0)
0326         goto exit_pdev_unregister;
0327 
0328     return 0;
0329 
0330 exit_pdev_unregister:
0331     platform_device_unregister(priv->ipc_dev);
0332 exit_unroll_pm:
0333     while (--i >= 0) {
0334         device_link_del(priv->link[i]);
0335         dev_pm_domain_detach(priv->pd_dev[i], false);
0336     }
0337 
0338     return ret;
0339 }
0340 
0341 static int imx8_remove(struct snd_sof_dev *sdev)
0342 {
0343     struct imx8_priv *priv = sdev->pdata->hw_pdata;
0344     int i;
0345 
0346     imx8_disable_clocks(sdev, priv->clks);
0347     platform_device_unregister(priv->ipc_dev);
0348 
0349     for (i = 0; i < priv->num_domains; i++) {
0350         device_link_del(priv->link[i]);
0351         dev_pm_domain_detach(priv->pd_dev[i], false);
0352     }
0353 
0354     return 0;
0355 }
0356 
0357 /* on i.MX8 there is 1 to 1 match between type and BAR idx */
0358 static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type)
0359 {
0360     /* Only IRAM and SRAM bars are valid */
0361     switch (type) {
0362     case SOF_FW_BLK_TYPE_IRAM:
0363     case SOF_FW_BLK_TYPE_SRAM:
0364         return type;
0365     default:
0366         return -EINVAL;
0367     }
0368 }
0369 
0370 static void imx8_suspend(struct snd_sof_dev *sdev)
0371 {
0372     int i;
0373     struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
0374 
0375     for (i = 0; i < DSP_MU_CHAN_NUM; i++)
0376         imx_dsp_free_channel(priv->dsp_ipc, i);
0377 
0378     imx8_disable_clocks(sdev, priv->clks);
0379 }
0380 
0381 static int imx8_resume(struct snd_sof_dev *sdev)
0382 {
0383     struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
0384     int ret;
0385     int i;
0386 
0387     ret = imx8_enable_clocks(sdev, priv->clks);
0388     if (ret < 0)
0389         return ret;
0390 
0391     for (i = 0; i < DSP_MU_CHAN_NUM; i++)
0392         imx_dsp_request_channel(priv->dsp_ipc, i);
0393 
0394     return 0;
0395 }
0396 
0397 static int imx8_dsp_runtime_resume(struct snd_sof_dev *sdev)
0398 {
0399     int ret;
0400     const struct sof_dsp_power_state target_dsp_state = {
0401         .state = SOF_DSP_PM_D0,
0402     };
0403 
0404     ret = imx8_resume(sdev);
0405     if (ret < 0)
0406         return ret;
0407 
0408     return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
0409 }
0410 
0411 static int imx8_dsp_runtime_suspend(struct snd_sof_dev *sdev)
0412 {
0413     const struct sof_dsp_power_state target_dsp_state = {
0414         .state = SOF_DSP_PM_D3,
0415     };
0416 
0417     imx8_suspend(sdev);
0418 
0419     return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
0420 }
0421 
0422 static int imx8_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state)
0423 {
0424     const struct sof_dsp_power_state target_dsp_state = {
0425         .state = target_state,
0426     };
0427 
0428     if (!pm_runtime_suspended(sdev->dev))
0429         imx8_suspend(sdev);
0430 
0431     return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
0432 }
0433 
0434 static int imx8_dsp_resume(struct snd_sof_dev *sdev)
0435 {
0436     int ret;
0437     const struct sof_dsp_power_state target_dsp_state = {
0438         .state = SOF_DSP_PM_D0,
0439     };
0440 
0441     ret = imx8_resume(sdev);
0442     if (ret < 0)
0443         return ret;
0444 
0445     if (pm_runtime_suspended(sdev->dev)) {
0446         pm_runtime_disable(sdev->dev);
0447         pm_runtime_set_active(sdev->dev);
0448         pm_runtime_mark_last_busy(sdev->dev);
0449         pm_runtime_enable(sdev->dev);
0450         pm_runtime_idle(sdev->dev);
0451     }
0452 
0453     return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
0454 }
0455 
0456 static struct snd_soc_dai_driver imx8_dai[] = {
0457 {
0458     .name = "esai0",
0459     .playback = {
0460         .channels_min = 1,
0461         .channels_max = 8,
0462     },
0463     .capture = {
0464         .channels_min = 1,
0465         .channels_max = 8,
0466     },
0467 },
0468 {
0469     .name = "sai1",
0470     .playback = {
0471         .channels_min = 1,
0472         .channels_max = 32,
0473     },
0474     .capture = {
0475         .channels_min = 1,
0476         .channels_max = 32,
0477     },
0478 },
0479 };
0480 
0481 static int imx8_dsp_set_power_state(struct snd_sof_dev *sdev,
0482                     const struct sof_dsp_power_state *target_state)
0483 {
0484     sdev->dsp_power_state = *target_state;
0485 
0486     return 0;
0487 }
0488 
0489 /* i.MX8 ops */
0490 static struct snd_sof_dsp_ops sof_imx8_ops = {
0491     /* probe and remove */
0492     .probe      = imx8_probe,
0493     .remove     = imx8_remove,
0494     /* DSP core boot */
0495     .run        = imx8_run,
0496 
0497     /* Block IO */
0498     .block_read = sof_block_read,
0499     .block_write    = sof_block_write,
0500 
0501     /* Mailbox IO */
0502     .mailbox_read   = sof_mailbox_read,
0503     .mailbox_write  = sof_mailbox_write,
0504 
0505     /* ipc */
0506     .send_msg   = imx8_send_msg,
0507     .get_mailbox_offset = imx8_get_mailbox_offset,
0508     .get_window_offset  = imx8_get_window_offset,
0509 
0510     .ipc_msg_data   = sof_ipc_msg_data,
0511     .set_stream_data_offset = sof_set_stream_data_offset,
0512 
0513     .get_bar_index  = imx8_get_bar_index,
0514 
0515     /* firmware loading */
0516     .load_firmware  = snd_sof_load_firmware_memcpy,
0517 
0518     /* Debug information */
0519     .dbg_dump = imx8_dump,
0520     .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
0521 
0522     /* stream callbacks */
0523     .pcm_open = sof_stream_pcm_open,
0524     .pcm_close = sof_stream_pcm_close,
0525 
0526     /* Firmware ops */
0527     .dsp_arch_ops = &sof_xtensa_arch_ops,
0528 
0529     /* DAI drivers */
0530     .drv = imx8_dai,
0531     .num_drv = ARRAY_SIZE(imx8_dai),
0532 
0533     /* ALSA HW info flags */
0534     .hw_info =  SNDRV_PCM_INFO_MMAP |
0535             SNDRV_PCM_INFO_MMAP_VALID |
0536             SNDRV_PCM_INFO_INTERLEAVED |
0537             SNDRV_PCM_INFO_PAUSE |
0538             SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
0539 
0540     /* PM */
0541     .runtime_suspend    = imx8_dsp_runtime_suspend,
0542     .runtime_resume     = imx8_dsp_runtime_resume,
0543 
0544     .suspend    = imx8_dsp_suspend,
0545     .resume     = imx8_dsp_resume,
0546 
0547     .set_power_state    = imx8_dsp_set_power_state,
0548 };
0549 
0550 /* i.MX8X ops */
0551 static struct snd_sof_dsp_ops sof_imx8x_ops = {
0552     /* probe and remove */
0553     .probe      = imx8_probe,
0554     .remove     = imx8_remove,
0555     /* DSP core boot */
0556     .run        = imx8x_run,
0557 
0558     /* Block IO */
0559     .block_read = sof_block_read,
0560     .block_write    = sof_block_write,
0561 
0562     /* Mailbox IO */
0563     .mailbox_read   = sof_mailbox_read,
0564     .mailbox_write  = sof_mailbox_write,
0565 
0566     /* ipc */
0567     .send_msg   = imx8_send_msg,
0568     .get_mailbox_offset = imx8_get_mailbox_offset,
0569     .get_window_offset  = imx8_get_window_offset,
0570 
0571     .ipc_msg_data   = sof_ipc_msg_data,
0572     .set_stream_data_offset = sof_set_stream_data_offset,
0573 
0574     .get_bar_index  = imx8_get_bar_index,
0575 
0576     /* firmware loading */
0577     .load_firmware  = snd_sof_load_firmware_memcpy,
0578 
0579     /* Debug information */
0580     .dbg_dump = imx8_dump,
0581     .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
0582 
0583     /* stream callbacks */
0584     .pcm_open = sof_stream_pcm_open,
0585     .pcm_close = sof_stream_pcm_close,
0586 
0587     /* Firmware ops */
0588     .dsp_arch_ops = &sof_xtensa_arch_ops,
0589 
0590     /* DAI drivers */
0591     .drv = imx8_dai,
0592     .num_drv = ARRAY_SIZE(imx8_dai),
0593 
0594     /* PM */
0595     .runtime_suspend    = imx8_dsp_runtime_suspend,
0596     .runtime_resume     = imx8_dsp_runtime_resume,
0597 
0598     .suspend    = imx8_dsp_suspend,
0599     .resume     = imx8_dsp_resume,
0600 
0601     .set_power_state    = imx8_dsp_set_power_state,
0602 
0603     /* ALSA HW info flags */
0604     .hw_info =  SNDRV_PCM_INFO_MMAP |
0605             SNDRV_PCM_INFO_MMAP_VALID |
0606             SNDRV_PCM_INFO_INTERLEAVED |
0607             SNDRV_PCM_INFO_PAUSE |
0608             SNDRV_PCM_INFO_NO_PERIOD_WAKEUP
0609 };
0610 
0611 static struct sof_dev_desc sof_of_imx8qxp_desc = {
0612     .ipc_supported_mask = BIT(SOF_IPC),
0613     .ipc_default        = SOF_IPC,
0614     .default_fw_path = {
0615         [SOF_IPC] = "imx/sof",
0616     },
0617     .default_tplg_path = {
0618         [SOF_IPC] = "imx/sof-tplg",
0619     },
0620     .default_fw_filename = {
0621         [SOF_IPC] = "sof-imx8x.ri",
0622     },
0623     .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
0624     .ops = &sof_imx8x_ops,
0625 };
0626 
0627 static struct sof_dev_desc sof_of_imx8qm_desc = {
0628     .ipc_supported_mask = BIT(SOF_IPC),
0629     .ipc_default        = SOF_IPC,
0630     .default_fw_path = {
0631         [SOF_IPC] = "imx/sof",
0632     },
0633     .default_tplg_path = {
0634         [SOF_IPC] = "imx/sof-tplg",
0635     },
0636     .default_fw_filename = {
0637         [SOF_IPC] = "sof-imx8.ri",
0638     },
0639     .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
0640     .ops = &sof_imx8_ops,
0641 };
0642 
0643 static const struct of_device_id sof_of_imx8_ids[] = {
0644     { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc},
0645     { .compatible = "fsl,imx8qm-dsp", .data = &sof_of_imx8qm_desc},
0646     { }
0647 };
0648 MODULE_DEVICE_TABLE(of, sof_of_imx8_ids);
0649 
0650 /* DT driver definition */
0651 static struct platform_driver snd_sof_of_imx8_driver = {
0652     .probe = sof_of_probe,
0653     .remove = sof_of_remove,
0654     .driver = {
0655         .name = "sof-audio-of-imx8",
0656         .pm = &sof_of_pm,
0657         .of_match_table = sof_of_imx8_ids,
0658     },
0659 };
0660 module_platform_driver(snd_sof_of_imx8_driver);
0661 
0662 MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
0663 MODULE_LICENSE("Dual BSD/GPL");