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