xref: /linux/sound/soc/amd/acp/acp-i2s.c (revision 34dc1baba215b826e454b8d19e4f24adbeb7d00d)
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_set_fmt(struct snd_soc_dai *cpu_dai,
29 			   unsigned int fmt)
30 {
31 	struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
32 	int mode;
33 
34 	mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
35 	switch (mode) {
36 	case SND_SOC_DAIFMT_I2S:
37 		adata->tdm_mode = TDM_DISABLE;
38 		break;
39 	case SND_SOC_DAIFMT_DSP_A:
40 		adata->tdm_mode = TDM_ENABLE;
41 		break;
42 	default:
43 		return -EINVAL;
44 	}
45 	return 0;
46 }
47 
48 static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask,
49 				int slots, int slot_width)
50 {
51 	struct device *dev = dai->component->dev;
52 	struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
53 	struct acp_stream *stream;
54 	int slot_len, no_of_slots;
55 
56 	switch (slot_width) {
57 	case SLOT_WIDTH_8:
58 		slot_len = 8;
59 		break;
60 	case SLOT_WIDTH_16:
61 		slot_len = 16;
62 		break;
63 	case SLOT_WIDTH_24:
64 		slot_len = 24;
65 		break;
66 	case SLOT_WIDTH_32:
67 		slot_len = 0;
68 		break;
69 	default:
70 		dev_err(dev, "Unsupported bitdepth %d\n", slot_width);
71 		return -EINVAL;
72 	}
73 
74 	switch (slots) {
75 	case 1 ... 7:
76 		no_of_slots = slots;
77 		break;
78 	case 8:
79 		no_of_slots = 0;
80 		break;
81 	default:
82 		dev_err(dev, "Unsupported slots %d\n", slots);
83 		return -EINVAL;
84 	}
85 
86 	slots = no_of_slots;
87 
88 	spin_lock_irq(&adata->acp_lock);
89 	list_for_each_entry(stream, &adata->stream_list, list) {
90 		if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
91 			adata->tdm_tx_fmt[stream->dai_id - 1] =
92 					FRM_LEN | (slots << 15) | (slot_len << 18);
93 		else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
94 			adata->tdm_rx_fmt[stream->dai_id - 1] =
95 					FRM_LEN | (slots << 15) | (slot_len << 18);
96 	}
97 	spin_unlock_irq(&adata->acp_lock);
98 	return 0;
99 }
100 
101 static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
102 			    struct snd_soc_dai *dai)
103 {
104 	struct device *dev = dai->component->dev;
105 	struct acp_dev_data *adata;
106 	struct acp_resource *rsrc;
107 	u32 val;
108 	u32 xfer_resolution;
109 	u32 reg_val, fmt_reg, tdm_fmt;
110 	u32 lrclk_div_val, bclk_div_val;
111 
112 	adata = snd_soc_dai_get_drvdata(dai);
113 	rsrc = adata->rsrc;
114 
115 	/* These values are as per Hardware Spec */
116 	switch (params_format(params)) {
117 	case SNDRV_PCM_FORMAT_U8:
118 	case SNDRV_PCM_FORMAT_S8:
119 		xfer_resolution = 0x0;
120 		break;
121 	case SNDRV_PCM_FORMAT_S16_LE:
122 		xfer_resolution = 0x02;
123 		break;
124 	case SNDRV_PCM_FORMAT_S24_LE:
125 		xfer_resolution = 0x04;
126 		break;
127 	case SNDRV_PCM_FORMAT_S32_LE:
128 		xfer_resolution = 0x05;
129 		break;
130 	default:
131 		return -EINVAL;
132 	}
133 
134 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
135 		switch (dai->driver->id) {
136 		case I2S_BT_INSTANCE:
137 			reg_val = ACP_BTTDM_ITER;
138 			fmt_reg = ACP_BTTDM_TXFRMT;
139 			break;
140 		case I2S_SP_INSTANCE:
141 			reg_val = ACP_I2STDM_ITER;
142 			fmt_reg = ACP_I2STDM_TXFRMT;
143 			break;
144 		case I2S_HS_INSTANCE:
145 			reg_val = ACP_HSTDM_ITER;
146 			fmt_reg = ACP_HSTDM_TXFRMT;
147 			break;
148 		default:
149 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
150 			return -EINVAL;
151 		}
152 		adata->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution;
153 	} else {
154 		switch (dai->driver->id) {
155 		case I2S_BT_INSTANCE:
156 			reg_val = ACP_BTTDM_IRER;
157 			fmt_reg = ACP_BTTDM_RXFRMT;
158 			break;
159 		case I2S_SP_INSTANCE:
160 			reg_val = ACP_I2STDM_IRER;
161 			fmt_reg = ACP_I2STDM_RXFRMT;
162 			break;
163 		case I2S_HS_INSTANCE:
164 			reg_val = ACP_HSTDM_IRER;
165 			fmt_reg = ACP_HSTDM_RXFRMT;
166 			break;
167 		default:
168 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
169 			return -EINVAL;
170 		}
171 		adata->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution;
172 	}
173 
174 	val = readl(adata->acp_base + reg_val);
175 	val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
176 	val = val | (xfer_resolution  << 3);
177 	writel(val, adata->acp_base + reg_val);
178 
179 	if (adata->tdm_mode) {
180 		val = readl(adata->acp_base + reg_val);
181 		writel(val | BIT(1), adata->acp_base + reg_val);
182 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
183 			tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1];
184 		else
185 			tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1];
186 		writel(tdm_fmt, adata->acp_base + fmt_reg);
187 	}
188 
189 	if (rsrc->soc_mclk) {
190 		switch (params_format(params)) {
191 		case SNDRV_PCM_FORMAT_S16_LE:
192 			switch (params_rate(params)) {
193 			case 8000:
194 				bclk_div_val = 768;
195 				break;
196 			case 16000:
197 				bclk_div_val = 384;
198 				break;
199 			case 24000:
200 				bclk_div_val = 256;
201 				break;
202 			case 32000:
203 				bclk_div_val = 192;
204 				break;
205 			case 44100:
206 			case 48000:
207 				bclk_div_val = 128;
208 				break;
209 			case 88200:
210 			case 96000:
211 				bclk_div_val = 64;
212 				break;
213 			case 192000:
214 				bclk_div_val = 32;
215 				break;
216 			default:
217 				return -EINVAL;
218 			}
219 			lrclk_div_val = 32;
220 			break;
221 		case SNDRV_PCM_FORMAT_S32_LE:
222 			switch (params_rate(params)) {
223 			case 8000:
224 				bclk_div_val = 384;
225 				break;
226 			case 16000:
227 				bclk_div_val = 192;
228 				break;
229 			case 24000:
230 				bclk_div_val = 128;
231 				break;
232 			case 32000:
233 				bclk_div_val = 96;
234 				break;
235 			case 44100:
236 			case 48000:
237 				bclk_div_val = 64;
238 				break;
239 			case 88200:
240 			case 96000:
241 				bclk_div_val = 32;
242 				break;
243 			case 192000:
244 				bclk_div_val = 16;
245 				break;
246 			default:
247 				return -EINVAL;
248 			}
249 			lrclk_div_val = 64;
250 			break;
251 		default:
252 			return -EINVAL;
253 		}
254 		adata->lrclk_div = lrclk_div_val;
255 		adata->bclk_div = bclk_div_val;
256 	}
257 	return 0;
258 }
259 
260 static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
261 {
262 	struct acp_stream *stream = substream->runtime->private_data;
263 	struct device *dev = dai->component->dev;
264 	struct acp_dev_data *adata = dev_get_drvdata(dev);
265 	struct acp_resource *rsrc = adata->rsrc;
266 	u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
267 
268 	period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
269 	buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
270 
271 	switch (cmd) {
272 	case SNDRV_PCM_TRIGGER_START:
273 	case SNDRV_PCM_TRIGGER_RESUME:
274 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
275 		stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
276 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
277 			switch (dai->driver->id) {
278 			case I2S_BT_INSTANCE:
279 				water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
280 				reg_val = ACP_BTTDM_ITER;
281 				ier_val = ACP_BTTDM_IER;
282 				buf_reg = ACP_BT_TX_RINGBUFSIZE;
283 				break;
284 			case I2S_SP_INSTANCE:
285 				water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
286 				reg_val = ACP_I2STDM_ITER;
287 				ier_val = ACP_I2STDM_IER;
288 				buf_reg = ACP_I2S_TX_RINGBUFSIZE;
289 				break;
290 			case I2S_HS_INSTANCE:
291 				water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
292 				reg_val = ACP_HSTDM_ITER;
293 				ier_val = ACP_HSTDM_IER;
294 				buf_reg = ACP_HS_TX_RINGBUFSIZE;
295 				break;
296 			default:
297 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
298 				return -EINVAL;
299 			}
300 		} else {
301 			switch (dai->driver->id) {
302 			case I2S_BT_INSTANCE:
303 				water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
304 				reg_val = ACP_BTTDM_IRER;
305 				ier_val = ACP_BTTDM_IER;
306 				buf_reg = ACP_BT_RX_RINGBUFSIZE;
307 				break;
308 			case I2S_SP_INSTANCE:
309 				water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
310 				reg_val = ACP_I2STDM_IRER;
311 				ier_val = ACP_I2STDM_IER;
312 				buf_reg = ACP_I2S_RX_RINGBUFSIZE;
313 				break;
314 			case I2S_HS_INSTANCE:
315 				water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
316 				reg_val = ACP_HSTDM_IRER;
317 				ier_val = ACP_HSTDM_IER;
318 				buf_reg = ACP_HS_RX_RINGBUFSIZE;
319 				break;
320 			default:
321 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
322 				return -EINVAL;
323 			}
324 		}
325 		writel(period_bytes, adata->acp_base + water_val);
326 		writel(buf_size, adata->acp_base + buf_reg);
327 		val = readl(adata->acp_base + reg_val);
328 		val = val | BIT(0);
329 		writel(val, adata->acp_base + reg_val);
330 		writel(1, adata->acp_base + ier_val);
331 		if (rsrc->soc_mclk)
332 			acp_set_i2s_clk(adata, dai->driver->id);
333 		return 0;
334 	case SNDRV_PCM_TRIGGER_STOP:
335 	case SNDRV_PCM_TRIGGER_SUSPEND:
336 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
337 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
338 			switch (dai->driver->id) {
339 			case I2S_BT_INSTANCE:
340 				reg_val = ACP_BTTDM_ITER;
341 				break;
342 			case I2S_SP_INSTANCE:
343 				reg_val = ACP_I2STDM_ITER;
344 				break;
345 			case I2S_HS_INSTANCE:
346 				reg_val = ACP_HSTDM_ITER;
347 				break;
348 			default:
349 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
350 				return -EINVAL;
351 			}
352 
353 		} else {
354 			switch (dai->driver->id) {
355 			case I2S_BT_INSTANCE:
356 				reg_val = ACP_BTTDM_IRER;
357 				break;
358 			case I2S_SP_INSTANCE:
359 				reg_val = ACP_I2STDM_IRER;
360 				break;
361 			case I2S_HS_INSTANCE:
362 				reg_val = ACP_HSTDM_IRER;
363 				break;
364 			default:
365 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
366 				return -EINVAL;
367 			}
368 		}
369 		val = readl(adata->acp_base + reg_val);
370 		val = val & ~BIT(0);
371 		writel(val, adata->acp_base + reg_val);
372 
373 		if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
374 		    !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
375 			writel(0, adata->acp_base + ACP_BTTDM_IER);
376 		if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
377 		    !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
378 			writel(0, adata->acp_base + ACP_I2STDM_IER);
379 		if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
380 		    !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
381 			writel(0, adata->acp_base + ACP_HSTDM_IER);
382 		return 0;
383 	default:
384 		return -EINVAL;
385 	}
386 
387 	return 0;
388 }
389 
390 static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
391 {
392 	struct device *dev = dai->component->dev;
393 	struct acp_dev_data *adata = dev_get_drvdata(dev);
394 	struct acp_resource *rsrc = adata->rsrc;
395 	struct acp_stream *stream = substream->runtime->private_data;
396 	u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
397 	u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
398 	unsigned int dir = substream->stream;
399 
400 	switch (dai->driver->id) {
401 	case I2S_SP_INSTANCE:
402 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
403 			reg_dma_size = ACP_I2S_TX_DMA_SIZE;
404 			acp_fifo_addr = rsrc->sram_pte_offset +
405 						SP_PB_FIFO_ADDR_OFFSET;
406 			reg_fifo_addr =	ACP_I2S_TX_FIFOADDR;
407 			reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
408 
409 			phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
410 			writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
411 		} else {
412 			reg_dma_size = ACP_I2S_RX_DMA_SIZE;
413 			acp_fifo_addr = rsrc->sram_pte_offset +
414 						SP_CAPT_FIFO_ADDR_OFFSET;
415 			reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
416 			reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
417 			phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
418 			writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
419 		}
420 		break;
421 	case I2S_BT_INSTANCE:
422 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
423 			reg_dma_size = ACP_BT_TX_DMA_SIZE;
424 			acp_fifo_addr = rsrc->sram_pte_offset +
425 						BT_PB_FIFO_ADDR_OFFSET;
426 			reg_fifo_addr = ACP_BT_TX_FIFOADDR;
427 			reg_fifo_size = ACP_BT_TX_FIFOSIZE;
428 
429 			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
430 			writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
431 		} else {
432 			reg_dma_size = ACP_BT_RX_DMA_SIZE;
433 			acp_fifo_addr = rsrc->sram_pte_offset +
434 						BT_CAPT_FIFO_ADDR_OFFSET;
435 			reg_fifo_addr = ACP_BT_RX_FIFOADDR;
436 			reg_fifo_size = ACP_BT_RX_FIFOSIZE;
437 
438 			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
439 			writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
440 		}
441 		break;
442 	case I2S_HS_INSTANCE:
443 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
444 			reg_dma_size = ACP_HS_TX_DMA_SIZE;
445 			acp_fifo_addr = rsrc->sram_pte_offset +
446 				HS_PB_FIFO_ADDR_OFFSET;
447 			reg_fifo_addr = ACP_HS_TX_FIFOADDR;
448 			reg_fifo_size = ACP_HS_TX_FIFOSIZE;
449 
450 			phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
451 			writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
452 		} else {
453 			reg_dma_size = ACP_HS_RX_DMA_SIZE;
454 			acp_fifo_addr = rsrc->sram_pte_offset +
455 					HS_CAPT_FIFO_ADDR_OFFSET;
456 			reg_fifo_addr = ACP_HS_RX_FIFOADDR;
457 			reg_fifo_size = ACP_HS_RX_FIFOSIZE;
458 
459 			phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
460 			writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
461 		}
462 		break;
463 	default:
464 		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
465 		return -EINVAL;
466 	}
467 
468 	writel(DMA_SIZE, adata->acp_base + reg_dma_size);
469 	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
470 	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
471 
472 	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
473 	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
474 			BIT(BT_RX_THRESHOLD(rsrc->offset)) |
475 			BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
476 			BIT(BT_TX_THRESHOLD(rsrc->offset)) |
477 			BIT(HS_RX_THRESHOLD(rsrc->offset)) |
478 			BIT(HS_TX_THRESHOLD(rsrc->offset));
479 
480 	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
481 
482 	return 0;
483 }
484 
485 static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
486 {
487 	struct acp_stream *stream = substream->runtime->private_data;
488 	struct device *dev = dai->component->dev;
489 	struct acp_dev_data *adata = dev_get_drvdata(dev);
490 	struct acp_resource *rsrc = adata->rsrc;
491 	unsigned int dir = substream->stream;
492 	unsigned int irq_bit = 0;
493 
494 	switch (dai->driver->id) {
495 	case I2S_SP_INSTANCE:
496 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
497 			irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
498 			stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
499 			stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
500 		} else {
501 			irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
502 			stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
503 			stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
504 		}
505 		break;
506 	case I2S_BT_INSTANCE:
507 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
508 			irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
509 			stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
510 			stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
511 		} else {
512 			irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
513 			stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
514 			stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
515 		}
516 		break;
517 	case I2S_HS_INSTANCE:
518 		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
519 			irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset));
520 			stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET;
521 			stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET;
522 		} else {
523 			irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset));
524 			stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET;
525 			stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET;
526 		}
527 		break;
528 	default:
529 		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
530 		return -EINVAL;
531 	}
532 
533 	/* Save runtime dai configuration in stream */
534 	stream->id = dai->driver->id + dir;
535 	stream->dai_id = dai->driver->id;
536 	stream->irq_bit = irq_bit;
537 	stream->dir = substream->stream;
538 
539 	return 0;
540 }
541 
542 static int acp_i2s_probe(struct snd_soc_dai *dai)
543 {
544 	struct device *dev = dai->component->dev;
545 	struct acp_dev_data *adata = dev_get_drvdata(dev);
546 	struct acp_resource *rsrc = adata->rsrc;
547 	unsigned int val;
548 
549 	if (!adata->acp_base) {
550 		dev_err(dev, "I2S base is NULL\n");
551 		return -EINVAL;
552 	}
553 
554 	val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
555 	if (val != rsrc->i2s_mode) {
556 		dev_err(dev, "I2S Mode not supported val %x\n", val);
557 		return -EINVAL;
558 	}
559 
560 	return 0;
561 }
562 
563 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
564 	.probe		= acp_i2s_probe,
565 	.startup	= acp_i2s_startup,
566 	.hw_params	= acp_i2s_hwparams,
567 	.prepare	= acp_i2s_prepare,
568 	.trigger	= acp_i2s_trigger,
569 	.set_fmt	= acp_i2s_set_fmt,
570 	.set_tdm_slot	= acp_i2s_set_tdm_slot,
571 };
572 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
573 
574 MODULE_LICENSE("Dual BSD/GPL");
575 MODULE_ALIAS(DRV_NAME);
576