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 "kirkwood.h" 26 27 #define DRV_NAME "kirkwood-i2s" 28 29 #define KIRKWOOD_I2S_RATES \ 30 (SNDRV_PCM_RATE_44100 | \ 31 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 32 #define KIRKWOOD_I2S_FORMATS \ 33 (SNDRV_PCM_FMTBIT_S16_LE | \ 34 SNDRV_PCM_FMTBIT_S24_LE | \ 35 SNDRV_PCM_FMTBIT_S32_LE) 36 37 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 38 unsigned int fmt) 39 { 40 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); 41 unsigned long mask; 42 unsigned long value; 43 44 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 45 case SND_SOC_DAIFMT_RIGHT_J: 46 mask = KIRKWOOD_I2S_CTL_RJ; 47 break; 48 case SND_SOC_DAIFMT_LEFT_J: 49 mask = KIRKWOOD_I2S_CTL_LJ; 50 break; 51 case SND_SOC_DAIFMT_I2S: 52 mask = KIRKWOOD_I2S_CTL_I2S; 53 break; 54 default: 55 return -EINVAL; 56 } 57 58 /* 59 * Set same format for playback and record 60 * This avoids some troubles. 61 */ 62 value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL); 63 value &= ~KIRKWOOD_I2S_CTL_JUST_MASK; 64 value |= mask; 65 writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL); 66 67 value = readl(priv->io+KIRKWOOD_I2S_RECCTL); 68 value &= ~KIRKWOOD_I2S_CTL_JUST_MASK; 69 value |= mask; 70 writel(value, priv->io+KIRKWOOD_I2S_RECCTL); 71 72 return 0; 73 } 74 75 static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) 76 { 77 unsigned long value; 78 79 value = KIRKWOOD_DCO_CTL_OFFSET_0; 80 switch (rate) { 81 default: 82 case 44100: 83 value |= KIRKWOOD_DCO_CTL_FREQ_11; 84 break; 85 case 48000: 86 value |= KIRKWOOD_DCO_CTL_FREQ_12; 87 break; 88 case 96000: 89 value |= KIRKWOOD_DCO_CTL_FREQ_24; 90 break; 91 } 92 writel(value, io + KIRKWOOD_DCO_CTL); 93 94 /* wait for dco locked */ 95 do { 96 cpu_relax(); 97 value = readl(io + KIRKWOOD_DCO_SPCR_STATUS); 98 value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK; 99 } while (value == 0); 100 } 101 102 static void kirkwood_set_rate(struct snd_soc_dai *dai, 103 struct kirkwood_dma_data *priv, unsigned long rate) 104 { 105 uint32_t clks_ctrl; 106 107 if (rate == 44100 || rate == 48000 || rate == 96000) { 108 /* use internal dco for supported rates */ 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 if (!IS_ERR(priv->extclk)) { 115 /* use optional external clk for other rates */ 116 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", 117 __func__, rate, 256 * rate); 118 clk_set_rate(priv->extclk, 256 * rate); 119 120 clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK; 121 } 122 writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL); 123 } 124 125 static int kirkwood_i2s_startup(struct snd_pcm_substream *substream, 126 struct snd_soc_dai *dai) 127 { 128 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 129 130 snd_soc_dai_set_dma_data(dai, substream, priv); 131 return 0; 132 } 133 134 static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, 135 struct snd_pcm_hw_params *params, 136 struct snd_soc_dai *dai) 137 { 138 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 139 uint32_t ctl_play, ctl_rec; 140 unsigned int i2s_reg; 141 unsigned long i2s_value; 142 143 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 144 i2s_reg = KIRKWOOD_I2S_PLAYCTL; 145 } else { 146 i2s_reg = KIRKWOOD_I2S_RECCTL; 147 } 148 149 kirkwood_set_rate(dai, priv, params_rate(params)); 150 151 i2s_value = readl(priv->io+i2s_reg); 152 i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK; 153 154 /* 155 * Size settings in play/rec i2s control regs and play/rec control 156 * regs must be the same. 157 */ 158 switch (params_format(params)) { 159 case SNDRV_PCM_FORMAT_S16_LE: 160 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16; 161 ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C | 162 KIRKWOOD_PLAYCTL_I2S_EN; 163 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C | 164 KIRKWOOD_RECCTL_I2S_EN; 165 break; 166 /* 167 * doesn't work... S20_3LE != kirkwood 20bit format ? 168 * 169 case SNDRV_PCM_FORMAT_S20_3LE: 170 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20; 171 ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 | 172 KIRKWOOD_PLAYCTL_I2S_EN; 173 ctl_rec = KIRKWOOD_RECCTL_SIZE_20 | 174 KIRKWOOD_RECCTL_I2S_EN; 175 break; 176 */ 177 case SNDRV_PCM_FORMAT_S24_LE: 178 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24; 179 ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 | 180 KIRKWOOD_PLAYCTL_I2S_EN; 181 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 | 182 KIRKWOOD_RECCTL_I2S_EN; 183 break; 184 case SNDRV_PCM_FORMAT_S32_LE: 185 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; 186 ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 | 187 KIRKWOOD_PLAYCTL_I2S_EN; 188 ctl_rec = KIRKWOOD_RECCTL_SIZE_32 | 189 KIRKWOOD_RECCTL_I2S_EN; 190 break; 191 default: 192 return -EINVAL; 193 } 194 195 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 196 if (params_channels(params) == 1) 197 ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH; 198 else 199 ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; 200 201 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | 202 KIRKWOOD_PLAYCTL_I2S_EN | 203 KIRKWOOD_PLAYCTL_SPDIF_EN | 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_I2S_EN | 248 KIRKWOOD_PLAYCTL_SPDIF_EN); 249 writel(value, priv->io + KIRKWOOD_PLAYCTL); 250 251 /* enable interrupts */ 252 value = readl(priv->io + KIRKWOOD_INT_MASK); 253 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; 254 writel(value, priv->io + KIRKWOOD_INT_MASK); 255 256 /* enable playback */ 257 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 258 break; 259 260 case SNDRV_PCM_TRIGGER_STOP: 261 /* stop audio, disable interrupts */ 262 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; 263 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 264 265 value = readl(priv->io + KIRKWOOD_INT_MASK); 266 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; 267 writel(value, priv->io + KIRKWOOD_INT_MASK); 268 269 /* disable all playbacks */ 270 ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); 271 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 272 break; 273 274 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 275 case SNDRV_PCM_TRIGGER_SUSPEND: 276 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; 277 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 278 break; 279 280 case SNDRV_PCM_TRIGGER_RESUME: 281 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 282 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); 283 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 284 break; 285 286 default: 287 return -EINVAL; 288 } 289 290 return 0; 291 } 292 293 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 294 int cmd, struct snd_soc_dai *dai) 295 { 296 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 297 uint32_t ctl, value; 298 299 value = readl(priv->io + KIRKWOOD_RECCTL); 300 301 switch (cmd) { 302 case SNDRV_PCM_TRIGGER_START: 303 /* configure */ 304 ctl = priv->ctl_rec; 305 value = ctl & ~KIRKWOOD_RECCTL_I2S_EN; 306 writel(value, priv->io + KIRKWOOD_RECCTL); 307 308 /* enable interrupts */ 309 value = readl(priv->io + KIRKWOOD_INT_MASK); 310 value |= KIRKWOOD_INT_CAUSE_REC_BYTES; 311 writel(value, priv->io + KIRKWOOD_INT_MASK); 312 313 /* enable record */ 314 writel(ctl, priv->io + KIRKWOOD_RECCTL); 315 break; 316 317 case SNDRV_PCM_TRIGGER_STOP: 318 /* stop audio, disable interrupts */ 319 value = readl(priv->io + KIRKWOOD_RECCTL); 320 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 321 writel(value, priv->io + KIRKWOOD_RECCTL); 322 323 value = readl(priv->io + KIRKWOOD_INT_MASK); 324 value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES; 325 writel(value, priv->io + KIRKWOOD_INT_MASK); 326 327 /* disable all records */ 328 value = readl(priv->io + KIRKWOOD_RECCTL); 329 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); 330 writel(value, priv->io + KIRKWOOD_RECCTL); 331 break; 332 333 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 334 case SNDRV_PCM_TRIGGER_SUSPEND: 335 value = readl(priv->io + KIRKWOOD_RECCTL); 336 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 337 writel(value, priv->io + KIRKWOOD_RECCTL); 338 break; 339 340 case SNDRV_PCM_TRIGGER_RESUME: 341 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 342 value = readl(priv->io + KIRKWOOD_RECCTL); 343 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE); 344 writel(value, priv->io + KIRKWOOD_RECCTL); 345 break; 346 347 default: 348 return -EINVAL; 349 } 350 351 return 0; 352 } 353 354 static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 355 struct snd_soc_dai *dai) 356 { 357 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 358 return kirkwood_i2s_play_trigger(substream, cmd, dai); 359 else 360 return kirkwood_i2s_rec_trigger(substream, cmd, dai); 361 362 return 0; 363 } 364 365 static int kirkwood_i2s_probe(struct snd_soc_dai *dai) 366 { 367 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 368 unsigned long value; 369 unsigned int reg_data; 370 371 /* put system in a "safe" state : */ 372 /* disable audio interrupts */ 373 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE); 374 writel(0, priv->io + KIRKWOOD_INT_MASK); 375 376 reg_data = readl(priv->io + 0x1200); 377 reg_data &= (~(0x333FF8)); 378 reg_data |= 0x111D18; 379 writel(reg_data, priv->io + 0x1200); 380 381 msleep(500); 382 383 reg_data = readl(priv->io + 0x1200); 384 reg_data &= (~(0x333FF8)); 385 reg_data |= 0x111D18; 386 writel(reg_data, priv->io + 0x1200); 387 388 /* disable playback/record */ 389 value = readl(priv->io + KIRKWOOD_PLAYCTL); 390 value &= ~(KIRKWOOD_PLAYCTL_I2S_EN|KIRKWOOD_PLAYCTL_SPDIF_EN); 391 writel(value, priv->io + KIRKWOOD_PLAYCTL); 392 393 value = readl(priv->io + KIRKWOOD_RECCTL); 394 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); 395 writel(value, priv->io + KIRKWOOD_RECCTL); 396 397 return 0; 398 399 } 400 401 static int kirkwood_i2s_remove(struct snd_soc_dai *dai) 402 { 403 return 0; 404 } 405 406 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 407 .startup = kirkwood_i2s_startup, 408 .trigger = kirkwood_i2s_trigger, 409 .hw_params = kirkwood_i2s_hw_params, 410 .set_fmt = kirkwood_i2s_set_fmt, 411 }; 412 413 414 static struct snd_soc_dai_driver kirkwood_i2s_dai = { 415 .probe = kirkwood_i2s_probe, 416 .remove = kirkwood_i2s_remove, 417 .playback = { 418 .channels_min = 1, 419 .channels_max = 2, 420 .rates = KIRKWOOD_I2S_RATES, 421 .formats = KIRKWOOD_I2S_FORMATS, 422 }, 423 .capture = { 424 .channels_min = 1, 425 .channels_max = 2, 426 .rates = KIRKWOOD_I2S_RATES, 427 .formats = KIRKWOOD_I2S_FORMATS, 428 }, 429 .ops = &kirkwood_i2s_dai_ops, 430 }; 431 432 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = { 433 .probe = kirkwood_i2s_probe, 434 .remove = kirkwood_i2s_remove, 435 .playback = { 436 .channels_min = 1, 437 .channels_max = 2, 438 .rates = SNDRV_PCM_RATE_8000_192000 | 439 SNDRV_PCM_RATE_CONTINUOUS | 440 SNDRV_PCM_RATE_KNOT, 441 .formats = KIRKWOOD_I2S_FORMATS, 442 }, 443 .capture = { 444 .channels_min = 1, 445 .channels_max = 2, 446 .rates = SNDRV_PCM_RATE_8000_192000 | 447 SNDRV_PCM_RATE_CONTINUOUS | 448 SNDRV_PCM_RATE_KNOT, 449 .formats = KIRKWOOD_I2S_FORMATS, 450 }, 451 .ops = &kirkwood_i2s_dai_ops, 452 }; 453 454 static int kirkwood_i2s_dev_probe(struct platform_device *pdev) 455 { 456 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; 457 struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai; 458 struct kirkwood_dma_data *priv; 459 struct resource *mem; 460 int err; 461 462 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 463 if (!priv) { 464 dev_err(&pdev->dev, "allocation failed\n"); 465 return -ENOMEM; 466 } 467 dev_set_drvdata(&pdev->dev, priv); 468 469 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 470 if (!mem) { 471 dev_err(&pdev->dev, "platform_get_resource failed\n"); 472 return -ENXIO; 473 } 474 475 priv->io = devm_request_and_ioremap(&pdev->dev, mem); 476 if (!priv->io) { 477 dev_err(&pdev->dev, "devm_request_and_ioremap failed\n"); 478 return -ENOMEM; 479 } 480 481 priv->irq = platform_get_irq(pdev, 0); 482 if (priv->irq <= 0) { 483 dev_err(&pdev->dev, "platform_get_irq failed\n"); 484 return -ENXIO; 485 } 486 487 if (!data) { 488 dev_err(&pdev->dev, "no platform data ?!\n"); 489 return -EINVAL; 490 } 491 492 priv->burst = data->burst; 493 494 priv->clk = devm_clk_get(&pdev->dev, NULL); 495 if (IS_ERR(priv->clk)) { 496 dev_err(&pdev->dev, "no clock\n"); 497 return PTR_ERR(priv->clk); 498 } 499 500 err = clk_prepare_enable(priv->clk); 501 if (err < 0) 502 return err; 503 504 priv->extclk = clk_get(&pdev->dev, "extclk"); 505 if (!IS_ERR(priv->extclk)) { 506 if (priv->extclk == priv->clk) { 507 clk_put(priv->extclk); 508 priv->extclk = ERR_PTR(-EINVAL); 509 } else { 510 dev_info(&pdev->dev, "found external clock\n"); 511 clk_prepare_enable(priv->extclk); 512 soc_dai = &kirkwood_i2s_dai_extclk; 513 } 514 } 515 516 /* Some sensible defaults - this reflects the powerup values */ 517 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; 518 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; 519 520 /* Select the burst size */ 521 if (data->burst == 32) { 522 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; 523 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; 524 } else { 525 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; 526 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 527 } 528 529 err = snd_soc_register_dai(&pdev->dev, soc_dai); 530 if (!err) 531 return 0; 532 dev_err(&pdev->dev, "snd_soc_register_dai failed\n"); 533 534 if (!IS_ERR(priv->extclk)) { 535 clk_disable_unprepare(priv->extclk); 536 clk_put(priv->extclk); 537 } 538 clk_disable_unprepare(priv->clk); 539 540 return err; 541 } 542 543 static int kirkwood_i2s_dev_remove(struct platform_device *pdev) 544 { 545 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 546 547 snd_soc_unregister_dai(&pdev->dev); 548 549 if (!IS_ERR(priv->extclk)) { 550 clk_disable_unprepare(priv->extclk); 551 clk_put(priv->extclk); 552 } 553 clk_disable_unprepare(priv->clk); 554 555 return 0; 556 } 557 558 static struct platform_driver kirkwood_i2s_driver = { 559 .probe = kirkwood_i2s_dev_probe, 560 .remove = kirkwood_i2s_dev_remove, 561 .driver = { 562 .name = DRV_NAME, 563 .owner = THIS_MODULE, 564 }, 565 }; 566 567 module_platform_driver(kirkwood_i2s_driver); 568 569 /* Module information */ 570 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); 571 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 572 MODULE_LICENSE("GPL"); 573 MODULE_ALIAS("platform:kirkwood-i2s"); 574