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_ENABLE_MASK | 216 KIRKWOOD_RECCTL_SIZE_MASK); 217 priv->ctl_rec |= ctl_rec; 218 } 219 220 writel(i2s_value, priv->io+i2s_reg); 221 222 return 0; 223 } 224 225 static unsigned kirkwood_i2s_play_mute(unsigned ctl) 226 { 227 if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN)) 228 ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE; 229 if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN)) 230 ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE; 231 return ctl; 232 } 233 234 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 235 int cmd, struct snd_soc_dai *dai) 236 { 237 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 238 uint32_t ctl, value; 239 240 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 241 if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) { 242 unsigned timeout = 5000; 243 /* 244 * The Armada510 spec says that if we enter pause mode, the 245 * busy bit must be read back as clear _twice_. Make sure 246 * we respect that otherwise we get DMA underruns. 247 */ 248 do { 249 value = ctl; 250 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 251 if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)) 252 break; 253 udelay(1); 254 } while (timeout--); 255 256 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) 257 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", 258 ctl); 259 } 260 261 switch (cmd) { 262 case SNDRV_PCM_TRIGGER_START: 263 /* configure */ 264 ctl = priv->ctl_play; 265 if (dai->id == 0) 266 ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ 267 else 268 ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ 269 ctl = kirkwood_i2s_play_mute(ctl); 270 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 271 writel(value, priv->io + KIRKWOOD_PLAYCTL); 272 273 /* enable interrupts */ 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 /* enable playback */ 279 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 280 break; 281 282 case SNDRV_PCM_TRIGGER_STOP: 283 /* stop audio, disable interrupts */ 284 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 285 KIRKWOOD_PLAYCTL_SPDIF_MUTE; 286 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 287 288 value = readl(priv->io + KIRKWOOD_INT_MASK); 289 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; 290 writel(value, priv->io + KIRKWOOD_INT_MASK); 291 292 /* disable all playbacks */ 293 ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 294 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 295 break; 296 297 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 298 case SNDRV_PCM_TRIGGER_SUSPEND: 299 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 300 KIRKWOOD_PLAYCTL_SPDIF_MUTE; 301 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 302 break; 303 304 case SNDRV_PCM_TRIGGER_RESUME: 305 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 306 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 307 KIRKWOOD_PLAYCTL_SPDIF_MUTE); 308 ctl = kirkwood_i2s_play_mute(ctl); 309 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 310 break; 311 312 default: 313 return -EINVAL; 314 } 315 316 return 0; 317 } 318 319 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 320 int cmd, struct snd_soc_dai *dai) 321 { 322 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 323 uint32_t ctl, value; 324 325 value = readl(priv->io + KIRKWOOD_RECCTL); 326 327 switch (cmd) { 328 case SNDRV_PCM_TRIGGER_START: 329 /* configure */ 330 ctl = priv->ctl_rec; 331 if (dai->id == 0) 332 ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN; /* i2s */ 333 else 334 ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ 335 336 value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK; 337 writel(value, priv->io + KIRKWOOD_RECCTL); 338 339 /* enable interrupts */ 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 /* enable record */ 345 writel(ctl, priv->io + KIRKWOOD_RECCTL); 346 break; 347 348 case SNDRV_PCM_TRIGGER_STOP: 349 /* stop audio, disable interrupts */ 350 value = readl(priv->io + KIRKWOOD_RECCTL); 351 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 352 writel(value, priv->io + KIRKWOOD_RECCTL); 353 354 value = readl(priv->io + KIRKWOOD_INT_MASK); 355 value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES; 356 writel(value, priv->io + KIRKWOOD_INT_MASK); 357 358 /* disable all records */ 359 value = readl(priv->io + KIRKWOOD_RECCTL); 360 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; 361 writel(value, priv->io + KIRKWOOD_RECCTL); 362 break; 363 364 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 365 case SNDRV_PCM_TRIGGER_SUSPEND: 366 value = readl(priv->io + KIRKWOOD_RECCTL); 367 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 368 writel(value, priv->io + KIRKWOOD_RECCTL); 369 break; 370 371 case SNDRV_PCM_TRIGGER_RESUME: 372 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 373 value = readl(priv->io + KIRKWOOD_RECCTL); 374 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE); 375 writel(value, priv->io + KIRKWOOD_RECCTL); 376 break; 377 378 default: 379 return -EINVAL; 380 } 381 382 return 0; 383 } 384 385 static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 386 struct snd_soc_dai *dai) 387 { 388 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 389 return kirkwood_i2s_play_trigger(substream, cmd, dai); 390 else 391 return kirkwood_i2s_rec_trigger(substream, cmd, dai); 392 393 return 0; 394 } 395 396 static int kirkwood_i2s_init(struct kirkwood_dma_data *priv) 397 { 398 unsigned long value; 399 unsigned int reg_data; 400 401 /* put system in a "safe" state : */ 402 /* disable audio interrupts */ 403 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE); 404 writel(0, priv->io + KIRKWOOD_INT_MASK); 405 406 reg_data = readl(priv->io + 0x1200); 407 reg_data &= (~(0x333FF8)); 408 reg_data |= 0x111D18; 409 writel(reg_data, priv->io + 0x1200); 410 411 msleep(500); 412 413 reg_data = readl(priv->io + 0x1200); 414 reg_data &= (~(0x333FF8)); 415 reg_data |= 0x111D18; 416 writel(reg_data, priv->io + 0x1200); 417 418 /* disable playback/record */ 419 value = readl(priv->io + KIRKWOOD_PLAYCTL); 420 value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 421 writel(value, priv->io + KIRKWOOD_PLAYCTL); 422 423 value = readl(priv->io + KIRKWOOD_RECCTL); 424 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; 425 writel(value, priv->io + KIRKWOOD_RECCTL); 426 427 return 0; 428 429 } 430 431 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 432 .startup = kirkwood_i2s_startup, 433 .trigger = kirkwood_i2s_trigger, 434 .hw_params = kirkwood_i2s_hw_params, 435 .set_fmt = kirkwood_i2s_set_fmt, 436 }; 437 438 static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = { 439 { 440 .name = "i2s", 441 .id = 0, 442 .playback = { 443 .channels_min = 1, 444 .channels_max = 2, 445 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 446 SNDRV_PCM_RATE_96000, 447 .formats = KIRKWOOD_I2S_FORMATS, 448 }, 449 .capture = { 450 .channels_min = 1, 451 .channels_max = 2, 452 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 453 SNDRV_PCM_RATE_96000, 454 .formats = KIRKWOOD_I2S_FORMATS, 455 }, 456 .ops = &kirkwood_i2s_dai_ops, 457 }, 458 { 459 .name = "spdif", 460 .id = 1, 461 .playback = { 462 .channels_min = 1, 463 .channels_max = 2, 464 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 465 SNDRV_PCM_RATE_96000, 466 .formats = KIRKWOOD_SPDIF_FORMATS, 467 }, 468 .capture = { 469 .channels_min = 1, 470 .channels_max = 2, 471 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 472 SNDRV_PCM_RATE_96000, 473 .formats = KIRKWOOD_SPDIF_FORMATS, 474 }, 475 .ops = &kirkwood_i2s_dai_ops, 476 }, 477 }; 478 479 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = { 480 { 481 .name = "i2s", 482 .id = 0, 483 .playback = { 484 .channels_min = 1, 485 .channels_max = 2, 486 .rates = SNDRV_PCM_RATE_CONTINUOUS, 487 .rate_min = 5512, 488 .rate_max = 192000, 489 .formats = KIRKWOOD_I2S_FORMATS, 490 }, 491 .capture = { 492 .channels_min = 1, 493 .channels_max = 2, 494 .rates = SNDRV_PCM_RATE_CONTINUOUS, 495 .rate_min = 5512, 496 .rate_max = 192000, 497 .formats = KIRKWOOD_I2S_FORMATS, 498 }, 499 .ops = &kirkwood_i2s_dai_ops, 500 }, 501 { 502 .name = "spdif", 503 .id = 1, 504 .playback = { 505 .channels_min = 1, 506 .channels_max = 2, 507 .rates = SNDRV_PCM_RATE_CONTINUOUS, 508 .rate_min = 5512, 509 .rate_max = 192000, 510 .formats = KIRKWOOD_SPDIF_FORMATS, 511 }, 512 .capture = { 513 .channels_min = 1, 514 .channels_max = 2, 515 .rates = SNDRV_PCM_RATE_CONTINUOUS, 516 .rate_min = 5512, 517 .rate_max = 192000, 518 .formats = KIRKWOOD_SPDIF_FORMATS, 519 }, 520 .ops = &kirkwood_i2s_dai_ops, 521 }, 522 }; 523 524 static const struct snd_soc_component_driver kirkwood_i2s_component = { 525 .name = DRV_NAME, 526 }; 527 528 static int kirkwood_i2s_dev_probe(struct platform_device *pdev) 529 { 530 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; 531 struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai; 532 struct kirkwood_dma_data *priv; 533 struct resource *mem; 534 struct device_node *np = pdev->dev.of_node; 535 int err; 536 537 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 538 if (!priv) { 539 dev_err(&pdev->dev, "allocation failed\n"); 540 return -ENOMEM; 541 } 542 dev_set_drvdata(&pdev->dev, priv); 543 544 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 545 priv->io = devm_ioremap_resource(&pdev->dev, mem); 546 if (IS_ERR(priv->io)) 547 return PTR_ERR(priv->io); 548 549 priv->irq = platform_get_irq(pdev, 0); 550 if (priv->irq <= 0) { 551 dev_err(&pdev->dev, "platform_get_irq failed\n"); 552 return -ENXIO; 553 } 554 555 if (np) { 556 priv->burst = 128; /* might be 32 or 128 */ 557 } else if (data) { 558 priv->burst = data->burst; 559 } else { 560 dev_err(&pdev->dev, "no DT nor platform data ?!\n"); 561 return -EINVAL; 562 } 563 564 priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL); 565 if (IS_ERR(priv->clk)) { 566 dev_err(&pdev->dev, "no clock\n"); 567 return PTR_ERR(priv->clk); 568 } 569 570 err = clk_prepare_enable(priv->clk); 571 if (err < 0) 572 return err; 573 574 priv->extclk = devm_clk_get(&pdev->dev, "extclk"); 575 if (IS_ERR(priv->extclk)) { 576 if (PTR_ERR(priv->extclk) == -EPROBE_DEFER) 577 return -EPROBE_DEFER; 578 } else { 579 if (priv->extclk == priv->clk) { 580 devm_clk_put(&pdev->dev, priv->extclk); 581 priv->extclk = ERR_PTR(-EINVAL); 582 } else { 583 dev_info(&pdev->dev, "found external clock\n"); 584 clk_prepare_enable(priv->extclk); 585 soc_dai = kirkwood_i2s_dai_extclk; 586 } 587 } 588 589 /* Some sensible defaults - this reflects the powerup values */ 590 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; 591 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; 592 593 /* Select the burst size */ 594 if (priv->burst == 32) { 595 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; 596 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; 597 } else { 598 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; 599 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 600 } 601 602 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component, 603 soc_dai, 2); 604 if (err) { 605 dev_err(&pdev->dev, "snd_soc_register_component failed\n"); 606 goto err_component; 607 } 608 609 err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); 610 if (err) { 611 dev_err(&pdev->dev, "snd_soc_register_platform failed\n"); 612 goto err_platform; 613 } 614 615 kirkwood_i2s_init(priv); 616 617 return 0; 618 err_platform: 619 snd_soc_unregister_component(&pdev->dev); 620 err_component: 621 if (!IS_ERR(priv->extclk)) 622 clk_disable_unprepare(priv->extclk); 623 clk_disable_unprepare(priv->clk); 624 625 return err; 626 } 627 628 static int kirkwood_i2s_dev_remove(struct platform_device *pdev) 629 { 630 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 631 632 snd_soc_unregister_platform(&pdev->dev); 633 snd_soc_unregister_component(&pdev->dev); 634 635 if (!IS_ERR(priv->extclk)) 636 clk_disable_unprepare(priv->extclk); 637 clk_disable_unprepare(priv->clk); 638 639 return 0; 640 } 641 642 #ifdef CONFIG_OF 643 static struct of_device_id mvebu_audio_of_match[] = { 644 { .compatible = "marvell,kirkwood-audio" }, 645 { .compatible = "marvell,dove-audio" }, 646 { .compatible = "marvell,armada370-audio" }, 647 { } 648 }; 649 MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); 650 #endif 651 652 static struct platform_driver kirkwood_i2s_driver = { 653 .probe = kirkwood_i2s_dev_probe, 654 .remove = kirkwood_i2s_dev_remove, 655 .driver = { 656 .name = DRV_NAME, 657 .owner = THIS_MODULE, 658 .of_match_table = of_match_ptr(mvebu_audio_of_match), 659 }, 660 }; 661 662 module_platform_driver(kirkwood_i2s_driver); 663 664 /* Module information */ 665 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); 666 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 667 MODULE_LICENSE("GPL"); 668 MODULE_ALIAS("platform:mvebu-audio"); 669