xref: /linux/sound/soc/xilinx/xlnx_formatter_pcm.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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 = 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 
725 MODULE_DESCRIPTION("ASoC driver for Xilinx audio formatter");
726 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
727 MODULE_LICENSE("GPL v2");
728