0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/io.h>
0013 #include <linux/slab.h>
0014 #include <linux/mbus.h>
0015 #include <linux/delay.h>
0016 #include <linux/clk.h>
0017 #include <sound/pcm.h>
0018 #include <sound/pcm_params.h>
0019 #include <sound/soc.h>
0020 #include <linux/platform_data/asoc-kirkwood.h>
0021 #include <linux/of.h>
0022
0023 #include "kirkwood.h"
0024
0025 #define KIRKWOOD_I2S_FORMATS \
0026 (SNDRV_PCM_FMTBIT_S16_LE | \
0027 SNDRV_PCM_FMTBIT_S24_LE | \
0028 SNDRV_PCM_FMTBIT_S32_LE)
0029
0030 #define KIRKWOOD_SPDIF_FORMATS \
0031 (SNDRV_PCM_FMTBIT_S16_LE | \
0032 SNDRV_PCM_FMTBIT_S24_LE)
0033
0034 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
0035 unsigned int fmt)
0036 {
0037 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
0038 unsigned long mask;
0039 unsigned long value;
0040
0041 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0042 case SND_SOC_DAIFMT_RIGHT_J:
0043 mask = KIRKWOOD_I2S_CTL_RJ;
0044 break;
0045 case SND_SOC_DAIFMT_LEFT_J:
0046 mask = KIRKWOOD_I2S_CTL_LJ;
0047 break;
0048 case SND_SOC_DAIFMT_I2S:
0049 mask = KIRKWOOD_I2S_CTL_I2S;
0050 break;
0051 default:
0052 return -EINVAL;
0053 }
0054
0055
0056
0057
0058
0059 value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
0060 value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
0061 value |= mask;
0062 writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
0063
0064 value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
0065 value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
0066 value |= mask;
0067 writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
0068
0069 return 0;
0070 }
0071
0072 static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
0073 {
0074 unsigned long value;
0075
0076 value = KIRKWOOD_DCO_CTL_OFFSET_0;
0077 switch (rate) {
0078 default:
0079 case 44100:
0080 value |= KIRKWOOD_DCO_CTL_FREQ_11;
0081 break;
0082 case 48000:
0083 value |= KIRKWOOD_DCO_CTL_FREQ_12;
0084 break;
0085 case 96000:
0086 value |= KIRKWOOD_DCO_CTL_FREQ_24;
0087 break;
0088 }
0089 writel(value, io + KIRKWOOD_DCO_CTL);
0090
0091
0092 do {
0093 cpu_relax();
0094 value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
0095 value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
0096 } while (value == 0);
0097 }
0098
0099 static void kirkwood_set_rate(struct snd_soc_dai *dai,
0100 struct kirkwood_dma_data *priv, unsigned long rate)
0101 {
0102 uint32_t clks_ctrl;
0103
0104 if (IS_ERR(priv->extclk)) {
0105
0106
0107 dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
0108 __func__, rate);
0109 kirkwood_set_dco(priv->io, rate);
0110
0111 clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
0112 } else {
0113
0114
0115 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
0116 __func__, rate, 256 * rate);
0117 clk_set_rate(priv->extclk, 256 * rate);
0118
0119 clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
0120 }
0121 writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
0122 }
0123
0124 static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
0125 struct snd_soc_dai *dai)
0126 {
0127 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
0128
0129 snd_soc_dai_set_dma_data(dai, substream, priv);
0130 return 0;
0131 }
0132
0133 static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
0134 struct snd_pcm_hw_params *params,
0135 struct snd_soc_dai *dai)
0136 {
0137 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
0138 uint32_t ctl_play, ctl_rec;
0139 unsigned int i2s_reg;
0140 unsigned long i2s_value;
0141
0142 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0143 i2s_reg = KIRKWOOD_I2S_PLAYCTL;
0144 } else {
0145 i2s_reg = KIRKWOOD_I2S_RECCTL;
0146 }
0147
0148 kirkwood_set_rate(dai, priv, params_rate(params));
0149
0150 i2s_value = readl(priv->io+i2s_reg);
0151 i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
0152
0153
0154
0155
0156
0157 switch (params_format(params)) {
0158 case SNDRV_PCM_FORMAT_S16_LE:
0159 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
0160 ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
0161 KIRKWOOD_PLAYCTL_I2S_EN |
0162 KIRKWOOD_PLAYCTL_SPDIF_EN;
0163 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
0164 KIRKWOOD_RECCTL_I2S_EN |
0165 KIRKWOOD_RECCTL_SPDIF_EN;
0166 break;
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 case SNDRV_PCM_FORMAT_S24_LE:
0179 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
0180 ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
0181 KIRKWOOD_PLAYCTL_I2S_EN |
0182 KIRKWOOD_PLAYCTL_SPDIF_EN;
0183 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
0184 KIRKWOOD_RECCTL_I2S_EN |
0185 KIRKWOOD_RECCTL_SPDIF_EN;
0186 break;
0187 case SNDRV_PCM_FORMAT_S32_LE:
0188 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
0189 ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
0190 KIRKWOOD_PLAYCTL_I2S_EN;
0191 ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
0192 KIRKWOOD_RECCTL_I2S_EN;
0193 break;
0194 default:
0195 return -EINVAL;
0196 }
0197
0198 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0199 if (params_channels(params) == 1)
0200 ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
0201 else
0202 ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
0203
0204 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
0205 KIRKWOOD_PLAYCTL_ENABLE_MASK |
0206 KIRKWOOD_PLAYCTL_SIZE_MASK);
0207 priv->ctl_play |= ctl_play;
0208 } else {
0209 priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
0210 KIRKWOOD_RECCTL_SIZE_MASK);
0211 priv->ctl_rec |= ctl_rec;
0212 }
0213
0214 writel(i2s_value, priv->io+i2s_reg);
0215
0216 return 0;
0217 }
0218
0219 static unsigned kirkwood_i2s_play_mute(unsigned ctl)
0220 {
0221 if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
0222 ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
0223 if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
0224 ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
0225 return ctl;
0226 }
0227
0228 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
0229 int cmd, struct snd_soc_dai *dai)
0230 {
0231 struct snd_pcm_runtime *runtime = substream->runtime;
0232 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
0233 uint32_t ctl, value;
0234
0235 ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
0236 if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
0237 unsigned timeout = 5000;
0238
0239
0240
0241
0242
0243 do {
0244 value = ctl;
0245 ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
0246 if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
0247 break;
0248 udelay(1);
0249 } while (timeout--);
0250
0251 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
0252 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
0253 ctl);
0254 }
0255
0256 switch (cmd) {
0257 case SNDRV_PCM_TRIGGER_START:
0258
0259 ctl = priv->ctl_play;
0260 if (dai->id == 0)
0261 ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;
0262 else
0263 ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;
0264 ctl = kirkwood_i2s_play_mute(ctl);
0265 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
0266 writel(value, priv->io + KIRKWOOD_PLAYCTL);
0267
0268
0269 if (!runtime->no_period_wakeup) {
0270 value = readl(priv->io + KIRKWOOD_INT_MASK);
0271 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
0272 writel(value, priv->io + KIRKWOOD_INT_MASK);
0273 }
0274
0275
0276 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
0277 break;
0278
0279 case SNDRV_PCM_TRIGGER_STOP:
0280
0281 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
0282 KIRKWOOD_PLAYCTL_SPDIF_MUTE;
0283 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
0284
0285 value = readl(priv->io + KIRKWOOD_INT_MASK);
0286 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
0287 writel(value, priv->io + KIRKWOOD_INT_MASK);
0288
0289
0290 ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
0291 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
0292 break;
0293
0294 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0295 case SNDRV_PCM_TRIGGER_SUSPEND:
0296 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
0297 KIRKWOOD_PLAYCTL_SPDIF_MUTE;
0298 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
0299 break;
0300
0301 case SNDRV_PCM_TRIGGER_RESUME:
0302 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0303 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
0304 KIRKWOOD_PLAYCTL_SPDIF_MUTE);
0305 ctl = kirkwood_i2s_play_mute(ctl);
0306 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
0307 break;
0308
0309 default:
0310 return -EINVAL;
0311 }
0312
0313 return 0;
0314 }
0315
0316 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
0317 int cmd, struct snd_soc_dai *dai)
0318 {
0319 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
0320 uint32_t ctl, value;
0321
0322 value = readl(priv->io + KIRKWOOD_RECCTL);
0323
0324 switch (cmd) {
0325 case SNDRV_PCM_TRIGGER_START:
0326
0327 ctl = priv->ctl_rec;
0328 if (dai->id == 0)
0329 ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN;
0330 else
0331 ctl &= ~KIRKWOOD_RECCTL_I2S_EN;
0332
0333 value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
0334 writel(value, priv->io + KIRKWOOD_RECCTL);
0335
0336
0337 value = readl(priv->io + KIRKWOOD_INT_MASK);
0338 value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
0339 writel(value, priv->io + KIRKWOOD_INT_MASK);
0340
0341
0342 writel(ctl, priv->io + KIRKWOOD_RECCTL);
0343 break;
0344
0345 case SNDRV_PCM_TRIGGER_STOP:
0346
0347 value = readl(priv->io + KIRKWOOD_RECCTL);
0348 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
0349 writel(value, priv->io + KIRKWOOD_RECCTL);
0350
0351 value = readl(priv->io + KIRKWOOD_INT_MASK);
0352 value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
0353 writel(value, priv->io + KIRKWOOD_INT_MASK);
0354
0355
0356 value = readl(priv->io + KIRKWOOD_RECCTL);
0357 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
0358 writel(value, priv->io + KIRKWOOD_RECCTL);
0359 break;
0360
0361 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0362 case SNDRV_PCM_TRIGGER_SUSPEND:
0363 value = readl(priv->io + KIRKWOOD_RECCTL);
0364 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
0365 writel(value, priv->io + KIRKWOOD_RECCTL);
0366 break;
0367
0368 case SNDRV_PCM_TRIGGER_RESUME:
0369 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0370 value = readl(priv->io + KIRKWOOD_RECCTL);
0371 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
0372 writel(value, priv->io + KIRKWOOD_RECCTL);
0373 break;
0374
0375 default:
0376 return -EINVAL;
0377 }
0378
0379 return 0;
0380 }
0381
0382 static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
0383 struct snd_soc_dai *dai)
0384 {
0385 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0386 return kirkwood_i2s_play_trigger(substream, cmd, dai);
0387 else
0388 return kirkwood_i2s_rec_trigger(substream, cmd, dai);
0389
0390 return 0;
0391 }
0392
0393 static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
0394 {
0395 unsigned long value;
0396 unsigned int reg_data;
0397
0398
0399
0400 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
0401 writel(0, priv->io + KIRKWOOD_INT_MASK);
0402
0403 reg_data = readl(priv->io + 0x1200);
0404 reg_data &= (~(0x333FF8));
0405 reg_data |= 0x111D18;
0406 writel(reg_data, priv->io + 0x1200);
0407
0408 msleep(500);
0409
0410 reg_data = readl(priv->io + 0x1200);
0411 reg_data &= (~(0x333FF8));
0412 reg_data |= 0x111D18;
0413 writel(reg_data, priv->io + 0x1200);
0414
0415
0416 value = readl(priv->io + KIRKWOOD_PLAYCTL);
0417 value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
0418 writel(value, priv->io + KIRKWOOD_PLAYCTL);
0419
0420 value = readl(priv->io + KIRKWOOD_RECCTL);
0421 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
0422 writel(value, priv->io + KIRKWOOD_RECCTL);
0423
0424 return 0;
0425
0426 }
0427
0428 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
0429 .startup = kirkwood_i2s_startup,
0430 .trigger = kirkwood_i2s_trigger,
0431 .hw_params = kirkwood_i2s_hw_params,
0432 .set_fmt = kirkwood_i2s_set_fmt,
0433 };
0434
0435 static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
0436 {
0437 .name = "i2s",
0438 .id = 0,
0439 .playback = {
0440 .channels_min = 1,
0441 .channels_max = 2,
0442 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
0443 SNDRV_PCM_RATE_96000,
0444 .formats = KIRKWOOD_I2S_FORMATS,
0445 },
0446 .capture = {
0447 .channels_min = 1,
0448 .channels_max = 2,
0449 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
0450 SNDRV_PCM_RATE_96000,
0451 .formats = KIRKWOOD_I2S_FORMATS,
0452 },
0453 .ops = &kirkwood_i2s_dai_ops,
0454 },
0455 {
0456 .name = "spdif",
0457 .id = 1,
0458 .playback = {
0459 .channels_min = 1,
0460 .channels_max = 2,
0461 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
0462 SNDRV_PCM_RATE_96000,
0463 .formats = KIRKWOOD_SPDIF_FORMATS,
0464 },
0465 .capture = {
0466 .channels_min = 1,
0467 .channels_max = 2,
0468 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
0469 SNDRV_PCM_RATE_96000,
0470 .formats = KIRKWOOD_SPDIF_FORMATS,
0471 },
0472 .ops = &kirkwood_i2s_dai_ops,
0473 },
0474 };
0475
0476 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
0477 {
0478 .name = "i2s",
0479 .id = 0,
0480 .playback = {
0481 .channels_min = 1,
0482 .channels_max = 2,
0483 .rates = SNDRV_PCM_RATE_CONTINUOUS,
0484 .rate_min = 5512,
0485 .rate_max = 192000,
0486 .formats = KIRKWOOD_I2S_FORMATS,
0487 },
0488 .capture = {
0489 .channels_min = 1,
0490 .channels_max = 2,
0491 .rates = SNDRV_PCM_RATE_CONTINUOUS,
0492 .rate_min = 5512,
0493 .rate_max = 192000,
0494 .formats = KIRKWOOD_I2S_FORMATS,
0495 },
0496 .ops = &kirkwood_i2s_dai_ops,
0497 },
0498 {
0499 .name = "spdif",
0500 .id = 1,
0501 .playback = {
0502 .channels_min = 1,
0503 .channels_max = 2,
0504 .rates = SNDRV_PCM_RATE_CONTINUOUS,
0505 .rate_min = 5512,
0506 .rate_max = 192000,
0507 .formats = KIRKWOOD_SPDIF_FORMATS,
0508 },
0509 .capture = {
0510 .channels_min = 1,
0511 .channels_max = 2,
0512 .rates = SNDRV_PCM_RATE_CONTINUOUS,
0513 .rate_min = 5512,
0514 .rate_max = 192000,
0515 .formats = KIRKWOOD_SPDIF_FORMATS,
0516 },
0517 .ops = &kirkwood_i2s_dai_ops,
0518 },
0519 };
0520
0521 static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
0522 {
0523 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
0524 struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
0525 struct kirkwood_dma_data *priv;
0526 struct device_node *np = pdev->dev.of_node;
0527 int err;
0528
0529 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0530 if (!priv)
0531 return -ENOMEM;
0532
0533 dev_set_drvdata(&pdev->dev, priv);
0534
0535 priv->io = devm_platform_ioremap_resource(pdev, 0);
0536 if (IS_ERR(priv->io))
0537 return PTR_ERR(priv->io);
0538
0539 priv->irq = platform_get_irq(pdev, 0);
0540 if (priv->irq < 0)
0541 return priv->irq;
0542
0543 if (np) {
0544 priv->burst = 128;
0545 } else if (data) {
0546 priv->burst = data->burst;
0547 } else {
0548 dev_err(&pdev->dev, "no DT nor platform data ?!\n");
0549 return -EINVAL;
0550 }
0551
0552 priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
0553 if (IS_ERR(priv->clk)) {
0554 dev_err(&pdev->dev, "no clock\n");
0555 return PTR_ERR(priv->clk);
0556 }
0557
0558 priv->extclk = devm_clk_get(&pdev->dev, "extclk");
0559 if (IS_ERR(priv->extclk)) {
0560 if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
0561 return -EPROBE_DEFER;
0562 } else {
0563 if (clk_is_match(priv->extclk, priv->clk)) {
0564 devm_clk_put(&pdev->dev, priv->extclk);
0565 priv->extclk = ERR_PTR(-EINVAL);
0566 } else {
0567 dev_info(&pdev->dev, "found external clock\n");
0568 clk_prepare_enable(priv->extclk);
0569 soc_dai = kirkwood_i2s_dai_extclk;
0570 }
0571 }
0572
0573 err = clk_prepare_enable(priv->clk);
0574 if (err < 0)
0575 return err;
0576
0577
0578 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
0579 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
0580
0581
0582 if (priv->burst == 32) {
0583 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
0584 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
0585 } else {
0586 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
0587 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
0588 }
0589
0590 err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
0591 soc_dai, 2);
0592 if (err) {
0593 dev_err(&pdev->dev, "snd_soc_register_component failed\n");
0594 goto err_component;
0595 }
0596
0597 kirkwood_i2s_init(priv);
0598
0599 return 0;
0600
0601 err_component:
0602 if (!IS_ERR(priv->extclk))
0603 clk_disable_unprepare(priv->extclk);
0604 clk_disable_unprepare(priv->clk);
0605
0606 return err;
0607 }
0608
0609 static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
0610 {
0611 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
0612
0613 snd_soc_unregister_component(&pdev->dev);
0614 if (!IS_ERR(priv->extclk))
0615 clk_disable_unprepare(priv->extclk);
0616 clk_disable_unprepare(priv->clk);
0617
0618 return 0;
0619 }
0620
0621 #ifdef CONFIG_OF
0622 static const struct of_device_id mvebu_audio_of_match[] = {
0623 { .compatible = "marvell,kirkwood-audio" },
0624 { .compatible = "marvell,dove-audio" },
0625 { .compatible = "marvell,armada370-audio" },
0626 { }
0627 };
0628 MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
0629 #endif
0630
0631 static struct platform_driver kirkwood_i2s_driver = {
0632 .probe = kirkwood_i2s_dev_probe,
0633 .remove = kirkwood_i2s_dev_remove,
0634 .driver = {
0635 .name = DRV_NAME,
0636 .of_match_table = of_match_ptr(mvebu_audio_of_match),
0637 },
0638 };
0639
0640 module_platform_driver(kirkwood_i2s_driver);
0641
0642
0643 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
0644 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
0645 MODULE_LICENSE("GPL");
0646 MODULE_ALIAS("platform:mvebu-audio");