aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorSedji Gaouaou <sedji.gaouaou@atmel.com>2008-10-03 10:57:50 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2008-10-31 09:12:26 -0400
commit6c7425095c9ee23d080dba3e27217a254cce4562 (patch)
treec6c27e1c986b2adeda4adbdcad934b816d654b75 /sound
parentdc06102a0c8b5aa0dd7f9a40ce241e793c252a87 (diff)
ASoC: Merge AT91 and AVR32 support into a single atmel architecture
The Ateml AT91 and AVR32 SoC share common IP for audio and can share the same driver code using the atmel-ssc API provided for both architectures. Do this, creating a new unified atmel ASoC architecture to replace the previous at32 and at91 ones. [This was contributed as a patch series for reviewability but has been squashed down to a single commit to help preserve both the history and bisectability. A small bugfix from Jukka is included.] Tested-by: Jukka Hynninen <ext-jukka.hynninen@vaisala.com> Signed-off-by: Sedji Gaouaou <sedji.gaouaou@atmel.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/at32/Kconfig34
-rw-r--r--sound/soc/at32/Makefile11
-rw-r--r--sound/soc/at32/at32-pcm.h79
-rw-r--r--sound/soc/at32/at32-ssc.c849
-rw-r--r--sound/soc/at32/at32-ssc.h59
-rw-r--r--sound/soc/at91/Kconfig10
-rw-r--r--sound/soc/at91/Makefile6
-rw-r--r--sound/soc/at91/at91-pcm.c434
-rw-r--r--sound/soc/at91/at91-pcm.h72
-rw-r--r--sound/soc/at91/at91-ssc.c791
-rw-r--r--sound/soc/at91/at91-ssc.h27
-rw-r--r--sound/soc/atmel/Kconfig43
-rw-r--r--sound/soc/atmel/Makefile15
-rw-r--r--sound/soc/atmel/atmel-pcm.c (renamed from sound/soc/at32/at32-pcm.c)376
-rw-r--r--sound/soc/atmel/atmel-pcm.h86
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c782
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h121
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c (renamed from sound/soc/at32/playpaq_wm8510.c)4
20 files changed, 1235 insertions, 2569 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 4dfda6674bec..615ebf0b76e7 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -23,8 +23,7 @@ config SND_SOC_AC97_BUS
23 bool 23 bool
24 24
25# All the supported Soc's 25# All the supported Soc's
26source "sound/soc/at32/Kconfig" 26source "sound/soc/atmel/Kconfig"
27source "sound/soc/at91/Kconfig"
28source "sound/soc/au1x/Kconfig" 27source "sound/soc/au1x/Kconfig"
29source "sound/soc/pxa/Kconfig" 28source "sound/soc/pxa/Kconfig"
30source "sound/soc/s3c24xx/Kconfig" 29source "sound/soc/s3c24xx/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index d849349f2c66..4d475c3ceb91 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,5 +1,5 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o 1snd-soc-core-objs := soc-core.o soc-dapm.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ 4obj-$(CONFIG_SND_SOC) += codecs/ atmel/ pxa/ s3c24xx/ sh/ fsl/ davinci/
5obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/ 5obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig
deleted file mode 100644
index b0765e86c085..000000000000
--- a/sound/soc/at32/Kconfig
+++ /dev/null
@@ -1,34 +0,0 @@
1config SND_AT32_SOC
2 tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
3 depends on AVR32 && SND_SOC
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the AT32 SSC interface. You will also need to
7 to select the audio interfaces to support below.
8
9
10config SND_AT32_SOC_SSC
11 tristate
12
13
14
15config SND_AT32_SOC_PLAYPAQ
16 tristate "SoC Audio support for PlayPaq with WM8510"
17 depends on SND_AT32_SOC && BOARD_PLAYPAQ
18 select SND_AT32_SOC_SSC
19 select SND_SOC_WM8510
20 help
21 Say Y or M here if you want to add support for SoC audio
22 on the LRS PlayPaq.
23
24
25
26config SND_AT32_SOC_PLAYPAQ_SLAVE
27 bool "Run CODEC on PlayPaq in slave mode"
28 depends on SND_AT32_SOC_PLAYPAQ
29 default n
30 help
31 Say Y if you want to run with the AT32 SSC generating the BCLK
32 and FRAME signals on the PlayPaq. Unless you want to play
33 with the AT32 as the SSC master, you probably want to say N here,
34 as this will give you better sound quality.
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile
deleted file mode 100644
index c03e55ececeb..000000000000
--- a/sound/soc/at32/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
1# AT32 Platform Support
2snd-soc-at32-objs := at32-pcm.o
3snd-soc-at32-ssc-objs := at32-ssc.o
4
5obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
6obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
7
8# AT32 Machine Support
9snd-soc-playpaq-objs := playpaq_wm8510.o
10
11obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h
deleted file mode 100644
index 2a52430417da..000000000000
--- a/sound/soc/at32/at32-pcm.h
+++ /dev/null
@@ -1,79 +0,0 @@
1/* sound/soc/at32/at32-pcm.h
2 * ASoC PCM interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __SOUND_SOC_AT32_AT32_PCM_H
13#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
14
15#include <linux/atmel-ssc.h>
16
17
18/*
19 * Registers and status bits that are required by the PCM driver
20 * TODO: Is ptcr really used?
21 */
22struct at32_pdc_regs {
23 u32 xpr; /* PDC RX/TX pointer */
24 u32 xcr; /* PDC RX/TX counter */
25 u32 xnpr; /* PDC next RX/TX pointer */
26 u32 xncr; /* PDC next RX/TX counter */
27 u32 ptcr; /* PDC transfer control */
28};
29
30
31
32/*
33 * SSC mask info
34 */
35struct at32_ssc_mask {
36 u32 ssc_enable; /* SSC RX/TX enable */
37 u32 ssc_disable; /* SSC RX/TX disable */
38 u32 ssc_endx; /* SSC ENDTX or ENDRX */
39 u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */
40 u32 pdc_enable; /* PDC RX/TX enable */
41 u32 pdc_disable; /* PDC RX/TX disable */
42};
43
44
45
46/*
47 * This structure, shared between the PCM driver and the interface,
48 * contains all information required by the PCM driver to perform the
49 * PDC DMA operation. All fields except dma_intr_handler() are initialized
50 * by the interface. The dms_intr_handler() pointer is set by the PCM
51 * driver and called by the interface SSC interrupt handler if it is
52 * non-NULL.
53 */
54struct at32_pcm_dma_params {
55 char *name; /* stream identifier */
56 int pdc_xfer_size; /* PDC counter increment in bytes */
57 struct ssc_device *ssc; /* SSC device for stream */
58 struct at32_pdc_regs *pdc; /* PDC register info */
59 struct at32_ssc_mask *mask; /* SSC mask info */
60 struct snd_pcm_substream *substream;
61 void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
62};
63
64
65
66/*
67 * The AT32 ASoC platform driver
68 */
69extern struct snd_soc_platform at32_soc_platform;
70
71
72
73/*
74 * SSC register access (since ssc_writel() / ssc_readl() require literal name)
75 */
76#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
77#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
78
79#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c
deleted file mode 100644
index 4ef6492c902e..000000000000
--- a/sound/soc/at32/at32-ssc.c
+++ /dev/null
@@ -1,849 +0,0 @@
1/* sound/soc/at32/at32-ssc.c
2 * ASoC platform driver for AT32 using SSC as DAI
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Note that this is basically a port of the sound/soc/at91-ssc.c to
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code.
13 */
14
15/* #define DEBUG */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24#include <linux/atmel_pdc.h>
25#include <linux/atmel-ssc.h>
26
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/initval.h>
31#include <sound/soc.h>
32
33#include "at32-pcm.h"
34#include "at32-ssc.h"
35
36
37
38/*-------------------------------------------------------------------------*\
39 * Constants
40\*-------------------------------------------------------------------------*/
41#define NUM_SSC_DEVICES 3
42
43/*
44 * SSC direction masks
45 */
46#define SSC_DIR_MASK_UNUSED 0
47#define SSC_DIR_MASK_PLAYBACK 1
48#define SSC_DIR_MASK_CAPTURE 2
49
50/*
51 * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
52 * are expected to be used with SSC_BF
53 */
54/* START bit field values */
55#define SSC_START_CONTINUOUS 0
56#define SSC_START_TX_RX 1
57#define SSC_START_LOW_RF 2
58#define SSC_START_HIGH_RF 3
59#define SSC_START_FALLING_RF 4
60#define SSC_START_RISING_RF 5
61#define SSC_START_LEVEL_RF 6
62#define SSC_START_EDGE_RF 7
63#define SSS_START_COMPARE_0 8
64
65/* CKI bit field values */
66#define SSC_CKI_FALLING 0
67#define SSC_CKI_RISING 1
68
69/* CKO bit field values */
70#define SSC_CKO_NONE 0
71#define SSC_CKO_CONTINUOUS 1
72#define SSC_CKO_TRANSFER 2
73
74/* CKS bit field values */
75#define SSC_CKS_DIV 0
76#define SSC_CKS_CLOCK 1
77#define SSC_CKS_PIN 2
78
79/* FSEDGE bit field values */
80#define SSC_FSEDGE_POSITIVE 0
81#define SSC_FSEDGE_NEGATIVE 1
82
83/* FSOS bit field values */
84#define SSC_FSOS_NONE 0
85#define SSC_FSOS_NEGATIVE 1
86#define SSC_FSOS_POSITIVE 2
87#define SSC_FSOS_LOW 3
88#define SSC_FSOS_HIGH 4
89#define SSC_FSOS_TOGGLE 5
90
91#define START_DELAY 1
92
93
94
95/*-------------------------------------------------------------------------*\
96 * Module data
97\*-------------------------------------------------------------------------*/
98/*
99 * SSC PDC registered required by the PCM DMA engine
100 */
101static struct at32_pdc_regs pdc_tx_reg = {
102 .xpr = SSC_PDC_TPR,
103 .xcr = SSC_PDC_TCR,
104 .xnpr = SSC_PDC_TNPR,
105 .xncr = SSC_PDC_TNCR,
106};
107
108
109
110static struct at32_pdc_regs pdc_rx_reg = {
111 .xpr = SSC_PDC_RPR,
112 .xcr = SSC_PDC_RCR,
113 .xnpr = SSC_PDC_RNPR,
114 .xncr = SSC_PDC_RNCR,
115};
116
117
118
119/*
120 * SSC and PDC status bits for transmit and receive
121 */
122static struct at32_ssc_mask ssc_tx_mask = {
123 .ssc_enable = SSC_BIT(CR_TXEN),
124 .ssc_disable = SSC_BIT(CR_TXDIS),
125 .ssc_endx = SSC_BIT(SR_ENDTX),
126 .ssc_endbuf = SSC_BIT(SR_TXBUFE),
127 .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
128 .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
129};
130
131
132
133static struct at32_ssc_mask ssc_rx_mask = {
134 .ssc_enable = SSC_BIT(CR_RXEN),
135 .ssc_disable = SSC_BIT(CR_RXDIS),
136 .ssc_endx = SSC_BIT(SR_ENDRX),
137 .ssc_endbuf = SSC_BIT(SR_RXBUFF),
138 .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
139 .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
140};
141
142
143
144/*
145 * DMA parameters for each SSC
146 */
147static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
148 {
149 {
150 .name = "SSC0 PCM out",
151 .pdc = &pdc_tx_reg,
152 .mask = &ssc_tx_mask,
153 },
154 {
155 .name = "SSC0 PCM in",
156 .pdc = &pdc_rx_reg,
157 .mask = &ssc_rx_mask,
158 },
159 },
160 {
161 {
162 .name = "SSC1 PCM out",
163 .pdc = &pdc_tx_reg,
164 .mask = &ssc_tx_mask,
165 },
166 {
167 .name = "SSC1 PCM in",
168 .pdc = &pdc_rx_reg,
169 .mask = &ssc_rx_mask,
170 },
171 },
172 {
173 {
174 .name = "SSC2 PCM out",
175 .pdc = &pdc_tx_reg,
176 .mask = &ssc_tx_mask,
177 },
178 {
179 .name = "SSC2 PCM in",
180 .pdc = &pdc_rx_reg,
181 .mask = &ssc_rx_mask,
182 },
183 },
184};
185
186
187
188static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
189 {
190 .name = "ssc0",
191 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
192 .dir_mask = SSC_DIR_MASK_UNUSED,
193 .initialized = 0,
194 },
195 {
196 .name = "ssc1",
197 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
198 .dir_mask = SSC_DIR_MASK_UNUSED,
199 .initialized = 0,
200 },
201 {
202 .name = "ssc2",
203 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
204 .dir_mask = SSC_DIR_MASK_UNUSED,
205 .initialized = 0,
206 },
207};
208
209
210
211
212/*-------------------------------------------------------------------------*\
213 * ISR
214\*-------------------------------------------------------------------------*/
215/*
216 * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt
217 * handler in the PCM driver.
218 */
219static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
220{
221 struct at32_ssc_info *ssc_p = dev_id;
222 struct at32_pcm_dma_params *dma_params;
223 u32 ssc_sr;
224 u32 ssc_substream_mask;
225 int i;
226
227 ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
228 ssc_readl(ssc_p->ssc->regs, IMR));
229
230 /*
231 * Loop through substreams attached to this SSC. If a DMA-related
232 * interrupt occured on that substream, call the DMA interrupt
233 * handler function, if one has been registered in the dma_param
234 * structure by the PCM driver.
235 */
236 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
237 dma_params = ssc_p->dma_params[i];
238
239 if ((dma_params != NULL) &&
240 (dma_params->dma_intr_handler != NULL)) {
241 ssc_substream_mask = (dma_params->mask->ssc_endx |
242 dma_params->mask->ssc_endbuf);
243 if (ssc_sr & ssc_substream_mask) {
244 dma_params->dma_intr_handler(ssc_sr,
245 dma_params->
246 substream);
247 }
248 }
249 }
250
251
252 return IRQ_HANDLED;
253}
254
255/*-------------------------------------------------------------------------*\
256 * DAI functions
257\*-------------------------------------------------------------------------*/
258/*
259 * Startup. Only that one substream allowed in each direction.
260 */
261static int at32_ssc_startup(struct snd_pcm_substream *substream)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
265 int dir_mask;
266
267 dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
268 SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
269
270 spin_lock_irq(&ssc_p->lock);
271 if (ssc_p->dir_mask & dir_mask) {
272 spin_unlock_irq(&ssc_p->lock);
273 return -EBUSY;
274 }
275 ssc_p->dir_mask |= dir_mask;
276 spin_unlock_irq(&ssc_p->lock);
277
278 return 0;
279}
280
281
282
283/*
284 * Shutdown. Clear DMA parameters and shutdown the SSC if there
285 * are no other substreams open.
286 */
287static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
288{
289 struct snd_soc_pcm_runtime *rtd = substream->private_data;
290 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
291 struct at32_pcm_dma_params *dma_params;
292 int dir_mask;
293
294 dma_params = ssc_p->dma_params[substream->stream];
295
296 if (dma_params != NULL) {
297 ssc_writel(dma_params->ssc->regs, CR,
298 dma_params->mask->ssc_disable);
299 pr_debug("%s disabled SSC_SR=0x%08x\n",
300 (substream->stream ? "receiver" : "transmit"),
301 ssc_readl(ssc_p->ssc->regs, SR));
302
303 dma_params->ssc = NULL;
304 dma_params->substream = NULL;
305 ssc_p->dma_params[substream->stream] = NULL;
306 }
307
308
309 dir_mask = 1 << substream->stream;
310 spin_lock_irq(&ssc_p->lock);
311 ssc_p->dir_mask &= ~dir_mask;
312 if (!ssc_p->dir_mask) {
313 /* Shutdown the SSC clock */
314 pr_debug("at32-ssc: Stopping user %d clock\n",
315 ssc_p->ssc->user);
316 clk_disable(ssc_p->ssc->clk);
317
318 if (ssc_p->initialized) {
319 free_irq(ssc_p->ssc->irq, ssc_p);
320 ssc_p->initialized = 0;
321 }
322
323 /* Reset the SSC */
324 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
325
326 /* clear the SSC dividers */
327 ssc_p->cmr_div = 0;
328 ssc_p->tcmr_period = 0;
329 ssc_p->rcmr_period = 0;
330 }
331 spin_unlock_irq(&ssc_p->lock);
332}
333
334
335
336/*
337 * Set the SSC system clock rate
338 */
339static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
340 int clk_id, unsigned int freq, int dir)
341{
342 /* TODO: What the heck do I do here? */
343 return 0;
344}
345
346
347
348/*
349 * Record DAI format for use by hw_params()
350 */
351static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
352 unsigned int fmt)
353{
354 struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
355
356 ssc_p->daifmt = fmt;
357 return 0;
358}
359
360
361
362/*
363 * Record SSC clock dividers for use in hw_params()
364 */
365static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
366 int div_id, int div)
367{
368 struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
369
370 switch (div_id) {
371 case AT32_SSC_CMR_DIV:
372 /*
373 * The same master clock divider is used for both
374 * transmit and receive, so if a value has already
375 * been set, it must match this value
376 */
377 if (ssc_p->cmr_div == 0)
378 ssc_p->cmr_div = div;
379 else if (div != ssc_p->cmr_div)
380 return -EBUSY;
381 break;
382
383 case AT32_SSC_TCMR_PERIOD:
384 ssc_p->tcmr_period = div;
385 break;
386
387 case AT32_SSC_RCMR_PERIOD:
388 ssc_p->rcmr_period = div;
389 break;
390
391 default:
392 return -EINVAL;
393 }
394
395 return 0;
396}
397
398
399
400/*
401 * Configure the SSC
402 */
403static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
404 struct snd_pcm_hw_params *params)
405{
406 struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 int id = rtd->dai->cpu_dai->id;
408 struct at32_ssc_info *ssc_p = &ssc_info[id];
409 struct at32_pcm_dma_params *dma_params;
410 int channels, bits;
411 u32 tfmr, rfmr, tcmr, rcmr;
412 int start_event;
413 int ret;
414
415
416 /*
417 * Currently, there is only one set of dma_params for each direction.
418 * If more are added, this code will have to be changed to select
419 * the proper set
420 */
421 dma_params = &ssc_dma_params[id][substream->stream];
422 dma_params->ssc = ssc_p->ssc;
423 dma_params->substream = substream;
424
425 ssc_p->dma_params[substream->stream] = dma_params;
426
427
428 /*
429 * The cpu_dai->dma_data field is only used to communicate the
430 * appropriate DMA parameters to the PCM driver's hw_params()
431 * function. It should not be used for other purposes as it
432 * is common to all substreams.
433 */
434 rtd->dai->cpu_dai->dma_data = dma_params;
435
436 channels = params_channels(params);
437
438
439 /*
440 * Determine sample size in bits and the PDC increment
441 */
442 switch (params_format(params)) {
443 case SNDRV_PCM_FORMAT_S8:
444 bits = 8;
445 dma_params->pdc_xfer_size = 1;
446 break;
447
448 case SNDRV_PCM_FORMAT_S16:
449 bits = 16;
450 dma_params->pdc_xfer_size = 2;
451 break;
452
453 case SNDRV_PCM_FORMAT_S24:
454 bits = 24;
455 dma_params->pdc_xfer_size = 4;
456 break;
457
458 case SNDRV_PCM_FORMAT_S32:
459 bits = 32;
460 dma_params->pdc_xfer_size = 4;
461 break;
462
463 default:
464 pr_warning("at32-ssc: Unsupported PCM format %d",
465 params_format(params));
466 return -EINVAL;
467 }
468 pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
469 bits, dma_params->pdc_xfer_size, channels);
470
471
472 /*
473 * The SSC only supports up to 16-bit samples in I2S format, due
474 * to the size of the Frame Mode Register FSLEN field.
475 */
476 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
477 if (bits > 16) {
478 pr_warning("at32-ssc: "
479 "sample size %d is too large for I2S\n",
480 bits);
481 return -EINVAL;
482 }
483
484
485 /*
486 * Compute the SSC register settings
487 */
488 switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
489 SND_SOC_DAIFMT_MASTER_MASK)) {
490 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
491 /*
492 * I2S format, SSC provides BCLK and LRS clocks.
493 *
494 * The SSC transmit and receive clocks are generated from the
495 * MCK divider, and the BCLK signal is output on the SSC TK line
496 */
497 pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
498 rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
499 SSC_BF(RCMR_STTDLY, START_DELAY) |
500 SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
501 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
502 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
503 SSC_BF(RCMR_CKS, SSC_CKS_DIV));
504
505 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
506 SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
507 SSC_BF(RFMR_FSLEN, bits - 1) |
508 SSC_BF(RFMR_DATNB, channels - 1) |
509 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
510
511 tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
512 SSC_BF(TCMR_STTDLY, START_DELAY) |
513 SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
514 SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
515 SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
516 SSC_BF(TCMR_CKS, SSC_CKS_DIV));
517
518 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
519 SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
520 SSC_BF(TFMR_FSLEN, bits - 1) |
521 SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
522 SSC_BF(TFMR_DATLEN, bits - 1));
523 break;
524
525
526 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
527 /*
528 * I2S format, CODEC supplies BCLK and LRC clock.
529 *
530 * The SSC transmit clock is obtained from the BCLK signal
531 * on the TK line, and the SSC receive clock is generated from
532 * the transmit clock.
533 *
534 * For single channel data, one sample is transferred on the
535 * falling edge of the LRC clock. For two channel data, one
536 * sample is transferred on both edges of the LRC clock.
537 */
538 pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
539 start_event = ((channels == 1) ?
540 SSC_START_FALLING_RF : SSC_START_EDGE_RF);
541
542 rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
543 SSC_BF(RCMR_START, start_event) |
544 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
545 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
546 SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
547
548 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
549 SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
550 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
551
552 tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
553 SSC_BF(TCMR_START, start_event) |
554 SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
555 SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
556 SSC_BF(TCMR_CKS, SSC_CKS_PIN));
557
558 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
559 SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
560 SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
561 break;
562
563
564 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
565 /*
566 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
567 *
568 * The SSC transmit and receive clocks are generated from the
569 * MCK divider, and the BCLK signal is output on the SSC TK line
570 */
571 pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
572 rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
573 SSC_BF(RCMR_STTDLY, 1) |
574 SSC_BF(RCMR_START, SSC_START_RISING_RF) |
575 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
576 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
577 SSC_BF(RCMR_CKS, SSC_CKS_DIV));
578
579 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
580 SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
581 SSC_BF(RFMR_DATNB, channels - 1) |
582 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
583
584 tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
585 SSC_BF(TCMR_STTDLY, 1) |
586 SSC_BF(TCMR_START, SSC_START_RISING_RF) |
587 SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
588 SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
589 SSC_BF(TCMR_CKS, SSC_CKS_DIV));
590
591 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
592 SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
593 SSC_BF(TFMR_DATNB, channels - 1) |
594 SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
595 break;
596
597
598 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
599 default:
600 pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
601 ssc_p->daifmt);
602 return -EINVAL;
603 break;
604 }
605 pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
606 rcmr, rfmr, tcmr, tfmr);
607
608
609 if (!ssc_p->initialized) {
610 /* enable peripheral clock */
611 pr_debug("at32-ssc: Starting clock\n");
612 clk_enable(ssc_p->ssc->clk);
613
614 /* Reset the SSC and its PDC registers */
615 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
616
617 ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
618 ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
619 ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
620 ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
621
622 ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
623 ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
624 ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
625 ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
626
627 ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
628 ssc_p->name, ssc_p);
629 if (ret < 0) {
630 pr_warning("at32-ssc: request irq failed (%d)\n", ret);
631 pr_debug("at32-ssc: Stopping clock\n");
632 clk_disable(ssc_p->ssc->clk);
633 return ret;
634 }
635
636 ssc_p->initialized = 1;
637 }
638
639 /* Set SSC clock mode register */
640 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
641
642 /* set receive clock mode and format */
643 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
644 ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
645
646 /* set transmit clock mode and format */
647 ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
648 ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
649
650 pr_debug("at32-ssc: SSC initialized\n");
651 return 0;
652}
653
654
655
656static int at32_ssc_prepare(struct snd_pcm_substream *substream)
657{
658 struct snd_soc_pcm_runtime *rtd = substream->private_data;
659 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
660 struct at32_pcm_dma_params *dma_params;
661
662 dma_params = ssc_p->dma_params[substream->stream];
663
664 ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
665
666 return 0;
667}
668
669
670
671#ifdef CONFIG_PM
672static int at32_ssc_suspend(struct platform_device *pdev,
673 struct snd_soc_dai *cpu_dai)
674{
675 struct at32_ssc_info *ssc_p;
676
677 if (!cpu_dai->active)
678 return 0;
679
680 ssc_p = &ssc_info[cpu_dai->id];
681
682 /* Save the status register before disabling transmit and receive */
683 ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
684 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
685
686 /* Save the current interrupt mask, then disable unmasked interrupts */
687 ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
688 ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
689
690 ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
691 ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
692 ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
693 ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
694 ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
695
696 return 0;
697}
698
699
700
701static int at32_ssc_resume(struct platform_device *pdev,
702 struct snd_soc_dai *cpu_dai)
703{
704 struct at32_ssc_info *ssc_p;
705 u32 cr;
706
707 if (!cpu_dai->active)
708 return 0;
709
710 ssc_p = &ssc_info[cpu_dai->id];
711
712 /* restore SSC register settings */
713 ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
714 ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
715 ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
716 ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
717 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
718
719 /* re-enable interrupts */
720 ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
721
722 /* Re-enable recieve and transmit as appropriate */
723 cr = 0;
724 cr |=
725 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
726 cr |=
727 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
728 ssc_writel(ssc_p->ssc->regs, CR, cr);
729
730 return 0;
731}
732#else /* CONFIG_PM */
733# define at32_ssc_suspend NULL
734# define at32_ssc_resume NULL
735#endif /* CONFIG_PM */
736
737
738#define AT32_SSC_RATES \
739 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
740 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
741 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
742
743
744#define AT32_SSC_FORMATS \
745 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \
746 SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
747
748
749struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
750 {
751 .name = "at32-ssc0",
752 .id = 0,
753 .type = SND_SOC_DAI_PCM,
754 .suspend = at32_ssc_suspend,
755 .resume = at32_ssc_resume,
756 .playback = {
757 .channels_min = 1,
758 .channels_max = 2,
759 .rates = AT32_SSC_RATES,
760 .formats = AT32_SSC_FORMATS,
761 },
762 .capture = {
763 .channels_min = 1,
764 .channels_max = 2,
765 .rates = AT32_SSC_RATES,
766 .formats = AT32_SSC_FORMATS,
767 },
768 .ops = {
769 .startup = at32_ssc_startup,
770 .shutdown = at32_ssc_shutdown,
771 .prepare = at32_ssc_prepare,
772 .hw_params = at32_ssc_hw_params,
773 },
774 .dai_ops = {
775 .set_sysclk = at32_ssc_set_dai_sysclk,
776 .set_fmt = at32_ssc_set_dai_fmt,
777 .set_clkdiv = at32_ssc_set_dai_clkdiv,
778 },
779 .private_data = &ssc_info[0],
780 },
781 {
782 .name = "at32-ssc1",
783 .id = 1,
784 .type = SND_SOC_DAI_PCM,
785 .suspend = at32_ssc_suspend,
786 .resume = at32_ssc_resume,
787 .playback = {
788 .channels_min = 1,
789 .channels_max = 2,
790 .rates = AT32_SSC_RATES,
791 .formats = AT32_SSC_FORMATS,
792 },
793 .capture = {
794 .channels_min = 1,
795 .channels_max = 2,
796 .rates = AT32_SSC_RATES,
797 .formats = AT32_SSC_FORMATS,
798 },
799 .ops = {
800 .startup = at32_ssc_startup,
801 .shutdown = at32_ssc_shutdown,
802 .prepare = at32_ssc_prepare,
803 .hw_params = at32_ssc_hw_params,
804 },
805 .dai_ops = {
806 .set_sysclk = at32_ssc_set_dai_sysclk,
807 .set_fmt = at32_ssc_set_dai_fmt,
808 .set_clkdiv = at32_ssc_set_dai_clkdiv,
809 },
810 .private_data = &ssc_info[1],
811 },
812 {
813 .name = "at32-ssc2",
814 .id = 2,
815 .type = SND_SOC_DAI_PCM,
816 .suspend = at32_ssc_suspend,
817 .resume = at32_ssc_resume,
818 .playback = {
819 .channels_min = 1,
820 .channels_max = 2,
821 .rates = AT32_SSC_RATES,
822 .formats = AT32_SSC_FORMATS,
823 },
824 .capture = {
825 .channels_min = 1,
826 .channels_max = 2,
827 .rates = AT32_SSC_RATES,
828 .formats = AT32_SSC_FORMATS,
829 },
830 .ops = {
831 .startup = at32_ssc_startup,
832 .shutdown = at32_ssc_shutdown,
833 .prepare = at32_ssc_prepare,
834 .hw_params = at32_ssc_hw_params,
835 },
836 .dai_ops = {
837 .set_sysclk = at32_ssc_set_dai_sysclk,
838 .set_fmt = at32_ssc_set_dai_fmt,
839 .set_clkdiv = at32_ssc_set_dai_clkdiv,
840 },
841 .private_data = &ssc_info[2],
842 },
843};
844EXPORT_SYMBOL_GPL(at32_ssc_dai);
845
846
847MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
848MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
849MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h
deleted file mode 100644
index 3c052dbbe460..000000000000
--- a/sound/soc/at32/at32-ssc.h
+++ /dev/null
@@ -1,59 +0,0 @@
1/* sound/soc/at32/at32-ssc.h
2 * ASoC SSC interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __SOUND_SOC_AT32_AT32_SSC_H
13#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
14
15#include <linux/types.h>
16#include <linux/atmel-ssc.h>
17
18#include "at32-pcm.h"
19
20
21
22struct at32_ssc_state {
23 u32 ssc_cmr;
24 u32 ssc_rcmr;
25 u32 ssc_rfmr;
26 u32 ssc_tcmr;
27 u32 ssc_tfmr;
28 u32 ssc_sr;
29 u32 ssc_imr;
30};
31
32
33
34struct at32_ssc_info {
35 char *name;
36 struct ssc_device *ssc;
37 spinlock_t lock; /* lock for dir_mask */
38 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
39 unsigned short initialized; /* true if SSC has been initialized */
40 unsigned short daifmt;
41 unsigned short cmr_div;
42 unsigned short tcmr_period;
43 unsigned short rcmr_period;
44 struct at32_pcm_dma_params *dma_params[2];
45 struct at32_ssc_state ssc_state;
46};
47
48
49/* SSC divider ids */
50#define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */
51#define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
52#define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
53
54
55extern struct snd_soc_dai at32_ssc_dai[];
56
57
58
59#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
deleted file mode 100644
index 85a883299c2e..000000000000
--- a/sound/soc/at91/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
1config SND_AT91_SOC
2 tristate "SoC Audio for the Atmel AT91 System-on-Chip"
3 depends on ARCH_AT91
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the AT91 SSC interface. You will also need
7 to select the audio interfaces to support below.
8
9config SND_AT91_SOC_SSC
10 tristate
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
deleted file mode 100644
index b817f11df286..000000000000
--- a/sound/soc/at91/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
1# AT91 Platform Support
2snd-soc-at91-objs := at91-pcm.o
3snd-soc-at91-ssc-objs := at91-ssc.o
4
5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
6obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
deleted file mode 100644
index 7ab48bd25e4c..000000000000
--- a/sound/soc/at91/at91-pcm.c
+++ /dev/null
@@ -1,434 +0,0 @@
1/*
2 * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 3, 2006
7 *
8 * Based on pxa2xx-pcm.c by:
9 *
10 * Author: Nicolas Pitre
11 * Created: Nov 30, 2004
12 * Copyright: (C) 2004 MontaVista Software, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/dma-mapping.h>
24#include <linux/atmel_pdc.h>
25
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/soc.h>
30
31#include <mach/hardware.h>
32#include <mach/at91_ssc.h>
33
34#include "at91-pcm.h"
35
36#if 0
37#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
38#else
39#define DBG(x...)
40#endif
41
42static const struct snd_pcm_hardware at91_pcm_hardware = {
43 .info = SNDRV_PCM_INFO_MMAP |
44 SNDRV_PCM_INFO_MMAP_VALID |
45 SNDRV_PCM_INFO_INTERLEAVED |
46 SNDRV_PCM_INFO_PAUSE,
47 .formats = SNDRV_PCM_FMTBIT_S16_LE,
48 .period_bytes_min = 32,
49 .period_bytes_max = 8192,
50 .periods_min = 2,
51 .periods_max = 1024,
52 .buffer_bytes_max = 32 * 1024,
53};
54
55struct at91_runtime_data {
56 struct at91_pcm_dma_params *params;
57 dma_addr_t dma_buffer; /* physical address of dma buffer */
58 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
59 size_t period_size;
60 dma_addr_t period_ptr; /* physical address of next period */
61 u32 pdc_xpr_save; /* PDC register save */
62 u32 pdc_xcr_save;
63 u32 pdc_xnpr_save;
64 u32 pdc_xncr_save;
65};
66
67static void at91_pcm_dma_irq(u32 ssc_sr,
68 struct snd_pcm_substream *substream)
69{
70 struct at91_runtime_data *prtd = substream->runtime->private_data;
71 struct at91_pcm_dma_params *params = prtd->params;
72 static int count = 0;
73
74 count++;
75
76 if (ssc_sr & params->mask->ssc_endbuf) {
77
78 printk(KERN_WARNING
79 "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
80 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
81 ? "underrun" : "overrun",
82 params->name, ssc_sr, count);
83
84 /* re-start the PDC */
85 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
86
87 prtd->period_ptr += prtd->period_size;
88 if (prtd->period_ptr >= prtd->dma_buffer_end) {
89 prtd->period_ptr = prtd->dma_buffer;
90 }
91
92 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
93 at91_ssc_write(params->ssc_base + params->pdc->xcr,
94 prtd->period_size / params->pdc_xfer_size);
95
96 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
97 }
98
99 if (ssc_sr & params->mask->ssc_endx) {
100
101 /* Load the PDC next pointer and counter registers */
102 prtd->period_ptr += prtd->period_size;
103 if (prtd->period_ptr >= prtd->dma_buffer_end) {
104 prtd->period_ptr = prtd->dma_buffer;
105 }
106 at91_ssc_write(params->ssc_base + params->pdc->xnpr,
107 prtd->period_ptr);
108 at91_ssc_write(params->ssc_base + params->pdc->xncr,
109 prtd->period_size / params->pdc_xfer_size);
110 }
111
112 snd_pcm_period_elapsed(substream);
113}
114
115static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
116 struct snd_pcm_hw_params *params)
117{
118 struct snd_pcm_runtime *runtime = substream->runtime;
119 struct at91_runtime_data *prtd = runtime->private_data;
120 struct snd_soc_pcm_runtime *rtd = substream->private_data;
121
122 /* this may get called several times by oss emulation
123 * with different params */
124
125 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
126 runtime->dma_bytes = params_buffer_bytes(params);
127
128 prtd->params = rtd->dai->cpu_dai->dma_data;
129 prtd->params->dma_intr_handler = at91_pcm_dma_irq;
130
131 prtd->dma_buffer = runtime->dma_addr;
132 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
133 prtd->period_size = params_period_bytes(params);
134
135 DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
136 prtd->params->name, runtime->dma_bytes, prtd->period_size);
137 return 0;
138}
139
140static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
141{
142 struct at91_runtime_data *prtd = substream->runtime->private_data;
143 struct at91_pcm_dma_params *params = prtd->params;
144
145 if (params != NULL) {
146 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
147 prtd->params->dma_intr_handler = NULL;
148 }
149
150 return 0;
151}
152
153static int at91_pcm_prepare(struct snd_pcm_substream *substream)
154{
155 struct at91_runtime_data *prtd = substream->runtime->private_data;
156 struct at91_pcm_dma_params *params = prtd->params;
157
158 at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
159 params->mask->ssc_endx | params->mask->ssc_endbuf);
160
161 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
162 return 0;
163}
164
165static int at91_pcm_trigger(struct snd_pcm_substream *substream,
166 int cmd)
167{
168 struct at91_runtime_data *prtd = substream->runtime->private_data;
169 struct at91_pcm_dma_params *params = prtd->params;
170 int ret = 0;
171
172 switch (cmd) {
173 case SNDRV_PCM_TRIGGER_START:
174 prtd->period_ptr = prtd->dma_buffer;
175
176 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
177 at91_ssc_write(params->ssc_base + params->pdc->xcr,
178 prtd->period_size / params->pdc_xfer_size);
179
180 prtd->period_ptr += prtd->period_size;
181 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
182 at91_ssc_write(params->ssc_base + params->pdc->xncr,
183 prtd->period_size / params->pdc_xfer_size);
184
185 DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
186 (unsigned long) prtd->period_ptr,
187 at91_ssc_read(params->ssc_base + params->pdc->xpr),
188 at91_ssc_read(params->ssc_base + params->pdc->xcr),
189 at91_ssc_read(params->ssc_base + params->pdc->xnpr),
190 at91_ssc_read(params->ssc_base + params->pdc->xncr));
191
192 at91_ssc_write(params->ssc_base + AT91_SSC_IER,
193 params->mask->ssc_endx | params->mask->ssc_endbuf);
194
195 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR,
196 params->mask->pdc_enable);
197
198 DBG("sr=%lx imr=%lx\n",
199 at91_ssc_read(params->ssc_base + AT91_SSC_SR),
200 at91_ssc_read(params->ssc_base + AT91_SSC_IMR));
201 break;
202
203 case SNDRV_PCM_TRIGGER_STOP:
204 case SNDRV_PCM_TRIGGER_SUSPEND:
205 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
206 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
207 break;
208
209 case SNDRV_PCM_TRIGGER_RESUME:
210 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
211 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
212 break;
213
214 default:
215 ret = -EINVAL;
216 }
217
218 return ret;
219}
220
221static snd_pcm_uframes_t at91_pcm_pointer(
222 struct snd_pcm_substream *substream)
223{
224 struct snd_pcm_runtime *runtime = substream->runtime;
225 struct at91_runtime_data *prtd = runtime->private_data;
226 struct at91_pcm_dma_params *params = prtd->params;
227 dma_addr_t ptr;
228 snd_pcm_uframes_t x;
229
230 ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
231 x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
232
233 if (x == runtime->buffer_size)
234 x = 0;
235 return x;
236}
237
238static int at91_pcm_open(struct snd_pcm_substream *substream)
239{
240 struct snd_pcm_runtime *runtime = substream->runtime;
241 struct at91_runtime_data *prtd;
242 int ret = 0;
243
244 snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
245
246 /* ensure that buffer size is a multiple of period size */
247 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
248 if (ret < 0)
249 goto out;
250
251 prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
252 if (prtd == NULL) {
253 ret = -ENOMEM;
254 goto out;
255 }
256 runtime->private_data = prtd;
257
258 out:
259 return ret;
260}
261
262static int at91_pcm_close(struct snd_pcm_substream *substream)
263{
264 struct at91_runtime_data *prtd = substream->runtime->private_data;
265
266 kfree(prtd);
267 return 0;
268}
269
270static int at91_pcm_mmap(struct snd_pcm_substream *substream,
271 struct vm_area_struct *vma)
272{
273 struct snd_pcm_runtime *runtime = substream->runtime;
274
275 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
276 runtime->dma_area,
277 runtime->dma_addr,
278 runtime->dma_bytes);
279}
280
281struct snd_pcm_ops at91_pcm_ops = {
282 .open = at91_pcm_open,
283 .close = at91_pcm_close,
284 .ioctl = snd_pcm_lib_ioctl,
285 .hw_params = at91_pcm_hw_params,
286 .hw_free = at91_pcm_hw_free,
287 .prepare = at91_pcm_prepare,
288 .trigger = at91_pcm_trigger,
289 .pointer = at91_pcm_pointer,
290 .mmap = at91_pcm_mmap,
291};
292
293static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
294 int stream)
295{
296 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
297 struct snd_dma_buffer *buf = &substream->dma_buffer;
298 size_t size = at91_pcm_hardware.buffer_bytes_max;
299
300 buf->dev.type = SNDRV_DMA_TYPE_DEV;
301 buf->dev.dev = pcm->card->dev;
302 buf->private_data = NULL;
303 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
304 &buf->addr, GFP_KERNEL);
305
306 DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
307 (void *) buf->area,
308 (void *) buf->addr,
309 size);
310
311 if (!buf->area)
312 return -ENOMEM;
313
314 buf->bytes = size;
315 return 0;
316}
317
318static u64 at91_pcm_dmamask = 0xffffffff;
319
320static int at91_pcm_new(struct snd_card *card,
321 struct snd_soc_dai *dai, struct snd_pcm *pcm)
322{
323 int ret = 0;
324
325 if (!card->dev->dma_mask)
326 card->dev->dma_mask = &at91_pcm_dmamask;
327 if (!card->dev->coherent_dma_mask)
328 card->dev->coherent_dma_mask = 0xffffffff;
329
330 if (dai->playback.channels_min) {
331 ret = at91_pcm_preallocate_dma_buffer(pcm,
332 SNDRV_PCM_STREAM_PLAYBACK);
333 if (ret)
334 goto out;
335 }
336
337 if (dai->capture.channels_min) {
338 ret = at91_pcm_preallocate_dma_buffer(pcm,
339 SNDRV_PCM_STREAM_CAPTURE);
340 if (ret)
341 goto out;
342 }
343 out:
344 return ret;
345}
346
347static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
348{
349 struct snd_pcm_substream *substream;
350 struct snd_dma_buffer *buf;
351 int stream;
352
353 for (stream = 0; stream < 2; stream++) {
354 substream = pcm->streams[stream].substream;
355 if (!substream)
356 continue;
357
358 buf = &substream->dma_buffer;
359 if (!buf->area)
360 continue;
361
362 dma_free_writecombine(pcm->card->dev, buf->bytes,
363 buf->area, buf->addr);
364 buf->area = NULL;
365 }
366}
367
368#ifdef CONFIG_PM
369static int at91_pcm_suspend(struct platform_device *pdev,
370 struct snd_soc_dai *dai)
371{
372 struct snd_pcm_runtime *runtime = dai->runtime;
373 struct at91_runtime_data *prtd;
374 struct at91_pcm_dma_params *params;
375
376 if (!runtime)
377 return 0;
378
379 prtd = runtime->private_data;
380 params = prtd->params;
381
382 /* disable the PDC and save the PDC registers */
383
384 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
385
386 prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
387 prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
388 prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
389 prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
390
391 return 0;
392}
393
394static int at91_pcm_resume(struct platform_device *pdev,
395 struct snd_soc_dai *dai)
396{
397 struct snd_pcm_runtime *runtime = dai->runtime;
398 struct at91_runtime_data *prtd;
399 struct at91_pcm_dma_params *params;
400
401 if (!runtime)
402 return 0;
403
404 prtd = runtime->private_data;
405 params = prtd->params;
406
407 /* restore the PDC registers and enable the PDC */
408 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
409 at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
410 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
411 at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
412
413 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
414 return 0;
415}
416#else
417#define at91_pcm_suspend NULL
418#define at91_pcm_resume NULL
419#endif
420
421struct snd_soc_platform at91_soc_platform = {
422 .name = "at91-audio",
423 .pcm_ops = &at91_pcm_ops,
424 .pcm_new = at91_pcm_new,
425 .pcm_free = at91_pcm_free_dma_buffers,
426 .suspend = at91_pcm_suspend,
427 .resume = at91_pcm_resume,
428};
429
430EXPORT_SYMBOL_GPL(at91_soc_platform);
431
432MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
433MODULE_DESCRIPTION("Atmel AT91 PCM module");
434MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
deleted file mode 100644
index e5aada2cb102..000000000000
--- a/sound/soc/at91/at91-pcm.h
+++ /dev/null
@@ -1,72 +0,0 @@
1/*
2 * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 3, 2006
7 *
8 * Based on pxa2xx-pcm.h by:
9 *
10 * Author: Nicolas Pitre
11 * Created: Nov 30, 2004
12 * Copyright: MontaVista Software, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#ifndef _AT91_PCM_H
20#define _AT91_PCM_H
21
22#include <mach/hardware.h>
23
24struct at91_ssc_periph {
25 void __iomem *base;
26 u32 pid;
27};
28
29/*
30 * Registers and status bits that are required by the PCM driver.
31 */
32struct at91_pdc_regs {
33 unsigned int xpr; /* PDC recv/trans pointer */
34 unsigned int xcr; /* PDC recv/trans counter */
35 unsigned int xnpr; /* PDC next recv/trans pointer */
36 unsigned int xncr; /* PDC next recv/trans counter */
37 unsigned int ptcr; /* PDC transfer control */
38};
39
40struct at91_ssc_mask {
41 u32 ssc_enable; /* SSC recv/trans enable */
42 u32 ssc_disable; /* SSC recv/trans disable */
43 u32 ssc_endx; /* SSC ENDTX or ENDRX */
44 u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
45 u32 pdc_enable; /* PDC recv/trans enable */
46 u32 pdc_disable; /* PDC recv/trans disable */
47};
48
49/*
50 * This structure, shared between the PCM driver and the interface,
51 * contains all information required by the PCM driver to perform the
52 * PDC DMA operation. All fields except dma_intr_handler() are initialized
53 * by the interface. The dms_intr_handler() pointer is set by the PCM
54 * driver and called by the interface SSC interrupt handler if it is
55 * non-NULL.
56 */
57struct at91_pcm_dma_params {
58 char *name; /* stream identifier */
59 int pdc_xfer_size; /* PDC counter increment in bytes */
60 void __iomem *ssc_base; /* SSC base address */
61 struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
62 struct at91_ssc_mask *mask;/* SSC & PDC status bits */
63 struct snd_pcm_substream *substream;
64 void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
65};
66
67extern struct snd_soc_platform at91_soc_platform;
68
69#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
70#define at91_ssc_write(a,v) __raw_writel((v),(a))
71
72#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
deleted file mode 100644
index 1b61cc461261..000000000000
--- a/sound/soc/at91/at91-ssc.c
+++ /dev/null
@@ -1,791 +0,0 @@
1/*
2 * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 *
7 * Based on pxa2xx Platform drivers by
8 * Liam Girdwood <lrg@slimlogic.co.uk>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/atmel_pdc.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/initval.h>
29#include <sound/soc.h>
30
31#include <mach/hardware.h>
32#include <mach/at91_pmc.h>
33#include <mach/at91_ssc.h>
34
35#include "at91-pcm.h"
36#include "at91-ssc.h"
37
38#if 0
39#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
40#else
41#define DBG(x...)
42#endif
43
44#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
45#define NUM_SSC_DEVICES 1
46#else
47#define NUM_SSC_DEVICES 3
48#endif
49
50
51/*
52 * SSC PDC registers required by the PCM DMA engine.
53 */
54static struct at91_pdc_regs pdc_tx_reg = {
55 .xpr = ATMEL_PDC_TPR,
56 .xcr = ATMEL_PDC_TCR,
57 .xnpr = ATMEL_PDC_TNPR,
58 .xncr = ATMEL_PDC_TNCR,
59};
60
61static struct at91_pdc_regs pdc_rx_reg = {
62 .xpr = ATMEL_PDC_RPR,
63 .xcr = ATMEL_PDC_RCR,
64 .xnpr = ATMEL_PDC_RNPR,
65 .xncr = ATMEL_PDC_RNCR,
66};
67
68/*
69 * SSC & PDC status bits for transmit and receive.
70 */
71static struct at91_ssc_mask ssc_tx_mask = {
72 .ssc_enable = AT91_SSC_TXEN,
73 .ssc_disable = AT91_SSC_TXDIS,
74 .ssc_endx = AT91_SSC_ENDTX,
75 .ssc_endbuf = AT91_SSC_TXBUFE,
76 .pdc_enable = ATMEL_PDC_TXTEN,
77 .pdc_disable = ATMEL_PDC_TXTDIS,
78};
79
80static struct at91_ssc_mask ssc_rx_mask = {
81 .ssc_enable = AT91_SSC_RXEN,
82 .ssc_disable = AT91_SSC_RXDIS,
83 .ssc_endx = AT91_SSC_ENDRX,
84 .ssc_endbuf = AT91_SSC_RXBUFF,
85 .pdc_enable = ATMEL_PDC_RXTEN,
86 .pdc_disable = ATMEL_PDC_RXTDIS,
87};
88
89
90/*
91 * DMA parameters.
92 */
93static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
94 {{
95 .name = "SSC0 PCM out",
96 .pdc = &pdc_tx_reg,
97 .mask = &ssc_tx_mask,
98 },
99 {
100 .name = "SSC0 PCM in",
101 .pdc = &pdc_rx_reg,
102 .mask = &ssc_rx_mask,
103 }},
104#if NUM_SSC_DEVICES == 3
105 {{
106 .name = "SSC1 PCM out",
107 .pdc = &pdc_tx_reg,
108 .mask = &ssc_tx_mask,
109 },
110 {
111 .name = "SSC1 PCM in",
112 .pdc = &pdc_rx_reg,
113 .mask = &ssc_rx_mask,
114 }},
115 {{
116 .name = "SSC2 PCM out",
117 .pdc = &pdc_tx_reg,
118 .mask = &ssc_tx_mask,
119 },
120 {
121 .name = "SSC2 PCM in",
122 .pdc = &pdc_rx_reg,
123 .mask = &ssc_rx_mask,
124 }},
125#endif
126};
127
128struct at91_ssc_state {
129 u32 ssc_cmr;
130 u32 ssc_rcmr;
131 u32 ssc_rfmr;
132 u32 ssc_tcmr;
133 u32 ssc_tfmr;
134 u32 ssc_sr;
135 u32 ssc_imr;
136};
137
138static struct at91_ssc_info {
139 char *name;
140 struct at91_ssc_periph ssc;
141 spinlock_t lock; /* lock for dir_mask */
142 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
143 unsigned short initialized; /* 1=SSC has been initialized */
144 unsigned short daifmt;
145 unsigned short cmr_div;
146 unsigned short tcmr_period;
147 unsigned short rcmr_period;
148 struct at91_pcm_dma_params *dma_params[2];
149 struct at91_ssc_state ssc_state;
150
151} ssc_info[NUM_SSC_DEVICES] = {
152 {
153 .name = "ssc0",
154 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
155 .dir_mask = 0,
156 .initialized = 0,
157 },
158#if NUM_SSC_DEVICES == 3
159 {
160 .name = "ssc1",
161 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
162 .dir_mask = 0,
163 .initialized = 0,
164 },
165 {
166 .name = "ssc2",
167 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
168 .dir_mask = 0,
169 .initialized = 0,
170 },
171#endif
172};
173
174static unsigned int at91_ssc_sysclk;
175
176/*
177 * SSC interrupt handler. Passes PDC interrupts to the DMA
178 * interrupt handler in the PCM driver.
179 */
180static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
181{
182 struct at91_ssc_info *ssc_p = dev_id;
183 struct at91_pcm_dma_params *dma_params;
184 u32 ssc_sr;
185 int i;
186
187 ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
188 & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
189
190 /*
191 * Loop through the substreams attached to this SSC. If
192 * a DMA-related interrupt occurred on that substream, call
193 * the DMA interrupt handler function, if one has been
194 * registered in the dma_params structure by the PCM driver.
195 */
196 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
197 dma_params = ssc_p->dma_params[i];
198
199 if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
200 (ssc_sr &
201 (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
202
203 dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
204 }
205
206 return IRQ_HANDLED;
207}
208
209/*
210 * Startup. Only that one substream allowed in each direction.
211 */
212static int at91_ssc_startup(struct snd_pcm_substream *substream)
213{
214 struct snd_soc_pcm_runtime *rtd = substream->private_data;
215 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
216 int dir_mask;
217
218 DBG("ssc_startup: SSC_SR=0x%08lx\n",
219 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
220 dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
221
222 spin_lock_irq(&ssc_p->lock);
223 if (ssc_p->dir_mask & dir_mask) {
224 spin_unlock_irq(&ssc_p->lock);
225 return -EBUSY;
226 }
227 ssc_p->dir_mask |= dir_mask;
228 spin_unlock_irq(&ssc_p->lock);
229
230 return 0;
231}
232
233/*
234 * Shutdown. Clear DMA parameters and shutdown the SSC if there
235 * are no other substreams open.
236 */
237static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
238{
239 struct snd_soc_pcm_runtime *rtd = substream->private_data;
240 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
241 struct at91_pcm_dma_params *dma_params;
242 int dir, dir_mask;
243
244 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
245 dma_params = ssc_p->dma_params[dir];
246
247 if (dma_params != NULL) {
248 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
249 dma_params->mask->ssc_disable);
250 DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
251 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
252
253 dma_params->ssc_base = NULL;
254 dma_params->substream = NULL;
255 ssc_p->dma_params[dir] = NULL;
256 }
257
258 dir_mask = 1 << dir;
259
260 spin_lock_irq(&ssc_p->lock);
261 ssc_p->dir_mask &= ~dir_mask;
262 if (!ssc_p->dir_mask) {
263 /* Shutdown the SSC clock. */
264 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
265 at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
266
267 if (ssc_p->initialized) {
268 free_irq(ssc_p->ssc.pid, ssc_p);
269 ssc_p->initialized = 0;
270 }
271
272 /* Reset the SSC */
273 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
274
275 /* Clear the SSC dividers */
276 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
277 }
278 spin_unlock_irq(&ssc_p->lock);
279}
280
281/*
282 * Record the SSC system clock rate.
283 */
284static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
285 int clk_id, unsigned int freq, int dir)
286{
287 /*
288 * The only clock supplied to the SSC is the AT91 master clock,
289 * which is only used if the SSC is generating BCLK and/or
290 * LRC clocks.
291 */
292 switch (clk_id) {
293 case AT91_SYSCLK_MCK:
294 at91_ssc_sysclk = freq;
295 break;
296 default:
297 return -EINVAL;
298 }
299
300 return 0;
301}
302
303/*
304 * Record the DAI format for use in hw_params().
305 */
306static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
307 unsigned int fmt)
308{
309 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
310
311 ssc_p->daifmt = fmt;
312 return 0;
313}
314
315/*
316 * Record SSC clock dividers for use in hw_params().
317 */
318static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
319 int div_id, int div)
320{
321 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
322
323 switch (div_id) {
324 case AT91SSC_CMR_DIV:
325 /*
326 * The same master clock divider is used for both
327 * transmit and receive, so if a value has already
328 * been set, it must match this value.
329 */
330 if (ssc_p->cmr_div == 0)
331 ssc_p->cmr_div = div;
332 else
333 if (div != ssc_p->cmr_div)
334 return -EBUSY;
335 break;
336
337 case AT91SSC_TCMR_PERIOD:
338 ssc_p->tcmr_period = div;
339 break;
340
341 case AT91SSC_RCMR_PERIOD:
342 ssc_p->rcmr_period = div;
343 break;
344
345 default:
346 return -EINVAL;
347 }
348
349 return 0;
350}
351
352/*
353 * Configure the SSC.
354 */
355static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
356 struct snd_pcm_hw_params *params)
357{
358 struct snd_soc_pcm_runtime *rtd = substream->private_data;
359 int id = rtd->dai->cpu_dai->id;
360 struct at91_ssc_info *ssc_p = &ssc_info[id];
361 struct at91_pcm_dma_params *dma_params;
362 int dir, channels, bits;
363 u32 tfmr, rfmr, tcmr, rcmr;
364 int start_event;
365 int ret;
366
367 /*
368 * Currently, there is only one set of dma params for
369 * each direction. If more are added, this code will
370 * have to be changed to select the proper set.
371 */
372 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
373
374 dma_params = &ssc_dma_params[id][dir];
375 dma_params->ssc_base = ssc_p->ssc.base;
376 dma_params->substream = substream;
377
378 ssc_p->dma_params[dir] = dma_params;
379
380 /*
381 * The cpu_dai->dma_data field is only used to communicate the
382 * appropriate DMA parameters to the pcm driver hw_params()
383 * function. It should not be used for other purposes
384 * as it is common to all substreams.
385 */
386 rtd->dai->cpu_dai->dma_data = dma_params;
387
388 channels = params_channels(params);
389
390 /*
391 * Determine sample size in bits and the PDC increment.
392 */
393 switch(params_format(params)) {
394 case SNDRV_PCM_FORMAT_S8:
395 bits = 8;
396 dma_params->pdc_xfer_size = 1;
397 break;
398 case SNDRV_PCM_FORMAT_S16_LE:
399 bits = 16;
400 dma_params->pdc_xfer_size = 2;
401 break;
402 case SNDRV_PCM_FORMAT_S24_LE:
403 bits = 24;
404 dma_params->pdc_xfer_size = 4;
405 break;
406 case SNDRV_PCM_FORMAT_S32_LE:
407 bits = 32;
408 dma_params->pdc_xfer_size = 4;
409 break;
410 default:
411 printk(KERN_WARNING "at91-ssc: unsupported PCM format\n");
412 return -EINVAL;
413 }
414
415 /*
416 * The SSC only supports up to 16-bit samples in I2S format, due
417 * to the size of the Frame Mode Register FSLEN field.
418 */
419 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
420 && bits > 16) {
421 printk(KERN_WARNING
422 "at91-ssc: sample size %d is too large for I2S\n", bits);
423 return -EINVAL;
424 }
425
426 /*
427 * Compute SSC register settings.
428 */
429 switch (ssc_p->daifmt
430 & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
431
432 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
433 /*
434 * I2S format, SSC provides BCLK and LRC clocks.
435 *
436 * The SSC transmit and receive clocks are generated from the
437 * MCK divider, and the BCLK signal is output on the SSC TK line.
438 */
439 rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
440 | (( 1 << 16) & AT91_SSC_STTDLY)
441 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
442 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
443 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
444 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
445
446 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
447 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
448 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
449 | (((channels - 1) << 8) & AT91_SSC_DATNB)
450 | (( 1 << 7) & AT91_SSC_MSBF)
451 | (( 0 << 5) & AT91_SSC_LOOP)
452 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
453
454 tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
455 | (( 1 << 16) & AT91_SSC_STTDLY)
456 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
457 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
458 | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
459 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
460
461 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
462 | (( 0 << 23) & AT91_SSC_FSDEN)
463 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
464 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
465 | (((channels - 1) << 8) & AT91_SSC_DATNB)
466 | (( 1 << 7) & AT91_SSC_MSBF)
467 | (( 0 << 5) & AT91_SSC_DATDEF)
468 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
469 break;
470
471 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
472 /*
473 * I2S format, CODEC supplies BCLK and LRC clocks.
474 *
475 * The SSC transmit clock is obtained from the BCLK signal on
476 * on the TK line, and the SSC receive clock is generated from the
477 * transmit clock.
478 *
479 * For single channel data, one sample is transferred on the falling
480 * edge of the LRC clock. For two channel data, one sample is
481 * transferred on both edges of the LRC clock.
482 */
483 start_event = channels == 1
484 ? AT91_SSC_START_FALLING_RF
485 : AT91_SSC_START_EDGE_RF;
486
487 rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
488 | (( 1 << 16) & AT91_SSC_STTDLY)
489 | (( start_event ) & AT91_SSC_START)
490 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
491 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
492 | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
493
494 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
495 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
496 | (( 0 << 16) & AT91_SSC_FSLEN)
497 | (( 0 << 8) & AT91_SSC_DATNB)
498 | (( 1 << 7) & AT91_SSC_MSBF)
499 | (( 0 << 5) & AT91_SSC_LOOP)
500 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
501
502 tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
503 | (( 1 << 16) & AT91_SSC_STTDLY)
504 | (( start_event ) & AT91_SSC_START)
505 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
506 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
507 | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
508
509 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
510 | (( 0 << 23) & AT91_SSC_FSDEN)
511 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
512 | (( 0 << 16) & AT91_SSC_FSLEN)
513 | (( 0 << 8) & AT91_SSC_DATNB)
514 | (( 1 << 7) & AT91_SSC_MSBF)
515 | (( 0 << 5) & AT91_SSC_DATDEF)
516 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
517 break;
518
519 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
520 /*
521 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
522 *
523 * The SSC transmit and receive clocks are generated from the
524 * MCK divider, and the BCLK signal is output on the SSC TK line.
525 */
526 rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
527 | (( 1 << 16) & AT91_SSC_STTDLY)
528 | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
529 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
530 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
531 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
532
533 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
534 | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
535 | (( 0 << 16) & AT91_SSC_FSLEN)
536 | (((channels - 1) << 8) & AT91_SSC_DATNB)
537 | (( 1 << 7) & AT91_SSC_MSBF)
538 | (( 0 << 5) & AT91_SSC_LOOP)
539 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
540
541 tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
542 | (( 1 << 16) & AT91_SSC_STTDLY)
543 | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
544 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
545 | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
546 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
547
548 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
549 | (( 0 << 23) & AT91_SSC_FSDEN)
550 | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
551 | (( 0 << 16) & AT91_SSC_FSLEN)
552 | (((channels - 1) << 8) & AT91_SSC_DATNB)
553 | (( 1 << 7) & AT91_SSC_MSBF)
554 | (( 0 << 5) & AT91_SSC_DATDEF)
555 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
556
557
558
559 break;
560
561 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
562 default:
563 printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
564 ssc_p->daifmt);
565 return -EINVAL;
566 break;
567 }
568 DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
569
570 if (!ssc_p->initialized) {
571
572 /* Enable PMC peripheral clock for this SSC */
573 DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
574 at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
575
576 /* Reset the SSC and its PDC registers */
577 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
578
579 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
580 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
581 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
582 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
583 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
584 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
585 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
586 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
587
588 if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
589 0, ssc_p->name, ssc_p)) < 0) {
590 printk(KERN_WARNING "at91-ssc: request_irq failure\n");
591
592 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
593 at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
594 return ret;
595 }
596
597 ssc_p->initialized = 1;
598 }
599
600 /* set SSC clock mode register */
601 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
602
603 /* set receive clock mode and format */
604 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
605 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
606
607 /* set transmit clock mode and format */
608 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
609 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
610
611 DBG("hw_params: SSC initialized\n");
612 return 0;
613}
614
615
616static int at91_ssc_prepare(struct snd_pcm_substream *substream)
617{
618 struct snd_soc_pcm_runtime *rtd = substream->private_data;
619 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
620 struct at91_pcm_dma_params *dma_params;
621 int dir;
622
623 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
624 dma_params = ssc_p->dma_params[dir];
625
626 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
627 dma_params->mask->ssc_enable);
628
629 DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
630 at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
631 return 0;
632}
633
634
635#ifdef CONFIG_PM
636static int at91_ssc_suspend(struct platform_device *pdev,
637 struct snd_soc_dai *cpu_dai)
638{
639 struct at91_ssc_info *ssc_p;
640
641 if(!cpu_dai->active)
642 return 0;
643
644 ssc_p = &ssc_info[cpu_dai->id];
645
646 /* Save the status register before disabling transmit and receive. */
647 ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
648 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
649 AT91_SSC_TXDIS | AT91_SSC_RXDIS);
650
651 /* Save the current interrupt mask, then disable unmasked interrupts. */
652 ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
653 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
654
655 ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
656 ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
657 ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
658 ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
659 ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
660
661 return 0;
662}
663
664static int at91_ssc_resume(struct platform_device *pdev,
665 struct snd_soc_dai *cpu_dai)
666{
667 struct at91_ssc_info *ssc_p;
668
669 if(!cpu_dai->active)
670 return 0;
671
672 ssc_p = &ssc_info[cpu_dai->id];
673
674 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
675 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
676 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
677 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
678 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
679
680 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
681
682 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
683 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
684 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
685
686 return 0;
687}
688
689#else
690#define at91_ssc_suspend NULL
691#define at91_ssc_resume NULL
692#endif
693
694#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
695 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
696 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
697 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
698 SNDRV_PCM_RATE_96000)
699
700#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
701 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
702
703struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
704 { .name = "at91-ssc0",
705 .id = 0,
706 .type = SND_SOC_DAI_PCM,
707 .suspend = at91_ssc_suspend,
708 .resume = at91_ssc_resume,
709 .playback = {
710 .channels_min = 1,
711 .channels_max = 2,
712 .rates = AT91_SSC_RATES,
713 .formats = AT91_SSC_FORMATS,},
714 .capture = {
715 .channels_min = 1,
716 .channels_max = 2,
717 .rates = AT91_SSC_RATES,
718 .formats = AT91_SSC_FORMATS,},
719 .ops = {
720 .startup = at91_ssc_startup,
721 .shutdown = at91_ssc_shutdown,
722 .prepare = at91_ssc_prepare,
723 .hw_params = at91_ssc_hw_params,},
724 .dai_ops = {
725 .set_sysclk = at91_ssc_set_dai_sysclk,
726 .set_fmt = at91_ssc_set_dai_fmt,
727 .set_clkdiv = at91_ssc_set_dai_clkdiv,},
728 .private_data = &ssc_info[0].ssc,
729 },
730#if NUM_SSC_DEVICES == 3
731 { .name = "at91-ssc1",
732 .id = 1,
733 .type = SND_SOC_DAI_PCM,
734 .suspend = at91_ssc_suspend,
735 .resume = at91_ssc_resume,
736 .playback = {
737 .channels_min = 1,
738 .channels_max = 2,
739 .rates = AT91_SSC_RATES,
740 .formats = AT91_SSC_FORMATS,},
741 .capture = {
742 .channels_min = 1,
743 .channels_max = 2,
744 .rates = AT91_SSC_RATES,
745 .formats = AT91_SSC_FORMATS,},
746 .ops = {
747 .startup = at91_ssc_startup,
748 .shutdown = at91_ssc_shutdown,
749 .prepare = at91_ssc_prepare,
750 .hw_params = at91_ssc_hw_params,},
751 .dai_ops = {
752 .set_sysclk = at91_ssc_set_dai_sysclk,
753 .set_fmt = at91_ssc_set_dai_fmt,
754 .set_clkdiv = at91_ssc_set_dai_clkdiv,},
755 .private_data = &ssc_info[1].ssc,
756 },
757 { .name = "at91-ssc2",
758 .id = 2,
759 .type = SND_SOC_DAI_PCM,
760 .suspend = at91_ssc_suspend,
761 .resume = at91_ssc_resume,
762 .playback = {
763 .channels_min = 1,
764 .channels_max = 2,
765 .rates = AT91_SSC_RATES,
766 .formats = AT91_SSC_FORMATS,},
767 .capture = {
768 .channels_min = 1,
769 .channels_max = 2,
770 .rates = AT91_SSC_RATES,
771 .formats = AT91_SSC_FORMATS,},
772 .ops = {
773 .startup = at91_ssc_startup,
774 .shutdown = at91_ssc_shutdown,
775 .prepare = at91_ssc_prepare,
776 .hw_params = at91_ssc_hw_params,},
777 .dai_ops = {
778 .set_sysclk = at91_ssc_set_dai_sysclk,
779 .set_fmt = at91_ssc_set_dai_fmt,
780 .set_clkdiv = at91_ssc_set_dai_clkdiv,},
781 .private_data = &ssc_info[2].ssc,
782 },
783#endif
784};
785
786EXPORT_SYMBOL_GPL(at91_ssc_dai);
787
788/* Module information */
789MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
790MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
791MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h
deleted file mode 100644
index 6b7bf382d06f..000000000000
--- a/sound/soc/at91/at91-ssc.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2 * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Jan 9, 2007
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _AT91_SSC_H
14#define _AT91_SSC_H
15
16/* SSC system clock ids */
17#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
18
19/* SSC divider ids */
20#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
21#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
22#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
23
24extern struct snd_soc_dai at91_ssc_dai[];
25
26#endif /* _AT91_SSC_H */
27
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
new file mode 100644
index 000000000000..a608d7009dbd
--- /dev/null
+++ b/sound/soc/atmel/Kconfig
@@ -0,0 +1,43 @@
1config SND_ATMEL_SOC
2 tristate "SoC Audio for the Atmel System-on-Chip"
3 depends on ARCH_AT91 || AVR32
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the ATMEL SSC interface. You will also need
7 to select the audio interfaces to support below.
8
9config SND_ATMEL_SOC_SSC
10 tristate
11 depends on SND_ATMEL_SOC
12 help
13 Say Y or M if you want to add support for codecs the
14 ATMEL SSC interface. You will also needs to select the individual
15 machine drivers to support below.
16
17config SND_AT91_SOC_SAM9G20_WM8731
18 tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
19 depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC
20 select SND_ATMEL_SOC_SSC
21 select SND_SOC_WM8731
22 help
23 Say Y if you want to add support for SoC audio on WM8731-based
24 AT91sam9g20 evaluation board.
25
26config SND_AT32_SOC_PLAYPAQ
27 tristate "SoC Audio support for PlayPaq with WM8510"
28 depends on SND_ATMEL_SOC && BOARD_PLAYPAQ
29 select SND_ATMEL_SOC_SSC
30 select SND_SOC_WM8510
31 help
32 Say Y or M here if you want to add support for SoC audio
33 on the LRS PlayPaq.
34
35config SND_AT32_SOC_PLAYPAQ_SLAVE
36 bool "Run CODEC on PlayPaq in slave mode"
37 depends on SND_AT32_SOC_PLAYPAQ
38 default n
39 help
40 Say Y if you want to run with the AT32 SSC generating the BCLK
41 and FRAME signals on the PlayPaq. Unless you want to play
42 with the AT32 as the SSC master, you probably want to say N here,
43 as this will give you better sound quality.
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
new file mode 100644
index 000000000000..f54a7cc68e66
--- /dev/null
+++ b/sound/soc/atmel/Makefile
@@ -0,0 +1,15 @@
1# AT91 Platform Support
2snd-soc-atmel-pcm-objs := atmel-pcm.o
3snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
4
5obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
6obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
7
8# AT91 Machine Support
9snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
10
11# AT32 Machine Support
12snd-soc-playpaq-objs := playpaq_wm8510.o
13
14obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
15obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/atmel/atmel-pcm.c
index c83584f989a9..394412fb396f 100644
--- a/sound/soc/at32/at32-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -1,15 +1,34 @@
1/* sound/soc/at32/at32-pcm.c 1/*
2 * ASoC PCM interface for Atmel AT32 SoC 2 * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC.
3 * 3 *
4 * Copyright (C) 2008 Long Range Systems 4 * Copyright (C) 2005 SAN People
5 * Geoffrey Wossum <gwossum@acm.org> 5 * Copyright (C) 2008 Atmel
6 *
7 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 *
9 * Based on at91-pcm. by:
10 * Frank Mandarino <fmandarino@endrelia.com>
11 * Copyright 2006 Endrelia Technologies Inc.
12 *
13 * Based on pxa2xx-pcm.c by:
14 *
15 * Author: Nicolas Pitre
16 * Created: Nov 30, 2004
17 * Copyright: (C) 2004 MontaVista Software, Inc.
6 * 18 *
7 * This program is free software; you can redistribute it and/or modify 19 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 20 * it under the terms of the GNU General Public License as published by
9 * published by the Free Software Foundation. 21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
10 * 23 *
11 * Note that this is basically a port of the sound/soc/at91-pcm.c to 24 * This program is distributed in the hope that it will be useful,
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code. 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13 */ 32 */
14 33
15#include <linux/module.h> 34#include <linux/module.h>
@@ -18,14 +37,16 @@
18#include <linux/slab.h> 37#include <linux/slab.h>
19#include <linux/dma-mapping.h> 38#include <linux/dma-mapping.h>
20#include <linux/atmel_pdc.h> 39#include <linux/atmel_pdc.h>
40#include <linux/atmel-ssc.h>
21 41
22#include <sound/core.h> 42#include <sound/core.h>
23#include <sound/pcm.h> 43#include <sound/pcm.h>
24#include <sound/pcm_params.h> 44#include <sound/pcm_params.h>
25#include <sound/soc.h> 45#include <sound/soc.h>
26 46
27#include "at32-pcm.h" 47#include <mach/hardware.h>
28 48
49#include "atmel-pcm.h"
29 50
30 51
31/*--------------------------------------------------------------------------*\ 52/*--------------------------------------------------------------------------*\
@@ -34,36 +55,33 @@
34/* TODO: These values were taken from the AT91 platform driver, check 55/* TODO: These values were taken from the AT91 platform driver, check
35 * them against real values for AT32 56 * them against real values for AT32
36 */ 57 */
37static const struct snd_pcm_hardware at32_pcm_hardware = { 58static const struct snd_pcm_hardware atmel_pcm_hardware = {
38 .info = (SNDRV_PCM_INFO_MMAP | 59 .info = SNDRV_PCM_INFO_MMAP |
39 SNDRV_PCM_INFO_MMAP_VALID | 60 SNDRV_PCM_INFO_MMAP_VALID |
40 SNDRV_PCM_INFO_INTERLEAVED | 61 SNDRV_PCM_INFO_INTERLEAVED |
41 SNDRV_PCM_INFO_BLOCK_TRANSFER | 62 SNDRV_PCM_INFO_PAUSE,
42 SNDRV_PCM_INFO_PAUSE), 63 .formats = SNDRV_PCM_FMTBIT_S16_LE,
43 64 .period_bytes_min = 32,
44 .formats = SNDRV_PCM_FMTBIT_S16, 65 .period_bytes_max = 8192,
45 .period_bytes_min = 32, 66 .periods_min = 2,
46 .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */ 67 .periods_max = 1024,
47 .periods_min = 2, 68 .buffer_bytes_max = 32 * 1024,
48 .periods_max = 1024,
49 .buffer_bytes_max = 32 * 1024,
50}; 69};
51 70
52 71
53
54/*--------------------------------------------------------------------------*\ 72/*--------------------------------------------------------------------------*\
55 * Data types 73 * Data types
56\*--------------------------------------------------------------------------*/ 74\*--------------------------------------------------------------------------*/
57struct at32_runtime_data { 75struct atmel_runtime_data {
58 struct at32_pcm_dma_params *params; 76 struct atmel_pcm_dma_params *params;
59 dma_addr_t dma_buffer; /* physical address of DMA buffer */ 77 dma_addr_t dma_buffer; /* physical address of dma buffer */
60 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ 78 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
61 size_t period_size; 79 size_t period_size;
62 80
63 dma_addr_t period_ptr; /* physical address of next period */ 81 dma_addr_t period_ptr; /* physical address of next period */
64 int periods; /* period index of period_ptr */ 82 int periods; /* period index of period_ptr */
65 83
66 /* Save PDC registers (for power management) */ 84 /* PDC register save */
67 u32 pdc_xpr_save; 85 u32 pdc_xpr_save;
68 u32 pdc_xcr_save; 86 u32 pdc_xcr_save;
69 u32 pdc_xnpr_save; 87 u32 pdc_xnpr_save;
@@ -71,49 +89,51 @@ struct at32_runtime_data {
71}; 89};
72 90
73 91
74
75/*--------------------------------------------------------------------------*\ 92/*--------------------------------------------------------------------------*\
76 * Helper functions 93 * Helper functions
77\*--------------------------------------------------------------------------*/ 94\*--------------------------------------------------------------------------*/
78static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 95static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
96 int stream)
79{ 97{
80 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 98 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
81 struct snd_dma_buffer *dmabuf = &substream->dma_buffer; 99 struct snd_dma_buffer *buf = &substream->dma_buffer;
82 size_t size = at32_pcm_hardware.buffer_bytes_max; 100 size_t size = atmel_pcm_hardware.buffer_bytes_max;
83 101
84 dmabuf->dev.type = SNDRV_DMA_TYPE_DEV; 102 buf->dev.type = SNDRV_DMA_TYPE_DEV;
85 dmabuf->dev.dev = pcm->card->dev; 103 buf->dev.dev = pcm->card->dev;
86 dmabuf->private_data = NULL; 104 buf->private_data = NULL;
87 dmabuf->area = dma_alloc_coherent(pcm->card->dev, size, 105 buf->area = dma_alloc_coherent(pcm->card->dev, size,
88 &dmabuf->addr, GFP_KERNEL); 106 &buf->addr, GFP_KERNEL);
89 pr_debug("at32_pcm: preallocate_dma_buffer: " 107 pr_debug("atmel-pcm:"
90 "area=%p, addr=%p, size=%ld\n", 108 "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
91 (void *)dmabuf->area, (void *)dmabuf->addr, size); 109 (void *) buf->area,
92 110 (void *) buf->addr,
93 if (!dmabuf->area) 111 size);
112
113 if (!buf->area)
94 return -ENOMEM; 114 return -ENOMEM;
95 115
96 dmabuf->bytes = size; 116 buf->bytes = size;
97 return 0; 117 return 0;
98} 118}
99
100
101
102/*--------------------------------------------------------------------------*\ 119/*--------------------------------------------------------------------------*\
103 * ISR 120 * ISR
104\*--------------------------------------------------------------------------*/ 121\*--------------------------------------------------------------------------*/
105static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream) 122static void atmel_pcm_dma_irq(u32 ssc_sr,
123 struct snd_pcm_substream *substream)
106{ 124{
107 struct snd_pcm_runtime *rtd = substream->runtime; 125 struct atmel_runtime_data *prtd = substream->runtime->private_data;
108 struct at32_runtime_data *prtd = rtd->private_data; 126 struct atmel_pcm_dma_params *params = prtd->params;
109 struct at32_pcm_dma_params *params = prtd->params;
110 static int count; 127 static int count;
111 128
112 count++; 129 count++;
130
113 if (ssc_sr & params->mask->ssc_endbuf) { 131 if (ssc_sr & params->mask->ssc_endbuf) {
114 pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n", 132 pr_warning("atmel-pcm: buffer %s on %s"
115 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 133 " (SSC_SR=%#x, count=%d)\n",
116 "underrun" : "overrun", params->name, ssc_sr, count); 134 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
135 ? "underrun" : "overrun",
136 params->name, ssc_sr, count);
117 137
118 /* re-start the PDC */ 138 /* re-start the PDC */
119 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, 139 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
@@ -122,7 +142,6 @@ static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
122 if (prtd->period_ptr >= prtd->dma_buffer_end) 142 if (prtd->period_ptr >= prtd->dma_buffer_end)
123 prtd->period_ptr = prtd->dma_buffer; 143 prtd->period_ptr = prtd->dma_buffer;
124 144
125
126 ssc_writex(params->ssc->regs, params->pdc->xpr, 145 ssc_writex(params->ssc->regs, params->pdc->xpr,
127 prtd->period_ptr); 146 prtd->period_ptr);
128 ssc_writex(params->ssc->regs, params->pdc->xcr, 147 ssc_writex(params->ssc->regs, params->pdc->xcr,
@@ -131,60 +150,58 @@ static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
131 params->mask->pdc_enable); 150 params->mask->pdc_enable);
132 } 151 }
133 152
134
135 if (ssc_sr & params->mask->ssc_endx) { 153 if (ssc_sr & params->mask->ssc_endx) {
136 /* Load the PDC next pointer and counter registers */ 154 /* Load the PDC next pointer and counter registers */
137 prtd->period_ptr += prtd->period_size; 155 prtd->period_ptr += prtd->period_size;
138 if (prtd->period_ptr >= prtd->dma_buffer_end) 156 if (prtd->period_ptr >= prtd->dma_buffer_end)
139 prtd->period_ptr = prtd->dma_buffer; 157 prtd->period_ptr = prtd->dma_buffer;
158
140 ssc_writex(params->ssc->regs, params->pdc->xnpr, 159 ssc_writex(params->ssc->regs, params->pdc->xnpr,
141 prtd->period_ptr); 160 prtd->period_ptr);
142 ssc_writex(params->ssc->regs, params->pdc->xncr, 161 ssc_writex(params->ssc->regs, params->pdc->xncr,
143 prtd->period_size / params->pdc_xfer_size); 162 prtd->period_size / params->pdc_xfer_size);
144 } 163 }
145 164
146
147 snd_pcm_period_elapsed(substream); 165 snd_pcm_period_elapsed(substream);
148} 166}
149 167
150 168
151
152/*--------------------------------------------------------------------------*\ 169/*--------------------------------------------------------------------------*\
153 * PCM operations 170 * PCM operations
154\*--------------------------------------------------------------------------*/ 171\*--------------------------------------------------------------------------*/
155static int at32_pcm_hw_params(struct snd_pcm_substream *substream, 172static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
156 struct snd_pcm_hw_params *params) 173 struct snd_pcm_hw_params *params)
157{ 174{
158 struct snd_pcm_runtime *runtime = substream->runtime; 175 struct snd_pcm_runtime *runtime = substream->runtime;
159 struct at32_runtime_data *prtd = runtime->private_data; 176 struct atmel_runtime_data *prtd = runtime->private_data;
160 struct snd_soc_pcm_runtime *rtd = substream->private_data; 177 struct snd_soc_pcm_runtime *rtd = substream->private_data;
161 178
162 /* this may get called several times by oss emulation 179 /* this may get called several times by oss emulation
163 * with different params 180 * with different params */
164 */ 181
165 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 182 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
166 runtime->dma_bytes = params_buffer_bytes(params); 183 runtime->dma_bytes = params_buffer_bytes(params);
167 184
168 prtd->params = rtd->dai->cpu_dai->dma_data; 185 prtd->params = rtd->dai->cpu_dai->dma_data;
169 prtd->params->dma_intr_handler = at32_pcm_dma_irq; 186 prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
170 187
171 prtd->dma_buffer = runtime->dma_addr; 188 prtd->dma_buffer = runtime->dma_addr;
172 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; 189 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
173 prtd->period_size = params_period_bytes(params); 190 prtd->period_size = params_period_bytes(params);
174 191
175 pr_debug("hw_params: DMA for %s initialized " 192 pr_debug("atmel-pcm: "
176 "(dma_bytes=%ld, period_size=%ld)\n", 193 "hw_params: DMA for %s initialized "
177 prtd->params->name, runtime->dma_bytes, prtd->period_size); 194 "(dma_bytes=%u, period_size=%u)\n",
178 195 prtd->params->name,
196 runtime->dma_bytes,
197 prtd->period_size);
179 return 0; 198 return 0;
180} 199}
181 200
182 201static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
183
184static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
185{ 202{
186 struct at32_runtime_data *prtd = substream->runtime->private_data; 203 struct atmel_runtime_data *prtd = substream->runtime->private_data;
187 struct at32_pcm_dma_params *params = prtd->params; 204 struct atmel_pcm_dma_params *params = prtd->params;
188 205
189 if (params != NULL) { 206 if (params != NULL) {
190 ssc_writex(params->ssc->regs, SSC_PDC_PTCR, 207 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
@@ -195,32 +212,29 @@ static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
195 return 0; 212 return 0;
196} 213}
197 214
198 215static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
199
200static int at32_pcm_prepare(struct snd_pcm_substream *substream)
201{ 216{
202 struct at32_runtime_data *prtd = substream->runtime->private_data; 217 struct atmel_runtime_data *prtd = substream->runtime->private_data;
203 struct at32_pcm_dma_params *params = prtd->params; 218 struct atmel_pcm_dma_params *params = prtd->params;
204 219
205 ssc_writex(params->ssc->regs, SSC_IDR, 220 ssc_writex(params->ssc->regs, SSC_IDR,
206 params->mask->ssc_endx | params->mask->ssc_endbuf); 221 params->mask->ssc_endx | params->mask->ssc_endbuf);
207 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, 222 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
208 params->mask->pdc_disable); 223 params->mask->pdc_disable);
209
210 return 0; 224 return 0;
211} 225}
212 226
213 227static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
214static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 228 int cmd)
215{ 229{
216 struct snd_pcm_runtime *rtd = substream->runtime; 230 struct snd_pcm_runtime *rtd = substream->runtime;
217 struct at32_runtime_data *prtd = rtd->private_data; 231 struct atmel_runtime_data *prtd = rtd->private_data;
218 struct at32_pcm_dma_params *params = prtd->params; 232 struct atmel_pcm_dma_params *params = prtd->params;
219 int ret = 0; 233 int ret = 0;
220 234
221 pr_debug("at32_pcm_trigger: buffer_size = %ld, " 235 pr_debug("atmel-pcm:buffer_size = %ld,"
222 "dma_area = %p, dma_bytes = %ld\n", 236 "dma_area = %p, dma_bytes = %u\n",
223 rtd->buffer_size, rtd->dma_area, rtd->dma_bytes); 237 rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
224 238
225 switch (cmd) { 239 switch (cmd) {
226 case SNDRV_PCM_TRIGGER_START: 240 case SNDRV_PCM_TRIGGER_START:
@@ -237,26 +251,25 @@ static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
237 ssc_writex(params->ssc->regs, params->pdc->xncr, 251 ssc_writex(params->ssc->regs, params->pdc->xncr,
238 prtd->period_size / params->pdc_xfer_size); 252 prtd->period_size / params->pdc_xfer_size);
239 253
240 pr_debug("trigger: period_ptr=%lx, xpr=%x, " 254 pr_debug("atmel-pcm: trigger: "
241 "xcr=%d, xnpr=%x, xncr=%d\n", 255 "period_ptr=%lx, xpr=%u, "
242 (unsigned long)prtd->period_ptr, 256 "xcr=%u, xnpr=%u, xncr=%u\n",
243 ssc_readx(params->ssc->regs, params->pdc->xpr), 257 (unsigned long)prtd->period_ptr,
244 ssc_readx(params->ssc->regs, params->pdc->xcr), 258 ssc_readx(params->ssc->regs, params->pdc->xpr),
245 ssc_readx(params->ssc->regs, params->pdc->xnpr), 259 ssc_readx(params->ssc->regs, params->pdc->xcr),
246 ssc_readx(params->ssc->regs, params->pdc->xncr)); 260 ssc_readx(params->ssc->regs, params->pdc->xnpr),
261 ssc_readx(params->ssc->regs, params->pdc->xncr));
247 262
248 ssc_writex(params->ssc->regs, SSC_IER, 263 ssc_writex(params->ssc->regs, SSC_IER,
249 params->mask->ssc_endx | params->mask->ssc_endbuf); 264 params->mask->ssc_endx | params->mask->ssc_endbuf);
250 ssc_writex(params->ssc->regs, SSC_PDC_PTCR, 265 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
251 params->mask->pdc_enable); 266 params->mask->pdc_enable);
252 267
253 pr_debug("sr=%x, imr=%x\n", 268 pr_debug("sr=%u imr=%u\n",
254 ssc_readx(params->ssc->regs, SSC_SR), 269 ssc_readx(params->ssc->regs, SSC_SR),
255 ssc_readx(params->ssc->regs, SSC_IER)); 270 ssc_readx(params->ssc->regs, SSC_IER));
256 break; /* SNDRV_PCM_TRIGGER_START */ 271 break; /* SNDRV_PCM_TRIGGER_START */
257 272
258
259
260 case SNDRV_PCM_TRIGGER_STOP: 273 case SNDRV_PCM_TRIGGER_STOP:
261 case SNDRV_PCM_TRIGGER_SUSPEND: 274 case SNDRV_PCM_TRIGGER_SUSPEND:
262 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 275 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -264,7 +277,6 @@ static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
264 params->mask->pdc_disable); 277 params->mask->pdc_disable);
265 break; 278 break;
266 279
267
268 case SNDRV_PCM_TRIGGER_RESUME: 280 case SNDRV_PCM_TRIGGER_RESUME:
269 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 281 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
270 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, 282 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
@@ -278,13 +290,12 @@ static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
278 return ret; 290 return ret;
279} 291}
280 292
281 293static snd_pcm_uframes_t atmel_pcm_pointer(
282 294 struct snd_pcm_substream *substream)
283static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
284{ 295{
285 struct snd_pcm_runtime *runtime = substream->runtime; 296 struct snd_pcm_runtime *runtime = substream->runtime;
286 struct at32_runtime_data *prtd = runtime->private_data; 297 struct atmel_runtime_data *prtd = runtime->private_data;
287 struct at32_pcm_dma_params *params = prtd->params; 298 struct atmel_pcm_dma_params *params = prtd->params;
288 dma_addr_t ptr; 299 dma_addr_t ptr;
289 snd_pcm_uframes_t x; 300 snd_pcm_uframes_t x;
290 301
@@ -297,108 +308,95 @@ static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
297 return x; 308 return x;
298} 309}
299 310
300 311static int atmel_pcm_open(struct snd_pcm_substream *substream)
301
302static int at32_pcm_open(struct snd_pcm_substream *substream)
303{ 312{
304 struct snd_pcm_runtime *runtime = substream->runtime; 313 struct snd_pcm_runtime *runtime = substream->runtime;
305 struct at32_runtime_data *prtd; 314 struct atmel_runtime_data *prtd;
306 int ret = 0; 315 int ret = 0;
307 316
308 snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware); 317 snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
309 318
310 /* ensure that buffer size is a multiple of period size */ 319 /* ensure that buffer size is a multiple of period size */
311 ret = snd_pcm_hw_constraint_integer(runtime, 320 ret = snd_pcm_hw_constraint_integer(runtime,
312 SNDRV_PCM_HW_PARAM_PERIODS); 321 SNDRV_PCM_HW_PARAM_PERIODS);
313 if (ret < 0) 322 if (ret < 0)
314 goto out; 323 goto out;
315 324
316 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 325 prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
317 if (prtd == NULL) { 326 if (prtd == NULL) {
318 ret = -ENOMEM; 327 ret = -ENOMEM;
319 goto out; 328 goto out;
320 } 329 }
321 runtime->private_data = prtd; 330 runtime->private_data = prtd;
322 331
323 332 out:
324out:
325 return ret; 333 return ret;
326} 334}
327 335
328 336static int atmel_pcm_close(struct snd_pcm_substream *substream)
329
330static int at32_pcm_close(struct snd_pcm_substream *substream)
331{ 337{
332 struct at32_runtime_data *prtd = substream->runtime->private_data; 338 struct atmel_runtime_data *prtd = substream->runtime->private_data;
333 339
334 kfree(prtd); 340 kfree(prtd);
335 return 0; 341 return 0;
336} 342}
337 343
338 344static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
339static int at32_pcm_mmap(struct snd_pcm_substream *substream, 345 struct vm_area_struct *vma)
340 struct vm_area_struct *vma)
341{ 346{
342 return remap_pfn_range(vma, vma->vm_start, 347 return remap_pfn_range(vma, vma->vm_start,
343 substream->dma_buffer.addr >> PAGE_SHIFT, 348 substream->dma_buffer.addr >> PAGE_SHIFT,
344 vma->vm_end - vma->vm_start, vma->vm_page_prot); 349 vma->vm_end - vma->vm_start, vma->vm_page_prot);
345} 350}
346 351
347 352struct snd_pcm_ops atmel_pcm_ops = {
348 353 .open = atmel_pcm_open,
349static struct snd_pcm_ops at32_pcm_ops = { 354 .close = atmel_pcm_close,
350 .open = at32_pcm_open, 355 .ioctl = snd_pcm_lib_ioctl,
351 .close = at32_pcm_close, 356 .hw_params = atmel_pcm_hw_params,
352 .ioctl = snd_pcm_lib_ioctl, 357 .hw_free = atmel_pcm_hw_free,
353 .hw_params = at32_pcm_hw_params, 358 .prepare = atmel_pcm_prepare,
354 .hw_free = at32_pcm_hw_free, 359 .trigger = atmel_pcm_trigger,
355 .prepare = at32_pcm_prepare, 360 .pointer = atmel_pcm_pointer,
356 .trigger = at32_pcm_trigger, 361 .mmap = atmel_pcm_mmap,
357 .pointer = at32_pcm_pointer,
358 .mmap = at32_pcm_mmap,
359}; 362};
360 363
361 364
362
363/*--------------------------------------------------------------------------*\ 365/*--------------------------------------------------------------------------*\
364 * ASoC platform driver 366 * ASoC platform driver
365\*--------------------------------------------------------------------------*/ 367\*--------------------------------------------------------------------------*/
366static u64 at32_pcm_dmamask = 0xffffffff; 368static u64 atmel_pcm_dmamask = 0xffffffff;
367 369
368static int at32_pcm_new(struct snd_card *card, 370static int atmel_pcm_new(struct snd_card *card,
369 struct snd_soc_dai *dai, 371 struct snd_soc_dai *dai, struct snd_pcm *pcm)
370 struct snd_pcm *pcm)
371{ 372{
372 int ret = 0; 373 int ret = 0;
373 374
374 if (!card->dev->dma_mask) 375 if (!card->dev->dma_mask)
375 card->dev->dma_mask = &at32_pcm_dmamask; 376 card->dev->dma_mask = &atmel_pcm_dmamask;
376 if (!card->dev->coherent_dma_mask) 377 if (!card->dev->coherent_dma_mask)
377 card->dev->coherent_dma_mask = 0xffffffff; 378 card->dev->coherent_dma_mask = 0xffffffff;
378 379
379 if (dai->playback.channels_min) { 380 if (dai->playback.channels_min) {
380 ret = at32_pcm_preallocate_dma_buffer( 381 ret = atmel_pcm_preallocate_dma_buffer(pcm,
381 pcm, SNDRV_PCM_STREAM_PLAYBACK); 382 SNDRV_PCM_STREAM_PLAYBACK);
382 if (ret) 383 if (ret)
383 goto out; 384 goto out;
384 } 385 }
385 386
386 if (dai->capture.channels_min) { 387 if (dai->capture.channels_min) {
387 pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n"); 388 pr_debug("at32-pcm:"
388 ret = at32_pcm_preallocate_dma_buffer( 389 "Allocating PCM capture DMA buffer\n");
389 pcm, SNDRV_PCM_STREAM_CAPTURE); 390 ret = atmel_pcm_preallocate_dma_buffer(pcm,
391 SNDRV_PCM_STREAM_CAPTURE);
390 if (ret) 392 if (ret)
391 goto out; 393 goto out;
392 } 394 }
393 395 out:
394
395out:
396 return ret; 396 return ret;
397} 397}
398 398
399 399static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
400
401static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
402{ 400{
403 struct snd_pcm_substream *substream; 401 struct snd_pcm_substream *substream;
404 struct snd_dma_buffer *buf; 402 struct snd_dma_buffer *buf;
@@ -406,7 +404,7 @@ static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
406 404
407 for (stream = 0; stream < 2; stream++) { 405 for (stream = 0; stream < 2; stream++) {
408 substream = pcm->streams[stream].substream; 406 substream = pcm->streams[stream].substream;
409 if (substream == NULL) 407 if (!substream)
410 continue; 408 continue;
411 409
412 buf = &substream->dma_buffer; 410 buf = &substream->dma_buffer;
@@ -418,24 +416,23 @@ static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
418 } 416 }
419} 417}
420 418
421
422
423#ifdef CONFIG_PM 419#ifdef CONFIG_PM
424static int at32_pcm_suspend(struct platform_device *pdev, 420static int atmel_pcm_suspend(struct platform_device *pdev,
425 struct snd_soc_dai *dai) 421 struct snd_soc_dai *dai)
426{ 422{
427 struct snd_pcm_runtime *runtime = dai->runtime; 423 struct snd_pcm_runtime *runtime = dai->runtime;
428 struct at32_runtime_data *prtd; 424 struct atmel_runtime_data *prtd;
429 struct at32_pcm_dma_params *params; 425 struct atmel_pcm_dma_params *params;
430 426
431 if (runtime == NULL) 427 if (!runtime)
432 return 0; 428 return 0;
429
433 prtd = runtime->private_data; 430 prtd = runtime->private_data;
434 params = prtd->params; 431 params = prtd->params;
435 432
436 /* Disable the PDC and save the PDC registers */ 433 /* disable the PDC and save the PDC registers */
437 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, 434
438 params->mask->pdc_disable); 435 ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
439 436
440 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr); 437 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
441 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr); 438 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
@@ -445,48 +442,43 @@ static int at32_pcm_suspend(struct platform_device *pdev,
445 return 0; 442 return 0;
446} 443}
447 444
448 445static int atmel_pcm_resume(struct platform_device *pdev,
449 446 struct snd_soc_dai *dai)
450static int at32_pcm_resume(struct platform_device *pdev,
451 struct snd_soc_dai *dai)
452{ 447{
453 struct snd_pcm_runtime *runtime = dai->runtime; 448 struct snd_pcm_runtime *runtime = dai->runtime;
454 struct at32_runtime_data *prtd; 449 struct atmel_runtime_data *prtd;
455 struct at32_pcm_dma_params *params; 450 struct atmel_pcm_dma_params *params;
456 451
457 if (runtime == NULL) 452 if (!runtime)
458 return 0; 453 return 0;
454
459 prtd = runtime->private_data; 455 prtd = runtime->private_data;
460 params = prtd->params; 456 params = prtd->params;
461 457
462 /* Restore the PDC registers and enable the PDC */ 458 /* restore the PDC registers and enable the PDC */
463 ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save); 459 ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
464 ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save); 460 ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
465 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save); 461 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
466 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save); 462 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
467 463
468 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable); 464 ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
469 return 0; 465 return 0;
470} 466}
471#else /* CONFIG_PM */ 467#else
472# define at32_pcm_suspend NULL 468#define atmel_pcm_suspend NULL
473# define at32_pcm_resume NULL 469#define atmel_pcm_resume NULL
474#endif /* CONFIG_PM */ 470#endif
475 471
476 472struct snd_soc_platform atmel_soc_platform = {
477 473 .name = "atmel-audio",
478struct snd_soc_platform at32_soc_platform = { 474 .pcm_ops = &atmel_pcm_ops,
479 .name = "at32-audio", 475 .pcm_new = atmel_pcm_new,
480 .pcm_ops = &at32_pcm_ops, 476 .pcm_free = atmel_pcm_free_dma_buffers,
481 .pcm_new = at32_pcm_new, 477 .suspend = atmel_pcm_suspend,
482 .pcm_free = at32_pcm_free_dma_buffers, 478 .resume = atmel_pcm_resume,
483 .suspend = at32_pcm_suspend,
484 .resume = at32_pcm_resume,
485}; 479};
486EXPORT_SYMBOL_GPL(at32_soc_platform); 480EXPORT_SYMBOL_GPL(atmel_soc_platform);
487
488
489 481
490MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>"); 482MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
491MODULE_DESCRIPTION("Atmel AT32 PCM module"); 483MODULE_DESCRIPTION("Atmel PCM module");
492MODULE_LICENSE("GPL"); 484MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
new file mode 100644
index 000000000000..ec9b2824b663
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -0,0 +1,86 @@
1/*
2 * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC.
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 *
9 * Based on at91-pcm. by:
10 * Frank Mandarino <fmandarino@endrelia.com>
11 * Copyright 2006 Endrelia Technologies Inc.
12 *
13 * Based on pxa2xx-pcm.c by:
14 *
15 * Author: Nicolas Pitre
16 * Created: Nov 30, 2004
17 * Copyright: (C) 2004 MontaVista Software, Inc.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#ifndef _ATMEL_PCM_H
35#define _ATMEL_PCM_H
36
37#include <linux/atmel-ssc.h>
38
39/*
40 * Registers and status bits that are required by the PCM driver.
41 */
42struct atmel_pdc_regs {
43 unsigned int xpr; /* PDC recv/trans pointer */
44 unsigned int xcr; /* PDC recv/trans counter */
45 unsigned int xnpr; /* PDC next recv/trans pointer */
46 unsigned int xncr; /* PDC next recv/trans counter */
47 unsigned int ptcr; /* PDC transfer control */
48};
49
50struct atmel_ssc_mask {
51 u32 ssc_enable; /* SSC recv/trans enable */
52 u32 ssc_disable; /* SSC recv/trans disable */
53 u32 ssc_endx; /* SSC ENDTX or ENDRX */
54 u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
55 u32 pdc_enable; /* PDC recv/trans enable */
56 u32 pdc_disable; /* PDC recv/trans disable */
57};
58
59/*
60 * This structure, shared between the PCM driver and the interface,
61 * contains all information required by the PCM driver to perform the
62 * PDC DMA operation. All fields except dma_intr_handler() are initialized
63 * by the interface. The dms_intr_handler() pointer is set by the PCM
64 * driver and called by the interface SSC interrupt handler if it is
65 * non-NULL.
66 */
67struct atmel_pcm_dma_params {
68 char *name; /* stream identifier */
69 int pdc_xfer_size; /* PDC counter increment in bytes */
70 struct ssc_device *ssc; /* SSC device for stream */
71 struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */
72 struct atmel_ssc_mask *mask; /* SSC & PDC status bits */
73 struct snd_pcm_substream *substream;
74 void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
75};
76
77extern struct snd_soc_platform atmel_soc_platform;
78
79
80/*
81 * SSC register access (since ssc_writel() / ssc_readl() require literal name)
82 */
83#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
84#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
85
86#endif /* _ATMEL_PCM_H */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
new file mode 100644
index 000000000000..d290b7894917
--- /dev/null
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -0,0 +1,782 @@
1/*
2 * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 * ATMEL CORP.
9 *
10 * Based on at91-ssc.c by
11 * Frank Mandarino <fmandarino@endrelia.com>
12 * Based on pxa2xx Platform drivers by
13 * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/init.h>
31#include <linux/module.h>
32#include <linux/interrupt.h>
33#include <linux/device.h>
34#include <linux/delay.h>
35#include <linux/clk.h>
36#include <linux/atmel_pdc.h>
37
38#include <linux/atmel-ssc.h>
39#include <sound/core.h>
40#include <sound/pcm.h>
41#include <sound/pcm_params.h>
42#include <sound/initval.h>
43#include <sound/soc.h>
44
45#include <mach/hardware.h>
46
47#include "atmel-pcm.h"
48#include "atmel_ssc_dai.h"
49
50
51#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
52#define NUM_SSC_DEVICES 1
53#else
54#define NUM_SSC_DEVICES 3
55#endif
56
57/*
58 * SSC PDC registers required by the PCM DMA engine.
59 */
60static struct atmel_pdc_regs pdc_tx_reg = {
61 .xpr = ATMEL_PDC_TPR,
62 .xcr = ATMEL_PDC_TCR,
63 .xnpr = ATMEL_PDC_TNPR,
64 .xncr = ATMEL_PDC_TNCR,
65};
66
67static struct atmel_pdc_regs pdc_rx_reg = {
68 .xpr = ATMEL_PDC_RPR,
69 .xcr = ATMEL_PDC_RCR,
70 .xnpr = ATMEL_PDC_RNPR,
71 .xncr = ATMEL_PDC_RNCR,
72};
73
74/*
75 * SSC & PDC status bits for transmit and receive.
76 */
77static struct atmel_ssc_mask ssc_tx_mask = {
78 .ssc_enable = SSC_BIT(CR_TXEN),
79 .ssc_disable = SSC_BIT(CR_TXDIS),
80 .ssc_endx = SSC_BIT(SR_ENDTX),
81 .ssc_endbuf = SSC_BIT(SR_TXBUFE),
82 .pdc_enable = ATMEL_PDC_TXTEN,
83 .pdc_disable = ATMEL_PDC_TXTDIS,
84};
85
86static struct atmel_ssc_mask ssc_rx_mask = {
87 .ssc_enable = SSC_BIT(CR_RXEN),
88 .ssc_disable = SSC_BIT(CR_RXDIS),
89 .ssc_endx = SSC_BIT(SR_ENDRX),
90 .ssc_endbuf = SSC_BIT(SR_RXBUFF),
91 .pdc_enable = ATMEL_PDC_RXTEN,
92 .pdc_disable = ATMEL_PDC_RXTDIS,
93};
94
95
96/*
97 * DMA parameters.
98 */
99static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
100 {{
101 .name = "SSC0 PCM out",
102 .pdc = &pdc_tx_reg,
103 .mask = &ssc_tx_mask,
104 },
105 {
106 .name = "SSC0 PCM in",
107 .pdc = &pdc_rx_reg,
108 .mask = &ssc_rx_mask,
109 } },
110#if NUM_SSC_DEVICES == 3
111 {{
112 .name = "SSC1 PCM out",
113 .pdc = &pdc_tx_reg,
114 .mask = &ssc_tx_mask,
115 },
116 {
117 .name = "SSC1 PCM in",
118 .pdc = &pdc_rx_reg,
119 .mask = &ssc_rx_mask,
120 } },
121 {{
122 .name = "SSC2 PCM out",
123 .pdc = &pdc_tx_reg,
124 .mask = &ssc_tx_mask,
125 },
126 {
127 .name = "SSC2 PCM in",
128 .pdc = &pdc_rx_reg,
129 .mask = &ssc_rx_mask,
130 } },
131#endif
132};
133
134
135static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
136 {
137 .name = "ssc0",
138 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
139 .dir_mask = SSC_DIR_MASK_UNUSED,
140 .initialized = 0,
141 },
142#if NUM_SSC_DEVICES == 3
143 {
144 .name = "ssc1",
145 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
146 .dir_mask = SSC_DIR_MASK_UNUSED,
147 .initialized = 0,
148 },
149 {
150 .name = "ssc2",
151 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
152 .dir_mask = SSC_DIR_MASK_UNUSED,
153 .initialized = 0,
154 },
155#endif
156};
157
158
159/*
160 * SSC interrupt handler. Passes PDC interrupts to the DMA
161 * interrupt handler in the PCM driver.
162 */
163static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
164{
165 struct atmel_ssc_info *ssc_p = dev_id;
166 struct atmel_pcm_dma_params *dma_params;
167 u32 ssc_sr;
168 u32 ssc_substream_mask;
169 int i;
170
171 ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR)
172 & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR);
173
174 /*
175 * Loop through the substreams attached to this SSC. If
176 * a DMA-related interrupt occurred on that substream, call
177 * the DMA interrupt handler function, if one has been
178 * registered in the dma_params structure by the PCM driver.
179 */
180 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
181 dma_params = ssc_p->dma_params[i];
182
183 if ((dma_params != NULL) &&
184 (dma_params->dma_intr_handler != NULL)) {
185 ssc_substream_mask = (dma_params->mask->ssc_endx |
186 dma_params->mask->ssc_endbuf);
187 if (ssc_sr & ssc_substream_mask) {
188 dma_params->dma_intr_handler(ssc_sr,
189 dma_params->
190 substream);
191 }
192 }
193 }
194
195 return IRQ_HANDLED;
196}
197
198
199/*-------------------------------------------------------------------------*\
200 * DAI functions
201\*-------------------------------------------------------------------------*/
202/*
203 * Startup. Only that one substream allowed in each direction.
204 */
205static int atmel_ssc_startup(struct snd_pcm_substream *substream)
206{
207 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
208 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
209 int dir_mask;
210
211 pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
212 ssc_readl(ssc_p->ssc->regs, SR));
213
214 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
215 dir_mask = SSC_DIR_MASK_PLAYBACK;
216 else
217 dir_mask = SSC_DIR_MASK_CAPTURE;
218
219 spin_lock_irq(&ssc_p->lock);
220 if (ssc_p->dir_mask & dir_mask) {
221 spin_unlock_irq(&ssc_p->lock);
222 return -EBUSY;
223 }
224 ssc_p->dir_mask |= dir_mask;
225 spin_unlock_irq(&ssc_p->lock);
226
227 return 0;
228}
229
230/*
231 * Shutdown. Clear DMA parameters and shutdown the SSC if there
232 * are no other substreams open.
233 */
234static void atmel_ssc_shutdown(struct snd_pcm_substream *substream)
235{
236 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
237 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
238 struct atmel_pcm_dma_params *dma_params;
239 int dir, dir_mask;
240
241 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
242 dir = 0;
243 else
244 dir = 1;
245
246 dma_params = ssc_p->dma_params[dir];
247
248 if (dma_params != NULL) {
249 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
250 pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
251 (dir ? "receive" : "transmit"),
252 ssc_readl(ssc_p->ssc->regs, SR));
253
254 dma_params->ssc = NULL;
255 dma_params->substream = NULL;
256 ssc_p->dma_params[dir] = NULL;
257 }
258
259 dir_mask = 1 << dir;
260
261 spin_lock_irq(&ssc_p->lock);
262 ssc_p->dir_mask &= ~dir_mask;
263 if (!ssc_p->dir_mask) {
264 if (ssc_p->initialized) {
265 /* Shutdown the SSC clock. */
266 pr_debug("atmel_ssc_dau: Stopping clock\n");
267 clk_disable(ssc_p->ssc->clk);
268
269 free_irq(ssc_p->ssc->irq, ssc_p);
270 ssc_p->initialized = 0;
271 }
272
273 /* Reset the SSC */
274 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
275 /* Clear the SSC dividers */
276 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
277 }
278 spin_unlock_irq(&ssc_p->lock);
279}
280
281
282/*
283 * Record the DAI format for use in hw_params().
284 */
285static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
286 unsigned int fmt)
287{
288 struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
289
290 ssc_p->daifmt = fmt;
291 return 0;
292}
293
294/*
295 * Record SSC clock dividers for use in hw_params().
296 */
297static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
298 int div_id, int div)
299{
300 struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
301
302 switch (div_id) {
303 case ATMEL_SSC_CMR_DIV:
304 /*
305 * The same master clock divider is used for both
306 * transmit and receive, so if a value has already
307 * been set, it must match this value.
308 */
309 if (ssc_p->cmr_div == 0)
310 ssc_p->cmr_div = div;
311 else
312 if (div != ssc_p->cmr_div)
313 return -EBUSY;
314 break;
315
316 case ATMEL_SSC_TCMR_PERIOD:
317 ssc_p->tcmr_period = div;
318 break;
319
320 case ATMEL_SSC_RCMR_PERIOD:
321 ssc_p->rcmr_period = div;
322 break;
323
324 default:
325 return -EINVAL;
326 }
327
328 return 0;
329}
330
331/*
332 * Configure the SSC.
333 */
334static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
335 struct snd_pcm_hw_params *params)
336{
337 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
338 int id = rtd->dai->cpu_dai->id;
339 struct atmel_ssc_info *ssc_p = &ssc_info[id];
340 struct atmel_pcm_dma_params *dma_params;
341 int dir, channels, bits;
342 u32 tfmr, rfmr, tcmr, rcmr;
343 int start_event;
344 int ret;
345
346 /*
347 * Currently, there is only one set of dma params for
348 * each direction. If more are added, this code will
349 * have to be changed to select the proper set.
350 */
351 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
352 dir = 0;
353 else
354 dir = 1;
355
356 dma_params = &ssc_dma_params[id][dir];
357 dma_params->ssc = ssc_p->ssc;
358 dma_params->substream = substream;
359
360 ssc_p->dma_params[dir] = dma_params;
361
362 /*
363 * The cpu_dai->dma_data field is only used to communicate the
364 * appropriate DMA parameters to the pcm driver hw_params()
365 * function. It should not be used for other purposes
366 * as it is common to all substreams.
367 */
368 rtd->dai->cpu_dai->dma_data = dma_params;
369
370 channels = params_channels(params);
371
372 /*
373 * Determine sample size in bits and the PDC increment.
374 */
375 switch (params_format(params)) {
376 case SNDRV_PCM_FORMAT_S8:
377 bits = 8;
378 dma_params->pdc_xfer_size = 1;
379 break;
380 case SNDRV_PCM_FORMAT_S16_LE:
381 bits = 16;
382 dma_params->pdc_xfer_size = 2;
383 break;
384 case SNDRV_PCM_FORMAT_S24_LE:
385 bits = 24;
386 dma_params->pdc_xfer_size = 4;
387 break;
388 case SNDRV_PCM_FORMAT_S32_LE:
389 bits = 32;
390 dma_params->pdc_xfer_size = 4;
391 break;
392 default:
393 printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format");
394 return -EINVAL;
395 }
396
397 /*
398 * The SSC only supports up to 16-bit samples in I2S format, due
399 * to the size of the Frame Mode Register FSLEN field.
400 */
401 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
402 && bits > 16) {
403 printk(KERN_WARNING
404 "atmel_ssc_dai: sample size %d"
405 "is too large for I2S\n", bits);
406 return -EINVAL;
407 }
408
409 /*
410 * Compute SSC register settings.
411 */
412 switch (ssc_p->daifmt
413 & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
414
415 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
416 /*
417 * I2S format, SSC provides BCLK and LRC clocks.
418 *
419 * The SSC transmit and receive clocks are generated
420 * from the MCK divider, and the BCLK signal
421 * is output on the SSC TK line.
422 */
423 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
424 | SSC_BF(RCMR_STTDLY, START_DELAY)
425 | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
426 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
427 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
428 | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
429
430 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
431 | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
432 | SSC_BF(RFMR_FSLEN, (bits - 1))
433 | SSC_BF(RFMR_DATNB, (channels - 1))
434 | SSC_BIT(RFMR_MSBF)
435 | SSC_BF(RFMR_LOOP, 0)
436 | SSC_BF(RFMR_DATLEN, (bits - 1));
437
438 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
439 | SSC_BF(TCMR_STTDLY, START_DELAY)
440 | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
441 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
442 | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
443 | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
444
445 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
446 | SSC_BF(TFMR_FSDEN, 0)
447 | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
448 | SSC_BF(TFMR_FSLEN, (bits - 1))
449 | SSC_BF(TFMR_DATNB, (channels - 1))
450 | SSC_BIT(TFMR_MSBF)
451 | SSC_BF(TFMR_DATDEF, 0)
452 | SSC_BF(TFMR_DATLEN, (bits - 1));
453 break;
454
455 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
456 /*
457 * I2S format, CODEC supplies BCLK and LRC clocks.
458 *
459 * The SSC transmit clock is obtained from the BCLK signal on
460 * on the TK line, and the SSC receive clock is
461 * generated from the transmit clock.
462 *
463 * For single channel data, one sample is transferred
464 * on the falling edge of the LRC clock.
465 * For two channel data, one sample is
466 * transferred on both edges of the LRC clock.
467 */
468 start_event = ((channels == 1)
469 ? SSC_START_FALLING_RF
470 : SSC_START_EDGE_RF);
471
472 rcmr = SSC_BF(RCMR_PERIOD, 0)
473 | SSC_BF(RCMR_STTDLY, START_DELAY)
474 | SSC_BF(RCMR_START, start_event)
475 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
476 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
477 | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
478
479 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
480 | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
481 | SSC_BF(RFMR_FSLEN, 0)
482 | SSC_BF(RFMR_DATNB, 0)
483 | SSC_BIT(RFMR_MSBF)
484 | SSC_BF(RFMR_LOOP, 0)
485 | SSC_BF(RFMR_DATLEN, (bits - 1));
486
487 tcmr = SSC_BF(TCMR_PERIOD, 0)
488 | SSC_BF(TCMR_STTDLY, START_DELAY)
489 | SSC_BF(TCMR_START, start_event)
490 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
491 | SSC_BF(TCMR_CKO, SSC_CKO_NONE)
492 | SSC_BF(TCMR_CKS, SSC_CKS_PIN);
493
494 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
495 | SSC_BF(TFMR_FSDEN, 0)
496 | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
497 | SSC_BF(TFMR_FSLEN, 0)
498 | SSC_BF(TFMR_DATNB, 0)
499 | SSC_BIT(TFMR_MSBF)
500 | SSC_BF(TFMR_DATDEF, 0)
501 | SSC_BF(TFMR_DATLEN, (bits - 1));
502 break;
503
504 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
505 /*
506 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
507 *
508 * The SSC transmit and receive clocks are generated from the
509 * MCK divider, and the BCLK signal is output
510 * on the SSC TK line.
511 */
512 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
513 | SSC_BF(RCMR_STTDLY, 1)
514 | SSC_BF(RCMR_START, SSC_START_RISING_RF)
515 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
516 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
517 | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
518
519 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
520 | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE)
521 | SSC_BF(RFMR_FSLEN, 0)
522 | SSC_BF(RFMR_DATNB, (channels - 1))
523 | SSC_BIT(RFMR_MSBF)
524 | SSC_BF(RFMR_LOOP, 0)
525 | SSC_BF(RFMR_DATLEN, (bits - 1));
526
527 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
528 | SSC_BF(TCMR_STTDLY, 1)
529 | SSC_BF(TCMR_START, SSC_START_RISING_RF)
530 | SSC_BF(TCMR_CKI, SSC_CKI_RISING)
531 | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
532 | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
533
534 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
535 | SSC_BF(TFMR_FSDEN, 0)
536 | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE)
537 | SSC_BF(TFMR_FSLEN, 0)
538 | SSC_BF(TFMR_DATNB, (channels - 1))
539 | SSC_BIT(TFMR_MSBF)
540 | SSC_BF(TFMR_DATDEF, 0)
541 | SSC_BF(TFMR_DATLEN, (bits - 1));
542 break;
543
544 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
545 default:
546 printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
547 ssc_p->daifmt);
548 return -EINVAL;
549 break;
550 }
551 pr_debug("atmel_ssc_hw_params: "
552 "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
553 rcmr, rfmr, tcmr, tfmr);
554
555 if (!ssc_p->initialized) {
556
557 /* Enable PMC peripheral clock for this SSC */
558 pr_debug("atmel_ssc_dai: Starting clock\n");
559 clk_enable(ssc_p->ssc->clk);
560
561 /* Reset the SSC and its PDC registers */
562 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
563
564 ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
565 ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
566 ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
567 ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
568
569 ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
570 ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
571 ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
572 ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
573
574 ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
575 ssc_p->name, ssc_p);
576 if (ret < 0) {
577 printk(KERN_WARNING
578 "atmel_ssc_dai: request_irq failure\n");
579 pr_debug("Atmel_ssc_dai: Stoping clock\n");
580 clk_disable(ssc_p->ssc->clk);
581 return ret;
582 }
583
584 ssc_p->initialized = 1;
585 }
586
587 /* set SSC clock mode register */
588 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
589
590 /* set receive clock mode and format */
591 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
592 ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
593
594 /* set transmit clock mode and format */
595 ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
596 ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
597
598 pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
599 return 0;
600}
601
602
603static int atmel_ssc_prepare(struct snd_pcm_substream *substream)
604{
605 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
606 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
607 struct atmel_pcm_dma_params *dma_params;
608 int dir;
609
610 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
611 dir = 0;
612 else
613 dir = 1;
614
615 dma_params = ssc_p->dma_params[dir];
616
617 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
618
619 pr_debug("%s enabled SSC_SR=0x%08x\n",
620 dir ? "receive" : "transmit",
621 ssc_readl(ssc_p->ssc->regs, SR));
622 return 0;
623}
624
625
626#ifdef CONFIG_PM
627static int atmel_ssc_suspend(struct platform_device *pdev,
628 struct snd_soc_dai *cpu_dai)
629{
630 struct atmel_ssc_info *ssc_p;
631
632 if (!cpu_dai->active)
633 return 0;
634
635 ssc_p = &ssc_info[cpu_dai->id];
636
637 /* Save the status register before disabling transmit and receive */
638 ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
639 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
640
641 /* Save the current interrupt mask, then disable unmasked interrupts */
642 ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
643 ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
644
645 ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
646 ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
647 ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
648 ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
649 ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
650
651 return 0;
652}
653
654
655
656static int atmel_ssc_resume(struct platform_device *pdev,
657 struct snd_soc_dai *cpu_dai)
658{
659 struct atmel_ssc_info *ssc_p;
660 u32 cr;
661
662 if (!cpu_dai->active)
663 return 0;
664
665 ssc_p = &ssc_info[cpu_dai->id];
666
667 /* restore SSC register settings */
668 ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
669 ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
670 ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
671 ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
672 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
673
674 /* re-enable interrupts */
675 ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
676
677 /* Re-enable recieve and transmit as appropriate */
678 cr = 0;
679 cr |=
680 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
681 cr |=
682 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
683 ssc_writel(ssc_p->ssc->regs, CR, cr);
684
685 return 0;
686}
687#else /* CONFIG_PM */
688# define atmel_ssc_suspend NULL
689# define atmel_ssc_resume NULL
690#endif /* CONFIG_PM */
691
692
693#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
694
695#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
696 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
697
698struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
699 { .name = "atmel-ssc0",
700 .id = 0,
701 .type = SND_SOC_DAI_PCM,
702 .suspend = atmel_ssc_suspend,
703 .resume = atmel_ssc_resume,
704 .playback = {
705 .channels_min = 1,
706 .channels_max = 2,
707 .rates = ATMEL_SSC_RATES,
708 .formats = ATMEL_SSC_FORMATS,},
709 .capture = {
710 .channels_min = 1,
711 .channels_max = 2,
712 .rates = ATMEL_SSC_RATES,
713 .formats = ATMEL_SSC_FORMATS,},
714 .ops = {
715 .startup = atmel_ssc_startup,
716 .shutdown = atmel_ssc_shutdown,
717 .prepare = atmel_ssc_prepare,
718 .hw_params = atmel_ssc_hw_params,},
719 .dai_ops = {
720 .set_fmt = atmel_ssc_set_dai_fmt,
721 .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
722 .private_data = &ssc_info[0],
723 },
724#if NUM_SSC_DEVICES == 3
725 { .name = "atmel-ssc1",
726 .id = 1,
727 .type = SND_SOC_DAI_PCM,
728 .suspend = atmel_ssc_suspend,
729 .resume = atmel_ssc_resume,
730 .playback = {
731 .channels_min = 1,
732 .channels_max = 2,
733 .rates = ATMEL_SSC_RATES,
734 .formats = ATMEL_SSC_FORMATS,},
735 .capture = {
736 .channels_min = 1,
737 .channels_max = 2,
738 .rates = ATMEL_SSC_RATES,
739 .formats = ATMEL_SSC_FORMATS,},
740 .ops = {
741 .startup = atmel_ssc_startup,
742 .shutdown = atmel_ssc_shutdown,
743 .prepare = atmel_ssc_prepare,
744 .hw_params = atmel_ssc_hw_params,},
745 .dai_ops = {
746 .set_fmt = atmel_ssc_set_dai_fmt,
747 .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
748 .private_data = &ssc_info[1],
749 },
750 { .name = "atmel-ssc2",
751 .id = 2,
752 .type = SND_SOC_DAI_PCM,
753 .suspend = atmel_ssc_suspend,
754 .resume = atmel_ssc_resume,
755 .playback = {
756 .channels_min = 1,
757 .channels_max = 2,
758 .rates = ATMEL_SSC_RATES,
759 .formats = ATMEL_SSC_FORMATS,},
760 .capture = {
761 .channels_min = 1,
762 .channels_max = 2,
763 .rates = ATMEL_SSC_RATES,
764 .formats = ATMEL_SSC_FORMATS,},
765 .ops = {
766 .startup = atmel_ssc_startup,
767 .shutdown = atmel_ssc_shutdown,
768 .prepare = atmel_ssc_prepare,
769 .hw_params = atmel_ssc_hw_params,},
770 .dai_ops = {
771 .set_fmt = atmel_ssc_set_dai_fmt,
772 .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
773 .private_data = &ssc_info[2],
774 },
775#endif
776};
777EXPORT_SYMBOL_GPL(atmel_ssc_dai);
778
779/* Module information */
780MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
781MODULE_DESCRIPTION("ATMEL SSC ASoC Interface");
782MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
new file mode 100644
index 000000000000..a828746e8a2f
--- /dev/null
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -0,0 +1,121 @@
1/*
2 * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 * ATMEL CORP.
9 *
10 * Based on at91-ssc.c by
11 * Frank Mandarino <fmandarino@endrelia.com>
12 * Based on pxa2xx Platform drivers by
13 * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#ifndef _ATMEL_SSC_DAI_H
31#define _ATMEL_SSC_DAI_H
32
33#include <linux/types.h>
34#include <linux/atmel-ssc.h>
35
36#include "atmel-pcm.h"
37
38/* SSC system clock ids */
39#define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
40
41/* SSC divider ids */
42#define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */
43#define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
44#define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
45/*
46 * SSC direction masks
47 */
48#define SSC_DIR_MASK_UNUSED 0
49#define SSC_DIR_MASK_PLAYBACK 1
50#define SSC_DIR_MASK_CAPTURE 2
51
52/*
53 * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
54 * are expected to be used with SSC_BF
55 */
56/* START bit field values */
57#define SSC_START_CONTINUOUS 0
58#define SSC_START_TX_RX 1
59#define SSC_START_LOW_RF 2
60#define SSC_START_HIGH_RF 3
61#define SSC_START_FALLING_RF 4
62#define SSC_START_RISING_RF 5
63#define SSC_START_LEVEL_RF 6
64#define SSC_START_EDGE_RF 7
65#define SSS_START_COMPARE_0 8
66
67/* CKI bit field values */
68#define SSC_CKI_FALLING 0
69#define SSC_CKI_RISING 1
70
71/* CKO bit field values */
72#define SSC_CKO_NONE 0
73#define SSC_CKO_CONTINUOUS 1
74#define SSC_CKO_TRANSFER 2
75
76/* CKS bit field values */
77#define SSC_CKS_DIV 0
78#define SSC_CKS_CLOCK 1
79#define SSC_CKS_PIN 2
80
81/* FSEDGE bit field values */
82#define SSC_FSEDGE_POSITIVE 0
83#define SSC_FSEDGE_NEGATIVE 1
84
85/* FSOS bit field values */
86#define SSC_FSOS_NONE 0
87#define SSC_FSOS_NEGATIVE 1
88#define SSC_FSOS_POSITIVE 2
89#define SSC_FSOS_LOW 3
90#define SSC_FSOS_HIGH 4
91#define SSC_FSOS_TOGGLE 5
92
93#define START_DELAY 1
94
95struct atmel_ssc_state {
96 u32 ssc_cmr;
97 u32 ssc_rcmr;
98 u32 ssc_rfmr;
99 u32 ssc_tcmr;
100 u32 ssc_tfmr;
101 u32 ssc_sr;
102 u32 ssc_imr;
103};
104
105
106struct atmel_ssc_info {
107 char *name;
108 struct ssc_device *ssc;
109 spinlock_t lock; /* lock for dir_mask */
110 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
111 unsigned short initialized; /* true if SSC has been initialized */
112 unsigned short daifmt;
113 unsigned short cmr_div;
114 unsigned short tcmr_period;
115 unsigned short rcmr_period;
116 struct atmel_pcm_dma_params *dma_params[2];
117 struct atmel_ssc_state ssc_state;
118};
119extern struct snd_soc_dai atmel_ssc_dai[];
120
121#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index b1966e4dfcd3..5b07cf7ea4e7 100644
--- a/sound/soc/at32/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -40,8 +40,8 @@
40#include <mach/portmux.h> 40#include <mach/portmux.h>
41 41
42#include "../codecs/wm8510.h" 42#include "../codecs/wm8510.h"
43#include "at32-pcm.h" 43#include "atmel-pcm.h"
44#include "at32-ssc.h" 44#include "atmel_ssc_dai.h"
45 45
46 46
47/*-------------------------------------------------------------------------*\ 47/*-------------------------------------------------------------------------*\