xref: /linux/sound/soc/atmel/atmel-i2s.c (revision 2f27fce67173bbb05d5a0ee03dae5c021202c912)
1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b543e467SCyrille Pitchen /*
3b543e467SCyrille Pitchen  * Driver for Atmel I2S controller
4b543e467SCyrille Pitchen  *
5b543e467SCyrille Pitchen  * Copyright (C) 2015 Atmel Corporation
6b543e467SCyrille Pitchen  *
7b543e467SCyrille Pitchen  * Author: Cyrille Pitchen <cyrille.pitchen@atmel.com>
8b543e467SCyrille Pitchen  */
9b543e467SCyrille Pitchen 
10b543e467SCyrille Pitchen #include <linux/init.h>
11b543e467SCyrille Pitchen #include <linux/module.h>
12b543e467SCyrille Pitchen #include <linux/device.h>
13b543e467SCyrille Pitchen #include <linux/slab.h>
14b543e467SCyrille Pitchen #include <linux/delay.h>
15b543e467SCyrille Pitchen #include <linux/io.h>
16b543e467SCyrille Pitchen #include <linux/clk.h>
17b543e467SCyrille Pitchen #include <linux/mfd/syscon.h>
18b543e467SCyrille Pitchen 
19b543e467SCyrille Pitchen #include <sound/core.h>
20b543e467SCyrille Pitchen #include <sound/pcm.h>
21b543e467SCyrille Pitchen #include <sound/pcm_params.h>
22b543e467SCyrille Pitchen #include <sound/initval.h>
23b543e467SCyrille Pitchen #include <sound/soc.h>
24b543e467SCyrille Pitchen #include <sound/dmaengine_pcm.h>
25b543e467SCyrille Pitchen 
26b543e467SCyrille Pitchen #define ATMEL_I2SC_MAX_TDM_CHANNELS	8
27b543e467SCyrille Pitchen 
28b543e467SCyrille Pitchen /*
29b543e467SCyrille Pitchen  * ---- I2S Controller Register map ----
30b543e467SCyrille Pitchen  */
31b543e467SCyrille Pitchen #define ATMEL_I2SC_CR		0x0000	/* Control Register */
32b543e467SCyrille Pitchen #define ATMEL_I2SC_MR		0x0004	/* Mode Register */
33b543e467SCyrille Pitchen #define ATMEL_I2SC_SR		0x0008	/* Status Register */
34b543e467SCyrille Pitchen #define ATMEL_I2SC_SCR		0x000c	/* Status Clear Register */
35b543e467SCyrille Pitchen #define ATMEL_I2SC_SSR		0x0010	/* Status Set Register */
36b543e467SCyrille Pitchen #define ATMEL_I2SC_IER		0x0014	/* Interrupt Enable Register */
37b543e467SCyrille Pitchen #define ATMEL_I2SC_IDR		0x0018	/* Interrupt Disable Register */
38b543e467SCyrille Pitchen #define ATMEL_I2SC_IMR		0x001c	/* Interrupt Mask Register */
39b543e467SCyrille Pitchen #define ATMEL_I2SC_RHR		0x0020	/* Receiver Holding Register */
40b543e467SCyrille Pitchen #define ATMEL_I2SC_THR		0x0024	/* Transmitter Holding Register */
41b543e467SCyrille Pitchen #define ATMEL_I2SC_VERSION	0x0028	/* Version Register */
42b543e467SCyrille Pitchen 
43b543e467SCyrille Pitchen /*
44b543e467SCyrille Pitchen  * ---- Control Register (Write-only) ----
45b543e467SCyrille Pitchen  */
46b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_RXEN	BIT(0)	/* Receiver Enable */
47b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_RXDIS	BIT(1)	/* Receiver Disable */
48b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_CKEN	BIT(2)	/* Clock Enable */
49b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_CKDIS	BIT(3)	/* Clock Disable */
50b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_TXEN	BIT(4)	/* Transmitter Enable */
51b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_TXDIS	BIT(5)	/* Transmitter Disable */
52b543e467SCyrille Pitchen #define ATMEL_I2SC_CR_SWRST	BIT(7)	/* Software Reset */
53b543e467SCyrille Pitchen 
54b543e467SCyrille Pitchen /*
55b543e467SCyrille Pitchen  * ---- Mode Register (Read/Write) ----
56b543e467SCyrille Pitchen  */
57b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_MODE_MASK		GENMASK(0, 0)
58b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_MODE_SLAVE	(0 << 0)
59b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_MODE_MASTER	(1 << 0)
60b543e467SCyrille Pitchen 
61b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_MASK		GENMASK(4, 2)
62b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_32_BITS	(0 << 2)
63b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_24_BITS	(1 << 2)
64b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_20_BITS	(2 << 2)
65b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_18_BITS	(3 << 2)
66b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_16_BITS	(4 << 2)
67b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_16_BITS_COMPACT	(5 << 2)
68b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_8_BITS		(6 << 2)
69b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_DATALENGTH_8_BITS_COMPACT	(7 << 2)
70b543e467SCyrille Pitchen 
71b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_FORMAT_MASK	GENMASK(7, 6)
72b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_FORMAT_I2S	(0 << 6)
73b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_FORMAT_LJ		(1 << 6)  /* Left Justified */
74b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_FORMAT_TDM	(2 << 6)
75b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_FORMAT_TDMLJ	(3 << 6)
76b543e467SCyrille Pitchen 
77b543e467SCyrille Pitchen /* Left audio samples duplicated to right audio channel */
78b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_RXMONO		BIT(8)
79b543e467SCyrille Pitchen 
80b543e467SCyrille Pitchen /* Receiver uses one DMA channel ... */
81b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_RXDMA_MASK	GENMASK(9, 9)
82b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_RXDMA_SINGLE	(0 << 9)  /* for all audio channels */
83b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_RXDMA_MULTIPLE	(1 << 9)  /* per audio channel */
84b543e467SCyrille Pitchen 
85b543e467SCyrille Pitchen /* I2SDO output of I2SC is internally connected to I2SDI input */
86b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_RXLOOP		BIT(10)
87b543e467SCyrille Pitchen 
88b543e467SCyrille Pitchen /* Left audio samples duplicated to right audio channel */
89b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXMONO		BIT(12)
90b543e467SCyrille Pitchen 
91b543e467SCyrille Pitchen /* Transmitter uses one DMA channel ... */
92b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXDMA_MASK	GENMASK(13, 13)
93b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXDMA_SINGLE	(0 << 13)  /* for all audio channels */
94b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXDME_MULTIPLE	(1 << 13)  /* per audio channel */
95b543e467SCyrille Pitchen 
96b543e467SCyrille Pitchen /* x sample transmitted when underrun */
97b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXSAME_MASK	GENMASK(14, 14)
98b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXSAME_ZERO	(0 << 14)  /* Zero sample */
99b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_TXSAME_PREVIOUS	(1 << 14)  /* Previous sample */
100b543e467SCyrille Pitchen 
101b543e467SCyrille Pitchen /* Audio Clock to I2SC Master Clock ratio */
102b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKDIV_MASK	GENMASK(21, 16)
103b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKDIV(div) \
104b543e467SCyrille Pitchen 	(((div) << 16) & ATMEL_I2SC_MR_IMCKDIV_MASK)
105b543e467SCyrille Pitchen 
106b543e467SCyrille Pitchen /* Master Clock to fs ratio */
107b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKFS_MASK	GENMASK(29, 24)
108b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKFS(fs) \
109b543e467SCyrille Pitchen 	(((fs) << 24) & ATMEL_I2SC_MR_IMCKFS_MASK)
110b543e467SCyrille Pitchen 
111b543e467SCyrille Pitchen /* Master Clock mode */
112b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKMODE_MASK	GENMASK(30, 30)
113b543e467SCyrille Pitchen /* 0: No master clock generated (selected clock drives I2SCK pin) */
114b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKMODE_I2SCK	(0 << 30)
115b543e467SCyrille Pitchen /* 1: master clock generated (internally generated clock drives I2SMCK pin) */
116b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IMCKMODE_I2SMCK	(1 << 30)
117b543e467SCyrille Pitchen 
118b543e467SCyrille Pitchen /* Slot Width */
119b543e467SCyrille Pitchen /* 0: slot is 32 bits wide for DATALENGTH = 18/20/24 bits. */
120b543e467SCyrille Pitchen /* 1: slot is 24 bits wide for DATALENGTH = 18/20/24 bits. */
121b543e467SCyrille Pitchen #define ATMEL_I2SC_MR_IWS		BIT(31)
122b543e467SCyrille Pitchen 
123b543e467SCyrille Pitchen /*
124b543e467SCyrille Pitchen  * ---- Status Registers ----
125b543e467SCyrille Pitchen  */
126b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_RXEN	BIT(0)	/* Receiver Enabled */
127b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_RXRDY	BIT(1)	/* Receive Ready */
128b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_RXOR	BIT(2)	/* Receive Overrun */
129b543e467SCyrille Pitchen 
130b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_TXEN	BIT(4)	/* Transmitter Enabled */
131b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_TXRDY	BIT(5)	/* Transmit Ready */
132b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_TXUR	BIT(6)	/* Transmit Underrun */
133b543e467SCyrille Pitchen 
134b543e467SCyrille Pitchen /* Receive Overrun Channel */
135b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_RXORCH_MASK	GENMASK(15, 8)
136b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_RXORCH(ch)	(1 << (((ch) & 0x7) + 8))
137b543e467SCyrille Pitchen 
138b543e467SCyrille Pitchen /* Transmit Underrun Channel */
139b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_TXURCH_MASK	GENMASK(27, 20)
140b543e467SCyrille Pitchen #define ATMEL_I2SC_SR_TXURCH(ch)	(1 << (((ch) & 0x7) + 20))
141b543e467SCyrille Pitchen 
142b543e467SCyrille Pitchen /*
143b543e467SCyrille Pitchen  * ---- Interrupt Enable/Disable/Mask Registers ----
144b543e467SCyrille Pitchen  */
145b543e467SCyrille Pitchen #define ATMEL_I2SC_INT_RXRDY	ATMEL_I2SC_SR_RXRDY
146b543e467SCyrille Pitchen #define ATMEL_I2SC_INT_RXOR	ATMEL_I2SC_SR_RXOR
147b543e467SCyrille Pitchen #define ATMEL_I2SC_INT_TXRDY	ATMEL_I2SC_SR_TXRDY
148b543e467SCyrille Pitchen #define ATMEL_I2SC_INT_TXUR	ATMEL_I2SC_SR_TXUR
149b543e467SCyrille Pitchen 
150b543e467SCyrille Pitchen static const struct regmap_config atmel_i2s_regmap_config = {
151b543e467SCyrille Pitchen 	.reg_bits = 32,
152b543e467SCyrille Pitchen 	.reg_stride = 4,
153b543e467SCyrille Pitchen 	.val_bits = 32,
154b543e467SCyrille Pitchen 	.max_register = ATMEL_I2SC_VERSION,
155b543e467SCyrille Pitchen };
156b543e467SCyrille Pitchen 
157b543e467SCyrille Pitchen struct atmel_i2s_gck_param {
158b543e467SCyrille Pitchen 	int		fs;
159b543e467SCyrille Pitchen 	unsigned long	mck;
160b543e467SCyrille Pitchen 	int		imckdiv;
161b543e467SCyrille Pitchen 	int		imckfs;
162b543e467SCyrille Pitchen };
163b543e467SCyrille Pitchen 
164b543e467SCyrille Pitchen #define I2S_MCK_12M288		12288000UL
165b543e467SCyrille Pitchen #define I2S_MCK_11M2896		11289600UL
166f85739c0SGuiting Shen #define I2S_MCK_6M144		6144000UL
167b543e467SCyrille Pitchen 
168b543e467SCyrille Pitchen /* mck = (32 * (imckfs+1) / (imckdiv+1)) * fs */
169b543e467SCyrille Pitchen static const struct atmel_i2s_gck_param gck_params[] = {
170f85739c0SGuiting Shen 	/* mck = 6.144Mhz */
171f85739c0SGuiting Shen 	{  8000, I2S_MCK_6M144,  1, 47},	/* mck =  768 fs */
172f85739c0SGuiting Shen 
173b543e467SCyrille Pitchen 	/* mck = 12.288MHz */
174b543e467SCyrille Pitchen 	{ 16000, I2S_MCK_12M288, 1, 47},	/* mck =  768 fs */
175b543e467SCyrille Pitchen 	{ 24000, I2S_MCK_12M288, 3, 63},	/* mck =  512 fs */
176b543e467SCyrille Pitchen 	{ 32000, I2S_MCK_12M288, 3, 47},	/* mck =  384 fs */
177b543e467SCyrille Pitchen 	{ 48000, I2S_MCK_12M288, 7, 63},	/* mck =  256 fs */
178b543e467SCyrille Pitchen 	{ 64000, I2S_MCK_12M288, 7, 47},	/* mck =  192 fs */
179b543e467SCyrille Pitchen 	{ 96000, I2S_MCK_12M288, 7, 31},	/* mck =  128 fs */
180b543e467SCyrille Pitchen 	{192000, I2S_MCK_12M288, 7, 15},	/* mck =   64 fs */
181b543e467SCyrille Pitchen 
182b543e467SCyrille Pitchen 	/* mck = 11.2896MHz */
183b543e467SCyrille Pitchen 	{ 11025, I2S_MCK_11M2896, 1, 63},	/* mck = 1024 fs */
184b543e467SCyrille Pitchen 	{ 22050, I2S_MCK_11M2896, 3, 63},	/* mck =  512 fs */
185b543e467SCyrille Pitchen 	{ 44100, I2S_MCK_11M2896, 7, 63},	/* mck =  256 fs */
186b543e467SCyrille Pitchen 	{ 88200, I2S_MCK_11M2896, 7, 31},	/* mck =  128 fs */
187b543e467SCyrille Pitchen 	{176400, I2S_MCK_11M2896, 7, 15},	/* mck =   64 fs */
188b543e467SCyrille Pitchen };
189b543e467SCyrille Pitchen 
190b543e467SCyrille Pitchen struct atmel_i2s_dev;
191b543e467SCyrille Pitchen 
192b543e467SCyrille Pitchen struct atmel_i2s_caps {
193b543e467SCyrille Pitchen 	int	(*mck_init)(struct atmel_i2s_dev *, struct device_node *np);
194b543e467SCyrille Pitchen };
195b543e467SCyrille Pitchen 
196b543e467SCyrille Pitchen struct atmel_i2s_dev {
197b543e467SCyrille Pitchen 	struct device				*dev;
198b543e467SCyrille Pitchen 	struct regmap				*regmap;
199b543e467SCyrille Pitchen 	struct clk				*pclk;
200b543e467SCyrille Pitchen 	struct clk				*gclk;
201b543e467SCyrille Pitchen 	struct snd_dmaengine_dai_dma_data	playback;
202b543e467SCyrille Pitchen 	struct snd_dmaengine_dai_dma_data	capture;
203b543e467SCyrille Pitchen 	unsigned int				fmt;
204b543e467SCyrille Pitchen 	const struct atmel_i2s_gck_param	*gck_param;
205b543e467SCyrille Pitchen 	const struct atmel_i2s_caps		*caps;
2063b7961a3SCodrin Ciubotariu 	int					clk_use_no;
207b543e467SCyrille Pitchen };
208b543e467SCyrille Pitchen 
209b543e467SCyrille Pitchen static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id)
210b543e467SCyrille Pitchen {
211b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = dev_id;
212b543e467SCyrille Pitchen 	unsigned int sr, imr, pending, ch, mask;
213b543e467SCyrille Pitchen 	irqreturn_t ret = IRQ_NONE;
214b543e467SCyrille Pitchen 
215b543e467SCyrille Pitchen 	regmap_read(dev->regmap, ATMEL_I2SC_SR, &sr);
216b543e467SCyrille Pitchen 	regmap_read(dev->regmap, ATMEL_I2SC_IMR, &imr);
217b543e467SCyrille Pitchen 	pending = sr & imr;
218b543e467SCyrille Pitchen 
219b543e467SCyrille Pitchen 	if (!pending)
220b543e467SCyrille Pitchen 		return IRQ_NONE;
221b543e467SCyrille Pitchen 
222b543e467SCyrille Pitchen 	if (pending & ATMEL_I2SC_INT_RXOR) {
223b543e467SCyrille Pitchen 		mask = ATMEL_I2SC_SR_RXOR;
224b543e467SCyrille Pitchen 
225b543e467SCyrille Pitchen 		for (ch = 0; ch < ATMEL_I2SC_MAX_TDM_CHANNELS; ++ch) {
226b543e467SCyrille Pitchen 			if (sr & ATMEL_I2SC_SR_RXORCH(ch)) {
227b543e467SCyrille Pitchen 				mask |= ATMEL_I2SC_SR_RXORCH(ch);
228b543e467SCyrille Pitchen 				dev_err(dev->dev,
229b543e467SCyrille Pitchen 					"RX overrun on channel %d\n", ch);
230b543e467SCyrille Pitchen 			}
231b543e467SCyrille Pitchen 		}
232b543e467SCyrille Pitchen 		regmap_write(dev->regmap, ATMEL_I2SC_SCR, mask);
233b543e467SCyrille Pitchen 		ret = IRQ_HANDLED;
234b543e467SCyrille Pitchen 	}
235b543e467SCyrille Pitchen 
236b543e467SCyrille Pitchen 	if (pending & ATMEL_I2SC_INT_TXUR) {
237b543e467SCyrille Pitchen 		mask = ATMEL_I2SC_SR_TXUR;
238b543e467SCyrille Pitchen 
239b543e467SCyrille Pitchen 		for (ch = 0; ch < ATMEL_I2SC_MAX_TDM_CHANNELS; ++ch) {
240b543e467SCyrille Pitchen 			if (sr & ATMEL_I2SC_SR_TXURCH(ch)) {
241b543e467SCyrille Pitchen 				mask |= ATMEL_I2SC_SR_TXURCH(ch);
242b543e467SCyrille Pitchen 				dev_err(dev->dev,
243b543e467SCyrille Pitchen 					"TX underrun on channel %d\n", ch);
244b543e467SCyrille Pitchen 			}
245b543e467SCyrille Pitchen 		}
246b543e467SCyrille Pitchen 		regmap_write(dev->regmap, ATMEL_I2SC_SCR, mask);
247b543e467SCyrille Pitchen 		ret = IRQ_HANDLED;
248b543e467SCyrille Pitchen 	}
249b543e467SCyrille Pitchen 
250b543e467SCyrille Pitchen 	return ret;
251b543e467SCyrille Pitchen }
252b543e467SCyrille Pitchen 
253b543e467SCyrille Pitchen #define ATMEL_I2S_RATES		SNDRV_PCM_RATE_8000_192000
254b543e467SCyrille Pitchen 
255b543e467SCyrille Pitchen #define ATMEL_I2S_FORMATS	(SNDRV_PCM_FMTBIT_S8 |		\
256b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S16_LE |	\
257b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S18_3LE |	\
258b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S20_3LE |	\
259b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S24_3LE |	\
260b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S24_LE |	\
261b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S32_LE)
262b543e467SCyrille Pitchen 
263b543e467SCyrille Pitchen static int atmel_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
264b543e467SCyrille Pitchen {
265b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
266b543e467SCyrille Pitchen 
267b543e467SCyrille Pitchen 	dev->fmt = fmt;
268b543e467SCyrille Pitchen 	return 0;
269b543e467SCyrille Pitchen }
270b543e467SCyrille Pitchen 
271b543e467SCyrille Pitchen static int atmel_i2s_prepare(struct snd_pcm_substream *substream,
272b543e467SCyrille Pitchen 			     struct snd_soc_dai *dai)
273b543e467SCyrille Pitchen {
274b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
275b543e467SCyrille Pitchen 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
276b543e467SCyrille Pitchen 	unsigned int rhr, sr = 0;
277b543e467SCyrille Pitchen 
278b543e467SCyrille Pitchen 	if (is_playback) {
279b543e467SCyrille Pitchen 		regmap_read(dev->regmap, ATMEL_I2SC_SR, &sr);
280b543e467SCyrille Pitchen 		if (sr & ATMEL_I2SC_SR_RXRDY) {
281b543e467SCyrille Pitchen 			/*
282b543e467SCyrille Pitchen 			 * The RX Ready flag should not be set. However if here,
283b543e467SCyrille Pitchen 			 * we flush (read) the Receive Holding Register to start
284b543e467SCyrille Pitchen 			 * from a clean state.
285b543e467SCyrille Pitchen 			 */
286b543e467SCyrille Pitchen 			dev_dbg(dev->dev, "RXRDY is set\n");
287b543e467SCyrille Pitchen 			regmap_read(dev->regmap, ATMEL_I2SC_RHR, &rhr);
288b543e467SCyrille Pitchen 		}
289b543e467SCyrille Pitchen 	}
290b543e467SCyrille Pitchen 
291b543e467SCyrille Pitchen 	return 0;
292b543e467SCyrille Pitchen }
293b543e467SCyrille Pitchen 
294b543e467SCyrille Pitchen static int atmel_i2s_get_gck_param(struct atmel_i2s_dev *dev, int fs)
295b543e467SCyrille Pitchen {
296b543e467SCyrille Pitchen 	int i, best;
297b543e467SCyrille Pitchen 
29873ad0df5SCodrin Ciubotariu 	if (!dev->gclk) {
299b543e467SCyrille Pitchen 		dev_err(dev->dev, "cannot generate the I2S Master Clock\n");
300b543e467SCyrille Pitchen 		return -EINVAL;
301b543e467SCyrille Pitchen 	}
302b543e467SCyrille Pitchen 
303b543e467SCyrille Pitchen 	/*
304b543e467SCyrille Pitchen 	 * Find the best possible settings to generate the I2S Master Clock
305b543e467SCyrille Pitchen 	 * from the PLL Audio.
306b543e467SCyrille Pitchen 	 */
307b543e467SCyrille Pitchen 	dev->gck_param = NULL;
308b543e467SCyrille Pitchen 	best = INT_MAX;
309b543e467SCyrille Pitchen 	for (i = 0; i < ARRAY_SIZE(gck_params); ++i) {
310b543e467SCyrille Pitchen 		const struct atmel_i2s_gck_param *gck_param = &gck_params[i];
311b543e467SCyrille Pitchen 		int val = abs(fs - gck_param->fs);
312b543e467SCyrille Pitchen 
313b543e467SCyrille Pitchen 		if (val < best) {
314b543e467SCyrille Pitchen 			best = val;
315b543e467SCyrille Pitchen 			dev->gck_param = gck_param;
316b543e467SCyrille Pitchen 		}
317b543e467SCyrille Pitchen 	}
318b543e467SCyrille Pitchen 
319b543e467SCyrille Pitchen 	return 0;
320b543e467SCyrille Pitchen }
321b543e467SCyrille Pitchen 
322b543e467SCyrille Pitchen static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
323b543e467SCyrille Pitchen 			       struct snd_pcm_hw_params *params,
324b543e467SCyrille Pitchen 			       struct snd_soc_dai *dai)
325b543e467SCyrille Pitchen {
326b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
327b543e467SCyrille Pitchen 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
3283b7961a3SCodrin Ciubotariu 	unsigned int mr = 0, mr_mask;
329b543e467SCyrille Pitchen 	int ret;
330b543e467SCyrille Pitchen 
3313b7961a3SCodrin Ciubotariu 	mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK |
3323b7961a3SCodrin Ciubotariu 		ATMEL_I2SC_MR_DATALENGTH_MASK;
3333b7961a3SCodrin Ciubotariu 	if (is_playback)
3343b7961a3SCodrin Ciubotariu 		mr_mask |= ATMEL_I2SC_MR_TXMONO;
3353b7961a3SCodrin Ciubotariu 	else
3363b7961a3SCodrin Ciubotariu 		mr_mask |= ATMEL_I2SC_MR_RXMONO;
3373b7961a3SCodrin Ciubotariu 
338b543e467SCyrille Pitchen 	switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
339b543e467SCyrille Pitchen 	case SND_SOC_DAIFMT_I2S:
340b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_FORMAT_I2S;
341b543e467SCyrille Pitchen 		break;
342b543e467SCyrille Pitchen 
343b543e467SCyrille Pitchen 	default:
344b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported bus format\n");
345b543e467SCyrille Pitchen 		return -EINVAL;
346b543e467SCyrille Pitchen 	}
347b543e467SCyrille Pitchen 
3484a8cf938SMark Brown 	switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
3490fd054a5SCharles Keepax 	case SND_SOC_DAIFMT_BP_FP:
350b543e467SCyrille Pitchen 		/* codec is slave, so cpu is master */
351b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_MODE_MASTER;
352b543e467SCyrille Pitchen 		ret = atmel_i2s_get_gck_param(dev, params_rate(params));
353b543e467SCyrille Pitchen 		if (ret)
354b543e467SCyrille Pitchen 			return ret;
355b543e467SCyrille Pitchen 		break;
356b543e467SCyrille Pitchen 
3570fd054a5SCharles Keepax 	case SND_SOC_DAIFMT_BC_FC:
358b543e467SCyrille Pitchen 		/* codec is master, so cpu is slave */
359b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_MODE_SLAVE;
360b543e467SCyrille Pitchen 		dev->gck_param = NULL;
361b543e467SCyrille Pitchen 		break;
362b543e467SCyrille Pitchen 
363b543e467SCyrille Pitchen 	default:
364b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported master/slave mode\n");
365b543e467SCyrille Pitchen 		return -EINVAL;
366b543e467SCyrille Pitchen 	}
367b543e467SCyrille Pitchen 
368b543e467SCyrille Pitchen 	switch (params_channels(params)) {
369b543e467SCyrille Pitchen 	case 1:
370b543e467SCyrille Pitchen 		if (is_playback)
371b543e467SCyrille Pitchen 			mr |= ATMEL_I2SC_MR_TXMONO;
372b543e467SCyrille Pitchen 		else
373b543e467SCyrille Pitchen 			mr |= ATMEL_I2SC_MR_RXMONO;
374b543e467SCyrille Pitchen 		break;
375b543e467SCyrille Pitchen 	case 2:
376b543e467SCyrille Pitchen 		break;
377b543e467SCyrille Pitchen 	default:
378b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported number of audio channels\n");
379b543e467SCyrille Pitchen 		return -EINVAL;
380b543e467SCyrille Pitchen 	}
381b543e467SCyrille Pitchen 
382b543e467SCyrille Pitchen 	switch (params_format(params)) {
383b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S8:
384b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_8_BITS;
385b543e467SCyrille Pitchen 		break;
386b543e467SCyrille Pitchen 
387b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S16_LE:
388b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_16_BITS;
389b543e467SCyrille Pitchen 		break;
390b543e467SCyrille Pitchen 
391b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S18_3LE:
392b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_18_BITS | ATMEL_I2SC_MR_IWS;
393b543e467SCyrille Pitchen 		break;
394b543e467SCyrille Pitchen 
395b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S20_3LE:
396b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_20_BITS | ATMEL_I2SC_MR_IWS;
397b543e467SCyrille Pitchen 		break;
398b543e467SCyrille Pitchen 
399b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S24_3LE:
400b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_24_BITS | ATMEL_I2SC_MR_IWS;
401b543e467SCyrille Pitchen 		break;
402b543e467SCyrille Pitchen 
403b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S24_LE:
404b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_24_BITS;
405b543e467SCyrille Pitchen 		break;
406b543e467SCyrille Pitchen 
407b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S32_LE:
408b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_32_BITS;
409b543e467SCyrille Pitchen 		break;
410b543e467SCyrille Pitchen 
411b543e467SCyrille Pitchen 	default:
412b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported size/endianness for audio samples\n");
413b543e467SCyrille Pitchen 		return -EINVAL;
414b543e467SCyrille Pitchen 	}
415b543e467SCyrille Pitchen 
4163b7961a3SCodrin Ciubotariu 	return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
417b543e467SCyrille Pitchen }
418b543e467SCyrille Pitchen 
419b543e467SCyrille Pitchen static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
420b543e467SCyrille Pitchen 					  bool enabled)
421b543e467SCyrille Pitchen {
422b543e467SCyrille Pitchen 	unsigned int mr, mr_mask;
42373ad0df5SCodrin Ciubotariu 	unsigned long gclk_rate;
424b543e467SCyrille Pitchen 	int ret;
425b543e467SCyrille Pitchen 
426b543e467SCyrille Pitchen 	mr = 0;
427b543e467SCyrille Pitchen 	mr_mask = (ATMEL_I2SC_MR_IMCKDIV_MASK |
428b543e467SCyrille Pitchen 		   ATMEL_I2SC_MR_IMCKFS_MASK |
429b543e467SCyrille Pitchen 		   ATMEL_I2SC_MR_IMCKMODE_MASK);
430b543e467SCyrille Pitchen 
431b543e467SCyrille Pitchen 	if (!enabled) {
432b543e467SCyrille Pitchen 		/* Disable the I2S Master Clock generator. */
433b543e467SCyrille Pitchen 		ret = regmap_write(dev->regmap, ATMEL_I2SC_CR,
434b543e467SCyrille Pitchen 				   ATMEL_I2SC_CR_CKDIS);
435b543e467SCyrille Pitchen 		if (ret)
436b543e467SCyrille Pitchen 			return ret;
437b543e467SCyrille Pitchen 
438b543e467SCyrille Pitchen 		/* Reset the I2S Master Clock generator settings. */
439b543e467SCyrille Pitchen 		ret = regmap_update_bits(dev->regmap, ATMEL_I2SC_MR,
440b543e467SCyrille Pitchen 					 mr_mask, mr);
441b543e467SCyrille Pitchen 		if (ret)
442b543e467SCyrille Pitchen 			return ret;
443b543e467SCyrille Pitchen 
444b543e467SCyrille Pitchen 		/* Disable/unprepare the PMC generated clock. */
445b543e467SCyrille Pitchen 		clk_disable_unprepare(dev->gclk);
446b543e467SCyrille Pitchen 
447b543e467SCyrille Pitchen 		return 0;
448b543e467SCyrille Pitchen 	}
449b543e467SCyrille Pitchen 
450b543e467SCyrille Pitchen 	if (!dev->gck_param)
451b543e467SCyrille Pitchen 		return -EINVAL;
452b543e467SCyrille Pitchen 
45373ad0df5SCodrin Ciubotariu 	gclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
454b543e467SCyrille Pitchen 
45573ad0df5SCodrin Ciubotariu 	ret = clk_set_rate(dev->gclk, gclk_rate);
456b543e467SCyrille Pitchen 	if (ret)
457b543e467SCyrille Pitchen 		return ret;
458b543e467SCyrille Pitchen 
459b543e467SCyrille Pitchen 	ret = clk_prepare_enable(dev->gclk);
460b543e467SCyrille Pitchen 	if (ret)
461b543e467SCyrille Pitchen 		return ret;
462b543e467SCyrille Pitchen 
463b543e467SCyrille Pitchen 	/* Update the Mode Register to generate the I2S Master Clock. */
464b543e467SCyrille Pitchen 	mr |= ATMEL_I2SC_MR_IMCKDIV(dev->gck_param->imckdiv);
465b543e467SCyrille Pitchen 	mr |= ATMEL_I2SC_MR_IMCKFS(dev->gck_param->imckfs);
466b543e467SCyrille Pitchen 	mr |= ATMEL_I2SC_MR_IMCKMODE_I2SMCK;
467b543e467SCyrille Pitchen 	ret = regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
468b543e467SCyrille Pitchen 	if (ret)
469b543e467SCyrille Pitchen 		return ret;
470b543e467SCyrille Pitchen 
471b543e467SCyrille Pitchen 	/* Finally enable the I2S Master Clock generator. */
472b543e467SCyrille Pitchen 	return regmap_write(dev->regmap, ATMEL_I2SC_CR,
473b543e467SCyrille Pitchen 			    ATMEL_I2SC_CR_CKEN);
474b543e467SCyrille Pitchen }
475b543e467SCyrille Pitchen 
476b543e467SCyrille Pitchen static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
477b543e467SCyrille Pitchen 			     struct snd_soc_dai *dai)
478b543e467SCyrille Pitchen {
479b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
480b543e467SCyrille Pitchen 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
481b543e467SCyrille Pitchen 	bool is_master, mck_enabled;
482b543e467SCyrille Pitchen 	unsigned int cr, mr;
483b543e467SCyrille Pitchen 	int err;
484b543e467SCyrille Pitchen 
485b543e467SCyrille Pitchen 	switch (cmd) {
486b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_START:
487b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_RESUME:
488b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
489b543e467SCyrille Pitchen 		cr = is_playback ? ATMEL_I2SC_CR_TXEN : ATMEL_I2SC_CR_RXEN;
490b543e467SCyrille Pitchen 		mck_enabled = true;
491b543e467SCyrille Pitchen 		break;
492b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_STOP:
493b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_SUSPEND:
494b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
495b543e467SCyrille Pitchen 		cr = is_playback ? ATMEL_I2SC_CR_TXDIS : ATMEL_I2SC_CR_RXDIS;
496b543e467SCyrille Pitchen 		mck_enabled = false;
497b543e467SCyrille Pitchen 		break;
498b543e467SCyrille Pitchen 	default:
499b543e467SCyrille Pitchen 		return -EINVAL;
500b543e467SCyrille Pitchen 	}
501b543e467SCyrille Pitchen 
502b543e467SCyrille Pitchen 	/* Read the Mode Register to retrieve the master/slave state. */
503b543e467SCyrille Pitchen 	err = regmap_read(dev->regmap, ATMEL_I2SC_MR, &mr);
504b543e467SCyrille Pitchen 	if (err)
505b543e467SCyrille Pitchen 		return err;
506b543e467SCyrille Pitchen 	is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER;
507b543e467SCyrille Pitchen 
508b543e467SCyrille Pitchen 	/* If master starts, enable the audio clock. */
5093b7961a3SCodrin Ciubotariu 	if (is_master && mck_enabled) {
5103b7961a3SCodrin Ciubotariu 		if (!dev->clk_use_no) {
511b543e467SCyrille Pitchen 			err = atmel_i2s_switch_mck_generator(dev, true);
512b543e467SCyrille Pitchen 			if (err)
513b543e467SCyrille Pitchen 				return err;
5143b7961a3SCodrin Ciubotariu 		}
5153b7961a3SCodrin Ciubotariu 		dev->clk_use_no++;
5163b7961a3SCodrin Ciubotariu 	}
517b543e467SCyrille Pitchen 
518b543e467SCyrille Pitchen 	err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr);
519b543e467SCyrille Pitchen 	if (err)
520b543e467SCyrille Pitchen 		return err;
521b543e467SCyrille Pitchen 
522b543e467SCyrille Pitchen 	/* If master stops, disable the audio clock. */
5233b7961a3SCodrin Ciubotariu 	if (is_master && !mck_enabled) {
5243b7961a3SCodrin Ciubotariu 		if (dev->clk_use_no == 1) {
525b543e467SCyrille Pitchen 			err = atmel_i2s_switch_mck_generator(dev, false);
5263b7961a3SCodrin Ciubotariu 			if (err)
5273b7961a3SCodrin Ciubotariu 				return err;
5283b7961a3SCodrin Ciubotariu 		}
5293b7961a3SCodrin Ciubotariu 		dev->clk_use_no--;
5303b7961a3SCodrin Ciubotariu 	}
531b543e467SCyrille Pitchen 
532b543e467SCyrille Pitchen 	return err;
533b543e467SCyrille Pitchen }
534b543e467SCyrille Pitchen 
535b543e467SCyrille Pitchen static int atmel_i2s_dai_probe(struct snd_soc_dai *dai)
536b543e467SCyrille Pitchen {
537b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
538b543e467SCyrille Pitchen 
539b543e467SCyrille Pitchen 	snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
540b543e467SCyrille Pitchen 	return 0;
541b543e467SCyrille Pitchen }
542b543e467SCyrille Pitchen 
5432ff8a43dSKuninori Morimoto static const struct snd_soc_dai_ops atmel_i2s_dai_ops = {
544b543e467SCyrille Pitchen 	.probe		= atmel_i2s_dai_probe,
5452ff8a43dSKuninori Morimoto 	.prepare	= atmel_i2s_prepare,
5462ff8a43dSKuninori Morimoto 	.trigger	= atmel_i2s_trigger,
5472ff8a43dSKuninori Morimoto 	.hw_params	= atmel_i2s_hw_params,
5482ff8a43dSKuninori Morimoto 	.set_fmt	= atmel_i2s_set_dai_fmt,
5492ff8a43dSKuninori Morimoto };
5502ff8a43dSKuninori Morimoto 
5512ff8a43dSKuninori Morimoto static struct snd_soc_dai_driver atmel_i2s_dai = {
552b543e467SCyrille Pitchen 	.playback = {
553b543e467SCyrille Pitchen 		.channels_min = 1,
554b543e467SCyrille Pitchen 		.channels_max = 2,
555b543e467SCyrille Pitchen 		.rates = ATMEL_I2S_RATES,
556b543e467SCyrille Pitchen 		.formats = ATMEL_I2S_FORMATS,
557b543e467SCyrille Pitchen 	},
558b543e467SCyrille Pitchen 	.capture = {
559b543e467SCyrille Pitchen 		.channels_min = 1,
560b543e467SCyrille Pitchen 		.channels_max = 2,
561b543e467SCyrille Pitchen 		.rates = ATMEL_I2S_RATES,
562b543e467SCyrille Pitchen 		.formats = ATMEL_I2S_FORMATS,
563b543e467SCyrille Pitchen 	},
564b543e467SCyrille Pitchen 	.ops = &atmel_i2s_dai_ops,
565ba471f8dSKuninori Morimoto 	.symmetric_rate = 1,
566489a830aSCodrin Ciubotariu 	.symmetric_sample_bits = 1,
567b543e467SCyrille Pitchen };
568b543e467SCyrille Pitchen 
569b543e467SCyrille Pitchen static const struct snd_soc_component_driver atmel_i2s_component = {
570b543e467SCyrille Pitchen 	.name			= "atmel-i2s",
5717593e008SCharles Keepax 	.legacy_dai_naming	= 1,
572b543e467SCyrille Pitchen };
573b543e467SCyrille Pitchen 
574b543e467SCyrille Pitchen static int atmel_i2s_sama5d2_mck_init(struct atmel_i2s_dev *dev,
575b543e467SCyrille Pitchen 				      struct device_node *np)
576b543e467SCyrille Pitchen {
577b543e467SCyrille Pitchen 	struct clk *muxclk;
578b543e467SCyrille Pitchen 	int err;
579b543e467SCyrille Pitchen 
580b543e467SCyrille Pitchen 	if (!dev->gclk)
581b543e467SCyrille Pitchen 		return 0;
582b543e467SCyrille Pitchen 
583b543e467SCyrille Pitchen 	/* muxclk is optional, so we return error for probe defer only */
584b543e467SCyrille Pitchen 	muxclk = devm_clk_get(dev->dev, "muxclk");
585b543e467SCyrille Pitchen 	if (IS_ERR(muxclk)) {
586b543e467SCyrille Pitchen 		err = PTR_ERR(muxclk);
587b543e467SCyrille Pitchen 		if (err == -EPROBE_DEFER)
588b543e467SCyrille Pitchen 			return -EPROBE_DEFER;
589f4bf1f4dSCodrin Ciubotariu 		dev_dbg(dev->dev,
590b543e467SCyrille Pitchen 			"failed to get the I2S clock control: %d\n", err);
591b543e467SCyrille Pitchen 		return 0;
592b543e467SCyrille Pitchen 	}
593b543e467SCyrille Pitchen 
594b543e467SCyrille Pitchen 	return clk_set_parent(muxclk, dev->gclk);
595b543e467SCyrille Pitchen }
596b543e467SCyrille Pitchen 
597b543e467SCyrille Pitchen static const struct atmel_i2s_caps atmel_i2s_sama5d2_caps = {
598b543e467SCyrille Pitchen 	.mck_init = atmel_i2s_sama5d2_mck_init,
599b543e467SCyrille Pitchen };
600b543e467SCyrille Pitchen 
601b543e467SCyrille Pitchen static const struct of_device_id atmel_i2s_dt_ids[] = {
602b543e467SCyrille Pitchen 	{
603b543e467SCyrille Pitchen 		.compatible = "atmel,sama5d2-i2s",
604b543e467SCyrille Pitchen 		.data = (void *)&atmel_i2s_sama5d2_caps,
605b543e467SCyrille Pitchen 	},
606b543e467SCyrille Pitchen 
607b543e467SCyrille Pitchen 	{ /* sentinel */ }
608b543e467SCyrille Pitchen };
609b543e467SCyrille Pitchen 
610b543e467SCyrille Pitchen MODULE_DEVICE_TABLE(of, atmel_i2s_dt_ids);
611b543e467SCyrille Pitchen 
612b543e467SCyrille Pitchen static int atmel_i2s_probe(struct platform_device *pdev)
613b543e467SCyrille Pitchen {
614b543e467SCyrille Pitchen 	struct device_node *np = pdev->dev.of_node;
615b543e467SCyrille Pitchen 	const struct of_device_id *match;
616b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev;
617b543e467SCyrille Pitchen 	struct resource *mem;
618b543e467SCyrille Pitchen 	struct regmap *regmap;
619b543e467SCyrille Pitchen 	void __iomem *base;
620b543e467SCyrille Pitchen 	int irq;
6216692dc07SPierre-Louis Bossart 	int err;
622b543e467SCyrille Pitchen 	unsigned int pcm_flags = 0;
623b543e467SCyrille Pitchen 	unsigned int version;
624b543e467SCyrille Pitchen 
625b543e467SCyrille Pitchen 	/* Get memory for driver data. */
626b543e467SCyrille Pitchen 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
627b543e467SCyrille Pitchen 	if (!dev)
628b543e467SCyrille Pitchen 		return -ENOMEM;
629b543e467SCyrille Pitchen 
630b543e467SCyrille Pitchen 	/* Get hardware capabilities. */
631b543e467SCyrille Pitchen 	match = of_match_node(atmel_i2s_dt_ids, np);
632b543e467SCyrille Pitchen 	if (match)
633b543e467SCyrille Pitchen 		dev->caps = match->data;
634b543e467SCyrille Pitchen 
635b543e467SCyrille Pitchen 	/* Map I/O registers. */
63639175acdSYang Yingliang 	base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
637b543e467SCyrille Pitchen 	if (IS_ERR(base))
638b543e467SCyrille Pitchen 		return PTR_ERR(base);
639b543e467SCyrille Pitchen 
640b543e467SCyrille Pitchen 	regmap = devm_regmap_init_mmio(&pdev->dev, base,
641b543e467SCyrille Pitchen 				       &atmel_i2s_regmap_config);
642b543e467SCyrille Pitchen 	if (IS_ERR(regmap))
643b543e467SCyrille Pitchen 		return PTR_ERR(regmap);
644b543e467SCyrille Pitchen 
645b543e467SCyrille Pitchen 	/* Request IRQ. */
646b543e467SCyrille Pitchen 	irq = platform_get_irq(pdev, 0);
647b543e467SCyrille Pitchen 	if (irq < 0)
648b543e467SCyrille Pitchen 		return irq;
649b543e467SCyrille Pitchen 
650b543e467SCyrille Pitchen 	err = devm_request_irq(&pdev->dev, irq, atmel_i2s_interrupt, 0,
651b543e467SCyrille Pitchen 			       dev_name(&pdev->dev), dev);
652b543e467SCyrille Pitchen 	if (err)
653b543e467SCyrille Pitchen 		return err;
654b543e467SCyrille Pitchen 
655b543e467SCyrille Pitchen 	/* Get the peripheral clock. */
656b543e467SCyrille Pitchen 	dev->pclk = devm_clk_get(&pdev->dev, "pclk");
657b543e467SCyrille Pitchen 	if (IS_ERR(dev->pclk)) {
658b543e467SCyrille Pitchen 		err = PTR_ERR(dev->pclk);
659b543e467SCyrille Pitchen 		dev_err(&pdev->dev,
660b543e467SCyrille Pitchen 			"failed to get the peripheral clock: %d\n", err);
661b543e467SCyrille Pitchen 		return err;
662b543e467SCyrille Pitchen 	}
663b543e467SCyrille Pitchen 
66473ad0df5SCodrin Ciubotariu 	/* Get audio clock to generate the I2S Master Clock (I2S_MCK) */
665b543e467SCyrille Pitchen 	dev->gclk = devm_clk_get(&pdev->dev, "gclk");
66673ad0df5SCodrin Ciubotariu 	if (IS_ERR(dev->gclk)) {
66773ad0df5SCodrin Ciubotariu 		if (PTR_ERR(dev->gclk) == -EPROBE_DEFER)
668b543e467SCyrille Pitchen 			return -EPROBE_DEFER;
669b543e467SCyrille Pitchen 		/* Master Mode not supported */
670b543e467SCyrille Pitchen 		dev->gclk = NULL;
671b543e467SCyrille Pitchen 	}
672b543e467SCyrille Pitchen 	dev->dev = &pdev->dev;
673b543e467SCyrille Pitchen 	dev->regmap = regmap;
674b543e467SCyrille Pitchen 	platform_set_drvdata(pdev, dev);
675b543e467SCyrille Pitchen 
676b543e467SCyrille Pitchen 	/* Do hardware specific settings to initialize I2S_MCK generator */
677b543e467SCyrille Pitchen 	if (dev->caps && dev->caps->mck_init) {
678b543e467SCyrille Pitchen 		err = dev->caps->mck_init(dev, np);
679b543e467SCyrille Pitchen 		if (err)
680b543e467SCyrille Pitchen 			return err;
681b543e467SCyrille Pitchen 	}
682b543e467SCyrille Pitchen 
683b543e467SCyrille Pitchen 	/* Enable the peripheral clock. */
684b543e467SCyrille Pitchen 	err = clk_prepare_enable(dev->pclk);
685b543e467SCyrille Pitchen 	if (err)
686b543e467SCyrille Pitchen 		return err;
687b543e467SCyrille Pitchen 
688b543e467SCyrille Pitchen 	/* Get IP version. */
689b543e467SCyrille Pitchen 	regmap_read(dev->regmap, ATMEL_I2SC_VERSION, &version);
690b543e467SCyrille Pitchen 	dev_info(&pdev->dev, "hw version: %#x\n", version);
691b543e467SCyrille Pitchen 
692b543e467SCyrille Pitchen 	/* Enable error interrupts. */
693b543e467SCyrille Pitchen 	regmap_write(dev->regmap, ATMEL_I2SC_IER,
694b543e467SCyrille Pitchen 		     ATMEL_I2SC_INT_RXOR | ATMEL_I2SC_INT_TXUR);
695b543e467SCyrille Pitchen 
696b543e467SCyrille Pitchen 	err = devm_snd_soc_register_component(&pdev->dev,
697b543e467SCyrille Pitchen 					      &atmel_i2s_component,
698b543e467SCyrille Pitchen 					      &atmel_i2s_dai, 1);
699b543e467SCyrille Pitchen 	if (err) {
700b543e467SCyrille Pitchen 		dev_err(&pdev->dev, "failed to register DAI: %d\n", err);
701b543e467SCyrille Pitchen 		clk_disable_unprepare(dev->pclk);
702b543e467SCyrille Pitchen 		return err;
703b543e467SCyrille Pitchen 	}
704b543e467SCyrille Pitchen 
705b543e467SCyrille Pitchen 	/* Prepare DMA config. */
706b543e467SCyrille Pitchen 	dev->playback.addr	= (dma_addr_t)mem->start + ATMEL_I2SC_THR;
707b543e467SCyrille Pitchen 	dev->playback.maxburst	= 1;
708b543e467SCyrille Pitchen 	dev->capture.addr	= (dma_addr_t)mem->start + ATMEL_I2SC_RHR;
709b543e467SCyrille Pitchen 	dev->capture.maxburst	= 1;
710b543e467SCyrille Pitchen 
711b543e467SCyrille Pitchen 	if (of_property_match_string(np, "dma-names", "rx-tx") == 0)
712b543e467SCyrille Pitchen 		pcm_flags |= SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX;
713b543e467SCyrille Pitchen 	err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, pcm_flags);
714b543e467SCyrille Pitchen 	if (err) {
715b543e467SCyrille Pitchen 		dev_err(&pdev->dev, "failed to register PCM: %d\n", err);
716b543e467SCyrille Pitchen 		clk_disable_unprepare(dev->pclk);
717b543e467SCyrille Pitchen 		return err;
718b543e467SCyrille Pitchen 	}
719b543e467SCyrille Pitchen 
720b543e467SCyrille Pitchen 	return 0;
721b543e467SCyrille Pitchen }
722b543e467SCyrille Pitchen 
723d0486266SUwe Kleine-König static void atmel_i2s_remove(struct platform_device *pdev)
724b543e467SCyrille Pitchen {
725b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = platform_get_drvdata(pdev);
726b543e467SCyrille Pitchen 
727b543e467SCyrille Pitchen 	clk_disable_unprepare(dev->pclk);
728b543e467SCyrille Pitchen }
729b543e467SCyrille Pitchen 
730b543e467SCyrille Pitchen static struct platform_driver atmel_i2s_driver = {
731b543e467SCyrille Pitchen 	.driver		= {
732b543e467SCyrille Pitchen 		.name	= "atmel_i2s",
73367ed7812SRuan Jinjie 		.of_match_table	= atmel_i2s_dt_ids,
734b543e467SCyrille Pitchen 	},
735b543e467SCyrille Pitchen 	.probe		= atmel_i2s_probe,
736*130af75bSUwe Kleine-König 	.remove		= atmel_i2s_remove,
737b543e467SCyrille Pitchen };
738b543e467SCyrille Pitchen module_platform_driver(atmel_i2s_driver);
739b543e467SCyrille Pitchen 
740b543e467SCyrille Pitchen MODULE_DESCRIPTION("Atmel I2S Controller driver");
741b543e467SCyrille Pitchen MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@atmel.com>");
742b543e467SCyrille Pitchen MODULE_LICENSE("GPL v2");
743