^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * kirkwood-i2s.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (c) 2010 Arnaud Patard <apatard@mandriva.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/platform_data/asoc-kirkwood.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "kirkwood.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define KIRKWOOD_I2S_FORMATS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) (SNDRV_PCM_FMTBIT_S16_LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) SNDRV_PCM_FMTBIT_S24_LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) SNDRV_PCM_FMTBIT_S32_LE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define KIRKWOOD_SPDIF_FORMATS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) (SNDRV_PCM_FMTBIT_S16_LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) SNDRV_PCM_FMTBIT_S24_LE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned long mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case SND_SOC_DAIFMT_RIGHT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) mask = KIRKWOOD_I2S_CTL_RJ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case SND_SOC_DAIFMT_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) mask = KIRKWOOD_I2S_CTL_LJ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) mask = KIRKWOOD_I2S_CTL_I2S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Set same format for playback and record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * This avoids some troubles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) value |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) value |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) value = KIRKWOOD_DCO_CTL_OFFSET_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) value |= KIRKWOOD_DCO_CTL_FREQ_11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) value |= KIRKWOOD_DCO_CTL_FREQ_12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) value |= KIRKWOOD_DCO_CTL_FREQ_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) writel(value, io + KIRKWOOD_DCO_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* wait for dco locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) } while (value == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void kirkwood_set_rate(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct kirkwood_dma_data *priv, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) uint32_t clks_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (IS_ERR(priv->extclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* use internal dco for the supported rates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * defined in kirkwood_i2s_dai */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __func__, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) kirkwood_set_dco(priv->io, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* use the external clock for the other rates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * defined in kirkwood_i2s_dai_extclk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) __func__, rate, 256 * rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) clk_set_rate(priv->extclk, 256 * rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) snd_soc_dai_set_dma_data(dai, substream, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) uint32_t ctl_play, ctl_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned int i2s_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long i2s_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) i2s_reg = KIRKWOOD_I2S_PLAYCTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) i2s_reg = KIRKWOOD_I2S_RECCTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) kirkwood_set_rate(dai, priv, params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) i2s_value = readl(priv->io+i2s_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Size settings in play/rec i2s control regs and play/rec control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * regs must be the same.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) switch (params_format(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) KIRKWOOD_PLAYCTL_I2S_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) KIRKWOOD_PLAYCTL_SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) KIRKWOOD_RECCTL_I2S_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) KIRKWOOD_RECCTL_SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * doesn't work... S20_3LE != kirkwood 20bit format ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) case SNDRV_PCM_FORMAT_S20_3LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) KIRKWOOD_PLAYCTL_I2S_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) KIRKWOOD_RECCTL_I2S_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case SNDRV_PCM_FORMAT_S24_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) KIRKWOOD_PLAYCTL_I2S_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) KIRKWOOD_PLAYCTL_SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) KIRKWOOD_RECCTL_I2S_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) KIRKWOOD_RECCTL_SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) case SNDRV_PCM_FORMAT_S32_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) KIRKWOOD_PLAYCTL_I2S_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) KIRKWOOD_RECCTL_I2S_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (params_channels(params) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) KIRKWOOD_PLAYCTL_ENABLE_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) KIRKWOOD_PLAYCTL_SIZE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) priv->ctl_play |= ctl_play;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) KIRKWOOD_RECCTL_SIZE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) priv->ctl_rec |= ctl_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) writel(i2s_value, priv->io+i2s_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static unsigned kirkwood_i2s_play_mute(unsigned ctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int cmd, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) uint32_t ctl, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned timeout = 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * The Armada510 spec says that if we enter pause mode, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * busy bit must be read back as clear _twice_. Make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * we respect that otherwise we get DMA underruns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) value = ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) } while (timeout--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* configure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ctl = priv->ctl_play;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (dai->id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ctl = kirkwood_i2s_play_mute(ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) writel(value, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!runtime->no_period_wakeup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) value = readl(priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) writel(value, priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* enable playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* stop audio, disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) KIRKWOOD_PLAYCTL_SPDIF_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) value = readl(priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) writel(value, priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* disable all playbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) KIRKWOOD_PLAYCTL_SPDIF_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) KIRKWOOD_PLAYCTL_SPDIF_MUTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ctl = kirkwood_i2s_play_mute(ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int cmd, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) uint32_t ctl, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) value = readl(priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* configure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ctl = priv->ctl_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (dai->id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN; /* i2s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) writel(value, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) value = readl(priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) writel(value, priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* enable record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) writel(ctl, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* stop audio, disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) value = readl(priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) writel(value, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) value = readl(priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) writel(value, priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* disable all records */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) value = readl(priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) writel(value, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) value = readl(priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) writel(value, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) value = readl(priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) writel(value, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return kirkwood_i2s_play_trigger(substream, cmd, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return kirkwood_i2s_rec_trigger(substream, cmd, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) unsigned int reg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* put system in a "safe" state : */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* disable audio interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) writel(0, priv->io + KIRKWOOD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) reg_data = readl(priv->io + 0x1200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) reg_data &= (~(0x333FF8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) reg_data |= 0x111D18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) writel(reg_data, priv->io + 0x1200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) reg_data = readl(priv->io + 0x1200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) reg_data &= (~(0x333FF8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) reg_data |= 0x111D18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) writel(reg_data, priv->io + 0x1200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* disable playback/record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) value = readl(priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) writel(value, priv->io + KIRKWOOD_PLAYCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) value = readl(priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) writel(value, priv->io + KIRKWOOD_RECCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .startup = kirkwood_i2s_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .trigger = kirkwood_i2s_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .hw_params = kirkwood_i2s_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .set_fmt = kirkwood_i2s_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .name = "i2s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) SNDRV_PCM_RATE_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) .formats = KIRKWOOD_I2S_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) SNDRV_PCM_RATE_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) .formats = KIRKWOOD_I2S_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .ops = &kirkwood_i2s_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .name = "spdif",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .id = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) SNDRV_PCM_RATE_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .formats = KIRKWOOD_SPDIF_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) SNDRV_PCM_RATE_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .formats = KIRKWOOD_SPDIF_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .ops = &kirkwood_i2s_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .name = "i2s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) .rates = SNDRV_PCM_RATE_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) .rate_min = 5512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .formats = KIRKWOOD_I2S_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) .rates = SNDRV_PCM_RATE_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .rate_min = 5512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) .formats = KIRKWOOD_I2S_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .ops = &kirkwood_i2s_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .name = "spdif",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .id = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) .rates = SNDRV_PCM_RATE_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .rate_min = 5512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .formats = KIRKWOOD_SPDIF_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .rates = SNDRV_PCM_RATE_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .rate_min = 5512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .formats = KIRKWOOD_SPDIF_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) .ops = &kirkwood_i2s_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct kirkwood_dma_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_set_drvdata(&pdev->dev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) priv->io = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (IS_ERR(priv->io))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return PTR_ERR(priv->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) priv->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (priv->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return priv->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) priv->burst = 128; /* might be 32 or 128 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) } else if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) priv->burst = data->burst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) dev_err(&pdev->dev, "no DT nor platform data ?!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (IS_ERR(priv->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dev_err(&pdev->dev, "no clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return PTR_ERR(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) priv->extclk = devm_clk_get(&pdev->dev, "extclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (IS_ERR(priv->extclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (clk_is_match(priv->extclk, priv->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) devm_clk_put(&pdev->dev, priv->extclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) priv->extclk = ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) dev_info(&pdev->dev, "found external clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) clk_prepare_enable(priv->extclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) soc_dai = kirkwood_i2s_dai_extclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) err = clk_prepare_enable(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* Some sensible defaults - this reflects the powerup values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* Select the burst size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (priv->burst == 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) soc_dai, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) dev_err(&pdev->dev, "snd_soc_register_component failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) goto err_component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) kirkwood_i2s_init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) err_component:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (!IS_ERR(priv->extclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) clk_disable_unprepare(priv->extclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) clk_disable_unprepare(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) snd_soc_unregister_component(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (!IS_ERR(priv->extclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) clk_disable_unprepare(priv->extclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) clk_disable_unprepare(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static const struct of_device_id mvebu_audio_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) { .compatible = "marvell,kirkwood-audio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) { .compatible = "marvell,dove-audio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) { .compatible = "marvell,armada370-audio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static struct platform_driver kirkwood_i2s_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) .probe = kirkwood_i2s_dev_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .remove = kirkwood_i2s_dev_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) .of_match_table = of_match_ptr(mvebu_audio_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) module_platform_driver(kirkwood_i2s_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* Module information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) MODULE_ALIAS("platform:mvebu-audio");