xref: /linux/sound/soc/atmel/atmel-i2s.c (revision 4a8cf938d5b6ee22c5a0bec84efb4b8068410ff4)
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
166b543e467SCyrille Pitchen 
167b543e467SCyrille Pitchen /* mck = (32 * (imckfs+1) / (imckdiv+1)) * fs */
168b543e467SCyrille Pitchen static const struct atmel_i2s_gck_param gck_params[] = {
169b543e467SCyrille Pitchen 	/* mck = 12.288MHz */
170b543e467SCyrille Pitchen 	{  8000, I2S_MCK_12M288, 0, 47},	/* mck = 1536 fs */
171b543e467SCyrille Pitchen 	{ 16000, I2S_MCK_12M288, 1, 47},	/* mck =  768 fs */
172b543e467SCyrille Pitchen 	{ 24000, I2S_MCK_12M288, 3, 63},	/* mck =  512 fs */
173b543e467SCyrille Pitchen 	{ 32000, I2S_MCK_12M288, 3, 47},	/* mck =  384 fs */
174b543e467SCyrille Pitchen 	{ 48000, I2S_MCK_12M288, 7, 63},	/* mck =  256 fs */
175b543e467SCyrille Pitchen 	{ 64000, I2S_MCK_12M288, 7, 47},	/* mck =  192 fs */
176b543e467SCyrille Pitchen 	{ 96000, I2S_MCK_12M288, 7, 31},	/* mck =  128 fs */
177b543e467SCyrille Pitchen 	{192000, I2S_MCK_12M288, 7, 15},	/* mck =   64 fs */
178b543e467SCyrille Pitchen 
179b543e467SCyrille Pitchen 	/* mck = 11.2896MHz */
180b543e467SCyrille Pitchen 	{ 11025, I2S_MCK_11M2896, 1, 63},	/* mck = 1024 fs */
181b543e467SCyrille Pitchen 	{ 22050, I2S_MCK_11M2896, 3, 63},	/* mck =  512 fs */
182b543e467SCyrille Pitchen 	{ 44100, I2S_MCK_11M2896, 7, 63},	/* mck =  256 fs */
183b543e467SCyrille Pitchen 	{ 88200, I2S_MCK_11M2896, 7, 31},	/* mck =  128 fs */
184b543e467SCyrille Pitchen 	{176400, I2S_MCK_11M2896, 7, 15},	/* mck =   64 fs */
185b543e467SCyrille Pitchen };
186b543e467SCyrille Pitchen 
187b543e467SCyrille Pitchen struct atmel_i2s_dev;
188b543e467SCyrille Pitchen 
189b543e467SCyrille Pitchen struct atmel_i2s_caps {
190b543e467SCyrille Pitchen 	int	(*mck_init)(struct atmel_i2s_dev *, struct device_node *np);
191b543e467SCyrille Pitchen };
192b543e467SCyrille Pitchen 
193b543e467SCyrille Pitchen struct atmel_i2s_dev {
194b543e467SCyrille Pitchen 	struct device				*dev;
195b543e467SCyrille Pitchen 	struct regmap				*regmap;
196b543e467SCyrille Pitchen 	struct clk				*pclk;
197b543e467SCyrille Pitchen 	struct clk				*gclk;
198b543e467SCyrille Pitchen 	struct snd_dmaengine_dai_dma_data	playback;
199b543e467SCyrille Pitchen 	struct snd_dmaengine_dai_dma_data	capture;
200b543e467SCyrille Pitchen 	unsigned int				fmt;
201b543e467SCyrille Pitchen 	const struct atmel_i2s_gck_param	*gck_param;
202b543e467SCyrille Pitchen 	const struct atmel_i2s_caps		*caps;
2033b7961a3SCodrin Ciubotariu 	int					clk_use_no;
204b543e467SCyrille Pitchen };
205b543e467SCyrille Pitchen 
206b543e467SCyrille Pitchen static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id)
207b543e467SCyrille Pitchen {
208b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = dev_id;
209b543e467SCyrille Pitchen 	unsigned int sr, imr, pending, ch, mask;
210b543e467SCyrille Pitchen 	irqreturn_t ret = IRQ_NONE;
211b543e467SCyrille Pitchen 
212b543e467SCyrille Pitchen 	regmap_read(dev->regmap, ATMEL_I2SC_SR, &sr);
213b543e467SCyrille Pitchen 	regmap_read(dev->regmap, ATMEL_I2SC_IMR, &imr);
214b543e467SCyrille Pitchen 	pending = sr & imr;
215b543e467SCyrille Pitchen 
216b543e467SCyrille Pitchen 	if (!pending)
217b543e467SCyrille Pitchen 		return IRQ_NONE;
218b543e467SCyrille Pitchen 
219b543e467SCyrille Pitchen 	if (pending & ATMEL_I2SC_INT_RXOR) {
220b543e467SCyrille Pitchen 		mask = ATMEL_I2SC_SR_RXOR;
221b543e467SCyrille Pitchen 
222b543e467SCyrille Pitchen 		for (ch = 0; ch < ATMEL_I2SC_MAX_TDM_CHANNELS; ++ch) {
223b543e467SCyrille Pitchen 			if (sr & ATMEL_I2SC_SR_RXORCH(ch)) {
224b543e467SCyrille Pitchen 				mask |= ATMEL_I2SC_SR_RXORCH(ch);
225b543e467SCyrille Pitchen 				dev_err(dev->dev,
226b543e467SCyrille Pitchen 					"RX overrun on channel %d\n", ch);
227b543e467SCyrille Pitchen 			}
228b543e467SCyrille Pitchen 		}
229b543e467SCyrille Pitchen 		regmap_write(dev->regmap, ATMEL_I2SC_SCR, mask);
230b543e467SCyrille Pitchen 		ret = IRQ_HANDLED;
231b543e467SCyrille Pitchen 	}
232b543e467SCyrille Pitchen 
233b543e467SCyrille Pitchen 	if (pending & ATMEL_I2SC_INT_TXUR) {
234b543e467SCyrille Pitchen 		mask = ATMEL_I2SC_SR_TXUR;
235b543e467SCyrille Pitchen 
236b543e467SCyrille Pitchen 		for (ch = 0; ch < ATMEL_I2SC_MAX_TDM_CHANNELS; ++ch) {
237b543e467SCyrille Pitchen 			if (sr & ATMEL_I2SC_SR_TXURCH(ch)) {
238b543e467SCyrille Pitchen 				mask |= ATMEL_I2SC_SR_TXURCH(ch);
239b543e467SCyrille Pitchen 				dev_err(dev->dev,
240b543e467SCyrille Pitchen 					"TX underrun on channel %d\n", ch);
241b543e467SCyrille Pitchen 			}
242b543e467SCyrille Pitchen 		}
243b543e467SCyrille Pitchen 		regmap_write(dev->regmap, ATMEL_I2SC_SCR, mask);
244b543e467SCyrille Pitchen 		ret = IRQ_HANDLED;
245b543e467SCyrille Pitchen 	}
246b543e467SCyrille Pitchen 
247b543e467SCyrille Pitchen 	return ret;
248b543e467SCyrille Pitchen }
249b543e467SCyrille Pitchen 
250b543e467SCyrille Pitchen #define ATMEL_I2S_RATES		SNDRV_PCM_RATE_8000_192000
251b543e467SCyrille Pitchen 
252b543e467SCyrille Pitchen #define ATMEL_I2S_FORMATS	(SNDRV_PCM_FMTBIT_S8 |		\
253b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S16_LE |	\
254b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S18_3LE |	\
255b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S20_3LE |	\
256b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S24_3LE |	\
257b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S24_LE |	\
258b543e467SCyrille Pitchen 				 SNDRV_PCM_FMTBIT_S32_LE)
259b543e467SCyrille Pitchen 
260b543e467SCyrille Pitchen static int atmel_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
261b543e467SCyrille Pitchen {
262b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
263b543e467SCyrille Pitchen 
264b543e467SCyrille Pitchen 	dev->fmt = fmt;
265b543e467SCyrille Pitchen 	return 0;
266b543e467SCyrille Pitchen }
267b543e467SCyrille Pitchen 
268b543e467SCyrille Pitchen static int atmel_i2s_prepare(struct snd_pcm_substream *substream,
269b543e467SCyrille Pitchen 			     struct snd_soc_dai *dai)
270b543e467SCyrille Pitchen {
271b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
272b543e467SCyrille Pitchen 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
273b543e467SCyrille Pitchen 	unsigned int rhr, sr = 0;
274b543e467SCyrille Pitchen 
275b543e467SCyrille Pitchen 	if (is_playback) {
276b543e467SCyrille Pitchen 		regmap_read(dev->regmap, ATMEL_I2SC_SR, &sr);
277b543e467SCyrille Pitchen 		if (sr & ATMEL_I2SC_SR_RXRDY) {
278b543e467SCyrille Pitchen 			/*
279b543e467SCyrille Pitchen 			 * The RX Ready flag should not be set. However if here,
280b543e467SCyrille Pitchen 			 * we flush (read) the Receive Holding Register to start
281b543e467SCyrille Pitchen 			 * from a clean state.
282b543e467SCyrille Pitchen 			 */
283b543e467SCyrille Pitchen 			dev_dbg(dev->dev, "RXRDY is set\n");
284b543e467SCyrille Pitchen 			regmap_read(dev->regmap, ATMEL_I2SC_RHR, &rhr);
285b543e467SCyrille Pitchen 		}
286b543e467SCyrille Pitchen 	}
287b543e467SCyrille Pitchen 
288b543e467SCyrille Pitchen 	return 0;
289b543e467SCyrille Pitchen }
290b543e467SCyrille Pitchen 
291b543e467SCyrille Pitchen static int atmel_i2s_get_gck_param(struct atmel_i2s_dev *dev, int fs)
292b543e467SCyrille Pitchen {
293b543e467SCyrille Pitchen 	int i, best;
294b543e467SCyrille Pitchen 
29573ad0df5SCodrin Ciubotariu 	if (!dev->gclk) {
296b543e467SCyrille Pitchen 		dev_err(dev->dev, "cannot generate the I2S Master Clock\n");
297b543e467SCyrille Pitchen 		return -EINVAL;
298b543e467SCyrille Pitchen 	}
299b543e467SCyrille Pitchen 
300b543e467SCyrille Pitchen 	/*
301b543e467SCyrille Pitchen 	 * Find the best possible settings to generate the I2S Master Clock
302b543e467SCyrille Pitchen 	 * from the PLL Audio.
303b543e467SCyrille Pitchen 	 */
304b543e467SCyrille Pitchen 	dev->gck_param = NULL;
305b543e467SCyrille Pitchen 	best = INT_MAX;
306b543e467SCyrille Pitchen 	for (i = 0; i < ARRAY_SIZE(gck_params); ++i) {
307b543e467SCyrille Pitchen 		const struct atmel_i2s_gck_param *gck_param = &gck_params[i];
308b543e467SCyrille Pitchen 		int val = abs(fs - gck_param->fs);
309b543e467SCyrille Pitchen 
310b543e467SCyrille Pitchen 		if (val < best) {
311b543e467SCyrille Pitchen 			best = val;
312b543e467SCyrille Pitchen 			dev->gck_param = gck_param;
313b543e467SCyrille Pitchen 		}
314b543e467SCyrille Pitchen 	}
315b543e467SCyrille Pitchen 
316b543e467SCyrille Pitchen 	return 0;
317b543e467SCyrille Pitchen }
318b543e467SCyrille Pitchen 
319b543e467SCyrille Pitchen static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
320b543e467SCyrille Pitchen 			       struct snd_pcm_hw_params *params,
321b543e467SCyrille Pitchen 			       struct snd_soc_dai *dai)
322b543e467SCyrille Pitchen {
323b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
324b543e467SCyrille Pitchen 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
3253b7961a3SCodrin Ciubotariu 	unsigned int mr = 0, mr_mask;
326b543e467SCyrille Pitchen 	int ret;
327b543e467SCyrille Pitchen 
3283b7961a3SCodrin Ciubotariu 	mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK |
3293b7961a3SCodrin Ciubotariu 		ATMEL_I2SC_MR_DATALENGTH_MASK;
3303b7961a3SCodrin Ciubotariu 	if (is_playback)
3313b7961a3SCodrin Ciubotariu 		mr_mask |= ATMEL_I2SC_MR_TXMONO;
3323b7961a3SCodrin Ciubotariu 	else
3333b7961a3SCodrin Ciubotariu 		mr_mask |= ATMEL_I2SC_MR_RXMONO;
3343b7961a3SCodrin Ciubotariu 
335b543e467SCyrille Pitchen 	switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
336b543e467SCyrille Pitchen 	case SND_SOC_DAIFMT_I2S:
337b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_FORMAT_I2S;
338b543e467SCyrille Pitchen 		break;
339b543e467SCyrille Pitchen 
340b543e467SCyrille Pitchen 	default:
341b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported bus format\n");
342b543e467SCyrille Pitchen 		return -EINVAL;
343b543e467SCyrille Pitchen 	}
344b543e467SCyrille Pitchen 
345*4a8cf938SMark Brown 	switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
346*4a8cf938SMark Brown 	case SND_SOC_DAIFMT_CBC_CFC:
347b543e467SCyrille Pitchen 		/* codec is slave, so cpu is master */
348b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_MODE_MASTER;
349b543e467SCyrille Pitchen 		ret = atmel_i2s_get_gck_param(dev, params_rate(params));
350b543e467SCyrille Pitchen 		if (ret)
351b543e467SCyrille Pitchen 			return ret;
352b543e467SCyrille Pitchen 		break;
353b543e467SCyrille Pitchen 
354*4a8cf938SMark Brown 	case SND_SOC_DAIFMT_CBP_CFP:
355b543e467SCyrille Pitchen 		/* codec is master, so cpu is slave */
356b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_MODE_SLAVE;
357b543e467SCyrille Pitchen 		dev->gck_param = NULL;
358b543e467SCyrille Pitchen 		break;
359b543e467SCyrille Pitchen 
360b543e467SCyrille Pitchen 	default:
361b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported master/slave mode\n");
362b543e467SCyrille Pitchen 		return -EINVAL;
363b543e467SCyrille Pitchen 	}
364b543e467SCyrille Pitchen 
365b543e467SCyrille Pitchen 	switch (params_channels(params)) {
366b543e467SCyrille Pitchen 	case 1:
367b543e467SCyrille Pitchen 		if (is_playback)
368b543e467SCyrille Pitchen 			mr |= ATMEL_I2SC_MR_TXMONO;
369b543e467SCyrille Pitchen 		else
370b543e467SCyrille Pitchen 			mr |= ATMEL_I2SC_MR_RXMONO;
371b543e467SCyrille Pitchen 		break;
372b543e467SCyrille Pitchen 	case 2:
373b543e467SCyrille Pitchen 		break;
374b543e467SCyrille Pitchen 	default:
375b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported number of audio channels\n");
376b543e467SCyrille Pitchen 		return -EINVAL;
377b543e467SCyrille Pitchen 	}
378b543e467SCyrille Pitchen 
379b543e467SCyrille Pitchen 	switch (params_format(params)) {
380b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S8:
381b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_8_BITS;
382b543e467SCyrille Pitchen 		break;
383b543e467SCyrille Pitchen 
384b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S16_LE:
385b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_16_BITS;
386b543e467SCyrille Pitchen 		break;
387b543e467SCyrille Pitchen 
388b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S18_3LE:
389b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_18_BITS | ATMEL_I2SC_MR_IWS;
390b543e467SCyrille Pitchen 		break;
391b543e467SCyrille Pitchen 
392b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S20_3LE:
393b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_20_BITS | ATMEL_I2SC_MR_IWS;
394b543e467SCyrille Pitchen 		break;
395b543e467SCyrille Pitchen 
396b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S24_3LE:
397b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_24_BITS | ATMEL_I2SC_MR_IWS;
398b543e467SCyrille Pitchen 		break;
399b543e467SCyrille Pitchen 
400b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S24_LE:
401b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_24_BITS;
402b543e467SCyrille Pitchen 		break;
403b543e467SCyrille Pitchen 
404b543e467SCyrille Pitchen 	case SNDRV_PCM_FORMAT_S32_LE:
405b543e467SCyrille Pitchen 		mr |= ATMEL_I2SC_MR_DATALENGTH_32_BITS;
406b543e467SCyrille Pitchen 		break;
407b543e467SCyrille Pitchen 
408b543e467SCyrille Pitchen 	default:
409b543e467SCyrille Pitchen 		dev_err(dev->dev, "unsupported size/endianness for audio samples\n");
410b543e467SCyrille Pitchen 		return -EINVAL;
411b543e467SCyrille Pitchen 	}
412b543e467SCyrille Pitchen 
4133b7961a3SCodrin Ciubotariu 	return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
414b543e467SCyrille Pitchen }
415b543e467SCyrille Pitchen 
416b543e467SCyrille Pitchen static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
417b543e467SCyrille Pitchen 					  bool enabled)
418b543e467SCyrille Pitchen {
419b543e467SCyrille Pitchen 	unsigned int mr, mr_mask;
42073ad0df5SCodrin Ciubotariu 	unsigned long gclk_rate;
421b543e467SCyrille Pitchen 	int ret;
422b543e467SCyrille Pitchen 
423b543e467SCyrille Pitchen 	mr = 0;
424b543e467SCyrille Pitchen 	mr_mask = (ATMEL_I2SC_MR_IMCKDIV_MASK |
425b543e467SCyrille Pitchen 		   ATMEL_I2SC_MR_IMCKFS_MASK |
426b543e467SCyrille Pitchen 		   ATMEL_I2SC_MR_IMCKMODE_MASK);
427b543e467SCyrille Pitchen 
428b543e467SCyrille Pitchen 	if (!enabled) {
429b543e467SCyrille Pitchen 		/* Disable the I2S Master Clock generator. */
430b543e467SCyrille Pitchen 		ret = regmap_write(dev->regmap, ATMEL_I2SC_CR,
431b543e467SCyrille Pitchen 				   ATMEL_I2SC_CR_CKDIS);
432b543e467SCyrille Pitchen 		if (ret)
433b543e467SCyrille Pitchen 			return ret;
434b543e467SCyrille Pitchen 
435b543e467SCyrille Pitchen 		/* Reset the I2S Master Clock generator settings. */
436b543e467SCyrille Pitchen 		ret = regmap_update_bits(dev->regmap, ATMEL_I2SC_MR,
437b543e467SCyrille Pitchen 					 mr_mask, mr);
438b543e467SCyrille Pitchen 		if (ret)
439b543e467SCyrille Pitchen 			return ret;
440b543e467SCyrille Pitchen 
441b543e467SCyrille Pitchen 		/* Disable/unprepare the PMC generated clock. */
442b543e467SCyrille Pitchen 		clk_disable_unprepare(dev->gclk);
443b543e467SCyrille Pitchen 
444b543e467SCyrille Pitchen 		return 0;
445b543e467SCyrille Pitchen 	}
446b543e467SCyrille Pitchen 
447b543e467SCyrille Pitchen 	if (!dev->gck_param)
448b543e467SCyrille Pitchen 		return -EINVAL;
449b543e467SCyrille Pitchen 
45073ad0df5SCodrin Ciubotariu 	gclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
451b543e467SCyrille Pitchen 
45273ad0df5SCodrin Ciubotariu 	ret = clk_set_rate(dev->gclk, gclk_rate);
453b543e467SCyrille Pitchen 	if (ret)
454b543e467SCyrille Pitchen 		return ret;
455b543e467SCyrille Pitchen 
456b543e467SCyrille Pitchen 	ret = clk_prepare_enable(dev->gclk);
457b543e467SCyrille Pitchen 	if (ret)
458b543e467SCyrille Pitchen 		return ret;
459b543e467SCyrille Pitchen 
460b543e467SCyrille Pitchen 	/* Update the Mode Register to generate the I2S Master Clock. */
461b543e467SCyrille Pitchen 	mr |= ATMEL_I2SC_MR_IMCKDIV(dev->gck_param->imckdiv);
462b543e467SCyrille Pitchen 	mr |= ATMEL_I2SC_MR_IMCKFS(dev->gck_param->imckfs);
463b543e467SCyrille Pitchen 	mr |= ATMEL_I2SC_MR_IMCKMODE_I2SMCK;
464b543e467SCyrille Pitchen 	ret = regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
465b543e467SCyrille Pitchen 	if (ret)
466b543e467SCyrille Pitchen 		return ret;
467b543e467SCyrille Pitchen 
468b543e467SCyrille Pitchen 	/* Finally enable the I2S Master Clock generator. */
469b543e467SCyrille Pitchen 	return regmap_write(dev->regmap, ATMEL_I2SC_CR,
470b543e467SCyrille Pitchen 			    ATMEL_I2SC_CR_CKEN);
471b543e467SCyrille Pitchen }
472b543e467SCyrille Pitchen 
473b543e467SCyrille Pitchen static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
474b543e467SCyrille Pitchen 			     struct snd_soc_dai *dai)
475b543e467SCyrille Pitchen {
476b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
477b543e467SCyrille Pitchen 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
478b543e467SCyrille Pitchen 	bool is_master, mck_enabled;
479b543e467SCyrille Pitchen 	unsigned int cr, mr;
480b543e467SCyrille Pitchen 	int err;
481b543e467SCyrille Pitchen 
482b543e467SCyrille Pitchen 	switch (cmd) {
483b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_START:
484b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_RESUME:
485b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
486b543e467SCyrille Pitchen 		cr = is_playback ? ATMEL_I2SC_CR_TXEN : ATMEL_I2SC_CR_RXEN;
487b543e467SCyrille Pitchen 		mck_enabled = true;
488b543e467SCyrille Pitchen 		break;
489b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_STOP:
490b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_SUSPEND:
491b543e467SCyrille Pitchen 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
492b543e467SCyrille Pitchen 		cr = is_playback ? ATMEL_I2SC_CR_TXDIS : ATMEL_I2SC_CR_RXDIS;
493b543e467SCyrille Pitchen 		mck_enabled = false;
494b543e467SCyrille Pitchen 		break;
495b543e467SCyrille Pitchen 	default:
496b543e467SCyrille Pitchen 		return -EINVAL;
497b543e467SCyrille Pitchen 	}
498b543e467SCyrille Pitchen 
499b543e467SCyrille Pitchen 	/* Read the Mode Register to retrieve the master/slave state. */
500b543e467SCyrille Pitchen 	err = regmap_read(dev->regmap, ATMEL_I2SC_MR, &mr);
501b543e467SCyrille Pitchen 	if (err)
502b543e467SCyrille Pitchen 		return err;
503b543e467SCyrille Pitchen 	is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER;
504b543e467SCyrille Pitchen 
505b543e467SCyrille Pitchen 	/* If master starts, enable the audio clock. */
5063b7961a3SCodrin Ciubotariu 	if (is_master && mck_enabled) {
5073b7961a3SCodrin Ciubotariu 		if (!dev->clk_use_no) {
508b543e467SCyrille Pitchen 			err = atmel_i2s_switch_mck_generator(dev, true);
509b543e467SCyrille Pitchen 			if (err)
510b543e467SCyrille Pitchen 				return err;
5113b7961a3SCodrin Ciubotariu 		}
5123b7961a3SCodrin Ciubotariu 		dev->clk_use_no++;
5133b7961a3SCodrin Ciubotariu 	}
514b543e467SCyrille Pitchen 
515b543e467SCyrille Pitchen 	err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr);
516b543e467SCyrille Pitchen 	if (err)
517b543e467SCyrille Pitchen 		return err;
518b543e467SCyrille Pitchen 
519b543e467SCyrille Pitchen 	/* If master stops, disable the audio clock. */
5203b7961a3SCodrin Ciubotariu 	if (is_master && !mck_enabled) {
5213b7961a3SCodrin Ciubotariu 		if (dev->clk_use_no == 1) {
522b543e467SCyrille Pitchen 			err = atmel_i2s_switch_mck_generator(dev, false);
5233b7961a3SCodrin Ciubotariu 			if (err)
5243b7961a3SCodrin Ciubotariu 				return err;
5253b7961a3SCodrin Ciubotariu 		}
5263b7961a3SCodrin Ciubotariu 		dev->clk_use_no--;
5273b7961a3SCodrin Ciubotariu 	}
528b543e467SCyrille Pitchen 
529b543e467SCyrille Pitchen 	return err;
530b543e467SCyrille Pitchen }
531b543e467SCyrille Pitchen 
532b543e467SCyrille Pitchen static const struct snd_soc_dai_ops atmel_i2s_dai_ops = {
533b543e467SCyrille Pitchen 	.prepare	= atmel_i2s_prepare,
534b543e467SCyrille Pitchen 	.trigger	= atmel_i2s_trigger,
535b543e467SCyrille Pitchen 	.hw_params	= atmel_i2s_hw_params,
536b543e467SCyrille Pitchen 	.set_fmt	= atmel_i2s_set_dai_fmt,
537b543e467SCyrille Pitchen };
538b543e467SCyrille Pitchen 
539b543e467SCyrille Pitchen static int atmel_i2s_dai_probe(struct snd_soc_dai *dai)
540b543e467SCyrille Pitchen {
541b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
542b543e467SCyrille Pitchen 
543b543e467SCyrille Pitchen 	snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
544b543e467SCyrille Pitchen 	return 0;
545b543e467SCyrille Pitchen }
546b543e467SCyrille Pitchen 
547b543e467SCyrille Pitchen static struct snd_soc_dai_driver atmel_i2s_dai = {
548b543e467SCyrille Pitchen 	.probe	= atmel_i2s_dai_probe,
549b543e467SCyrille Pitchen 	.playback = {
550b543e467SCyrille Pitchen 		.channels_min = 1,
551b543e467SCyrille Pitchen 		.channels_max = 2,
552b543e467SCyrille Pitchen 		.rates = ATMEL_I2S_RATES,
553b543e467SCyrille Pitchen 		.formats = ATMEL_I2S_FORMATS,
554b543e467SCyrille Pitchen 	},
555b543e467SCyrille Pitchen 	.capture = {
556b543e467SCyrille Pitchen 		.channels_min = 1,
557b543e467SCyrille Pitchen 		.channels_max = 2,
558b543e467SCyrille Pitchen 		.rates = ATMEL_I2S_RATES,
559b543e467SCyrille Pitchen 		.formats = ATMEL_I2S_FORMATS,
560b543e467SCyrille Pitchen 	},
561b543e467SCyrille Pitchen 	.ops = &atmel_i2s_dai_ops,
562ba471f8dSKuninori Morimoto 	.symmetric_rate = 1,
563489a830aSCodrin Ciubotariu 	.symmetric_sample_bits = 1,
564b543e467SCyrille Pitchen };
565b543e467SCyrille Pitchen 
566b543e467SCyrille Pitchen static const struct snd_soc_component_driver atmel_i2s_component = {
567b543e467SCyrille Pitchen 	.name	= "atmel-i2s",
568b543e467SCyrille Pitchen };
569b543e467SCyrille Pitchen 
570b543e467SCyrille Pitchen static int atmel_i2s_sama5d2_mck_init(struct atmel_i2s_dev *dev,
571b543e467SCyrille Pitchen 				      struct device_node *np)
572b543e467SCyrille Pitchen {
573b543e467SCyrille Pitchen 	struct clk *muxclk;
574b543e467SCyrille Pitchen 	int err;
575b543e467SCyrille Pitchen 
576b543e467SCyrille Pitchen 	if (!dev->gclk)
577b543e467SCyrille Pitchen 		return 0;
578b543e467SCyrille Pitchen 
579b543e467SCyrille Pitchen 	/* muxclk is optional, so we return error for probe defer only */
580b543e467SCyrille Pitchen 	muxclk = devm_clk_get(dev->dev, "muxclk");
581b543e467SCyrille Pitchen 	if (IS_ERR(muxclk)) {
582b543e467SCyrille Pitchen 		err = PTR_ERR(muxclk);
583b543e467SCyrille Pitchen 		if (err == -EPROBE_DEFER)
584b543e467SCyrille Pitchen 			return -EPROBE_DEFER;
585f4bf1f4dSCodrin Ciubotariu 		dev_dbg(dev->dev,
586b543e467SCyrille Pitchen 			"failed to get the I2S clock control: %d\n", err);
587b543e467SCyrille Pitchen 		return 0;
588b543e467SCyrille Pitchen 	}
589b543e467SCyrille Pitchen 
590b543e467SCyrille Pitchen 	return clk_set_parent(muxclk, dev->gclk);
591b543e467SCyrille Pitchen }
592b543e467SCyrille Pitchen 
593b543e467SCyrille Pitchen static const struct atmel_i2s_caps atmel_i2s_sama5d2_caps = {
594b543e467SCyrille Pitchen 	.mck_init = atmel_i2s_sama5d2_mck_init,
595b543e467SCyrille Pitchen };
596b543e467SCyrille Pitchen 
597b543e467SCyrille Pitchen static const struct of_device_id atmel_i2s_dt_ids[] = {
598b543e467SCyrille Pitchen 	{
599b543e467SCyrille Pitchen 		.compatible = "atmel,sama5d2-i2s",
600b543e467SCyrille Pitchen 		.data = (void *)&atmel_i2s_sama5d2_caps,
601b543e467SCyrille Pitchen 	},
602b543e467SCyrille Pitchen 
603b543e467SCyrille Pitchen 	{ /* sentinel */ }
604b543e467SCyrille Pitchen };
605b543e467SCyrille Pitchen 
606b543e467SCyrille Pitchen MODULE_DEVICE_TABLE(of, atmel_i2s_dt_ids);
607b543e467SCyrille Pitchen 
608b543e467SCyrille Pitchen static int atmel_i2s_probe(struct platform_device *pdev)
609b543e467SCyrille Pitchen {
610b543e467SCyrille Pitchen 	struct device_node *np = pdev->dev.of_node;
611b543e467SCyrille Pitchen 	const struct of_device_id *match;
612b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev;
613b543e467SCyrille Pitchen 	struct resource *mem;
614b543e467SCyrille Pitchen 	struct regmap *regmap;
615b543e467SCyrille Pitchen 	void __iomem *base;
616b543e467SCyrille Pitchen 	int irq;
6176692dc07SPierre-Louis Bossart 	int err;
618b543e467SCyrille Pitchen 	unsigned int pcm_flags = 0;
619b543e467SCyrille Pitchen 	unsigned int version;
620b543e467SCyrille Pitchen 
621b543e467SCyrille Pitchen 	/* Get memory for driver data. */
622b543e467SCyrille Pitchen 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
623b543e467SCyrille Pitchen 	if (!dev)
624b543e467SCyrille Pitchen 		return -ENOMEM;
625b543e467SCyrille Pitchen 
626b543e467SCyrille Pitchen 	/* Get hardware capabilities. */
627b543e467SCyrille Pitchen 	match = of_match_node(atmel_i2s_dt_ids, np);
628b543e467SCyrille Pitchen 	if (match)
629b543e467SCyrille Pitchen 		dev->caps = match->data;
630b543e467SCyrille Pitchen 
631b543e467SCyrille Pitchen 	/* Map I/O registers. */
63239175acdSYang Yingliang 	base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
633b543e467SCyrille Pitchen 	if (IS_ERR(base))
634b543e467SCyrille Pitchen 		return PTR_ERR(base);
635b543e467SCyrille Pitchen 
636b543e467SCyrille Pitchen 	regmap = devm_regmap_init_mmio(&pdev->dev, base,
637b543e467SCyrille Pitchen 				       &atmel_i2s_regmap_config);
638b543e467SCyrille Pitchen 	if (IS_ERR(regmap))
639b543e467SCyrille Pitchen 		return PTR_ERR(regmap);
640b543e467SCyrille Pitchen 
641b543e467SCyrille Pitchen 	/* Request IRQ. */
642b543e467SCyrille Pitchen 	irq = platform_get_irq(pdev, 0);
643b543e467SCyrille Pitchen 	if (irq < 0)
644b543e467SCyrille Pitchen 		return irq;
645b543e467SCyrille Pitchen 
646b543e467SCyrille Pitchen 	err = devm_request_irq(&pdev->dev, irq, atmel_i2s_interrupt, 0,
647b543e467SCyrille Pitchen 			       dev_name(&pdev->dev), dev);
648b543e467SCyrille Pitchen 	if (err)
649b543e467SCyrille Pitchen 		return err;
650b543e467SCyrille Pitchen 
651b543e467SCyrille Pitchen 	/* Get the peripheral clock. */
652b543e467SCyrille Pitchen 	dev->pclk = devm_clk_get(&pdev->dev, "pclk");
653b543e467SCyrille Pitchen 	if (IS_ERR(dev->pclk)) {
654b543e467SCyrille Pitchen 		err = PTR_ERR(dev->pclk);
655b543e467SCyrille Pitchen 		dev_err(&pdev->dev,
656b543e467SCyrille Pitchen 			"failed to get the peripheral clock: %d\n", err);
657b543e467SCyrille Pitchen 		return err;
658b543e467SCyrille Pitchen 	}
659b543e467SCyrille Pitchen 
66073ad0df5SCodrin Ciubotariu 	/* Get audio clock to generate the I2S Master Clock (I2S_MCK) */
661b543e467SCyrille Pitchen 	dev->gclk = devm_clk_get(&pdev->dev, "gclk");
66273ad0df5SCodrin Ciubotariu 	if (IS_ERR(dev->gclk)) {
66373ad0df5SCodrin Ciubotariu 		if (PTR_ERR(dev->gclk) == -EPROBE_DEFER)
664b543e467SCyrille Pitchen 			return -EPROBE_DEFER;
665b543e467SCyrille Pitchen 		/* Master Mode not supported */
666b543e467SCyrille Pitchen 		dev->gclk = NULL;
667b543e467SCyrille Pitchen 	}
668b543e467SCyrille Pitchen 	dev->dev = &pdev->dev;
669b543e467SCyrille Pitchen 	dev->regmap = regmap;
670b543e467SCyrille Pitchen 	platform_set_drvdata(pdev, dev);
671b543e467SCyrille Pitchen 
672b543e467SCyrille Pitchen 	/* Do hardware specific settings to initialize I2S_MCK generator */
673b543e467SCyrille Pitchen 	if (dev->caps && dev->caps->mck_init) {
674b543e467SCyrille Pitchen 		err = dev->caps->mck_init(dev, np);
675b543e467SCyrille Pitchen 		if (err)
676b543e467SCyrille Pitchen 			return err;
677b543e467SCyrille Pitchen 	}
678b543e467SCyrille Pitchen 
679b543e467SCyrille Pitchen 	/* Enable the peripheral clock. */
680b543e467SCyrille Pitchen 	err = clk_prepare_enable(dev->pclk);
681b543e467SCyrille Pitchen 	if (err)
682b543e467SCyrille Pitchen 		return err;
683b543e467SCyrille Pitchen 
684b543e467SCyrille Pitchen 	/* Get IP version. */
685b543e467SCyrille Pitchen 	regmap_read(dev->regmap, ATMEL_I2SC_VERSION, &version);
686b543e467SCyrille Pitchen 	dev_info(&pdev->dev, "hw version: %#x\n", version);
687b543e467SCyrille Pitchen 
688b543e467SCyrille Pitchen 	/* Enable error interrupts. */
689b543e467SCyrille Pitchen 	regmap_write(dev->regmap, ATMEL_I2SC_IER,
690b543e467SCyrille Pitchen 		     ATMEL_I2SC_INT_RXOR | ATMEL_I2SC_INT_TXUR);
691b543e467SCyrille Pitchen 
692b543e467SCyrille Pitchen 	err = devm_snd_soc_register_component(&pdev->dev,
693b543e467SCyrille Pitchen 					      &atmel_i2s_component,
694b543e467SCyrille Pitchen 					      &atmel_i2s_dai, 1);
695b543e467SCyrille Pitchen 	if (err) {
696b543e467SCyrille Pitchen 		dev_err(&pdev->dev, "failed to register DAI: %d\n", err);
697b543e467SCyrille Pitchen 		clk_disable_unprepare(dev->pclk);
698b543e467SCyrille Pitchen 		return err;
699b543e467SCyrille Pitchen 	}
700b543e467SCyrille Pitchen 
701b543e467SCyrille Pitchen 	/* Prepare DMA config. */
702b543e467SCyrille Pitchen 	dev->playback.addr	= (dma_addr_t)mem->start + ATMEL_I2SC_THR;
703b543e467SCyrille Pitchen 	dev->playback.maxburst	= 1;
704b543e467SCyrille Pitchen 	dev->capture.addr	= (dma_addr_t)mem->start + ATMEL_I2SC_RHR;
705b543e467SCyrille Pitchen 	dev->capture.maxburst	= 1;
706b543e467SCyrille Pitchen 
707b543e467SCyrille Pitchen 	if (of_property_match_string(np, "dma-names", "rx-tx") == 0)
708b543e467SCyrille Pitchen 		pcm_flags |= SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX;
709b543e467SCyrille Pitchen 	err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, pcm_flags);
710b543e467SCyrille Pitchen 	if (err) {
711b543e467SCyrille Pitchen 		dev_err(&pdev->dev, "failed to register PCM: %d\n", err);
712b543e467SCyrille Pitchen 		clk_disable_unprepare(dev->pclk);
713b543e467SCyrille Pitchen 		return err;
714b543e467SCyrille Pitchen 	}
715b543e467SCyrille Pitchen 
716b543e467SCyrille Pitchen 	return 0;
717b543e467SCyrille Pitchen }
718b543e467SCyrille Pitchen 
719b543e467SCyrille Pitchen static int atmel_i2s_remove(struct platform_device *pdev)
720b543e467SCyrille Pitchen {
721b543e467SCyrille Pitchen 	struct atmel_i2s_dev *dev = platform_get_drvdata(pdev);
722b543e467SCyrille Pitchen 
723b543e467SCyrille Pitchen 	clk_disable_unprepare(dev->pclk);
724b543e467SCyrille Pitchen 
725b543e467SCyrille Pitchen 	return 0;
726b543e467SCyrille Pitchen }
727b543e467SCyrille Pitchen 
728b543e467SCyrille Pitchen static struct platform_driver atmel_i2s_driver = {
729b543e467SCyrille Pitchen 	.driver		= {
730b543e467SCyrille Pitchen 		.name	= "atmel_i2s",
731b543e467SCyrille Pitchen 		.of_match_table	= of_match_ptr(atmel_i2s_dt_ids),
732b543e467SCyrille Pitchen 	},
733b543e467SCyrille Pitchen 	.probe		= atmel_i2s_probe,
734b543e467SCyrille Pitchen 	.remove		= atmel_i2s_remove,
735b543e467SCyrille Pitchen };
736b543e467SCyrille Pitchen module_platform_driver(atmel_i2s_driver);
737b543e467SCyrille Pitchen 
738b543e467SCyrille Pitchen MODULE_DESCRIPTION("Atmel I2S Controller driver");
739b543e467SCyrille Pitchen MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@atmel.com>");
740b543e467SCyrille Pitchen MODULE_LICENSE("GPL v2");
741