aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa
diff options
context:
space:
mode:
authorZhangfei Gao <zhangfei.gao@marvell.com>2012-06-11 06:04:39 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-06-13 08:13:39 -0400
commitfa375d42f0e531b7ca4316ea9fd5444e01d585e8 (patch)
treee4c3284ecf74a37f52ff54ceacd4cf3ab5db2d18 /sound/soc/pxa
parent7a824e214e25a49442fe868dac0af8a904b24f58 (diff)
ASoC: mmp: add sspa support
The SSPA is a configurable multi-channel audio serial (TDM) interface. It's configurable at runtime to support up to 128 channels and the number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also support stereo format: I2S, left-justified or right-justified. Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com> Signed-off-by: Leo Yan <leoy@marvell.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/pxa')
-rw-r--r--sound/soc/pxa/Kconfig3
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/mmp-sspa.c480
-rw-r--r--sound/soc/pxa/mmp-sspa.h92
4 files changed, 577 insertions, 0 deletions
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 5d76e2971fbe..6c3d00b8ea0b 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -35,6 +35,9 @@ config SND_PXA_SOC_SSP
35 tristate 35 tristate
36 select PXA_SSP 36 select PXA_SSP
37 37
38config SND_MMP_SOC_SSPA
39 tristate
40
38config SND_PXA2XX_SOC_CORGI 41config SND_PXA2XX_SOC_CORGI
39 tristate "SoC Audio support for Sharp Zaurus SL-C7x0" 42 tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
40 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx 43 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index f913e9bfce4f..07b841746fc3 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -4,12 +4,14 @@ snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
4snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o 4snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
5snd-soc-pxa-ssp-objs := pxa-ssp.o 5snd-soc-pxa-ssp-objs := pxa-ssp.o
6snd-soc-mmp-objs := mmp-pcm.o 6snd-soc-mmp-objs := mmp-pcm.o
7snd-soc-mmp-sspa-objs := mmp-sspa.o
7 8
8obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o 9obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
9obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o 10obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
10obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o 11obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
11obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o 12obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
12obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o 13obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o
14obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o
13 15
14# PXA Machine Support 16# PXA Machine Support
15snd-soc-corgi-objs := corgi.o 17snd-soc-corgi-objs := corgi.o
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
new file mode 100644
index 000000000000..4d6cb8a30fc8
--- /dev/null
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -0,0 +1,480 @@
1/*
2 * linux/sound/soc/pxa/mmp-sspa.c
3 * Base on pxa2xx-ssp.c
4 *
5 * Copyright (C) 2011 Marvell International Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/delay.h>
26#include <linux/clk.h>
27#include <linux/slab.h>
28#include <linux/pxa2xx_ssp.h>
29#include <linux/io.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/initval.h>
33#include <sound/pcm_params.h>
34#include <sound/soc.h>
35#include <sound/pxa2xx-lib.h>
36#include "mmp-sspa.h"
37
38/*
39 * SSPA audio private data
40 */
41struct sspa_priv {
42 struct ssp_device *sspa;
43 struct pxa2xx_pcm_dma_params *dma_params;
44 struct clk *audio_clk;
45 struct clk *sysclk;
46 int dai_fmt;
47 int running_cnt;
48};
49
50static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val)
51{
52 __raw_writel(val, sspa->mmio_base + reg);
53}
54
55static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg)
56{
57 return __raw_readl(sspa->mmio_base + reg);
58}
59
60static void mmp_sspa_tx_enable(struct ssp_device *sspa)
61{
62 unsigned int sspa_sp;
63
64 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP);
65 sspa_sp |= SSPA_SP_S_EN;
66 sspa_sp |= SSPA_SP_WEN;
67 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
68}
69
70static void mmp_sspa_tx_disable(struct ssp_device *sspa)
71{
72 unsigned int sspa_sp;
73
74 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP);
75 sspa_sp &= ~SSPA_SP_S_EN;
76 sspa_sp |= SSPA_SP_WEN;
77 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
78}
79
80static void mmp_sspa_rx_enable(struct ssp_device *sspa)
81{
82 unsigned int sspa_sp;
83
84 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP);
85 sspa_sp |= SSPA_SP_S_EN;
86 sspa_sp |= SSPA_SP_WEN;
87 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
88}
89
90static void mmp_sspa_rx_disable(struct ssp_device *sspa)
91{
92 unsigned int sspa_sp;
93
94 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP);
95 sspa_sp &= ~SSPA_SP_S_EN;
96 sspa_sp |= SSPA_SP_WEN;
97 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
98}
99
100static int mmp_sspa_startup(struct snd_pcm_substream *substream,
101 struct snd_soc_dai *dai)
102{
103 struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai);
104
105 clk_enable(priv->sysclk);
106 clk_enable(priv->sspa->clk);
107
108 return 0;
109}
110
111static void mmp_sspa_shutdown(struct snd_pcm_substream *substream,
112 struct snd_soc_dai *dai)
113{
114 struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai);
115
116 clk_disable(priv->sspa->clk);
117 clk_disable(priv->sysclk);
118
119 return;
120}
121
122/*
123 * Set the SSP ports SYSCLK.
124 */
125static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
126 int clk_id, unsigned int freq, int dir)
127{
128 struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
129 int ret = 0;
130
131 switch (clk_id) {
132 case MMP_SSPA_CLK_AUDIO:
133 ret = clk_set_rate(priv->audio_clk, freq);
134 if (ret)
135 return ret;
136 break;
137 case MMP_SSPA_CLK_PLL:
138 case MMP_SSPA_CLK_VCXO:
139 /* not support yet */
140 return -EINVAL;
141 default:
142 return -EINVAL;
143 }
144
145 return 0;
146}
147
148static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
149 int source, unsigned int freq_in,
150 unsigned int freq_out)
151{
152 struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
153 int ret = 0;
154
155 switch (pll_id) {
156 case MMP_SYSCLK:
157 ret = clk_set_rate(priv->sysclk, freq_out);
158 if (ret)
159 return ret;
160 break;
161 case MMP_SSPA_CLK:
162 ret = clk_set_rate(priv->sspa->clk, freq_out);
163 if (ret)
164 return ret;
165 break;
166 default:
167 return -ENODEV;
168 }
169
170 return 0;
171}
172
173/*
174 * Set up the sspa dai format. The sspa port must be inactive
175 * before calling this function as the physical
176 * interface format is changed.
177 */
178static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai,
179 unsigned int fmt)
180{
181 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
182 struct ssp_device *sspa = sspa_priv->sspa;
183 u32 sspa_sp, sspa_ctrl;
184
185 /* check if we need to change anything at all */
186 if (sspa_priv->dai_fmt == fmt)
187 return 0;
188
189 /* we can only change the settings if the port is not in use */
190 if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) ||
191 (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) {
192 dev_err(&sspa->pdev->dev,
193 "can't change hardware dai format: stream is in use\n");
194 return -EINVAL;
195 }
196
197 /* reset port settings */
198 sspa_sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH;
199 sspa_ctrl = 0;
200
201 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
202 case SND_SOC_DAIFMT_CBS_CFS:
203 sspa_sp |= SSPA_SP_MSL;
204 break;
205 case SND_SOC_DAIFMT_CBM_CFM:
206 break;
207 default:
208 return -EINVAL;
209 }
210
211 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
212 case SND_SOC_DAIFMT_NB_NF:
213 sspa_sp |= SSPA_SP_FSP;
214 break;
215 default:
216 return -EINVAL;
217 }
218
219 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
220 case SND_SOC_DAIFMT_I2S:
221 sspa_sp |= SSPA_TXSP_FPER(63);
222 sspa_sp |= SSPA_SP_FWID(31);
223 sspa_ctrl |= SSPA_CTL_XDATDLY(1);
224 break;
225 default:
226 return -EINVAL;
227 }
228
229 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
230 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
231
232 sspa_sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH);
233 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
234 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
235
236 /*
237 * FIXME: hw issue, for the tx serial port,
238 * can not config the master/slave mode;
239 * so must clean this bit.
240 * The master/slave mode has been set in the
241 * rx port.
242 */
243 sspa_sp &= ~SSPA_SP_MSL;
244 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
245
246 mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl);
247 mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl);
248
249 /* Since we are configuring the timings for the format by hand
250 * we have to defer some things until hw_params() where we
251 * know parameters like the sample size.
252 */
253 sspa_priv->dai_fmt = fmt;
254 return 0;
255}
256
257/*
258 * Set the SSPA audio DMA parameters and sample size.
259 * Can be called multiple times by oss emulation.
260 */
261static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
262 struct snd_pcm_hw_params *params,
263 struct snd_soc_dai *dai)
264{
265 struct snd_soc_pcm_runtime *rtd = substream->private_data;
266 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
267 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
268 struct ssp_device *sspa = sspa_priv->sspa;
269 struct pxa2xx_pcm_dma_params *dma_params;
270 u32 sspa_ctrl;
271
272 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
273 sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL);
274 else
275 sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL);
276
277 sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK;
278 sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1);
279 sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK;
280 sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS);
281 sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK;
282
283 switch (params_format(params)) {
284 case SNDRV_PCM_FORMAT_S8:
285 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS);
286 break;
287 case SNDRV_PCM_FORMAT_S16_LE:
288 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS);
289 break;
290 case SNDRV_PCM_FORMAT_S20_3LE:
291 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS);
292 break;
293 case SNDRV_PCM_FORMAT_S24_3LE:
294 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS);
295 break;
296 case SNDRV_PCM_FORMAT_S32_LE:
297 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS);
298 break;
299 default:
300 return -EINVAL;
301 }
302
303 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
304 mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl);
305 mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1);
306 } else {
307 mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl);
308 mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0);
309 }
310
311 dma_params = &sspa_priv->dma_params[substream->stream];
312 dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
313 (sspa->phys_base + SSPA_TXD) :
314 (sspa->phys_base + SSPA_RXD);
315 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params);
316 return 0;
317}
318
319static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd,
320 struct snd_soc_dai *dai)
321{
322 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
323 struct ssp_device *sspa = sspa_priv->sspa;
324 int ret = 0;
325
326 switch (cmd) {
327 case SNDRV_PCM_TRIGGER_START:
328 case SNDRV_PCM_TRIGGER_RESUME:
329 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
330 /*
331 * whatever playback or capture, must enable rx.
332 * this is a hw issue, so need check if rx has been
333 * enabled or not; if has been enabled by another
334 * stream, do not enable again.
335 */
336 if (!sspa_priv->running_cnt)
337 mmp_sspa_rx_enable(sspa);
338
339 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
340 mmp_sspa_tx_enable(sspa);
341
342 sspa_priv->running_cnt++;
343 break;
344
345 case SNDRV_PCM_TRIGGER_STOP:
346 case SNDRV_PCM_TRIGGER_SUSPEND:
347 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
348 sspa_priv->running_cnt--;
349
350 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
351 mmp_sspa_tx_disable(sspa);
352
353 /* have no capture stream, disable rx port */
354 if (!sspa_priv->running_cnt)
355 mmp_sspa_rx_disable(sspa);
356 break;
357
358 default:
359 ret = -EINVAL;
360 }
361
362 return ret;
363}
364
365static int mmp_sspa_probe(struct snd_soc_dai *dai)
366{
367 struct sspa_priv *priv = dev_get_drvdata(dai->dev);
368
369 snd_soc_dai_set_drvdata(dai, priv);
370 return 0;
371
372}
373
374#define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000
375#define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
376 SNDRV_PCM_FMTBIT_S16_LE | \
377 SNDRV_PCM_FMTBIT_S24_LE | \
378 SNDRV_PCM_FMTBIT_S24_LE | \
379 SNDRV_PCM_FMTBIT_S32_LE)
380
381static struct snd_soc_dai_ops mmp_sspa_dai_ops = {
382 .startup = mmp_sspa_startup,
383 .shutdown = mmp_sspa_shutdown,
384 .trigger = mmp_sspa_trigger,
385 .hw_params = mmp_sspa_hw_params,
386 .set_sysclk = mmp_sspa_set_dai_sysclk,
387 .set_pll = mmp_sspa_set_dai_pll,
388 .set_fmt = mmp_sspa_set_dai_fmt,
389};
390
391struct snd_soc_dai_driver mmp_sspa_dai = {
392 .probe = mmp_sspa_probe,
393 .playback = {
394 .channels_min = 1,
395 .channels_max = 128,
396 .rates = MMP_SSPA_RATES,
397 .formats = MMP_SSPA_FORMATS,
398 },
399 .capture = {
400 .channels_min = 1,
401 .channels_max = 2,
402 .rates = MMP_SSPA_RATES,
403 .formats = MMP_SSPA_FORMATS,
404 },
405 .ops = &mmp_sspa_dai_ops,
406};
407
408static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
409{
410 struct sspa_priv *priv;
411 struct resource *res;
412
413 priv = devm_kzalloc(&pdev->dev,
414 sizeof(struct sspa_priv), GFP_KERNEL);
415 if (!priv)
416 return -ENOMEM;
417
418 priv->sspa = devm_kzalloc(&pdev->dev,
419 sizeof(struct ssp_device), GFP_KERNEL);
420 if (priv->sspa == NULL)
421 return -ENOMEM;
422
423 priv->dma_params = devm_kzalloc(&pdev->dev,
424 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL);
425 if (priv->dma_params == NULL)
426 return -ENOMEM;
427
428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
429 if (res == NULL)
430 return -ENOMEM;
431
432 priv->sspa->mmio_base = devm_request_and_ioremap(&pdev->dev, res);
433 if (priv->sspa->mmio_base == NULL)
434 return -ENODEV;
435
436 priv->sspa->clk = devm_clk_get(&pdev->dev, NULL);
437 if (IS_ERR(priv->sspa->clk))
438 return PTR_ERR(priv->sspa->clk);
439
440 priv->audio_clk = clk_get(NULL, "mmp-audio");
441 if (IS_ERR(priv->audio_clk))
442 return PTR_ERR(priv->audio_clk);
443
444 priv->sysclk = clk_get(NULL, "mmp-sysclk");
445 if (IS_ERR(priv->sysclk)) {
446 clk_put(priv->audio_clk);
447 return PTR_ERR(priv->sysclk);
448 }
449 clk_enable(priv->audio_clk);
450 priv->dai_fmt = (unsigned int) -1;
451 platform_set_drvdata(pdev, priv);
452
453 return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai);
454}
455
456static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev)
457{
458 struct sspa_priv *priv = platform_get_drvdata(pdev);
459
460 clk_disable(priv->audio_clk);
461 clk_put(priv->audio_clk);
462 clk_put(priv->sysclk);
463 snd_soc_unregister_dai(&pdev->dev);
464 return 0;
465}
466
467static struct platform_driver asoc_mmp_sspa_driver = {
468 .driver = {
469 .name = "mmp-sspa-dai",
470 .owner = THIS_MODULE,
471 },
472 .probe = asoc_mmp_sspa_probe,
473 .remove = __devexit_p(asoc_mmp_sspa_remove),
474};
475
476module_platform_driver(asoc_mmp_sspa_driver);
477
478MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
479MODULE_DESCRIPTION("MMP SSPA SoC Interface");
480MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h
new file mode 100644
index 000000000000..ea365cb9e784
--- /dev/null
+++ b/sound/soc/pxa/mmp-sspa.h
@@ -0,0 +1,92 @@
1/*
2 * linux/sound/soc/pxa/mmp-sspa.h
3 *
4 * Copyright (C) 2011 Marvell International Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#ifndef _MMP_SSPA_H
22#define _MMP_SSPA_H
23
24/*
25 * SSPA Registers
26 */
27#define SSPA_RXD (0x00)
28#define SSPA_RXID (0x04)
29#define SSPA_RXCTL (0x08)
30#define SSPA_RXSP (0x0c)
31#define SSPA_RXFIFO_UL (0x10)
32#define SSPA_RXINT_MASK (0x14)
33#define SSPA_RXC (0x18)
34#define SSPA_RXFIFO_NOFS (0x1c)
35#define SSPA_RXFIFO_SIZE (0x20)
36
37#define SSPA_TXD (0x80)
38#define SSPA_TXID (0x84)
39#define SSPA_TXCTL (0x88)
40#define SSPA_TXSP (0x8c)
41#define SSPA_TXFIFO_LL (0x90)
42#define SSPA_TXINT_MASK (0x94)
43#define SSPA_TXC (0x98)
44#define SSPA_TXFIFO_NOFS (0x9c)
45#define SSPA_TXFIFO_SIZE (0xa0)
46
47/* SSPA Control Register */
48#define SSPA_CTL_XPH (1 << 31) /* Read Phase */
49#define SSPA_CTL_XFIG (1 << 15) /* Transmit Zeros when FIFO Empty */
50#define SSPA_CTL_JST (1 << 3) /* Audio Sample Justification */
51#define SSPA_CTL_XFRLEN2_MASK (7 << 24)
52#define SSPA_CTL_XFRLEN2(x) ((x) << 24) /* Transmit Frame Length in Phase 2 */
53#define SSPA_CTL_XWDLEN2_MASK (7 << 21)
54#define SSPA_CTL_XWDLEN2(x) ((x) << 21) /* Transmit Word Length in Phase 2 */
55#define SSPA_CTL_XDATDLY(x) ((x) << 19) /* Tansmit Data Delay */
56#define SSPA_CTL_XSSZ2_MASK (7 << 16)
57#define SSPA_CTL_XSSZ2(x) ((x) << 16) /* Transmit Sample Audio Size */
58#define SSPA_CTL_XFRLEN1_MASK (7 << 8)
59#define SSPA_CTL_XFRLEN1(x) ((x) << 8) /* Transmit Frame Length in Phase 1 */
60#define SSPA_CTL_XWDLEN1_MASK (7 << 5)
61#define SSPA_CTL_XWDLEN1(x) ((x) << 5) /* Transmit Word Length in Phase 1 */
62#define SSPA_CTL_XSSZ1_MASK (7 << 0)
63#define SSPA_CTL_XSSZ1(x) ((x) << 0) /* XSSZ1 */
64
65#define SSPA_CTL_8_BITS (0x0) /* Sample Size */
66#define SSPA_CTL_12_BITS (0x1)
67#define SSPA_CTL_16_BITS (0x2)
68#define SSPA_CTL_20_BITS (0x3)
69#define SSPA_CTL_24_BITS (0x4)
70#define SSPA_CTL_32_BITS (0x5)
71
72/* SSPA Serial Port Register */
73#define SSPA_SP_WEN (1 << 31) /* Write Configuration Enable */
74#define SSPA_SP_MSL (1 << 18) /* Master Slave Configuration */
75#define SSPA_SP_CLKP (1 << 17) /* CLKP Polarity Clock Edge Select */
76#define SSPA_SP_FSP (1 << 16) /* FSP Polarity Clock Edge Select */
77#define SSPA_SP_FFLUSH (1 << 2) /* FIFO Flush */
78#define SSPA_SP_S_RST (1 << 1) /* Active High Reset Signal */
79#define SSPA_SP_S_EN (1 << 0) /* Serial Clock Domain Enable */
80#define SSPA_SP_FWID(x) ((x) << 20) /* Frame-Sync Width */
81#define SSPA_TXSP_FPER(x) ((x) << 4) /* Frame-Sync Active */
82
83/* sspa clock sources */
84#define MMP_SSPA_CLK_PLL 0
85#define MMP_SSPA_CLK_VCXO 1
86#define MMP_SSPA_CLK_AUDIO 3
87
88/* sspa pll id */
89#define MMP_SYSCLK 0
90#define MMP_SSPA_CLK 1
91
92#endif /* _MMP_SSPA_H */