xref: /openbmc/linux/sound/soc/sof/intel/hda-dsp.c (revision 747503b1813a3e6e4c52d9c0b4bd462b64940940)
1*747503b1SLiam Girdwood // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2*747503b1SLiam Girdwood //
3*747503b1SLiam Girdwood // This file is provided under a dual BSD/GPLv2 license.  When using or
4*747503b1SLiam Girdwood // redistributing this file, you may do so under either license.
5*747503b1SLiam Girdwood //
6*747503b1SLiam Girdwood // Copyright(c) 2018 Intel Corporation. All rights reserved.
7*747503b1SLiam Girdwood //
8*747503b1SLiam Girdwood // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9*747503b1SLiam Girdwood //	    Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
10*747503b1SLiam Girdwood //	    Rander Wang <rander.wang@intel.com>
11*747503b1SLiam Girdwood //          Keyon Jie <yang.jie@linux.intel.com>
12*747503b1SLiam Girdwood //
13*747503b1SLiam Girdwood 
14*747503b1SLiam Girdwood /*
15*747503b1SLiam Girdwood  * Hardware interface for generic Intel audio DSP HDA IP
16*747503b1SLiam Girdwood  */
17*747503b1SLiam Girdwood 
18*747503b1SLiam Girdwood #include <sound/hdaudio_ext.h>
19*747503b1SLiam Girdwood #include <sound/hda_register.h>
20*747503b1SLiam Girdwood #include "../ops.h"
21*747503b1SLiam Girdwood #include "hda.h"
22*747503b1SLiam Girdwood 
23*747503b1SLiam Girdwood /*
24*747503b1SLiam Girdwood  * DSP Core control.
25*747503b1SLiam Girdwood  */
26*747503b1SLiam Girdwood 
27*747503b1SLiam Girdwood int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev, unsigned int core_mask)
28*747503b1SLiam Girdwood {
29*747503b1SLiam Girdwood 	u32 adspcs;
30*747503b1SLiam Girdwood 	u32 reset;
31*747503b1SLiam Girdwood 	int ret;
32*747503b1SLiam Girdwood 
33*747503b1SLiam Girdwood 	/* set reset bits for cores */
34*747503b1SLiam Girdwood 	reset = HDA_DSP_ADSPCS_CRST_MASK(core_mask);
35*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
36*747503b1SLiam Girdwood 					 HDA_DSP_REG_ADSPCS,
37*747503b1SLiam Girdwood 					 reset, reset),
38*747503b1SLiam Girdwood 
39*747503b1SLiam Girdwood 	/* poll with timeout to check if operation successful */
40*747503b1SLiam Girdwood 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
41*747503b1SLiam Girdwood 					HDA_DSP_REG_ADSPCS, adspcs,
42*747503b1SLiam Girdwood 					((adspcs & reset) == reset),
43*747503b1SLiam Girdwood 					HDA_DSP_REG_POLL_INTERVAL_US,
44*747503b1SLiam Girdwood 					HDA_DSP_RESET_TIMEOUT_US);
45*747503b1SLiam Girdwood 
46*747503b1SLiam Girdwood 	/* has core entered reset ? */
47*747503b1SLiam Girdwood 	adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
48*747503b1SLiam Girdwood 				  HDA_DSP_REG_ADSPCS);
49*747503b1SLiam Girdwood 	if ((adspcs & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) !=
50*747503b1SLiam Girdwood 		HDA_DSP_ADSPCS_CRST_MASK(core_mask)) {
51*747503b1SLiam Girdwood 		dev_err(sdev->dev,
52*747503b1SLiam Girdwood 			"error: reset enter failed: core_mask %x adspcs 0x%x\n",
53*747503b1SLiam Girdwood 			core_mask, adspcs);
54*747503b1SLiam Girdwood 		ret = -EIO;
55*747503b1SLiam Girdwood 	}
56*747503b1SLiam Girdwood 
57*747503b1SLiam Girdwood 	return ret;
58*747503b1SLiam Girdwood }
59*747503b1SLiam Girdwood 
60*747503b1SLiam Girdwood int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, unsigned int core_mask)
61*747503b1SLiam Girdwood {
62*747503b1SLiam Girdwood 	unsigned int crst;
63*747503b1SLiam Girdwood 	u32 adspcs;
64*747503b1SLiam Girdwood 	int ret;
65*747503b1SLiam Girdwood 
66*747503b1SLiam Girdwood 	/* clear reset bits for cores */
67*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
68*747503b1SLiam Girdwood 					 HDA_DSP_REG_ADSPCS,
69*747503b1SLiam Girdwood 					 HDA_DSP_ADSPCS_CRST_MASK(core_mask),
70*747503b1SLiam Girdwood 					 0);
71*747503b1SLiam Girdwood 
72*747503b1SLiam Girdwood 	/* poll with timeout to check if operation successful */
73*747503b1SLiam Girdwood 	crst = HDA_DSP_ADSPCS_CRST_MASK(core_mask);
74*747503b1SLiam Girdwood 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
75*747503b1SLiam Girdwood 					    HDA_DSP_REG_ADSPCS, adspcs,
76*747503b1SLiam Girdwood 					    !(adspcs & crst),
77*747503b1SLiam Girdwood 					    HDA_DSP_REG_POLL_INTERVAL_US,
78*747503b1SLiam Girdwood 					    HDA_DSP_RESET_TIMEOUT_US);
79*747503b1SLiam Girdwood 
80*747503b1SLiam Girdwood 	/* has core left reset ? */
81*747503b1SLiam Girdwood 	adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
82*747503b1SLiam Girdwood 				  HDA_DSP_REG_ADSPCS);
83*747503b1SLiam Girdwood 	if ((adspcs & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) != 0) {
84*747503b1SLiam Girdwood 		dev_err(sdev->dev,
85*747503b1SLiam Girdwood 			"error: reset leave failed: core_mask %x adspcs 0x%x\n",
86*747503b1SLiam Girdwood 			core_mask, adspcs);
87*747503b1SLiam Girdwood 		ret = -EIO;
88*747503b1SLiam Girdwood 	}
89*747503b1SLiam Girdwood 
90*747503b1SLiam Girdwood 	return ret;
91*747503b1SLiam Girdwood }
92*747503b1SLiam Girdwood 
93*747503b1SLiam Girdwood int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask)
94*747503b1SLiam Girdwood {
95*747503b1SLiam Girdwood 	/* stall core */
96*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
97*747503b1SLiam Girdwood 					 HDA_DSP_REG_ADSPCS,
98*747503b1SLiam Girdwood 					 HDA_DSP_ADSPCS_CSTALL_MASK(core_mask),
99*747503b1SLiam Girdwood 					 HDA_DSP_ADSPCS_CSTALL_MASK(core_mask));
100*747503b1SLiam Girdwood 
101*747503b1SLiam Girdwood 	/* set reset state */
102*747503b1SLiam Girdwood 	return hda_dsp_core_reset_enter(sdev, core_mask);
103*747503b1SLiam Girdwood }
104*747503b1SLiam Girdwood 
105*747503b1SLiam Girdwood int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
106*747503b1SLiam Girdwood {
107*747503b1SLiam Girdwood 	int ret;
108*747503b1SLiam Girdwood 
109*747503b1SLiam Girdwood 	/* leave reset state */
110*747503b1SLiam Girdwood 	ret = hda_dsp_core_reset_leave(sdev, core_mask);
111*747503b1SLiam Girdwood 	if (ret < 0)
112*747503b1SLiam Girdwood 		return ret;
113*747503b1SLiam Girdwood 
114*747503b1SLiam Girdwood 	/* run core */
115*747503b1SLiam Girdwood 	dev_dbg(sdev->dev, "unstall/run core: core_mask = %x\n", core_mask);
116*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
117*747503b1SLiam Girdwood 					 HDA_DSP_REG_ADSPCS,
118*747503b1SLiam Girdwood 					 HDA_DSP_ADSPCS_CSTALL_MASK(core_mask),
119*747503b1SLiam Girdwood 					 0);
120*747503b1SLiam Girdwood 
121*747503b1SLiam Girdwood 	/* is core now running ? */
122*747503b1SLiam Girdwood 	if (!hda_dsp_core_is_enabled(sdev, core_mask)) {
123*747503b1SLiam Girdwood 		hda_dsp_core_stall_reset(sdev, core_mask);
124*747503b1SLiam Girdwood 		dev_err(sdev->dev, "error: DSP start core failed: core_mask %x\n",
125*747503b1SLiam Girdwood 			core_mask);
126*747503b1SLiam Girdwood 		ret = -EIO;
127*747503b1SLiam Girdwood 	}
128*747503b1SLiam Girdwood 
129*747503b1SLiam Girdwood 	return ret;
130*747503b1SLiam Girdwood }
131*747503b1SLiam Girdwood 
132*747503b1SLiam Girdwood /*
133*747503b1SLiam Girdwood  * Power Management.
134*747503b1SLiam Girdwood  */
135*747503b1SLiam Girdwood 
136*747503b1SLiam Girdwood int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
137*747503b1SLiam Girdwood {
138*747503b1SLiam Girdwood 	unsigned int cpa;
139*747503b1SLiam Girdwood 	u32 adspcs;
140*747503b1SLiam Girdwood 	int ret;
141*747503b1SLiam Girdwood 
142*747503b1SLiam Girdwood 	/* update bits */
143*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS,
144*747503b1SLiam Girdwood 				HDA_DSP_ADSPCS_SPA_MASK(core_mask),
145*747503b1SLiam Girdwood 				HDA_DSP_ADSPCS_SPA_MASK(core_mask));
146*747503b1SLiam Girdwood 
147*747503b1SLiam Girdwood 	/* poll with timeout to check if operation successful */
148*747503b1SLiam Girdwood 	cpa = HDA_DSP_ADSPCS_CPA_MASK(core_mask);
149*747503b1SLiam Girdwood 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
150*747503b1SLiam Girdwood 					    HDA_DSP_REG_ADSPCS, adspcs,
151*747503b1SLiam Girdwood 					    (adspcs & cpa) == cpa,
152*747503b1SLiam Girdwood 					    HDA_DSP_REG_POLL_INTERVAL_US,
153*747503b1SLiam Girdwood 					    HDA_DSP_RESET_TIMEOUT_US);
154*747503b1SLiam Girdwood 	if (ret < 0)
155*747503b1SLiam Girdwood 		dev_err(sdev->dev, "error: timeout on core powerup\n");
156*747503b1SLiam Girdwood 
157*747503b1SLiam Girdwood 	/* did core power up ? */
158*747503b1SLiam Girdwood 	adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
159*747503b1SLiam Girdwood 				  HDA_DSP_REG_ADSPCS);
160*747503b1SLiam Girdwood 	if ((adspcs & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) !=
161*747503b1SLiam Girdwood 		HDA_DSP_ADSPCS_CPA_MASK(core_mask)) {
162*747503b1SLiam Girdwood 		dev_err(sdev->dev,
163*747503b1SLiam Girdwood 			"error: power up core failed core_mask %xadspcs 0x%x\n",
164*747503b1SLiam Girdwood 			core_mask, adspcs);
165*747503b1SLiam Girdwood 		ret = -EIO;
166*747503b1SLiam Girdwood 	}
167*747503b1SLiam Girdwood 
168*747503b1SLiam Girdwood 	return ret;
169*747503b1SLiam Girdwood }
170*747503b1SLiam Girdwood 
171*747503b1SLiam Girdwood int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
172*747503b1SLiam Girdwood {
173*747503b1SLiam Girdwood 	u32 adspcs;
174*747503b1SLiam Girdwood 
175*747503b1SLiam Girdwood 	/* update bits */
176*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
177*747503b1SLiam Girdwood 					 HDA_DSP_REG_ADSPCS,
178*747503b1SLiam Girdwood 					 HDA_DSP_ADSPCS_SPA_MASK(core_mask), 0);
179*747503b1SLiam Girdwood 
180*747503b1SLiam Girdwood 	return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
181*747503b1SLiam Girdwood 				HDA_DSP_REG_ADSPCS, adspcs,
182*747503b1SLiam Girdwood 				!(adspcs & HDA_DSP_ADSPCS_SPA_MASK(core_mask)),
183*747503b1SLiam Girdwood 				HDA_DSP_REG_POLL_INTERVAL_US,
184*747503b1SLiam Girdwood 				HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
185*747503b1SLiam Girdwood }
186*747503b1SLiam Girdwood 
187*747503b1SLiam Girdwood bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev,
188*747503b1SLiam Girdwood 			     unsigned int core_mask)
189*747503b1SLiam Girdwood {
190*747503b1SLiam Girdwood 	int val;
191*747503b1SLiam Girdwood 	bool is_enable;
192*747503b1SLiam Girdwood 
193*747503b1SLiam Girdwood 	val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS);
194*747503b1SLiam Girdwood 
195*747503b1SLiam Girdwood 	is_enable = ((val & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) &&
196*747503b1SLiam Girdwood 			(val & HDA_DSP_ADSPCS_SPA_MASK(core_mask)) &&
197*747503b1SLiam Girdwood 			!(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) &&
198*747503b1SLiam Girdwood 			!(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask)));
199*747503b1SLiam Girdwood 
200*747503b1SLiam Girdwood 	dev_dbg(sdev->dev, "DSP core(s) enabled? %d : core_mask %x\n",
201*747503b1SLiam Girdwood 		is_enable, core_mask);
202*747503b1SLiam Girdwood 
203*747503b1SLiam Girdwood 	return is_enable;
204*747503b1SLiam Girdwood }
205*747503b1SLiam Girdwood 
206*747503b1SLiam Girdwood int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask)
207*747503b1SLiam Girdwood {
208*747503b1SLiam Girdwood 	int ret;
209*747503b1SLiam Girdwood 
210*747503b1SLiam Girdwood 	/* return if core is already enabled */
211*747503b1SLiam Girdwood 	if (hda_dsp_core_is_enabled(sdev, core_mask))
212*747503b1SLiam Girdwood 		return 0;
213*747503b1SLiam Girdwood 
214*747503b1SLiam Girdwood 	/* power up */
215*747503b1SLiam Girdwood 	ret = hda_dsp_core_power_up(sdev, core_mask);
216*747503b1SLiam Girdwood 	if (ret < 0) {
217*747503b1SLiam Girdwood 		dev_err(sdev->dev, "error: dsp core power up failed: core_mask %x\n",
218*747503b1SLiam Girdwood 			core_mask);
219*747503b1SLiam Girdwood 		return ret;
220*747503b1SLiam Girdwood 	}
221*747503b1SLiam Girdwood 
222*747503b1SLiam Girdwood 	return hda_dsp_core_run(sdev, core_mask);
223*747503b1SLiam Girdwood }
224*747503b1SLiam Girdwood 
225*747503b1SLiam Girdwood int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
226*747503b1SLiam Girdwood 				  unsigned int core_mask)
227*747503b1SLiam Girdwood {
228*747503b1SLiam Girdwood 	int ret;
229*747503b1SLiam Girdwood 
230*747503b1SLiam Girdwood 	/* place core in reset prior to power down */
231*747503b1SLiam Girdwood 	ret = hda_dsp_core_stall_reset(sdev, core_mask);
232*747503b1SLiam Girdwood 	if (ret < 0) {
233*747503b1SLiam Girdwood 		dev_err(sdev->dev, "error: dsp core reset failed: core_mask %x\n",
234*747503b1SLiam Girdwood 			core_mask);
235*747503b1SLiam Girdwood 		return ret;
236*747503b1SLiam Girdwood 	}
237*747503b1SLiam Girdwood 
238*747503b1SLiam Girdwood 	/* power down core */
239*747503b1SLiam Girdwood 	ret = hda_dsp_core_power_down(sdev, core_mask);
240*747503b1SLiam Girdwood 	if (ret < 0) {
241*747503b1SLiam Girdwood 		dev_err(sdev->dev, "error: dsp core power down fail mask %x: %d\n",
242*747503b1SLiam Girdwood 			core_mask, ret);
243*747503b1SLiam Girdwood 		return ret;
244*747503b1SLiam Girdwood 	}
245*747503b1SLiam Girdwood 
246*747503b1SLiam Girdwood 	/* make sure we are in OFF state */
247*747503b1SLiam Girdwood 	if (hda_dsp_core_is_enabled(sdev, core_mask)) {
248*747503b1SLiam Girdwood 		dev_err(sdev->dev, "error: dsp core disable fail mask %x: %d\n",
249*747503b1SLiam Girdwood 			core_mask, ret);
250*747503b1SLiam Girdwood 		ret = -EIO;
251*747503b1SLiam Girdwood 	}
252*747503b1SLiam Girdwood 
253*747503b1SLiam Girdwood 	return ret;
254*747503b1SLiam Girdwood }
255*747503b1SLiam Girdwood 
256*747503b1SLiam Girdwood void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev)
257*747503b1SLiam Girdwood {
258*747503b1SLiam Girdwood 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
259*747503b1SLiam Girdwood 	const struct sof_intel_dsp_desc *chip = hda->desc;
260*747503b1SLiam Girdwood 
261*747503b1SLiam Girdwood 	/* enable IPC DONE and BUSY interrupts */
262*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
263*747503b1SLiam Girdwood 			HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY,
264*747503b1SLiam Girdwood 			HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY);
265*747503b1SLiam Girdwood 
266*747503b1SLiam Girdwood 	/* enable IPC interrupt */
267*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
268*747503b1SLiam Girdwood 				HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC);
269*747503b1SLiam Girdwood }
270*747503b1SLiam Girdwood 
271*747503b1SLiam Girdwood void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev)
272*747503b1SLiam Girdwood {
273*747503b1SLiam Girdwood 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
274*747503b1SLiam Girdwood 	const struct sof_intel_dsp_desc *chip = hda->desc;
275*747503b1SLiam Girdwood 
276*747503b1SLiam Girdwood 	/* disable IPC interrupt */
277*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
278*747503b1SLiam Girdwood 				HDA_DSP_ADSPIC_IPC, 0);
279*747503b1SLiam Girdwood 
280*747503b1SLiam Girdwood 	/* disable IPC BUSY and DONE interrupt */
281*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
282*747503b1SLiam Girdwood 			HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0);
283*747503b1SLiam Girdwood }
284*747503b1SLiam Girdwood 
285*747503b1SLiam Girdwood static int hda_suspend(struct snd_sof_dev *sdev, int state)
286*747503b1SLiam Girdwood {
287*747503b1SLiam Girdwood 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
288*747503b1SLiam Girdwood 	const struct sof_intel_dsp_desc *chip = hda->desc;
289*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
290*747503b1SLiam Girdwood 	struct hdac_bus *bus = sof_to_bus(sdev);
291*747503b1SLiam Girdwood #endif
292*747503b1SLiam Girdwood 	int ret;
293*747503b1SLiam Girdwood 
294*747503b1SLiam Girdwood 	/* disable IPC interrupts */
295*747503b1SLiam Girdwood 	hda_dsp_ipc_int_disable(sdev);
296*747503b1SLiam Girdwood 
297*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
298*747503b1SLiam Girdwood 	/* power down all hda link */
299*747503b1SLiam Girdwood 	snd_hdac_ext_bus_link_power_down_all(bus);
300*747503b1SLiam Girdwood #endif
301*747503b1SLiam Girdwood 
302*747503b1SLiam Girdwood 	/* power down DSP */
303*747503b1SLiam Girdwood 	ret = hda_dsp_core_reset_power_down(sdev, chip->cores_mask);
304*747503b1SLiam Girdwood 	if (ret < 0) {
305*747503b1SLiam Girdwood 		dev_err(sdev->dev,
306*747503b1SLiam Girdwood 			"error: failed to power down core during suspend\n");
307*747503b1SLiam Girdwood 		return ret;
308*747503b1SLiam Girdwood 	}
309*747503b1SLiam Girdwood 
310*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
311*747503b1SLiam Girdwood 	/* disable ppcap interrupt */
312*747503b1SLiam Girdwood 	snd_hdac_ext_bus_ppcap_int_enable(bus, false);
313*747503b1SLiam Girdwood 	snd_hdac_ext_bus_ppcap_enable(bus, false);
314*747503b1SLiam Girdwood 
315*747503b1SLiam Girdwood 	/* disable hda bus irq and i/o */
316*747503b1SLiam Girdwood 	snd_hdac_bus_stop_chip(bus);
317*747503b1SLiam Girdwood #else
318*747503b1SLiam Girdwood 	/* disable ppcap interrupt */
319*747503b1SLiam Girdwood 	hda_dsp_ctrl_ppcap_enable(sdev, false);
320*747503b1SLiam Girdwood 	hda_dsp_ctrl_ppcap_int_enable(sdev, false);
321*747503b1SLiam Girdwood 
322*747503b1SLiam Girdwood 	/* disable hda bus irq */
323*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
324*747503b1SLiam Girdwood 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
325*747503b1SLiam Girdwood 				0);
326*747503b1SLiam Girdwood #endif
327*747503b1SLiam Girdwood 
328*747503b1SLiam Girdwood 	/* disable LP retention mode */
329*747503b1SLiam Girdwood 	snd_sof_pci_update_bits(sdev, PCI_PGCTL,
330*747503b1SLiam Girdwood 				PCI_PGCTL_LSRMD_MASK, PCI_PGCTL_LSRMD_MASK);
331*747503b1SLiam Girdwood 
332*747503b1SLiam Girdwood 	/* reset controller */
333*747503b1SLiam Girdwood 	ret = hda_dsp_ctrl_link_reset(sdev, true);
334*747503b1SLiam Girdwood 	if (ret < 0) {
335*747503b1SLiam Girdwood 		dev_err(sdev->dev,
336*747503b1SLiam Girdwood 			"error: failed to reset controller during suspend\n");
337*747503b1SLiam Girdwood 		return ret;
338*747503b1SLiam Girdwood 	}
339*747503b1SLiam Girdwood 
340*747503b1SLiam Girdwood 	return 0;
341*747503b1SLiam Girdwood }
342*747503b1SLiam Girdwood 
343*747503b1SLiam Girdwood static int hda_resume(struct snd_sof_dev *sdev)
344*747503b1SLiam Girdwood {
345*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
346*747503b1SLiam Girdwood 	struct hdac_bus *bus = sof_to_bus(sdev);
347*747503b1SLiam Girdwood 	struct hdac_ext_link *hlink = NULL;
348*747503b1SLiam Girdwood #endif
349*747503b1SLiam Girdwood 	int ret;
350*747503b1SLiam Girdwood 
351*747503b1SLiam Girdwood 	/*
352*747503b1SLiam Girdwood 	 * clear TCSEL to clear playback on some HD Audio
353*747503b1SLiam Girdwood 	 * codecs. PCI TCSEL is defined in the Intel manuals.
354*747503b1SLiam Girdwood 	 */
355*747503b1SLiam Girdwood 	snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0);
356*747503b1SLiam Girdwood 
357*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
358*747503b1SLiam Girdwood 	/* reset and start hda controller */
359*747503b1SLiam Girdwood 	ret = hda_dsp_ctrl_init_chip(sdev, true);
360*747503b1SLiam Girdwood 	if (ret < 0) {
361*747503b1SLiam Girdwood 		dev_err(sdev->dev,
362*747503b1SLiam Girdwood 			"error: failed to start controller after resume\n");
363*747503b1SLiam Girdwood 		return ret;
364*747503b1SLiam Girdwood 	}
365*747503b1SLiam Girdwood 
366*747503b1SLiam Girdwood 	hda_dsp_ctrl_misc_clock_gating(sdev, false);
367*747503b1SLiam Girdwood 
368*747503b1SLiam Girdwood 	/* Reset stream-to-link mapping */
369*747503b1SLiam Girdwood 	list_for_each_entry(hlink, &bus->hlink_list, list)
370*747503b1SLiam Girdwood 		bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
371*747503b1SLiam Girdwood 
372*747503b1SLiam Girdwood 	hda_dsp_ctrl_misc_clock_gating(sdev, true);
373*747503b1SLiam Girdwood 
374*747503b1SLiam Girdwood 	/* enable ppcap interrupt */
375*747503b1SLiam Girdwood 	snd_hdac_ext_bus_ppcap_enable(bus, true);
376*747503b1SLiam Girdwood 	snd_hdac_ext_bus_ppcap_int_enable(bus, true);
377*747503b1SLiam Girdwood #else
378*747503b1SLiam Girdwood 
379*747503b1SLiam Girdwood 	hda_dsp_ctrl_misc_clock_gating(sdev, false);
380*747503b1SLiam Girdwood 
381*747503b1SLiam Girdwood 	/* reset controller */
382*747503b1SLiam Girdwood 	ret = hda_dsp_ctrl_link_reset(sdev, true);
383*747503b1SLiam Girdwood 	if (ret < 0) {
384*747503b1SLiam Girdwood 		dev_err(sdev->dev,
385*747503b1SLiam Girdwood 			"error: failed to reset controller during resume\n");
386*747503b1SLiam Girdwood 		return ret;
387*747503b1SLiam Girdwood 	}
388*747503b1SLiam Girdwood 
389*747503b1SLiam Girdwood 	/* take controller out of reset */
390*747503b1SLiam Girdwood 	ret = hda_dsp_ctrl_link_reset(sdev, false);
391*747503b1SLiam Girdwood 	if (ret < 0) {
392*747503b1SLiam Girdwood 		dev_err(sdev->dev,
393*747503b1SLiam Girdwood 			"error: failed to ready controller during resume\n");
394*747503b1SLiam Girdwood 		return ret;
395*747503b1SLiam Girdwood 	}
396*747503b1SLiam Girdwood 
397*747503b1SLiam Girdwood 	/* enable hda bus irq */
398*747503b1SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
399*747503b1SLiam Girdwood 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
400*747503b1SLiam Girdwood 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
401*747503b1SLiam Girdwood 
402*747503b1SLiam Girdwood 	hda_dsp_ctrl_misc_clock_gating(sdev, true);
403*747503b1SLiam Girdwood 
404*747503b1SLiam Girdwood 	/* enable ppcap interrupt */
405*747503b1SLiam Girdwood 	hda_dsp_ctrl_ppcap_enable(sdev, true);
406*747503b1SLiam Girdwood 	hda_dsp_ctrl_ppcap_int_enable(sdev, true);
407*747503b1SLiam Girdwood #endif
408*747503b1SLiam Girdwood 
409*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
410*747503b1SLiam Girdwood 	/* turn off the links that were off before suspend */
411*747503b1SLiam Girdwood 	list_for_each_entry(hlink, &bus->hlink_list, list) {
412*747503b1SLiam Girdwood 		if (!hlink->ref_count)
413*747503b1SLiam Girdwood 			snd_hdac_ext_bus_link_power_down(hlink);
414*747503b1SLiam Girdwood 	}
415*747503b1SLiam Girdwood 
416*747503b1SLiam Girdwood 	/* check dma status and clean up CORB/RIRB buffers */
417*747503b1SLiam Girdwood 	if (!bus->cmd_dma_state)
418*747503b1SLiam Girdwood 		snd_hdac_bus_stop_cmd_io(bus);
419*747503b1SLiam Girdwood #endif
420*747503b1SLiam Girdwood 
421*747503b1SLiam Girdwood 	return 0;
422*747503b1SLiam Girdwood }
423*747503b1SLiam Girdwood 
424*747503b1SLiam Girdwood int hda_dsp_resume(struct snd_sof_dev *sdev)
425*747503b1SLiam Girdwood {
426*747503b1SLiam Girdwood 	/* init hda controller. DSP cores will be powered up during fw boot */
427*747503b1SLiam Girdwood 	return hda_resume(sdev);
428*747503b1SLiam Girdwood }
429*747503b1SLiam Girdwood 
430*747503b1SLiam Girdwood int hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
431*747503b1SLiam Girdwood {
432*747503b1SLiam Girdwood 	/* init hda controller. DSP cores will be powered up during fw boot */
433*747503b1SLiam Girdwood 	return hda_resume(sdev);
434*747503b1SLiam Girdwood }
435*747503b1SLiam Girdwood 
436*747503b1SLiam Girdwood int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state)
437*747503b1SLiam Girdwood {
438*747503b1SLiam Girdwood 	/* stop hda controller and power dsp off */
439*747503b1SLiam Girdwood 	return hda_suspend(sdev, state);
440*747503b1SLiam Girdwood }
441*747503b1SLiam Girdwood 
442*747503b1SLiam Girdwood int hda_dsp_suspend(struct snd_sof_dev *sdev, int state)
443*747503b1SLiam Girdwood {
444*747503b1SLiam Girdwood 	struct hdac_bus *bus = sof_to_bus(sdev);
445*747503b1SLiam Girdwood 	int ret;
446*747503b1SLiam Girdwood 
447*747503b1SLiam Girdwood 	/* stop hda controller and power dsp off */
448*747503b1SLiam Girdwood 	ret = hda_suspend(sdev, state);
449*747503b1SLiam Girdwood 	if (ret < 0) {
450*747503b1SLiam Girdwood 		dev_err(bus->dev, "error: suspending dsp\n");
451*747503b1SLiam Girdwood 		return ret;
452*747503b1SLiam Girdwood 	}
453*747503b1SLiam Girdwood 
454*747503b1SLiam Girdwood 	return 0;
455*747503b1SLiam Girdwood }
456