xref: /linux/sound/soc/xilinx/xlnx_formatter_pcm.c (revision c44e278ce02efd0c4be79a8eda1ea6885c1ce5ec)
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 xlnx_pcm_drv_data *adata = arg;
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 xlnx_pcm_drv_data *adata = arg;
303 
304 	reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
305 	val = readl(reg);
306 	if (val & AUD_STS_IOC_IRQ_MASK) {
307 		writel(val & AUD_STS_IOC_IRQ_MASK, reg);
308 		if (adata->capture_stream)
309 			snd_pcm_period_elapsed(adata->capture_stream);
310 		return IRQ_HANDLED;
311 	}
312 
313 	return IRQ_NONE;
314 }
315 
316 static int xlnx_formatter_set_sysclk(struct snd_soc_component *component,
317 				     int clk_id, int source, unsigned int freq, int dir)
318 {
319 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
320 
321 	adata->sysclk = freq;
322 	return 0;
323 }
324 
325 static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
326 				   struct snd_pcm_substream *substream)
327 {
328 	int err;
329 	u32 val, data_format_mode;
330 	u32 ch_count_mask, ch_count_shift, data_xfer_mode, data_xfer_shift;
331 	struct xlnx_pcm_stream_param *stream_data;
332 	struct snd_pcm_runtime *runtime = substream->runtime;
333 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
334 
335 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
336 	    !adata->mm2s_presence)
337 		return -ENODEV;
338 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
339 		 !adata->s2mm_presence)
340 		return -ENODEV;
341 
342 	stream_data = kzalloc_obj(*stream_data);
343 	if (!stream_data)
344 		return -ENOMEM;
345 
346 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
347 		ch_count_mask = CFG_MM2S_CH_MASK;
348 		ch_count_shift = CFG_MM2S_CH_SHIFT;
349 		data_xfer_mode = CFG_MM2S_XFER_MASK;
350 		data_xfer_shift = CFG_MM2S_XFER_SHIFT;
351 		data_format_mode = CFG_MM2S_PKG_MASK;
352 		stream_data->mmio = adata->mmio + XLNX_MM2S_OFFSET;
353 		adata->play_stream = substream;
354 
355 	} else {
356 		ch_count_mask = CFG_S2MM_CH_MASK;
357 		ch_count_shift = CFG_S2MM_CH_SHIFT;
358 		data_xfer_mode = CFG_S2MM_XFER_MASK;
359 		data_xfer_shift = CFG_S2MM_XFER_SHIFT;
360 		data_format_mode = CFG_S2MM_PKG_MASK;
361 		stream_data->mmio = adata->mmio + XLNX_S2MM_OFFSET;
362 		adata->capture_stream = substream;
363 	}
364 
365 	val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG);
366 
367 	if (!(val & data_format_mode))
368 		stream_data->interleaved = true;
369 
370 	stream_data->xfer_mode = (val & data_xfer_mode) >> data_xfer_shift;
371 	stream_data->ch_limit = (val & ch_count_mask) >> ch_count_shift;
372 	dev_info(component->dev,
373 		 "stream %d : format = %d mode = %d ch_limit = %d\n",
374 		 substream->stream, stream_data->interleaved,
375 		 stream_data->xfer_mode, stream_data->ch_limit);
376 
377 	snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
378 	runtime->private_data = stream_data;
379 
380 	/* Resize the period bytes as divisible by 64 */
381 	err = snd_pcm_hw_constraint_step(runtime, 0,
382 					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
383 					 XLNX_AUD_ALIGN_BYTES);
384 	if (err) {
385 		dev_err(component->dev,
386 			"Unable to set constraint on period bytes\n");
387 		return err;
388 	}
389 
390 	/* Resize the buffer bytes as divisible by 64 */
391 	err = snd_pcm_hw_constraint_step(runtime, 0,
392 					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
393 					 XLNX_AUD_ALIGN_BYTES);
394 	if (err) {
395 		dev_err(component->dev,
396 			"Unable to set constraint on buffer bytes\n");
397 		return err;
398 	}
399 
400 	/* Set periods as integer multiple */
401 	err = snd_pcm_hw_constraint_integer(runtime,
402 					    SNDRV_PCM_HW_PARAM_PERIODS);
403 	if (err < 0) {
404 		dev_err(component->dev,
405 			"Unable to set constraint on periods to be integer\n");
406 		return err;
407 	}
408 
409 	/* enable DMA IOC irq */
410 	val = readl(stream_data->mmio + XLNX_AUD_CTRL);
411 	val |= AUD_CTRL_IOC_IRQ_MASK;
412 	writel(val, stream_data->mmio + XLNX_AUD_CTRL);
413 
414 	return 0;
415 }
416 
417 static int xlnx_formatter_pcm_close(struct snd_soc_component *component,
418 				    struct snd_pcm_substream *substream)
419 {
420 	int ret;
421 	struct xlnx_pcm_stream_param *stream_data =
422 			substream->runtime->private_data;
423 
424 	ret = xlnx_formatter_pcm_reset(stream_data->mmio);
425 	if (ret) {
426 		dev_err(component->dev, "audio formatter reset failed\n");
427 		goto err_reset;
428 	}
429 	xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream);
430 
431 err_reset:
432 	kfree(stream_data);
433 	return 0;
434 }
435 
436 static snd_pcm_uframes_t
437 xlnx_formatter_pcm_pointer(struct snd_soc_component *component,
438 			   struct snd_pcm_substream *substream)
439 {
440 	u32 pos;
441 	struct snd_pcm_runtime *runtime = substream->runtime;
442 	struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
443 
444 	pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT);
445 
446 	if (pos >= stream_data->buffer_size)
447 		pos = 0;
448 
449 	return bytes_to_frames(runtime, pos);
450 }
451 
452 static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
453 					struct snd_pcm_substream *substream,
454 					struct snd_pcm_hw_params *params)
455 {
456 	u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample;
457 	u32 aes_reg1_val, aes_reg2_val;
458 	u64 size;
459 	struct snd_pcm_runtime *runtime = substream->runtime;
460 	struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
461 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
462 
463 	active_ch = params_channels(params);
464 	if (active_ch > stream_data->ch_limit)
465 		return -EINVAL;
466 
467 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
468 	    adata->sysclk) {
469 		unsigned int mclk_fs = adata->sysclk / params_rate(params);
470 
471 		if (adata->sysclk % params_rate(params) != 0) {
472 			dev_warn(component->dev, "sysclk %u not divisible by rate %u\n",
473 				 adata->sysclk, params_rate(params));
474 			return -EINVAL;
475 		}
476 
477 		writel(mclk_fs, stream_data->mmio + XLNX_AUD_FS_MULTIPLIER);
478 	}
479 
480 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
481 	    stream_data->xfer_mode == AES_TO_PCM) {
482 		val = readl(stream_data->mmio + XLNX_AUD_STS);
483 		if (val & AUD_STS_CH_STS_MASK) {
484 			aes_reg1_val = readl(stream_data->mmio +
485 					     XLNX_AUD_CH_STS_START);
486 			aes_reg2_val = readl(stream_data->mmio +
487 					     XLNX_AUD_CH_STS_START + 0x4);
488 
489 			xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val,
490 					      component->dev);
491 		}
492 	}
493 
494 	size = params_buffer_bytes(params);
495 
496 	stream_data->buffer_size = size;
497 
498 	low = lower_32_bits(runtime->dma_addr);
499 	high = upper_32_bits(runtime->dma_addr);
500 	writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
501 	writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
502 
503 	val = readl(stream_data->mmio + XLNX_AUD_CTRL);
504 	bits_per_sample = params_width(params);
505 	switch (bits_per_sample) {
506 	case 8:
507 		val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT);
508 		break;
509 	case 16:
510 		val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT);
511 		break;
512 	case 20:
513 		val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT);
514 		break;
515 	case 24:
516 		val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT);
517 		break;
518 	case 32:
519 		val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT);
520 		break;
521 	default:
522 		return -EINVAL;
523 	}
524 
525 	val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT;
526 	writel(val, stream_data->mmio + XLNX_AUD_CTRL);
527 
528 	val = (params_periods(params) << PERIOD_CFG_PERIODS_SHIFT)
529 		| params_period_bytes(params);
530 	writel(val, stream_data->mmio + XLNX_AUD_PERIOD_CONFIG);
531 	bytes_per_ch = DIV_ROUND_UP(params_period_bytes(params), active_ch);
532 	writel(bytes_per_ch, stream_data->mmio + XLNX_BYTES_PER_CH);
533 
534 	return 0;
535 }
536 
537 static int xlnx_formatter_pcm_trigger(struct snd_soc_component *component,
538 				      struct snd_pcm_substream *substream,
539 				      int cmd)
540 {
541 	u32 val;
542 	struct xlnx_pcm_stream_param *stream_data =
543 			substream->runtime->private_data;
544 
545 	switch (cmd) {
546 	case SNDRV_PCM_TRIGGER_START:
547 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
548 	case SNDRV_PCM_TRIGGER_RESUME:
549 		val = readl(stream_data->mmio + XLNX_AUD_CTRL);
550 		val |= AUD_CTRL_DMA_EN_MASK;
551 		writel(val, stream_data->mmio + XLNX_AUD_CTRL);
552 		break;
553 	case SNDRV_PCM_TRIGGER_STOP:
554 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
555 	case SNDRV_PCM_TRIGGER_SUSPEND:
556 		val = readl(stream_data->mmio + XLNX_AUD_CTRL);
557 		val &= ~AUD_CTRL_DMA_EN_MASK;
558 		writel(val, stream_data->mmio + XLNX_AUD_CTRL);
559 		break;
560 	}
561 
562 	return 0;
563 }
564 
565 static int xlnx_formatter_pcm_new(struct snd_soc_component *component,
566 				  struct snd_soc_pcm_runtime *rtd)
567 {
568 	snd_pcm_set_managed_buffer_all(rtd->pcm,
569 			SNDRV_DMA_TYPE_DEV, component->dev,
570 			xlnx_pcm_hardware.buffer_bytes_max,
571 			xlnx_pcm_hardware.buffer_bytes_max);
572 	return 0;
573 }
574 
575 static const struct snd_soc_component_driver xlnx_asoc_component = {
576 	.name			= DRV_NAME,
577 	.set_sysclk		= xlnx_formatter_set_sysclk,
578 	.open			= xlnx_formatter_pcm_open,
579 	.close			= xlnx_formatter_pcm_close,
580 	.hw_params		= xlnx_formatter_pcm_hw_params,
581 	.trigger		= xlnx_formatter_pcm_trigger,
582 	.pointer		= xlnx_formatter_pcm_pointer,
583 	.pcm_new		= xlnx_formatter_pcm_new,
584 };
585 
586 static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
587 {
588 	int ret;
589 	u32 val;
590 	struct xlnx_pcm_drv_data *aud_drv_data;
591 	struct device *dev = &pdev->dev;
592 
593 	aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL);
594 	if (!aud_drv_data)
595 		return -ENOMEM;
596 
597 	aud_drv_data->axi_clk = devm_clk_get(dev, "s_axi_lite_aclk");
598 	if (IS_ERR(aud_drv_data->axi_clk)) {
599 		ret = PTR_ERR(aud_drv_data->axi_clk);
600 		dev_err(dev, "failed to get s_axi_lite_aclk(%d)\n", ret);
601 		return ret;
602 	}
603 	ret = clk_prepare_enable(aud_drv_data->axi_clk);
604 	if (ret) {
605 		dev_err(dev,
606 			"failed to enable s_axi_lite_aclk(%d)\n", ret);
607 		return ret;
608 	}
609 
610 	aud_drv_data->mmio = devm_platform_ioremap_resource(pdev, 0);
611 	if (IS_ERR(aud_drv_data->mmio)) {
612 		dev_err(dev, "audio formatter ioremap failed\n");
613 		ret = PTR_ERR(aud_drv_data->mmio);
614 		goto clk_err;
615 	}
616 
617 	val = readl(aud_drv_data->mmio + XLNX_AUD_CORE_CONFIG);
618 	if (val & AUD_CFG_MM2S_MASK) {
619 		aud_drv_data->mm2s_presence = true;
620 		ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
621 					       XLNX_MM2S_OFFSET);
622 		if (ret) {
623 			dev_err(dev, "audio formatter reset failed\n");
624 			goto clk_err;
625 		}
626 		xlnx_formatter_disable_irqs(aud_drv_data->mmio +
627 					    XLNX_MM2S_OFFSET,
628 					    SNDRV_PCM_STREAM_PLAYBACK);
629 
630 		aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev,
631 								 "irq_mm2s");
632 		if (aud_drv_data->mm2s_irq < 0) {
633 			ret = aud_drv_data->mm2s_irq;
634 			goto clk_err;
635 		}
636 		ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
637 				       xlnx_mm2s_irq_handler, 0,
638 				       "xlnx_formatter_pcm_mm2s_irq", aud_drv_data);
639 		if (ret) {
640 			dev_err(dev, "xlnx audio mm2s irq request failed\n");
641 			goto clk_err;
642 		}
643 	}
644 	if (val & AUD_CFG_S2MM_MASK) {
645 		aud_drv_data->s2mm_presence = true;
646 		ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
647 					       XLNX_S2MM_OFFSET);
648 		if (ret) {
649 			dev_err(dev, "audio formatter reset failed\n");
650 			goto clk_err;
651 		}
652 		xlnx_formatter_disable_irqs(aud_drv_data->mmio +
653 					    XLNX_S2MM_OFFSET,
654 					    SNDRV_PCM_STREAM_CAPTURE);
655 
656 		aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
657 								 "irq_s2mm");
658 		if (aud_drv_data->s2mm_irq < 0) {
659 			ret = aud_drv_data->s2mm_irq;
660 			goto clk_err;
661 		}
662 		ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
663 				       xlnx_s2mm_irq_handler, 0,
664 				       "xlnx_formatter_pcm_s2mm_irq",
665 				       aud_drv_data);
666 		if (ret) {
667 			dev_err(dev, "xlnx audio s2mm irq request failed\n");
668 			goto clk_err;
669 		}
670 	}
671 
672 	dev_set_drvdata(dev, aud_drv_data);
673 
674 	ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
675 					      NULL, 0);
676 	if (ret) {
677 		dev_err(dev, "pcm platform device register failed\n");
678 		goto clk_err;
679 	}
680 
681 	return 0;
682 
683 clk_err:
684 	clk_disable_unprepare(aud_drv_data->axi_clk);
685 	return ret;
686 }
687 
688 static void xlnx_formatter_pcm_remove(struct platform_device *pdev)
689 {
690 	int ret = 0;
691 	struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
692 
693 	if (adata->s2mm_presence)
694 		ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
695 
696 	/* Try MM2S reset, even if S2MM  reset fails */
697 	if (adata->mm2s_presence)
698 		ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET);
699 
700 	if (ret)
701 		dev_err(&pdev->dev, "audio formatter reset failed\n");
702 
703 	clk_disable_unprepare(adata->axi_clk);
704 }
705 
706 static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
707 	{ .compatible = "xlnx,audio-formatter-1.0"},
708 	{},
709 };
710 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
711 
712 static struct platform_driver xlnx_formatter_pcm_driver = {
713 	.probe	= xlnx_formatter_pcm_probe,
714 	.remove = xlnx_formatter_pcm_remove,
715 	.driver	= {
716 		.name	= DRV_NAME,
717 		.of_match_table	= xlnx_formatter_pcm_of_match,
718 	},
719 };
720 
721 module_platform_driver(xlnx_formatter_pcm_driver);
722 
723 MODULE_DESCRIPTION("ASoC driver for Xilinx audio formatter");
724 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
725 MODULE_LICENSE("GPL v2");
726