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