Lines Matching +full:i2s +full:- +full:regs

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * kirkwood-i2s.c
6 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
20 #include <linux/platform_data/asoc-kirkwood.h>
34 /* These registers are relative to the second register region -
56 struct device_node *np = pdev->dev.of_node; in armada_38x_i2s_init_quirk()
60 priv->pll_config = devm_platform_ioremap_resource_byname(pdev, "pll_regs"); in armada_38x_i2s_init_quirk()
61 if (IS_ERR(priv->pll_config)) in armada_38x_i2s_init_quirk()
62 return -ENOMEM; in armada_38x_i2s_init_quirk()
64 priv->soc_control = devm_platform_ioremap_resource_byname(pdev, "soc_ctrl"); in armada_38x_i2s_init_quirk()
65 if (IS_ERR(priv->soc_control)) in armada_38x_i2s_init_quirk()
66 return -ENOMEM; in armada_38x_i2s_init_quirk()
68 /* Select one of exceptive modes: I2S or S/PDIF */ in armada_38x_i2s_init_quirk()
69 reg_val = readl(priv->soc_control); in armada_38x_i2s_init_quirk()
70 if (of_property_read_bool(np, "spdif-mode")) { in armada_38x_i2s_init_quirk()
72 dev_info(&pdev->dev, "using S/PDIF mode\n"); in armada_38x_i2s_init_quirk()
75 dev_info(&pdev->dev, "using I2S mode\n"); in armada_38x_i2s_init_quirk()
77 writel(reg_val, priv->soc_control); in armada_38x_i2s_init_quirk()
168 return -EINVAL; in kirkwood_i2s_set_fmt()
175 value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL); in kirkwood_i2s_set_fmt()
178 writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL); in kirkwood_i2s_set_fmt()
180 value = readl(priv->io+KIRKWOOD_I2S_RECCTL); in kirkwood_i2s_set_fmt()
183 writel(value, priv->io+KIRKWOOD_I2S_RECCTL); in kirkwood_i2s_set_fmt()
220 if (IS_ERR(priv->extclk)) { in kirkwood_set_rate()
223 dev_dbg(dai->dev, "%s: dco set rate = %lu\n", in kirkwood_set_rate()
225 if (priv->pll_config) in kirkwood_set_rate()
226 armada_38x_set_pll(priv->pll_config, rate); in kirkwood_set_rate()
228 kirkwood_set_dco(priv->io, rate); in kirkwood_set_rate()
234 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", in kirkwood_set_rate()
236 clk_set_rate(priv->extclk, 256 * rate); in kirkwood_set_rate()
240 writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL); in kirkwood_set_rate()
261 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in kirkwood_i2s_hw_params()
269 i2s_value = readl(priv->io+i2s_reg); in kirkwood_i2s_hw_params()
273 * Size settings in play/rec i2s control regs and play/rec control in kirkwood_i2s_hw_params()
274 * regs must be the same. in kirkwood_i2s_hw_params()
314 return -EINVAL; in kirkwood_i2s_hw_params()
317 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in kirkwood_i2s_hw_params()
323 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | in kirkwood_i2s_hw_params()
326 priv->ctl_play |= ctl_play; in kirkwood_i2s_hw_params()
328 priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK | in kirkwood_i2s_hw_params()
330 priv->ctl_rec |= ctl_rec; in kirkwood_i2s_hw_params()
333 writel(i2s_value, priv->io+i2s_reg); in kirkwood_i2s_hw_params()
350 struct snd_pcm_runtime *runtime = substream->runtime; in kirkwood_i2s_play_trigger()
354 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
364 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
368 } while (timeout--); in kirkwood_i2s_play_trigger()
371 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", in kirkwood_i2s_play_trigger()
378 ctl = priv->ctl_play; in kirkwood_i2s_play_trigger()
379 if (dai->id == 0) in kirkwood_i2s_play_trigger()
380 ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ in kirkwood_i2s_play_trigger()
385 writel(value, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
388 if (!runtime->no_period_wakeup) { in kirkwood_i2s_play_trigger()
389 value = readl(priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_play_trigger()
391 writel(value, priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_play_trigger()
395 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
402 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
404 value = readl(priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_play_trigger()
406 writel(value, priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_play_trigger()
410 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
417 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
425 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_play_trigger()
429 return -EINVAL; in kirkwood_i2s_play_trigger()
441 value = readl(priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
446 ctl = priv->ctl_rec; in kirkwood_i2s_rec_trigger()
447 if (dai->id == 0) in kirkwood_i2s_rec_trigger()
448 ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN; /* i2s */ in kirkwood_i2s_rec_trigger()
453 writel(value, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
456 value = readl(priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_rec_trigger()
458 writel(value, priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_rec_trigger()
461 writel(ctl, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
466 value = readl(priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
468 writel(value, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
470 value = readl(priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_rec_trigger()
472 writel(value, priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_rec_trigger()
475 value = readl(priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
477 writel(value, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
482 value = readl(priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
484 writel(value, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
489 value = readl(priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
491 writel(value, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_rec_trigger()
495 return -EINVAL; in kirkwood_i2s_rec_trigger()
504 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in kirkwood_i2s_trigger()
519 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE); in kirkwood_i2s_init()
520 writel(0, priv->io + KIRKWOOD_INT_MASK); in kirkwood_i2s_init()
522 reg_data = readl(priv->io + 0x1200); in kirkwood_i2s_init()
525 writel(reg_data, priv->io + 0x1200); in kirkwood_i2s_init()
529 reg_data = readl(priv->io + 0x1200); in kirkwood_i2s_init()
532 writel(reg_data, priv->io + 0x1200); in kirkwood_i2s_init()
535 value = readl(priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_init()
537 writel(value, priv->io + KIRKWOOD_PLAYCTL); in kirkwood_i2s_init()
539 value = readl(priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_init()
541 writel(value, priv->io + KIRKWOOD_RECCTL); in kirkwood_i2s_init()
556 .name = "i2s",
597 .name = "i2s",
642 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; in kirkwood_i2s_dev_probe()
645 struct device_node *np = pdev->dev.of_node; in kirkwood_i2s_dev_probe()
648 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in kirkwood_i2s_dev_probe()
650 return -ENOMEM; in kirkwood_i2s_dev_probe()
652 dev_set_drvdata(&pdev->dev, priv); in kirkwood_i2s_dev_probe()
654 if (of_device_is_compatible(np, "marvell,armada-380-audio")) in kirkwood_i2s_dev_probe()
655 priv->io = devm_platform_ioremap_resource_byname(pdev, "i2s_regs"); in kirkwood_i2s_dev_probe()
657 priv->io = devm_platform_ioremap_resource(pdev, 0); in kirkwood_i2s_dev_probe()
658 if (IS_ERR(priv->io)) in kirkwood_i2s_dev_probe()
659 return PTR_ERR(priv->io); in kirkwood_i2s_dev_probe()
661 priv->irq = platform_get_irq(pdev, 0); in kirkwood_i2s_dev_probe()
662 if (priv->irq < 0) in kirkwood_i2s_dev_probe()
663 return priv->irq; in kirkwood_i2s_dev_probe()
665 if (of_device_is_compatible(np, "marvell,armada-380-audio")) { in kirkwood_i2s_dev_probe()
670 armada_38x_set_pll(priv->pll_config, 44100); in kirkwood_i2s_dev_probe()
674 priv->burst = 128; /* might be 32 or 128 */ in kirkwood_i2s_dev_probe()
676 priv->burst = data->burst; in kirkwood_i2s_dev_probe()
678 dev_err(&pdev->dev, "no DT nor platform data ?!\n"); in kirkwood_i2s_dev_probe()
679 return -EINVAL; in kirkwood_i2s_dev_probe()
682 priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL); in kirkwood_i2s_dev_probe()
683 if (IS_ERR(priv->clk)) { in kirkwood_i2s_dev_probe()
684 dev_err(&pdev->dev, "no clock\n"); in kirkwood_i2s_dev_probe()
685 return PTR_ERR(priv->clk); in kirkwood_i2s_dev_probe()
688 priv->extclk = devm_clk_get(&pdev->dev, "extclk"); in kirkwood_i2s_dev_probe()
689 if (IS_ERR(priv->extclk)) { in kirkwood_i2s_dev_probe()
690 if (PTR_ERR(priv->extclk) == -EPROBE_DEFER) in kirkwood_i2s_dev_probe()
691 return -EPROBE_DEFER; in kirkwood_i2s_dev_probe()
693 if (clk_is_match(priv->extclk, priv->clk)) { in kirkwood_i2s_dev_probe()
694 devm_clk_put(&pdev->dev, priv->extclk); in kirkwood_i2s_dev_probe()
695 priv->extclk = ERR_PTR(-EINVAL); in kirkwood_i2s_dev_probe()
697 dev_info(&pdev->dev, "found external clock\n"); in kirkwood_i2s_dev_probe()
698 clk_prepare_enable(priv->extclk); in kirkwood_i2s_dev_probe()
703 err = clk_prepare_enable(priv->clk); in kirkwood_i2s_dev_probe()
707 /* Some sensible defaults - this reflects the powerup values */ in kirkwood_i2s_dev_probe()
708 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; in kirkwood_i2s_dev_probe()
709 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; in kirkwood_i2s_dev_probe()
712 if (priv->burst == 32) { in kirkwood_i2s_dev_probe()
713 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; in kirkwood_i2s_dev_probe()
714 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; in kirkwood_i2s_dev_probe()
716 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; in kirkwood_i2s_dev_probe()
717 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; in kirkwood_i2s_dev_probe()
720 err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component, in kirkwood_i2s_dev_probe()
723 dev_err(&pdev->dev, "snd_soc_register_component failed\n"); in kirkwood_i2s_dev_probe()
732 if (!IS_ERR(priv->extclk)) in kirkwood_i2s_dev_probe()
733 clk_disable_unprepare(priv->extclk); in kirkwood_i2s_dev_probe()
734 clk_disable_unprepare(priv->clk); in kirkwood_i2s_dev_probe()
741 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); in kirkwood_i2s_dev_remove()
743 snd_soc_unregister_component(&pdev->dev); in kirkwood_i2s_dev_remove()
744 if (!IS_ERR(priv->extclk)) in kirkwood_i2s_dev_remove()
745 clk_disable_unprepare(priv->extclk); in kirkwood_i2s_dev_remove()
746 clk_disable_unprepare(priv->clk); in kirkwood_i2s_dev_remove()
751 { .compatible = "marvell,kirkwood-audio" },
752 { .compatible = "marvell,dove-audio" },
753 { .compatible = "marvell,armada370-audio" },
754 { .compatible = "marvell,armada-380-audio" },
772 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
773 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
775 MODULE_ALIAS("platform:mvebu-audio");