^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // AMD ACP PCI Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //Copyright 2016 Advanced Micro Devices, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "acp3x.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct acp3x_dev_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) void __iomem *acp3x_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) bool acp3x_audio_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct platform_device *pdev[ACP3x_DEVS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) u32 pme_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int acp3x_power_on(struct acp3x_dev_data *adata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) void __iomem *acp3x_base = adata->acp3x_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (val == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (!((val & ACP_PGFSM_STATUS_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ACP_POWER_ON_IN_PROGRESS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) acp3x_base + mmACP_PGFSM_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) while (++timeout < 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* ACP power On clears PME_EN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Restore the value to its prior state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int acp3x_reset(void __iomem *acp3x_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) while (++timeout < 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) while (++timeout < 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void acp3x_enable_interrupts(void __iomem *acp_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) rv_writel(0x01, acp_base + mmACP_EXTERNAL_INTR_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static void acp3x_disable_interrupts(void __iomem *acp_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) rv_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) mmACP_EXTERNAL_INTR_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_ENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int acp3x_init(struct acp3x_dev_data *adata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) void __iomem *acp3x_base = adata->acp3x_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* power on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ret = acp3x_power_on(adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) pr_err("ACP3x power on failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = acp3x_reset(acp3x_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pr_err("ACP3x reset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) acp3x_enable_interrupts(acp3x_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int acp3x_deinit(void __iomem *acp3x_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) acp3x_disable_interrupts(acp3x_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ret = acp3x_reset(acp3x_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) pr_err("ACP3x reset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int snd_acp3x_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct acp3x_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct platform_device_info pdevinfo[ACP3x_DEVS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) unsigned int irqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 addr, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* Raven device detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (pci->revision != 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (pci_enable_device(pci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_err(&pci->dev, "pci_enable_device failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ret = pci_request_regions(pci, "AMD ACP3x audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dev_err(&pci->dev, "pci_request_regions failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto disable_pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (!adata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto release_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* check for msi interrupt support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ret = pci_enable_msi(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* msi is not enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) irqflags = IRQF_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* msi is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) irqflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) addr = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) adata->acp3x_base = devm_ioremap(&pci->dev, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pci_resource_len(pci, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (!adata->acp3x_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) goto disable_msi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) pci_set_drvdata(pci, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* Save ACP_PME_EN state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = acp3x_init(adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto disable_msi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) case I2S_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) adata->res = devm_kzalloc(&pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) sizeof(struct resource) * 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (!adata->res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) goto de_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) adata->res[0].name = "acp3x_i2s_iomem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) adata->res[0].flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) adata->res[0].start = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) adata->res[1].name = "acp3x_i2s_sp";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) adata->res[1].flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) adata->res[1].start = addr + ACP3x_I2STDM_REG_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) adata->res[1].end = addr + ACP3x_I2STDM_REG_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) adata->res[2].name = "acp3x_i2s_bt";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) adata->res[2].flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) adata->res[2].start = addr + ACP3x_BT_TDM_REG_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) adata->res[2].end = addr + ACP3x_BT_TDM_REG_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) adata->res[3].name = "acp3x_i2s_irq";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) adata->res[3].flags = IORESOURCE_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) adata->res[3].start = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) adata->res[3].end = adata->res[3].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) adata->acp3x_audio_mode = ACP3x_I2S_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) memset(&pdevinfo, 0, sizeof(pdevinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) pdevinfo[0].name = "acp3x_rv_i2s_dma";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) pdevinfo[0].id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) pdevinfo[0].parent = &pci->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) pdevinfo[0].num_res = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) pdevinfo[0].res = &adata->res[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) pdevinfo[0].data = &irqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) pdevinfo[0].size_data = sizeof(irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) pdevinfo[1].name = "acp3x_i2s_playcap";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) pdevinfo[1].id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pdevinfo[1].parent = &pci->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) pdevinfo[1].num_res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pdevinfo[1].res = &adata->res[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) pdevinfo[2].name = "acp3x_i2s_playcap";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pdevinfo[2].id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) pdevinfo[2].parent = &pci->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pdevinfo[2].num_res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pdevinfo[2].res = &adata->res[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) pdevinfo[3].name = "acp3x_i2s_playcap";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pdevinfo[3].id = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) pdevinfo[3].parent = &pci->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) pdevinfo[3].num_res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pdevinfo[3].res = &adata->res[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) for (i = 0; i < ACP3x_DEVS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) adata->pdev[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) platform_device_register_full(&pdevinfo[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (IS_ERR(adata->pdev[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dev_err(&pci->dev, "cannot register %s device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pdevinfo[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ret = PTR_ERR(adata->pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) goto unregister_devs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) goto disable_msi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pm_runtime_use_autosuspend(&pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) pm_runtime_put_noidle(&pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pm_runtime_allow(&pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unregister_devs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (val == I2S_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) for (i = 0; i < ACP3x_DEVS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) platform_device_unregister(adata->pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) de_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (acp3x_deinit(adata->acp3x_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) dev_err(&pci->dev, "ACP de-init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) disable_msi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) pci_disable_msi(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) release_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pci_release_regions(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) disable_pci:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int snd_acp3x_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct acp3x_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) adata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = acp3x_deinit(adata->acp3x_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dev_err(dev, "ACP de-init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dev_dbg(dev, "ACP de-initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int snd_acp3x_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct acp3x_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) adata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ret = acp3x_init(adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dev_err(dev, "ACP init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static const struct dev_pm_ops acp3x_pm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .runtime_suspend = snd_acp3x_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .runtime_resume = snd_acp3x_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .resume = snd_acp3x_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static void snd_acp3x_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct acp3x_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) adata = pci_get_drvdata(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) for (i = 0; i < ACP3x_DEVS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) platform_device_unregister(adata->pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = acp3x_deinit(adata->acp3x_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) dev_err(&pci->dev, "ACP de-init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) pm_runtime_forbid(&pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) pm_runtime_get_noresume(&pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) pci_disable_msi(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) pci_release_regions(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static const struct pci_device_id snd_acp3x_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .class_mask = 0xffffff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) { 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) MODULE_DEVICE_TABLE(pci, snd_acp3x_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static struct pci_driver acp3x_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .id_table = snd_acp3x_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .probe = snd_acp3x_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .remove = snd_acp3x_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .pm = &acp3x_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) module_pci_driver(acp3x_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) MODULE_DESCRIPTION("AMD ACP3x PCI driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) MODULE_LICENSE("GPL v2");