xref: /linux/sound/soc/kirkwood/kirkwood-i2s.c (revision 2874c5fd284268364ece81a7bd936f3c8168e567)
1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f9b95980Sapatard@mandriva.com /*
3f9b95980Sapatard@mandriva.com  * kirkwood-i2s.c
4f9b95980Sapatard@mandriva.com  *
5f9b95980Sapatard@mandriva.com  * (c) 2010 Arnaud Patard <apatard@mandriva.com>
669737897SArnaud Patard (Rtp)  * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
7f9b95980Sapatard@mandriva.com  */
8f9b95980Sapatard@mandriva.com 
9f9b95980Sapatard@mandriva.com #include <linux/init.h>
10f9b95980Sapatard@mandriva.com #include <linux/module.h>
11f9b95980Sapatard@mandriva.com #include <linux/platform_device.h>
12f9b95980Sapatard@mandriva.com #include <linux/io.h>
13f9b95980Sapatard@mandriva.com #include <linux/slab.h>
14f9b95980Sapatard@mandriva.com #include <linux/mbus.h>
15f9b95980Sapatard@mandriva.com #include <linux/delay.h>
16e919c716SAndrew Lunn #include <linux/clk.h>
17f9b95980Sapatard@mandriva.com #include <sound/pcm.h>
18f9b95980Sapatard@mandriva.com #include <sound/pcm_params.h>
19f9b95980Sapatard@mandriva.com #include <sound/soc.h>
20c02cecb9SArnd Bergmann #include <linux/platform_data/asoc-kirkwood.h>
21eb632318SJean-Francois Moine #include <linux/of.h>
22eb632318SJean-Francois Moine 
23f9b95980Sapatard@mandriva.com #include "kirkwood.h"
24f9b95980Sapatard@mandriva.com 
25f9b95980Sapatard@mandriva.com #define KIRKWOOD_I2S_FORMATS \
26f9b95980Sapatard@mandriva.com 	(SNDRV_PCM_FMTBIT_S16_LE | \
27f9b95980Sapatard@mandriva.com 	 SNDRV_PCM_FMTBIT_S24_LE | \
28f9b95980Sapatard@mandriva.com 	 SNDRV_PCM_FMTBIT_S32_LE)
29f9b95980Sapatard@mandriva.com 
301c195ddbSJean-Francois Moine #define KIRKWOOD_SPDIF_FORMATS \
311c195ddbSJean-Francois Moine 	(SNDRV_PCM_FMTBIT_S16_LE | \
321c195ddbSJean-Francois Moine 	 SNDRV_PCM_FMTBIT_S24_LE)
331c195ddbSJean-Francois Moine 
34f9b95980Sapatard@mandriva.com static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
35f9b95980Sapatard@mandriva.com 		unsigned int fmt)
36f9b95980Sapatard@mandriva.com {
37f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
38f9b95980Sapatard@mandriva.com 	unsigned long mask;
39f9b95980Sapatard@mandriva.com 	unsigned long value;
40f9b95980Sapatard@mandriva.com 
41f9b95980Sapatard@mandriva.com 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
42f9b95980Sapatard@mandriva.com 	case SND_SOC_DAIFMT_RIGHT_J:
43f9b95980Sapatard@mandriva.com 		mask = KIRKWOOD_I2S_CTL_RJ;
44f9b95980Sapatard@mandriva.com 		break;
45f9b95980Sapatard@mandriva.com 	case SND_SOC_DAIFMT_LEFT_J:
46f9b95980Sapatard@mandriva.com 		mask = KIRKWOOD_I2S_CTL_LJ;
47f9b95980Sapatard@mandriva.com 		break;
48f9b95980Sapatard@mandriva.com 	case SND_SOC_DAIFMT_I2S:
49f9b95980Sapatard@mandriva.com 		mask = KIRKWOOD_I2S_CTL_I2S;
50f9b95980Sapatard@mandriva.com 		break;
51f9b95980Sapatard@mandriva.com 	default:
52f9b95980Sapatard@mandriva.com 		return -EINVAL;
53f9b95980Sapatard@mandriva.com 	}
54f9b95980Sapatard@mandriva.com 
55f9b95980Sapatard@mandriva.com 	/*
56f9b95980Sapatard@mandriva.com 	 * Set same format for playback and record
57f9b95980Sapatard@mandriva.com 	 * This avoids some troubles.
58f9b95980Sapatard@mandriva.com 	 */
59f9b95980Sapatard@mandriva.com 	value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
60f9b95980Sapatard@mandriva.com 	value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
61f9b95980Sapatard@mandriva.com 	value |= mask;
62f9b95980Sapatard@mandriva.com 	writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
63f9b95980Sapatard@mandriva.com 
64f9b95980Sapatard@mandriva.com 	value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
65f9b95980Sapatard@mandriva.com 	value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
66f9b95980Sapatard@mandriva.com 	value |= mask;
67f9b95980Sapatard@mandriva.com 	writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
68f9b95980Sapatard@mandriva.com 
69f9b95980Sapatard@mandriva.com 	return 0;
70f9b95980Sapatard@mandriva.com }
71f9b95980Sapatard@mandriva.com 
72f9b95980Sapatard@mandriva.com static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
73f9b95980Sapatard@mandriva.com {
74f9b95980Sapatard@mandriva.com 	unsigned long value;
75f9b95980Sapatard@mandriva.com 
76f9b95980Sapatard@mandriva.com 	value = KIRKWOOD_DCO_CTL_OFFSET_0;
77f9b95980Sapatard@mandriva.com 	switch (rate) {
78f9b95980Sapatard@mandriva.com 	default:
79f9b95980Sapatard@mandriva.com 	case 44100:
80f9b95980Sapatard@mandriva.com 		value |= KIRKWOOD_DCO_CTL_FREQ_11;
81f9b95980Sapatard@mandriva.com 		break;
82f9b95980Sapatard@mandriva.com 	case 48000:
83f9b95980Sapatard@mandriva.com 		value |= KIRKWOOD_DCO_CTL_FREQ_12;
84f9b95980Sapatard@mandriva.com 		break;
85f9b95980Sapatard@mandriva.com 	case 96000:
86f9b95980Sapatard@mandriva.com 		value |= KIRKWOOD_DCO_CTL_FREQ_24;
87f9b95980Sapatard@mandriva.com 		break;
88f9b95980Sapatard@mandriva.com 	}
89f9b95980Sapatard@mandriva.com 	writel(value, io + KIRKWOOD_DCO_CTL);
90f9b95980Sapatard@mandriva.com 
91f9b95980Sapatard@mandriva.com 	/* wait for dco locked */
92f9b95980Sapatard@mandriva.com 	do {
93f9b95980Sapatard@mandriva.com 		cpu_relax();
94f9b95980Sapatard@mandriva.com 		value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
952424d458SRussell King 		value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
96f9b95980Sapatard@mandriva.com 	} while (value == 0);
97f9b95980Sapatard@mandriva.com }
98f9b95980Sapatard@mandriva.com 
99363589bfSRussell King static void kirkwood_set_rate(struct snd_soc_dai *dai,
100363589bfSRussell King 	struct kirkwood_dma_data *priv, unsigned long rate)
101363589bfSRussell King {
102363589bfSRussell King 	uint32_t clks_ctrl;
103363589bfSRussell King 
1041f1b6579SJean-Francois Moine 	if (IS_ERR(priv->extclk)) {
1058a537f85SJean-Francois Moine 		/* use internal dco for the supported rates
1068a537f85SJean-Francois Moine 		 * defined in kirkwood_i2s_dai */
107363589bfSRussell King 		dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
108363589bfSRussell King 			__func__, rate);
109363589bfSRussell King 		kirkwood_set_dco(priv->io, rate);
110363589bfSRussell King 
111363589bfSRussell King 		clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
1128a537f85SJean-Francois Moine 	} else {
1138a537f85SJean-Francois Moine 		/* use the external clock for the other rates
1148a537f85SJean-Francois Moine 		 * defined in kirkwood_i2s_dai_extclk */
115363589bfSRussell King 		dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
116363589bfSRussell King 			__func__, rate, 256 * rate);
117363589bfSRussell King 		clk_set_rate(priv->extclk, 256 * rate);
118363589bfSRussell King 
119363589bfSRussell King 		clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
120363589bfSRussell King 	}
121363589bfSRussell King 	writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
122363589bfSRussell King }
123363589bfSRussell King 
124f0fba2adSLiam Girdwood static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
125f0fba2adSLiam Girdwood 		struct snd_soc_dai *dai)
126f0fba2adSLiam Girdwood {
127f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
128f0fba2adSLiam Girdwood 
129f0fba2adSLiam Girdwood 	snd_soc_dai_set_dma_data(dai, substream, priv);
130f0fba2adSLiam Girdwood 	return 0;
131f0fba2adSLiam Girdwood }
132f0fba2adSLiam Girdwood 
133f9b95980Sapatard@mandriva.com static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
134f9b95980Sapatard@mandriva.com 				 struct snd_pcm_hw_params *params,
135f9b95980Sapatard@mandriva.com 				 struct snd_soc_dai *dai)
136f9b95980Sapatard@mandriva.com {
137f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
138d8d11ba5SRussell King 	uint32_t ctl_play, ctl_rec;
139d8d11ba5SRussell King 	unsigned int i2s_reg;
140d8d11ba5SRussell King 	unsigned long i2s_value;
141f9b95980Sapatard@mandriva.com 
142f9b95980Sapatard@mandriva.com 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
143f9b95980Sapatard@mandriva.com 		i2s_reg = KIRKWOOD_I2S_PLAYCTL;
144f9b95980Sapatard@mandriva.com 	} else {
145f9b95980Sapatard@mandriva.com 		i2s_reg = KIRKWOOD_I2S_RECCTL;
146f9b95980Sapatard@mandriva.com 	}
147f9b95980Sapatard@mandriva.com 
148363589bfSRussell King 	kirkwood_set_rate(dai, priv, params_rate(params));
149f9b95980Sapatard@mandriva.com 
150f9b95980Sapatard@mandriva.com 	i2s_value = readl(priv->io+i2s_reg);
151f9b95980Sapatard@mandriva.com 	i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
152f9b95980Sapatard@mandriva.com 
153f9b95980Sapatard@mandriva.com 	/*
154f9b95980Sapatard@mandriva.com 	 * Size settings in play/rec i2s control regs and play/rec control
155f9b95980Sapatard@mandriva.com 	 * regs must be the same.
156f9b95980Sapatard@mandriva.com 	 */
157f9b95980Sapatard@mandriva.com 	switch (params_format(params)) {
158f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_FORMAT_S16_LE:
159f9b95980Sapatard@mandriva.com 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
160d8d11ba5SRussell King 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
16175b9b65eSJean-Francois Moine 			   KIRKWOOD_PLAYCTL_I2S_EN |
16275b9b65eSJean-Francois Moine 			   KIRKWOOD_PLAYCTL_SPDIF_EN;
163d8d11ba5SRussell King 		ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
16475b9b65eSJean-Francois Moine 			  KIRKWOOD_RECCTL_I2S_EN |
16575b9b65eSJean-Francois Moine 			  KIRKWOOD_RECCTL_SPDIF_EN;
166f9b95980Sapatard@mandriva.com 		break;
167f9b95980Sapatard@mandriva.com 	/*
168f9b95980Sapatard@mandriva.com 	 * doesn't work... S20_3LE != kirkwood 20bit format ?
169f9b95980Sapatard@mandriva.com 	 *
170f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_FORMAT_S20_3LE:
171f9b95980Sapatard@mandriva.com 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
172d8d11ba5SRussell King 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
173d8d11ba5SRussell King 			   KIRKWOOD_PLAYCTL_I2S_EN;
174d8d11ba5SRussell King 		ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
175d8d11ba5SRussell King 			  KIRKWOOD_RECCTL_I2S_EN;
176f9b95980Sapatard@mandriva.com 		break;
177f9b95980Sapatard@mandriva.com 	*/
178f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_FORMAT_S24_LE:
179f9b95980Sapatard@mandriva.com 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
180d8d11ba5SRussell King 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
18175b9b65eSJean-Francois Moine 			   KIRKWOOD_PLAYCTL_I2S_EN |
18275b9b65eSJean-Francois Moine 			   KIRKWOOD_PLAYCTL_SPDIF_EN;
183d8d11ba5SRussell King 		ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
18475b9b65eSJean-Francois Moine 			  KIRKWOOD_RECCTL_I2S_EN |
18575b9b65eSJean-Francois Moine 			  KIRKWOOD_RECCTL_SPDIF_EN;
186f9b95980Sapatard@mandriva.com 		break;
187f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_FORMAT_S32_LE:
188f9b95980Sapatard@mandriva.com 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
189d8d11ba5SRussell King 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
190d8d11ba5SRussell King 			   KIRKWOOD_PLAYCTL_I2S_EN;
191d8d11ba5SRussell King 		ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
192d8d11ba5SRussell King 			  KIRKWOOD_RECCTL_I2S_EN;
193f9b95980Sapatard@mandriva.com 		break;
194f9b95980Sapatard@mandriva.com 	default:
195f9b95980Sapatard@mandriva.com 		return -EINVAL;
196f9b95980Sapatard@mandriva.com 	}
197dfe4c936Sarnaud.patard@rtp-net.org 
198dfe4c936Sarnaud.patard@rtp-net.org 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
199dfe4c936Sarnaud.patard@rtp-net.org 		if (params_channels(params) == 1)
200d8d11ba5SRussell King 			ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
201dfe4c936Sarnaud.patard@rtp-net.org 		else
202d8d11ba5SRussell King 			ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
203d8d11ba5SRussell King 
204d8d11ba5SRussell King 		priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
205db43b16fSRussell King 				    KIRKWOOD_PLAYCTL_ENABLE_MASK |
206d8d11ba5SRussell King 				    KIRKWOOD_PLAYCTL_SIZE_MASK);
207d8d11ba5SRussell King 		priv->ctl_play |= ctl_play;
208d8d11ba5SRussell King 	} else {
20967721906SRussell King 		priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
21067721906SRussell King 				   KIRKWOOD_RECCTL_SIZE_MASK);
211d8d11ba5SRussell King 		priv->ctl_rec |= ctl_rec;
212dfe4c936Sarnaud.patard@rtp-net.org 	}
213dfe4c936Sarnaud.patard@rtp-net.org 
214f9b95980Sapatard@mandriva.com 	writel(i2s_value, priv->io+i2s_reg);
215f9b95980Sapatard@mandriva.com 
216f9b95980Sapatard@mandriva.com 	return 0;
217f9b95980Sapatard@mandriva.com }
218f9b95980Sapatard@mandriva.com 
2192fbc3821SRussell King static unsigned kirkwood_i2s_play_mute(unsigned ctl)
2202fbc3821SRussell King {
2212fbc3821SRussell King 	if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
2222fbc3821SRussell King 		ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
2232fbc3821SRussell King 	if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
2242fbc3821SRussell King 		ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
2252fbc3821SRussell King 	return ctl;
2262fbc3821SRussell King }
2272fbc3821SRussell King 
228f9b95980Sapatard@mandriva.com static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
229f9b95980Sapatard@mandriva.com 				int cmd, struct snd_soc_dai *dai)
230f9b95980Sapatard@mandriva.com {
231920ec4e5SRussell King 	struct snd_pcm_runtime *runtime = substream->runtime;
232f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
233982b604bSRussell King 	uint32_t ctl, value;
234f9b95980Sapatard@mandriva.com 
235982b604bSRussell King 	ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
2364d2097e5SRussell King 	if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
237982b604bSRussell King 		unsigned timeout = 5000;
238f9b95980Sapatard@mandriva.com 		/*
239982b604bSRussell King 		 * The Armada510 spec says that if we enter pause mode, the
240982b604bSRussell King 		 * busy bit must be read back as clear _twice_.  Make sure
241982b604bSRussell King 		 * we respect that otherwise we get DMA underruns.
242f9b95980Sapatard@mandriva.com 		 */
243982b604bSRussell King 		do {
244982b604bSRussell King 			value = ctl;
245982b604bSRussell King 			ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
246982b604bSRussell King 			if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
247982b604bSRussell King 				break;
248982b604bSRussell King 			udelay(1);
249982b604bSRussell King 		} while (timeout--);
250982b604bSRussell King 
251982b604bSRussell King 		if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
252982b604bSRussell King 			dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
253982b604bSRussell King 				   ctl);
254982b604bSRussell King 	}
255f9b95980Sapatard@mandriva.com 
2564f6f1478SJean-Francois Moine 	switch (cmd) {
2574f6f1478SJean-Francois Moine 	case SNDRV_PCM_TRIGGER_START:
2584f6f1478SJean-Francois Moine 		/* configure */
2594f6f1478SJean-Francois Moine 		ctl = priv->ctl_play;
26075b9b65eSJean-Francois Moine 		if (dai->id == 0)
26175b9b65eSJean-Francois Moine 			ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;	/* i2s */
26275b9b65eSJean-Francois Moine 		else
26375b9b65eSJean-Francois Moine 			ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;	/* spdif */
2642fbc3821SRussell King 		ctl = kirkwood_i2s_play_mute(ctl);
265db43b16fSRussell King 		value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
266d8d11ba5SRussell King 		writel(value, priv->io + KIRKWOOD_PLAYCTL);
267d8d11ba5SRussell King 
268d8d11ba5SRussell King 		/* enable interrupts */
269920ec4e5SRussell King 		if (!runtime->no_period_wakeup) {
270f9b95980Sapatard@mandriva.com 			value = readl(priv->io + KIRKWOOD_INT_MASK);
271f9b95980Sapatard@mandriva.com 			value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
272f9b95980Sapatard@mandriva.com 			writel(value, priv->io + KIRKWOOD_INT_MASK);
273920ec4e5SRussell King 		}
274f9b95980Sapatard@mandriva.com 
275d8d11ba5SRussell King 		/* enable playback */
276982b604bSRussell King 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
277f9b95980Sapatard@mandriva.com 		break;
278f9b95980Sapatard@mandriva.com 
279f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_STOP:
280f9b95980Sapatard@mandriva.com 		/* stop audio, disable interrupts */
28175b9b65eSJean-Francois Moine 		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
28275b9b65eSJean-Francois Moine 				KIRKWOOD_PLAYCTL_SPDIF_MUTE;
283982b604bSRussell King 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
284f9b95980Sapatard@mandriva.com 
285f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_INT_MASK);
286f9b95980Sapatard@mandriva.com 		value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
287f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_INT_MASK);
288f9b95980Sapatard@mandriva.com 
289f9b95980Sapatard@mandriva.com 		/* disable all playbacks */
290db43b16fSRussell King 		ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
291982b604bSRussell King 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
292f9b95980Sapatard@mandriva.com 		break;
293f9b95980Sapatard@mandriva.com 
294f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
295f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_SUSPEND:
29675b9b65eSJean-Francois Moine 		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
29775b9b65eSJean-Francois Moine 				KIRKWOOD_PLAYCTL_SPDIF_MUTE;
298982b604bSRussell King 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
299f9b95980Sapatard@mandriva.com 		break;
300f9b95980Sapatard@mandriva.com 
301f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_RESUME:
302f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
30375b9b65eSJean-Francois Moine 		ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
30475b9b65eSJean-Francois Moine 				KIRKWOOD_PLAYCTL_SPDIF_MUTE);
3052fbc3821SRussell King 		ctl = kirkwood_i2s_play_mute(ctl);
306982b604bSRussell King 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
307f9b95980Sapatard@mandriva.com 		break;
308f9b95980Sapatard@mandriva.com 
309f9b95980Sapatard@mandriva.com 	default:
310f9b95980Sapatard@mandriva.com 		return -EINVAL;
311f9b95980Sapatard@mandriva.com 	}
312f9b95980Sapatard@mandriva.com 
313f9b95980Sapatard@mandriva.com 	return 0;
314f9b95980Sapatard@mandriva.com }
315f9b95980Sapatard@mandriva.com 
316f9b95980Sapatard@mandriva.com static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
317f9b95980Sapatard@mandriva.com 				int cmd, struct snd_soc_dai *dai)
318f9b95980Sapatard@mandriva.com {
319f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
320d8d11ba5SRussell King 	uint32_t ctl, value;
321f9b95980Sapatard@mandriva.com 
322f9b95980Sapatard@mandriva.com 	value = readl(priv->io + KIRKWOOD_RECCTL);
323f9b95980Sapatard@mandriva.com 
324f9b95980Sapatard@mandriva.com 	switch (cmd) {
325f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_START:
326d8d11ba5SRussell King 		/* configure */
327d8d11ba5SRussell King 		ctl = priv->ctl_rec;
32875b9b65eSJean-Francois Moine 		if (dai->id == 0)
32975b9b65eSJean-Francois Moine 			ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN;	/* i2s */
33075b9b65eSJean-Francois Moine 		else
33175b9b65eSJean-Francois Moine 			ctl &= ~KIRKWOOD_RECCTL_I2S_EN;		/* spdif */
33275b9b65eSJean-Francois Moine 
33352b896cfSRussell King 		value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
334d8d11ba5SRussell King 		writel(value, priv->io + KIRKWOOD_RECCTL);
335d8d11ba5SRussell King 
336d8d11ba5SRussell King 		/* enable interrupts */
337f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_INT_MASK);
338f9b95980Sapatard@mandriva.com 		value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
339f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_INT_MASK);
340f9b95980Sapatard@mandriva.com 
341d8d11ba5SRussell King 		/* enable record */
342d8d11ba5SRussell King 		writel(ctl, priv->io + KIRKWOOD_RECCTL);
343f9b95980Sapatard@mandriva.com 		break;
344f9b95980Sapatard@mandriva.com 
345f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_STOP:
346f9b95980Sapatard@mandriva.com 		/* stop audio, disable interrupts */
347f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_RECCTL);
348b424ec95Sarnaud.patard@rtp-net.org 		value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
349f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_RECCTL);
350f9b95980Sapatard@mandriva.com 
351f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_INT_MASK);
352f9b95980Sapatard@mandriva.com 		value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
353f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_INT_MASK);
354f9b95980Sapatard@mandriva.com 
355f9b95980Sapatard@mandriva.com 		/* disable all records */
356f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_RECCTL);
35752b896cfSRussell King 		value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
358f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_RECCTL);
359f9b95980Sapatard@mandriva.com 		break;
360f9b95980Sapatard@mandriva.com 
361f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
362f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_SUSPEND:
363f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_RECCTL);
364b424ec95Sarnaud.patard@rtp-net.org 		value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
365f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_RECCTL);
366f9b95980Sapatard@mandriva.com 		break;
367f9b95980Sapatard@mandriva.com 
368f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_RESUME:
369f9b95980Sapatard@mandriva.com 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
370f9b95980Sapatard@mandriva.com 		value = readl(priv->io + KIRKWOOD_RECCTL);
371b424ec95Sarnaud.patard@rtp-net.org 		value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
372f9b95980Sapatard@mandriva.com 		writel(value, priv->io + KIRKWOOD_RECCTL);
373f9b95980Sapatard@mandriva.com 		break;
374f9b95980Sapatard@mandriva.com 
375f9b95980Sapatard@mandriva.com 	default:
376f9b95980Sapatard@mandriva.com 		return -EINVAL;
377f9b95980Sapatard@mandriva.com 	}
378f9b95980Sapatard@mandriva.com 
379f9b95980Sapatard@mandriva.com 	return 0;
380f9b95980Sapatard@mandriva.com }
381f9b95980Sapatard@mandriva.com 
382f9b95980Sapatard@mandriva.com static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
383f9b95980Sapatard@mandriva.com 			       struct snd_soc_dai *dai)
384f9b95980Sapatard@mandriva.com {
385f9b95980Sapatard@mandriva.com 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
386f9b95980Sapatard@mandriva.com 		return kirkwood_i2s_play_trigger(substream, cmd, dai);
387f9b95980Sapatard@mandriva.com 	else
388f9b95980Sapatard@mandriva.com 		return kirkwood_i2s_rec_trigger(substream, cmd, dai);
389f9b95980Sapatard@mandriva.com 
390f9b95980Sapatard@mandriva.com 	return 0;
391f9b95980Sapatard@mandriva.com }
392f9b95980Sapatard@mandriva.com 
39375b9b65eSJean-Francois Moine static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
394f9b95980Sapatard@mandriva.com {
395f9b95980Sapatard@mandriva.com 	unsigned long value;
396f9b95980Sapatard@mandriva.com 	unsigned int reg_data;
397f9b95980Sapatard@mandriva.com 
398f9b95980Sapatard@mandriva.com 	/* put system in a "safe" state : */
399f9b95980Sapatard@mandriva.com 	/* disable audio interrupts */
400f9b95980Sapatard@mandriva.com 	writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
401f9b95980Sapatard@mandriva.com 	writel(0, priv->io + KIRKWOOD_INT_MASK);
402f9b95980Sapatard@mandriva.com 
403f9b95980Sapatard@mandriva.com 	reg_data = readl(priv->io + 0x1200);
404f9b95980Sapatard@mandriva.com 	reg_data &= (~(0x333FF8));
405f9b95980Sapatard@mandriva.com 	reg_data |= 0x111D18;
406f9b95980Sapatard@mandriva.com 	writel(reg_data, priv->io + 0x1200);
407f9b95980Sapatard@mandriva.com 
408f9b95980Sapatard@mandriva.com 	msleep(500);
409f9b95980Sapatard@mandriva.com 
410f9b95980Sapatard@mandriva.com 	reg_data = readl(priv->io + 0x1200);
411f9b95980Sapatard@mandriva.com 	reg_data &= (~(0x333FF8));
412f9b95980Sapatard@mandriva.com 	reg_data |= 0x111D18;
413f9b95980Sapatard@mandriva.com 	writel(reg_data, priv->io + 0x1200);
414f9b95980Sapatard@mandriva.com 
415f9b95980Sapatard@mandriva.com 	/* disable playback/record */
416f9b95980Sapatard@mandriva.com 	value = readl(priv->io + KIRKWOOD_PLAYCTL);
417db43b16fSRussell King 	value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
418f9b95980Sapatard@mandriva.com 	writel(value, priv->io + KIRKWOOD_PLAYCTL);
419f9b95980Sapatard@mandriva.com 
420f9b95980Sapatard@mandriva.com 	value = readl(priv->io + KIRKWOOD_RECCTL);
42152b896cfSRussell King 	value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
422f9b95980Sapatard@mandriva.com 	writel(value, priv->io + KIRKWOOD_RECCTL);
423f9b95980Sapatard@mandriva.com 
424f9b95980Sapatard@mandriva.com 	return 0;
425f9b95980Sapatard@mandriva.com 
426f9b95980Sapatard@mandriva.com }
427f9b95980Sapatard@mandriva.com 
42885e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
429f0fba2adSLiam Girdwood 	.startup	= kirkwood_i2s_startup,
430f9b95980Sapatard@mandriva.com 	.trigger	= kirkwood_i2s_trigger,
431f9b95980Sapatard@mandriva.com 	.hw_params      = kirkwood_i2s_hw_params,
432f9b95980Sapatard@mandriva.com 	.set_fmt        = kirkwood_i2s_set_fmt,
433f9b95980Sapatard@mandriva.com };
434f9b95980Sapatard@mandriva.com 
43575b9b65eSJean-Francois Moine static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
43675b9b65eSJean-Francois Moine     {
43775b9b65eSJean-Francois Moine 	.name = "i2s",
43875b9b65eSJean-Francois Moine 	.id = 0,
439f9b95980Sapatard@mandriva.com 	.playback = {
440f9b95980Sapatard@mandriva.com 		.channels_min = 1,
441f9b95980Sapatard@mandriva.com 		.channels_max = 2,
4429e12cbd9SMark Brown 		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
4439e12cbd9SMark Brown 				SNDRV_PCM_RATE_96000,
444363589bfSRussell King 		.formats = KIRKWOOD_I2S_FORMATS,
445363589bfSRussell King 	},
446f9b95980Sapatard@mandriva.com 	.capture = {
447f9b95980Sapatard@mandriva.com 		.channels_min = 1,
448f9b95980Sapatard@mandriva.com 		.channels_max = 2,
4499e12cbd9SMark Brown 		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
4509e12cbd9SMark Brown 				SNDRV_PCM_RATE_96000,
451363589bfSRussell King 		.formats = KIRKWOOD_I2S_FORMATS,
452363589bfSRussell King 	},
453363589bfSRussell King 	.ops = &kirkwood_i2s_dai_ops,
45475b9b65eSJean-Francois Moine     },
45575b9b65eSJean-Francois Moine     {
45675b9b65eSJean-Francois Moine 	.name = "spdif",
45775b9b65eSJean-Francois Moine 	.id = 1,
45875b9b65eSJean-Francois Moine 	.playback = {
45975b9b65eSJean-Francois Moine 		.channels_min = 1,
46075b9b65eSJean-Francois Moine 		.channels_max = 2,
46175b9b65eSJean-Francois Moine 		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
46275b9b65eSJean-Francois Moine 				SNDRV_PCM_RATE_96000,
4631c195ddbSJean-Francois Moine 		.formats = KIRKWOOD_SPDIF_FORMATS,
46475b9b65eSJean-Francois Moine 	},
46575b9b65eSJean-Francois Moine 	.capture = {
46675b9b65eSJean-Francois Moine 		.channels_min = 1,
46775b9b65eSJean-Francois Moine 		.channels_max = 2,
46875b9b65eSJean-Francois Moine 		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
46975b9b65eSJean-Francois Moine 				SNDRV_PCM_RATE_96000,
4701c195ddbSJean-Francois Moine 		.formats = KIRKWOOD_SPDIF_FORMATS,
47175b9b65eSJean-Francois Moine 	},
47275b9b65eSJean-Francois Moine 	.ops = &kirkwood_i2s_dai_ops,
47375b9b65eSJean-Francois Moine     },
474363589bfSRussell King };
475363589bfSRussell King 
47675b9b65eSJean-Francois Moine static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
47775b9b65eSJean-Francois Moine     {
47875b9b65eSJean-Francois Moine 	.name = "i2s",
47975b9b65eSJean-Francois Moine 	.id = 0,
480363589bfSRussell King 	.playback = {
481363589bfSRussell King 		.channels_min = 1,
482363589bfSRussell King 		.channels_max = 2,
48302fc17c1SJean-Francois Moine 		.rates = SNDRV_PCM_RATE_CONTINUOUS,
48402fc17c1SJean-Francois Moine 		.rate_min = 5512,
48502fc17c1SJean-Francois Moine 		.rate_max = 192000,
486363589bfSRussell King 		.formats = KIRKWOOD_I2S_FORMATS,
487363589bfSRussell King 	},
488363589bfSRussell King 	.capture = {
489363589bfSRussell King 		.channels_min = 1,
490363589bfSRussell King 		.channels_max = 2,
49102fc17c1SJean-Francois Moine 		.rates = SNDRV_PCM_RATE_CONTINUOUS,
49202fc17c1SJean-Francois Moine 		.rate_min = 5512,
49302fc17c1SJean-Francois Moine 		.rate_max = 192000,
494363589bfSRussell King 		.formats = KIRKWOOD_I2S_FORMATS,
495363589bfSRussell King 	},
496f9b95980Sapatard@mandriva.com 	.ops = &kirkwood_i2s_dai_ops,
49775b9b65eSJean-Francois Moine     },
49875b9b65eSJean-Francois Moine     {
49975b9b65eSJean-Francois Moine 	.name = "spdif",
50075b9b65eSJean-Francois Moine 	.id = 1,
50175b9b65eSJean-Francois Moine 	.playback = {
50275b9b65eSJean-Francois Moine 		.channels_min = 1,
50375b9b65eSJean-Francois Moine 		.channels_max = 2,
50402fc17c1SJean-Francois Moine 		.rates = SNDRV_PCM_RATE_CONTINUOUS,
50502fc17c1SJean-Francois Moine 		.rate_min = 5512,
50602fc17c1SJean-Francois Moine 		.rate_max = 192000,
5071c195ddbSJean-Francois Moine 		.formats = KIRKWOOD_SPDIF_FORMATS,
50875b9b65eSJean-Francois Moine 	},
50975b9b65eSJean-Francois Moine 	.capture = {
51075b9b65eSJean-Francois Moine 		.channels_min = 1,
51175b9b65eSJean-Francois Moine 		.channels_max = 2,
51202fc17c1SJean-Francois Moine 		.rates = SNDRV_PCM_RATE_CONTINUOUS,
51302fc17c1SJean-Francois Moine 		.rate_min = 5512,
51402fc17c1SJean-Francois Moine 		.rate_max = 192000,
5151c195ddbSJean-Francois Moine 		.formats = KIRKWOOD_SPDIF_FORMATS,
51675b9b65eSJean-Francois Moine 	},
51775b9b65eSJean-Francois Moine 	.ops = &kirkwood_i2s_dai_ops,
51875b9b65eSJean-Francois Moine     },
519f9b95980Sapatard@mandriva.com };
520f9b95980Sapatard@mandriva.com 
52134e15fbdSBill Pemberton static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
522f9b95980Sapatard@mandriva.com {
523363589bfSRussell King 	struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
52475b9b65eSJean-Francois Moine 	struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
525f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv;
526363589bfSRussell King 	struct resource *mem;
527eb632318SJean-Francois Moine 	struct device_node *np = pdev->dev.of_node;
528f9b95980Sapatard@mandriva.com 	int err;
529f9b95980Sapatard@mandriva.com 
530dbc517bfSRussell King 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
531c7591edcSMarkus Elfring 	if (!priv)
532dbc517bfSRussell King 		return -ENOMEM;
533c7591edcSMarkus Elfring 
534f0fba2adSLiam Girdwood 	dev_set_drvdata(&pdev->dev, priv);
535f9b95980Sapatard@mandriva.com 
536f9b95980Sapatard@mandriva.com 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
537b25b5aa0SThierry Reding 	priv->io = devm_ioremap_resource(&pdev->dev, mem);
538b25b5aa0SThierry Reding 	if (IS_ERR(priv->io))
539b25b5aa0SThierry Reding 		return PTR_ERR(priv->io);
540f9b95980Sapatard@mandriva.com 
541f9b95980Sapatard@mandriva.com 	priv->irq = platform_get_irq(pdev, 0);
542e7b2e30aSGustavo A. R. Silva 	if (priv->irq < 0) {
543e7b2e30aSGustavo A. R. Silva 		dev_err(&pdev->dev, "platform_get_irq failed: %d\n", priv->irq);
544e7b2e30aSGustavo A. R. Silva 		return priv->irq;
545f9b95980Sapatard@mandriva.com 	}
546f9b95980Sapatard@mandriva.com 
547eb632318SJean-Francois Moine 	if (np) {
548eb632318SJean-Francois Moine 		priv->burst = 128;		/* might be 32 or 128 */
549eb632318SJean-Francois Moine 	} else if (data) {
550eb632318SJean-Francois Moine 		priv->burst = data->burst;
551eb632318SJean-Francois Moine 	} else {
552eb632318SJean-Francois Moine 		dev_err(&pdev->dev, "no DT nor platform data ?!\n");
553dbc517bfSRussell King 		return -EINVAL;
554f9b95980Sapatard@mandriva.com 	}
555f9b95980Sapatard@mandriva.com 
556eb632318SJean-Francois Moine 	priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
557e919c716SAndrew Lunn 	if (IS_ERR(priv->clk)) {
558e919c716SAndrew Lunn 		dev_err(&pdev->dev, "no clock\n");
559dbc517bfSRussell King 		return PTR_ERR(priv->clk);
560e919c716SAndrew Lunn 	}
561dbc517bfSRussell King 
562dbc517bfSRussell King 	err = clk_prepare_enable(priv->clk);
563dbc517bfSRussell King 	if (err < 0)
564dbc517bfSRussell King 		return err;
565e919c716SAndrew Lunn 
5664734dc96SMark Brown 	priv->extclk = devm_clk_get(&pdev->dev, "extclk");
56784aac6c7SJean-Francois Moine 	if (IS_ERR(priv->extclk)) {
56884aac6c7SJean-Francois Moine 		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
56984aac6c7SJean-Francois Moine 			return -EPROBE_DEFER;
57084aac6c7SJean-Francois Moine 	} else {
571aaa6d062SShawn Guo 		if (clk_is_match(priv->extclk, priv->clk)) {
572af64d734SRussell King 			devm_clk_put(&pdev->dev, priv->extclk);
573d8d11ba5SRussell King 			priv->extclk = ERR_PTR(-EINVAL);
574d8d11ba5SRussell King 		} else {
575d8d11ba5SRussell King 			dev_info(&pdev->dev, "found external clock\n");
576d8d11ba5SRussell King 			clk_prepare_enable(priv->extclk);
57799d8d3baSJean-Francois Moine 			soc_dai = kirkwood_i2s_dai_extclk;
578d8d11ba5SRussell King 		}
579d8d11ba5SRussell King 	}
580d8d11ba5SRussell King 
581d8d11ba5SRussell King 	/* Some sensible defaults - this reflects the powerup values */
582d8d11ba5SRussell King 	priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
583d8d11ba5SRussell King 	priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
584d8d11ba5SRussell King 
585d8d11ba5SRussell King 	/* Select the burst size */
586eb632318SJean-Francois Moine 	if (priv->burst == 32) {
587d8d11ba5SRussell King 		priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
588d8d11ba5SRussell King 		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
589d8d11ba5SRussell King 	} else {
590d8d11ba5SRussell King 		priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
591d8d11ba5SRussell King 		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
592d8d11ba5SRussell King 	}
593d8d11ba5SRussell King 
594f98fc0f8SKuninori Morimoto 	err = devm_snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
59575b9b65eSJean-Francois Moine 					 soc_dai, 2);
59664ddf1f8SRussell King 	if (err) {
59783d85f53SKuninori Morimoto 		dev_err(&pdev->dev, "snd_soc_register_component failed\n");
59864ddf1f8SRussell King 		goto err_component;
59964ddf1f8SRussell King 	}
600baffab28SSimon Baatz 
60175b9b65eSJean-Francois Moine 	kirkwood_i2s_init(priv);
60275b9b65eSJean-Francois Moine 
60364ddf1f8SRussell King 	return 0;
604f98fc0f8SKuninori Morimoto 
60564ddf1f8SRussell King  err_component:
6064734dc96SMark Brown 	if (!IS_ERR(priv->extclk))
607363589bfSRussell King 		clk_disable_unprepare(priv->extclk);
608baffab28SSimon Baatz 	clk_disable_unprepare(priv->clk);
609f9b95980Sapatard@mandriva.com 
610f9b95980Sapatard@mandriva.com 	return err;
611f9b95980Sapatard@mandriva.com }
612f9b95980Sapatard@mandriva.com 
61334e15fbdSBill Pemberton static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
614f9b95980Sapatard@mandriva.com {
615f0fba2adSLiam Girdwood 	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
616f0fba2adSLiam Girdwood 
6174734dc96SMark Brown 	if (!IS_ERR(priv->extclk))
618363589bfSRussell King 		clk_disable_unprepare(priv->extclk);
619e919c716SAndrew Lunn 	clk_disable_unprepare(priv->clk);
620f0fba2adSLiam Girdwood 
621f9b95980Sapatard@mandriva.com 	return 0;
622f9b95980Sapatard@mandriva.com }
623f9b95980Sapatard@mandriva.com 
624eb632318SJean-Francois Moine #ifdef CONFIG_OF
6257f2c52afSFabian Frederick static const struct of_device_id mvebu_audio_of_match[] = {
626d098b2f0SThomas Petazzoni 	{ .compatible = "marvell,kirkwood-audio" },
627d098b2f0SThomas Petazzoni 	{ .compatible = "marvell,dove-audio" },
6289a0d5113SThomas Petazzoni 	{ .compatible = "marvell,armada370-audio" },
629eb632318SJean-Francois Moine 	{ }
630eb632318SJean-Francois Moine };
631eb632318SJean-Francois Moine MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
632eb632318SJean-Francois Moine #endif
633eb632318SJean-Francois Moine 
634f9b95980Sapatard@mandriva.com static struct platform_driver kirkwood_i2s_driver = {
635f9b95980Sapatard@mandriva.com 	.probe  = kirkwood_i2s_dev_probe,
63634e15fbdSBill Pemberton 	.remove = kirkwood_i2s_dev_remove,
637f9b95980Sapatard@mandriva.com 	.driver = {
638f9b95980Sapatard@mandriva.com 		.name = DRV_NAME,
639eb632318SJean-Francois Moine 		.of_match_table = of_match_ptr(mvebu_audio_of_match),
640f9b95980Sapatard@mandriva.com 	},
641f9b95980Sapatard@mandriva.com };
642f9b95980Sapatard@mandriva.com 
64341b10225SAxel Lin module_platform_driver(kirkwood_i2s_driver);
644f9b95980Sapatard@mandriva.com 
645f9b95980Sapatard@mandriva.com /* Module information */
64669737897SArnaud Patard (Rtp) MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
647f9b95980Sapatard@mandriva.com MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
648f9b95980Sapatard@mandriva.com MODULE_LICENSE("GPL");
64964ddf1f8SRussell King MODULE_ALIAS("platform:mvebu-audio");
650