0001
0002
0003
0004
0005
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
0025
0026
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
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
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
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
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
0169 .matches = {
0170 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0171 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81NB"),
0172 }
0173 },
0174 {
0175
0176 .matches = {
0177 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0178 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81X2"),
0179 }
0180 },
0181 {
0182
0183 .matches = {
0184 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0185 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81YQ"),
0186 }
0187 },
0188 {
0189
0190 .matches = {
0191 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0192 DMI_EXACT_MATCH(DMI_BOARD_NAME, "20T6CTO1WW"),
0193 }
0194 },
0195 {
0196
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
0220 flag = snd_amd_acp_find_config(pci);
0221 if (flag)
0222 return -ENODEV;
0223
0224
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
0247 ret = pci_enable_msi(pci);
0248 if (ret)
0249
0250 irqflags = IRQF_SHARED;
0251 else
0252
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");