Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  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
 70enum bit_depth {
 71	BIT_DEPTH_8,
 72	BIT_DEPTH_16,
 73	BIT_DEPTH_20,
 74	BIT_DEPTH_24,
 75	BIT_DEPTH_32,
 76};
 77
 78struct 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 */
 98struct 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
106static 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
124enum {
125	AES_TO_AES,
126	AES_TO_PCM,
127	PCM_TO_PCM,
128	PCM_TO_AES
129};
130
131static 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
235log_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
247static 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
268static 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
280static 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
299static 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
318static 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
327static 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
419static 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
433err_reset:
434	kfree(stream_data);
435	return 0;
436}
437
438static snd_pcm_uframes_t
439xlnx_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
454static 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
539static 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
567static 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
577static 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
588static 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
685clk_err:
686	clk_disable_unprepare(aud_drv_data->axi_clk);
687	return ret;
688}
689
690static int 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	return 0;
707}
708
709static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
710	{ .compatible = "xlnx,audio-formatter-1.0"},
711	{},
712};
713MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
714
715static struct platform_driver xlnx_formatter_pcm_driver = {
716	.probe	= xlnx_formatter_pcm_probe,
717	.remove	= xlnx_formatter_pcm_remove,
718	.driver	= {
719		.name	= DRV_NAME,
720		.of_match_table	= xlnx_formatter_pcm_of_match,
721	},
722};
723
724module_platform_driver(xlnx_formatter_pcm_driver);
725MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
726MODULE_LICENSE("GPL v2");