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 (rate == 44100 || rate == 48000 || rate == 96000) { 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 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C | 165 KIRKWOOD_RECCTL_I2S_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 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 | 183 KIRKWOOD_RECCTL_I2S_EN; 184 break; 185 case SNDRV_PCM_FORMAT_S32_LE: 186 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; 187 ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 | 188 KIRKWOOD_PLAYCTL_I2S_EN; 189 ctl_rec = KIRKWOOD_RECCTL_SIZE_32 | 190 KIRKWOOD_RECCTL_I2S_EN; 191 break; 192 default: 193 return -EINVAL; 194 } 195 196 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 197 if (params_channels(params) == 1) 198 ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH; 199 else 200 ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; 201 202 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | 203 KIRKWOOD_PLAYCTL_ENABLE_MASK | 204 KIRKWOOD_PLAYCTL_SIZE_MASK); 205 priv->ctl_play |= ctl_play; 206 } else { 207 priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK; 208 priv->ctl_rec |= ctl_rec; 209 } 210 211 writel(i2s_value, priv->io+i2s_reg); 212 213 return 0; 214 } 215 216 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 217 int cmd, struct snd_soc_dai *dai) 218 { 219 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 220 uint32_t ctl, value; 221 222 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 223 if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { 224 unsigned timeout = 5000; 225 /* 226 * The Armada510 spec says that if we enter pause mode, the 227 * busy bit must be read back as clear _twice_. Make sure 228 * we respect that otherwise we get DMA underruns. 229 */ 230 do { 231 value = ctl; 232 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 233 if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)) 234 break; 235 udelay(1); 236 } while (timeout--); 237 238 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) 239 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", 240 ctl); 241 } 242 243 switch (cmd) { 244 case SNDRV_PCM_TRIGGER_START: 245 /* configure */ 246 ctl = priv->ctl_play; 247 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 248 writel(value, priv->io + KIRKWOOD_PLAYCTL); 249 250 /* enable interrupts */ 251 value = readl(priv->io + KIRKWOOD_INT_MASK); 252 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; 253 writel(value, priv->io + KIRKWOOD_INT_MASK); 254 255 /* enable playback */ 256 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 257 break; 258 259 case SNDRV_PCM_TRIGGER_STOP: 260 /* stop audio, disable interrupts */ 261 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; 262 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 263 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 /* disable all playbacks */ 269 ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 270 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 271 break; 272 273 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 274 case SNDRV_PCM_TRIGGER_SUSPEND: 275 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; 276 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 277 break; 278 279 case SNDRV_PCM_TRIGGER_RESUME: 280 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 281 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); 282 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 283 break; 284 285 default: 286 return -EINVAL; 287 } 288 289 return 0; 290 } 291 292 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 293 int cmd, struct snd_soc_dai *dai) 294 { 295 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 296 uint32_t ctl, value; 297 298 value = readl(priv->io + KIRKWOOD_RECCTL); 299 300 switch (cmd) { 301 case SNDRV_PCM_TRIGGER_START: 302 /* configure */ 303 ctl = priv->ctl_rec; 304 value = ctl & ~KIRKWOOD_RECCTL_I2S_EN; 305 writel(value, priv->io + KIRKWOOD_RECCTL); 306 307 /* enable interrupts */ 308 value = readl(priv->io + KIRKWOOD_INT_MASK); 309 value |= KIRKWOOD_INT_CAUSE_REC_BYTES; 310 writel(value, priv->io + KIRKWOOD_INT_MASK); 311 312 /* enable record */ 313 writel(ctl, priv->io + KIRKWOOD_RECCTL); 314 break; 315 316 case SNDRV_PCM_TRIGGER_STOP: 317 /* stop audio, disable interrupts */ 318 value = readl(priv->io + KIRKWOOD_RECCTL); 319 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 320 writel(value, priv->io + KIRKWOOD_RECCTL); 321 322 value = readl(priv->io + KIRKWOOD_INT_MASK); 323 value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES; 324 writel(value, priv->io + KIRKWOOD_INT_MASK); 325 326 /* disable all records */ 327 value = readl(priv->io + KIRKWOOD_RECCTL); 328 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); 329 writel(value, priv->io + KIRKWOOD_RECCTL); 330 break; 331 332 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 333 case SNDRV_PCM_TRIGGER_SUSPEND: 334 value = readl(priv->io + KIRKWOOD_RECCTL); 335 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 336 writel(value, priv->io + KIRKWOOD_RECCTL); 337 break; 338 339 case SNDRV_PCM_TRIGGER_RESUME: 340 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 341 value = readl(priv->io + KIRKWOOD_RECCTL); 342 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE); 343 writel(value, priv->io + KIRKWOOD_RECCTL); 344 break; 345 346 default: 347 return -EINVAL; 348 } 349 350 return 0; 351 } 352 353 static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 354 struct snd_soc_dai *dai) 355 { 356 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 357 return kirkwood_i2s_play_trigger(substream, cmd, dai); 358 else 359 return kirkwood_i2s_rec_trigger(substream, cmd, dai); 360 361 return 0; 362 } 363 364 static int kirkwood_i2s_probe(struct snd_soc_dai *dai) 365 { 366 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 367 unsigned long value; 368 unsigned int reg_data; 369 370 /* put system in a "safe" state : */ 371 /* disable audio interrupts */ 372 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE); 373 writel(0, priv->io + KIRKWOOD_INT_MASK); 374 375 reg_data = readl(priv->io + 0x1200); 376 reg_data &= (~(0x333FF8)); 377 reg_data |= 0x111D18; 378 writel(reg_data, priv->io + 0x1200); 379 380 msleep(500); 381 382 reg_data = readl(priv->io + 0x1200); 383 reg_data &= (~(0x333FF8)); 384 reg_data |= 0x111D18; 385 writel(reg_data, priv->io + 0x1200); 386 387 /* disable playback/record */ 388 value = readl(priv->io + KIRKWOOD_PLAYCTL); 389 value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 390 writel(value, priv->io + KIRKWOOD_PLAYCTL); 391 392 value = readl(priv->io + KIRKWOOD_RECCTL); 393 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); 394 writel(value, priv->io + KIRKWOOD_RECCTL); 395 396 return 0; 397 398 } 399 400 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 401 .startup = kirkwood_i2s_startup, 402 .trigger = kirkwood_i2s_trigger, 403 .hw_params = kirkwood_i2s_hw_params, 404 .set_fmt = kirkwood_i2s_set_fmt, 405 }; 406 407 408 static struct snd_soc_dai_driver kirkwood_i2s_dai = { 409 .probe = kirkwood_i2s_probe, 410 .playback = { 411 .channels_min = 1, 412 .channels_max = 2, 413 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 414 SNDRV_PCM_RATE_96000, 415 .formats = KIRKWOOD_I2S_FORMATS, 416 }, 417 .capture = { 418 .channels_min = 1, 419 .channels_max = 2, 420 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 421 SNDRV_PCM_RATE_96000, 422 .formats = KIRKWOOD_I2S_FORMATS, 423 }, 424 .ops = &kirkwood_i2s_dai_ops, 425 }; 426 427 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = { 428 .probe = kirkwood_i2s_probe, 429 .playback = { 430 .channels_min = 1, 431 .channels_max = 2, 432 .rates = SNDRV_PCM_RATE_8000_192000 | 433 SNDRV_PCM_RATE_CONTINUOUS | 434 SNDRV_PCM_RATE_KNOT, 435 .formats = KIRKWOOD_I2S_FORMATS, 436 }, 437 .capture = { 438 .channels_min = 1, 439 .channels_max = 2, 440 .rates = SNDRV_PCM_RATE_8000_192000 | 441 SNDRV_PCM_RATE_CONTINUOUS | 442 SNDRV_PCM_RATE_KNOT, 443 .formats = KIRKWOOD_I2S_FORMATS, 444 }, 445 .ops = &kirkwood_i2s_dai_ops, 446 }; 447 448 static const struct snd_soc_component_driver kirkwood_i2s_component = { 449 .name = DRV_NAME, 450 }; 451 452 static int kirkwood_i2s_dev_probe(struct platform_device *pdev) 453 { 454 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; 455 struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai; 456 struct kirkwood_dma_data *priv; 457 struct resource *mem; 458 struct device_node *np = pdev->dev.of_node; 459 int err; 460 461 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 462 if (!priv) { 463 dev_err(&pdev->dev, "allocation failed\n"); 464 return -ENOMEM; 465 } 466 dev_set_drvdata(&pdev->dev, priv); 467 468 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 469 priv->io = devm_ioremap_resource(&pdev->dev, mem); 470 if (IS_ERR(priv->io)) 471 return PTR_ERR(priv->io); 472 473 priv->irq = platform_get_irq(pdev, 0); 474 if (priv->irq <= 0) { 475 dev_err(&pdev->dev, "platform_get_irq failed\n"); 476 return -ENXIO; 477 } 478 479 if (np) { 480 priv->burst = 128; /* might be 32 or 128 */ 481 } else if (data) { 482 priv->burst = data->burst; 483 } else { 484 dev_err(&pdev->dev, "no DT nor platform data ?!\n"); 485 return -EINVAL; 486 } 487 488 priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL); 489 if (IS_ERR(priv->clk)) { 490 dev_err(&pdev->dev, "no clock\n"); 491 return PTR_ERR(priv->clk); 492 } 493 494 err = clk_prepare_enable(priv->clk); 495 if (err < 0) 496 return err; 497 498 priv->extclk = devm_clk_get(&pdev->dev, "extclk"); 499 if (!IS_ERR(priv->extclk)) { 500 if (priv->extclk == priv->clk) { 501 devm_clk_put(&pdev->dev, priv->extclk); 502 priv->extclk = ERR_PTR(-EINVAL); 503 } else { 504 dev_info(&pdev->dev, "found external clock\n"); 505 clk_prepare_enable(priv->extclk); 506 soc_dai = &kirkwood_i2s_dai_extclk; 507 } 508 } 509 510 /* Some sensible defaults - this reflects the powerup values */ 511 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; 512 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; 513 514 /* Select the burst size */ 515 if (priv->burst == 32) { 516 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; 517 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; 518 } else { 519 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; 520 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 521 } 522 523 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component, 524 soc_dai, 1); 525 if (err) { 526 dev_err(&pdev->dev, "snd_soc_register_component failed\n"); 527 goto err_component; 528 } 529 530 err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); 531 if (err) { 532 dev_err(&pdev->dev, "snd_soc_register_platform failed\n"); 533 goto err_platform; 534 } 535 return 0; 536 err_platform: 537 snd_soc_unregister_component(&pdev->dev); 538 err_component: 539 if (!IS_ERR(priv->extclk)) 540 clk_disable_unprepare(priv->extclk); 541 clk_disable_unprepare(priv->clk); 542 543 return err; 544 } 545 546 static int kirkwood_i2s_dev_remove(struct platform_device *pdev) 547 { 548 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 549 550 snd_soc_unregister_platform(&pdev->dev); 551 snd_soc_unregister_component(&pdev->dev); 552 553 if (!IS_ERR(priv->extclk)) 554 clk_disable_unprepare(priv->extclk); 555 clk_disable_unprepare(priv->clk); 556 557 return 0; 558 } 559 560 #ifdef CONFIG_OF 561 static struct of_device_id mvebu_audio_of_match[] = { 562 { .compatible = "marvell,kirkwood-audio" }, 563 { .compatible = "marvell,dove-audio" }, 564 { } 565 }; 566 MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); 567 #endif 568 569 static struct platform_driver kirkwood_i2s_driver = { 570 .probe = kirkwood_i2s_dev_probe, 571 .remove = kirkwood_i2s_dev_remove, 572 .driver = { 573 .name = DRV_NAME, 574 .owner = THIS_MODULE, 575 .of_match_table = of_match_ptr(mvebu_audio_of_match), 576 }, 577 }; 578 579 module_platform_driver(kirkwood_i2s_driver); 580 581 /* Module information */ 582 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); 583 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 584 MODULE_LICENSE("GPL"); 585 MODULE_ALIAS("platform:mvebu-audio"); 586