Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // This file is provided under a dual BSD/GPLv2 license. When using or
0004 // redistributing this file, you may do so under either license.
0005 //
0006 // Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
0007 //
0008 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
0009 
0010 /*
0011  * PCI interface for Renoir ACP device
0012  */
0013 
0014 #include <linux/module.h>
0015 #include <linux/pci.h>
0016 #include <linux/platform_device.h>
0017 #include <sound/sof.h>
0018 #include <sound/soc-acpi.h>
0019 
0020 #include "../ops.h"
0021 #include "../sof-pci-dev.h"
0022 #include "../../amd/mach-config.h"
0023 #include "acp.h"
0024 
0025 #define ACP3x_REG_START     0x1240000
0026 #define ACP3x_REG_END       0x125C000
0027 
0028 static struct platform_device *dmic_dev;
0029 static struct platform_device *pdev;
0030 
0031 static const struct resource renoir_res[] = {
0032     {
0033         .start = 0,
0034         .end = ACP3x_REG_END - ACP3x_REG_START,
0035         .name = "acp_mem",
0036         .flags = IORESOURCE_MEM,
0037     },
0038     {
0039         .start = 0,
0040         .end = 0,
0041         .name = "acp_dai_irq",
0042         .flags = IORESOURCE_IRQ,
0043     },
0044 };
0045 
0046 static const struct sof_amd_acp_desc renoir_chip_info = {
0047     .host_bridge_id = HOST_BRIDGE_CZN,
0048 };
0049 
0050 static const struct sof_dev_desc renoir_desc = {
0051     .machines       = snd_soc_acpi_amd_sof_machines,
0052     .use_acpi_target_states = true,
0053     .resindex_lpe_base  = 0,
0054     .resindex_pcicfg_base   = -1,
0055     .resindex_imr_base  = -1,
0056     .irqindex_host_ipc  = -1,
0057     .chip_info      = &renoir_chip_info,
0058     .ipc_supported_mask = BIT(SOF_IPC),
0059     .ipc_default        = SOF_IPC,
0060     .default_fw_path = {
0061         [SOF_IPC] = "amd/sof",
0062     },
0063     .default_tplg_path = {
0064         [SOF_IPC] = "amd/sof-tplg",
0065     },
0066     .default_fw_filename    = {
0067         [SOF_IPC] = "sof-rn.ri",
0068     },
0069     .nocodec_tplg_filename  = "sof-acp.tplg",
0070     .ops            = &sof_renoir_ops,
0071 };
0072 
0073 static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
0074 {
0075     struct platform_device_info pdevinfo;
0076     struct device *dev = &pci->dev;
0077     const struct resource *res_i2s;
0078     struct resource *res;
0079     unsigned int flag, i, addr;
0080     int ret;
0081 
0082     flag = snd_amd_acp_find_config(pci);
0083     if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC)
0084         return -ENODEV;
0085 
0086     ret = sof_pci_probe(pci, pci_id);
0087     if (ret != 0)
0088         return ret;
0089 
0090     dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
0091     if (IS_ERR(dmic_dev)) {
0092         dev_err(dev, "failed to create DMIC device\n");
0093         sof_pci_remove(pci);
0094         return PTR_ERR(dmic_dev);
0095     }
0096 
0097     /* Register platform device only if flag set to FLAG_AMD_SOF_ONLY_DMIC */
0098     if (flag != FLAG_AMD_SOF_ONLY_DMIC)
0099         return 0;
0100 
0101     addr = pci_resource_start(pci, 0);
0102     res = devm_kzalloc(&pci->dev, sizeof(struct resource) * ARRAY_SIZE(renoir_res), GFP_KERNEL);
0103     if (!res) {
0104         sof_pci_remove(pci);
0105         platform_device_unregister(dmic_dev);
0106         return -ENOMEM;
0107     }
0108 
0109     res_i2s = renoir_res;
0110     for (i = 0; i < ARRAY_SIZE(renoir_res); i++, res_i2s++) {
0111         res[i].name = res_i2s->name;
0112         res[i].flags = res_i2s->flags;
0113         res[i].start = addr + res_i2s->start;
0114         res[i].end = addr + res_i2s->end;
0115         if (res_i2s->flags == IORESOURCE_IRQ) {
0116             res[i].start = pci->irq;
0117             res[i].end = res[i].start;
0118         }
0119     }
0120 
0121     memset(&pdevinfo, 0, sizeof(pdevinfo));
0122 
0123     /*
0124      * We have common PCI driver probe for ACP device but we have to support I2S without SOF
0125      * for some distributions. Register platform device that will be used to support non dsp
0126      * ACP's audio ends points on some machines.
0127      */
0128 
0129     pdevinfo.name = "acp_asoc_renoir";
0130     pdevinfo.id = 0;
0131     pdevinfo.parent = &pci->dev;
0132     pdevinfo.num_res = ARRAY_SIZE(renoir_res);
0133     pdevinfo.res = &res[0];
0134 
0135     pdev = platform_device_register_full(&pdevinfo);
0136     if (IS_ERR(pdev)) {
0137         dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
0138         sof_pci_remove(pci);
0139         platform_device_unregister(dmic_dev);
0140         ret = PTR_ERR(pdev);
0141     }
0142 
0143     return ret;
0144 };
0145 
0146 static void acp_pci_rn_remove(struct pci_dev *pci)
0147 {
0148     if (dmic_dev)
0149         platform_device_unregister(dmic_dev);
0150     if (pdev)
0151         platform_device_unregister(pdev);
0152 
0153     return sof_pci_remove(pci);
0154 }
0155 
0156 /* PCI IDs */
0157 static const struct pci_device_id rn_pci_ids[] = {
0158     { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_PCI_DEV_ID),
0159     .driver_data = (unsigned long)&renoir_desc},
0160     { 0, }
0161 };
0162 MODULE_DEVICE_TABLE(pci, rn_pci_ids);
0163 
0164 /* pci_driver definition */
0165 static struct pci_driver snd_sof_pci_amd_rn_driver = {
0166     .name = KBUILD_MODNAME,
0167     .id_table = rn_pci_ids,
0168     .probe = acp_pci_rn_probe,
0169     .remove = acp_pci_rn_remove,
0170     .driver = {
0171         .pm = &sof_pci_pm,
0172     },
0173 };
0174 module_pci_driver(snd_sof_pci_amd_rn_driver);
0175 
0176 MODULE_LICENSE("Dual BSD/GPL");
0177 MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
0178 MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);