xref: /linux/sound/soc/sof/intel/hda-ctrl.c (revision 11f45690b3f6c6a2b5c57dbb036df3f838f7c016)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
7 //
8 // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //	    Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
10 //	    Rander Wang <rander.wang@intel.com>
11 //          Keyon Jie <yang.jie@linux.intel.com>
12 //
13 
14 /*
15  * Hardware interface for generic Intel audio DSP HDA IP
16  */
17 
18 #include <linux/module.h>
19 #include <sound/hdaudio_ext.h>
20 #include <sound/hda_register.h>
21 #include <sound/hda_component.h>
22 #include "../ops.h"
23 #include "hda.h"
24 
25 /*
26  * HDA Operations.
27  */
28 
29 int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev, bool reset)
30 {
31 	unsigned long timeout;
32 	u32 gctl = 0;
33 	u32 val;
34 
35 	/* 0 to enter reset and 1 to exit reset */
36 	val = reset ? 0 : SOF_HDA_GCTL_RESET;
37 
38 	/* enter/exit HDA controller reset */
39 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL,
40 				SOF_HDA_GCTL_RESET, val);
41 
42 	/* wait to enter/exit reset */
43 	timeout = jiffies + msecs_to_jiffies(HDA_DSP_CTRL_RESET_TIMEOUT);
44 	while (time_before(jiffies, timeout)) {
45 		gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL);
46 		if ((gctl & SOF_HDA_GCTL_RESET) == val)
47 			return 0;
48 		usleep_range(500, 1000);
49 	}
50 
51 	/* enter/exit reset failed */
52 	dev_err(sdev->dev, "error: failed to %s HDA controller gctl 0x%x\n",
53 		reset ? "reset" : "ready", gctl);
54 	return -EIO;
55 }
56 
57 int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev)
58 {
59 	struct hdac_bus *bus = sof_to_bus(sdev);
60 	u32 cap, offset, feature;
61 	int count = 0;
62 	int ret;
63 
64 	/*
65 	 * On some devices, one reset cycle is necessary before reading
66 	 * capabilities
67 	 */
68 	ret = hda_dsp_ctrl_link_reset(sdev, true);
69 	if (ret < 0)
70 		return ret;
71 	ret = hda_dsp_ctrl_link_reset(sdev, false);
72 	if (ret < 0)
73 		return ret;
74 
75 	offset = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_LLCH);
76 
77 	do {
78 		dev_dbg(sdev->dev, "checking for capabilities at offset 0x%x\n",
79 			offset & SOF_HDA_CAP_NEXT_MASK);
80 
81 		cap = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, offset);
82 
83 		if (cap == -1) {
84 			dev_dbg(bus->dev, "Invalid capability reg read\n");
85 			break;
86 		}
87 
88 		feature = (cap & SOF_HDA_CAP_ID_MASK) >> SOF_HDA_CAP_ID_OFF;
89 
90 		switch (feature) {
91 		case SOF_HDA_PP_CAP_ID:
92 			dev_dbg(sdev->dev, "found DSP capability at 0x%x\n",
93 				offset);
94 			bus->ppcap = bus->remap_addr + offset;
95 			sdev->bar[HDA_DSP_PP_BAR] = bus->ppcap;
96 			break;
97 		case SOF_HDA_SPIB_CAP_ID:
98 			dev_dbg(sdev->dev, "found SPIB capability at 0x%x\n",
99 				offset);
100 			bus->spbcap = bus->remap_addr + offset;
101 			sdev->bar[HDA_DSP_SPIB_BAR] = bus->spbcap;
102 			break;
103 		case SOF_HDA_DRSM_CAP_ID:
104 			dev_dbg(sdev->dev, "found DRSM capability at 0x%x\n",
105 				offset);
106 			bus->drsmcap = bus->remap_addr + offset;
107 			sdev->bar[HDA_DSP_DRSM_BAR] = bus->drsmcap;
108 			break;
109 		case SOF_HDA_GTS_CAP_ID:
110 			dev_dbg(sdev->dev, "found GTS capability at 0x%x\n",
111 				offset);
112 			bus->gtscap = bus->remap_addr + offset;
113 			break;
114 		case SOF_HDA_ML_CAP_ID:
115 			dev_dbg(sdev->dev, "found ML capability at 0x%x\n",
116 				offset);
117 			bus->mlcap = bus->remap_addr + offset;
118 			break;
119 		default:
120 			dev_dbg(sdev->dev, "found capability %d at 0x%x\n",
121 				feature, offset);
122 			break;
123 		}
124 
125 		offset = cap & SOF_HDA_CAP_NEXT_MASK;
126 	} while (count++ <= SOF_HDA_MAX_CAPS && offset);
127 
128 	return 0;
129 }
130 
131 void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable)
132 {
133 	u32 val = enable ? SOF_HDA_PPCTL_GPROCEN : 0;
134 
135 	snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
136 				SOF_HDA_PPCTL_GPROCEN, val);
137 }
138 
139 void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable)
140 {
141 	u32 val	= enable ? SOF_HDA_PPCTL_PIE : 0;
142 
143 	snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
144 				SOF_HDA_PPCTL_PIE, val);
145 }
146 
147 void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable)
148 {
149 	u32 val = enable ? PCI_CGCTL_MISCBDCGE_MASK : 0;
150 
151 	snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_MISCBDCGE_MASK, val);
152 }
153 
154 /*
155  * enable/disable audio dsp clock gating and power gating bits.
156  * This allows the HW to opportunistically power and clock gate
157  * the audio dsp when it is idle
158  */
159 int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable)
160 {
161 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
162 	u32 val;
163 
164 	/* enable/disable audio dsp clock gating */
165 	val = enable ? PCI_CGCTL_ADSPDCGE : 0;
166 	snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val);
167 
168 	/* disable the DMI link when requested. But enable only if it wasn't disabled previously */
169 	val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0;
170 	if (!enable || !hda->l1_disabled)
171 		snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
172 					HDA_VS_INTEL_EM2_L1SEN, val);
173 
174 	/* enable/disable audio dsp power gating */
175 	val = enable ? 0 : PCI_PGCTL_ADSPPGD;
176 	snd_sof_pci_update_bits(sdev, PCI_PGCTL, PCI_PGCTL_ADSPPGD, val);
177 
178 	return 0;
179 }
180 
181 int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)
182 {
183 	struct hdac_bus *bus = sof_to_bus(sdev);
184 	struct hdac_stream *stream;
185 	int sd_offset, ret = 0;
186 
187 	if (bus->chip_init)
188 		return 0;
189 
190 	hda_codec_set_codec_wakeup(sdev, true);
191 
192 	hda_dsp_ctrl_misc_clock_gating(sdev, false);
193 
194 	/* reset HDA controller */
195 	ret = hda_dsp_ctrl_link_reset(sdev, true);
196 	if (ret < 0) {
197 		dev_err(sdev->dev, "error: failed to reset HDA controller\n");
198 		goto err;
199 	}
200 
201 	/* exit HDA controller reset */
202 	ret = hda_dsp_ctrl_link_reset(sdev, false);
203 	if (ret < 0) {
204 		dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
205 		goto err;
206 	}
207 
208 	hda_codec_detect_mask(sdev);
209 
210 	/* clear stream status */
211 	list_for_each_entry(stream, &bus->stream_list, list) {
212 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
213 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
214 				  sd_offset + SOF_HDA_ADSP_REG_SD_STS,
215 				  SOF_HDA_CL_DMA_SD_INT_MASK);
216 	}
217 
218 	/* clear WAKESTS */
219 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
220 			  SOF_HDA_WAKESTS_INT_MASK);
221 
222 	hda_codec_rirb_status_clear(sdev);
223 
224 	/* clear interrupt status register */
225 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
226 			  SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
227 
228 	hda_codec_init_cmd_io(sdev);
229 
230 	/* enable CIE and GIE interrupts */
231 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
232 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
233 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
234 
235 	/* program the position buffer */
236 	if (bus->use_posbuf && bus->posbuf.addr) {
237 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE,
238 				  (u32)bus->posbuf.addr);
239 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE,
240 				  upper_32_bits(bus->posbuf.addr));
241 	}
242 
243 	hda_bus_ml_reset_losidv(bus);
244 
245 	bus->chip_init = true;
246 
247 err:
248 	hda_dsp_ctrl_misc_clock_gating(sdev, true);
249 
250 	hda_codec_set_codec_wakeup(sdev, false);
251 
252 	return ret;
253 }
254 
255 void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev)
256 {
257 	struct hdac_bus *bus = sof_to_bus(sdev);
258 	struct hdac_stream *stream;
259 	int sd_offset;
260 
261 	if (!bus->chip_init)
262 		return;
263 
264 	/* disable interrupts in stream descriptor */
265 	list_for_each_entry(stream, &bus->stream_list, list) {
266 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
267 		snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
268 					sd_offset +
269 					SOF_HDA_ADSP_REG_SD_CTL,
270 					SOF_HDA_CL_DMA_SD_INT_MASK,
271 					0);
272 	}
273 
274 	/* disable SIE for all streams */
275 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
276 				SOF_HDA_INT_ALL_STREAM,	0);
277 
278 	/* disable controller CIE and GIE */
279 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
280 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
281 				0);
282 
283 	/* clear stream status */
284 	list_for_each_entry(stream, &bus->stream_list, list) {
285 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
286 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
287 				  sd_offset + SOF_HDA_ADSP_REG_SD_STS,
288 				  SOF_HDA_CL_DMA_SD_INT_MASK);
289 	}
290 
291 	/* clear WAKESTS */
292 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
293 			  SOF_HDA_WAKESTS_INT_MASK);
294 
295 	hda_codec_rirb_status_clear(sdev);
296 
297 	/* clear interrupt status register */
298 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
299 			  SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
300 
301 	hda_codec_stop_cmd_io(sdev);
302 
303 	/* disable position buffer */
304 	if (bus->use_posbuf && bus->posbuf.addr) {
305 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
306 				  SOF_HDA_ADSP_DPLBASE, 0);
307 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
308 				  SOF_HDA_ADSP_DPUBASE, 0);
309 	}
310 
311 	bus->chip_init = false;
312 }
313