xref: /openbmc/linux/sound/soc/sof/intel/hda-ctrl.c (revision fa8c052b)
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 	usleep_range(500, 1000);
202 
203 	/* exit HDA controller reset */
204 	ret = hda_dsp_ctrl_link_reset(sdev, false);
205 	if (ret < 0) {
206 		dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
207 		goto err;
208 	}
209 	usleep_range(1000, 1200);
210 
211 	hda_codec_detect_mask(sdev);
212 
213 	/* clear stream status */
214 	list_for_each_entry(stream, &bus->stream_list, list) {
215 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
216 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
217 				  sd_offset + SOF_HDA_ADSP_REG_SD_STS,
218 				  SOF_HDA_CL_DMA_SD_INT_MASK);
219 	}
220 
221 	/* clear WAKESTS */
222 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
223 			  SOF_HDA_WAKESTS_INT_MASK);
224 
225 	hda_codec_rirb_status_clear(sdev);
226 
227 	/* clear interrupt status register */
228 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
229 			  SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
230 
231 	hda_codec_init_cmd_io(sdev);
232 
233 	/* enable CIE and GIE interrupts */
234 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
235 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
236 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
237 
238 	/* program the position buffer */
239 	if (bus->use_posbuf && bus->posbuf.addr) {
240 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE,
241 				  (u32)bus->posbuf.addr);
242 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE,
243 				  upper_32_bits(bus->posbuf.addr));
244 	}
245 
246 	hda_bus_ml_reset_losidv(bus);
247 
248 	bus->chip_init = true;
249 
250 err:
251 	hda_dsp_ctrl_misc_clock_gating(sdev, true);
252 
253 	hda_codec_set_codec_wakeup(sdev, false);
254 
255 	return ret;
256 }
257 
258 void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev)
259 {
260 	struct hdac_bus *bus = sof_to_bus(sdev);
261 	struct hdac_stream *stream;
262 	int sd_offset;
263 
264 	if (!bus->chip_init)
265 		return;
266 
267 	/* disable interrupts in stream descriptor */
268 	list_for_each_entry(stream, &bus->stream_list, list) {
269 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
270 		snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
271 					sd_offset +
272 					SOF_HDA_ADSP_REG_SD_CTL,
273 					SOF_HDA_CL_DMA_SD_INT_MASK,
274 					0);
275 	}
276 
277 	/* disable SIE for all streams */
278 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
279 				SOF_HDA_INT_ALL_STREAM,	0);
280 
281 	/* disable controller CIE and GIE */
282 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
283 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
284 				0);
285 
286 	/* clear stream status */
287 	list_for_each_entry(stream, &bus->stream_list, list) {
288 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
289 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
290 				  sd_offset + SOF_HDA_ADSP_REG_SD_STS,
291 				  SOF_HDA_CL_DMA_SD_INT_MASK);
292 	}
293 
294 	/* clear WAKESTS */
295 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
296 			  SOF_HDA_WAKESTS_INT_MASK);
297 
298 	hda_codec_rirb_status_clear(sdev);
299 
300 	/* clear interrupt status register */
301 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
302 			  SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
303 
304 	hda_codec_stop_cmd_io(sdev);
305 
306 	/* disable position buffer */
307 	if (bus->use_posbuf && bus->posbuf.addr) {
308 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
309 				  SOF_HDA_ADSP_DPLBASE, 0);
310 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
311 				  SOF_HDA_ADSP_DPUBASE, 0);
312 	}
313 
314 	bus->chip_init = false;
315 }
316