Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // AMD Renoir ACP PCI Driver
0004 //
0005 //Copyright 2020 Advanced Micro Devices, Inc.
0006 
0007 #include <linux/pci.h>
0008 #include <linux/acpi.h>
0009 #include <linux/dmi.h>
0010 #include <linux/module.h>
0011 #include <linux/io.h>
0012 #include <linux/delay.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/pm_runtime.h>
0016 
0017 #include "rn_acp3x.h"
0018 
0019 static int acp_power_gating;
0020 module_param(acp_power_gating, int, 0644);
0021 MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating");
0022 
0023 /*
0024  * dmic_acpi_check = -1 - Use ACPI/DMI method to detect the DMIC hardware presence at runtime
0025  *                 =  0 - Skip the DMIC device creation and return probe failure
0026  *                 =  1 - Force DMIC support
0027  */
0028 static int dmic_acpi_check = ACP_DMIC_AUTO;
0029 module_param(dmic_acpi_check, bint, 0644);
0030 MODULE_PARM_DESC(dmic_acpi_check, "Digital microphone presence (-1=auto, 0=none, 1=force)");
0031 
0032 struct acp_dev_data {
0033     void __iomem *acp_base;
0034     struct resource *res;
0035     struct platform_device *pdev[ACP_DEVS];
0036 };
0037 
0038 static int rn_acp_power_on(void __iomem *acp_base)
0039 {
0040     u32 val;
0041     int timeout;
0042 
0043     val = rn_readl(acp_base + ACP_PGFSM_STATUS);
0044 
0045     if (val == 0)
0046         return val;
0047 
0048     if ((val & ACP_PGFSM_STATUS_MASK) !=
0049                 ACP_POWER_ON_IN_PROGRESS)
0050         rn_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
0051               acp_base + ACP_PGFSM_CONTROL);
0052     timeout = 0;
0053     while (++timeout < 500) {
0054         val = rn_readl(acp_base + ACP_PGFSM_STATUS);
0055         if (!val)
0056             return 0;
0057         udelay(1);
0058     }
0059     return -ETIMEDOUT;
0060 }
0061 
0062 static int rn_acp_power_off(void __iomem *acp_base)
0063 {
0064     u32 val;
0065     int timeout;
0066 
0067     rn_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
0068           acp_base + ACP_PGFSM_CONTROL);
0069     timeout = 0;
0070     while (++timeout < 500) {
0071         val = rn_readl(acp_base + ACP_PGFSM_STATUS);
0072         if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
0073             return 0;
0074         udelay(1);
0075     }
0076     return -ETIMEDOUT;
0077 }
0078 
0079 static int rn_acp_reset(void __iomem *acp_base)
0080 {
0081     u32 val;
0082     int timeout;
0083 
0084     rn_writel(1, acp_base + ACP_SOFT_RESET);
0085     timeout = 0;
0086     while (++timeout < 500) {
0087         val = rn_readl(acp_base + ACP_SOFT_RESET);
0088         if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
0089             break;
0090         cpu_relax();
0091     }
0092     rn_writel(0, acp_base + ACP_SOFT_RESET);
0093     timeout = 0;
0094     while (++timeout < 500) {
0095         val = rn_readl(acp_base + ACP_SOFT_RESET);
0096         if (!val)
0097             return 0;
0098         cpu_relax();
0099     }
0100     return -ETIMEDOUT;
0101 }
0102 
0103 static void rn_acp_enable_interrupts(void __iomem *acp_base)
0104 {
0105     u32 ext_intr_ctrl;
0106 
0107     rn_writel(0x01, acp_base + ACP_EXTERNAL_INTR_ENB);
0108     ext_intr_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
0109     ext_intr_ctrl |= ACP_ERROR_MASK;
0110     rn_writel(ext_intr_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
0111 }
0112 
0113 static void rn_acp_disable_interrupts(void __iomem *acp_base)
0114 {
0115     rn_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base +
0116           ACP_EXTERNAL_INTR_STAT);
0117     rn_writel(0x00, acp_base + ACP_EXTERNAL_INTR_ENB);
0118 }
0119 
0120 static int rn_acp_init(void __iomem *acp_base)
0121 {
0122     int ret;
0123 
0124     /* power on */
0125     ret = rn_acp_power_on(acp_base);
0126     if (ret) {
0127         pr_err("ACP power on failed\n");
0128         return ret;
0129     }
0130     rn_writel(0x01, acp_base + ACP_CONTROL);
0131     /* Reset */
0132     ret = rn_acp_reset(acp_base);
0133     if (ret) {
0134         pr_err("ACP reset failed\n");
0135         return ret;
0136     }
0137     rn_writel(0x03, acp_base + ACP_CLKMUX_SEL);
0138     rn_acp_enable_interrupts(acp_base);
0139     return 0;
0140 }
0141 
0142 static int rn_acp_deinit(void __iomem *acp_base)
0143 {
0144     int ret;
0145 
0146     rn_acp_disable_interrupts(acp_base);
0147     /* Reset */
0148     ret = rn_acp_reset(acp_base);
0149     if (ret) {
0150         pr_err("ACP reset failed\n");
0151         return ret;
0152     }
0153     rn_writel(0x00, acp_base + ACP_CLKMUX_SEL);
0154     rn_writel(0x00, acp_base + ACP_CONTROL);
0155     /* power off */
0156     if (acp_power_gating) {
0157         ret = rn_acp_power_off(acp_base);
0158         if (ret) {
0159             pr_err("ACP power off failed\n");
0160             return ret;
0161         }
0162     }
0163     return 0;
0164 }
0165 
0166 static const struct dmi_system_id rn_acp_quirk_table[] = {
0167     {
0168         /* Lenovo IdeaPad S340-14API */
0169         .matches = {
0170             DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0171             DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81NB"),
0172         }
0173     },
0174     {
0175         /* Lenovo IdeaPad Flex 5 14ARE05 */
0176         .matches = {
0177             DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0178             DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81X2"),
0179         }
0180     },
0181     {
0182         /* Lenovo IdeaPad 5 15ARE05 */
0183         .matches = {
0184             DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0185             DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81YQ"),
0186         }
0187     },
0188     {
0189         /* Lenovo ThinkPad E14 Gen 2 */
0190         .matches = {
0191             DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0192             DMI_EXACT_MATCH(DMI_BOARD_NAME, "20T6CTO1WW"),
0193         }
0194     },
0195     {
0196         /* Lenovo ThinkPad X395 */
0197         .matches = {
0198             DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0199             DMI_EXACT_MATCH(DMI_BOARD_NAME, "20NLCTO1WW"),
0200         }
0201     },
0202     {}
0203 };
0204 
0205 static int snd_rn_acp_probe(struct pci_dev *pci,
0206                 const struct pci_device_id *pci_id)
0207 {
0208     struct acp_dev_data *adata;
0209     struct platform_device_info pdevinfo[ACP_DEVS];
0210 #if defined(CONFIG_ACPI)
0211     acpi_handle handle;
0212     acpi_integer dmic_status;
0213 #endif
0214     const struct dmi_system_id *dmi_id;
0215     unsigned int irqflags, flag;
0216     int ret, index;
0217     u32 addr;
0218 
0219     /* Return if acp config flag is defined */
0220     flag = snd_amd_acp_find_config(pci);
0221     if (flag)
0222         return -ENODEV;
0223 
0224     /* Renoir device check */
0225     if (pci->revision != 0x01)
0226         return -ENODEV;
0227 
0228     if (pci_enable_device(pci)) {
0229         dev_err(&pci->dev, "pci_enable_device failed\n");
0230         return -ENODEV;
0231     }
0232 
0233     ret = pci_request_regions(pci, "AMD ACP3x audio");
0234     if (ret < 0) {
0235         dev_err(&pci->dev, "pci_request_regions failed\n");
0236         goto disable_pci;
0237     }
0238 
0239     adata = devm_kzalloc(&pci->dev, sizeof(struct acp_dev_data),
0240                  GFP_KERNEL);
0241     if (!adata) {
0242         ret = -ENOMEM;
0243         goto release_regions;
0244     }
0245 
0246     /* check for msi interrupt support */
0247     ret = pci_enable_msi(pci);
0248     if (ret)
0249         /* msi is not enabled */
0250         irqflags = IRQF_SHARED;
0251     else
0252         /* msi is enabled */
0253         irqflags = 0;
0254 
0255     addr = pci_resource_start(pci, 0);
0256     adata->acp_base = devm_ioremap(&pci->dev, addr,
0257                        pci_resource_len(pci, 0));
0258     if (!adata->acp_base) {
0259         ret = -ENOMEM;
0260         goto disable_msi;
0261     }
0262     pci_set_master(pci);
0263     pci_set_drvdata(pci, adata);
0264     ret = rn_acp_init(adata->acp_base);
0265     if (ret)
0266         goto disable_msi;
0267 
0268     if (!dmic_acpi_check) {
0269         ret = -ENODEV;
0270         goto de_init;
0271     } else if (dmic_acpi_check == ACP_DMIC_AUTO) {
0272 #if defined(CONFIG_ACPI)
0273         handle = ACPI_HANDLE(&pci->dev);
0274         ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
0275         if (ACPI_FAILURE(ret)) {
0276             ret = -ENODEV;
0277             goto de_init;
0278         }
0279         if (!dmic_status) {
0280             ret = -ENODEV;
0281             goto de_init;
0282         }
0283 #endif
0284         dmi_id = dmi_first_match(rn_acp_quirk_table);
0285         if (dmi_id && !dmi_id->driver_data) {
0286             dev_info(&pci->dev, "ACPI settings override using DMI (ACP mic is not present)");
0287             ret = -ENODEV;
0288             goto de_init;
0289         }
0290     }
0291 
0292     adata->res = devm_kzalloc(&pci->dev,
0293                   sizeof(struct resource) * 2,
0294                   GFP_KERNEL);
0295     if (!adata->res) {
0296         ret = -ENOMEM;
0297         goto de_init;
0298     }
0299 
0300     adata->res[0].name = "acp_pdm_iomem";
0301     adata->res[0].flags = IORESOURCE_MEM;
0302     adata->res[0].start = addr;
0303     adata->res[0].end = addr + (ACP_REG_END - ACP_REG_START);
0304     adata->res[1].name = "acp_pdm_irq";
0305     adata->res[1].flags = IORESOURCE_IRQ;
0306     adata->res[1].start = pci->irq;
0307     adata->res[1].end = pci->irq;
0308 
0309     memset(&pdevinfo, 0, sizeof(pdevinfo));
0310     pdevinfo[0].name = "acp_rn_pdm_dma";
0311     pdevinfo[0].id = 0;
0312     pdevinfo[0].parent = &pci->dev;
0313     pdevinfo[0].num_res = 2;
0314     pdevinfo[0].res = adata->res;
0315     pdevinfo[0].data = &irqflags;
0316     pdevinfo[0].size_data = sizeof(irqflags);
0317 
0318     pdevinfo[1].name = "dmic-codec";
0319     pdevinfo[1].id = 0;
0320     pdevinfo[1].parent = &pci->dev;
0321     pdevinfo[2].name = "acp_pdm_mach";
0322     pdevinfo[2].id = 0;
0323     pdevinfo[2].parent = &pci->dev;
0324     for (index = 0; index < ACP_DEVS; index++) {
0325         adata->pdev[index] =
0326                 platform_device_register_full(&pdevinfo[index]);
0327         if (IS_ERR(adata->pdev[index])) {
0328             dev_err(&pci->dev, "cannot register %s device\n",
0329                 pdevinfo[index].name);
0330             ret = PTR_ERR(adata->pdev[index]);
0331             goto unregister_devs;
0332         }
0333     }
0334     pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS);
0335     pm_runtime_use_autosuspend(&pci->dev);
0336     pm_runtime_put_noidle(&pci->dev);
0337     pm_runtime_allow(&pci->dev);
0338     return 0;
0339 
0340 unregister_devs:
0341     for (index = 0; index < ACP_DEVS; index++)
0342         platform_device_unregister(adata->pdev[index]);
0343 de_init:
0344     if (rn_acp_deinit(adata->acp_base))
0345         dev_err(&pci->dev, "ACP de-init failed\n");
0346 disable_msi:
0347     pci_disable_msi(pci);
0348 release_regions:
0349     pci_release_regions(pci);
0350 disable_pci:
0351     pci_disable_device(pci);
0352 
0353     return ret;
0354 }
0355 
0356 static int snd_rn_acp_suspend(struct device *dev)
0357 {
0358     int ret;
0359     struct acp_dev_data *adata;
0360 
0361     adata = dev_get_drvdata(dev);
0362     ret = rn_acp_deinit(adata->acp_base);
0363     if (ret)
0364         dev_err(dev, "ACP de-init failed\n");
0365     else
0366         dev_dbg(dev, "ACP de-initialized\n");
0367 
0368     return ret;
0369 }
0370 
0371 static int snd_rn_acp_resume(struct device *dev)
0372 {
0373     int ret;
0374     struct acp_dev_data *adata;
0375 
0376     adata = dev_get_drvdata(dev);
0377     ret = rn_acp_init(adata->acp_base);
0378     if (ret) {
0379         dev_err(dev, "ACP init failed\n");
0380         return ret;
0381     }
0382     return 0;
0383 }
0384 
0385 static const struct dev_pm_ops rn_acp_pm = {
0386     .runtime_suspend = snd_rn_acp_suspend,
0387     .runtime_resume =  snd_rn_acp_resume,
0388     .suspend = snd_rn_acp_suspend,
0389     .resume =   snd_rn_acp_resume,
0390     .restore =  snd_rn_acp_resume,
0391     .poweroff = snd_rn_acp_suspend,
0392 };
0393 
0394 static void snd_rn_acp_remove(struct pci_dev *pci)
0395 {
0396     struct acp_dev_data *adata;
0397     int ret, index;
0398 
0399     adata = pci_get_drvdata(pci);
0400     for (index = 0; index < ACP_DEVS; index++)
0401         platform_device_unregister(adata->pdev[index]);
0402     ret = rn_acp_deinit(adata->acp_base);
0403     if (ret)
0404         dev_err(&pci->dev, "ACP de-init failed\n");
0405     pm_runtime_forbid(&pci->dev);
0406     pm_runtime_get_noresume(&pci->dev);
0407     pci_disable_msi(pci);
0408     pci_release_regions(pci);
0409     pci_disable_device(pci);
0410 }
0411 
0412 static const struct pci_device_id snd_rn_acp_ids[] = {
0413     { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
0414     .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
0415     .class_mask = 0xffffff },
0416     { 0, },
0417 };
0418 MODULE_DEVICE_TABLE(pci, snd_rn_acp_ids);
0419 
0420 static struct pci_driver rn_acp_driver  = {
0421     .name = KBUILD_MODNAME,
0422     .id_table = snd_rn_acp_ids,
0423     .probe = snd_rn_acp_probe,
0424     .remove = snd_rn_acp_remove,
0425     .driver = {
0426         .pm = &rn_acp_pm,
0427     }
0428 };
0429 
0430 module_pci_driver(rn_acp_driver);
0431 
0432 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
0433 MODULE_DESCRIPTION("AMD ACP Renoir PCI driver");
0434 MODULE_LICENSE("GPL v2");