1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2012 Samsung Electronics
4  * R. Chandrasekar <rcsekar@samsung.com>
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <i2s.h>
10 #include <log.h>
11 #include <sound.h>
12 #include <asm/arch/clk.h>
13 #include <asm/arch/pinmux.h>
14 #include <asm/arch/i2s-regs.h>
15 #include <asm/io.h>
16 
17 #define FIC_TX2COUNT(x)		(((x) >>  24) & 0xf)
18 #define FIC_TX1COUNT(x)		(((x) >>  16) & 0xf)
19 #define FIC_TXCOUNT(x)		(((x) >>  8) & 0xf)
20 #define FIC_RXCOUNT(x)		(((x) >>  0) & 0xf)
21 #define FICS_TXCOUNT(x)		(((x) >>  8) & 0x7f)
22 
23 #define TIMEOUT_I2S_TX		100	/* i2s transfer timeout */
24 
25 /*
26  * Sets the frame size for I2S LR clock
27  *
28  * @param i2s_reg	i2s register address
29  * @param rfs		Frame Size
30  */
i2s_set_lr_framesize(struct i2s_reg * i2s_reg,unsigned int rfs)31 static void i2s_set_lr_framesize(struct i2s_reg *i2s_reg, unsigned int rfs)
32 {
33 	unsigned int mod = readl(&i2s_reg->mod);
34 
35 	mod &= ~MOD_RCLK_MASK;
36 
37 	switch (rfs) {
38 	case 768:
39 		mod |= MOD_RCLK_768FS;
40 		break;
41 	case 512:
42 		mod |= MOD_RCLK_512FS;
43 		break;
44 	case 384:
45 		mod |= MOD_RCLK_384FS;
46 		break;
47 	default:
48 		mod |= MOD_RCLK_256FS;
49 		break;
50 	}
51 
52 	writel(mod, &i2s_reg->mod);
53 }
54 
55 /*
56  * Sets the i2s transfer control
57  *
58  * @param i2s_reg	i2s register address
59  * @param on		1 enable tx , 0 disable tx transfer
60  */
i2s_txctrl(struct i2s_reg * i2s_reg,int on)61 static void i2s_txctrl(struct i2s_reg *i2s_reg, int on)
62 {
63 	unsigned int con = readl(&i2s_reg->con);
64 	unsigned int mod = readl(&i2s_reg->mod) & ~MOD_MASK;
65 
66 	if (on) {
67 		con |= CON_ACTIVE;
68 		con &= ~CON_TXCH_PAUSE;
69 	} else {
70 		con |=  CON_TXCH_PAUSE;
71 		con &= ~CON_ACTIVE;
72 	}
73 
74 	writel(mod, &i2s_reg->mod);
75 	writel(con, &i2s_reg->con);
76 }
77 
78 /*
79  * set the bit clock frame size (in multiples of LRCLK)
80  *
81  * @param i2s_reg	i2s register address
82  * @param bfs		bit Frame Size
83  */
i2s_set_bitclk_framesize(struct i2s_reg * i2s_reg,unsigned bfs)84 static void i2s_set_bitclk_framesize(struct i2s_reg *i2s_reg, unsigned bfs)
85 {
86 	unsigned int mod = readl(&i2s_reg->mod);
87 
88 	mod &= ~MOD_BCLK_MASK;
89 
90 	switch (bfs) {
91 	case 48:
92 		mod |= MOD_BCLK_48FS;
93 		break;
94 	case 32:
95 		mod |= MOD_BCLK_32FS;
96 		break;
97 	case 24:
98 		mod |= MOD_BCLK_24FS;
99 		break;
100 	case 16:
101 		mod |= MOD_BCLK_16FS;
102 		break;
103 	default:
104 		return;
105 	}
106 	writel(mod, &i2s_reg->mod);
107 }
108 
109 /*
110  * flushes the i2stx fifo
111  *
112  * @param i2s_reg	i2s register address
113  * @param flush		Tx fifo flush command (0x00 - do not flush
114  *				0x80 - flush tx fifo)
115  */
i2s_fifo(struct i2s_reg * i2s_reg,unsigned int flush)116 static void i2s_fifo(struct i2s_reg *i2s_reg, unsigned int flush)
117 {
118 	/* Flush the FIFO */
119 	setbits_le32(&i2s_reg->fic, flush);
120 	clrbits_le32(&i2s_reg->fic, flush);
121 }
122 
123 /*
124  * Set System Clock direction
125  *
126  * @param i2s_reg	i2s register address
127  * @param dir		Clock direction
128  *
129  * @return		int value 0 for success, -1 in case of error
130  */
i2s_set_sysclk_dir(struct i2s_reg * i2s_reg,int dir)131 static int i2s_set_sysclk_dir(struct i2s_reg *i2s_reg, int dir)
132 {
133 	unsigned int mod = readl(&i2s_reg->mod);
134 
135 	if (dir == SND_SOC_CLOCK_IN)
136 		mod |= MOD_CDCLKCON;
137 	else
138 		mod &= ~MOD_CDCLKCON;
139 
140 	writel(mod, &i2s_reg->mod);
141 
142 	return 0;
143 }
144 
145 /*
146  * Sets I2S Clcok format
147  *
148  * @param fmt		i2s clock properties
149  * @param i2s_reg	i2s register address
150  *
151  * @return		int value 0 for success, -1 in case of error
152  */
i2s_set_fmt(struct i2s_reg * i2s_reg,unsigned int fmt)153 static int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
154 {
155 	unsigned int mod = readl(&i2s_reg->mod);
156 	unsigned int tmp = 0;
157 	unsigned int ret = 0;
158 
159 	/* Format is priority */
160 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
161 	case SND_SOC_DAIFMT_RIGHT_J:
162 		tmp |= MOD_LR_RLOW;
163 		tmp |= MOD_SDF_MSB;
164 		break;
165 	case SND_SOC_DAIFMT_LEFT_J:
166 		tmp |= MOD_LR_RLOW;
167 		tmp |= MOD_SDF_LSB;
168 		break;
169 	case SND_SOC_DAIFMT_I2S:
170 		tmp |= MOD_SDF_IIS;
171 		break;
172 	default:
173 		debug("%s: Invalid format priority [0x%x]\n", __func__,
174 		      (fmt & SND_SOC_DAIFMT_FORMAT_MASK));
175 		return -ERANGE;
176 	}
177 
178 	/*
179 	 * INV flag is relative to the FORMAT flag - if set it simply
180 	 * flips the polarity specified by the Standard
181 	 */
182 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
183 	case SND_SOC_DAIFMT_NB_NF:
184 		break;
185 	case SND_SOC_DAIFMT_NB_IF:
186 		if (tmp & MOD_LR_RLOW)
187 			tmp &= ~MOD_LR_RLOW;
188 		else
189 			tmp |= MOD_LR_RLOW;
190 		break;
191 	default:
192 		debug("%s: Invalid clock ploarity input [0x%x]\n", __func__,
193 		      (fmt & SND_SOC_DAIFMT_INV_MASK));
194 		return -ERANGE;
195 	}
196 
197 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
198 	case SND_SOC_DAIFMT_CBS_CFS:
199 		tmp |= MOD_SLAVE;
200 		break;
201 	case SND_SOC_DAIFMT_CBM_CFM:
202 		/* Set default source clock in Master mode */
203 		ret = i2s_set_sysclk_dir(i2s_reg, SND_SOC_CLOCK_OUT);
204 		if (ret != 0) {
205 			debug("%s:set i2s clock direction failed\n", __func__);
206 			return ret;
207 		}
208 		break;
209 	default:
210 		debug("%s: Invalid master selection [0x%x]\n", __func__,
211 		      (fmt & SND_SOC_DAIFMT_MASTER_MASK));
212 		return -ERANGE;
213 	}
214 
215 	mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE);
216 	mod |= tmp;
217 	writel(mod, &i2s_reg->mod);
218 
219 	return 0;
220 }
221 
222 /*
223  * Sets the sample width in bits
224  *
225  * @param blc		samplewidth (size of sample in bits)
226  * @param i2s_reg	i2s register address
227  *
228  * @return		int value 0 for success, -1 in case of error
229  */
i2s_set_samplesize(struct i2s_reg * i2s_reg,unsigned int blc)230 static int i2s_set_samplesize(struct i2s_reg *i2s_reg, unsigned int blc)
231 {
232 	unsigned int mod = readl(&i2s_reg->mod);
233 
234 	mod &= ~MOD_BLCP_MASK;
235 	mod &= ~MOD_BLC_MASK;
236 
237 	switch (blc) {
238 	case 8:
239 		mod |= MOD_BLCP_8BIT;
240 		mod |= MOD_BLC_8BIT;
241 		break;
242 	case 16:
243 		mod |= MOD_BLCP_16BIT;
244 		mod |= MOD_BLC_16BIT;
245 		break;
246 	case 24:
247 		mod |= MOD_BLCP_24BIT;
248 		mod |= MOD_BLC_24BIT;
249 		break;
250 	default:
251 		debug("%s: Invalid sample size input [0x%x]\n",
252 		      __func__, blc);
253 		return -ERANGE;
254 	}
255 	writel(mod, &i2s_reg->mod);
256 
257 	return 0;
258 }
259 
i2s_transfer_tx_data(struct i2s_uc_priv * pi2s_tx,void * data,uint data_size)260 int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, void *data,
261 			 uint data_size)
262 {
263 	struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address;
264 	u32 *ptr;
265 	int i;
266 	int start;
267 
268 	if (data_size < FIFO_LENGTH) {
269 		debug("%s : Invalid data size\n", __func__);
270 		return -ENODATA; /* invalid pcm data size */
271 	}
272 
273 	/* fill the tx buffer before stating the tx transmit */
274 	for (i = 0, ptr = data; i < FIFO_LENGTH; i++)
275 		writel(*ptr++, &i2s_reg->txd);
276 
277 	data_size -= sizeof(*ptr) * FIFO_LENGTH;
278 	i2s_txctrl(i2s_reg, I2S_TX_ON);
279 
280 	while (data_size > 0) {
281 		start = get_timer(0);
282 		if (!(CON_TXFIFO_FULL & (readl(&i2s_reg->con)))) {
283 			writel(*ptr++, &i2s_reg->txd);
284 			data_size -= sizeof(*ptr);
285 		} else {
286 			if (get_timer(start) > TIMEOUT_I2S_TX) {
287 				i2s_txctrl(i2s_reg, I2S_TX_OFF);
288 				debug("%s: I2S Transfer Timeout\n", __func__);
289 				return -ETIMEDOUT;
290 			}
291 		}
292 	}
293 	i2s_txctrl(i2s_reg, I2S_TX_OFF);
294 
295 	return 0;
296 }
297 
i2s_tx_init(struct i2s_uc_priv * pi2s_tx)298 static int i2s_tx_init(struct i2s_uc_priv *pi2s_tx)
299 {
300 	int ret;
301 	struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address;
302 
303 	if (pi2s_tx->id == 0) {
304 		/* Initialize GPIO for I2S-0 */
305 		exynos_pinmux_config(PERIPH_ID_I2S0, 0);
306 
307 		/* Set EPLL Clock */
308 		ret = set_epll_clk(pi2s_tx->samplingrate * pi2s_tx->rfs * 4);
309 	} else if (pi2s_tx->id == 1) {
310 		/* Initialize GPIO for I2S-1 */
311 		exynos_pinmux_config(PERIPH_ID_I2S1, 0);
312 
313 		/* Set EPLL Clock */
314 		ret = set_epll_clk(pi2s_tx->audio_pll_clk);
315 	} else {
316 		debug("%s: unsupported i2s-%d bus\n", __func__, pi2s_tx->id);
317 		return -ERANGE;
318 	}
319 
320 	if (ret) {
321 		debug("%s: epll clock set rate failed\n", __func__);
322 		return ret;
323 	}
324 
325 	/* Select Clk Source for Audio 0 or 1 */
326 	ret = set_i2s_clk_source(pi2s_tx->id);
327 	if (ret) {
328 		debug("%s: unsupported clock for i2s-%d\n", __func__,
329 		      pi2s_tx->id);
330 		return ret;
331 	}
332 
333 	if (pi2s_tx->id == 0) {
334 		/*Reset the i2s module */
335 		writel(CON_RESET, &i2s_reg->con);
336 
337 		writel(MOD_OP_CLK | MOD_RCLKSRC, &i2s_reg->mod);
338 		/* set i2s prescaler */
339 		writel(PSREN | PSVAL, &i2s_reg->psr);
340 	} else {
341 		/* Set Prescaler to get MCLK */
342 		ret = set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk,
343 				(pi2s_tx->samplingrate * (pi2s_tx->rfs)),
344 				pi2s_tx->id);
345 	}
346 	if (ret) {
347 		debug("%s: unsupported prescalar for i2s-%d\n", __func__,
348 		      pi2s_tx->id);
349 		return ret;
350 	}
351 
352 	/* Configure I2s format */
353 	ret = i2s_set_fmt(i2s_reg, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
354 			  SND_SOC_DAIFMT_CBM_CFM);
355 	if (ret == 0) {
356 		i2s_set_lr_framesize(i2s_reg, pi2s_tx->rfs);
357 		ret = i2s_set_samplesize(i2s_reg, pi2s_tx->bitspersample);
358 		if (ret != 0) {
359 			debug("%s:set sample rate failed\n", __func__);
360 			return ret;
361 		}
362 
363 		i2s_set_bitclk_framesize(i2s_reg, pi2s_tx->bfs);
364 		/* disable i2s transfer flag and flush the fifo */
365 		i2s_txctrl(i2s_reg, I2S_TX_OFF);
366 		i2s_fifo(i2s_reg, FIC_TXFLUSH);
367 	} else {
368 		debug("%s: failed\n", __func__);
369 	}
370 
371 	return ret;
372 }
373 
samsung_i2s_tx_data(struct udevice * dev,void * data,uint data_size)374 static int samsung_i2s_tx_data(struct udevice *dev, void *data, uint data_size)
375 {
376 	struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
377 
378 	return i2s_transfer_tx_data(priv, data, data_size);
379 }
380 
samsung_i2s_probe(struct udevice * dev)381 static int samsung_i2s_probe(struct udevice *dev)
382 {
383 	struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
384 
385 	return i2s_tx_init(priv);
386 }
387 
samsung_i2s_of_to_plat(struct udevice * dev)388 static int samsung_i2s_of_to_plat(struct udevice *dev)
389 {
390 	struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
391 	ulong base;
392 
393 	/*
394 	 * Get the pre-defined sound specific values from FDT.
395 	 * All of these are expected to be correct otherwise
396 	 * wrong register values in i2s setup parameters
397 	 * may result in no sound play.
398 	 */
399 	base = dev_read_addr(dev);
400 	if (base == FDT_ADDR_T_NONE) {
401 		debug("%s: Missing  i2s base\n", __func__);
402 		return -EINVAL;
403 	}
404 	priv->base_address = base;
405 
406 	if (dev_read_u32u(dev, "samsung,i2s-epll-clock-frequency",
407 			  &priv->audio_pll_clk))
408 		goto err;
409 	debug("audio_pll_clk = %d\n", priv->audio_pll_clk);
410 	if (dev_read_u32u(dev, "samsung,i2s-sampling-rate",
411 			  &priv->samplingrate))
412 		goto err;
413 	debug("samplingrate = %d\n", priv->samplingrate);
414 	if (dev_read_u32u(dev, "samsung,i2s-bits-per-sample",
415 			  &priv->bitspersample))
416 		goto err;
417 	debug("bitspersample = %d\n", priv->bitspersample);
418 	if (dev_read_u32u(dev, "samsung,i2s-channels", &priv->channels))
419 		goto err;
420 	debug("channels = %d\n", priv->channels);
421 	if (dev_read_u32u(dev, "samsung,i2s-lr-clk-framesize", &priv->rfs))
422 		goto err;
423 	debug("rfs = %d\n", priv->rfs);
424 	if (dev_read_u32u(dev, "samsung,i2s-bit-clk-framesize", &priv->bfs))
425 		goto err;
426 	debug("bfs = %d\n", priv->bfs);
427 
428 	if (dev_read_u32u(dev, "samsung,i2s-id", &priv->id))
429 		goto err;
430 	debug("id = %d\n", priv->id);
431 
432 	return 0;
433 
434 err:
435 	debug("fail to get sound i2s node properties\n");
436 
437 	return -EINVAL;
438 }
439 
440 static const struct i2s_ops samsung_i2s_ops = {
441 	.tx_data	= samsung_i2s_tx_data,
442 };
443 
444 static const struct udevice_id samsung_i2s_ids[] = {
445 	{ .compatible = "samsung,s5pv210-i2s" },
446 	{ }
447 };
448 
449 U_BOOT_DRIVER(samsung_i2s) = {
450 	.name		= "samsung_i2s",
451 	.id		= UCLASS_I2S,
452 	.of_match	= samsung_i2s_ids,
453 	.probe		= samsung_i2s_probe,
454 	.of_to_plat	= samsung_i2s_of_to_plat,
455 	.ops		= &samsung_i2s_ops,
456 };
457