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 };
88 
89 /*
90  * struct xlnx_pcm_stream_param - stream configuration
91  * @mmio: base address offset
92  * @interleaved: audio channels arrangement in buffer
93  * @xfer_mode: data formatting mode during transfer
94  * @ch_limit: Maximum channels supported
95  * @buffer_size: stream ring buffer size
96  */
97 struct xlnx_pcm_stream_param {
98 	void __iomem *mmio;
99 	bool interleaved;
100 	u32 xfer_mode;
101 	u32 ch_limit;
102 	u64 buffer_size;
103 };
104 
105 static const struct snd_pcm_hardware xlnx_pcm_hardware = {
106 	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
107 		SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_PAUSE |
108 		SNDRV_PCM_INFO_RESUME,
109 	.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
110 		   SNDRV_PCM_FMTBIT_S24_LE,
111 	.channels_min = 2,
112 	.channels_max = 2,
113 	.rates = SNDRV_PCM_RATE_8000_192000,
114 	.rate_min = 8000,
115 	.rate_max = 192000,
116 	.buffer_bytes_max = PERIODS_MAX * PERIOD_BYTES_MAX,
117 	.period_bytes_min = PERIOD_BYTES_MIN,
118 	.period_bytes_max = PERIOD_BYTES_MAX,
119 	.periods_min = PERIODS_MIN,
120 	.periods_max = PERIODS_MAX,
121 };
122 
123 enum {
124 	AES_TO_AES,
125 	AES_TO_PCM,
126 	PCM_TO_PCM,
127 	PCM_TO_AES
128 };
129 
130 static void xlnx_parse_aes_params(u32 chsts_reg1_val, u32 chsts_reg2_val,
131 				  struct device *dev)
132 {
133 	u32 padded, srate, bit_depth, status[2];
134 
135 	if (chsts_reg1_val & IEC958_AES0_PROFESSIONAL) {
136 		status[0] = chsts_reg1_val & 0xff;
137 		status[1] = (chsts_reg1_val >> 16) & 0xff;
138 
139 		switch (status[0] & IEC958_AES0_PRO_FS) {
140 		case IEC958_AES0_PRO_FS_44100:
141 			srate = 44100;
142 			break;
143 		case IEC958_AES0_PRO_FS_48000:
144 			srate = 48000;
145 			break;
146 		case IEC958_AES0_PRO_FS_32000:
147 			srate = 32000;
148 			break;
149 		case IEC958_AES0_PRO_FS_NOTID:
150 		default:
151 			srate = XLNX_PARAM_UNKNOWN;
152 			break;
153 		}
154 
155 		switch (status[1] & IEC958_AES2_PRO_SBITS) {
156 		case IEC958_AES2_PRO_WORDLEN_NOTID:
157 		case IEC958_AES2_PRO_SBITS_20:
158 			padded = 0;
159 			break;
160 		case IEC958_AES2_PRO_SBITS_24:
161 			padded = 4;
162 			break;
163 		default:
164 			bit_depth = XLNX_PARAM_UNKNOWN;
165 			goto log_params;
166 		}
167 
168 		switch (status[1] & IEC958_AES2_PRO_WORDLEN) {
169 		case IEC958_AES2_PRO_WORDLEN_20_16:
170 			bit_depth = 16 + padded;
171 			break;
172 		case IEC958_AES2_PRO_WORDLEN_22_18:
173 			bit_depth = 18 + padded;
174 			break;
175 		case IEC958_AES2_PRO_WORDLEN_23_19:
176 			bit_depth = 19 + padded;
177 			break;
178 		case IEC958_AES2_PRO_WORDLEN_24_20:
179 			bit_depth = 20 + padded;
180 			break;
181 		case IEC958_AES2_PRO_WORDLEN_NOTID:
182 		default:
183 			bit_depth = XLNX_PARAM_UNKNOWN;
184 			break;
185 		}
186 
187 	} else {
188 		status[0] = (chsts_reg1_val >> 24) & 0xff;
189 		status[1] = chsts_reg2_val & 0xff;
190 
191 		switch (status[0] & IEC958_AES3_CON_FS) {
192 		case IEC958_AES3_CON_FS_44100:
193 			srate = 44100;
194 			break;
195 		case IEC958_AES3_CON_FS_48000:
196 			srate = 48000;
197 			break;
198 		case IEC958_AES3_CON_FS_32000:
199 			srate = 32000;
200 			break;
201 		default:
202 			srate = XLNX_PARAM_UNKNOWN;
203 			break;
204 		}
205 
206 		if (status[1] & IEC958_AES4_CON_MAX_WORDLEN_24)
207 			padded = 4;
208 		else
209 			padded = 0;
210 
211 		switch (status[1] & IEC958_AES4_CON_WORDLEN) {
212 		case IEC958_AES4_CON_WORDLEN_20_16:
213 			bit_depth = 16 + padded;
214 			break;
215 		case IEC958_AES4_CON_WORDLEN_22_18:
216 			bit_depth = 18 + padded;
217 			break;
218 		case IEC958_AES4_CON_WORDLEN_23_19:
219 			bit_depth = 19 + padded;
220 			break;
221 		case IEC958_AES4_CON_WORDLEN_24_20:
222 			bit_depth = 20 + padded;
223 			break;
224 		case IEC958_AES4_CON_WORDLEN_21_17:
225 			bit_depth = 17 + padded;
226 			break;
227 		case IEC958_AES4_CON_WORDLEN_NOTID:
228 		default:
229 			bit_depth = XLNX_PARAM_UNKNOWN;
230 			break;
231 		}
232 	}
233 
234 log_params:
235 	if (srate != XLNX_PARAM_UNKNOWN)
236 		dev_info(dev, "sample rate = %d\n", srate);
237 	else
238 		dev_info(dev, "sample rate = unknown\n");
239 
240 	if (bit_depth != XLNX_PARAM_UNKNOWN)
241 		dev_info(dev, "bit_depth = %d\n", bit_depth);
242 	else
243 		dev_info(dev, "bit_depth = unknown\n");
244 }
245 
246 static int xlnx_formatter_pcm_reset(void __iomem *mmio_base)
247 {
248 	u32 val, retries = 0;
249 
250 	val = readl(mmio_base + XLNX_AUD_CTRL);
251 	val |= AUD_CTRL_RESET_MASK;
252 	writel(val, mmio_base + XLNX_AUD_CTRL);
253 
254 	val = readl(mmio_base + XLNX_AUD_CTRL);
255 	/* Poll for maximum timeout of approximately 100ms (1 * 100)*/
256 	while ((val & AUD_CTRL_RESET_MASK) && (retries < 100)) {
257 		mdelay(1);
258 		retries++;
259 		val = readl(mmio_base + XLNX_AUD_CTRL);
260 	}
261 	if (val & AUD_CTRL_RESET_MASK)
262 		return -ENODEV;
263 
264 	return 0;
265 }
266 
267 static void xlnx_formatter_disable_irqs(void __iomem *mmio_base, int stream)
268 {
269 	u32 val;
270 
271 	val = readl(mmio_base + XLNX_AUD_CTRL);
272 	val &= ~AUD_CTRL_IOC_IRQ_MASK;
273 	if (stream == SNDRV_PCM_STREAM_CAPTURE)
274 		val &= ~AUD_CTRL_TOUT_IRQ_MASK;
275 
276 	writel(val, mmio_base + XLNX_AUD_CTRL);
277 }
278 
279 static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg)
280 {
281 	u32 val;
282 	void __iomem *reg;
283 	struct device *dev = arg;
284 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
285 
286 	reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS;
287 	val = readl(reg);
288 	if (val & AUD_STS_IOC_IRQ_MASK) {
289 		writel(val & AUD_STS_IOC_IRQ_MASK, reg);
290 		if (adata->play_stream)
291 			snd_pcm_period_elapsed(adata->play_stream);
292 		return IRQ_HANDLED;
293 	}
294 
295 	return IRQ_NONE;
296 }
297 
298 static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
299 {
300 	u32 val;
301 	void __iomem *reg;
302 	struct device *dev = arg;
303 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
304 
305 	reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
306 	val = readl(reg);
307 	if (val & AUD_STS_IOC_IRQ_MASK) {
308 		writel(val & AUD_STS_IOC_IRQ_MASK, reg);
309 		if (adata->capture_stream)
310 			snd_pcm_period_elapsed(adata->capture_stream);
311 		return IRQ_HANDLED;
312 	}
313 
314 	return IRQ_NONE;
315 }
316 
317 static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
318 				   struct snd_pcm_substream *substream)
319 {
320 	int err;
321 	u32 val, data_format_mode;
322 	u32 ch_count_mask, ch_count_shift, data_xfer_mode, data_xfer_shift;
323 	struct xlnx_pcm_stream_param *stream_data;
324 	struct snd_pcm_runtime *runtime = substream->runtime;
325 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
326 
327 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
328 	    !adata->mm2s_presence)
329 		return -ENODEV;
330 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
331 		 !adata->s2mm_presence)
332 		return -ENODEV;
333 
334 	stream_data = kzalloc(sizeof(*stream_data), GFP_KERNEL);
335 	if (!stream_data)
336 		return -ENOMEM;
337 
338 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
339 		ch_count_mask = CFG_MM2S_CH_MASK;
340 		ch_count_shift = CFG_MM2S_CH_SHIFT;
341 		data_xfer_mode = CFG_MM2S_XFER_MASK;
342 		data_xfer_shift = CFG_MM2S_XFER_SHIFT;
343 		data_format_mode = CFG_MM2S_PKG_MASK;
344 		stream_data->mmio = adata->mmio + XLNX_MM2S_OFFSET;
345 		adata->play_stream = substream;
346 
347 	} else {
348 		ch_count_mask = CFG_S2MM_CH_MASK;
349 		ch_count_shift = CFG_S2MM_CH_SHIFT;
350 		data_xfer_mode = CFG_S2MM_XFER_MASK;
351 		data_xfer_shift = CFG_S2MM_XFER_SHIFT;
352 		data_format_mode = CFG_S2MM_PKG_MASK;
353 		stream_data->mmio = adata->mmio + XLNX_S2MM_OFFSET;
354 		adata->capture_stream = substream;
355 	}
356 
357 	val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG);
358 
359 	if (!(val & data_format_mode))
360 		stream_data->interleaved = true;
361 
362 	stream_data->xfer_mode = (val & data_xfer_mode) >> data_xfer_shift;
363 	stream_data->ch_limit = (val & ch_count_mask) >> ch_count_shift;
364 	dev_info(component->dev,
365 		 "stream %d : format = %d mode = %d ch_limit = %d\n",
366 		 substream->stream, stream_data->interleaved,
367 		 stream_data->xfer_mode, stream_data->ch_limit);
368 
369 	snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
370 	runtime->private_data = stream_data;
371 
372 	/* Resize the period bytes as divisible by 64 */
373 	err = snd_pcm_hw_constraint_step(runtime, 0,
374 					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
375 					 XLNX_AUD_ALIGN_BYTES);
376 	if (err) {
377 		dev_err(component->dev,
378 			"Unable to set constraint on period bytes\n");
379 		return err;
380 	}
381 
382 	/* Resize the buffer bytes as divisible by 64 */
383 	err = snd_pcm_hw_constraint_step(runtime, 0,
384 					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
385 					 XLNX_AUD_ALIGN_BYTES);
386 	if (err) {
387 		dev_err(component->dev,
388 			"Unable to set constraint on buffer bytes\n");
389 		return err;
390 	}
391 
392 	/* Set periods as integer multiple */
393 	err = snd_pcm_hw_constraint_integer(runtime,
394 					    SNDRV_PCM_HW_PARAM_PERIODS);
395 	if (err < 0) {
396 		dev_err(component->dev,
397 			"Unable to set constraint on periods to be integer\n");
398 		return err;
399 	}
400 
401 	/* enable DMA IOC irq */
402 	val = readl(stream_data->mmio + XLNX_AUD_CTRL);
403 	val |= AUD_CTRL_IOC_IRQ_MASK;
404 	writel(val, stream_data->mmio + XLNX_AUD_CTRL);
405 
406 	return 0;
407 }
408 
409 static int xlnx_formatter_pcm_close(struct snd_soc_component *component,
410 				    struct snd_pcm_substream *substream)
411 {
412 	int ret;
413 	struct xlnx_pcm_stream_param *stream_data =
414 			substream->runtime->private_data;
415 
416 	ret = xlnx_formatter_pcm_reset(stream_data->mmio);
417 	if (ret) {
418 		dev_err(component->dev, "audio formatter reset failed\n");
419 		goto err_reset;
420 	}
421 	xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream);
422 
423 err_reset:
424 	kfree(stream_data);
425 	return 0;
426 }
427 
428 static snd_pcm_uframes_t
429 xlnx_formatter_pcm_pointer(struct snd_soc_component *component,
430 			   struct snd_pcm_substream *substream)
431 {
432 	u32 pos;
433 	struct snd_pcm_runtime *runtime = substream->runtime;
434 	struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
435 
436 	pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT);
437 
438 	if (pos >= stream_data->buffer_size)
439 		pos = 0;
440 
441 	return bytes_to_frames(runtime, pos);
442 }
443 
444 static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
445 					struct snd_pcm_substream *substream,
446 					struct snd_pcm_hw_params *params)
447 {
448 	u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample;
449 	u32 aes_reg1_val, aes_reg2_val;
450 	u64 size;
451 	struct snd_pcm_runtime *runtime = substream->runtime;
452 	struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
453 
454 	active_ch = params_channels(params);
455 	if (active_ch > stream_data->ch_limit)
456 		return -EINVAL;
457 
458 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
459 	    stream_data->xfer_mode == AES_TO_PCM) {
460 		val = readl(stream_data->mmio + XLNX_AUD_STS);
461 		if (val & AUD_STS_CH_STS_MASK) {
462 			aes_reg1_val = readl(stream_data->mmio +
463 					     XLNX_AUD_CH_STS_START);
464 			aes_reg2_val = readl(stream_data->mmio +
465 					     XLNX_AUD_CH_STS_START + 0x4);
466 
467 			xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val,
468 					      component->dev);
469 		}
470 	}
471 
472 	size = params_buffer_bytes(params);
473 
474 	stream_data->buffer_size = size;
475 
476 	low = lower_32_bits(runtime->dma_addr);
477 	high = upper_32_bits(runtime->dma_addr);
478 	writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
479 	writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
480 
481 	val = readl(stream_data->mmio + XLNX_AUD_CTRL);
482 	bits_per_sample = params_width(params);
483 	switch (bits_per_sample) {
484 	case 8:
485 		val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT);
486 		break;
487 	case 16:
488 		val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT);
489 		break;
490 	case 20:
491 		val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT);
492 		break;
493 	case 24:
494 		val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT);
495 		break;
496 	case 32:
497 		val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT);
498 		break;
499 	default:
500 		return -EINVAL;
501 	}
502 
503 	val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT;
504 	writel(val, stream_data->mmio + XLNX_AUD_CTRL);
505 
506 	val = (params_periods(params) << PERIOD_CFG_PERIODS_SHIFT)
507 		| params_period_bytes(params);
508 	writel(val, stream_data->mmio + XLNX_AUD_PERIOD_CONFIG);
509 	bytes_per_ch = DIV_ROUND_UP(params_period_bytes(params), active_ch);
510 	writel(bytes_per_ch, stream_data->mmio + XLNX_BYTES_PER_CH);
511 
512 	return 0;
513 }
514 
515 static int xlnx_formatter_pcm_trigger(struct snd_soc_component *component,
516 				      struct snd_pcm_substream *substream,
517 				      int cmd)
518 {
519 	u32 val;
520 	struct xlnx_pcm_stream_param *stream_data =
521 			substream->runtime->private_data;
522 
523 	switch (cmd) {
524 	case SNDRV_PCM_TRIGGER_START:
525 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
526 	case SNDRV_PCM_TRIGGER_RESUME:
527 		val = readl(stream_data->mmio + XLNX_AUD_CTRL);
528 		val |= AUD_CTRL_DMA_EN_MASK;
529 		writel(val, stream_data->mmio + XLNX_AUD_CTRL);
530 		break;
531 	case SNDRV_PCM_TRIGGER_STOP:
532 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
533 	case SNDRV_PCM_TRIGGER_SUSPEND:
534 		val = readl(stream_data->mmio + XLNX_AUD_CTRL);
535 		val &= ~AUD_CTRL_DMA_EN_MASK;
536 		writel(val, stream_data->mmio + XLNX_AUD_CTRL);
537 		break;
538 	}
539 
540 	return 0;
541 }
542 
543 static int xlnx_formatter_pcm_new(struct snd_soc_component *component,
544 				  struct snd_soc_pcm_runtime *rtd)
545 {
546 	snd_pcm_set_managed_buffer_all(rtd->pcm,
547 			SNDRV_DMA_TYPE_DEV, component->dev,
548 			xlnx_pcm_hardware.buffer_bytes_max,
549 			xlnx_pcm_hardware.buffer_bytes_max);
550 	return 0;
551 }
552 
553 static const struct snd_soc_component_driver xlnx_asoc_component = {
554 	.name		= DRV_NAME,
555 	.open		= xlnx_formatter_pcm_open,
556 	.close		= xlnx_formatter_pcm_close,
557 	.hw_params	= xlnx_formatter_pcm_hw_params,
558 	.trigger	= xlnx_formatter_pcm_trigger,
559 	.pointer	= xlnx_formatter_pcm_pointer,
560 	.pcm_construct	= xlnx_formatter_pcm_new,
561 };
562 
563 static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
564 {
565 	int ret;
566 	u32 val;
567 	struct xlnx_pcm_drv_data *aud_drv_data;
568 	struct device *dev = &pdev->dev;
569 
570 	aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL);
571 	if (!aud_drv_data)
572 		return -ENOMEM;
573 
574 	aud_drv_data->axi_clk = devm_clk_get(dev, "s_axi_lite_aclk");
575 	if (IS_ERR(aud_drv_data->axi_clk)) {
576 		ret = PTR_ERR(aud_drv_data->axi_clk);
577 		dev_err(dev, "failed to get s_axi_lite_aclk(%d)\n", ret);
578 		return ret;
579 	}
580 	ret = clk_prepare_enable(aud_drv_data->axi_clk);
581 	if (ret) {
582 		dev_err(dev,
583 			"failed to enable s_axi_lite_aclk(%d)\n", ret);
584 		return ret;
585 	}
586 
587 	aud_drv_data->mmio = devm_platform_ioremap_resource(pdev, 0);
588 	if (IS_ERR(aud_drv_data->mmio)) {
589 		dev_err(dev, "audio formatter ioremap failed\n");
590 		ret = PTR_ERR(aud_drv_data->mmio);
591 		goto clk_err;
592 	}
593 
594 	val = readl(aud_drv_data->mmio + XLNX_AUD_CORE_CONFIG);
595 	if (val & AUD_CFG_MM2S_MASK) {
596 		aud_drv_data->mm2s_presence = true;
597 		ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
598 					       XLNX_MM2S_OFFSET);
599 		if (ret) {
600 			dev_err(dev, "audio formatter reset failed\n");
601 			goto clk_err;
602 		}
603 		xlnx_formatter_disable_irqs(aud_drv_data->mmio +
604 					    XLNX_MM2S_OFFSET,
605 					    SNDRV_PCM_STREAM_PLAYBACK);
606 
607 		aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev,
608 								 "irq_mm2s");
609 		if (aud_drv_data->mm2s_irq < 0) {
610 			ret = aud_drv_data->mm2s_irq;
611 			goto clk_err;
612 		}
613 		ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
614 				       xlnx_mm2s_irq_handler, 0,
615 				       "xlnx_formatter_pcm_mm2s_irq", dev);
616 		if (ret) {
617 			dev_err(dev, "xlnx audio mm2s irq request failed\n");
618 			goto clk_err;
619 		}
620 	}
621 	if (val & AUD_CFG_S2MM_MASK) {
622 		aud_drv_data->s2mm_presence = true;
623 		ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
624 					       XLNX_S2MM_OFFSET);
625 		if (ret) {
626 			dev_err(dev, "audio formatter reset failed\n");
627 			goto clk_err;
628 		}
629 		xlnx_formatter_disable_irqs(aud_drv_data->mmio +
630 					    XLNX_S2MM_OFFSET,
631 					    SNDRV_PCM_STREAM_CAPTURE);
632 
633 		aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
634 								 "irq_s2mm");
635 		if (aud_drv_data->s2mm_irq < 0) {
636 			ret = aud_drv_data->s2mm_irq;
637 			goto clk_err;
638 		}
639 		ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
640 				       xlnx_s2mm_irq_handler, 0,
641 				       "xlnx_formatter_pcm_s2mm_irq",
642 				       dev);
643 		if (ret) {
644 			dev_err(dev, "xlnx audio s2mm irq request failed\n");
645 			goto clk_err;
646 		}
647 	}
648 
649 	dev_set_drvdata(dev, aud_drv_data);
650 
651 	ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
652 					      NULL, 0);
653 	if (ret) {
654 		dev_err(dev, "pcm platform device register failed\n");
655 		goto clk_err;
656 	}
657 
658 	return 0;
659 
660 clk_err:
661 	clk_disable_unprepare(aud_drv_data->axi_clk);
662 	return ret;
663 }
664 
665 static int xlnx_formatter_pcm_remove(struct platform_device *pdev)
666 {
667 	int ret = 0;
668 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
669 
670 	if (adata->s2mm_presence)
671 		ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
672 
673 	/* Try MM2S reset, even if S2MM  reset fails */
674 	if (adata->mm2s_presence)
675 		ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET);
676 
677 	if (ret)
678 		dev_err(&pdev->dev, "audio formatter reset failed\n");
679 
680 	clk_disable_unprepare(adata->axi_clk);
681 	return ret;
682 }
683 
684 static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
685 	{ .compatible = "xlnx,audio-formatter-1.0"},
686 	{},
687 };
688 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
689 
690 static struct platform_driver xlnx_formatter_pcm_driver = {
691 	.probe	= xlnx_formatter_pcm_probe,
692 	.remove	= xlnx_formatter_pcm_remove,
693 	.driver	= {
694 		.name	= DRV_NAME,
695 		.of_match_table	= xlnx_formatter_pcm_of_match,
696 	},
697 };
698 
699 module_platform_driver(xlnx_formatter_pcm_driver);
700 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
701 MODULE_LICENSE("GPL v2");
702