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