Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration.
0004  *
0005  * Copyright (c) 2013, Intel Corporation.
0006  *
0007  *  Authors:    Ramesh Babu K V <Ramesh.Babu@intel.com>
0008  *  Authors:    Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/fs.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/slab.h>
0015 #include <linux/io.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/firmware.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/pm_qos.h>
0020 #include <linux/dmi.h>
0021 #include <linux/acpi.h>
0022 #include <asm/platform_sst_audio.h>
0023 #include <sound/core.h>
0024 #include <sound/intel-dsp-config.h>
0025 #include <sound/soc.h>
0026 #include <sound/compress_driver.h>
0027 #include <acpi/acbuffer.h>
0028 #include <acpi/platform/acenv.h>
0029 #include <acpi/platform/aclinux.h>
0030 #include <acpi/actypes.h>
0031 #include <acpi/acpi_bus.h>
0032 #include <sound/soc-acpi.h>
0033 #include <sound/soc-acpi-intel-match.h>
0034 #include "../sst-mfld-platform.h"
0035 #include "../../common/soc-intel-quirks.h"
0036 #include "sst.h"
0037 
0038 /* LPE viewpoint addresses */
0039 #define SST_BYT_IRAM_PHY_START  0xff2c0000
0040 #define SST_BYT_IRAM_PHY_END    0xff2d4000
0041 #define SST_BYT_DRAM_PHY_START  0xff300000
0042 #define SST_BYT_DRAM_PHY_END    0xff320000
0043 #define SST_BYT_IMR_VIRT_START  0xc0000000 /* virtual addr in LPE */
0044 #define SST_BYT_IMR_VIRT_END    0xc01fffff
0045 #define SST_BYT_SHIM_PHY_ADDR   0xff340000
0046 #define SST_BYT_MBOX_PHY_ADDR   0xff344000
0047 #define SST_BYT_DMA0_PHY_ADDR   0xff298000
0048 #define SST_BYT_DMA1_PHY_ADDR   0xff29c000
0049 #define SST_BYT_SSP0_PHY_ADDR   0xff2a0000
0050 #define SST_BYT_SSP2_PHY_ADDR   0xff2a2000
0051 
0052 #define BYT_FW_MOD_TABLE_OFFSET 0x80000
0053 #define BYT_FW_MOD_TABLE_SIZE   0x100
0054 #define BYT_FW_MOD_OFFSET   (BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE)
0055 
0056 static const struct sst_info byt_fwparse_info = {
0057     .use_elf    = false,
0058     .max_streams    = 25,
0059     .iram_start = SST_BYT_IRAM_PHY_START,
0060     .iram_end   = SST_BYT_IRAM_PHY_END,
0061     .iram_use   = true,
0062     .dram_start = SST_BYT_DRAM_PHY_START,
0063     .dram_end   = SST_BYT_DRAM_PHY_END,
0064     .dram_use   = true,
0065     .imr_start  = SST_BYT_IMR_VIRT_START,
0066     .imr_end    = SST_BYT_IMR_VIRT_END,
0067     .imr_use    = true,
0068     .mailbox_start  = SST_BYT_MBOX_PHY_ADDR,
0069     .num_probes = 0,
0070     .lpe_viewpt_rqd  = true,
0071 };
0072 
0073 static const struct sst_ipc_info byt_ipc_info = {
0074     .ipc_offset = 0,
0075     .mbox_recv_off = 0x400,
0076 };
0077 
0078 static const struct sst_lib_dnld_info  byt_lib_dnld_info = {
0079     .mod_base           = SST_BYT_IMR_VIRT_START,
0080     .mod_end            = SST_BYT_IMR_VIRT_END,
0081     .mod_table_offset   = BYT_FW_MOD_TABLE_OFFSET,
0082     .mod_table_size     = BYT_FW_MOD_TABLE_SIZE,
0083     .mod_ddr_dnld       = false,
0084 };
0085 
0086 static const struct sst_res_info byt_rvp_res_info = {
0087     .shim_offset = 0x140000,
0088     .shim_size = 0x000100,
0089     .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
0090     .ssp0_offset = 0xa0000,
0091     .ssp0_size = 0x1000,
0092     .dma0_offset = 0x98000,
0093     .dma0_size = 0x4000,
0094     .dma1_offset = 0x9c000,
0095     .dma1_size = 0x4000,
0096     .iram_offset = 0x0c0000,
0097     .iram_size = 0x14000,
0098     .dram_offset = 0x100000,
0099     .dram_size = 0x28000,
0100     .mbox_offset = 0x144000,
0101     .mbox_size = 0x1000,
0102     .acpi_lpe_res_index = 0,
0103     .acpi_ddr_index = 2,
0104     .acpi_ipc_irq_index = 5,
0105 };
0106 
0107 /* BYTCR has different BIOS from BYT */
0108 static const struct sst_res_info bytcr_res_info = {
0109     .shim_offset = 0x140000,
0110     .shim_size = 0x000100,
0111     .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
0112     .ssp0_offset = 0xa0000,
0113     .ssp0_size = 0x1000,
0114     .dma0_offset = 0x98000,
0115     .dma0_size = 0x4000,
0116     .dma1_offset = 0x9c000,
0117     .dma1_size = 0x4000,
0118     .iram_offset = 0x0c0000,
0119     .iram_size = 0x14000,
0120     .dram_offset = 0x100000,
0121     .dram_size = 0x28000,
0122     .mbox_offset = 0x144000,
0123     .mbox_size = 0x1000,
0124     .acpi_lpe_res_index = 0,
0125     .acpi_ddr_index = 2,
0126     .acpi_ipc_irq_index = 0
0127 };
0128 
0129 static struct sst_platform_info byt_rvp_platform_data = {
0130     .probe_data = &byt_fwparse_info,
0131     .ipc_info = &byt_ipc_info,
0132     .lib_info = &byt_lib_dnld_info,
0133     .res_info = &byt_rvp_res_info,
0134     .platform = "sst-mfld-platform",
0135     .streams_lost_on_suspend = true,
0136 };
0137 
0138 /* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
0139  * so pdata is same as Baytrail, minus the streams_lost_on_suspend quirk.
0140  */
0141 static struct sst_platform_info chv_platform_data = {
0142     .probe_data = &byt_fwparse_info,
0143     .ipc_info = &byt_ipc_info,
0144     .lib_info = &byt_lib_dnld_info,
0145     .res_info = &byt_rvp_res_info,
0146     .platform = "sst-mfld-platform",
0147 };
0148 
0149 static int sst_platform_get_resources(struct intel_sst_drv *ctx)
0150 {
0151     struct resource *rsrc;
0152     struct platform_device *pdev = to_platform_device(ctx->dev);
0153 
0154     /* All ACPI resource request here */
0155     /* Get Shim addr */
0156     rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
0157                     ctx->pdata->res_info->acpi_lpe_res_index);
0158     if (!rsrc) {
0159         dev_err(ctx->dev, "Invalid SHIM base from IFWI\n");
0160         return -EIO;
0161     }
0162     dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start,
0163                     (unsigned int)resource_size(rsrc));
0164 
0165     ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset;
0166     ctx->iram_end =  ctx->iram_base + ctx->pdata->res_info->iram_size - 1;
0167     dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base);
0168     ctx->iram = devm_ioremap(ctx->dev, ctx->iram_base,
0169                      ctx->pdata->res_info->iram_size);
0170     if (!ctx->iram) {
0171         dev_err(ctx->dev, "unable to map IRAM\n");
0172         return -EIO;
0173     }
0174 
0175     ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset;
0176     ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1;
0177     dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base);
0178     ctx->dram = devm_ioremap(ctx->dev, ctx->dram_base,
0179                      ctx->pdata->res_info->dram_size);
0180     if (!ctx->dram) {
0181         dev_err(ctx->dev, "unable to map DRAM\n");
0182         return -EIO;
0183     }
0184 
0185     ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset;
0186     dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add);
0187     ctx->shim = devm_ioremap(ctx->dev, ctx->shim_phy_add,
0188                     ctx->pdata->res_info->shim_size);
0189     if (!ctx->shim) {
0190         dev_err(ctx->dev, "unable to map SHIM\n");
0191         return -EIO;
0192     }
0193 
0194     /* reassign physical address to LPE viewpoint address */
0195     ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr;
0196 
0197     /* Get mailbox addr */
0198     ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset;
0199     dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add);
0200     ctx->mailbox = devm_ioremap(ctx->dev, ctx->mailbox_add,
0201                         ctx->pdata->res_info->mbox_size);
0202     if (!ctx->mailbox) {
0203         dev_err(ctx->dev, "unable to map mailbox\n");
0204         return -EIO;
0205     }
0206 
0207     /* reassign physical address to LPE viewpoint address */
0208     ctx->mailbox_add = ctx->info.mailbox_start;
0209 
0210     rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
0211                     ctx->pdata->res_info->acpi_ddr_index);
0212     if (!rsrc) {
0213         dev_err(ctx->dev, "Invalid DDR base from IFWI\n");
0214         return -EIO;
0215     }
0216     ctx->ddr_base = rsrc->start;
0217     ctx->ddr_end = rsrc->end;
0218     dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base);
0219     ctx->ddr = devm_ioremap(ctx->dev, ctx->ddr_base,
0220                     resource_size(rsrc));
0221     if (!ctx->ddr) {
0222         dev_err(ctx->dev, "unable to map DDR\n");
0223         return -EIO;
0224     }
0225 
0226     /* Find the IRQ */
0227     ctx->irq_num = platform_get_irq(pdev,
0228                 ctx->pdata->res_info->acpi_ipc_irq_index);
0229     if (ctx->irq_num <= 0)
0230         return ctx->irq_num < 0 ? ctx->irq_num : -EIO;
0231 
0232     return 0;
0233 }
0234 
0235 static int sst_acpi_probe(struct platform_device *pdev)
0236 {
0237     struct device *dev = &pdev->dev;
0238     int ret = 0;
0239     struct intel_sst_drv *ctx;
0240     const struct acpi_device_id *id;
0241     struct snd_soc_acpi_mach *mach;
0242     struct platform_device *mdev;
0243     struct platform_device *plat_dev;
0244     struct sst_platform_info *pdata;
0245     unsigned int dev_id;
0246 
0247     id = acpi_match_device(dev->driver->acpi_match_table, dev);
0248     if (!id)
0249         return -ENODEV;
0250 
0251     ret = snd_intel_acpi_dsp_driver_probe(dev, id->id);
0252     if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SST) {
0253         dev_dbg(dev, "SST ACPI driver not selected, aborting probe\n");
0254         return -ENODEV;
0255     }
0256 
0257     dev_dbg(dev, "for %s\n", id->id);
0258 
0259     mach = (struct snd_soc_acpi_mach *)id->driver_data;
0260     mach = snd_soc_acpi_find_machine(mach);
0261     if (mach == NULL) {
0262         dev_err(dev, "No matching machine driver found\n");
0263         return -ENODEV;
0264     }
0265 
0266     if (soc_intel_is_byt())
0267         mach->pdata = &byt_rvp_platform_data;
0268     else
0269         mach->pdata = &chv_platform_data;
0270     pdata = mach->pdata;
0271 
0272     ret = kstrtouint(id->id, 16, &dev_id);
0273     if (ret < 0) {
0274         dev_err(dev, "Unique device id conversion error: %d\n", ret);
0275         return ret;
0276     }
0277 
0278     dev_dbg(dev, "ACPI device id: %x\n", dev_id);
0279 
0280     ret = sst_alloc_drv_context(&ctx, dev, dev_id);
0281     if (ret < 0)
0282         return ret;
0283 
0284     if (soc_intel_is_byt_cr(pdev)) {
0285         /* override resource info */
0286         byt_rvp_platform_data.res_info = &bytcr_res_info;
0287     }
0288 
0289     /* update machine parameters */
0290     mach->mach_params.acpi_ipc_irq_index =
0291         pdata->res_info->acpi_ipc_irq_index;
0292 
0293     plat_dev = platform_device_register_data(dev, pdata->platform, -1,
0294                         NULL, 0);
0295     if (IS_ERR(plat_dev)) {
0296         dev_err(dev, "Failed to create machine device: %s\n",
0297             pdata->platform);
0298         return PTR_ERR(plat_dev);
0299     }
0300 
0301     /*
0302      * Create platform device for sst machine driver,
0303      * pass machine info as pdata
0304      */
0305     mdev = platform_device_register_data(dev, mach->drv_name, -1,
0306                     (const void *)mach, sizeof(*mach));
0307     if (IS_ERR(mdev)) {
0308         dev_err(dev, "Failed to create machine device: %s\n",
0309             mach->drv_name);
0310         return PTR_ERR(mdev);
0311     }
0312 
0313     /* Fill sst platform data */
0314     ctx->pdata = pdata;
0315     strcpy(ctx->firmware_name, mach->fw_filename);
0316 
0317     ret = sst_platform_get_resources(ctx);
0318     if (ret)
0319         return ret;
0320 
0321     ret = sst_context_init(ctx);
0322     if (ret < 0)
0323         return ret;
0324 
0325     sst_configure_runtime_pm(ctx);
0326     platform_set_drvdata(pdev, ctx);
0327     return ret;
0328 }
0329 
0330 /**
0331 * sst_acpi_remove - remove function
0332 *
0333 * @pdev:    platform device structure
0334 *
0335 * This function is called by OS when a device is unloaded
0336 * This frees the interrupt etc
0337 */
0338 static int sst_acpi_remove(struct platform_device *pdev)
0339 {
0340     struct intel_sst_drv *ctx;
0341 
0342     ctx = platform_get_drvdata(pdev);
0343     sst_context_cleanup(ctx);
0344     platform_set_drvdata(pdev, NULL);
0345     return 0;
0346 }
0347 
0348 static const struct acpi_device_id sst_acpi_ids[] = {
0349     { "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
0350     { "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
0351     { },
0352 };
0353 
0354 MODULE_DEVICE_TABLE(acpi, sst_acpi_ids);
0355 
0356 static struct platform_driver sst_acpi_driver = {
0357     .driver = {
0358         .name           = "intel_sst_acpi",
0359         .acpi_match_table   = ACPI_PTR(sst_acpi_ids),
0360         .pm         = &intel_sst_pm,
0361     },
0362     .probe  = sst_acpi_probe,
0363     .remove = sst_acpi_remove,
0364 };
0365 
0366 module_platform_driver(sst_acpi_driver);
0367 
0368 MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver");
0369 MODULE_AUTHOR("Ramesh Babu K V");
0370 MODULE_AUTHOR("Omair Mohammed Abdullah");
0371 MODULE_LICENSE("GPL v2");
0372 MODULE_ALIAS("sst");