kirkwood-i2s.c (1f1b65796ef882bb9101d22b17e1a1824b3a6489) kirkwood-i2s.c (75b9b65ee5a80e99efe2fd551d08bc86f115550f)
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

--- 146 unchanged lines hidden (view full) ---

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 |
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

--- 146 unchanged lines hidden (view full) ---

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;
163 KIRKWOOD_PLAYCTL_I2S_EN |
164 KIRKWOOD_PLAYCTL_SPDIF_EN;
164 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
165 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
165 KIRKWOOD_RECCTL_I2S_EN;
166 KIRKWOOD_RECCTL_I2S_EN |
167 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 |
168 break;
169 /*
170 * doesn't work... S20_3LE != kirkwood 20bit format ?
171 *
172 case SNDRV_PCM_FORMAT_S20_3LE:
173 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
174 ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
175 KIRKWOOD_PLAYCTL_I2S_EN;
176 ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
177 KIRKWOOD_RECCTL_I2S_EN;
178 break;
179 */
180 case SNDRV_PCM_FORMAT_S24_LE:
181 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
182 ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
181 KIRKWOOD_PLAYCTL_I2S_EN;
183 KIRKWOOD_PLAYCTL_I2S_EN |
184 KIRKWOOD_PLAYCTL_SPDIF_EN;
182 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
185 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
183 KIRKWOOD_RECCTL_I2S_EN;
186 KIRKWOOD_RECCTL_I2S_EN |
187 KIRKWOOD_RECCTL_SPDIF_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;

--- 43 unchanged lines hidden (view full) ---

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
188 break;
189 case SNDRV_PCM_FORMAT_S32_LE:
190 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
191 ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
192 KIRKWOOD_PLAYCTL_I2S_EN;
193 ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
194 KIRKWOOD_RECCTL_I2S_EN;
195 break;

--- 43 unchanged lines hidden (view full) ---

239 udelay(1);
240 } while (timeout--);
241
242 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
243 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
244 ctl);
245 }
246
247 if (dai->id == 0)
248 ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */
249 else
250 ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */
251
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 */
252 switch (cmd) {
253 case SNDRV_PCM_TRIGGER_START:
254 /* configure */
255 ctl = priv->ctl_play;
256 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
257 writel(value, priv->io + KIRKWOOD_PLAYCTL);
258
259 /* enable interrupts */
260 value = readl(priv->io + KIRKWOOD_INT_MASK);
261 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
262 writel(value, priv->io + KIRKWOOD_INT_MASK);
263
264 /* enable playback */
265 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
266 break;
267
268 case SNDRV_PCM_TRIGGER_STOP:
269 /* stop audio, disable interrupts */
261 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
270 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
271 KIRKWOOD_PLAYCTL_SPDIF_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:
272 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
273
274 value = readl(priv->io + KIRKWOOD_INT_MASK);
275 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
276 writel(value, priv->io + KIRKWOOD_INT_MASK);
277
278 /* disable all playbacks */
279 ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
280 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
281 break;
282
283 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
284 case SNDRV_PCM_TRIGGER_SUSPEND:
275 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
285 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
286 KIRKWOOD_PLAYCTL_SPDIF_MUTE;
276 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
277 break;
278
279 case SNDRV_PCM_TRIGGER_RESUME:
280 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
287 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
288 break;
289
290 case SNDRV_PCM_TRIGGER_RESUME:
291 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
281 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
292 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
293 KIRKWOOD_PLAYCTL_SPDIF_MUTE);
282 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
283 break;
284
285 default:
286 return -EINVAL;
287 }
288
289 return 0;

--- 6 unchanged lines hidden (view full) ---

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;
294 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
295 break;
296
297 default:
298 return -EINVAL;
299 }
300
301 return 0;

--- 6 unchanged lines hidden (view full) ---

308 uint32_t ctl, value;
309
310 value = readl(priv->io + KIRKWOOD_RECCTL);
311
312 switch (cmd) {
313 case SNDRV_PCM_TRIGGER_START:
314 /* configure */
315 ctl = priv->ctl_rec;
304 value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
316 if (dai->id == 0)
317 ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN; /* i2s */
318 else
319 ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */
320
321 value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN |
322 KIRKWOOD_RECCTL_SPDIF_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 */

--- 43 unchanged lines hidden (view full) ---

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
323 writel(value, priv->io + KIRKWOOD_RECCTL);
324
325 /* enable interrupts */
326 value = readl(priv->io + KIRKWOOD_INT_MASK);
327 value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
328 writel(value, priv->io + KIRKWOOD_INT_MASK);
329
330 /* enable record */

--- 43 unchanged lines hidden (view full) ---

374 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
375 return kirkwood_i2s_play_trigger(substream, cmd, dai);
376 else
377 return kirkwood_i2s_rec_trigger(substream, cmd, dai);
378
379 return 0;
380}
381
364static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
382static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
365{
383{
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

--- 24 unchanged lines hidden (view full) ---

399
400static 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
384 unsigned long value;
385 unsigned int reg_data;
386
387 /* put system in a "safe" state : */
388 /* disable audio interrupts */
389 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
390 writel(0, priv->io + KIRKWOOD_INT_MASK);
391

--- 24 unchanged lines hidden (view full) ---

416
417static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
418 .startup = kirkwood_i2s_startup,
419 .trigger = kirkwood_i2s_trigger,
420 .hw_params = kirkwood_i2s_hw_params,
421 .set_fmt = kirkwood_i2s_set_fmt,
422};
423
407
408static struct snd_soc_dai_driver kirkwood_i2s_dai = {
409 .probe = kirkwood_i2s_probe,
424static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
425 {
426 .name = "i2s",
427 .id = 0,
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,
428 .playback = {
429 .channels_min = 1,
430 .channels_max = 2,
431 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
432 SNDRV_PCM_RATE_96000,
433 .formats = KIRKWOOD_I2S_FORMATS,
434 },
435 .capture = {
436 .channels_min = 1,
437 .channels_max = 2,
438 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
439 SNDRV_PCM_RATE_96000,
440 .formats = KIRKWOOD_I2S_FORMATS,
441 },
442 .ops = &kirkwood_i2s_dai_ops,
443 },
444 {
445 .name = "spdif",
446 .id = 1,
447 .playback = {
448 .channels_min = 1,
449 .channels_max = 2,
450 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
451 SNDRV_PCM_RATE_96000,
452 .formats = KIRKWOOD_I2S_FORMATS,
453 },
454 .capture = {
455 .channels_min = 1,
456 .channels_max = 2,
457 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
458 SNDRV_PCM_RATE_96000,
459 .formats = KIRKWOOD_I2S_FORMATS,
460 },
461 .ops = &kirkwood_i2s_dai_ops,
462 },
425};
426
463};
464
427static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
428 .probe = kirkwood_i2s_probe,
465static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
466 {
467 .name = "i2s",
468 .id = 0,
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,
469 .playback = {
470 .channels_min = 1,
471 .channels_max = 2,
472 .rates = SNDRV_PCM_RATE_8000_192000 |
473 SNDRV_PCM_RATE_CONTINUOUS |
474 SNDRV_PCM_RATE_KNOT,
475 .formats = KIRKWOOD_I2S_FORMATS,
476 },
477 .capture = {
478 .channels_min = 1,
479 .channels_max = 2,
480 .rates = SNDRV_PCM_RATE_8000_192000 |
481 SNDRV_PCM_RATE_CONTINUOUS |
482 SNDRV_PCM_RATE_KNOT,
483 .formats = KIRKWOOD_I2S_FORMATS,
484 },
485 .ops = &kirkwood_i2s_dai_ops,
486 },
487 {
488 .name = "spdif",
489 .id = 1,
490 .playback = {
491 .channels_min = 1,
492 .channels_max = 2,
493 .rates = SNDRV_PCM_RATE_8000_192000 |
494 SNDRV_PCM_RATE_CONTINUOUS |
495 SNDRV_PCM_RATE_KNOT,
496 .formats = KIRKWOOD_I2S_FORMATS,
497 },
498 .capture = {
499 .channels_min = 1,
500 .channels_max = 2,
501 .rates = SNDRV_PCM_RATE_8000_192000 |
502 SNDRV_PCM_RATE_CONTINUOUS |
503 SNDRV_PCM_RATE_KNOT,
504 .formats = KIRKWOOD_I2S_FORMATS,
505 },
506 .ops = &kirkwood_i2s_dai_ops,
507 },
446};
447
448static const struct snd_soc_component_driver kirkwood_i2s_component = {
449 .name = DRV_NAME,
450};
451
452static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
453{
454 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
508};
509
510static const struct snd_soc_component_driver kirkwood_i2s_component = {
511 .name = DRV_NAME,
512};
513
514static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
515{
516 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
455 struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
517 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");

--- 55 unchanged lines hidden (view full) ---

519 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
520 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
521 } else {
522 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
523 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
524 }
525
526 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
518 struct kirkwood_dma_data *priv;
519 struct resource *mem;
520 struct device_node *np = pdev->dev.of_node;
521 int err;
522
523 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
524 if (!priv) {
525 dev_err(&pdev->dev, "allocation failed\n");

--- 55 unchanged lines hidden (view full) ---

581 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
582 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
583 } else {
584 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
585 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
586 }
587
588 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
527 soc_dai, 1);
589 soc_dai, 2);
528 if (err) {
529 dev_err(&pdev->dev, "snd_soc_register_component failed\n");
530 goto err_component;
531 }
532
533 err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
534 if (err) {
535 dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
536 goto err_platform;
537 }
590 if (err) {
591 dev_err(&pdev->dev, "snd_soc_register_component failed\n");
592 goto err_component;
593 }
594
595 err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
596 if (err) {
597 dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
598 goto err_platform;
599 }
600
601 kirkwood_i2s_init(priv);
602
538 return 0;
539 err_platform:
540 snd_soc_unregister_component(&pdev->dev);
541 err_component:
542 if (!IS_ERR(priv->extclk))
543 clk_disable_unprepare(priv->extclk);
544 clk_disable_unprepare(priv->clk);
545

--- 43 unchanged lines hidden ---
603 return 0;
604 err_platform:
605 snd_soc_unregister_component(&pdev->dev);
606 err_component:
607 if (!IS_ERR(priv->extclk))
608 clk_disable_unprepare(priv->extclk);
609 clk_disable_unprepare(priv->clk);
610

--- 43 unchanged lines hidden ---