arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / soc / xilinx / xlnx_formatter_pcm.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Xilinx ASoC audio formatter support
4 //
5 // Copyright (C) 2018 Xilinx, Inc.
6 //
7 // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
8
9 #include <linux/clk.h>
10 #include <linux/io.h>
11 #include <linux/module.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 #include <linux/sizes.h>
15
16 #include <sound/asoundef.h>
17 #include <sound/soc.h>
18 #include <sound/pcm_params.h>
19
20 #define DRV_NAME "xlnx_formatter_pcm"
21
22 #define XLNX_S2MM_OFFSET        0
23 #define XLNX_MM2S_OFFSET        0x100
24
25 #define XLNX_AUD_CORE_CONFIG    0x4
26 #define XLNX_AUD_CTRL           0x10
27 #define XLNX_AUD_STS            0x14
28
29 #define AUD_CTRL_RESET_MASK     BIT(1)
30 #define AUD_CFG_MM2S_MASK       BIT(15)
31 #define AUD_CFG_S2MM_MASK       BIT(31)
32
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
41
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)
47
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)
53
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)
59
60 #define AUD_CTRL_DATA_WIDTH_SHIFT       16
61 #define AUD_CTRL_ACTIVE_CH_SHIFT        19
62 #define PERIOD_CFG_PERIODS_SHIFT        16
63
64 #define PERIODS_MIN             2
65 #define PERIODS_MAX             6
66 #define PERIOD_BYTES_MIN        192
67 #define PERIOD_BYTES_MAX        (50 * 1024)
68 #define XLNX_PARAM_UNKNOWN      0
69
70 enum bit_depth {
71         BIT_DEPTH_8,
72         BIT_DEPTH_16,
73         BIT_DEPTH_20,
74         BIT_DEPTH_24,
75         BIT_DEPTH_32,
76 };
77
78 struct xlnx_pcm_drv_data {
79         void __iomem *mmio;
80         bool s2mm_presence;
81         bool mm2s_presence;
82         int s2mm_irq;
83         int mm2s_irq;
84         struct snd_pcm_substream *play_stream;
85         struct snd_pcm_substream *capture_stream;
86         struct clk *axi_clk;
87         unsigned int sysclk;
88 };
89
90 /*
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
97  */
98 struct xlnx_pcm_stream_param {
99         void __iomem *mmio;
100         bool interleaved;
101         u32 xfer_mode;
102         u32 ch_limit;
103         u64 buffer_size;
104 };
105
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,
112         .channels_min = 2,
113         .channels_max = 2,
114         .rates = SNDRV_PCM_RATE_8000_192000,
115         .rate_min = 8000,
116         .rate_max = 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,
122 };
123
124 enum {
125         AES_TO_AES,
126         AES_TO_PCM,
127         PCM_TO_PCM,
128         PCM_TO_AES
129 };
130
131 static void xlnx_parse_aes_params(u32 chsts_reg1_val, u32 chsts_reg2_val,
132                                   struct device *dev)
133 {
134         u32 padded, srate, bit_depth, status[2];
135
136         if (chsts_reg1_val & IEC958_AES0_PROFESSIONAL) {
137                 status[0] = chsts_reg1_val & 0xff;
138                 status[1] = (chsts_reg1_val >> 16) & 0xff;
139
140                 switch (status[0] & IEC958_AES0_PRO_FS) {
141                 case IEC958_AES0_PRO_FS_44100:
142                         srate = 44100;
143                         break;
144                 case IEC958_AES0_PRO_FS_48000:
145                         srate = 48000;
146                         break;
147                 case IEC958_AES0_PRO_FS_32000:
148                         srate = 32000;
149                         break;
150                 case IEC958_AES0_PRO_FS_NOTID:
151                 default:
152                         srate = XLNX_PARAM_UNKNOWN;
153                         break;
154                 }
155
156                 switch (status[1] & IEC958_AES2_PRO_SBITS) {
157                 case IEC958_AES2_PRO_WORDLEN_NOTID:
158                 case IEC958_AES2_PRO_SBITS_20:
159                         padded = 0;
160                         break;
161                 case IEC958_AES2_PRO_SBITS_24:
162                         padded = 4;
163                         break;
164                 default:
165                         bit_depth = XLNX_PARAM_UNKNOWN;
166                         goto log_params;
167                 }
168
169                 switch (status[1] & IEC958_AES2_PRO_WORDLEN) {
170                 case IEC958_AES2_PRO_WORDLEN_20_16:
171                         bit_depth = 16 + padded;
172                         break;
173                 case IEC958_AES2_PRO_WORDLEN_22_18:
174                         bit_depth = 18 + padded;
175                         break;
176                 case IEC958_AES2_PRO_WORDLEN_23_19:
177                         bit_depth = 19 + padded;
178                         break;
179                 case IEC958_AES2_PRO_WORDLEN_24_20:
180                         bit_depth = 20 + padded;
181                         break;
182                 case IEC958_AES2_PRO_WORDLEN_NOTID:
183                 default:
184                         bit_depth = XLNX_PARAM_UNKNOWN;
185                         break;
186                 }
187
188         } else {
189                 status[0] = (chsts_reg1_val >> 24) & 0xff;
190                 status[1] = chsts_reg2_val & 0xff;
191
192                 switch (status[0] & IEC958_AES3_CON_FS) {
193                 case IEC958_AES3_CON_FS_44100:
194                         srate = 44100;
195                         break;
196                 case IEC958_AES3_CON_FS_48000:
197                         srate = 48000;
198                         break;
199                 case IEC958_AES3_CON_FS_32000:
200                         srate = 32000;
201                         break;
202                 default:
203                         srate = XLNX_PARAM_UNKNOWN;
204                         break;
205                 }
206
207                 if (status[1] & IEC958_AES4_CON_MAX_WORDLEN_24)
208                         padded = 4;
209                 else
210                         padded = 0;
211
212                 switch (status[1] & IEC958_AES4_CON_WORDLEN) {
213                 case IEC958_AES4_CON_WORDLEN_20_16:
214                         bit_depth = 16 + padded;
215                         break;
216                 case IEC958_AES4_CON_WORDLEN_22_18:
217                         bit_depth = 18 + padded;
218                         break;
219                 case IEC958_AES4_CON_WORDLEN_23_19:
220                         bit_depth = 19 + padded;
221                         break;
222                 case IEC958_AES4_CON_WORDLEN_24_20:
223                         bit_depth = 20 + padded;
224                         break;
225                 case IEC958_AES4_CON_WORDLEN_21_17:
226                         bit_depth = 17 + padded;
227                         break;
228                 case IEC958_AES4_CON_WORDLEN_NOTID:
229                 default:
230                         bit_depth = XLNX_PARAM_UNKNOWN;
231                         break;
232                 }
233         }
234
235 log_params:
236         if (srate != XLNX_PARAM_UNKNOWN)
237                 dev_info(dev, "sample rate = %d\n", srate);
238         else
239                 dev_info(dev, "sample rate = unknown\n");
240
241         if (bit_depth != XLNX_PARAM_UNKNOWN)
242                 dev_info(dev, "bit_depth = %d\n", bit_depth);
243         else
244                 dev_info(dev, "bit_depth = unknown\n");
245 }
246
247 static int xlnx_formatter_pcm_reset(void __iomem *mmio_base)
248 {
249         u32 val, retries = 0;
250
251         val = readl(mmio_base + XLNX_AUD_CTRL);
252         val |= AUD_CTRL_RESET_MASK;
253         writel(val, mmio_base + XLNX_AUD_CTRL);
254
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)) {
258                 mdelay(1);
259                 retries++;
260                 val = readl(mmio_base + XLNX_AUD_CTRL);
261         }
262         if (val & AUD_CTRL_RESET_MASK)
263                 return -ENODEV;
264
265         return 0;
266 }
267
268 static void xlnx_formatter_disable_irqs(void __iomem *mmio_base, int stream)
269 {
270         u32 val;
271
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;
276
277         writel(val, mmio_base + XLNX_AUD_CTRL);
278 }
279
280 static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg)
281 {
282         u32 val;
283         void __iomem *reg;
284         struct device *dev = arg;
285         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
286
287         reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS;
288         val = readl(reg);
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);
293                 return IRQ_HANDLED;
294         }
295
296         return IRQ_NONE;
297 }
298
299 static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
300 {
301         u32 val;
302         void __iomem *reg;
303         struct device *dev = arg;
304         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
305
306         reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
307         val = readl(reg);
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);
312                 return IRQ_HANDLED;
313         }
314
315         return IRQ_NONE;
316 }
317
318 static int xlnx_formatter_set_sysclk(struct snd_soc_component *component,
319                                      int clk_id, int source, unsigned int freq, int dir)
320 {
321         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
322
323         adata->sysclk = freq;
324         return 0;
325 }
326
327 static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
328                                    struct snd_pcm_substream *substream)
329 {
330         int err;
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);
336
337         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
338             !adata->mm2s_presence)
339                 return -ENODEV;
340         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
341                  !adata->s2mm_presence)
342                 return -ENODEV;
343
344         stream_data = kzalloc(sizeof(*stream_data), GFP_KERNEL);
345         if (!stream_data)
346                 return -ENOMEM;
347
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;
356
357         } else {
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;
365         }
366
367         val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG);
368
369         if (!(val & data_format_mode))
370                 stream_data->interleaved = true;
371
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);
378
379         snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
380         runtime->private_data = stream_data;
381
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);
386         if (err) {
387                 dev_err(component->dev,
388                         "Unable to set constraint on period bytes\n");
389                 return err;
390         }
391
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);
396         if (err) {
397                 dev_err(component->dev,
398                         "Unable to set constraint on buffer bytes\n");
399                 return err;
400         }
401
402         /* Set periods as integer multiple */
403         err = snd_pcm_hw_constraint_integer(runtime,
404                                             SNDRV_PCM_HW_PARAM_PERIODS);
405         if (err < 0) {
406                 dev_err(component->dev,
407                         "Unable to set constraint on periods to be integer\n");
408                 return err;
409         }
410
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);
415
416         return 0;
417 }
418
419 static int xlnx_formatter_pcm_close(struct snd_soc_component *component,
420                                     struct snd_pcm_substream *substream)
421 {
422         int ret;
423         struct xlnx_pcm_stream_param *stream_data =
424                         substream->runtime->private_data;
425
426         ret = xlnx_formatter_pcm_reset(stream_data->mmio);
427         if (ret) {
428                 dev_err(component->dev, "audio formatter reset failed\n");
429                 goto err_reset;
430         }
431         xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream);
432
433 err_reset:
434         kfree(stream_data);
435         return 0;
436 }
437
438 static snd_pcm_uframes_t
439 xlnx_formatter_pcm_pointer(struct snd_soc_component *component,
440                            struct snd_pcm_substream *substream)
441 {
442         u32 pos;
443         struct snd_pcm_runtime *runtime = substream->runtime;
444         struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
445
446         pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT);
447
448         if (pos >= stream_data->buffer_size)
449                 pos = 0;
450
451         return bytes_to_frames(runtime, pos);
452 }
453
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)
457 {
458         u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample;
459         u32 aes_reg1_val, aes_reg2_val;
460         u64 size;
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);
464
465         active_ch = params_channels(params);
466         if (active_ch > stream_data->ch_limit)
467                 return -EINVAL;
468
469         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
470             adata->sysclk) {
471                 unsigned int mclk_fs = adata->sysclk / params_rate(params);
472
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));
476                         return -EINVAL;
477                 }
478
479                 writel(mclk_fs, stream_data->mmio + XLNX_AUD_FS_MULTIPLIER);
480         }
481
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);
490
491                         xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val,
492                                               component->dev);
493                 }
494         }
495
496         size = params_buffer_bytes(params);
497
498         stream_data->buffer_size = size;
499
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);
504
505         val = readl(stream_data->mmio + XLNX_AUD_CTRL);
506         bits_per_sample = params_width(params);
507         switch (bits_per_sample) {
508         case 8:
509                 val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT);
510                 break;
511         case 16:
512                 val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT);
513                 break;
514         case 20:
515                 val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT);
516                 break;
517         case 24:
518                 val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT);
519                 break;
520         case 32:
521                 val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT);
522                 break;
523         default:
524                 return -EINVAL;
525         }
526
527         val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT;
528         writel(val, stream_data->mmio + XLNX_AUD_CTRL);
529
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);
535
536         return 0;
537 }
538
539 static int xlnx_formatter_pcm_trigger(struct snd_soc_component *component,
540                                       struct snd_pcm_substream *substream,
541                                       int cmd)
542 {
543         u32 val;
544         struct xlnx_pcm_stream_param *stream_data =
545                         substream->runtime->private_data;
546
547         switch (cmd) {
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);
554                 break;
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);
561                 break;
562         }
563
564         return 0;
565 }
566
567 static int xlnx_formatter_pcm_new(struct snd_soc_component *component,
568                                   struct snd_soc_pcm_runtime *rtd)
569 {
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);
574         return 0;
575 }
576
577 static const struct snd_soc_component_driver xlnx_asoc_component = {
578         .name                   = DRV_NAME,
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,
586 };
587
588 static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
589 {
590         int ret;
591         u32 val;
592         struct xlnx_pcm_drv_data *aud_drv_data;
593         struct device *dev = &pdev->dev;
594
595         aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL);
596         if (!aud_drv_data)
597                 return -ENOMEM;
598
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);
603                 return ret;
604         }
605         ret = clk_prepare_enable(aud_drv_data->axi_clk);
606         if (ret) {
607                 dev_err(dev,
608                         "failed to enable s_axi_lite_aclk(%d)\n", ret);
609                 return ret;
610         }
611
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);
616                 goto clk_err;
617         }
618
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 +
623                                                XLNX_MM2S_OFFSET);
624                 if (ret) {
625                         dev_err(dev, "audio formatter reset failed\n");
626                         goto clk_err;
627                 }
628                 xlnx_formatter_disable_irqs(aud_drv_data->mmio +
629                                             XLNX_MM2S_OFFSET,
630                                             SNDRV_PCM_STREAM_PLAYBACK);
631
632                 aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev,
633                                                                  "irq_mm2s");
634                 if (aud_drv_data->mm2s_irq < 0) {
635                         ret = aud_drv_data->mm2s_irq;
636                         goto clk_err;
637                 }
638                 ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
639                                        xlnx_mm2s_irq_handler, 0,
640                                        "xlnx_formatter_pcm_mm2s_irq", dev);
641                 if (ret) {
642                         dev_err(dev, "xlnx audio mm2s irq request failed\n");
643                         goto clk_err;
644                 }
645         }
646         if (val & AUD_CFG_S2MM_MASK) {
647                 aud_drv_data->s2mm_presence = true;
648                 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
649                                                XLNX_S2MM_OFFSET);
650                 if (ret) {
651                         dev_err(dev, "audio formatter reset failed\n");
652                         goto clk_err;
653                 }
654                 xlnx_formatter_disable_irqs(aud_drv_data->mmio +
655                                             XLNX_S2MM_OFFSET,
656                                             SNDRV_PCM_STREAM_CAPTURE);
657
658                 aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
659                                                                  "irq_s2mm");
660                 if (aud_drv_data->s2mm_irq < 0) {
661                         ret = aud_drv_data->s2mm_irq;
662                         goto clk_err;
663                 }
664                 ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
665                                        xlnx_s2mm_irq_handler, 0,
666                                        "xlnx_formatter_pcm_s2mm_irq",
667                                        dev);
668                 if (ret) {
669                         dev_err(dev, "xlnx audio s2mm irq request failed\n");
670                         goto clk_err;
671                 }
672         }
673
674         dev_set_drvdata(dev, aud_drv_data);
675
676         ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
677                                               NULL, 0);
678         if (ret) {
679                 dev_err(dev, "pcm platform device register failed\n");
680                 goto clk_err;
681         }
682
683         return 0;
684
685 clk_err:
686         clk_disable_unprepare(aud_drv_data->axi_clk);
687         return ret;
688 }
689
690 static void xlnx_formatter_pcm_remove(struct platform_device *pdev)
691 {
692         int ret = 0;
693         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
694
695         if (adata->s2mm_presence)
696                 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
697
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);
701
702         if (ret)
703                 dev_err(&pdev->dev, "audio formatter reset failed\n");
704
705         clk_disable_unprepare(adata->axi_clk);
706 }
707
708 static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
709         { .compatible = "xlnx,audio-formatter-1.0"},
710         {},
711 };
712 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
713
714 static struct platform_driver xlnx_formatter_pcm_driver = {
715         .probe  = xlnx_formatter_pcm_probe,
716         .remove_new = xlnx_formatter_pcm_remove,
717         .driver = {
718                 .name   = DRV_NAME,
719                 .of_match_table = xlnx_formatter_pcm_of_match,
720         },
721 };
722
723 module_platform_driver(xlnx_formatter_pcm_driver);
724 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
725 MODULE_LICENSE("GPL v2");