xref: /openbmc/linux/sound/soc/amd/raven/pci-acp3x.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1d5a932e5SVijendar Mukunda // SPDX-License-Identifier: GPL-2.0+
2d5a932e5SVijendar Mukunda //
3d5a932e5SVijendar Mukunda // AMD ACP PCI Driver
4d5a932e5SVijendar Mukunda //
5d5a932e5SVijendar Mukunda //Copyright 2016 Advanced Micro Devices, Inc.
6e30d9128SMaruthi Srinivas Bayyavarapu 
7e30d9128SMaruthi Srinivas Bayyavarapu #include <linux/pci.h>
8e30d9128SMaruthi Srinivas Bayyavarapu #include <linux/module.h>
9e30d9128SMaruthi Srinivas Bayyavarapu #include <linux/io.h>
107894a7e7SVijendar Mukunda #include <linux/platform_device.h>
117894a7e7SVijendar Mukunda #include <linux/interrupt.h>
12535fd141SRavulapati Vishnu vardhan rao #include <linux/pm_runtime.h>
13535fd141SRavulapati Vishnu vardhan rao #include <linux/delay.h>
14e30d9128SMaruthi Srinivas Bayyavarapu 
15e30d9128SMaruthi Srinivas Bayyavarapu #include "acp3x.h"
16e30d9128SMaruthi Srinivas Bayyavarapu 
17e30d9128SMaruthi Srinivas Bayyavarapu struct acp3x_dev_data {
18e30d9128SMaruthi Srinivas Bayyavarapu 	void __iomem *acp3x_base;
197894a7e7SVijendar Mukunda 	bool acp3x_audio_mode;
207894a7e7SVijendar Mukunda 	struct resource *res;
215def0136SRavulapati Vishnu vardhan rao 	struct platform_device *pdev[ACP3x_DEVS];
221255296cSAkshu Agrawal 	u32 pme_en;
23e30d9128SMaruthi Srinivas Bayyavarapu };
24e30d9128SMaruthi Srinivas Bayyavarapu 
acp3x_power_on(struct acp3x_dev_data * adata)251255296cSAkshu Agrawal static int acp3x_power_on(struct acp3x_dev_data *adata)
26535fd141SRavulapati Vishnu vardhan rao {
271255296cSAkshu Agrawal 	void __iomem *acp3x_base = adata->acp3x_base;
28535fd141SRavulapati Vishnu vardhan rao 	u32 val;
29535fd141SRavulapati Vishnu vardhan rao 	int timeout;
30535fd141SRavulapati Vishnu vardhan rao 
31535fd141SRavulapati Vishnu vardhan rao 	val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
32535fd141SRavulapati Vishnu vardhan rao 
33535fd141SRavulapati Vishnu vardhan rao 	if (val == 0)
34535fd141SRavulapati Vishnu vardhan rao 		return val;
35535fd141SRavulapati Vishnu vardhan rao 
36535fd141SRavulapati Vishnu vardhan rao 	if (!((val & ACP_PGFSM_STATUS_MASK) ==
37535fd141SRavulapati Vishnu vardhan rao 				ACP_POWER_ON_IN_PROGRESS))
38535fd141SRavulapati Vishnu vardhan rao 		rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
39535fd141SRavulapati Vishnu vardhan rao 			acp3x_base + mmACP_PGFSM_CONTROL);
40535fd141SRavulapati Vishnu vardhan rao 	timeout = 0;
41535fd141SRavulapati Vishnu vardhan rao 	while (++timeout < 500) {
42535fd141SRavulapati Vishnu vardhan rao 		val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
43911abf8bSAkshu Agrawal 		if (!val) {
441255296cSAkshu Agrawal 			/* ACP power On clears PME_EN.
451255296cSAkshu Agrawal 			 * Restore the value to its prior state
46911abf8bSAkshu Agrawal 			 */
471255296cSAkshu Agrawal 			rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN);
48535fd141SRavulapati Vishnu vardhan rao 			return 0;
49911abf8bSAkshu Agrawal 		}
50535fd141SRavulapati Vishnu vardhan rao 		udelay(1);
51535fd141SRavulapati Vishnu vardhan rao 	}
52535fd141SRavulapati Vishnu vardhan rao 	return -ETIMEDOUT;
53535fd141SRavulapati Vishnu vardhan rao }
54535fd141SRavulapati Vishnu vardhan rao 
acp3x_reset(void __iomem * acp3x_base)55535fd141SRavulapati Vishnu vardhan rao static int acp3x_reset(void __iomem *acp3x_base)
56535fd141SRavulapati Vishnu vardhan rao {
57535fd141SRavulapati Vishnu vardhan rao 	u32 val;
58535fd141SRavulapati Vishnu vardhan rao 	int timeout;
59535fd141SRavulapati Vishnu vardhan rao 
60535fd141SRavulapati Vishnu vardhan rao 	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
61535fd141SRavulapati Vishnu vardhan rao 	timeout = 0;
62535fd141SRavulapati Vishnu vardhan rao 	while (++timeout < 500) {
63535fd141SRavulapati Vishnu vardhan rao 		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
64535fd141SRavulapati Vishnu vardhan rao 		if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
65535fd141SRavulapati Vishnu vardhan rao 			break;
66535fd141SRavulapati Vishnu vardhan rao 		cpu_relax();
67535fd141SRavulapati Vishnu vardhan rao 	}
68535fd141SRavulapati Vishnu vardhan rao 	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
69535fd141SRavulapati Vishnu vardhan rao 	timeout = 0;
70535fd141SRavulapati Vishnu vardhan rao 	while (++timeout < 500) {
71535fd141SRavulapati Vishnu vardhan rao 		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
72535fd141SRavulapati Vishnu vardhan rao 		if (!val)
73535fd141SRavulapati Vishnu vardhan rao 			return 0;
74535fd141SRavulapati Vishnu vardhan rao 		cpu_relax();
75535fd141SRavulapati Vishnu vardhan rao 	}
76535fd141SRavulapati Vishnu vardhan rao 	return -ETIMEDOUT;
77535fd141SRavulapati Vishnu vardhan rao }
78535fd141SRavulapati Vishnu vardhan rao 
acp3x_enable_interrupts(void __iomem * acp_base)79*6879e8e7SVijendar Mukunda static void acp3x_enable_interrupts(void __iomem *acp_base)
80*6879e8e7SVijendar Mukunda {
81*6879e8e7SVijendar Mukunda 	rv_writel(0x01, acp_base + mmACP_EXTERNAL_INTR_ENB);
82*6879e8e7SVijendar Mukunda }
83*6879e8e7SVijendar Mukunda 
acp3x_disable_interrupts(void __iomem * acp_base)84*6879e8e7SVijendar Mukunda static void acp3x_disable_interrupts(void __iomem *acp_base)
85*6879e8e7SVijendar Mukunda {
86*6879e8e7SVijendar Mukunda 	rv_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base +
87*6879e8e7SVijendar Mukunda 		  mmACP_EXTERNAL_INTR_STAT);
88*6879e8e7SVijendar Mukunda 	rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_CNTL);
89*6879e8e7SVijendar Mukunda 	rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_ENB);
90*6879e8e7SVijendar Mukunda }
91*6879e8e7SVijendar Mukunda 
acp3x_init(struct acp3x_dev_data * adata)921255296cSAkshu Agrawal static int acp3x_init(struct acp3x_dev_data *adata)
93535fd141SRavulapati Vishnu vardhan rao {
941255296cSAkshu Agrawal 	void __iomem *acp3x_base = adata->acp3x_base;
95535fd141SRavulapati Vishnu vardhan rao 	int ret;
96535fd141SRavulapati Vishnu vardhan rao 
97535fd141SRavulapati Vishnu vardhan rao 	/* power on */
981255296cSAkshu Agrawal 	ret = acp3x_power_on(adata);
99535fd141SRavulapati Vishnu vardhan rao 	if (ret) {
100535fd141SRavulapati Vishnu vardhan rao 		pr_err("ACP3x power on failed\n");
101535fd141SRavulapati Vishnu vardhan rao 		return ret;
102535fd141SRavulapati Vishnu vardhan rao 	}
103535fd141SRavulapati Vishnu vardhan rao 	/* Reset */
104535fd141SRavulapati Vishnu vardhan rao 	ret = acp3x_reset(acp3x_base);
105535fd141SRavulapati Vishnu vardhan rao 	if (ret) {
106535fd141SRavulapati Vishnu vardhan rao 		pr_err("ACP3x reset failed\n");
107535fd141SRavulapati Vishnu vardhan rao 		return ret;
108535fd141SRavulapati Vishnu vardhan rao 	}
109*6879e8e7SVijendar Mukunda 	acp3x_enable_interrupts(acp3x_base);
110535fd141SRavulapati Vishnu vardhan rao 	return 0;
111535fd141SRavulapati Vishnu vardhan rao }
112535fd141SRavulapati Vishnu vardhan rao 
acp3x_deinit(void __iomem * acp3x_base)113535fd141SRavulapati Vishnu vardhan rao static int acp3x_deinit(void __iomem *acp3x_base)
114535fd141SRavulapati Vishnu vardhan rao {
115535fd141SRavulapati Vishnu vardhan rao 	int ret;
116535fd141SRavulapati Vishnu vardhan rao 
117*6879e8e7SVijendar Mukunda 	acp3x_disable_interrupts(acp3x_base);
118535fd141SRavulapati Vishnu vardhan rao 	/* Reset */
119535fd141SRavulapati Vishnu vardhan rao 	ret = acp3x_reset(acp3x_base);
120535fd141SRavulapati Vishnu vardhan rao 	if (ret) {
121535fd141SRavulapati Vishnu vardhan rao 		pr_err("ACP3x reset failed\n");
122535fd141SRavulapati Vishnu vardhan rao 		return ret;
123535fd141SRavulapati Vishnu vardhan rao 	}
124535fd141SRavulapati Vishnu vardhan rao 	return 0;
125535fd141SRavulapati Vishnu vardhan rao }
126535fd141SRavulapati Vishnu vardhan rao 
snd_acp3x_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)127e30d9128SMaruthi Srinivas Bayyavarapu static int snd_acp3x_probe(struct pci_dev *pci,
128e30d9128SMaruthi Srinivas Bayyavarapu 			   const struct pci_device_id *pci_id)
129e30d9128SMaruthi Srinivas Bayyavarapu {
130e30d9128SMaruthi Srinivas Bayyavarapu 	struct acp3x_dev_data *adata;
1315def0136SRavulapati Vishnu vardhan rao 	struct platform_device_info pdevinfo[ACP3x_DEVS];
1327894a7e7SVijendar Mukunda 	unsigned int irqflags;
1335def0136SRavulapati Vishnu vardhan rao 	int ret, i;
1345def0136SRavulapati Vishnu vardhan rao 	u32 addr, val;
135e30d9128SMaruthi Srinivas Bayyavarapu 
13655d8e6a8SJaroslav Kysela 	/* Raven device detection */
13755d8e6a8SJaroslav Kysela 	if (pci->revision != 0x00)
13855d8e6a8SJaroslav Kysela 		return -ENODEV;
13955d8e6a8SJaroslav Kysela 
140e30d9128SMaruthi Srinivas Bayyavarapu 	if (pci_enable_device(pci)) {
141e30d9128SMaruthi Srinivas Bayyavarapu 		dev_err(&pci->dev, "pci_enable_device failed\n");
142e30d9128SMaruthi Srinivas Bayyavarapu 		return -ENODEV;
143e30d9128SMaruthi Srinivas Bayyavarapu 	}
144e30d9128SMaruthi Srinivas Bayyavarapu 
145e30d9128SMaruthi Srinivas Bayyavarapu 	ret = pci_request_regions(pci, "AMD ACP3x audio");
146e30d9128SMaruthi Srinivas Bayyavarapu 	if (ret < 0) {
147e30d9128SMaruthi Srinivas Bayyavarapu 		dev_err(&pci->dev, "pci_request_regions failed\n");
148e30d9128SMaruthi Srinivas Bayyavarapu 		goto disable_pci;
149e30d9128SMaruthi Srinivas Bayyavarapu 	}
150e30d9128SMaruthi Srinivas Bayyavarapu 
151e30d9128SMaruthi Srinivas Bayyavarapu 	adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data),
152e30d9128SMaruthi Srinivas Bayyavarapu 			     GFP_KERNEL);
153e30d9128SMaruthi Srinivas Bayyavarapu 	if (!adata) {
154e30d9128SMaruthi Srinivas Bayyavarapu 		ret = -ENOMEM;
155e30d9128SMaruthi Srinivas Bayyavarapu 		goto release_regions;
156e30d9128SMaruthi Srinivas Bayyavarapu 	}
157e30d9128SMaruthi Srinivas Bayyavarapu 
1587894a7e7SVijendar Mukunda 	irqflags = IRQF_SHARED;
1597894a7e7SVijendar Mukunda 
160e30d9128SMaruthi Srinivas Bayyavarapu 	addr = pci_resource_start(pci, 0);
1615def0136SRavulapati Vishnu vardhan rao 	adata->acp3x_base = devm_ioremap(&pci->dev, addr,
1625def0136SRavulapati Vishnu vardhan rao 					pci_resource_len(pci, 0));
163e30d9128SMaruthi Srinivas Bayyavarapu 	if (!adata->acp3x_base) {
164e30d9128SMaruthi Srinivas Bayyavarapu 		ret = -ENOMEM;
165a523e153SRavulapati Vishnu vardhan rao 		goto release_regions;
166e30d9128SMaruthi Srinivas Bayyavarapu 	}
167e30d9128SMaruthi Srinivas Bayyavarapu 	pci_set_master(pci);
168e30d9128SMaruthi Srinivas Bayyavarapu 	pci_set_drvdata(pci, adata);
1691255296cSAkshu Agrawal 	/* Save ACP_PME_EN state */
1701255296cSAkshu Agrawal 	adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN);
1711255296cSAkshu Agrawal 	ret = acp3x_init(adata);
172535fd141SRavulapati Vishnu vardhan rao 	if (ret)
173a523e153SRavulapati Vishnu vardhan rao 		goto release_regions;
1747894a7e7SVijendar Mukunda 
1757894a7e7SVijendar Mukunda 	val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
1767894a7e7SVijendar Mukunda 	switch (val) {
1777894a7e7SVijendar Mukunda 	case I2S_MODE:
1787894a7e7SVijendar Mukunda 		adata->res = devm_kzalloc(&pci->dev,
1795def0136SRavulapati Vishnu vardhan rao 					  sizeof(struct resource) * 4,
1807894a7e7SVijendar Mukunda 					  GFP_KERNEL);
1817894a7e7SVijendar Mukunda 		if (!adata->res) {
1827894a7e7SVijendar Mukunda 			ret = -ENOMEM;
183535fd141SRavulapati Vishnu vardhan rao 			goto de_init;
1847894a7e7SVijendar Mukunda 		}
1857894a7e7SVijendar Mukunda 
1867894a7e7SVijendar Mukunda 		adata->res[0].name = "acp3x_i2s_iomem";
1877894a7e7SVijendar Mukunda 		adata->res[0].flags = IORESOURCE_MEM;
1887894a7e7SVijendar Mukunda 		adata->res[0].start = addr;
1897894a7e7SVijendar Mukunda 		adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START);
1907894a7e7SVijendar Mukunda 
1915def0136SRavulapati Vishnu vardhan rao 		adata->res[1].name = "acp3x_i2s_sp";
1925def0136SRavulapati Vishnu vardhan rao 		adata->res[1].flags = IORESOURCE_MEM;
1935def0136SRavulapati Vishnu vardhan rao 		adata->res[1].start = addr + ACP3x_I2STDM_REG_START;
1945def0136SRavulapati Vishnu vardhan rao 		adata->res[1].end = addr + ACP3x_I2STDM_REG_END;
1955def0136SRavulapati Vishnu vardhan rao 
1965def0136SRavulapati Vishnu vardhan rao 		adata->res[2].name = "acp3x_i2s_bt";
1975def0136SRavulapati Vishnu vardhan rao 		adata->res[2].flags = IORESOURCE_MEM;
1985def0136SRavulapati Vishnu vardhan rao 		adata->res[2].start = addr + ACP3x_BT_TDM_REG_START;
1995def0136SRavulapati Vishnu vardhan rao 		adata->res[2].end = addr + ACP3x_BT_TDM_REG_END;
2005def0136SRavulapati Vishnu vardhan rao 
2015def0136SRavulapati Vishnu vardhan rao 		adata->res[3].name = "acp3x_i2s_irq";
2025def0136SRavulapati Vishnu vardhan rao 		adata->res[3].flags = IORESOURCE_IRQ;
2035def0136SRavulapati Vishnu vardhan rao 		adata->res[3].start = pci->irq;
2045def0136SRavulapati Vishnu vardhan rao 		adata->res[3].end = adata->res[3].start;
2057894a7e7SVijendar Mukunda 
2067894a7e7SVijendar Mukunda 		adata->acp3x_audio_mode = ACP3x_I2S_MODE;
2077894a7e7SVijendar Mukunda 
2087894a7e7SVijendar Mukunda 		memset(&pdevinfo, 0, sizeof(pdevinfo));
2095def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].name = "acp3x_rv_i2s_dma";
2105def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].id = 0;
2115def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].parent = &pci->dev;
2125def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].num_res = 4;
2135def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].res = &adata->res[0];
2145def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].data = &irqflags;
2155def0136SRavulapati Vishnu vardhan rao 		pdevinfo[0].size_data = sizeof(irqflags);
2167894a7e7SVijendar Mukunda 
2175def0136SRavulapati Vishnu vardhan rao 		pdevinfo[1].name = "acp3x_i2s_playcap";
2185def0136SRavulapati Vishnu vardhan rao 		pdevinfo[1].id = 0;
2195def0136SRavulapati Vishnu vardhan rao 		pdevinfo[1].parent = &pci->dev;
2205def0136SRavulapati Vishnu vardhan rao 		pdevinfo[1].num_res = 1;
2215def0136SRavulapati Vishnu vardhan rao 		pdevinfo[1].res = &adata->res[1];
2225def0136SRavulapati Vishnu vardhan rao 
2235def0136SRavulapati Vishnu vardhan rao 		pdevinfo[2].name = "acp3x_i2s_playcap";
2245def0136SRavulapati Vishnu vardhan rao 		pdevinfo[2].id = 1;
2255def0136SRavulapati Vishnu vardhan rao 		pdevinfo[2].parent = &pci->dev;
2265def0136SRavulapati Vishnu vardhan rao 		pdevinfo[2].num_res = 1;
227a174a6c2SRavulapati Vishnu vardhan rao 		pdevinfo[2].res = &adata->res[1];
228a174a6c2SRavulapati Vishnu vardhan rao 
229a174a6c2SRavulapati Vishnu vardhan rao 		pdevinfo[3].name = "acp3x_i2s_playcap";
230a174a6c2SRavulapati Vishnu vardhan rao 		pdevinfo[3].id = 2;
231a174a6c2SRavulapati Vishnu vardhan rao 		pdevinfo[3].parent = &pci->dev;
232a174a6c2SRavulapati Vishnu vardhan rao 		pdevinfo[3].num_res = 1;
233a174a6c2SRavulapati Vishnu vardhan rao 		pdevinfo[3].res = &adata->res[2];
2345def0136SRavulapati Vishnu vardhan rao 		for (i = 0; i < ACP3x_DEVS; i++) {
2355def0136SRavulapati Vishnu vardhan rao 			adata->pdev[i] =
2365def0136SRavulapati Vishnu vardhan rao 				platform_device_register_full(&pdevinfo[i]);
2375def0136SRavulapati Vishnu vardhan rao 			if (IS_ERR(adata->pdev[i])) {
2387894a7e7SVijendar Mukunda 				dev_err(&pci->dev, "cannot register %s device\n",
2395def0136SRavulapati Vishnu vardhan rao 					pdevinfo[i].name);
2405def0136SRavulapati Vishnu vardhan rao 				ret = PTR_ERR(adata->pdev[i]);
2415def0136SRavulapati Vishnu vardhan rao 				goto unregister_devs;
2425def0136SRavulapati Vishnu vardhan rao 			}
2437894a7e7SVijendar Mukunda 		}
2447894a7e7SVijendar Mukunda 		break;
2457894a7e7SVijendar Mukunda 	default:
246efb38304SVijendar Mukunda 		dev_info(&pci->dev, "ACP audio mode : %d\n", val);
247e5879d98SMark Brown 		break;
2487894a7e7SVijendar Mukunda 	}
249535fd141SRavulapati Vishnu vardhan rao 	pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
250535fd141SRavulapati Vishnu vardhan rao 	pm_runtime_use_autosuspend(&pci->dev);
251535fd141SRavulapati Vishnu vardhan rao 	pm_runtime_put_noidle(&pci->dev);
252535fd141SRavulapati Vishnu vardhan rao 	pm_runtime_allow(&pci->dev);
253e30d9128SMaruthi Srinivas Bayyavarapu 	return 0;
254e30d9128SMaruthi Srinivas Bayyavarapu 
2555def0136SRavulapati Vishnu vardhan rao unregister_devs:
2565def0136SRavulapati Vishnu vardhan rao 	if (val == I2S_MODE)
2575def0136SRavulapati Vishnu vardhan rao 		for (i = 0; i < ACP3x_DEVS; i++)
2585def0136SRavulapati Vishnu vardhan rao 			platform_device_unregister(adata->pdev[i]);
259535fd141SRavulapati Vishnu vardhan rao de_init:
260535fd141SRavulapati Vishnu vardhan rao 	if (acp3x_deinit(adata->acp3x_base))
261535fd141SRavulapati Vishnu vardhan rao 		dev_err(&pci->dev, "ACP de-init failed\n");
262e30d9128SMaruthi Srinivas Bayyavarapu release_regions:
263e30d9128SMaruthi Srinivas Bayyavarapu 	pci_release_regions(pci);
264e30d9128SMaruthi Srinivas Bayyavarapu disable_pci:
265e30d9128SMaruthi Srinivas Bayyavarapu 	pci_disable_device(pci);
266e30d9128SMaruthi Srinivas Bayyavarapu 
267e30d9128SMaruthi Srinivas Bayyavarapu 	return ret;
268e30d9128SMaruthi Srinivas Bayyavarapu }
269e30d9128SMaruthi Srinivas Bayyavarapu 
snd_acp3x_suspend(struct device * dev)270535fd141SRavulapati Vishnu vardhan rao static int snd_acp3x_suspend(struct device *dev)
271535fd141SRavulapati Vishnu vardhan rao {
272535fd141SRavulapati Vishnu vardhan rao 	int ret;
273535fd141SRavulapati Vishnu vardhan rao 	struct acp3x_dev_data *adata;
274535fd141SRavulapati Vishnu vardhan rao 
275535fd141SRavulapati Vishnu vardhan rao 	adata = dev_get_drvdata(dev);
276535fd141SRavulapati Vishnu vardhan rao 	ret = acp3x_deinit(adata->acp3x_base);
277535fd141SRavulapati Vishnu vardhan rao 	if (ret)
278535fd141SRavulapati Vishnu vardhan rao 		dev_err(dev, "ACP de-init failed\n");
279535fd141SRavulapati Vishnu vardhan rao 	else
280535fd141SRavulapati Vishnu vardhan rao 		dev_dbg(dev, "ACP de-initialized\n");
281535fd141SRavulapati Vishnu vardhan rao 
282535fd141SRavulapati Vishnu vardhan rao 	return 0;
283535fd141SRavulapati Vishnu vardhan rao }
284535fd141SRavulapati Vishnu vardhan rao 
snd_acp3x_resume(struct device * dev)285535fd141SRavulapati Vishnu vardhan rao static int snd_acp3x_resume(struct device *dev)
286535fd141SRavulapati Vishnu vardhan rao {
287535fd141SRavulapati Vishnu vardhan rao 	int ret;
288535fd141SRavulapati Vishnu vardhan rao 	struct acp3x_dev_data *adata;
289535fd141SRavulapati Vishnu vardhan rao 
290535fd141SRavulapati Vishnu vardhan rao 	adata = dev_get_drvdata(dev);
2911255296cSAkshu Agrawal 	ret = acp3x_init(adata);
292535fd141SRavulapati Vishnu vardhan rao 	if (ret) {
293535fd141SRavulapati Vishnu vardhan rao 		dev_err(dev, "ACP init failed\n");
294535fd141SRavulapati Vishnu vardhan rao 		return ret;
295535fd141SRavulapati Vishnu vardhan rao 	}
296535fd141SRavulapati Vishnu vardhan rao 	return 0;
297535fd141SRavulapati Vishnu vardhan rao }
298535fd141SRavulapati Vishnu vardhan rao 
299535fd141SRavulapati Vishnu vardhan rao static const struct dev_pm_ops acp3x_pm = {
300535fd141SRavulapati Vishnu vardhan rao 	.runtime_suspend = snd_acp3x_suspend,
301535fd141SRavulapati Vishnu vardhan rao 	.runtime_resume =  snd_acp3x_resume,
302535fd141SRavulapati Vishnu vardhan rao 	.resume =	snd_acp3x_resume,
303535fd141SRavulapati Vishnu vardhan rao };
304535fd141SRavulapati Vishnu vardhan rao 
snd_acp3x_remove(struct pci_dev * pci)305e30d9128SMaruthi Srinivas Bayyavarapu static void snd_acp3x_remove(struct pci_dev *pci)
306e30d9128SMaruthi Srinivas Bayyavarapu {
307535fd141SRavulapati Vishnu vardhan rao 	struct acp3x_dev_data *adata;
308535fd141SRavulapati Vishnu vardhan rao 	int i, ret;
309e30d9128SMaruthi Srinivas Bayyavarapu 
310535fd141SRavulapati Vishnu vardhan rao 	adata = pci_get_drvdata(pci);
3115def0136SRavulapati Vishnu vardhan rao 	if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
3125def0136SRavulapati Vishnu vardhan rao 		for (i = 0; i < ACP3x_DEVS; i++)
3135def0136SRavulapati Vishnu vardhan rao 			platform_device_unregister(adata->pdev[i]);
3145def0136SRavulapati Vishnu vardhan rao 	}
315535fd141SRavulapati Vishnu vardhan rao 	ret = acp3x_deinit(adata->acp3x_base);
316535fd141SRavulapati Vishnu vardhan rao 	if (ret)
317535fd141SRavulapati Vishnu vardhan rao 		dev_err(&pci->dev, "ACP de-init failed\n");
318ad922ca1SRavulapati Vishnu vardhan rao 	pm_runtime_forbid(&pci->dev);
319535fd141SRavulapati Vishnu vardhan rao 	pm_runtime_get_noresume(&pci->dev);
320e30d9128SMaruthi Srinivas Bayyavarapu 	pci_release_regions(pci);
321e30d9128SMaruthi Srinivas Bayyavarapu 	pci_disable_device(pci);
322e30d9128SMaruthi Srinivas Bayyavarapu }
323e30d9128SMaruthi Srinivas Bayyavarapu 
324e30d9128SMaruthi Srinivas Bayyavarapu static const struct pci_device_id snd_acp3x_ids[] = {
325e30d9128SMaruthi Srinivas Bayyavarapu 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
326e30d9128SMaruthi Srinivas Bayyavarapu 	.class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
327e30d9128SMaruthi Srinivas Bayyavarapu 	.class_mask = 0xffffff },
328e30d9128SMaruthi Srinivas Bayyavarapu 	{ 0, },
329e30d9128SMaruthi Srinivas Bayyavarapu };
330e30d9128SMaruthi Srinivas Bayyavarapu MODULE_DEVICE_TABLE(pci, snd_acp3x_ids);
331e30d9128SMaruthi Srinivas Bayyavarapu 
332e30d9128SMaruthi Srinivas Bayyavarapu static struct pci_driver acp3x_driver  = {
333e30d9128SMaruthi Srinivas Bayyavarapu 	.name = KBUILD_MODNAME,
334e30d9128SMaruthi Srinivas Bayyavarapu 	.id_table = snd_acp3x_ids,
335e30d9128SMaruthi Srinivas Bayyavarapu 	.probe = snd_acp3x_probe,
336e30d9128SMaruthi Srinivas Bayyavarapu 	.remove = snd_acp3x_remove,
337535fd141SRavulapati Vishnu vardhan rao 	.driver = {
338535fd141SRavulapati Vishnu vardhan rao 		.pm = &acp3x_pm,
339535fd141SRavulapati Vishnu vardhan rao 	}
340e30d9128SMaruthi Srinivas Bayyavarapu };
341e30d9128SMaruthi Srinivas Bayyavarapu 
342e30d9128SMaruthi Srinivas Bayyavarapu module_pci_driver(acp3x_driver);
343e30d9128SMaruthi Srinivas Bayyavarapu 
3445def0136SRavulapati Vishnu vardhan rao MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
345e30d9128SMaruthi Srinivas Bayyavarapu MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
346e30d9128SMaruthi Srinivas Bayyavarapu MODULE_DESCRIPTION("AMD ACP3x PCI driver");
347e30d9128SMaruthi Srinivas Bayyavarapu MODULE_LICENSE("GPL v2");
348