1f9b95980Sapatard@mandriva.com /* 2f9b95980Sapatard@mandriva.com * kirkwood-i2s.c 3f9b95980Sapatard@mandriva.com * 4f9b95980Sapatard@mandriva.com * (c) 2010 Arnaud Patard <apatard@mandriva.com> 569737897SArnaud Patard (Rtp) * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 6f9b95980Sapatard@mandriva.com * 7f9b95980Sapatard@mandriva.com * This program is free software; you can redistribute it and/or modify it 8f9b95980Sapatard@mandriva.com * under the terms of the GNU General Public License as published by the 9f9b95980Sapatard@mandriva.com * Free Software Foundation; either version 2 of the License, or (at your 10f9b95980Sapatard@mandriva.com * option) any later version. 11f9b95980Sapatard@mandriva.com */ 12f9b95980Sapatard@mandriva.com 13f9b95980Sapatard@mandriva.com #include <linux/init.h> 14f9b95980Sapatard@mandriva.com #include <linux/module.h> 15f9b95980Sapatard@mandriva.com #include <linux/platform_device.h> 16f9b95980Sapatard@mandriva.com #include <linux/io.h> 17f9b95980Sapatard@mandriva.com #include <linux/slab.h> 18f9b95980Sapatard@mandriva.com #include <linux/mbus.h> 19f9b95980Sapatard@mandriva.com #include <linux/delay.h> 20e919c716SAndrew Lunn #include <linux/clk.h> 21f9b95980Sapatard@mandriva.com #include <sound/pcm.h> 22f9b95980Sapatard@mandriva.com #include <sound/pcm_params.h> 23f9b95980Sapatard@mandriva.com #include <sound/soc.h> 24c02cecb9SArnd Bergmann #include <linux/platform_data/asoc-kirkwood.h> 25eb632318SJean-Francois Moine #include <linux/of.h> 26eb632318SJean-Francois Moine 27f9b95980Sapatard@mandriva.com #include "kirkwood.h" 28f9b95980Sapatard@mandriva.com 29f9b95980Sapatard@mandriva.com #define KIRKWOOD_I2S_FORMATS \ 30f9b95980Sapatard@mandriva.com (SNDRV_PCM_FMTBIT_S16_LE | \ 31f9b95980Sapatard@mandriva.com SNDRV_PCM_FMTBIT_S24_LE | \ 32f9b95980Sapatard@mandriva.com SNDRV_PCM_FMTBIT_S32_LE) 33f9b95980Sapatard@mandriva.com 341c195ddbSJean-Francois Moine #define KIRKWOOD_SPDIF_FORMATS \ 351c195ddbSJean-Francois Moine (SNDRV_PCM_FMTBIT_S16_LE | \ 361c195ddbSJean-Francois Moine SNDRV_PCM_FMTBIT_S24_LE) 371c195ddbSJean-Francois Moine 38f9b95980Sapatard@mandriva.com static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 39f9b95980Sapatard@mandriva.com unsigned int fmt) 40f9b95980Sapatard@mandriva.com { 41f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); 42f9b95980Sapatard@mandriva.com unsigned long mask; 43f9b95980Sapatard@mandriva.com unsigned long value; 44f9b95980Sapatard@mandriva.com 45f9b95980Sapatard@mandriva.com switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 46f9b95980Sapatard@mandriva.com case SND_SOC_DAIFMT_RIGHT_J: 47f9b95980Sapatard@mandriva.com mask = KIRKWOOD_I2S_CTL_RJ; 48f9b95980Sapatard@mandriva.com break; 49f9b95980Sapatard@mandriva.com case SND_SOC_DAIFMT_LEFT_J: 50f9b95980Sapatard@mandriva.com mask = KIRKWOOD_I2S_CTL_LJ; 51f9b95980Sapatard@mandriva.com break; 52f9b95980Sapatard@mandriva.com case SND_SOC_DAIFMT_I2S: 53f9b95980Sapatard@mandriva.com mask = KIRKWOOD_I2S_CTL_I2S; 54f9b95980Sapatard@mandriva.com break; 55f9b95980Sapatard@mandriva.com default: 56f9b95980Sapatard@mandriva.com return -EINVAL; 57f9b95980Sapatard@mandriva.com } 58f9b95980Sapatard@mandriva.com 59f9b95980Sapatard@mandriva.com /* 60f9b95980Sapatard@mandriva.com * Set same format for playback and record 61f9b95980Sapatard@mandriva.com * This avoids some troubles. 62f9b95980Sapatard@mandriva.com */ 63f9b95980Sapatard@mandriva.com value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL); 64f9b95980Sapatard@mandriva.com value &= ~KIRKWOOD_I2S_CTL_JUST_MASK; 65f9b95980Sapatard@mandriva.com value |= mask; 66f9b95980Sapatard@mandriva.com writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL); 67f9b95980Sapatard@mandriva.com 68f9b95980Sapatard@mandriva.com value = readl(priv->io+KIRKWOOD_I2S_RECCTL); 69f9b95980Sapatard@mandriva.com value &= ~KIRKWOOD_I2S_CTL_JUST_MASK; 70f9b95980Sapatard@mandriva.com value |= mask; 71f9b95980Sapatard@mandriva.com writel(value, priv->io+KIRKWOOD_I2S_RECCTL); 72f9b95980Sapatard@mandriva.com 73f9b95980Sapatard@mandriva.com return 0; 74f9b95980Sapatard@mandriva.com } 75f9b95980Sapatard@mandriva.com 76f9b95980Sapatard@mandriva.com static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) 77f9b95980Sapatard@mandriva.com { 78f9b95980Sapatard@mandriva.com unsigned long value; 79f9b95980Sapatard@mandriva.com 80f9b95980Sapatard@mandriva.com value = KIRKWOOD_DCO_CTL_OFFSET_0; 81f9b95980Sapatard@mandriva.com switch (rate) { 82f9b95980Sapatard@mandriva.com default: 83f9b95980Sapatard@mandriva.com case 44100: 84f9b95980Sapatard@mandriva.com value |= KIRKWOOD_DCO_CTL_FREQ_11; 85f9b95980Sapatard@mandriva.com break; 86f9b95980Sapatard@mandriva.com case 48000: 87f9b95980Sapatard@mandriva.com value |= KIRKWOOD_DCO_CTL_FREQ_12; 88f9b95980Sapatard@mandriva.com break; 89f9b95980Sapatard@mandriva.com case 96000: 90f9b95980Sapatard@mandriva.com value |= KIRKWOOD_DCO_CTL_FREQ_24; 91f9b95980Sapatard@mandriva.com break; 92f9b95980Sapatard@mandriva.com } 93f9b95980Sapatard@mandriva.com writel(value, io + KIRKWOOD_DCO_CTL); 94f9b95980Sapatard@mandriva.com 95f9b95980Sapatard@mandriva.com /* wait for dco locked */ 96f9b95980Sapatard@mandriva.com do { 97f9b95980Sapatard@mandriva.com cpu_relax(); 98f9b95980Sapatard@mandriva.com value = readl(io + KIRKWOOD_DCO_SPCR_STATUS); 992424d458SRussell King value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK; 100f9b95980Sapatard@mandriva.com } while (value == 0); 101f9b95980Sapatard@mandriva.com } 102f9b95980Sapatard@mandriva.com 103363589bfSRussell King static void kirkwood_set_rate(struct snd_soc_dai *dai, 104363589bfSRussell King struct kirkwood_dma_data *priv, unsigned long rate) 105363589bfSRussell King { 106363589bfSRussell King uint32_t clks_ctrl; 107363589bfSRussell King 1081f1b6579SJean-Francois Moine if (IS_ERR(priv->extclk)) { 1098a537f85SJean-Francois Moine /* use internal dco for the supported rates 1108a537f85SJean-Francois Moine * defined in kirkwood_i2s_dai */ 111363589bfSRussell King dev_dbg(dai->dev, "%s: dco set rate = %lu\n", 112363589bfSRussell King __func__, rate); 113363589bfSRussell King kirkwood_set_dco(priv->io, rate); 114363589bfSRussell King 115363589bfSRussell King clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO; 1168a537f85SJean-Francois Moine } else { 1178a537f85SJean-Francois Moine /* use the external clock for the other rates 1188a537f85SJean-Francois Moine * defined in kirkwood_i2s_dai_extclk */ 119363589bfSRussell King dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", 120363589bfSRussell King __func__, rate, 256 * rate); 121363589bfSRussell King clk_set_rate(priv->extclk, 256 * rate); 122363589bfSRussell King 123363589bfSRussell King clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK; 124363589bfSRussell King } 125363589bfSRussell King writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL); 126363589bfSRussell King } 127363589bfSRussell King 128f0fba2adSLiam Girdwood static int kirkwood_i2s_startup(struct snd_pcm_substream *substream, 129f0fba2adSLiam Girdwood struct snd_soc_dai *dai) 130f0fba2adSLiam Girdwood { 131f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 132f0fba2adSLiam Girdwood 133f0fba2adSLiam Girdwood snd_soc_dai_set_dma_data(dai, substream, priv); 134f0fba2adSLiam Girdwood return 0; 135f0fba2adSLiam Girdwood } 136f0fba2adSLiam Girdwood 137f9b95980Sapatard@mandriva.com static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, 138f9b95980Sapatard@mandriva.com struct snd_pcm_hw_params *params, 139f9b95980Sapatard@mandriva.com struct snd_soc_dai *dai) 140f9b95980Sapatard@mandriva.com { 141f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 142d8d11ba5SRussell King uint32_t ctl_play, ctl_rec; 143d8d11ba5SRussell King unsigned int i2s_reg; 144d8d11ba5SRussell King unsigned long i2s_value; 145f9b95980Sapatard@mandriva.com 146f9b95980Sapatard@mandriva.com if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 147f9b95980Sapatard@mandriva.com i2s_reg = KIRKWOOD_I2S_PLAYCTL; 148f9b95980Sapatard@mandriva.com } else { 149f9b95980Sapatard@mandriva.com i2s_reg = KIRKWOOD_I2S_RECCTL; 150f9b95980Sapatard@mandriva.com } 151f9b95980Sapatard@mandriva.com 152363589bfSRussell King kirkwood_set_rate(dai, priv, params_rate(params)); 153f9b95980Sapatard@mandriva.com 154f9b95980Sapatard@mandriva.com i2s_value = readl(priv->io+i2s_reg); 155f9b95980Sapatard@mandriva.com i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK; 156f9b95980Sapatard@mandriva.com 157f9b95980Sapatard@mandriva.com /* 158f9b95980Sapatard@mandriva.com * Size settings in play/rec i2s control regs and play/rec control 159f9b95980Sapatard@mandriva.com * regs must be the same. 160f9b95980Sapatard@mandriva.com */ 161f9b95980Sapatard@mandriva.com switch (params_format(params)) { 162f9b95980Sapatard@mandriva.com case SNDRV_PCM_FORMAT_S16_LE: 163f9b95980Sapatard@mandriva.com i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16; 164d8d11ba5SRussell King ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C | 16575b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_I2S_EN | 16675b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_SPDIF_EN; 167d8d11ba5SRussell King ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C | 16875b9b65eSJean-Francois Moine KIRKWOOD_RECCTL_I2S_EN | 16975b9b65eSJean-Francois Moine KIRKWOOD_RECCTL_SPDIF_EN; 170f9b95980Sapatard@mandriva.com break; 171f9b95980Sapatard@mandriva.com /* 172f9b95980Sapatard@mandriva.com * doesn't work... S20_3LE != kirkwood 20bit format ? 173f9b95980Sapatard@mandriva.com * 174f9b95980Sapatard@mandriva.com case SNDRV_PCM_FORMAT_S20_3LE: 175f9b95980Sapatard@mandriva.com i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20; 176d8d11ba5SRussell King ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 | 177d8d11ba5SRussell King KIRKWOOD_PLAYCTL_I2S_EN; 178d8d11ba5SRussell King ctl_rec = KIRKWOOD_RECCTL_SIZE_20 | 179d8d11ba5SRussell King KIRKWOOD_RECCTL_I2S_EN; 180f9b95980Sapatard@mandriva.com break; 181f9b95980Sapatard@mandriva.com */ 182f9b95980Sapatard@mandriva.com case SNDRV_PCM_FORMAT_S24_LE: 183f9b95980Sapatard@mandriva.com i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24; 184d8d11ba5SRussell King ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 | 18575b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_I2S_EN | 18675b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_SPDIF_EN; 187d8d11ba5SRussell King ctl_rec = KIRKWOOD_RECCTL_SIZE_24 | 18875b9b65eSJean-Francois Moine KIRKWOOD_RECCTL_I2S_EN | 18975b9b65eSJean-Francois Moine KIRKWOOD_RECCTL_SPDIF_EN; 190f9b95980Sapatard@mandriva.com break; 191f9b95980Sapatard@mandriva.com case SNDRV_PCM_FORMAT_S32_LE: 192f9b95980Sapatard@mandriva.com i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; 193d8d11ba5SRussell King ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 | 194d8d11ba5SRussell King KIRKWOOD_PLAYCTL_I2S_EN; 195d8d11ba5SRussell King ctl_rec = KIRKWOOD_RECCTL_SIZE_32 | 196d8d11ba5SRussell King KIRKWOOD_RECCTL_I2S_EN; 197f9b95980Sapatard@mandriva.com break; 198f9b95980Sapatard@mandriva.com default: 199f9b95980Sapatard@mandriva.com return -EINVAL; 200f9b95980Sapatard@mandriva.com } 201dfe4c936Sarnaud.patard@rtp-net.org 202dfe4c936Sarnaud.patard@rtp-net.org if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 203dfe4c936Sarnaud.patard@rtp-net.org if (params_channels(params) == 1) 204d8d11ba5SRussell King ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH; 205dfe4c936Sarnaud.patard@rtp-net.org else 206d8d11ba5SRussell King ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; 207d8d11ba5SRussell King 208d8d11ba5SRussell King priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | 209db43b16fSRussell King KIRKWOOD_PLAYCTL_ENABLE_MASK | 210d8d11ba5SRussell King KIRKWOOD_PLAYCTL_SIZE_MASK); 211d8d11ba5SRussell King priv->ctl_play |= ctl_play; 212d8d11ba5SRussell King } else { 21367721906SRussell King priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK | 21467721906SRussell King KIRKWOOD_RECCTL_SIZE_MASK); 215d8d11ba5SRussell King priv->ctl_rec |= ctl_rec; 216dfe4c936Sarnaud.patard@rtp-net.org } 217dfe4c936Sarnaud.patard@rtp-net.org 218f9b95980Sapatard@mandriva.com writel(i2s_value, priv->io+i2s_reg); 219f9b95980Sapatard@mandriva.com 220f9b95980Sapatard@mandriva.com return 0; 221f9b95980Sapatard@mandriva.com } 222f9b95980Sapatard@mandriva.com 2232fbc3821SRussell King static unsigned kirkwood_i2s_play_mute(unsigned ctl) 2242fbc3821SRussell King { 2252fbc3821SRussell King if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN)) 2262fbc3821SRussell King ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE; 2272fbc3821SRussell King if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN)) 2282fbc3821SRussell King ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE; 2292fbc3821SRussell King return ctl; 2302fbc3821SRussell King } 2312fbc3821SRussell King 232f9b95980Sapatard@mandriva.com static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 233f9b95980Sapatard@mandriva.com int cmd, struct snd_soc_dai *dai) 234f9b95980Sapatard@mandriva.com { 235920ec4e5SRussell King struct snd_pcm_runtime *runtime = substream->runtime; 236f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 237982b604bSRussell King uint32_t ctl, value; 238f9b95980Sapatard@mandriva.com 239982b604bSRussell King ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 2404d2097e5SRussell King if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) { 241982b604bSRussell King unsigned timeout = 5000; 242f9b95980Sapatard@mandriva.com /* 243982b604bSRussell King * The Armada510 spec says that if we enter pause mode, the 244982b604bSRussell King * busy bit must be read back as clear _twice_. Make sure 245982b604bSRussell King * we respect that otherwise we get DMA underruns. 246f9b95980Sapatard@mandriva.com */ 247982b604bSRussell King do { 248982b604bSRussell King value = ctl; 249982b604bSRussell King ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 250982b604bSRussell King if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)) 251982b604bSRussell King break; 252982b604bSRussell King udelay(1); 253982b604bSRussell King } while (timeout--); 254982b604bSRussell King 255982b604bSRussell King if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) 256982b604bSRussell King dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", 257982b604bSRussell King ctl); 258982b604bSRussell King } 259f9b95980Sapatard@mandriva.com 2604f6f1478SJean-Francois Moine switch (cmd) { 2614f6f1478SJean-Francois Moine case SNDRV_PCM_TRIGGER_START: 2624f6f1478SJean-Francois Moine /* configure */ 2634f6f1478SJean-Francois Moine ctl = priv->ctl_play; 26475b9b65eSJean-Francois Moine if (dai->id == 0) 26575b9b65eSJean-Francois Moine ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ 26675b9b65eSJean-Francois Moine else 26775b9b65eSJean-Francois Moine ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ 2682fbc3821SRussell King ctl = kirkwood_i2s_play_mute(ctl); 269db43b16fSRussell King value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 270d8d11ba5SRussell King writel(value, priv->io + KIRKWOOD_PLAYCTL); 271d8d11ba5SRussell King 272d8d11ba5SRussell King /* enable interrupts */ 273920ec4e5SRussell King if (!runtime->no_period_wakeup) { 274f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_INT_MASK); 275f9b95980Sapatard@mandriva.com value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; 276f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_INT_MASK); 277920ec4e5SRussell King } 278f9b95980Sapatard@mandriva.com 279d8d11ba5SRussell King /* enable playback */ 280982b604bSRussell King writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 281f9b95980Sapatard@mandriva.com break; 282f9b95980Sapatard@mandriva.com 283f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_STOP: 284f9b95980Sapatard@mandriva.com /* stop audio, disable interrupts */ 28575b9b65eSJean-Francois Moine ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 28675b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_SPDIF_MUTE; 287982b604bSRussell King writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 288f9b95980Sapatard@mandriva.com 289f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_INT_MASK); 290f9b95980Sapatard@mandriva.com value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; 291f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_INT_MASK); 292f9b95980Sapatard@mandriva.com 293f9b95980Sapatard@mandriva.com /* disable all playbacks */ 294db43b16fSRussell King ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 295982b604bSRussell King writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 296f9b95980Sapatard@mandriva.com break; 297f9b95980Sapatard@mandriva.com 298f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 299f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_SUSPEND: 30075b9b65eSJean-Francois Moine ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 30175b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_SPDIF_MUTE; 302982b604bSRussell King writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 303f9b95980Sapatard@mandriva.com break; 304f9b95980Sapatard@mandriva.com 305f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_RESUME: 306f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 30775b9b65eSJean-Francois Moine ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 30875b9b65eSJean-Francois Moine KIRKWOOD_PLAYCTL_SPDIF_MUTE); 3092fbc3821SRussell King ctl = kirkwood_i2s_play_mute(ctl); 310982b604bSRussell King writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 311f9b95980Sapatard@mandriva.com break; 312f9b95980Sapatard@mandriva.com 313f9b95980Sapatard@mandriva.com default: 314f9b95980Sapatard@mandriva.com return -EINVAL; 315f9b95980Sapatard@mandriva.com } 316f9b95980Sapatard@mandriva.com 317f9b95980Sapatard@mandriva.com return 0; 318f9b95980Sapatard@mandriva.com } 319f9b95980Sapatard@mandriva.com 320f9b95980Sapatard@mandriva.com static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 321f9b95980Sapatard@mandriva.com int cmd, struct snd_soc_dai *dai) 322f9b95980Sapatard@mandriva.com { 323f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 324d8d11ba5SRussell King uint32_t ctl, value; 325f9b95980Sapatard@mandriva.com 326f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_RECCTL); 327f9b95980Sapatard@mandriva.com 328f9b95980Sapatard@mandriva.com switch (cmd) { 329f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_START: 330d8d11ba5SRussell King /* configure */ 331d8d11ba5SRussell King ctl = priv->ctl_rec; 33275b9b65eSJean-Francois Moine if (dai->id == 0) 33375b9b65eSJean-Francois Moine ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN; /* i2s */ 33475b9b65eSJean-Francois Moine else 33575b9b65eSJean-Francois Moine ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ 33675b9b65eSJean-Francois Moine 33752b896cfSRussell King value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK; 338d8d11ba5SRussell King writel(value, priv->io + KIRKWOOD_RECCTL); 339d8d11ba5SRussell King 340d8d11ba5SRussell King /* enable interrupts */ 341f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_INT_MASK); 342f9b95980Sapatard@mandriva.com value |= KIRKWOOD_INT_CAUSE_REC_BYTES; 343f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_INT_MASK); 344f9b95980Sapatard@mandriva.com 345d8d11ba5SRussell King /* enable record */ 346d8d11ba5SRussell King writel(ctl, priv->io + KIRKWOOD_RECCTL); 347f9b95980Sapatard@mandriva.com break; 348f9b95980Sapatard@mandriva.com 349f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_STOP: 350f9b95980Sapatard@mandriva.com /* stop audio, disable interrupts */ 351f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_RECCTL); 352b424ec95Sarnaud.patard@rtp-net.org value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 353f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_RECCTL); 354f9b95980Sapatard@mandriva.com 355f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_INT_MASK); 356f9b95980Sapatard@mandriva.com value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES; 357f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_INT_MASK); 358f9b95980Sapatard@mandriva.com 359f9b95980Sapatard@mandriva.com /* disable all records */ 360f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_RECCTL); 36152b896cfSRussell King value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; 362f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_RECCTL); 363f9b95980Sapatard@mandriva.com break; 364f9b95980Sapatard@mandriva.com 365f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 366f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_SUSPEND: 367f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_RECCTL); 368b424ec95Sarnaud.patard@rtp-net.org value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 369f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_RECCTL); 370f9b95980Sapatard@mandriva.com break; 371f9b95980Sapatard@mandriva.com 372f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_RESUME: 373f9b95980Sapatard@mandriva.com case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 374f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_RECCTL); 375b424ec95Sarnaud.patard@rtp-net.org value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE); 376f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_RECCTL); 377f9b95980Sapatard@mandriva.com break; 378f9b95980Sapatard@mandriva.com 379f9b95980Sapatard@mandriva.com default: 380f9b95980Sapatard@mandriva.com return -EINVAL; 381f9b95980Sapatard@mandriva.com } 382f9b95980Sapatard@mandriva.com 383f9b95980Sapatard@mandriva.com return 0; 384f9b95980Sapatard@mandriva.com } 385f9b95980Sapatard@mandriva.com 386f9b95980Sapatard@mandriva.com static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 387f9b95980Sapatard@mandriva.com struct snd_soc_dai *dai) 388f9b95980Sapatard@mandriva.com { 389f9b95980Sapatard@mandriva.com if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 390f9b95980Sapatard@mandriva.com return kirkwood_i2s_play_trigger(substream, cmd, dai); 391f9b95980Sapatard@mandriva.com else 392f9b95980Sapatard@mandriva.com return kirkwood_i2s_rec_trigger(substream, cmd, dai); 393f9b95980Sapatard@mandriva.com 394f9b95980Sapatard@mandriva.com return 0; 395f9b95980Sapatard@mandriva.com } 396f9b95980Sapatard@mandriva.com 39775b9b65eSJean-Francois Moine static int kirkwood_i2s_init(struct kirkwood_dma_data *priv) 398f9b95980Sapatard@mandriva.com { 399f9b95980Sapatard@mandriva.com unsigned long value; 400f9b95980Sapatard@mandriva.com unsigned int reg_data; 401f9b95980Sapatard@mandriva.com 402f9b95980Sapatard@mandriva.com /* put system in a "safe" state : */ 403f9b95980Sapatard@mandriva.com /* disable audio interrupts */ 404f9b95980Sapatard@mandriva.com writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE); 405f9b95980Sapatard@mandriva.com writel(0, priv->io + KIRKWOOD_INT_MASK); 406f9b95980Sapatard@mandriva.com 407f9b95980Sapatard@mandriva.com reg_data = readl(priv->io + 0x1200); 408f9b95980Sapatard@mandriva.com reg_data &= (~(0x333FF8)); 409f9b95980Sapatard@mandriva.com reg_data |= 0x111D18; 410f9b95980Sapatard@mandriva.com writel(reg_data, priv->io + 0x1200); 411f9b95980Sapatard@mandriva.com 412f9b95980Sapatard@mandriva.com msleep(500); 413f9b95980Sapatard@mandriva.com 414f9b95980Sapatard@mandriva.com reg_data = readl(priv->io + 0x1200); 415f9b95980Sapatard@mandriva.com reg_data &= (~(0x333FF8)); 416f9b95980Sapatard@mandriva.com reg_data |= 0x111D18; 417f9b95980Sapatard@mandriva.com writel(reg_data, priv->io + 0x1200); 418f9b95980Sapatard@mandriva.com 419f9b95980Sapatard@mandriva.com /* disable playback/record */ 420f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_PLAYCTL); 421db43b16fSRussell King value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 422f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_PLAYCTL); 423f9b95980Sapatard@mandriva.com 424f9b95980Sapatard@mandriva.com value = readl(priv->io + KIRKWOOD_RECCTL); 42552b896cfSRussell King value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; 426f9b95980Sapatard@mandriva.com writel(value, priv->io + KIRKWOOD_RECCTL); 427f9b95980Sapatard@mandriva.com 428f9b95980Sapatard@mandriva.com return 0; 429f9b95980Sapatard@mandriva.com 430f9b95980Sapatard@mandriva.com } 431f9b95980Sapatard@mandriva.com 43285e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 433f0fba2adSLiam Girdwood .startup = kirkwood_i2s_startup, 434f9b95980Sapatard@mandriva.com .trigger = kirkwood_i2s_trigger, 435f9b95980Sapatard@mandriva.com .hw_params = kirkwood_i2s_hw_params, 436f9b95980Sapatard@mandriva.com .set_fmt = kirkwood_i2s_set_fmt, 437f9b95980Sapatard@mandriva.com }; 438f9b95980Sapatard@mandriva.com 43975b9b65eSJean-Francois Moine static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = { 44075b9b65eSJean-Francois Moine { 44175b9b65eSJean-Francois Moine .name = "i2s", 44275b9b65eSJean-Francois Moine .id = 0, 443f9b95980Sapatard@mandriva.com .playback = { 444f9b95980Sapatard@mandriva.com .channels_min = 1, 445f9b95980Sapatard@mandriva.com .channels_max = 2, 4469e12cbd9SMark Brown .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 4479e12cbd9SMark Brown SNDRV_PCM_RATE_96000, 448363589bfSRussell King .formats = KIRKWOOD_I2S_FORMATS, 449363589bfSRussell King }, 450f9b95980Sapatard@mandriva.com .capture = { 451f9b95980Sapatard@mandriva.com .channels_min = 1, 452f9b95980Sapatard@mandriva.com .channels_max = 2, 4539e12cbd9SMark Brown .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 4549e12cbd9SMark Brown SNDRV_PCM_RATE_96000, 455363589bfSRussell King .formats = KIRKWOOD_I2S_FORMATS, 456363589bfSRussell King }, 457363589bfSRussell King .ops = &kirkwood_i2s_dai_ops, 45875b9b65eSJean-Francois Moine }, 45975b9b65eSJean-Francois Moine { 46075b9b65eSJean-Francois Moine .name = "spdif", 46175b9b65eSJean-Francois Moine .id = 1, 46275b9b65eSJean-Francois Moine .playback = { 46375b9b65eSJean-Francois Moine .channels_min = 1, 46475b9b65eSJean-Francois Moine .channels_max = 2, 46575b9b65eSJean-Francois Moine .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 46675b9b65eSJean-Francois Moine SNDRV_PCM_RATE_96000, 4671c195ddbSJean-Francois Moine .formats = KIRKWOOD_SPDIF_FORMATS, 46875b9b65eSJean-Francois Moine }, 46975b9b65eSJean-Francois Moine .capture = { 47075b9b65eSJean-Francois Moine .channels_min = 1, 47175b9b65eSJean-Francois Moine .channels_max = 2, 47275b9b65eSJean-Francois Moine .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 47375b9b65eSJean-Francois Moine SNDRV_PCM_RATE_96000, 4741c195ddbSJean-Francois Moine .formats = KIRKWOOD_SPDIF_FORMATS, 47575b9b65eSJean-Francois Moine }, 47675b9b65eSJean-Francois Moine .ops = &kirkwood_i2s_dai_ops, 47775b9b65eSJean-Francois Moine }, 478363589bfSRussell King }; 479363589bfSRussell King 48075b9b65eSJean-Francois Moine static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = { 48175b9b65eSJean-Francois Moine { 48275b9b65eSJean-Francois Moine .name = "i2s", 48375b9b65eSJean-Francois Moine .id = 0, 484363589bfSRussell King .playback = { 485363589bfSRussell King .channels_min = 1, 486363589bfSRussell King .channels_max = 2, 48702fc17c1SJean-Francois Moine .rates = SNDRV_PCM_RATE_CONTINUOUS, 48802fc17c1SJean-Francois Moine .rate_min = 5512, 48902fc17c1SJean-Francois Moine .rate_max = 192000, 490363589bfSRussell King .formats = KIRKWOOD_I2S_FORMATS, 491363589bfSRussell King }, 492363589bfSRussell King .capture = { 493363589bfSRussell King .channels_min = 1, 494363589bfSRussell King .channels_max = 2, 49502fc17c1SJean-Francois Moine .rates = SNDRV_PCM_RATE_CONTINUOUS, 49602fc17c1SJean-Francois Moine .rate_min = 5512, 49702fc17c1SJean-Francois Moine .rate_max = 192000, 498363589bfSRussell King .formats = KIRKWOOD_I2S_FORMATS, 499363589bfSRussell King }, 500f9b95980Sapatard@mandriva.com .ops = &kirkwood_i2s_dai_ops, 50175b9b65eSJean-Francois Moine }, 50275b9b65eSJean-Francois Moine { 50375b9b65eSJean-Francois Moine .name = "spdif", 50475b9b65eSJean-Francois Moine .id = 1, 50575b9b65eSJean-Francois Moine .playback = { 50675b9b65eSJean-Francois Moine .channels_min = 1, 50775b9b65eSJean-Francois Moine .channels_max = 2, 50802fc17c1SJean-Francois Moine .rates = SNDRV_PCM_RATE_CONTINUOUS, 50902fc17c1SJean-Francois Moine .rate_min = 5512, 51002fc17c1SJean-Francois Moine .rate_max = 192000, 5111c195ddbSJean-Francois Moine .formats = KIRKWOOD_SPDIF_FORMATS, 51275b9b65eSJean-Francois Moine }, 51375b9b65eSJean-Francois Moine .capture = { 51475b9b65eSJean-Francois Moine .channels_min = 1, 51575b9b65eSJean-Francois Moine .channels_max = 2, 51602fc17c1SJean-Francois Moine .rates = SNDRV_PCM_RATE_CONTINUOUS, 51702fc17c1SJean-Francois Moine .rate_min = 5512, 51802fc17c1SJean-Francois Moine .rate_max = 192000, 5191c195ddbSJean-Francois Moine .formats = KIRKWOOD_SPDIF_FORMATS, 52075b9b65eSJean-Francois Moine }, 52175b9b65eSJean-Francois Moine .ops = &kirkwood_i2s_dai_ops, 52275b9b65eSJean-Francois Moine }, 523f9b95980Sapatard@mandriva.com }; 524f9b95980Sapatard@mandriva.com 52534e15fbdSBill Pemberton static int kirkwood_i2s_dev_probe(struct platform_device *pdev) 526f9b95980Sapatard@mandriva.com { 527363589bfSRussell King struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; 52875b9b65eSJean-Francois Moine struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai; 529f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv; 530363589bfSRussell King struct resource *mem; 531eb632318SJean-Francois Moine struct device_node *np = pdev->dev.of_node; 532f9b95980Sapatard@mandriva.com int err; 533f9b95980Sapatard@mandriva.com 534dbc517bfSRussell King priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 535c7591edcSMarkus Elfring if (!priv) 536dbc517bfSRussell King return -ENOMEM; 537c7591edcSMarkus Elfring 538f0fba2adSLiam Girdwood dev_set_drvdata(&pdev->dev, priv); 539f9b95980Sapatard@mandriva.com 540f9b95980Sapatard@mandriva.com mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 541b25b5aa0SThierry Reding priv->io = devm_ioremap_resource(&pdev->dev, mem); 542b25b5aa0SThierry Reding if (IS_ERR(priv->io)) 543b25b5aa0SThierry Reding return PTR_ERR(priv->io); 544f9b95980Sapatard@mandriva.com 545f9b95980Sapatard@mandriva.com priv->irq = platform_get_irq(pdev, 0); 546e7b2e30aSGustavo A. R. Silva if (priv->irq < 0) { 547e7b2e30aSGustavo A. R. Silva dev_err(&pdev->dev, "platform_get_irq failed: %d\n", priv->irq); 548e7b2e30aSGustavo A. R. Silva return priv->irq; 549f9b95980Sapatard@mandriva.com } 550f9b95980Sapatard@mandriva.com 551eb632318SJean-Francois Moine if (np) { 552eb632318SJean-Francois Moine priv->burst = 128; /* might be 32 or 128 */ 553eb632318SJean-Francois Moine } else if (data) { 554eb632318SJean-Francois Moine priv->burst = data->burst; 555eb632318SJean-Francois Moine } else { 556eb632318SJean-Francois Moine dev_err(&pdev->dev, "no DT nor platform data ?!\n"); 557dbc517bfSRussell King return -EINVAL; 558f9b95980Sapatard@mandriva.com } 559f9b95980Sapatard@mandriva.com 560eb632318SJean-Francois Moine priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL); 561e919c716SAndrew Lunn if (IS_ERR(priv->clk)) { 562e919c716SAndrew Lunn dev_err(&pdev->dev, "no clock\n"); 563dbc517bfSRussell King return PTR_ERR(priv->clk); 564e919c716SAndrew Lunn } 565dbc517bfSRussell King 566dbc517bfSRussell King err = clk_prepare_enable(priv->clk); 567dbc517bfSRussell King if (err < 0) 568dbc517bfSRussell King return err; 569e919c716SAndrew Lunn 5704734dc96SMark Brown priv->extclk = devm_clk_get(&pdev->dev, "extclk"); 57184aac6c7SJean-Francois Moine if (IS_ERR(priv->extclk)) { 57284aac6c7SJean-Francois Moine if (PTR_ERR(priv->extclk) == -EPROBE_DEFER) 57384aac6c7SJean-Francois Moine return -EPROBE_DEFER; 57484aac6c7SJean-Francois Moine } else { 575aaa6d062SShawn Guo if (clk_is_match(priv->extclk, priv->clk)) { 576af64d734SRussell King devm_clk_put(&pdev->dev, priv->extclk); 577d8d11ba5SRussell King priv->extclk = ERR_PTR(-EINVAL); 578d8d11ba5SRussell King } else { 579d8d11ba5SRussell King dev_info(&pdev->dev, "found external clock\n"); 580d8d11ba5SRussell King clk_prepare_enable(priv->extclk); 58199d8d3baSJean-Francois Moine soc_dai = kirkwood_i2s_dai_extclk; 582d8d11ba5SRussell King } 583d8d11ba5SRussell King } 584d8d11ba5SRussell King 585d8d11ba5SRussell King /* Some sensible defaults - this reflects the powerup values */ 586d8d11ba5SRussell King priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; 587d8d11ba5SRussell King priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; 588d8d11ba5SRussell King 589d8d11ba5SRussell King /* Select the burst size */ 590eb632318SJean-Francois Moine if (priv->burst == 32) { 591d8d11ba5SRussell King priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; 592d8d11ba5SRussell King priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; 593d8d11ba5SRussell King } else { 594d8d11ba5SRussell King priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; 595d8d11ba5SRussell King priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 596d8d11ba5SRussell King } 597d8d11ba5SRussell King 598*f98fc0f8SKuninori Morimoto err = devm_snd_soc_register_component(&pdev->dev, &kirkwood_soc_component, 59975b9b65eSJean-Francois Moine soc_dai, 2); 60064ddf1f8SRussell King if (err) { 60183d85f53SKuninori Morimoto dev_err(&pdev->dev, "snd_soc_register_component failed\n"); 60264ddf1f8SRussell King goto err_component; 60364ddf1f8SRussell King } 604baffab28SSimon Baatz 60575b9b65eSJean-Francois Moine kirkwood_i2s_init(priv); 60675b9b65eSJean-Francois Moine 60764ddf1f8SRussell King return 0; 608*f98fc0f8SKuninori Morimoto 60964ddf1f8SRussell King err_component: 6104734dc96SMark Brown if (!IS_ERR(priv->extclk)) 611363589bfSRussell King clk_disable_unprepare(priv->extclk); 612baffab28SSimon Baatz clk_disable_unprepare(priv->clk); 613f9b95980Sapatard@mandriva.com 614f9b95980Sapatard@mandriva.com return err; 615f9b95980Sapatard@mandriva.com } 616f9b95980Sapatard@mandriva.com 61734e15fbdSBill Pemberton static int kirkwood_i2s_dev_remove(struct platform_device *pdev) 618f9b95980Sapatard@mandriva.com { 619f0fba2adSLiam Girdwood struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 620f0fba2adSLiam Girdwood 6214734dc96SMark Brown if (!IS_ERR(priv->extclk)) 622363589bfSRussell King clk_disable_unprepare(priv->extclk); 623e919c716SAndrew Lunn clk_disable_unprepare(priv->clk); 624f0fba2adSLiam Girdwood 625f9b95980Sapatard@mandriva.com return 0; 626f9b95980Sapatard@mandriva.com } 627f9b95980Sapatard@mandriva.com 628eb632318SJean-Francois Moine #ifdef CONFIG_OF 6297f2c52afSFabian Frederick static const struct of_device_id mvebu_audio_of_match[] = { 630d098b2f0SThomas Petazzoni { .compatible = "marvell,kirkwood-audio" }, 631d098b2f0SThomas Petazzoni { .compatible = "marvell,dove-audio" }, 6329a0d5113SThomas Petazzoni { .compatible = "marvell,armada370-audio" }, 633eb632318SJean-Francois Moine { } 634eb632318SJean-Francois Moine }; 635eb632318SJean-Francois Moine MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); 636eb632318SJean-Francois Moine #endif 637eb632318SJean-Francois Moine 638f9b95980Sapatard@mandriva.com static struct platform_driver kirkwood_i2s_driver = { 639f9b95980Sapatard@mandriva.com .probe = kirkwood_i2s_dev_probe, 64034e15fbdSBill Pemberton .remove = kirkwood_i2s_dev_remove, 641f9b95980Sapatard@mandriva.com .driver = { 642f9b95980Sapatard@mandriva.com .name = DRV_NAME, 643eb632318SJean-Francois Moine .of_match_table = of_match_ptr(mvebu_audio_of_match), 644f9b95980Sapatard@mandriva.com }, 645f9b95980Sapatard@mandriva.com }; 646f9b95980Sapatard@mandriva.com 64741b10225SAxel Lin module_platform_driver(kirkwood_i2s_driver); 648f9b95980Sapatard@mandriva.com 649f9b95980Sapatard@mandriva.com /* Module information */ 65069737897SArnaud Patard (Rtp) MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); 651f9b95980Sapatard@mandriva.com MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 652f9b95980Sapatard@mandriva.com MODULE_LICENSE("GPL"); 65364ddf1f8SRussell King MODULE_ALIAS("platform:mvebu-audio"); 654