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) 2023 Advanced Micro Devices, Inc.
7 //
8 // Authors: Syed Saba Kareem <[email protected]>
9 //
10
11 /*
12 * Common file to be used by amd platforms
13 */
14
15 #include "amd.h"
16 #include <linux/acpi.h>
17 #include <linux/pci.h>
18 #include <linux/export.h>
19
20 #define ACP_RENOIR_PDM_ADDR 0x02
21 #define ACP_REMBRANDT_PDM_ADDR 0x03
22 #define ACP63_PDM_ADDR 0x02
23 #define ACP70_PDM_ADDR 0x02
24
acp_enable_interrupts(struct acp_dev_data * adata)25 void acp_enable_interrupts(struct acp_dev_data *adata)
26 {
27 struct acp_resource *rsrc = adata->rsrc;
28 u32 ext_intr_ctrl;
29
30 writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
31 ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
32 ext_intr_ctrl |= ACP_ERROR_MASK;
33 writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
34 }
35 EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON");
36
acp_disable_interrupts(struct acp_dev_data * adata)37 void acp_disable_interrupts(struct acp_dev_data *adata)
38 {
39 struct acp_resource *rsrc = adata->rsrc;
40
41 writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
42 writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
43 }
44 EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON");
45
set_acp_pdm_ring_buffer(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)46 static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
47 struct snd_soc_dai *dai)
48 {
49 struct snd_pcm_runtime *runtime = substream->runtime;
50 struct acp_stream *stream = runtime->private_data;
51 struct device *dev = dai->component->dev;
52 struct acp_dev_data *adata = dev_get_drvdata(dev);
53
54 u32 physical_addr, pdm_size, period_bytes;
55
56 period_bytes = frames_to_bytes(runtime, runtime->period_size);
57 pdm_size = frames_to_bytes(runtime, runtime->buffer_size);
58 physical_addr = stream->reg_offset + MEM_WINDOW_START;
59
60 /* Init ACP PDM Ring buffer */
61 writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
62 writel(pdm_size, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
63 writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
64 writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
65 }
66
set_acp_pdm_clk(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)67 static void set_acp_pdm_clk(struct snd_pcm_substream *substream,
68 struct snd_soc_dai *dai)
69 {
70 struct device *dev = dai->component->dev;
71 struct acp_dev_data *adata = dev_get_drvdata(dev);
72 unsigned int pdm_ctrl;
73
74 /* Enable default ACP PDM clk */
75 writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
76 pdm_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
77 pdm_ctrl |= PDM_MISC_CTRL_MASK;
78 writel(pdm_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
79 set_acp_pdm_ring_buffer(substream, dai);
80 }
81
restore_acp_pdm_params(struct snd_pcm_substream * substream,struct acp_dev_data * adata)82 void restore_acp_pdm_params(struct snd_pcm_substream *substream,
83 struct acp_dev_data *adata)
84 {
85 struct snd_soc_dai *dai;
86 struct snd_soc_pcm_runtime *soc_runtime;
87 u32 ext_int_ctrl;
88
89 soc_runtime = snd_soc_substream_to_rtd(substream);
90 dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
91 /* Programming channel mask and sampling rate */
92 writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
93 writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
94
95 /* Enabling ACP Pdm interuppts */
96 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
97 ext_int_ctrl |= PDM_DMA_INTR_MASK;
98 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
99 set_acp_pdm_clk(substream, dai);
100 }
101 EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON");
102
set_acp_i2s_dma_fifo(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)103 static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
104 struct snd_soc_dai *dai)
105 {
106 struct device *dev = dai->component->dev;
107 struct acp_dev_data *adata = dev_get_drvdata(dev);
108 struct acp_resource *rsrc = adata->rsrc;
109 struct acp_stream *stream = substream->runtime->private_data;
110 u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
111 u32 phy_addr, acp_fifo_addr, ext_int_ctrl;
112 unsigned int dir = substream->stream;
113
114 switch (dai->driver->id) {
115 case I2S_SP_INSTANCE:
116 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
117 reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata);
118 acp_fifo_addr = rsrc->sram_pte_offset +
119 SP_PB_FIFO_ADDR_OFFSET;
120 reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
121 reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
122 phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
123 writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata));
124 } else {
125 reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata);
126 acp_fifo_addr = rsrc->sram_pte_offset +
127 SP_CAPT_FIFO_ADDR_OFFSET;
128 reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
129 reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
130 phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
131 writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata));
132 }
133 break;
134 case I2S_BT_INSTANCE:
135 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
136 reg_dma_size = ACP_BT_TX_DMA_SIZE(adata);
137 acp_fifo_addr = rsrc->sram_pte_offset +
138 BT_PB_FIFO_ADDR_OFFSET;
139 reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
140 reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
141 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
142 writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata));
143 } else {
144 reg_dma_size = ACP_BT_RX_DMA_SIZE(adata);
145 acp_fifo_addr = rsrc->sram_pte_offset +
146 BT_CAPT_FIFO_ADDR_OFFSET;
147 reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
148 reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
149 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
150 writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata));
151 }
152 break;
153 case I2S_HS_INSTANCE:
154 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
155 reg_dma_size = ACP_HS_TX_DMA_SIZE;
156 acp_fifo_addr = rsrc->sram_pte_offset +
157 HS_PB_FIFO_ADDR_OFFSET;
158 reg_fifo_addr = ACP_HS_TX_FIFOADDR;
159 reg_fifo_size = ACP_HS_TX_FIFOSIZE;
160 phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
161 writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
162 } else {
163 reg_dma_size = ACP_HS_RX_DMA_SIZE;
164 acp_fifo_addr = rsrc->sram_pte_offset +
165 HS_CAPT_FIFO_ADDR_OFFSET;
166 reg_fifo_addr = ACP_HS_RX_FIFOADDR;
167 reg_fifo_size = ACP_HS_RX_FIFOSIZE;
168 phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
169 writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
170 }
171 break;
172 default:
173 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
174 return -EINVAL;
175 }
176
177 writel(DMA_SIZE, adata->acp_base + reg_dma_size);
178 writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
179 writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
180
181 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
182 ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
183 BIT(BT_RX_THRESHOLD(rsrc->offset)) |
184 BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
185 BIT(BT_TX_THRESHOLD(rsrc->offset)) |
186 BIT(HS_RX_THRESHOLD(rsrc->offset)) |
187 BIT(HS_TX_THRESHOLD(rsrc->offset));
188
189 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
190 return 0;
191 }
192
restore_acp_i2s_params(struct snd_pcm_substream * substream,struct acp_dev_data * adata,struct acp_stream * stream)193 int restore_acp_i2s_params(struct snd_pcm_substream *substream,
194 struct acp_dev_data *adata,
195 struct acp_stream *stream)
196 {
197 struct snd_soc_dai *dai;
198 struct snd_soc_pcm_runtime *soc_runtime;
199 u32 tdm_fmt, reg_val, fmt_reg, val;
200
201 soc_runtime = snd_soc_substream_to_rtd(substream);
202 dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
203 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
204 tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1];
205 switch (stream->dai_id) {
206 case I2S_BT_INSTANCE:
207 reg_val = ACP_BTTDM_ITER;
208 fmt_reg = ACP_BTTDM_TXFRMT;
209 break;
210 case I2S_SP_INSTANCE:
211 reg_val = ACP_I2STDM_ITER;
212 fmt_reg = ACP_I2STDM_TXFRMT;
213 break;
214 case I2S_HS_INSTANCE:
215 reg_val = ACP_HSTDM_ITER;
216 fmt_reg = ACP_HSTDM_TXFRMT;
217 break;
218 default:
219 pr_err("Invalid dai id %x\n", stream->dai_id);
220 return -EINVAL;
221 }
222 val = adata->xfer_tx_resolution[stream->dai_id - 1] << 3;
223 } else {
224 tdm_fmt = adata->tdm_rx_fmt[stream->dai_id - 1];
225 switch (stream->dai_id) {
226 case I2S_BT_INSTANCE:
227 reg_val = ACP_BTTDM_IRER;
228 fmt_reg = ACP_BTTDM_RXFRMT;
229 break;
230 case I2S_SP_INSTANCE:
231 reg_val = ACP_I2STDM_IRER;
232 fmt_reg = ACP_I2STDM_RXFRMT;
233 break;
234 case I2S_HS_INSTANCE:
235 reg_val = ACP_HSTDM_IRER;
236 fmt_reg = ACP_HSTDM_RXFRMT;
237 break;
238 default:
239 pr_err("Invalid dai id %x\n", stream->dai_id);
240 return -EINVAL;
241 }
242 val = adata->xfer_rx_resolution[stream->dai_id - 1] << 3;
243 }
244 writel(val, adata->acp_base + reg_val);
245 if (adata->tdm_mode == TDM_ENABLE) {
246 writel(tdm_fmt, adata->acp_base + fmt_reg);
247 val = readl(adata->acp_base + reg_val);
248 writel(val | 0x2, adata->acp_base + reg_val);
249 }
250 return set_acp_i2s_dma_fifo(substream, dai);
251 }
252 EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, "SND_SOC_ACP_COMMON");
253
acp_power_on(struct acp_chip_info * chip)254 static int acp_power_on(struct acp_chip_info *chip)
255 {
256 u32 val, acp_pgfsm_stat_reg, acp_pgfsm_ctrl_reg;
257 void __iomem *base;
258
259 base = chip->base;
260 switch (chip->acp_rev) {
261 case ACP_RN_PCI_ID:
262 acp_pgfsm_stat_reg = ACP_PGFSM_STATUS;
263 acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL;
264 break;
265 case ACP_RMB_PCI_ID:
266 acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS;
267 acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL;
268 break;
269 case ACP63_PCI_ID:
270 acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS;
271 acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL;
272 break;
273 case ACP70_PCI_ID:
274 case ACP71_PCI_ID:
275 acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS;
276 acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL;
277 break;
278 default:
279 return -EINVAL;
280 }
281
282 val = readl(base + acp_pgfsm_stat_reg);
283 if (val == ACP_POWERED_ON)
284 return 0;
285
286 if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS)
287 writel(ACP_PGFSM_CNTL_POWER_ON_MASK, base + acp_pgfsm_ctrl_reg);
288
289 return readl_poll_timeout(base + acp_pgfsm_stat_reg, val,
290 !val, DELAY_US, ACP_TIMEOUT);
291 }
292
acp_reset(void __iomem * base)293 static int acp_reset(void __iomem *base)
294 {
295 u32 val;
296 int ret;
297
298 writel(1, base + ACP_SOFT_RESET);
299 ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK,
300 DELAY_US, ACP_TIMEOUT);
301 if (ret)
302 return ret;
303
304 writel(0, base + ACP_SOFT_RESET);
305 return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
306 }
307
acp_init(struct acp_chip_info * chip)308 int acp_init(struct acp_chip_info *chip)
309 {
310 int ret;
311
312 /* power on */
313 ret = acp_power_on(chip);
314 if (ret) {
315 pr_err("ACP power on failed\n");
316 return ret;
317 }
318 writel(0x01, chip->base + ACP_CONTROL);
319
320 /* Reset */
321 ret = acp_reset(chip->base);
322 if (ret) {
323 pr_err("ACP reset failed\n");
324 return ret;
325 }
326 if (chip->acp_rev >= ACP70_PCI_ID)
327 writel(0, chip->base + ACP_ZSC_DSP_CTRL);
328 return 0;
329 }
330 EXPORT_SYMBOL_NS_GPL(acp_init, "SND_SOC_ACP_COMMON");
331
acp_deinit(struct acp_chip_info * chip)332 int acp_deinit(struct acp_chip_info *chip)
333 {
334 int ret;
335
336 /* Reset */
337 ret = acp_reset(chip->base);
338 if (ret)
339 return ret;
340
341 if (chip->acp_rev < ACP70_PCI_ID)
342 writel(0, chip->base + ACP_CONTROL);
343 else
344 writel(0x01, chip->base + ACP_ZSC_DSP_CTRL);
345 return 0;
346 }
347 EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON");
348
smn_write(struct pci_dev * dev,u32 smn_addr,u32 data)349 int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
350 {
351 pci_write_config_dword(dev, 0x60, smn_addr);
352 pci_write_config_dword(dev, 0x64, data);
353 return 0;
354 }
355 EXPORT_SYMBOL_NS_GPL(smn_write, "SND_SOC_ACP_COMMON");
356
smn_read(struct pci_dev * dev,u32 smn_addr)357 int smn_read(struct pci_dev *dev, u32 smn_addr)
358 {
359 u32 data;
360
361 pci_write_config_dword(dev, 0x60, smn_addr);
362 pci_read_config_dword(dev, 0x64, &data);
363 return data;
364 }
365 EXPORT_SYMBOL_NS_GPL(smn_read, "SND_SOC_ACP_COMMON");
366
check_acp3x_config(struct acp_chip_info * chip)367 static void check_acp3x_config(struct acp_chip_info *chip)
368 {
369 u32 val;
370
371 val = readl(chip->base + ACP3X_PIN_CONFIG);
372 switch (val) {
373 case ACP_CONFIG_4:
374 chip->is_i2s_config = true;
375 chip->is_pdm_config = true;
376 break;
377 default:
378 chip->is_pdm_config = true;
379 break;
380 }
381 }
382
check_acp6x_config(struct acp_chip_info * chip)383 static void check_acp6x_config(struct acp_chip_info *chip)
384 {
385 u32 val;
386
387 val = readl(chip->base + ACP_PIN_CONFIG);
388 switch (val) {
389 case ACP_CONFIG_4:
390 case ACP_CONFIG_5:
391 case ACP_CONFIG_6:
392 case ACP_CONFIG_7:
393 case ACP_CONFIG_8:
394 case ACP_CONFIG_11:
395 case ACP_CONFIG_14:
396 chip->is_pdm_config = true;
397 break;
398 case ACP_CONFIG_9:
399 chip->is_i2s_config = true;
400 break;
401 case ACP_CONFIG_10:
402 case ACP_CONFIG_12:
403 case ACP_CONFIG_13:
404 chip->is_i2s_config = true;
405 chip->is_pdm_config = true;
406 break;
407 default:
408 break;
409 }
410 }
411
check_acp70_config(struct acp_chip_info * chip)412 static void check_acp70_config(struct acp_chip_info *chip)
413 {
414 u32 val;
415
416 val = readl(chip->base + ACP_PIN_CONFIG);
417 switch (val) {
418 case ACP_CONFIG_4:
419 case ACP_CONFIG_5:
420 case ACP_CONFIG_6:
421 case ACP_CONFIG_7:
422 case ACP_CONFIG_8:
423 case ACP_CONFIG_11:
424 case ACP_CONFIG_14:
425 case ACP_CONFIG_17:
426 case ACP_CONFIG_18:
427 chip->is_pdm_config = true;
428 break;
429 case ACP_CONFIG_9:
430 chip->is_i2s_config = true;
431 break;
432 case ACP_CONFIG_10:
433 case ACP_CONFIG_12:
434 case ACP_CONFIG_13:
435 case ACP_CONFIG_19:
436 case ACP_CONFIG_20:
437 chip->is_i2s_config = true;
438 chip->is_pdm_config = true;
439 break;
440 default:
441 break;
442 }
443 }
444
check_acp_config(struct pci_dev * pci,struct acp_chip_info * chip)445 void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
446 {
447 struct acpi_device *pdm_dev;
448 const union acpi_object *obj;
449 acpi_handle handle;
450 acpi_integer dmic_status;
451 u32 pdm_addr, ret;
452
453 switch (chip->acp_rev) {
454 case ACP_RN_PCI_ID:
455 pdm_addr = ACP_RENOIR_PDM_ADDR;
456 check_acp3x_config(chip);
457 break;
458 case ACP_RMB_PCI_ID:
459 pdm_addr = ACP_REMBRANDT_PDM_ADDR;
460 check_acp6x_config(chip);
461 break;
462 case ACP63_PCI_ID:
463 pdm_addr = ACP63_PDM_ADDR;
464 check_acp6x_config(chip);
465 break;
466 case ACP70_PCI_ID:
467 case ACP71_PCI_ID:
468 pdm_addr = ACP70_PDM_ADDR;
469 check_acp70_config(chip);
470 break;
471 default:
472 break;
473 }
474
475 if (chip->is_pdm_config) {
476 pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0);
477 if (pdm_dev) {
478 if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
479 ACPI_TYPE_INTEGER, &obj) &&
480 obj->integer.value == pdm_addr)
481 chip->is_pdm_dev = true;
482 }
483
484 handle = ACPI_HANDLE(&pci->dev);
485 ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
486 if (!ACPI_FAILURE(ret))
487 chip->is_pdm_dev = dmic_status;
488 }
489 }
490 EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON");
491
492 MODULE_DESCRIPTION("AMD ACP legacy common features");
493 MODULE_LICENSE("Dual BSD/GPL");
494