xref: /openbmc/linux/sound/soc/sof/intel/hda-ctrl.c (revision ecfb9f40)
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 	u32 val;
162 
163 	/* enable/disable audio dsp clock gating */
164 	val = enable ? PCI_CGCTL_ADSPDCGE : 0;
165 	snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val);
166 
167 	/* enable/disable DMI Link L1 support */
168 	val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0;
169 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
170 				HDA_VS_INTEL_EM2_L1SEN, val);
171 
172 	/* enable/disable audio dsp power gating */
173 	val = enable ? 0 : PCI_PGCTL_ADSPPGD;
174 	snd_sof_pci_update_bits(sdev, PCI_PGCTL, PCI_PGCTL_ADSPPGD, val);
175 
176 	return 0;
177 }
178 
179 int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)
180 {
181 	struct hdac_bus *bus = sof_to_bus(sdev);
182 	struct hdac_stream *stream;
183 	int sd_offset, ret = 0;
184 
185 	if (bus->chip_init)
186 		return 0;
187 
188 	hda_codec_set_codec_wakeup(sdev, true);
189 
190 	hda_dsp_ctrl_misc_clock_gating(sdev, false);
191 
192 	/* reset HDA controller */
193 	ret = hda_dsp_ctrl_link_reset(sdev, true);
194 	if (ret < 0) {
195 		dev_err(sdev->dev, "error: failed to reset HDA controller\n");
196 		goto err;
197 	}
198 
199 	/* exit HDA controller reset */
200 	ret = hda_dsp_ctrl_link_reset(sdev, false);
201 	if (ret < 0) {
202 		dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
203 		goto err;
204 	}
205 
206 	hda_codec_detect_mask(sdev);
207 
208 	/* clear stream status */
209 	list_for_each_entry(stream, &bus->stream_list, list) {
210 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
211 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
212 				  sd_offset + SOF_HDA_ADSP_REG_SD_STS,
213 				  SOF_HDA_CL_DMA_SD_INT_MASK);
214 	}
215 
216 	/* clear WAKESTS */
217 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
218 			  SOF_HDA_WAKESTS_INT_MASK);
219 
220 	hda_codec_rirb_status_clear(sdev);
221 
222 	/* clear interrupt status register */
223 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
224 			  SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
225 
226 	hda_codec_init_cmd_io(sdev);
227 
228 	/* enable CIE and GIE interrupts */
229 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
230 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
231 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
232 
233 	/* program the position buffer */
234 	if (bus->use_posbuf && bus->posbuf.addr) {
235 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE,
236 				  (u32)bus->posbuf.addr);
237 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE,
238 				  upper_32_bits(bus->posbuf.addr));
239 	}
240 
241 	hda_bus_ml_reset_losidv(bus);
242 
243 	bus->chip_init = true;
244 
245 err:
246 	hda_dsp_ctrl_misc_clock_gating(sdev, true);
247 
248 	hda_codec_set_codec_wakeup(sdev, false);
249 
250 	return ret;
251 }
252 
253 void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev)
254 {
255 	struct hdac_bus *bus = sof_to_bus(sdev);
256 	struct hdac_stream *stream;
257 	int sd_offset;
258 
259 	if (!bus->chip_init)
260 		return;
261 
262 	/* disable interrupts in stream descriptor */
263 	list_for_each_entry(stream, &bus->stream_list, list) {
264 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
265 		snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
266 					sd_offset +
267 					SOF_HDA_ADSP_REG_SD_CTL,
268 					SOF_HDA_CL_DMA_SD_INT_MASK,
269 					0);
270 	}
271 
272 	/* disable SIE for all streams */
273 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
274 				SOF_HDA_INT_ALL_STREAM,	0);
275 
276 	/* disable controller CIE and GIE */
277 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
278 				SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
279 				0);
280 
281 	/* clear stream status */
282 	list_for_each_entry(stream, &bus->stream_list, list) {
283 		sd_offset = SOF_STREAM_SD_OFFSET(stream);
284 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
285 				  sd_offset + SOF_HDA_ADSP_REG_SD_STS,
286 				  SOF_HDA_CL_DMA_SD_INT_MASK);
287 	}
288 
289 	/* clear WAKESTS */
290 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
291 			  SOF_HDA_WAKESTS_INT_MASK);
292 
293 	hda_codec_rirb_status_clear(sdev);
294 
295 	/* clear interrupt status register */
296 	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
297 			  SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
298 
299 	hda_codec_stop_cmd_io(sdev);
300 
301 	/* disable position buffer */
302 	if (bus->use_posbuf && bus->posbuf.addr) {
303 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
304 				  SOF_HDA_ADSP_DPLBASE, 0);
305 		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
306 				  SOF_HDA_ADSP_DPUBASE, 0);
307 	}
308 
309 	bus->chip_init = false;
310 }
311