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 const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 402 .startup = kirkwood_i2s_startup, 403 .trigger = kirkwood_i2s_trigger, 404 .hw_params = kirkwood_i2s_hw_params, 405 .set_fmt = kirkwood_i2s_set_fmt, 406 }; 407 408 409 static struct snd_soc_dai_driver kirkwood_i2s_dai = { 410 .probe = kirkwood_i2s_probe, 411 .playback = { 412 .channels_min = 1, 413 .channels_max = 2, 414 .rates = KIRKWOOD_I2S_RATES, 415 .formats = KIRKWOOD_I2S_FORMATS, 416 }, 417 .capture = { 418 .channels_min = 1, 419 .channels_max = 2, 420 .rates = KIRKWOOD_I2S_RATES, 421 .formats = KIRKWOOD_I2S_FORMATS, 422 }, 423 .ops = &kirkwood_i2s_dai_ops, 424 }; 425 426 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = { 427 .probe = kirkwood_i2s_probe, 428 .playback = { 429 .channels_min = 1, 430 .channels_max = 2, 431 .rates = SNDRV_PCM_RATE_8000_192000 | 432 SNDRV_PCM_RATE_CONTINUOUS | 433 SNDRV_PCM_RATE_KNOT, 434 .formats = KIRKWOOD_I2S_FORMATS, 435 }, 436 .capture = { 437 .channels_min = 1, 438 .channels_max = 2, 439 .rates = SNDRV_PCM_RATE_8000_192000 | 440 SNDRV_PCM_RATE_CONTINUOUS | 441 SNDRV_PCM_RATE_KNOT, 442 .formats = KIRKWOOD_I2S_FORMATS, 443 }, 444 .ops = &kirkwood_i2s_dai_ops, 445 }; 446 447 static const struct snd_soc_component_driver kirkwood_i2s_component = { 448 .name = DRV_NAME, 449 }; 450 451 static int kirkwood_i2s_dev_probe(struct platform_device *pdev) 452 { 453 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; 454 struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai; 455 struct kirkwood_dma_data *priv; 456 struct resource *mem; 457 int err; 458 459 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 460 if (!priv) { 461 dev_err(&pdev->dev, "allocation failed\n"); 462 return -ENOMEM; 463 } 464 dev_set_drvdata(&pdev->dev, priv); 465 466 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 467 priv->io = devm_ioremap_resource(&pdev->dev, mem); 468 if (IS_ERR(priv->io)) 469 return PTR_ERR(priv->io); 470 471 priv->irq = platform_get_irq(pdev, 0); 472 if (priv->irq <= 0) { 473 dev_err(&pdev->dev, "platform_get_irq failed\n"); 474 return -ENXIO; 475 } 476 477 if (!data) { 478 dev_err(&pdev->dev, "no platform data ?!\n"); 479 return -EINVAL; 480 } 481 482 priv->burst = data->burst; 483 484 priv->clk = devm_clk_get(&pdev->dev, NULL); 485 if (IS_ERR(priv->clk)) { 486 dev_err(&pdev->dev, "no clock\n"); 487 return PTR_ERR(priv->clk); 488 } 489 490 err = clk_prepare_enable(priv->clk); 491 if (err < 0) 492 return err; 493 494 priv->extclk = devm_clk_get(&pdev->dev, "extclk"); 495 if (!IS_ERR(priv->extclk)) { 496 if (priv->extclk == priv->clk) { 497 priv->extclk = ERR_PTR(-EINVAL); 498 } else { 499 dev_info(&pdev->dev, "found external clock\n"); 500 clk_prepare_enable(priv->extclk); 501 soc_dai = &kirkwood_i2s_dai_extclk; 502 } 503 } 504 505 /* Some sensible defaults - this reflects the powerup values */ 506 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; 507 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; 508 509 /* Select the burst size */ 510 if (data->burst == 32) { 511 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; 512 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; 513 } else { 514 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; 515 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 516 } 517 518 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component, 519 soc_dai, 1); 520 if (!err) 521 return 0; 522 dev_err(&pdev->dev, "snd_soc_register_component failed\n"); 523 524 if (!IS_ERR(priv->extclk)) 525 clk_disable_unprepare(priv->extclk); 526 clk_disable_unprepare(priv->clk); 527 528 return err; 529 } 530 531 static int kirkwood_i2s_dev_remove(struct platform_device *pdev) 532 { 533 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 534 535 snd_soc_unregister_component(&pdev->dev); 536 537 if (!IS_ERR(priv->extclk)) 538 clk_disable_unprepare(priv->extclk); 539 clk_disable_unprepare(priv->clk); 540 541 return 0; 542 } 543 544 static struct platform_driver kirkwood_i2s_driver = { 545 .probe = kirkwood_i2s_dev_probe, 546 .remove = kirkwood_i2s_dev_remove, 547 .driver = { 548 .name = DRV_NAME, 549 .owner = THIS_MODULE, 550 }, 551 }; 552 553 module_platform_driver(kirkwood_i2s_driver); 554 555 /* Module information */ 556 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); 557 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 558 MODULE_LICENSE("GPL"); 559 MODULE_ALIAS("platform:kirkwood-i2s"); 560