xref: /openbmc/linux/sound/soc/amd/acp/acp-i2s.c (revision 1ed1f6be)
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) 2021 Advanced Micro Devices, Inc.
7 //
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9 //
10 
11 /*
12  * Generic Hardware interface for ACP Audio I2S controller
13  */
14 
15 #include <linux/platform_device.h>
16 #include <linux/module.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/soc-dai.h>
22 #include <linux/dma-mapping.h>
23 
24 #include "amd.h"
25 
26 #define DRV_NAME "acp_i2s_playcap"
27 
28 static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
29 			    struct snd_soc_dai *dai)
30 {
31 	struct device *dev = dai->component->dev;
32 	struct acp_dev_data *adata;
33 	struct acp_resource *rsrc;
34 	u32 val;
35 	u32 xfer_resolution;
36 	u32 reg_val;
37 	u32 lrclk_div_val, bclk_div_val;
38 
39 	adata = snd_soc_dai_get_drvdata(dai);
40 	rsrc = adata->rsrc;
41 
42 	/* These values are as per Hardware Spec */
43 	switch (params_format(params)) {
44 	case SNDRV_PCM_FORMAT_U8:
45 	case SNDRV_PCM_FORMAT_S8:
46 		xfer_resolution = 0x0;
47 		break;
48 	case SNDRV_PCM_FORMAT_S16_LE:
49 		xfer_resolution = 0x02;
50 		break;
51 	case SNDRV_PCM_FORMAT_S24_LE:
52 		xfer_resolution = 0x04;
53 		break;
54 	case SNDRV_PCM_FORMAT_S32_LE:
55 		xfer_resolution = 0x05;
56 		break;
57 	default:
58 		return -EINVAL;
59 	}
60 
61 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
62 		switch (dai->driver->id) {
63 		case I2S_BT_INSTANCE:
64 			reg_val = ACP_BTTDM_ITER;
65 			break;
66 		case I2S_SP_INSTANCE:
67 			reg_val = ACP_I2STDM_ITER;
68 			break;
69 		case I2S_HS_INSTANCE:
70 			reg_val = ACP_HSTDM_ITER;
71 			break;
72 		default:
73 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
74 			return -EINVAL;
75 		}
76 	} else {
77 		switch (dai->driver->id) {
78 		case I2S_BT_INSTANCE:
79 			reg_val = ACP_BTTDM_IRER;
80 			break;
81 		case I2S_SP_INSTANCE:
82 			reg_val = ACP_I2STDM_IRER;
83 			break;
84 		case I2S_HS_INSTANCE:
85 			reg_val = ACP_HSTDM_IRER;
86 			break;
87 		default:
88 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
89 			return -EINVAL;
90 		}
91 	}
92 
93 	val = readl(adata->acp_base + reg_val);
94 	val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
95 	val = val | (xfer_resolution  << 3);
96 	writel(val, adata->acp_base + reg_val);
97 
98 	if (rsrc->soc_mclk) {
99 		switch (params_format(params)) {
100 		case SNDRV_PCM_FORMAT_S16_LE:
101 			switch (params_rate(params)) {
102 			case 8000:
103 				bclk_div_val = 768;
104 				break;
105 			case 16000:
106 				bclk_div_val = 384;
107 				break;
108 			case 24000:
109 				bclk_div_val = 256;
110 				break;
111 			case 32000:
112 				bclk_div_val = 192;
113 				break;
114 			case 44100:
115 			case 48000:
116 				bclk_div_val = 128;
117 				break;
118 			case 88200:
119 			case 96000:
120 				bclk_div_val = 64;
121 				break;
122 			case 192000:
123 				bclk_div_val = 32;
124 				break;
125 			default:
126 				return -EINVAL;
127 			}
128 			lrclk_div_val = 32;
129 			break;
130 		case SNDRV_PCM_FORMAT_S32_LE:
131 			switch (params_rate(params)) {
132 			case 8000:
133 				bclk_div_val = 384;
134 				break;
135 			case 16000:
136 				bclk_div_val = 192;
137 				break;
138 			case 24000:
139 				bclk_div_val = 128;
140 				break;
141 			case 32000:
142 				bclk_div_val = 96;
143 				break;
144 			case 44100:
145 			case 48000:
146 				bclk_div_val = 64;
147 				break;
148 			case 88200:
149 			case 96000:
150 				bclk_div_val = 32;
151 				break;
152 			case 192000:
153 				bclk_div_val = 16;
154 				break;
155 			default:
156 				return -EINVAL;
157 			}
158 			lrclk_div_val = 64;
159 			break;
160 		default:
161 			return -EINVAL;
162 		}
163 		adata->lrclk_div = lrclk_div_val;
164 		adata->bclk_div = bclk_div_val;
165 	}
166 	return 0;
167 }
168 
169 static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
170 {
171 	struct acp_stream *stream = substream->runtime->private_data;
172 	struct device *dev = dai->component->dev;
173 	struct acp_dev_data *adata = dev_get_drvdata(dev);
174 	struct acp_resource *rsrc = adata->rsrc;
175 	u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
176 
177 	period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
178 	buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
179 
180 	switch (cmd) {
181 	case SNDRV_PCM_TRIGGER_START:
182 	case SNDRV_PCM_TRIGGER_RESUME:
183 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
184 		stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
185 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
186 			switch (dai->driver->id) {
187 			case I2S_BT_INSTANCE:
188 				water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
189 				reg_val = ACP_BTTDM_ITER;
190 				ier_val = ACP_BTTDM_IER;
191 				buf_reg = ACP_BT_TX_RINGBUFSIZE;
192 				break;
193 			case I2S_SP_INSTANCE:
194 				water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
195 				reg_val = ACP_I2STDM_ITER;
196 				ier_val = ACP_I2STDM_IER;
197 				buf_reg = ACP_I2S_TX_RINGBUFSIZE;
198 				break;
199 			case I2S_HS_INSTANCE:
200 				water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
201 				reg_val = ACP_HSTDM_ITER;
202 				ier_val = ACP_HSTDM_IER;
203 				buf_reg = ACP_HS_TX_RINGBUFSIZE;
204 				break;
205 			default:
206 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
207 				return -EINVAL;
208 			}
209 		} else {
210 			switch (dai->driver->id) {
211 			case I2S_BT_INSTANCE:
212 				water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
213 				reg_val = ACP_BTTDM_IRER;
214 				ier_val = ACP_BTTDM_IER;
215 				buf_reg = ACP_BT_RX_RINGBUFSIZE;
216 				break;
217 			case I2S_SP_INSTANCE:
218 				water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
219 				reg_val = ACP_I2STDM_IRER;
220 				ier_val = ACP_I2STDM_IER;
221 				buf_reg = ACP_I2S_RX_RINGBUFSIZE;
222 				break;
223 			case I2S_HS_INSTANCE:
224 				water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
225 				reg_val = ACP_HSTDM_IRER;
226 				ier_val = ACP_HSTDM_IER;
227 				buf_reg = ACP_HS_RX_RINGBUFSIZE;
228 				break;
229 			default:
230 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
231 				return -EINVAL;
232 			}
233 		}
234 		writel(period_bytes, adata->acp_base + water_val);
235 		writel(buf_size, adata->acp_base + buf_reg);
236 		val = readl(adata->acp_base + reg_val);
237 		val = val | BIT(0);
238 		writel(val, adata->acp_base + reg_val);
239 		writel(1, adata->acp_base + ier_val);
240 		if (rsrc->soc_mclk)
241 			acp_set_i2s_clk(adata, dai->driver->id);
242 		return 0;
243 	case SNDRV_PCM_TRIGGER_STOP:
244 	case SNDRV_PCM_TRIGGER_SUSPEND:
245 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
246 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
247 			switch (dai->driver->id) {
248 			case I2S_BT_INSTANCE:
249 				reg_val = ACP_BTTDM_ITER;
250 				break;
251 			case I2S_SP_INSTANCE:
252 				reg_val = ACP_I2STDM_ITER;
253 				break;
254 			case I2S_HS_INSTANCE:
255 				reg_val = ACP_HSTDM_ITER;
256 				break;
257 			default:
258 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
259 				return -EINVAL;
260 			}
261 
262 		} else {
263 			switch (dai->driver->id) {
264 			case I2S_BT_INSTANCE:
265 				reg_val = ACP_BTTDM_IRER;
266 				break;
267 			case I2S_SP_INSTANCE:
268 				reg_val = ACP_I2STDM_IRER;
269 				break;
270 			case I2S_HS_INSTANCE:
271 				reg_val = ACP_HSTDM_IRER;
272 				break;
273 			default:
274 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
275 				return -EINVAL;
276 			}
277 		}
278 		val = readl(adata->acp_base + reg_val);
279 		val = val & ~BIT(0);
280 		writel(val, adata->acp_base + reg_val);
281 
282 		if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
283 		    !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
284 			writel(0, adata->acp_base + ACP_BTTDM_IER);
285 		if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
286 		    !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
287 			writel(0, adata->acp_base + ACP_I2STDM_IER);
288 		if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
289 		    !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
290 			writel(0, adata->acp_base + ACP_HSTDM_IER);
291 		return 0;
292 	default:
293 		return -EINVAL;
294 	}
295 
296 	return 0;
297 }
298 
299 static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
300 {
301 	struct device *dev = dai->component->dev;
302 	struct acp_dev_data *adata = dev_get_drvdata(dev);
303 	struct acp_resource *rsrc = adata->rsrc;
304 	struct acp_stream *stream = substream->runtime->private_data;
305 	u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
306 	u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
307 	unsigned int dir = substream->stream;
308 
309 	switch (dai->driver->id) {
310 	case I2S_SP_INSTANCE:
311 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
312 			reg_dma_size = ACP_I2S_TX_DMA_SIZE;
313 			acp_fifo_addr = rsrc->sram_pte_offset +
314 						SP_PB_FIFO_ADDR_OFFSET;
315 			reg_fifo_addr =	ACP_I2S_TX_FIFOADDR;
316 			reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
317 
318 			phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
319 			writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
320 		} else {
321 			reg_dma_size = ACP_I2S_RX_DMA_SIZE;
322 			acp_fifo_addr = rsrc->sram_pte_offset +
323 						SP_CAPT_FIFO_ADDR_OFFSET;
324 			reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
325 			reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
326 			phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
327 			writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
328 		}
329 		break;
330 	case I2S_BT_INSTANCE:
331 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
332 			reg_dma_size = ACP_BT_TX_DMA_SIZE;
333 			acp_fifo_addr = rsrc->sram_pte_offset +
334 						BT_PB_FIFO_ADDR_OFFSET;
335 			reg_fifo_addr = ACP_BT_TX_FIFOADDR;
336 			reg_fifo_size = ACP_BT_TX_FIFOSIZE;
337 
338 			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
339 			writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
340 		} else {
341 			reg_dma_size = ACP_BT_RX_DMA_SIZE;
342 			acp_fifo_addr = rsrc->sram_pte_offset +
343 						BT_CAPT_FIFO_ADDR_OFFSET;
344 			reg_fifo_addr = ACP_BT_RX_FIFOADDR;
345 			reg_fifo_size = ACP_BT_RX_FIFOSIZE;
346 
347 			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
348 			writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
349 		}
350 		break;
351 	case I2S_HS_INSTANCE:
352 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
353 			reg_dma_size = ACP_HS_TX_DMA_SIZE;
354 			acp_fifo_addr = rsrc->sram_pte_offset +
355 				HS_PB_FIFO_ADDR_OFFSET;
356 			reg_fifo_addr = ACP_HS_TX_FIFOADDR;
357 			reg_fifo_size = ACP_HS_TX_FIFOSIZE;
358 
359 			phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
360 			writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
361 		} else {
362 			reg_dma_size = ACP_HS_RX_DMA_SIZE;
363 			acp_fifo_addr = rsrc->sram_pte_offset +
364 					HS_CAPT_FIFO_ADDR_OFFSET;
365 			reg_fifo_addr = ACP_HS_RX_FIFOADDR;
366 			reg_fifo_size = ACP_HS_RX_FIFOSIZE;
367 
368 			phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
369 			writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
370 		}
371 		break;
372 	default:
373 		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
374 		return -EINVAL;
375 	}
376 
377 	writel(DMA_SIZE, adata->acp_base + reg_dma_size);
378 	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
379 	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
380 
381 	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
382 	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
383 			BIT(BT_RX_THRESHOLD(rsrc->offset)) |
384 			BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
385 			BIT(BT_TX_THRESHOLD(rsrc->offset)) |
386 			BIT(HS_RX_THRESHOLD(rsrc->offset)) |
387 			BIT(HS_TX_THRESHOLD(rsrc->offset));
388 
389 	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
390 
391 	return 0;
392 }
393 
394 static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
395 {
396 	struct acp_stream *stream = substream->runtime->private_data;
397 	struct device *dev = dai->component->dev;
398 	struct acp_dev_data *adata = dev_get_drvdata(dev);
399 	struct acp_resource *rsrc = adata->rsrc;
400 	unsigned int dir = substream->stream;
401 	unsigned int irq_bit = 0;
402 
403 	switch (dai->driver->id) {
404 	case I2S_SP_INSTANCE:
405 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
406 			irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
407 			stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
408 			stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
409 		} else {
410 			irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
411 			stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
412 			stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
413 		}
414 		break;
415 	case I2S_BT_INSTANCE:
416 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
417 			irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
418 			stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
419 			stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
420 		} else {
421 			irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
422 			stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
423 			stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
424 		}
425 		break;
426 	case I2S_HS_INSTANCE:
427 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
428 			irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset));
429 			stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET;
430 			stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET;
431 		} else {
432 			irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset));
433 			stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET;
434 			stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET;
435 		}
436 		break;
437 	default:
438 		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
439 		return -EINVAL;
440 	}
441 
442 	/* Save runtime dai configuration in stream */
443 	stream->id = dai->driver->id + dir;
444 	stream->dai_id = dai->driver->id;
445 	stream->irq_bit = irq_bit;
446 
447 	return 0;
448 }
449 
450 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
451 	.startup = acp_i2s_startup,
452 	.hw_params = acp_i2s_hwparams,
453 	.prepare = acp_i2s_prepare,
454 	.trigger = acp_i2s_trigger,
455 };
456 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
457 
458 int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
459 {
460 	struct device *dev = dai->component->dev;
461 	struct acp_dev_data *adata = dev_get_drvdata(dev);
462 	struct acp_resource *rsrc = adata->rsrc;
463 	unsigned int val;
464 
465 	if (!adata->acp_base) {
466 		dev_err(dev, "I2S base is NULL\n");
467 		return -EINVAL;
468 	}
469 
470 	val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
471 	if (val != rsrc->i2s_mode) {
472 		dev_err(dev, "I2S Mode not supported val %x\n", val);
473 		return -EINVAL;
474 	}
475 
476 	return 0;
477 }
478 EXPORT_SYMBOL_NS_GPL(asoc_acp_i2s_probe, SND_SOC_ACP_COMMON);
479 
480 MODULE_LICENSE("Dual BSD/GPL");
481 MODULE_ALIAS(DRV_NAME);
482