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