1 // SPDX-License-Identifier: GPL-2.0
3 // Xilinx ASoC audio formatter support
5 // Copyright (C) 2018 Xilinx, Inc.
7 // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
11 #include <linux/module.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 #include <linux/sizes.h>
16 #include <sound/asoundef.h>
17 #include <sound/soc.h>
18 #include <sound/pcm_params.h>
20 #define DRV_NAME "xlnx_formatter_pcm"
22 #define XLNX_S2MM_OFFSET 0
23 #define XLNX_MM2S_OFFSET 0x100
25 #define XLNX_AUD_CORE_CONFIG 0x4
26 #define XLNX_AUD_CTRL 0x10
27 #define XLNX_AUD_STS 0x14
29 #define AUD_CTRL_RESET_MASK BIT(1)
30 #define AUD_CFG_MM2S_MASK BIT(15)
31 #define AUD_CFG_S2MM_MASK BIT(31)
33 #define XLNX_AUD_FS_MULTIPLIER 0x18
34 #define XLNX_AUD_PERIOD_CONFIG 0x1C
35 #define XLNX_AUD_BUFF_ADDR_LSB 0x20
36 #define XLNX_AUD_BUFF_ADDR_MSB 0x24
37 #define XLNX_AUD_XFER_COUNT 0x28
38 #define XLNX_AUD_CH_STS_START 0x2C
39 #define XLNX_BYTES_PER_CH 0x44
40 #define XLNX_AUD_ALIGN_BYTES 64
42 #define AUD_STS_IOC_IRQ_MASK BIT(31)
43 #define AUD_STS_CH_STS_MASK BIT(29)
44 #define AUD_CTRL_IOC_IRQ_MASK BIT(13)
45 #define AUD_CTRL_TOUT_IRQ_MASK BIT(14)
46 #define AUD_CTRL_DMA_EN_MASK BIT(0)
48 #define CFG_MM2S_CH_MASK GENMASK(11, 8)
49 #define CFG_MM2S_CH_SHIFT 8
50 #define CFG_MM2S_XFER_MASK GENMASK(14, 13)
51 #define CFG_MM2S_XFER_SHIFT 13
52 #define CFG_MM2S_PKG_MASK BIT(12)
54 #define CFG_S2MM_CH_MASK GENMASK(27, 24)
55 #define CFG_S2MM_CH_SHIFT 24
56 #define CFG_S2MM_XFER_MASK GENMASK(30, 29)
57 #define CFG_S2MM_XFER_SHIFT 29
58 #define CFG_S2MM_PKG_MASK BIT(28)
60 #define AUD_CTRL_DATA_WIDTH_SHIFT 16
61 #define AUD_CTRL_ACTIVE_CH_SHIFT 19
62 #define PERIOD_CFG_PERIODS_SHIFT 16
66 #define PERIOD_BYTES_MIN 192
67 #define PERIOD_BYTES_MAX (50 * 1024)
68 #define XLNX_PARAM_UNKNOWN 0
78 struct xlnx_pcm_drv_data
{
84 struct snd_pcm_substream
*play_stream
;
85 struct snd_pcm_substream
*capture_stream
;
91 * struct xlnx_pcm_stream_param - stream configuration
92 * @mmio: base address offset
93 * @interleaved: audio channels arrangement in buffer
94 * @xfer_mode: data formatting mode during transfer
95 * @ch_limit: Maximum channels supported
96 * @buffer_size: stream ring buffer size
98 struct xlnx_pcm_stream_param
{
106 static const struct snd_pcm_hardware xlnx_pcm_hardware
= {
107 .info
= SNDRV_PCM_INFO_INTERLEAVED
| SNDRV_PCM_INFO_BLOCK_TRANSFER
|
108 SNDRV_PCM_INFO_BATCH
| SNDRV_PCM_INFO_PAUSE
|
109 SNDRV_PCM_INFO_RESUME
,
110 .formats
= SNDRV_PCM_FMTBIT_S8
| SNDRV_PCM_FMTBIT_S16_LE
|
111 SNDRV_PCM_FMTBIT_S24_LE
,
114 .rates
= SNDRV_PCM_RATE_8000_192000
,
117 .buffer_bytes_max
= PERIODS_MAX
* PERIOD_BYTES_MAX
,
118 .period_bytes_min
= PERIOD_BYTES_MIN
,
119 .period_bytes_max
= PERIOD_BYTES_MAX
,
120 .periods_min
= PERIODS_MIN
,
121 .periods_max
= PERIODS_MAX
,
131 static void xlnx_parse_aes_params(u32 chsts_reg1_val
, u32 chsts_reg2_val
,
134 u32 padded
, srate
, bit_depth
, status
[2];
136 if (chsts_reg1_val
& IEC958_AES0_PROFESSIONAL
) {
137 status
[0] = chsts_reg1_val
& 0xff;
138 status
[1] = (chsts_reg1_val
>> 16) & 0xff;
140 switch (status
[0] & IEC958_AES0_PRO_FS
) {
141 case IEC958_AES0_PRO_FS_44100
:
144 case IEC958_AES0_PRO_FS_48000
:
147 case IEC958_AES0_PRO_FS_32000
:
150 case IEC958_AES0_PRO_FS_NOTID
:
152 srate
= XLNX_PARAM_UNKNOWN
;
156 switch (status
[1] & IEC958_AES2_PRO_SBITS
) {
157 case IEC958_AES2_PRO_WORDLEN_NOTID
:
158 case IEC958_AES2_PRO_SBITS_20
:
161 case IEC958_AES2_PRO_SBITS_24
:
165 bit_depth
= XLNX_PARAM_UNKNOWN
;
169 switch (status
[1] & IEC958_AES2_PRO_WORDLEN
) {
170 case IEC958_AES2_PRO_WORDLEN_20_16
:
171 bit_depth
= 16 + padded
;
173 case IEC958_AES2_PRO_WORDLEN_22_18
:
174 bit_depth
= 18 + padded
;
176 case IEC958_AES2_PRO_WORDLEN_23_19
:
177 bit_depth
= 19 + padded
;
179 case IEC958_AES2_PRO_WORDLEN_24_20
:
180 bit_depth
= 20 + padded
;
182 case IEC958_AES2_PRO_WORDLEN_NOTID
:
184 bit_depth
= XLNX_PARAM_UNKNOWN
;
189 status
[0] = (chsts_reg1_val
>> 24) & 0xff;
190 status
[1] = chsts_reg2_val
& 0xff;
192 switch (status
[0] & IEC958_AES3_CON_FS
) {
193 case IEC958_AES3_CON_FS_44100
:
196 case IEC958_AES3_CON_FS_48000
:
199 case IEC958_AES3_CON_FS_32000
:
203 srate
= XLNX_PARAM_UNKNOWN
;
207 if (status
[1] & IEC958_AES4_CON_MAX_WORDLEN_24
)
212 switch (status
[1] & IEC958_AES4_CON_WORDLEN
) {
213 case IEC958_AES4_CON_WORDLEN_20_16
:
214 bit_depth
= 16 + padded
;
216 case IEC958_AES4_CON_WORDLEN_22_18
:
217 bit_depth
= 18 + padded
;
219 case IEC958_AES4_CON_WORDLEN_23_19
:
220 bit_depth
= 19 + padded
;
222 case IEC958_AES4_CON_WORDLEN_24_20
:
223 bit_depth
= 20 + padded
;
225 case IEC958_AES4_CON_WORDLEN_21_17
:
226 bit_depth
= 17 + padded
;
228 case IEC958_AES4_CON_WORDLEN_NOTID
:
230 bit_depth
= XLNX_PARAM_UNKNOWN
;
236 if (srate
!= XLNX_PARAM_UNKNOWN
)
237 dev_info(dev
, "sample rate = %d\n", srate
);
239 dev_info(dev
, "sample rate = unknown\n");
241 if (bit_depth
!= XLNX_PARAM_UNKNOWN
)
242 dev_info(dev
, "bit_depth = %d\n", bit_depth
);
244 dev_info(dev
, "bit_depth = unknown\n");
247 static int xlnx_formatter_pcm_reset(void __iomem
*mmio_base
)
249 u32 val
, retries
= 0;
251 val
= readl(mmio_base
+ XLNX_AUD_CTRL
);
252 val
|= AUD_CTRL_RESET_MASK
;
253 writel(val
, mmio_base
+ XLNX_AUD_CTRL
);
255 val
= readl(mmio_base
+ XLNX_AUD_CTRL
);
256 /* Poll for maximum timeout of approximately 100ms (1 * 100)*/
257 while ((val
& AUD_CTRL_RESET_MASK
) && (retries
< 100)) {
260 val
= readl(mmio_base
+ XLNX_AUD_CTRL
);
262 if (val
& AUD_CTRL_RESET_MASK
)
268 static void xlnx_formatter_disable_irqs(void __iomem
*mmio_base
, int stream
)
272 val
= readl(mmio_base
+ XLNX_AUD_CTRL
);
273 val
&= ~AUD_CTRL_IOC_IRQ_MASK
;
274 if (stream
== SNDRV_PCM_STREAM_CAPTURE
)
275 val
&= ~AUD_CTRL_TOUT_IRQ_MASK
;
277 writel(val
, mmio_base
+ XLNX_AUD_CTRL
);
280 static irqreturn_t
xlnx_mm2s_irq_handler(int irq
, void *arg
)
284 struct device
*dev
= arg
;
285 struct xlnx_pcm_drv_data
*adata
= dev_get_drvdata(dev
);
287 reg
= adata
->mmio
+ XLNX_MM2S_OFFSET
+ XLNX_AUD_STS
;
289 if (val
& AUD_STS_IOC_IRQ_MASK
) {
290 writel(val
& AUD_STS_IOC_IRQ_MASK
, reg
);
291 if (adata
->play_stream
)
292 snd_pcm_period_elapsed(adata
->play_stream
);
299 static irqreturn_t
xlnx_s2mm_irq_handler(int irq
, void *arg
)
303 struct device
*dev
= arg
;
304 struct xlnx_pcm_drv_data
*adata
= dev_get_drvdata(dev
);
306 reg
= adata
->mmio
+ XLNX_S2MM_OFFSET
+ XLNX_AUD_STS
;
308 if (val
& AUD_STS_IOC_IRQ_MASK
) {
309 writel(val
& AUD_STS_IOC_IRQ_MASK
, reg
);
310 if (adata
->capture_stream
)
311 snd_pcm_period_elapsed(adata
->capture_stream
);
318 static int xlnx_formatter_set_sysclk(struct snd_soc_component
*component
,
319 int clk_id
, int source
, unsigned int freq
, int dir
)
321 struct xlnx_pcm_drv_data
*adata
= dev_get_drvdata(component
->dev
);
323 adata
->sysclk
= freq
;
327 static int xlnx_formatter_pcm_open(struct snd_soc_component
*component
,
328 struct snd_pcm_substream
*substream
)
331 u32 val
, data_format_mode
;
332 u32 ch_count_mask
, ch_count_shift
, data_xfer_mode
, data_xfer_shift
;
333 struct xlnx_pcm_stream_param
*stream_data
;
334 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
335 struct xlnx_pcm_drv_data
*adata
= dev_get_drvdata(component
->dev
);
337 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
&&
338 !adata
->mm2s_presence
)
340 else if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
&&
341 !adata
->s2mm_presence
)
344 stream_data
= kzalloc(sizeof(*stream_data
), GFP_KERNEL
);
348 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
349 ch_count_mask
= CFG_MM2S_CH_MASK
;
350 ch_count_shift
= CFG_MM2S_CH_SHIFT
;
351 data_xfer_mode
= CFG_MM2S_XFER_MASK
;
352 data_xfer_shift
= CFG_MM2S_XFER_SHIFT
;
353 data_format_mode
= CFG_MM2S_PKG_MASK
;
354 stream_data
->mmio
= adata
->mmio
+ XLNX_MM2S_OFFSET
;
355 adata
->play_stream
= substream
;
358 ch_count_mask
= CFG_S2MM_CH_MASK
;
359 ch_count_shift
= CFG_S2MM_CH_SHIFT
;
360 data_xfer_mode
= CFG_S2MM_XFER_MASK
;
361 data_xfer_shift
= CFG_S2MM_XFER_SHIFT
;
362 data_format_mode
= CFG_S2MM_PKG_MASK
;
363 stream_data
->mmio
= adata
->mmio
+ XLNX_S2MM_OFFSET
;
364 adata
->capture_stream
= substream
;
367 val
= readl(adata
->mmio
+ XLNX_AUD_CORE_CONFIG
);
369 if (!(val
& data_format_mode
))
370 stream_data
->interleaved
= true;
372 stream_data
->xfer_mode
= (val
& data_xfer_mode
) >> data_xfer_shift
;
373 stream_data
->ch_limit
= (val
& ch_count_mask
) >> ch_count_shift
;
374 dev_info(component
->dev
,
375 "stream %d : format = %d mode = %d ch_limit = %d\n",
376 substream
->stream
, stream_data
->interleaved
,
377 stream_data
->xfer_mode
, stream_data
->ch_limit
);
379 snd_soc_set_runtime_hwparams(substream
, &xlnx_pcm_hardware
);
380 runtime
->private_data
= stream_data
;
382 /* Resize the period bytes as divisible by 64 */
383 err
= snd_pcm_hw_constraint_step(runtime
, 0,
384 SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
385 XLNX_AUD_ALIGN_BYTES
);
387 dev_err(component
->dev
,
388 "Unable to set constraint on period bytes\n");
392 /* Resize the buffer bytes as divisible by 64 */
393 err
= snd_pcm_hw_constraint_step(runtime
, 0,
394 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
395 XLNX_AUD_ALIGN_BYTES
);
397 dev_err(component
->dev
,
398 "Unable to set constraint on buffer bytes\n");
402 /* Set periods as integer multiple */
403 err
= snd_pcm_hw_constraint_integer(runtime
,
404 SNDRV_PCM_HW_PARAM_PERIODS
);
406 dev_err(component
->dev
,
407 "Unable to set constraint on periods to be integer\n");
411 /* enable DMA IOC irq */
412 val
= readl(stream_data
->mmio
+ XLNX_AUD_CTRL
);
413 val
|= AUD_CTRL_IOC_IRQ_MASK
;
414 writel(val
, stream_data
->mmio
+ XLNX_AUD_CTRL
);
419 static int xlnx_formatter_pcm_close(struct snd_soc_component
*component
,
420 struct snd_pcm_substream
*substream
)
423 struct xlnx_pcm_stream_param
*stream_data
=
424 substream
->runtime
->private_data
;
426 ret
= xlnx_formatter_pcm_reset(stream_data
->mmio
);
428 dev_err(component
->dev
, "audio formatter reset failed\n");
431 xlnx_formatter_disable_irqs(stream_data
->mmio
, substream
->stream
);
438 static snd_pcm_uframes_t
439 xlnx_formatter_pcm_pointer(struct snd_soc_component
*component
,
440 struct snd_pcm_substream
*substream
)
443 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
444 struct xlnx_pcm_stream_param
*stream_data
= runtime
->private_data
;
446 pos
= readl(stream_data
->mmio
+ XLNX_AUD_XFER_COUNT
);
448 if (pos
>= stream_data
->buffer_size
)
451 return bytes_to_frames(runtime
, pos
);
454 static int xlnx_formatter_pcm_hw_params(struct snd_soc_component
*component
,
455 struct snd_pcm_substream
*substream
,
456 struct snd_pcm_hw_params
*params
)
458 u32 low
, high
, active_ch
, val
, bytes_per_ch
, bits_per_sample
;
459 u32 aes_reg1_val
, aes_reg2_val
;
461 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
462 struct xlnx_pcm_stream_param
*stream_data
= runtime
->private_data
;
463 struct xlnx_pcm_drv_data
*adata
= dev_get_drvdata(component
->dev
);
465 active_ch
= params_channels(params
);
466 if (active_ch
> stream_data
->ch_limit
)
469 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
&&
471 unsigned int mclk_fs
= adata
->sysclk
/ params_rate(params
);
473 if (adata
->sysclk
% params_rate(params
) != 0) {
474 dev_warn(component
->dev
, "sysclk %u not divisible by rate %u\n",
475 adata
->sysclk
, params_rate(params
));
479 writel(mclk_fs
, stream_data
->mmio
+ XLNX_AUD_FS_MULTIPLIER
);
482 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
&&
483 stream_data
->xfer_mode
== AES_TO_PCM
) {
484 val
= readl(stream_data
->mmio
+ XLNX_AUD_STS
);
485 if (val
& AUD_STS_CH_STS_MASK
) {
486 aes_reg1_val
= readl(stream_data
->mmio
+
487 XLNX_AUD_CH_STS_START
);
488 aes_reg2_val
= readl(stream_data
->mmio
+
489 XLNX_AUD_CH_STS_START
+ 0x4);
491 xlnx_parse_aes_params(aes_reg1_val
, aes_reg2_val
,
496 size
= params_buffer_bytes(params
);
498 stream_data
->buffer_size
= size
;
500 low
= lower_32_bits(runtime
->dma_addr
);
501 high
= upper_32_bits(runtime
->dma_addr
);
502 writel(low
, stream_data
->mmio
+ XLNX_AUD_BUFF_ADDR_LSB
);
503 writel(high
, stream_data
->mmio
+ XLNX_AUD_BUFF_ADDR_MSB
);
505 val
= readl(stream_data
->mmio
+ XLNX_AUD_CTRL
);
506 bits_per_sample
= params_width(params
);
507 switch (bits_per_sample
) {
509 val
|= (BIT_DEPTH_8
<< AUD_CTRL_DATA_WIDTH_SHIFT
);
512 val
|= (BIT_DEPTH_16
<< AUD_CTRL_DATA_WIDTH_SHIFT
);
515 val
|= (BIT_DEPTH_20
<< AUD_CTRL_DATA_WIDTH_SHIFT
);
518 val
|= (BIT_DEPTH_24
<< AUD_CTRL_DATA_WIDTH_SHIFT
);
521 val
|= (BIT_DEPTH_32
<< AUD_CTRL_DATA_WIDTH_SHIFT
);
527 val
|= active_ch
<< AUD_CTRL_ACTIVE_CH_SHIFT
;
528 writel(val
, stream_data
->mmio
+ XLNX_AUD_CTRL
);
530 val
= (params_periods(params
) << PERIOD_CFG_PERIODS_SHIFT
)
531 | params_period_bytes(params
);
532 writel(val
, stream_data
->mmio
+ XLNX_AUD_PERIOD_CONFIG
);
533 bytes_per_ch
= DIV_ROUND_UP(params_period_bytes(params
), active_ch
);
534 writel(bytes_per_ch
, stream_data
->mmio
+ XLNX_BYTES_PER_CH
);
539 static int xlnx_formatter_pcm_trigger(struct snd_soc_component
*component
,
540 struct snd_pcm_substream
*substream
,
544 struct xlnx_pcm_stream_param
*stream_data
=
545 substream
->runtime
->private_data
;
548 case SNDRV_PCM_TRIGGER_START
:
549 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
550 case SNDRV_PCM_TRIGGER_RESUME
:
551 val
= readl(stream_data
->mmio
+ XLNX_AUD_CTRL
);
552 val
|= AUD_CTRL_DMA_EN_MASK
;
553 writel(val
, stream_data
->mmio
+ XLNX_AUD_CTRL
);
555 case SNDRV_PCM_TRIGGER_STOP
:
556 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
557 case SNDRV_PCM_TRIGGER_SUSPEND
:
558 val
= readl(stream_data
->mmio
+ XLNX_AUD_CTRL
);
559 val
&= ~AUD_CTRL_DMA_EN_MASK
;
560 writel(val
, stream_data
->mmio
+ XLNX_AUD_CTRL
);
567 static int xlnx_formatter_pcm_new(struct snd_soc_component
*component
,
568 struct snd_soc_pcm_runtime
*rtd
)
570 snd_pcm_set_managed_buffer_all(rtd
->pcm
,
571 SNDRV_DMA_TYPE_DEV
, component
->dev
,
572 xlnx_pcm_hardware
.buffer_bytes_max
,
573 xlnx_pcm_hardware
.buffer_bytes_max
);
577 static const struct snd_soc_component_driver xlnx_asoc_component
= {
579 .set_sysclk
= xlnx_formatter_set_sysclk
,
580 .open
= xlnx_formatter_pcm_open
,
581 .close
= xlnx_formatter_pcm_close
,
582 .hw_params
= xlnx_formatter_pcm_hw_params
,
583 .trigger
= xlnx_formatter_pcm_trigger
,
584 .pointer
= xlnx_formatter_pcm_pointer
,
585 .pcm_construct
= xlnx_formatter_pcm_new
,
588 static int xlnx_formatter_pcm_probe(struct platform_device
*pdev
)
592 struct xlnx_pcm_drv_data
*aud_drv_data
;
593 struct device
*dev
= &pdev
->dev
;
595 aud_drv_data
= devm_kzalloc(dev
, sizeof(*aud_drv_data
), GFP_KERNEL
);
599 aud_drv_data
->axi_clk
= devm_clk_get(dev
, "s_axi_lite_aclk");
600 if (IS_ERR(aud_drv_data
->axi_clk
)) {
601 ret
= PTR_ERR(aud_drv_data
->axi_clk
);
602 dev_err(dev
, "failed to get s_axi_lite_aclk(%d)\n", ret
);
605 ret
= clk_prepare_enable(aud_drv_data
->axi_clk
);
608 "failed to enable s_axi_lite_aclk(%d)\n", ret
);
612 aud_drv_data
->mmio
= devm_platform_ioremap_resource(pdev
, 0);
613 if (IS_ERR(aud_drv_data
->mmio
)) {
614 dev_err(dev
, "audio formatter ioremap failed\n");
615 ret
= PTR_ERR(aud_drv_data
->mmio
);
619 val
= readl(aud_drv_data
->mmio
+ XLNX_AUD_CORE_CONFIG
);
620 if (val
& AUD_CFG_MM2S_MASK
) {
621 aud_drv_data
->mm2s_presence
= true;
622 ret
= xlnx_formatter_pcm_reset(aud_drv_data
->mmio
+
625 dev_err(dev
, "audio formatter reset failed\n");
628 xlnx_formatter_disable_irqs(aud_drv_data
->mmio
+
630 SNDRV_PCM_STREAM_PLAYBACK
);
632 aud_drv_data
->mm2s_irq
= platform_get_irq_byname(pdev
,
634 if (aud_drv_data
->mm2s_irq
< 0) {
635 ret
= aud_drv_data
->mm2s_irq
;
638 ret
= devm_request_irq(dev
, aud_drv_data
->mm2s_irq
,
639 xlnx_mm2s_irq_handler
, 0,
640 "xlnx_formatter_pcm_mm2s_irq", dev
);
642 dev_err(dev
, "xlnx audio mm2s irq request failed\n");
646 if (val
& AUD_CFG_S2MM_MASK
) {
647 aud_drv_data
->s2mm_presence
= true;
648 ret
= xlnx_formatter_pcm_reset(aud_drv_data
->mmio
+
651 dev_err(dev
, "audio formatter reset failed\n");
654 xlnx_formatter_disable_irqs(aud_drv_data
->mmio
+
656 SNDRV_PCM_STREAM_CAPTURE
);
658 aud_drv_data
->s2mm_irq
= platform_get_irq_byname(pdev
,
660 if (aud_drv_data
->s2mm_irq
< 0) {
661 ret
= aud_drv_data
->s2mm_irq
;
664 ret
= devm_request_irq(dev
, aud_drv_data
->s2mm_irq
,
665 xlnx_s2mm_irq_handler
, 0,
666 "xlnx_formatter_pcm_s2mm_irq",
669 dev_err(dev
, "xlnx audio s2mm irq request failed\n");
674 dev_set_drvdata(dev
, aud_drv_data
);
676 ret
= devm_snd_soc_register_component(dev
, &xlnx_asoc_component
,
679 dev_err(dev
, "pcm platform device register failed\n");
686 clk_disable_unprepare(aud_drv_data
->axi_clk
);
690 static void xlnx_formatter_pcm_remove(struct platform_device
*pdev
)
693 struct xlnx_pcm_drv_data
*adata
= dev_get_drvdata(&pdev
->dev
);
695 if (adata
->s2mm_presence
)
696 ret
= xlnx_formatter_pcm_reset(adata
->mmio
+ XLNX_S2MM_OFFSET
);
698 /* Try MM2S reset, even if S2MM reset fails */
699 if (adata
->mm2s_presence
)
700 ret
= xlnx_formatter_pcm_reset(adata
->mmio
+ XLNX_MM2S_OFFSET
);
703 dev_err(&pdev
->dev
, "audio formatter reset failed\n");
705 clk_disable_unprepare(adata
->axi_clk
);
708 static const struct of_device_id xlnx_formatter_pcm_of_match
[] = {
709 { .compatible
= "xlnx,audio-formatter-1.0"},
712 MODULE_DEVICE_TABLE(of
, xlnx_formatter_pcm_of_match
);
714 static struct platform_driver xlnx_formatter_pcm_driver
= {
715 .probe
= xlnx_formatter_pcm_probe
,
716 .remove
= xlnx_formatter_pcm_remove
,
719 .of_match_table
= xlnx_formatter_pcm_of_match
,
723 module_platform_driver(xlnx_formatter_pcm_driver
);
725 MODULE_DESCRIPTION("ASoC driver for Xilinx audio formatter");
726 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
727 MODULE_LICENSE("GPL v2");