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 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
acp_i2s_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)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
acp_i2s_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
acp_i2s_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
acp_i2s_probe(struct snd_soc_dai * dai)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
547 if (!adata->acp_base) {
548 dev_err(dev, "I2S base is NULL\n");
549 return -EINVAL;
550 }
551
552 return 0;
553 }
554
555 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
556 .probe = acp_i2s_probe,
557 .startup = acp_i2s_startup,
558 .hw_params = acp_i2s_hwparams,
559 .prepare = acp_i2s_prepare,
560 .trigger = acp_i2s_trigger,
561 .set_fmt = acp_i2s_set_fmt,
562 .set_tdm_slot = acp_i2s_set_tdm_slot,
563 };
564 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
565
566 MODULE_LICENSE("Dual BSD/GPL");
567 MODULE_ALIAS(DRV_NAME);
568