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
acp_i2s_set_fmt(struct snd_soc_dai * cpu_dai,unsigned int fmt)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
acp_i2s_set_tdm_slot(struct snd_soc_dai * dai,u32 tx_mask,u32 rx_mask,int slots,int slot_width)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
acp_i2s_hwparams(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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 } else {
153 switch (dai->driver->id) {
154 case I2S_BT_INSTANCE:
155 reg_val = ACP_BTTDM_IRER;
156 fmt_reg = ACP_BTTDM_RXFRMT;
157 break;
158 case I2S_SP_INSTANCE:
159 reg_val = ACP_I2STDM_IRER;
160 fmt_reg = ACP_I2STDM_RXFRMT;
161 break;
162 case I2S_HS_INSTANCE:
163 reg_val = ACP_HSTDM_IRER;
164 fmt_reg = ACP_HSTDM_RXFRMT;
165 break;
166 default:
167 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
168 return -EINVAL;
169 }
170 }
171
172 val = readl(adata->acp_base + reg_val);
173 val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
174 val = val | (xfer_resolution << 3);
175 writel(val, adata->acp_base + reg_val);
176
177 if (adata->tdm_mode) {
178 val = readl(adata->acp_base + reg_val);
179 writel(val | BIT(1), adata->acp_base + reg_val);
180 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
181 tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1];
182 else
183 tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1];
184 writel(tdm_fmt, adata->acp_base + fmt_reg);
185 }
186
187 if (rsrc->soc_mclk) {
188 switch (params_format(params)) {
189 case SNDRV_PCM_FORMAT_S16_LE:
190 switch (params_rate(params)) {
191 case 8000:
192 bclk_div_val = 768;
193 break;
194 case 16000:
195 bclk_div_val = 384;
196 break;
197 case 24000:
198 bclk_div_val = 256;
199 break;
200 case 32000:
201 bclk_div_val = 192;
202 break;
203 case 44100:
204 case 48000:
205 bclk_div_val = 128;
206 break;
207 case 88200:
208 case 96000:
209 bclk_div_val = 64;
210 break;
211 case 192000:
212 bclk_div_val = 32;
213 break;
214 default:
215 return -EINVAL;
216 }
217 lrclk_div_val = 32;
218 break;
219 case SNDRV_PCM_FORMAT_S32_LE:
220 switch (params_rate(params)) {
221 case 8000:
222 bclk_div_val = 384;
223 break;
224 case 16000:
225 bclk_div_val = 192;
226 break;
227 case 24000:
228 bclk_div_val = 128;
229 break;
230 case 32000:
231 bclk_div_val = 96;
232 break;
233 case 44100:
234 case 48000:
235 bclk_div_val = 64;
236 break;
237 case 88200:
238 case 96000:
239 bclk_div_val = 32;
240 break;
241 case 192000:
242 bclk_div_val = 16;
243 break;
244 default:
245 return -EINVAL;
246 }
247 lrclk_div_val = 64;
248 break;
249 default:
250 return -EINVAL;
251 }
252 adata->lrclk_div = lrclk_div_val;
253 adata->bclk_div = bclk_div_val;
254 }
255 return 0;
256 }
257
acp_i2s_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)258 static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
259 {
260 struct acp_stream *stream = substream->runtime->private_data;
261 struct device *dev = dai->component->dev;
262 struct acp_dev_data *adata = dev_get_drvdata(dev);
263 struct acp_resource *rsrc = adata->rsrc;
264 u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
265
266 period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
267 buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
268
269 switch (cmd) {
270 case SNDRV_PCM_TRIGGER_START:
271 case SNDRV_PCM_TRIGGER_RESUME:
272 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
273 stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
275 switch (dai->driver->id) {
276 case I2S_BT_INSTANCE:
277 water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
278 reg_val = ACP_BTTDM_ITER;
279 ier_val = ACP_BTTDM_IER;
280 buf_reg = ACP_BT_TX_RINGBUFSIZE;
281 break;
282 case I2S_SP_INSTANCE:
283 water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
284 reg_val = ACP_I2STDM_ITER;
285 ier_val = ACP_I2STDM_IER;
286 buf_reg = ACP_I2S_TX_RINGBUFSIZE;
287 break;
288 case I2S_HS_INSTANCE:
289 water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
290 reg_val = ACP_HSTDM_ITER;
291 ier_val = ACP_HSTDM_IER;
292 buf_reg = ACP_HS_TX_RINGBUFSIZE;
293 break;
294 default:
295 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
296 return -EINVAL;
297 }
298 } else {
299 switch (dai->driver->id) {
300 case I2S_BT_INSTANCE:
301 water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
302 reg_val = ACP_BTTDM_IRER;
303 ier_val = ACP_BTTDM_IER;
304 buf_reg = ACP_BT_RX_RINGBUFSIZE;
305 break;
306 case I2S_SP_INSTANCE:
307 water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
308 reg_val = ACP_I2STDM_IRER;
309 ier_val = ACP_I2STDM_IER;
310 buf_reg = ACP_I2S_RX_RINGBUFSIZE;
311 break;
312 case I2S_HS_INSTANCE:
313 water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
314 reg_val = ACP_HSTDM_IRER;
315 ier_val = ACP_HSTDM_IER;
316 buf_reg = ACP_HS_RX_RINGBUFSIZE;
317 break;
318 default:
319 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
320 return -EINVAL;
321 }
322 }
323 writel(period_bytes, adata->acp_base + water_val);
324 writel(buf_size, adata->acp_base + buf_reg);
325 val = readl(adata->acp_base + reg_val);
326 val = val | BIT(0);
327 writel(val, adata->acp_base + reg_val);
328 writel(1, adata->acp_base + ier_val);
329 if (rsrc->soc_mclk)
330 acp_set_i2s_clk(adata, dai->driver->id);
331 return 0;
332 case SNDRV_PCM_TRIGGER_STOP:
333 case SNDRV_PCM_TRIGGER_SUSPEND:
334 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
335 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
336 switch (dai->driver->id) {
337 case I2S_BT_INSTANCE:
338 reg_val = ACP_BTTDM_ITER;
339 break;
340 case I2S_SP_INSTANCE:
341 reg_val = ACP_I2STDM_ITER;
342 break;
343 case I2S_HS_INSTANCE:
344 reg_val = ACP_HSTDM_ITER;
345 break;
346 default:
347 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
348 return -EINVAL;
349 }
350
351 } else {
352 switch (dai->driver->id) {
353 case I2S_BT_INSTANCE:
354 reg_val = ACP_BTTDM_IRER;
355 break;
356 case I2S_SP_INSTANCE:
357 reg_val = ACP_I2STDM_IRER;
358 break;
359 case I2S_HS_INSTANCE:
360 reg_val = ACP_HSTDM_IRER;
361 break;
362 default:
363 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
364 return -EINVAL;
365 }
366 }
367 val = readl(adata->acp_base + reg_val);
368 val = val & ~BIT(0);
369 writel(val, adata->acp_base + reg_val);
370
371 if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
372 !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
373 writel(0, adata->acp_base + ACP_BTTDM_IER);
374 if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
375 !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
376 writel(0, adata->acp_base + ACP_I2STDM_IER);
377 if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
378 !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
379 writel(0, adata->acp_base + ACP_HSTDM_IER);
380 return 0;
381 default:
382 return -EINVAL;
383 }
384
385 return 0;
386 }
387
acp_i2s_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)388 static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
389 {
390 struct device *dev = dai->component->dev;
391 struct acp_dev_data *adata = dev_get_drvdata(dev);
392 struct acp_resource *rsrc = adata->rsrc;
393 struct acp_stream *stream = substream->runtime->private_data;
394 u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
395 u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
396 unsigned int dir = substream->stream;
397
398 switch (dai->driver->id) {
399 case I2S_SP_INSTANCE:
400 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
401 reg_dma_size = ACP_I2S_TX_DMA_SIZE;
402 acp_fifo_addr = rsrc->sram_pte_offset +
403 SP_PB_FIFO_ADDR_OFFSET;
404 reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
405 reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
406
407 phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
408 writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
409 } else {
410 reg_dma_size = ACP_I2S_RX_DMA_SIZE;
411 acp_fifo_addr = rsrc->sram_pte_offset +
412 SP_CAPT_FIFO_ADDR_OFFSET;
413 reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
414 reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
415 phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
416 writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
417 }
418 break;
419 case I2S_BT_INSTANCE:
420 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
421 reg_dma_size = ACP_BT_TX_DMA_SIZE;
422 acp_fifo_addr = rsrc->sram_pte_offset +
423 BT_PB_FIFO_ADDR_OFFSET;
424 reg_fifo_addr = ACP_BT_TX_FIFOADDR;
425 reg_fifo_size = ACP_BT_TX_FIFOSIZE;
426
427 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
428 writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
429 } else {
430 reg_dma_size = ACP_BT_RX_DMA_SIZE;
431 acp_fifo_addr = rsrc->sram_pte_offset +
432 BT_CAPT_FIFO_ADDR_OFFSET;
433 reg_fifo_addr = ACP_BT_RX_FIFOADDR;
434 reg_fifo_size = ACP_BT_RX_FIFOSIZE;
435
436 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
437 writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
438 }
439 break;
440 case I2S_HS_INSTANCE:
441 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
442 reg_dma_size = ACP_HS_TX_DMA_SIZE;
443 acp_fifo_addr = rsrc->sram_pte_offset +
444 HS_PB_FIFO_ADDR_OFFSET;
445 reg_fifo_addr = ACP_HS_TX_FIFOADDR;
446 reg_fifo_size = ACP_HS_TX_FIFOSIZE;
447
448 phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
449 writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
450 } else {
451 reg_dma_size = ACP_HS_RX_DMA_SIZE;
452 acp_fifo_addr = rsrc->sram_pte_offset +
453 HS_CAPT_FIFO_ADDR_OFFSET;
454 reg_fifo_addr = ACP_HS_RX_FIFOADDR;
455 reg_fifo_size = ACP_HS_RX_FIFOSIZE;
456
457 phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
458 writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
459 }
460 break;
461 default:
462 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
463 return -EINVAL;
464 }
465
466 writel(DMA_SIZE, adata->acp_base + reg_dma_size);
467 writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
468 writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
469
470 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
471 ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
472 BIT(BT_RX_THRESHOLD(rsrc->offset)) |
473 BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
474 BIT(BT_TX_THRESHOLD(rsrc->offset)) |
475 BIT(HS_RX_THRESHOLD(rsrc->offset)) |
476 BIT(HS_TX_THRESHOLD(rsrc->offset));
477
478 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
479
480 return 0;
481 }
482
acp_i2s_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)483 static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
484 {
485 struct acp_stream *stream = substream->runtime->private_data;
486 struct device *dev = dai->component->dev;
487 struct acp_dev_data *adata = dev_get_drvdata(dev);
488 struct acp_resource *rsrc = adata->rsrc;
489 unsigned int dir = substream->stream;
490 unsigned int irq_bit = 0;
491
492 switch (dai->driver->id) {
493 case I2S_SP_INSTANCE:
494 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
495 irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
496 stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
497 stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
498 } else {
499 irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
500 stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
501 stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
502 }
503 break;
504 case I2S_BT_INSTANCE:
505 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
506 irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
507 stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
508 stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
509 } else {
510 irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
511 stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
512 stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
513 }
514 break;
515 case I2S_HS_INSTANCE:
516 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
517 irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset));
518 stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET;
519 stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET;
520 } else {
521 irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset));
522 stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET;
523 stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET;
524 }
525 break;
526 default:
527 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
528 return -EINVAL;
529 }
530
531 /* Save runtime dai configuration in stream */
532 stream->id = dai->driver->id + dir;
533 stream->dai_id = dai->driver->id;
534 stream->irq_bit = irq_bit;
535 stream->dir = substream->stream;
536
537 return 0;
538 }
539
540 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
541 .startup = acp_i2s_startup,
542 .hw_params = acp_i2s_hwparams,
543 .prepare = acp_i2s_prepare,
544 .trigger = acp_i2s_trigger,
545 .set_fmt = acp_i2s_set_fmt,
546 .set_tdm_slot = acp_i2s_set_tdm_slot,
547 };
548 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
549
asoc_acp_i2s_probe(struct snd_soc_dai * dai)550 int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
551 {
552 struct device *dev = dai->component->dev;
553 struct acp_dev_data *adata = dev_get_drvdata(dev);
554 struct acp_resource *rsrc = adata->rsrc;
555 unsigned int val;
556
557 if (!adata->acp_base) {
558 dev_err(dev, "I2S base is NULL\n");
559 return -EINVAL;
560 }
561
562 val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
563 if (val != rsrc->i2s_mode) {
564 dev_err(dev, "I2S Mode not supported val %x\n", val);
565 return -EINVAL;
566 }
567
568 return 0;
569 }
570 EXPORT_SYMBOL_NS_GPL(asoc_acp_i2s_probe, SND_SOC_ACP_COMMON);
571
572 MODULE_LICENSE("Dual BSD/GPL");
573 MODULE_ALIAS(DRV_NAME);
574