kirkwood-i2s.c (c95baf12f5077419db01313ab61c2aac007d40cd) | kirkwood-i2s.c (2adfc688777e58f22f691d08728dd74d76177fd9) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * kirkwood-i2s.c 4 * 5 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 6 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 7 */ 8 --- 17 unchanged lines hidden (view full) --- 26 (SNDRV_PCM_FMTBIT_S16_LE | \ 27 SNDRV_PCM_FMTBIT_S24_LE | \ 28 SNDRV_PCM_FMTBIT_S32_LE) 29 30#define KIRKWOOD_SPDIF_FORMATS \ 31 (SNDRV_PCM_FMTBIT_S16_LE | \ 32 SNDRV_PCM_FMTBIT_S24_LE) 33 | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * kirkwood-i2s.c 4 * 5 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 6 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 7 */ 8 --- 17 unchanged lines hidden (view full) --- 26 (SNDRV_PCM_FMTBIT_S16_LE | \ 27 SNDRV_PCM_FMTBIT_S24_LE | \ 28 SNDRV_PCM_FMTBIT_S32_LE) 29 30#define KIRKWOOD_SPDIF_FORMATS \ 31 (SNDRV_PCM_FMTBIT_S16_LE | \ 32 SNDRV_PCM_FMTBIT_S24_LE) 33 |
34/* These registers are relative to the second register region - 35 * audio pll configuration. 36 */ 37#define A38X_PLL_CONF_REG0 0x0 38#define A38X_PLL_FB_CLK_DIV_OFFSET 10 39#define A38X_PLL_FB_CLK_DIV_MASK 0x7fc00 40#define A38X_PLL_CONF_REG1 0x4 41#define A38X_PLL_FREQ_OFFSET_MASK 0xffff 42#define A38X_PLL_FREQ_OFFSET_VALID BIT(16) 43#define A38X_PLL_SW_RESET BIT(31) 44#define A38X_PLL_CONF_REG2 0x8 45#define A38X_PLL_AUDIO_POSTDIV_MASK 0x7f 46 47/* Bit below belongs to SoC control register corresponding to the third 48 * register region. 49 */ 50#define A38X_SPDIF_MODE_ENABLE BIT(27) 51 52static int armada_38x_i2s_init_quirk(struct platform_device *pdev, 53 struct kirkwood_dma_data *priv, 54 struct snd_soc_dai_driver *dai_drv) 55{ 56 struct device_node *np = pdev->dev.of_node; 57 u32 reg_val; 58 int i; 59 60 priv->pll_config = devm_platform_ioremap_resource_byname(pdev, "pll_regs"); 61 if (IS_ERR(priv->pll_config)) 62 return -ENOMEM; 63 64 priv->soc_control = devm_platform_ioremap_resource_byname(pdev, "soc_ctrl"); 65 if (IS_ERR(priv->soc_control)) 66 return -ENOMEM; 67 68 /* Select one of exceptive modes: I2S or S/PDIF */ 69 reg_val = readl(priv->soc_control); 70 if (of_property_read_bool(np, "spdif-mode")) { 71 reg_val |= A38X_SPDIF_MODE_ENABLE; 72 dev_info(&pdev->dev, "using S/PDIF mode\n"); 73 } else { 74 reg_val &= ~A38X_SPDIF_MODE_ENABLE; 75 dev_info(&pdev->dev, "using I2S mode\n"); 76 } 77 writel(reg_val, priv->soc_control); 78 79 /* Update available rates of mclk's fs */ 80 for (i = 0; i < 2; i++) { 81 dai_drv[i].playback.rates |= SNDRV_PCM_RATE_192000; 82 dai_drv[i].capture.rates |= SNDRV_PCM_RATE_192000; 83 } 84 85 return 0; 86} 87 88static inline void armada_38x_set_pll(void __iomem *base, unsigned long rate) 89{ 90 u32 reg_val; 91 u16 freq_offset = 0x22b0; 92 u8 audio_postdiv, fb_clk_div = 0x1d; 93 94 /* Set frequency offset value to not valid and enable PLL reset */ 95 reg_val = readl(base + A38X_PLL_CONF_REG1); 96 reg_val &= ~A38X_PLL_FREQ_OFFSET_VALID; 97 reg_val &= ~A38X_PLL_SW_RESET; 98 writel(reg_val, base + A38X_PLL_CONF_REG1); 99 100 udelay(1); 101 102 /* Update PLL parameters */ 103 switch (rate) { 104 default: 105 case 44100: 106 freq_offset = 0x735; 107 fb_clk_div = 0x1b; 108 audio_postdiv = 0xc; 109 break; 110 case 48000: 111 audio_postdiv = 0xc; 112 break; 113 case 96000: 114 audio_postdiv = 0x6; 115 break; 116 case 192000: 117 audio_postdiv = 0x3; 118 break; 119 } 120 121 reg_val = readl(base + A38X_PLL_CONF_REG0); 122 reg_val &= ~A38X_PLL_FB_CLK_DIV_MASK; 123 reg_val |= (fb_clk_div << A38X_PLL_FB_CLK_DIV_OFFSET); 124 writel(reg_val, base + A38X_PLL_CONF_REG0); 125 126 reg_val = readl(base + A38X_PLL_CONF_REG2); 127 reg_val &= ~A38X_PLL_AUDIO_POSTDIV_MASK; 128 reg_val |= audio_postdiv; 129 writel(reg_val, base + A38X_PLL_CONF_REG2); 130 131 reg_val = readl(base + A38X_PLL_CONF_REG1); 132 reg_val &= ~A38X_PLL_FREQ_OFFSET_MASK; 133 reg_val |= freq_offset; 134 writel(reg_val, base + A38X_PLL_CONF_REG1); 135 136 udelay(1); 137 138 /* Disable reset */ 139 reg_val |= A38X_PLL_SW_RESET; 140 writel(reg_val, base + A38X_PLL_CONF_REG1); 141 142 /* Wait 50us for PLL to lock */ 143 udelay(50); 144 145 /* Restore frequency offset value validity */ 146 reg_val |= A38X_PLL_FREQ_OFFSET_VALID; 147 writel(reg_val, base + A38X_PLL_CONF_REG1); 148} 149 |
|
34static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 35 unsigned int fmt) 36{ 37 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); 38 unsigned long mask; 39 unsigned long value; 40 41 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { --- 59 unchanged lines hidden (view full) --- 101{ 102 uint32_t clks_ctrl; 103 104 if (IS_ERR(priv->extclk)) { 105 /* use internal dco for the supported rates 106 * defined in kirkwood_i2s_dai */ 107 dev_dbg(dai->dev, "%s: dco set rate = %lu\n", 108 __func__, rate); | 150static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 151 unsigned int fmt) 152{ 153 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); 154 unsigned long mask; 155 unsigned long value; 156 157 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { --- 59 unchanged lines hidden (view full) --- 217{ 218 uint32_t clks_ctrl; 219 220 if (IS_ERR(priv->extclk)) { 221 /* use internal dco for the supported rates 222 * defined in kirkwood_i2s_dai */ 223 dev_dbg(dai->dev, "%s: dco set rate = %lu\n", 224 __func__, rate); |
109 kirkwood_set_dco(priv->io, rate); | 225 if (priv->pll_config) 226 armada_38x_set_pll(priv->pll_config, rate); 227 else 228 kirkwood_set_dco(priv->io, rate); |
110 111 clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO; 112 } else { 113 /* use the external clock for the other rates 114 * defined in kirkwood_i2s_dai_extclk */ 115 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", 116 __func__, rate, 256 * rate); 117 clk_set_rate(priv->extclk, 256 * rate); --- 409 unchanged lines hidden (view full) --- 527 int err; 528 529 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 530 if (!priv) 531 return -ENOMEM; 532 533 dev_set_drvdata(&pdev->dev, priv); 534 | 229 230 clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO; 231 } else { 232 /* use the external clock for the other rates 233 * defined in kirkwood_i2s_dai_extclk */ 234 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", 235 __func__, rate, 256 * rate); 236 clk_set_rate(priv->extclk, 256 * rate); --- 409 unchanged lines hidden (view full) --- 646 int err; 647 648 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 649 if (!priv) 650 return -ENOMEM; 651 652 dev_set_drvdata(&pdev->dev, priv); 653 |
535 priv->io = devm_platform_ioremap_resource(pdev, 0); | 654 if (of_device_is_compatible(np, "marvell,armada-380-audio")) 655 priv->io = devm_platform_ioremap_resource_byname(pdev, "i2s_regs"); 656 else 657 priv->io = devm_platform_ioremap_resource(pdev, 0); |
536 if (IS_ERR(priv->io)) 537 return PTR_ERR(priv->io); 538 539 priv->irq = platform_get_irq(pdev, 0); 540 if (priv->irq < 0) 541 return priv->irq; 542 | 658 if (IS_ERR(priv->io)) 659 return PTR_ERR(priv->io); 660 661 priv->irq = platform_get_irq(pdev, 0); 662 if (priv->irq < 0) 663 return priv->irq; 664 |
665 if (of_device_is_compatible(np, "marvell,armada-380-audio")) { 666 err = armada_38x_i2s_init_quirk(pdev, priv, soc_dai); 667 if (err < 0) 668 return err; 669 /* Set initial pll frequency */ 670 armada_38x_set_pll(priv->pll_config, 44100); 671 } 672 |
|
543 if (np) { 544 priv->burst = 128; /* might be 32 or 128 */ 545 } else if (data) { 546 priv->burst = data->burst; 547 } else { 548 dev_err(&pdev->dev, "no DT nor platform data ?!\n"); 549 return -EINVAL; 550 } --- 67 unchanged lines hidden (view full) --- 618 return 0; 619} 620 621#ifdef CONFIG_OF 622static const struct of_device_id mvebu_audio_of_match[] = { 623 { .compatible = "marvell,kirkwood-audio" }, 624 { .compatible = "marvell,dove-audio" }, 625 { .compatible = "marvell,armada370-audio" }, | 673 if (np) { 674 priv->burst = 128; /* might be 32 or 128 */ 675 } else if (data) { 676 priv->burst = data->burst; 677 } else { 678 dev_err(&pdev->dev, "no DT nor platform data ?!\n"); 679 return -EINVAL; 680 } --- 67 unchanged lines hidden (view full) --- 748 return 0; 749} 750 751#ifdef CONFIG_OF 752static const struct of_device_id mvebu_audio_of_match[] = { 753 { .compatible = "marvell,kirkwood-audio" }, 754 { .compatible = "marvell,dove-audio" }, 755 { .compatible = "marvell,armada370-audio" }, |
756 { .compatible = "marvell,armada-380-audio" }, |
|
626 { } 627}; 628MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); 629#endif 630 631static struct platform_driver kirkwood_i2s_driver = { 632 .probe = kirkwood_i2s_dev_probe, 633 .remove = kirkwood_i2s_dev_remove, --- 13 unchanged lines hidden --- | 757 { } 758}; 759MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); 760#endif 761 762static struct platform_driver kirkwood_i2s_driver = { 763 .probe = kirkwood_i2s_dev_probe, 764 .remove = kirkwood_i2s_dev_remove, --- 13 unchanged lines hidden --- |