1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * AMD Pink Sardine ACP PCI Driver 4 * 5 * Copyright 2022 Advanced Micro Devices, Inc. 6 */ 7 8 #include <linux/pci.h> 9 #include <linux/module.h> 10 #include <linux/io.h> 11 #include <linux/delay.h> 12 #include <linux/platform_device.h> 13 #include <linux/acpi.h> 14 #include <linux/interrupt.h> 15 #include <sound/pcm_params.h> 16 #include <linux/pm_runtime.h> 17 18 #include "acp62.h" 19 20 struct acp62_dev_data { 21 void __iomem *acp62_base; 22 struct resource *res; 23 bool acp62_audio_mode; 24 struct platform_device *pdev[ACP6x_DEVS]; 25 }; 26 27 static int acp62_power_on(void __iomem *acp_base) 28 { 29 u32 val; 30 int timeout; 31 32 val = acp62_readl(acp_base + ACP_PGFSM_STATUS); 33 34 if (!val) 35 return val; 36 37 if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) 38 acp62_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); 39 timeout = 0; 40 while (++timeout < 500) { 41 val = acp62_readl(acp_base + ACP_PGFSM_STATUS); 42 if (!val) 43 return 0; 44 udelay(1); 45 } 46 return -ETIMEDOUT; 47 } 48 49 static int acp62_reset(void __iomem *acp_base) 50 { 51 u32 val; 52 int timeout; 53 54 acp62_writel(1, acp_base + ACP_SOFT_RESET); 55 timeout = 0; 56 while (++timeout < 500) { 57 val = acp62_readl(acp_base + ACP_SOFT_RESET); 58 if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) 59 break; 60 cpu_relax(); 61 } 62 acp62_writel(0, acp_base + ACP_SOFT_RESET); 63 timeout = 0; 64 while (++timeout < 500) { 65 val = acp62_readl(acp_base + ACP_SOFT_RESET); 66 if (!val) 67 return 0; 68 cpu_relax(); 69 } 70 return -ETIMEDOUT; 71 } 72 73 static void acp62_enable_interrupts(void __iomem *acp_base) 74 { 75 acp62_writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); 76 } 77 78 static void acp62_disable_interrupts(void __iomem *acp_base) 79 { 80 acp62_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + 81 ACP_EXTERNAL_INTR_STAT); 82 acp62_writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); 83 acp62_writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); 84 } 85 86 static int acp62_init(void __iomem *acp_base, struct device *dev) 87 { 88 int ret; 89 90 ret = acp62_power_on(acp_base); 91 if (ret) { 92 dev_err(dev, "ACP power on failed\n"); 93 return ret; 94 } 95 acp62_writel(0x01, acp_base + ACP_CONTROL); 96 ret = acp62_reset(acp_base); 97 if (ret) { 98 dev_err(dev, "ACP reset failed\n"); 99 return ret; 100 } 101 acp62_writel(0x03, acp_base + ACP_CLKMUX_SEL); 102 acp62_enable_interrupts(acp_base); 103 return 0; 104 } 105 106 static int acp62_deinit(void __iomem *acp_base, struct device *dev) 107 { 108 int ret; 109 110 acp62_disable_interrupts(acp_base); 111 ret = acp62_reset(acp_base); 112 if (ret) { 113 dev_err(dev, "ACP reset failed\n"); 114 return ret; 115 } 116 acp62_writel(0, acp_base + ACP_CLKMUX_SEL); 117 acp62_writel(0, acp_base + ACP_CONTROL); 118 return 0; 119 } 120 121 static irqreturn_t acp62_irq_handler(int irq, void *dev_id) 122 { 123 struct acp62_dev_data *adata; 124 struct pdm_dev_data *ps_pdm_data; 125 u32 val; 126 127 adata = dev_id; 128 if (!adata) 129 return IRQ_NONE; 130 131 val = acp62_readl(adata->acp62_base + ACP_EXTERNAL_INTR_STAT); 132 if (val & BIT(PDM_DMA_STAT)) { 133 ps_pdm_data = dev_get_drvdata(&adata->pdev[0]->dev); 134 acp62_writel(BIT(PDM_DMA_STAT), adata->acp62_base + ACP_EXTERNAL_INTR_STAT); 135 if (ps_pdm_data->capture_stream) 136 snd_pcm_period_elapsed(ps_pdm_data->capture_stream); 137 return IRQ_HANDLED; 138 } 139 return IRQ_NONE; 140 } 141 142 static int snd_acp62_probe(struct pci_dev *pci, 143 const struct pci_device_id *pci_id) 144 { 145 struct acp62_dev_data *adata; 146 struct platform_device_info pdevinfo[ACP6x_DEVS]; 147 int index, ret; 148 int val = 0x00; 149 struct acpi_device *adev; 150 const union acpi_object *obj; 151 u32 addr; 152 unsigned int irqflags; 153 154 irqflags = IRQF_SHARED; 155 /* Pink Sardine device check */ 156 switch (pci->revision) { 157 case 0x63: 158 break; 159 default: 160 dev_dbg(&pci->dev, "acp62 pci device not found\n"); 161 return -ENODEV; 162 } 163 if (pci_enable_device(pci)) { 164 dev_err(&pci->dev, "pci_enable_device failed\n"); 165 return -ENODEV; 166 } 167 168 ret = pci_request_regions(pci, "AMD ACP6.2 audio"); 169 if (ret < 0) { 170 dev_err(&pci->dev, "pci_request_regions failed\n"); 171 goto disable_pci; 172 } 173 adata = devm_kzalloc(&pci->dev, sizeof(struct acp62_dev_data), 174 GFP_KERNEL); 175 if (!adata) { 176 ret = -ENOMEM; 177 goto release_regions; 178 } 179 180 addr = pci_resource_start(pci, 0); 181 adata->acp62_base = devm_ioremap(&pci->dev, addr, 182 pci_resource_len(pci, 0)); 183 if (!adata->acp62_base) { 184 ret = -ENOMEM; 185 goto release_regions; 186 } 187 pci_set_master(pci); 188 pci_set_drvdata(pci, adata); 189 ret = acp62_init(adata->acp62_base, &pci->dev); 190 if (ret) 191 goto release_regions; 192 val = acp62_readl(adata->acp62_base + ACP_PIN_CONFIG); 193 switch (val) { 194 case ACP_CONFIG_0: 195 case ACP_CONFIG_1: 196 case ACP_CONFIG_2: 197 case ACP_CONFIG_3: 198 case ACP_CONFIG_9: 199 case ACP_CONFIG_15: 200 dev_info(&pci->dev, "Audio Mode %d\n", val); 201 break; 202 default: 203 204 /* Checking DMIC hardware*/ 205 adev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), 0x02, 0); 206 207 if (!adev) 208 break; 209 210 if (!acpi_dev_get_property(adev, "acp-audio-device-type", 211 ACPI_TYPE_INTEGER, &obj) && 212 obj->integer.value == 2) { 213 adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL); 214 if (!adata->res) { 215 ret = -ENOMEM; 216 goto de_init; 217 } 218 219 adata->res->name = "acp_iomem"; 220 adata->res->flags = IORESOURCE_MEM; 221 adata->res->start = addr; 222 adata->res->end = addr + (ACP6x_REG_END - ACP6x_REG_START); 223 adata->acp62_audio_mode = ACP6x_PDM_MODE; 224 225 memset(&pdevinfo, 0, sizeof(pdevinfo)); 226 pdevinfo[0].name = "acp_ps_pdm_dma"; 227 pdevinfo[0].id = 0; 228 pdevinfo[0].parent = &pci->dev; 229 pdevinfo[0].num_res = 1; 230 pdevinfo[0].res = adata->res; 231 232 pdevinfo[1].name = "dmic-codec"; 233 pdevinfo[1].id = 0; 234 pdevinfo[1].parent = &pci->dev; 235 236 pdevinfo[2].name = "acp_ps_mach"; 237 pdevinfo[2].id = 0; 238 pdevinfo[2].parent = &pci->dev; 239 240 for (index = 0; index < ACP6x_DEVS; index++) { 241 adata->pdev[index] = 242 platform_device_register_full(&pdevinfo[index]); 243 244 if (IS_ERR(adata->pdev[index])) { 245 dev_err(&pci->dev, 246 "cannot register %s device\n", 247 pdevinfo[index].name); 248 ret = PTR_ERR(adata->pdev[index]); 249 goto unregister_devs; 250 } 251 ret = devm_request_irq(&pci->dev, pci->irq, acp62_irq_handler, 252 irqflags, "ACP_PCI_IRQ", adata); 253 if (ret) { 254 dev_err(&pci->dev, "ACP PCI IRQ request failed\n"); 255 goto unregister_devs; 256 } 257 } 258 } 259 break; 260 } 261 pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); 262 pm_runtime_use_autosuspend(&pci->dev); 263 pm_runtime_put_noidle(&pci->dev); 264 pm_runtime_allow(&pci->dev); 265 return 0; 266 unregister_devs: 267 for (--index; index >= 0; index--) 268 platform_device_unregister(adata->pdev[index]); 269 de_init: 270 if (acp62_deinit(adata->acp62_base, &pci->dev)) 271 dev_err(&pci->dev, "ACP de-init failed\n"); 272 release_regions: 273 pci_release_regions(pci); 274 disable_pci: 275 pci_disable_device(pci); 276 277 return ret; 278 } 279 280 static int __maybe_unused snd_acp62_suspend(struct device *dev) 281 { 282 struct acp62_dev_data *adata; 283 int ret; 284 285 adata = dev_get_drvdata(dev); 286 ret = acp62_deinit(adata->acp62_base, dev); 287 if (ret) 288 dev_err(dev, "ACP de-init failed\n"); 289 return ret; 290 } 291 292 static int __maybe_unused snd_acp62_resume(struct device *dev) 293 { 294 struct acp62_dev_data *adata; 295 int ret; 296 297 adata = dev_get_drvdata(dev); 298 ret = acp62_init(adata->acp62_base, dev); 299 if (ret) 300 dev_err(dev, "ACP init failed\n"); 301 return ret; 302 } 303 304 static const struct dev_pm_ops acp62_pm_ops = { 305 SET_RUNTIME_PM_OPS(snd_acp62_suspend, snd_acp62_resume, NULL) 306 SET_SYSTEM_SLEEP_PM_OPS(snd_acp62_suspend, snd_acp62_resume) 307 }; 308 309 static void snd_acp62_remove(struct pci_dev *pci) 310 { 311 struct acp62_dev_data *adata; 312 int ret, index; 313 314 adata = pci_get_drvdata(pci); 315 if (adata->acp62_audio_mode == ACP6x_PDM_MODE) { 316 for (index = 0; index < ACP6x_DEVS; index++) 317 platform_device_unregister(adata->pdev[index]); 318 } 319 ret = acp62_deinit(adata->acp62_base, &pci->dev); 320 if (ret) 321 dev_err(&pci->dev, "ACP de-init failed\n"); 322 pm_runtime_forbid(&pci->dev); 323 pm_runtime_get_noresume(&pci->dev); 324 pci_release_regions(pci); 325 pci_disable_device(pci); 326 } 327 328 static const struct pci_device_id snd_acp62_ids[] = { 329 { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), 330 .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, 331 .class_mask = 0xffffff }, 332 { 0, }, 333 }; 334 MODULE_DEVICE_TABLE(pci, snd_acp62_ids); 335 336 static struct pci_driver ps_acp62_driver = { 337 .name = KBUILD_MODNAME, 338 .id_table = snd_acp62_ids, 339 .probe = snd_acp62_probe, 340 .remove = snd_acp62_remove, 341 .driver = { 342 .pm = &acp62_pm_ops, 343 } 344 }; 345 346 module_pci_driver(ps_acp62_driver); 347 348 MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); 349 MODULE_AUTHOR("Syed.SabaKareem@amd.com"); 350 MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver"); 351 MODULE_LICENSE("GPL v2"); 352