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 <linux/io.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/initval.h>
24#include <sound/soc.h>
25#include <sound/pxa2xx-lib.h>
26#include <sound/dmaengine_pcm.h>
27
28#include <mach/hardware.h>
29#include <mach/audio.h>
30
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;
83static int clk_ena = 0;
84
85static unsigned long pxa2xx_i2s_pcm_stereo_out_req = 3;
86static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_out = {
87	.addr		= __PREG(SADR),
88	.addr_width	= DMA_SLAVE_BUSWIDTH_4_BYTES,
89	.maxburst	= 32,
90	.filter_data	= &pxa2xx_i2s_pcm_stereo_out_req,
91};
92
93static unsigned long pxa2xx_i2s_pcm_stereo_in_req = 2;
94static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = {
95	.addr		= __PREG(SADR),
96	.addr_width	= DMA_SLAVE_BUSWIDTH_4_BYTES,
97	.maxburst	= 32,
98	.filter_data	= &pxa2xx_i2s_pcm_stereo_in_req,
99};
100
101static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
102			      struct snd_soc_dai *dai)
103{
104	struct snd_soc_pcm_runtime *rtd = substream->private_data;
105	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
106
107	if (IS_ERR(clk_i2s))
108		return PTR_ERR(clk_i2s);
109
110	if (!cpu_dai->active)
111		SACR0 = 0;
112
113	return 0;
114}
115
116/* wait for I2S controller to be ready */
117static int pxa_i2s_wait(void)
118{
119	int i;
120
121	/* flush the Rx FIFO */
122	for(i = 0; i < 16; i++)
123		SADR;
124	return 0;
125}
126
127static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
128		unsigned int fmt)
129{
130	/* interface format */
131	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
132	case SND_SOC_DAIFMT_I2S:
133		pxa_i2s.fmt = 0;
134		break;
135	case SND_SOC_DAIFMT_LEFT_J:
136		pxa_i2s.fmt = SACR1_AMSL;
137		break;
138	}
139
140	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
141	case SND_SOC_DAIFMT_CBS_CFS:
142		pxa_i2s.master = 1;
143		break;
144	case SND_SOC_DAIFMT_CBM_CFS:
145		pxa_i2s.master = 0;
146		break;
147	default:
148		break;
149	}
150	return 0;
151}
152
153static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
154		int clk_id, unsigned int freq, int dir)
155{
156	if (clk_id != PXA2XX_I2S_SYSCLK)
157		return -ENODEV;
158
159	return 0;
160}
161
162static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
163				struct snd_pcm_hw_params *params,
164				struct snd_soc_dai *dai)
165{
166	struct snd_dmaengine_dai_dma_data *dma_data;
167
168	if (WARN_ON(IS_ERR(clk_i2s)))
169		return -EINVAL;
170	clk_prepare_enable(clk_i2s);
171	clk_ena = 1;
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(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 (clk_ena) {
263			clk_disable_unprepare(clk_i2s);
264			clk_ena = 0;
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
303static int pxa2xx_i2s_probe(struct snd_soc_dai *dai)
304{
305	clk_i2s = clk_get(dai->dev, "I2SCLK");
306	if (IS_ERR(clk_i2s))
307		return PTR_ERR(clk_i2s);
308
309	/*
310	 * PXA Developer's Manual:
311	 * If SACR0[ENB] is toggled in the middle of a normal operation,
312	 * the SACR0[RST] bit must also be set and cleared to reset all
313	 * I2S controller registers.
314	 */
315	SACR0 = SACR0_RST;
316	SACR0 = 0;
317	/* Make sure RPL and REC are disabled */
318	SACR1 = SACR1_DRPL | SACR1_DREC;
319	/* Along with FIFO servicing */
320	SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
321
322	return 0;
323}
324
325static int  pxa2xx_i2s_remove(struct snd_soc_dai *dai)
326{
327	clk_put(clk_i2s);
328	clk_i2s = ERR_PTR(-ENOENT);
329	return 0;
330}
331
332#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
333		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
334		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
335
336static const struct snd_soc_dai_ops pxa_i2s_dai_ops = {
337	.startup	= pxa2xx_i2s_startup,
338	.shutdown	= pxa2xx_i2s_shutdown,
339	.trigger	= pxa2xx_i2s_trigger,
340	.hw_params	= pxa2xx_i2s_hw_params,
341	.set_fmt	= pxa2xx_i2s_set_dai_fmt,
342	.set_sysclk	= pxa2xx_i2s_set_dai_sysclk,
343};
344
345static struct snd_soc_dai_driver pxa_i2s_dai = {
346	.probe = pxa2xx_i2s_probe,
347	.remove = pxa2xx_i2s_remove,
348	.suspend = pxa2xx_i2s_suspend,
349	.resume = pxa2xx_i2s_resume,
350	.playback = {
351		.channels_min = 2,
352		.channels_max = 2,
353		.rates = PXA2XX_I2S_RATES,
354		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
355	.capture = {
356		.channels_min = 2,
357		.channels_max = 2,
358		.rates = PXA2XX_I2S_RATES,
359		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
360	.ops = &pxa_i2s_dai_ops,
361	.symmetric_rates = 1,
362};
363
364static const struct snd_soc_component_driver pxa_i2s_component = {
365	.name		= "pxa-i2s",
366};
367
368static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
369{
370	return snd_soc_register_component(&pdev->dev, &pxa_i2s_component,
371					  &pxa_i2s_dai, 1);
372}
373
374static int pxa2xx_i2s_drv_remove(struct platform_device *pdev)
375{
376	snd_soc_unregister_component(&pdev->dev);
377	return 0;
378}
379
380static struct platform_driver pxa2xx_i2s_driver = {
381	.probe = pxa2xx_i2s_drv_probe,
382	.remove = pxa2xx_i2s_drv_remove,
383
384	.driver = {
385		.name = "pxa2xx-i2s",
386	},
387};
388
389static int __init pxa2xx_i2s_init(void)
390{
391	clk_i2s = ERR_PTR(-ENOENT);
392	return platform_driver_register(&pxa2xx_i2s_driver);
393}
394
395static void __exit pxa2xx_i2s_exit(void)
396{
397	platform_driver_unregister(&pxa2xx_i2s_driver);
398}
399
400module_init(pxa2xx_i2s_init);
401module_exit(pxa2xx_i2s_exit);
402
403/* Module information */
404MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
405MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
406MODULE_LICENSE("GPL");
407MODULE_ALIAS("platform:pxa2xx-i2s");
408