xref: /linux/sound/soc/kirkwood/kirkwood-i2s.c (revision 54c1e27d8a683e325a8f5f350a4b79e44bbef46d)
1 /*
2  * kirkwood-i2s.c
3  *
4  * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5  * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation;  either version 2 of the  License, or (at your
10  *  option) any later version.
11  */
12 
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/io.h>
17 #include <linux/slab.h>
18 #include <linux/mbus.h>
19 #include <linux/delay.h>
20 #include <linux/clk.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <linux/platform_data/asoc-kirkwood.h>
25 #include "kirkwood.h"
26 
27 #define DRV_NAME	"mvebu-audio"
28 
29 #define KIRKWOOD_I2S_FORMATS \
30 	(SNDRV_PCM_FMTBIT_S16_LE | \
31 	 SNDRV_PCM_FMTBIT_S24_LE | \
32 	 SNDRV_PCM_FMTBIT_S32_LE)
33 
34 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
35 		unsigned int fmt)
36 {
37 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
38 	unsigned long mask;
39 	unsigned long value;
40 
41 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
42 	case SND_SOC_DAIFMT_RIGHT_J:
43 		mask = KIRKWOOD_I2S_CTL_RJ;
44 		break;
45 	case SND_SOC_DAIFMT_LEFT_J:
46 		mask = KIRKWOOD_I2S_CTL_LJ;
47 		break;
48 	case SND_SOC_DAIFMT_I2S:
49 		mask = KIRKWOOD_I2S_CTL_I2S;
50 		break;
51 	default:
52 		return -EINVAL;
53 	}
54 
55 	/*
56 	 * Set same format for playback and record
57 	 * This avoids some troubles.
58 	 */
59 	value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
60 	value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
61 	value |= mask;
62 	writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
63 
64 	value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
65 	value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
66 	value |= mask;
67 	writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
68 
69 	return 0;
70 }
71 
72 static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
73 {
74 	unsigned long value;
75 
76 	value = KIRKWOOD_DCO_CTL_OFFSET_0;
77 	switch (rate) {
78 	default:
79 	case 44100:
80 		value |= KIRKWOOD_DCO_CTL_FREQ_11;
81 		break;
82 	case 48000:
83 		value |= KIRKWOOD_DCO_CTL_FREQ_12;
84 		break;
85 	case 96000:
86 		value |= KIRKWOOD_DCO_CTL_FREQ_24;
87 		break;
88 	}
89 	writel(value, io + KIRKWOOD_DCO_CTL);
90 
91 	/* wait for dco locked */
92 	do {
93 		cpu_relax();
94 		value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
95 		value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
96 	} while (value == 0);
97 }
98 
99 static void kirkwood_set_rate(struct snd_soc_dai *dai,
100 	struct kirkwood_dma_data *priv, unsigned long rate)
101 {
102 	uint32_t clks_ctrl;
103 
104 	if (rate == 44100 || rate == 48000 || rate == 96000) {
105 		/* use internal dco for the supported rates
106 		 * defined in kirkwood_i2s_dai */
107 		dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
108 			__func__, rate);
109 		kirkwood_set_dco(priv->io, rate);
110 
111 		clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
112 	} else {
113 		/* use the external clock for the other rates
114 		 * defined in kirkwood_i2s_dai_extclk */
115 		dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
116 			__func__, rate, 256 * rate);
117 		clk_set_rate(priv->extclk, 256 * rate);
118 
119 		clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
120 	}
121 	writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
122 }
123 
124 static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
125 		struct snd_soc_dai *dai)
126 {
127 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
128 
129 	snd_soc_dai_set_dma_data(dai, substream, priv);
130 	return 0;
131 }
132 
133 static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
134 				 struct snd_pcm_hw_params *params,
135 				 struct snd_soc_dai *dai)
136 {
137 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
138 	uint32_t ctl_play, ctl_rec;
139 	unsigned int i2s_reg;
140 	unsigned long i2s_value;
141 
142 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
143 		i2s_reg = KIRKWOOD_I2S_PLAYCTL;
144 	} else {
145 		i2s_reg = KIRKWOOD_I2S_RECCTL;
146 	}
147 
148 	kirkwood_set_rate(dai, priv, params_rate(params));
149 
150 	i2s_value = readl(priv->io+i2s_reg);
151 	i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
152 
153 	/*
154 	 * Size settings in play/rec i2s control regs and play/rec control
155 	 * regs must be the same.
156 	 */
157 	switch (params_format(params)) {
158 	case SNDRV_PCM_FORMAT_S16_LE:
159 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
160 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
161 			   KIRKWOOD_PLAYCTL_I2S_EN;
162 		ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
163 			  KIRKWOOD_RECCTL_I2S_EN;
164 		break;
165 	/*
166 	 * doesn't work... S20_3LE != kirkwood 20bit format ?
167 	 *
168 	case SNDRV_PCM_FORMAT_S20_3LE:
169 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
170 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
171 			   KIRKWOOD_PLAYCTL_I2S_EN;
172 		ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
173 			  KIRKWOOD_RECCTL_I2S_EN;
174 		break;
175 	*/
176 	case SNDRV_PCM_FORMAT_S24_LE:
177 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
178 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
179 			   KIRKWOOD_PLAYCTL_I2S_EN;
180 		ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
181 			  KIRKWOOD_RECCTL_I2S_EN;
182 		break;
183 	case SNDRV_PCM_FORMAT_S32_LE:
184 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
185 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
186 			   KIRKWOOD_PLAYCTL_I2S_EN;
187 		ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
188 			  KIRKWOOD_RECCTL_I2S_EN;
189 		break;
190 	default:
191 		return -EINVAL;
192 	}
193 
194 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
195 		if (params_channels(params) == 1)
196 			ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
197 		else
198 			ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
199 
200 		priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
201 				    KIRKWOOD_PLAYCTL_ENABLE_MASK |
202 				    KIRKWOOD_PLAYCTL_SIZE_MASK);
203 		priv->ctl_play |= ctl_play;
204 	} else {
205 		priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK;
206 		priv->ctl_rec |= ctl_rec;
207 	}
208 
209 	writel(i2s_value, priv->io+i2s_reg);
210 
211 	return 0;
212 }
213 
214 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
215 				int cmd, struct snd_soc_dai *dai)
216 {
217 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
218 	uint32_t ctl, value;
219 
220 	ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
221 	if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
222 		unsigned timeout = 5000;
223 		/*
224 		 * The Armada510 spec says that if we enter pause mode, the
225 		 * busy bit must be read back as clear _twice_.  Make sure
226 		 * we respect that otherwise we get DMA underruns.
227 		 */
228 		do {
229 			value = ctl;
230 			ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
231 			if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
232 				break;
233 			udelay(1);
234 		} while (timeout--);
235 
236 		if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
237 			dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
238 				   ctl);
239 	}
240 
241 	switch (cmd) {
242 	case SNDRV_PCM_TRIGGER_START:
243 		/* configure */
244 		ctl = priv->ctl_play;
245 		value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
246 		writel(value, priv->io + KIRKWOOD_PLAYCTL);
247 
248 		/* enable interrupts */
249 		value = readl(priv->io + KIRKWOOD_INT_MASK);
250 		value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
251 		writel(value, priv->io + KIRKWOOD_INT_MASK);
252 
253 		/* enable playback */
254 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
255 		break;
256 
257 	case SNDRV_PCM_TRIGGER_STOP:
258 		/* stop audio, disable interrupts */
259 		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
260 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
261 
262 		value = readl(priv->io + KIRKWOOD_INT_MASK);
263 		value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
264 		writel(value, priv->io + KIRKWOOD_INT_MASK);
265 
266 		/* disable all playbacks */
267 		ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
268 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
269 		break;
270 
271 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
272 	case SNDRV_PCM_TRIGGER_SUSPEND:
273 		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
274 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
275 		break;
276 
277 	case SNDRV_PCM_TRIGGER_RESUME:
278 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
279 		ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
280 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
281 		break;
282 
283 	default:
284 		return -EINVAL;
285 	}
286 
287 	return 0;
288 }
289 
290 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
291 				int cmd, struct snd_soc_dai *dai)
292 {
293 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
294 	uint32_t ctl, value;
295 
296 	value = readl(priv->io + KIRKWOOD_RECCTL);
297 
298 	switch (cmd) {
299 	case SNDRV_PCM_TRIGGER_START:
300 		/* configure */
301 		ctl = priv->ctl_rec;
302 		value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
303 		writel(value, priv->io + KIRKWOOD_RECCTL);
304 
305 		/* enable interrupts */
306 		value = readl(priv->io + KIRKWOOD_INT_MASK);
307 		value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
308 		writel(value, priv->io + KIRKWOOD_INT_MASK);
309 
310 		/* enable record */
311 		writel(ctl, priv->io + KIRKWOOD_RECCTL);
312 		break;
313 
314 	case SNDRV_PCM_TRIGGER_STOP:
315 		/* stop audio, disable interrupts */
316 		value = readl(priv->io + KIRKWOOD_RECCTL);
317 		value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
318 		writel(value, priv->io + KIRKWOOD_RECCTL);
319 
320 		value = readl(priv->io + KIRKWOOD_INT_MASK);
321 		value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
322 		writel(value, priv->io + KIRKWOOD_INT_MASK);
323 
324 		/* disable all records */
325 		value = readl(priv->io + KIRKWOOD_RECCTL);
326 		value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
327 		writel(value, priv->io + KIRKWOOD_RECCTL);
328 		break;
329 
330 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
331 	case SNDRV_PCM_TRIGGER_SUSPEND:
332 		value = readl(priv->io + KIRKWOOD_RECCTL);
333 		value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
334 		writel(value, priv->io + KIRKWOOD_RECCTL);
335 		break;
336 
337 	case SNDRV_PCM_TRIGGER_RESUME:
338 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
339 		value = readl(priv->io + KIRKWOOD_RECCTL);
340 		value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
341 		writel(value, priv->io + KIRKWOOD_RECCTL);
342 		break;
343 
344 	default:
345 		return -EINVAL;
346 	}
347 
348 	return 0;
349 }
350 
351 static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
352 			       struct snd_soc_dai *dai)
353 {
354 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
355 		return kirkwood_i2s_play_trigger(substream, cmd, dai);
356 	else
357 		return kirkwood_i2s_rec_trigger(substream, cmd, dai);
358 
359 	return 0;
360 }
361 
362 static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
363 {
364 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
365 	unsigned long value;
366 	unsigned int reg_data;
367 
368 	/* put system in a "safe" state : */
369 	/* disable audio interrupts */
370 	writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
371 	writel(0, priv->io + KIRKWOOD_INT_MASK);
372 
373 	reg_data = readl(priv->io + 0x1200);
374 	reg_data &= (~(0x333FF8));
375 	reg_data |= 0x111D18;
376 	writel(reg_data, priv->io + 0x1200);
377 
378 	msleep(500);
379 
380 	reg_data = readl(priv->io + 0x1200);
381 	reg_data &= (~(0x333FF8));
382 	reg_data |= 0x111D18;
383 	writel(reg_data, priv->io + 0x1200);
384 
385 	/* disable playback/record */
386 	value = readl(priv->io + KIRKWOOD_PLAYCTL);
387 	value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
388 	writel(value, priv->io + KIRKWOOD_PLAYCTL);
389 
390 	value = readl(priv->io + KIRKWOOD_RECCTL);
391 	value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
392 	writel(value, priv->io + KIRKWOOD_RECCTL);
393 
394 	return 0;
395 
396 }
397 
398 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
399 	.startup	= kirkwood_i2s_startup,
400 	.trigger	= kirkwood_i2s_trigger,
401 	.hw_params      = kirkwood_i2s_hw_params,
402 	.set_fmt        = kirkwood_i2s_set_fmt,
403 };
404 
405 
406 static struct snd_soc_dai_driver kirkwood_i2s_dai = {
407 	.probe = kirkwood_i2s_probe,
408 	.playback = {
409 		.channels_min = 1,
410 		.channels_max = 2,
411 		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
412 				SNDRV_PCM_RATE_96000,
413 		.formats = KIRKWOOD_I2S_FORMATS,
414 	},
415 	.capture = {
416 		.channels_min = 1,
417 		.channels_max = 2,
418 		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
419 				SNDRV_PCM_RATE_96000,
420 		.formats = KIRKWOOD_I2S_FORMATS,
421 	},
422 	.ops = &kirkwood_i2s_dai_ops,
423 };
424 
425 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
426 	.probe = kirkwood_i2s_probe,
427 	.playback = {
428 		.channels_min = 1,
429 		.channels_max = 2,
430 		.rates = SNDRV_PCM_RATE_8000_192000 |
431 			 SNDRV_PCM_RATE_CONTINUOUS |
432 			 SNDRV_PCM_RATE_KNOT,
433 		.formats = KIRKWOOD_I2S_FORMATS,
434 	},
435 	.capture = {
436 		.channels_min = 1,
437 		.channels_max = 2,
438 		.rates = SNDRV_PCM_RATE_8000_192000 |
439 			 SNDRV_PCM_RATE_CONTINUOUS |
440 			 SNDRV_PCM_RATE_KNOT,
441 		.formats = KIRKWOOD_I2S_FORMATS,
442 	},
443 	.ops = &kirkwood_i2s_dai_ops,
444 };
445 
446 static const struct snd_soc_component_driver kirkwood_i2s_component = {
447 	.name		= DRV_NAME,
448 };
449 
450 static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
451 {
452 	struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
453 	struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
454 	struct kirkwood_dma_data *priv;
455 	struct resource *mem;
456 	int err;
457 
458 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
459 	if (!priv) {
460 		dev_err(&pdev->dev, "allocation failed\n");
461 		return -ENOMEM;
462 	}
463 	dev_set_drvdata(&pdev->dev, priv);
464 
465 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
466 	priv->io = devm_ioremap_resource(&pdev->dev, mem);
467 	if (IS_ERR(priv->io))
468 		return PTR_ERR(priv->io);
469 
470 	priv->irq = platform_get_irq(pdev, 0);
471 	if (priv->irq <= 0) {
472 		dev_err(&pdev->dev, "platform_get_irq failed\n");
473 		return -ENXIO;
474 	}
475 
476 	if (!data) {
477 		dev_err(&pdev->dev, "no platform data ?!\n");
478 		return -EINVAL;
479 	}
480 
481 	priv->burst = data->burst;
482 
483 	priv->clk = devm_clk_get(&pdev->dev, NULL);
484 	if (IS_ERR(priv->clk)) {
485 		dev_err(&pdev->dev, "no clock\n");
486 		return PTR_ERR(priv->clk);
487 	}
488 
489 	err = clk_prepare_enable(priv->clk);
490 	if (err < 0)
491 		return err;
492 
493 	priv->extclk = devm_clk_get(&pdev->dev, "extclk");
494 	if (!IS_ERR(priv->extclk)) {
495 		if (priv->extclk == priv->clk) {
496 			devm_clk_put(&pdev->dev, priv->extclk);
497 			priv->extclk = ERR_PTR(-EINVAL);
498 		} else {
499 			dev_info(&pdev->dev, "found external clock\n");
500 			clk_prepare_enable(priv->extclk);
501 			soc_dai = &kirkwood_i2s_dai_extclk;
502 		}
503 	}
504 
505 	/* Some sensible defaults - this reflects the powerup values */
506 	priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
507 	priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
508 
509 	/* Select the burst size */
510 	if (data->burst == 32) {
511 		priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
512 		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
513 	} else {
514 		priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
515 		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
516 	}
517 
518 	err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
519 					 soc_dai, 1);
520 	if (err) {
521 		dev_err(&pdev->dev, "snd_soc_register_component failed\n");
522 		goto err_component;
523 	}
524 
525 	err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
526 	if (err) {
527 		dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
528 		goto err_platform;
529 	}
530 	return 0;
531  err_platform:
532 	snd_soc_unregister_component(&pdev->dev);
533  err_component:
534 	if (!IS_ERR(priv->extclk))
535 		clk_disable_unprepare(priv->extclk);
536 	clk_disable_unprepare(priv->clk);
537 
538 	return err;
539 }
540 
541 static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
542 {
543 	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
544 
545 	snd_soc_unregister_platform(&pdev->dev);
546 	snd_soc_unregister_component(&pdev->dev);
547 
548 	if (!IS_ERR(priv->extclk))
549 		clk_disable_unprepare(priv->extclk);
550 	clk_disable_unprepare(priv->clk);
551 
552 	return 0;
553 }
554 
555 static struct platform_driver kirkwood_i2s_driver = {
556 	.probe  = kirkwood_i2s_dev_probe,
557 	.remove = kirkwood_i2s_dev_remove,
558 	.driver = {
559 		.name = DRV_NAME,
560 		.owner = THIS_MODULE,
561 	},
562 };
563 
564 module_platform_driver(kirkwood_i2s_driver);
565 
566 /* Module information */
567 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
568 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
569 MODULE_LICENSE("GPL");
570 MODULE_ALIAS("platform:mvebu-audio");
571