• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/sound/soc/pxa/
1/*
2 * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 *         lrg@slimlogic.co.uk
7 *
8 *  This program is free software; you can redistribute  it and/or modify it
9 *  under  the terms of  the GNU General  Public License as published by the
10 *  Free Software Foundation;  either version 2 of the  License, or (at your
11 *  option) any later version.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/clk.h>
19#include <linux/platform_device.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/initval.h>
23#include <sound/soc.h>
24#include <sound/pxa2xx-lib.h>
25
26#include <mach/hardware.h>
27#include <mach/dma.h>
28#include <mach/audio.h>
29
30#include "pxa2xx-pcm.h"
31#include "pxa2xx-i2s.h"
32
33/*
34 * I2S Controller Register and Bit Definitions
35 */
36#define SACR0		__REG(0x40400000)  /* Global Control Register */
37#define SACR1		__REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
38#define SASR0		__REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
39#define SAIMR		__REG(0x40400014)  /* Serial Audio Interrupt Mask Register */
40#define SAICR		__REG(0x40400018)  /* Serial Audio Interrupt Clear Register */
41#define SADIV		__REG(0x40400060)  /* Audio Clock Divider Register. */
42#define SADR		__REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
43
44#define SACR0_RFTH(x)	((x) << 12)	/* Rx FIFO Interrupt or DMA Trigger Threshold */
45#define SACR0_TFTH(x)	((x) << 8)	/* Tx FIFO Interrupt or DMA Trigger Threshold */
46#define SACR0_STRF	(1 << 5)	/* FIFO Select for EFWR Special Function */
47#define SACR0_EFWR	(1 << 4)	/* Enable EFWR Function  */
48#define SACR0_RST	(1 << 3)	/* FIFO, i2s Register Reset */
49#define SACR0_BCKD	(1 << 2) 	/* Bit Clock Direction */
50#define SACR0_ENB	(1 << 0)	/* Enable I2S Link */
51#define SACR1_ENLBF	(1 << 5)	/* Enable Loopback */
52#define SACR1_DRPL	(1 << 4) 	/* Disable Replaying Function */
53#define SACR1_DREC	(1 << 3)	/* Disable Recording Function */
54#define SACR1_AMSL	(1 << 0)	/* Specify Alternate Mode */
55
56#define SASR0_I2SOFF	(1 << 7)	/* Controller Status */
57#define SASR0_ROR	(1 << 6)	/* Rx FIFO Overrun */
58#define SASR0_TUR	(1 << 5)	/* Tx FIFO Underrun */
59#define SASR0_RFS	(1 << 4)	/* Rx FIFO Service Request */
60#define SASR0_TFS	(1 << 3)	/* Tx FIFO Service Request */
61#define SASR0_BSY	(1 << 2)	/* I2S Busy */
62#define SASR0_RNE	(1 << 1)	/* Rx FIFO Not Empty */
63#define SASR0_TNF	(1 << 0) 	/* Tx FIFO Not Empty */
64
65#define SAICR_ROR	(1 << 6)	/* Clear Rx FIFO Overrun Interrupt */
66#define SAICR_TUR	(1 << 5)	/* Clear Tx FIFO Underrun Interrupt */
67
68#define SAIMR_ROR	(1 << 6)	/* Enable Rx FIFO Overrun Condition Interrupt */
69#define SAIMR_TUR	(1 << 5)	/* Enable Tx FIFO Underrun Condition Interrupt */
70#define SAIMR_RFS	(1 << 4)	/* Enable Rx FIFO Service Interrupt */
71#define SAIMR_TFS	(1 << 3)	/* Enable Tx FIFO Service Interrupt */
72
73struct pxa_i2s_port {
74	u32 sadiv;
75	u32 sacr0;
76	u32 sacr1;
77	u32 saimr;
78	int master;
79	u32 fmt;
80};
81static struct pxa_i2s_port pxa_i2s;
82static struct clk *clk_i2s;
83
84static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
85	.name			= "I2S PCM Stereo out",
86	.dev_addr		= __PREG(SADR),
87	.drcmr			= &DRCMR(3),
88	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
89				  DCMD_BURST32 | DCMD_WIDTH4,
90};
91
92static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
93	.name			= "I2S PCM Stereo in",
94	.dev_addr		= __PREG(SADR),
95	.drcmr			= &DRCMR(2),
96	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
97				  DCMD_BURST32 | DCMD_WIDTH4,
98};
99
100static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
101			      struct snd_soc_dai *dai)
102{
103	struct snd_soc_pcm_runtime *rtd = substream->private_data;
104	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
105
106	if (IS_ERR(clk_i2s))
107		return PTR_ERR(clk_i2s);
108
109	if (!cpu_dai->active)
110		SACR0 = 0;
111
112	return 0;
113}
114
115/* wait for I2S controller to be ready */
116static int pxa_i2s_wait(void)
117{
118	int i;
119
120	/* flush the Rx FIFO */
121	for(i = 0; i < 16; i++)
122		SADR;
123	return 0;
124}
125
126static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
127		unsigned int fmt)
128{
129	/* interface format */
130	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
131	case SND_SOC_DAIFMT_I2S:
132		pxa_i2s.fmt = 0;
133		break;
134	case SND_SOC_DAIFMT_LEFT_J:
135		pxa_i2s.fmt = SACR1_AMSL;
136		break;
137	}
138
139	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
140	case SND_SOC_DAIFMT_CBS_CFS:
141		pxa_i2s.master = 1;
142		break;
143	case SND_SOC_DAIFMT_CBM_CFS:
144		pxa_i2s.master = 0;
145		break;
146	default:
147		break;
148	}
149	return 0;
150}
151
152static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
153		int clk_id, unsigned int freq, int dir)
154{
155	if (clk_id != PXA2XX_I2S_SYSCLK)
156		return -ENODEV;
157
158	return 0;
159}
160
161static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
162				struct snd_pcm_hw_params *params,
163				struct snd_soc_dai *dai)
164{
165	struct snd_soc_pcm_runtime *rtd = substream->private_data;
166	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
167	struct pxa2xx_pcm_dma_params *dma_data;
168
169	BUG_ON(IS_ERR(clk_i2s));
170	clk_enable(clk_i2s);
171	dai->private_data = dai;
172	pxa_i2s_wait();
173
174	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
175		dma_data = &pxa2xx_i2s_pcm_stereo_out;
176	else
177		dma_data = &pxa2xx_i2s_pcm_stereo_in;
178
179	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
180
181	/* is port used by another stream */
182	if (!(SACR0 & SACR0_ENB)) {
183		SACR0 = 0;
184		if (pxa_i2s.master)
185			SACR0 |= SACR0_BCKD;
186
187		SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
188		SACR1 |= pxa_i2s.fmt;
189	}
190	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
191		SAIMR |= SAIMR_TFS;
192	else
193		SAIMR |= SAIMR_RFS;
194
195	switch (params_rate(params)) {
196	case 8000:
197		SADIV = 0x48;
198		break;
199	case 11025:
200		SADIV = 0x34;
201		break;
202	case 16000:
203		SADIV = 0x24;
204		break;
205	case 22050:
206		SADIV = 0x1a;
207		break;
208	case 44100:
209		SADIV = 0xd;
210		break;
211	case 48000:
212		SADIV = 0xc;
213		break;
214	case 96000: /* not in manual and possibly slightly inaccurate */
215		SADIV = 0x6;
216		break;
217	}
218
219	return 0;
220}
221
222static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
223			      struct snd_soc_dai *dai)
224{
225	int ret = 0;
226
227	switch (cmd) {
228	case SNDRV_PCM_TRIGGER_START:
229		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
230			SACR1 &= ~SACR1_DRPL;
231		else
232			SACR1 &= ~SACR1_DREC;
233		SACR0 |= SACR0_ENB;
234		break;
235	case SNDRV_PCM_TRIGGER_RESUME:
236	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
237	case SNDRV_PCM_TRIGGER_STOP:
238	case SNDRV_PCM_TRIGGER_SUSPEND:
239	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
240		break;
241	default:
242		ret = -EINVAL;
243	}
244
245	return ret;
246}
247
248static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
249				struct snd_soc_dai *dai)
250{
251	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
252		SACR1 |= SACR1_DRPL;
253		SAIMR &= ~SAIMR_TFS;
254	} else {
255		SACR1 |= SACR1_DREC;
256		SAIMR &= ~SAIMR_RFS;
257	}
258
259	if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
260		SACR0 &= ~SACR0_ENB;
261		pxa_i2s_wait();
262		if (dai->private_data != NULL) {
263			clk_disable(clk_i2s);
264			dai->private_data = NULL;
265		}
266	}
267}
268
269#ifdef CONFIG_PM
270static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
271{
272	/* store registers */
273	pxa_i2s.sacr0 = SACR0;
274	pxa_i2s.sacr1 = SACR1;
275	pxa_i2s.saimr = SAIMR;
276	pxa_i2s.sadiv = SADIV;
277
278	/* deactivate link */
279	SACR0 &= ~SACR0_ENB;
280	pxa_i2s_wait();
281	return 0;
282}
283
284static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
285{
286	pxa_i2s_wait();
287
288	SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
289	SACR1 = pxa_i2s.sacr1;
290	SAIMR = pxa_i2s.saimr;
291	SADIV = pxa_i2s.sadiv;
292
293	SACR0 = pxa_i2s.sacr0;
294
295	return 0;
296}
297
298#else
299#define pxa2xx_i2s_suspend	NULL
300#define pxa2xx_i2s_resume	NULL
301#endif
302
303#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
304		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
305		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
306
307static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
308	.startup	= pxa2xx_i2s_startup,
309	.shutdown	= pxa2xx_i2s_shutdown,
310	.trigger	= pxa2xx_i2s_trigger,
311	.hw_params	= pxa2xx_i2s_hw_params,
312	.set_fmt	= pxa2xx_i2s_set_dai_fmt,
313	.set_sysclk	= pxa2xx_i2s_set_dai_sysclk,
314};
315
316struct snd_soc_dai pxa_i2s_dai = {
317	.name = "pxa2xx-i2s",
318	.id = 0,
319	.suspend = pxa2xx_i2s_suspend,
320	.resume = pxa2xx_i2s_resume,
321	.playback = {
322		.channels_min = 2,
323		.channels_max = 2,
324		.rates = PXA2XX_I2S_RATES,
325		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
326	.capture = {
327		.channels_min = 2,
328		.channels_max = 2,
329		.rates = PXA2XX_I2S_RATES,
330		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
331	.ops = &pxa_i2s_dai_ops,
332	.symmetric_rates = 1,
333};
334
335EXPORT_SYMBOL_GPL(pxa_i2s_dai);
336
337static int pxa2xx_i2s_probe(struct platform_device *dev)
338{
339	int ret;
340
341	clk_i2s = clk_get(&dev->dev, "I2SCLK");
342	if (IS_ERR(clk_i2s))
343		return PTR_ERR(clk_i2s);
344
345	pxa_i2s_dai.dev = &dev->dev;
346	pxa_i2s_dai.private_data = NULL;
347	ret = snd_soc_register_dai(&pxa_i2s_dai);
348	if (ret != 0)
349		clk_put(clk_i2s);
350
351	/*
352	 * PXA Developer's Manual:
353	 * If SACR0[ENB] is toggled in the middle of a normal operation,
354	 * the SACR0[RST] bit must also be set and cleared to reset all
355	 * I2S controller registers.
356	 */
357	SACR0 = SACR0_RST;
358	SACR0 = 0;
359	/* Make sure RPL and REC are disabled */
360	SACR1 = SACR1_DRPL | SACR1_DREC;
361	/* Along with FIFO servicing */
362	SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
363
364	return ret;
365}
366
367static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
368{
369	snd_soc_unregister_dai(&pxa_i2s_dai);
370	clk_put(clk_i2s);
371	clk_i2s = ERR_PTR(-ENOENT);
372	return 0;
373}
374
375static struct platform_driver pxa2xx_i2s_driver = {
376	.probe = pxa2xx_i2s_probe,
377	.remove = __devexit_p(pxa2xx_i2s_remove),
378
379	.driver = {
380		.name = "pxa2xx-i2s",
381		.owner = THIS_MODULE,
382	},
383};
384
385static int __init pxa2xx_i2s_init(void)
386{
387	clk_i2s = ERR_PTR(-ENOENT);
388	return platform_driver_register(&pxa2xx_i2s_driver);
389}
390
391static void __exit pxa2xx_i2s_exit(void)
392{
393	platform_driver_unregister(&pxa2xx_i2s_driver);
394}
395
396module_init(pxa2xx_i2s_init);
397module_exit(pxa2xx_i2s_exit);
398
399/* Module information */
400MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
401MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
402MODULE_LICENSE("GPL");
403