• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * linux/sound/soc/ep93xx-i2s.c
3  * EP93xx I2S driver
4  *
5  * Copyright (C) 2010 Ryan Mallon
6  *
7  * Based on the original driver by:
8  *   Copyright (C) 2007 Chase Douglas <chasedouglas@gmail>
9  *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  *
15  */
16 
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/slab.h>
20 #include <linux/clk.h>
21 #include <linux/io.h>
22 
23 #include <sound/core.h>
24 #include <sound/dmaengine_pcm.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/initval.h>
28 #include <sound/soc.h>
29 
30 #include <mach/hardware.h>
31 #include <mach/ep93xx-regs.h>
32 #include <linux/platform_data/dma-ep93xx.h>
33 
34 #include "ep93xx-pcm.h"
35 
36 #define EP93XX_I2S_TXCLKCFG		0x00
37 #define EP93XX_I2S_RXCLKCFG		0x04
38 #define EP93XX_I2S_GLCTRL		0x0C
39 
40 #define EP93XX_I2S_TXLINCTRLDATA	0x28
41 #define EP93XX_I2S_TXCTRL		0x2C
42 #define EP93XX_I2S_TXWRDLEN		0x30
43 #define EP93XX_I2S_TX0EN		0x34
44 
45 #define EP93XX_I2S_RXLINCTRLDATA	0x58
46 #define EP93XX_I2S_RXCTRL		0x5C
47 #define EP93XX_I2S_RXWRDLEN		0x60
48 #define EP93XX_I2S_RX0EN		0x64
49 
50 #define EP93XX_I2S_WRDLEN_16		(0 << 0)
51 #define EP93XX_I2S_WRDLEN_24		(1 << 0)
52 #define EP93XX_I2S_WRDLEN_32		(2 << 0)
53 
54 #define EP93XX_I2S_RXLINCTRLDATA_R_JUST	BIT(1) /* Right justify */
55 
56 #define EP93XX_I2S_TXLINCTRLDATA_R_JUST	BIT(2) /* Right justify */
57 
58 #define EP93XX_I2S_CLKCFG_LRS		(1 << 0) /* lrclk polarity */
59 #define EP93XX_I2S_CLKCFG_CKP		(1 << 1) /* Bit clock polarity */
60 #define EP93XX_I2S_CLKCFG_REL		(1 << 2) /* First bit transition */
61 #define EP93XX_I2S_CLKCFG_MASTER	(1 << 3) /* Master mode */
62 #define EP93XX_I2S_CLKCFG_NBCG		(1 << 4) /* Not bit clock gating */
63 
64 struct ep93xx_i2s_info {
65 	struct clk			*mclk;
66 	struct clk			*sclk;
67 	struct clk			*lrclk;
68 	void __iomem			*regs;
69 	struct snd_dmaengine_dai_dma_data dma_params_rx;
70 	struct snd_dmaengine_dai_dma_data dma_params_tx;
71 };
72 
73 static struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
74 	[SNDRV_PCM_STREAM_PLAYBACK] = {
75 		.name		= "i2s-pcm-out",
76 		.port		= EP93XX_DMA_I2S1,
77 		.direction	= DMA_MEM_TO_DEV,
78 	},
79 	[SNDRV_PCM_STREAM_CAPTURE] = {
80 		.name		= "i2s-pcm-in",
81 		.port		= EP93XX_DMA_I2S1,
82 		.direction	= DMA_DEV_TO_MEM,
83 	},
84 };
85 
ep93xx_i2s_write_reg(struct ep93xx_i2s_info * info,unsigned reg,unsigned val)86 static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info,
87 					unsigned reg, unsigned val)
88 {
89 	__raw_writel(val, info->regs + reg);
90 }
91 
ep93xx_i2s_read_reg(struct ep93xx_i2s_info * info,unsigned reg)92 static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info,
93 					   unsigned reg)
94 {
95 	return __raw_readl(info->regs + reg);
96 }
97 
ep93xx_i2s_enable(struct ep93xx_i2s_info * info,int stream)98 static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
99 {
100 	unsigned base_reg;
101 	int i;
102 
103 	if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
104 	    (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
105 		/* Enable clocks */
106 		clk_enable(info->mclk);
107 		clk_enable(info->sclk);
108 		clk_enable(info->lrclk);
109 
110 		/* Enable i2s */
111 		ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1);
112 	}
113 
114 	/* Enable fifos */
115 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
116 		base_reg = EP93XX_I2S_TX0EN;
117 	else
118 		base_reg = EP93XX_I2S_RX0EN;
119 	for (i = 0; i < 3; i++)
120 		ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1);
121 }
122 
ep93xx_i2s_disable(struct ep93xx_i2s_info * info,int stream)123 static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
124 {
125 	unsigned base_reg;
126 	int i;
127 
128 	/* Disable fifos */
129 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
130 		base_reg = EP93XX_I2S_TX0EN;
131 	else
132 		base_reg = EP93XX_I2S_RX0EN;
133 	for (i = 0; i < 3; i++)
134 		ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0);
135 
136 	if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
137 	    (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
138 		/* Disable i2s */
139 		ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0);
140 
141 		/* Disable clocks */
142 		clk_disable(info->lrclk);
143 		clk_disable(info->sclk);
144 		clk_disable(info->mclk);
145 	}
146 }
147 
ep93xx_i2s_dai_probe(struct snd_soc_dai * dai)148 static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai)
149 {
150 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
151 
152 	info->dma_params_tx.filter_data =
153 		&ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK];
154 	info->dma_params_rx.filter_data =
155 		&ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE];
156 
157 	dai->playback_dma_data = &info->dma_params_tx;
158 	dai->capture_dma_data = &info->dma_params_rx;
159 
160 	return 0;
161 }
162 
ep93xx_i2s_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)163 static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
164 				struct snd_soc_dai *dai)
165 {
166 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
167 
168 	ep93xx_i2s_disable(info, substream->stream);
169 }
170 
ep93xx_i2s_set_dai_fmt(struct snd_soc_dai * cpu_dai,unsigned int fmt)171 static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
172 				  unsigned int fmt)
173 {
174 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
175 	unsigned int clk_cfg;
176 	unsigned int txlin_ctrl = 0;
177 	unsigned int rxlin_ctrl = 0;
178 
179 	clk_cfg  = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
180 
181 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
182 	case SND_SOC_DAIFMT_I2S:
183 		clk_cfg |= EP93XX_I2S_CLKCFG_REL;
184 		break;
185 
186 	case SND_SOC_DAIFMT_LEFT_J:
187 		clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
188 		break;
189 
190 	case SND_SOC_DAIFMT_RIGHT_J:
191 		clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
192 		rxlin_ctrl |= EP93XX_I2S_RXLINCTRLDATA_R_JUST;
193 		txlin_ctrl |= EP93XX_I2S_TXLINCTRLDATA_R_JUST;
194 		break;
195 
196 	default:
197 		return -EINVAL;
198 	}
199 
200 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
201 	case SND_SOC_DAIFMT_CBS_CFS:
202 		/* CPU is master */
203 		clk_cfg |= EP93XX_I2S_CLKCFG_MASTER;
204 		break;
205 
206 	case SND_SOC_DAIFMT_CBM_CFM:
207 		/* Codec is master */
208 		clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER;
209 		break;
210 
211 	default:
212 		return -EINVAL;
213 	}
214 
215 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
216 	case SND_SOC_DAIFMT_NB_NF:
217 		/* Negative bit clock, lrclk low on left word */
218 		clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS);
219 		break;
220 
221 	case SND_SOC_DAIFMT_NB_IF:
222 		/* Negative bit clock, lrclk low on right word */
223 		clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP;
224 		clk_cfg |= EP93XX_I2S_CLKCFG_LRS;
225 		break;
226 
227 	case SND_SOC_DAIFMT_IB_NF:
228 		/* Positive bit clock, lrclk low on left word */
229 		clk_cfg |= EP93XX_I2S_CLKCFG_CKP;
230 		clk_cfg &= ~EP93XX_I2S_CLKCFG_LRS;
231 		break;
232 
233 	case SND_SOC_DAIFMT_IB_IF:
234 		/* Positive bit clock, lrclk low on right word */
235 		clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS;
236 		break;
237 	}
238 
239 	/* Write new register values */
240 	ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg);
241 	ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg);
242 	ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, rxlin_ctrl);
243 	ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, txlin_ctrl);
244 	return 0;
245 }
246 
ep93xx_i2s_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)247 static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
248 				struct snd_pcm_hw_params *params,
249 				struct snd_soc_dai *dai)
250 {
251 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
252 	unsigned word_len, div, sdiv, lrdiv;
253 	int err;
254 
255 	switch (params_format(params)) {
256 	case SNDRV_PCM_FORMAT_S16_LE:
257 		word_len = EP93XX_I2S_WRDLEN_16;
258 		break;
259 
260 	case SNDRV_PCM_FORMAT_S24_LE:
261 		word_len = EP93XX_I2S_WRDLEN_24;
262 		break;
263 
264 	case SNDRV_PCM_FORMAT_S32_LE:
265 		word_len = EP93XX_I2S_WRDLEN_32;
266 		break;
267 
268 	default:
269 		return -EINVAL;
270 	}
271 
272 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
273 		ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len);
274 	else
275 		ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
276 
277 	/*
278 	 * EP93xx I2S module can be setup so SCLK / LRCLK value can be
279 	 * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
280 	 * We set LRCLK equal to `rate' and minimum SCLK / LRCLK
281 	 * value is 64, because our sample size is 32 bit * 2 channels.
282 	 * I2S standard permits us to transmit more bits than
283 	 * the codec uses.
284 	 */
285 	div = clk_get_rate(info->mclk) / params_rate(params);
286 	sdiv = 4;
287 	if (div > (256 + 512) / 2) {
288 		lrdiv = 128;
289 	} else {
290 		lrdiv = 64;
291 		if (div < (128 + 256) / 2)
292 			sdiv = 2;
293 	}
294 
295 	err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
296 	if (err)
297 		return err;
298 
299 	err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv);
300 	if (err)
301 		return err;
302 
303 	ep93xx_i2s_enable(info, substream->stream);
304 	return 0;
305 }
306 
ep93xx_i2s_set_sysclk(struct snd_soc_dai * cpu_dai,int clk_id,unsigned int freq,int dir)307 static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
308 				 unsigned int freq, int dir)
309 {
310 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
311 
312 	if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
313 		return -EINVAL;
314 
315 	return clk_set_rate(info->mclk, freq);
316 }
317 
318 #ifdef CONFIG_PM
ep93xx_i2s_suspend(struct snd_soc_dai * dai)319 static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
320 {
321 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
322 
323 	if (!dai->active)
324 		return 0;
325 
326 	ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
327 	ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
328 
329 	return 0;
330 }
331 
ep93xx_i2s_resume(struct snd_soc_dai * dai)332 static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
333 {
334 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
335 
336 	if (!dai->active)
337 		return 0;
338 
339 	ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
340 	ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
341 
342 	return 0;
343 }
344 #else
345 #define ep93xx_i2s_suspend	NULL
346 #define ep93xx_i2s_resume	NULL
347 #endif
348 
349 static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
350 	.shutdown	= ep93xx_i2s_shutdown,
351 	.hw_params	= ep93xx_i2s_hw_params,
352 	.set_sysclk	= ep93xx_i2s_set_sysclk,
353 	.set_fmt	= ep93xx_i2s_set_dai_fmt,
354 };
355 
356 #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
357 
358 static struct snd_soc_dai_driver ep93xx_i2s_dai = {
359 	.symmetric_rates= 1,
360 	.probe		= ep93xx_i2s_dai_probe,
361 	.suspend	= ep93xx_i2s_suspend,
362 	.resume		= ep93xx_i2s_resume,
363 	.playback	= {
364 		.channels_min	= 2,
365 		.channels_max	= 2,
366 		.rates		= SNDRV_PCM_RATE_8000_192000,
367 		.formats	= EP93XX_I2S_FORMATS,
368 	},
369 	.capture	= {
370 		 .channels_min	= 2,
371 		 .channels_max	= 2,
372 		 .rates		= SNDRV_PCM_RATE_8000_192000,
373 		 .formats	= EP93XX_I2S_FORMATS,
374 	},
375 	.ops		= &ep93xx_i2s_dai_ops,
376 };
377 
378 static const struct snd_soc_component_driver ep93xx_i2s_component = {
379 	.name		= "ep93xx-i2s",
380 };
381 
ep93xx_i2s_probe(struct platform_device * pdev)382 static int ep93xx_i2s_probe(struct platform_device *pdev)
383 {
384 	struct ep93xx_i2s_info *info;
385 	struct resource *res;
386 	int err;
387 
388 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
389 	if (!info)
390 		return -ENOMEM;
391 
392 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
393 	info->regs = devm_ioremap_resource(&pdev->dev, res);
394 	if (IS_ERR(info->regs))
395 		return PTR_ERR(info->regs);
396 
397 	info->mclk = clk_get(&pdev->dev, "mclk");
398 	if (IS_ERR(info->mclk)) {
399 		err = PTR_ERR(info->mclk);
400 		goto fail;
401 	}
402 
403 	info->sclk = clk_get(&pdev->dev, "sclk");
404 	if (IS_ERR(info->sclk)) {
405 		err = PTR_ERR(info->sclk);
406 		goto fail_put_mclk;
407 	}
408 
409 	info->lrclk = clk_get(&pdev->dev, "lrclk");
410 	if (IS_ERR(info->lrclk)) {
411 		err = PTR_ERR(info->lrclk);
412 		goto fail_put_sclk;
413 	}
414 
415 	dev_set_drvdata(&pdev->dev, info);
416 
417 	err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
418 					 &ep93xx_i2s_dai, 1);
419 	if (err)
420 		goto fail_put_lrclk;
421 
422 	err = devm_ep93xx_pcm_platform_register(&pdev->dev);
423 	if (err)
424 		goto fail_unregister;
425 
426 	return 0;
427 
428 fail_unregister:
429 	snd_soc_unregister_component(&pdev->dev);
430 fail_put_lrclk:
431 	clk_put(info->lrclk);
432 fail_put_sclk:
433 	clk_put(info->sclk);
434 fail_put_mclk:
435 	clk_put(info->mclk);
436 fail:
437 	return err;
438 }
439 
ep93xx_i2s_remove(struct platform_device * pdev)440 static int ep93xx_i2s_remove(struct platform_device *pdev)
441 {
442 	struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
443 
444 	snd_soc_unregister_component(&pdev->dev);
445 	clk_put(info->lrclk);
446 	clk_put(info->sclk);
447 	clk_put(info->mclk);
448 	return 0;
449 }
450 
451 static struct platform_driver ep93xx_i2s_driver = {
452 	.probe	= ep93xx_i2s_probe,
453 	.remove	= ep93xx_i2s_remove,
454 	.driver	= {
455 		.name	= "ep93xx-i2s",
456 	},
457 };
458 
459 module_platform_driver(ep93xx_i2s_driver);
460 
461 MODULE_ALIAS("platform:ep93xx-i2s");
462 MODULE_AUTHOR("Ryan Mallon");
463 MODULE_DESCRIPTION("EP93XX I2S driver");
464 MODULE_LICENSE("GPL");
465