]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - sound/soc/at91/at91-i2s.c
[ALSA] SoC codecs - fix Kconfig - depends -> depends on
[mirror_ubuntu-hirsute-kernel.git] / sound / soc / at91 / at91-i2s.c
CommitLineData
0cbbec09 1/*
9f0ac6e1 2 * at91-i2s.c -- ALSA SoC I2S Audio Layer Platform driver
0cbbec09
FM
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 *
7 * Based on pxa2xx Platform drivers by
8 * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
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 *
0cbbec09
FM
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 <sound/driver.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
0cbbec09 29#include <asm/arch/hardware.h>
9f0ac6e1
FM
30#include <asm/arch/at91_pmc.h>
31#include <asm/arch/at91_ssc.h>
32#include <asm/arch/at91_pdc.h>
0cbbec09 33
9f0ac6e1 34#include "at91-pcm.h"
171eb8f8 35#include "at91-i2s.h"
0cbbec09
FM
36
37#if 0
9f0ac6e1 38#define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x)
0cbbec09
FM
39#else
40#define DBG(x...)
41#endif
42
9f0ac6e1
FM
43#if defined(CONFIG_ARCH_AT91SAM9260)
44#define NUM_SSC_DEVICES 1
45#else
46#define NUM_SSC_DEVICES 3
47#endif
48
49
0cbbec09 50/*
9f0ac6e1 51 * SSC PDC registers required by the PCM DMA engine.
0cbbec09 52 */
9f0ac6e1
FM
53static struct at91_pdc_regs pdc_tx_reg = {
54 .xpr = AT91_PDC_TPR,
55 .xcr = AT91_PDC_TCR,
56 .xnpr = AT91_PDC_TNPR,
57 .xncr = AT91_PDC_TNCR,
0cbbec09
FM
58};
59
9f0ac6e1
FM
60static struct at91_pdc_regs pdc_rx_reg = {
61 .xpr = AT91_PDC_RPR,
62 .xcr = AT91_PDC_RCR,
63 .xnpr = AT91_PDC_RNPR,
64 .xncr = AT91_PDC_RNCR,
0cbbec09
FM
65};
66
67/*
68 * SSC & PDC status bits for transmit and receive.
69 */
9f0ac6e1 70static struct at91_ssc_mask ssc_tx_mask = {
0cbbec09
FM
71 .ssc_enable = AT91_SSC_TXEN,
72 .ssc_disable = AT91_SSC_TXDIS,
73 .ssc_endx = AT91_SSC_ENDTX,
74 .ssc_endbuf = AT91_SSC_TXBUFE,
75 .pdc_enable = AT91_PDC_TXTEN,
76 .pdc_disable = AT91_PDC_TXTDIS,
77};
78
9f0ac6e1 79static struct at91_ssc_mask ssc_rx_mask = {
0cbbec09
FM
80 .ssc_enable = AT91_SSC_RXEN,
81 .ssc_disable = AT91_SSC_RXDIS,
82 .ssc_endx = AT91_SSC_ENDRX,
83 .ssc_endbuf = AT91_SSC_RXBUFF,
84 .pdc_enable = AT91_PDC_RXTEN,
85 .pdc_disable = AT91_PDC_RXTDIS,
86};
87
0cbbec09
FM
88
89/*
90 * DMA parameters.
91 */
9f0ac6e1 92static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
0cbbec09
FM
93 {{
94 .name = "SSC0/I2S PCM Stereo out",
9f0ac6e1 95 .pdc = &pdc_tx_reg,
0cbbec09
FM
96 .mask = &ssc_tx_mask,
97 },
98 {
99 .name = "SSC0/I2S PCM Stereo in",
9f0ac6e1 100 .pdc = &pdc_rx_reg,
0cbbec09
FM
101 .mask = &ssc_rx_mask,
102 }},
9f0ac6e1 103#if NUM_SSC_DEVICES == 3
0cbbec09
FM
104 {{
105 .name = "SSC1/I2S PCM Stereo out",
9f0ac6e1 106 .pdc = &pdc_tx_reg,
0cbbec09
FM
107 .mask = &ssc_tx_mask,
108 },
109 {
110 .name = "SSC1/I2S PCM Stereo in",
9f0ac6e1 111 .pdc = &pdc_rx_reg,
0cbbec09
FM
112 .mask = &ssc_rx_mask,
113 }},
114 {{
115 .name = "SSC2/I2S PCM Stereo out",
9f0ac6e1 116 .pdc = &pdc_tx_reg,
0cbbec09
FM
117 .mask = &ssc_tx_mask,
118 },
119 {
120 .name = "SSC1/I2S PCM Stereo in",
9f0ac6e1 121 .pdc = &pdc_rx_reg,
0cbbec09
FM
122 .mask = &ssc_rx_mask,
123 }},
9f0ac6e1 124#endif
0cbbec09
FM
125};
126
9f0ac6e1 127struct at91_ssc_state {
0cbbec09
FM
128 u32 ssc_cmr;
129 u32 ssc_rcmr;
130 u32 ssc_rfmr;
131 u32 ssc_tcmr;
132 u32 ssc_tfmr;
133 u32 ssc_sr;
134 u32 ssc_imr;
135};
136
9f0ac6e1 137static struct at91_ssc_info {
0cbbec09 138 char *name;
9f0ac6e1 139 struct at91_ssc_periph ssc;
0cbbec09 140 spinlock_t lock; /* lock for dir_mask */
171eb8f8
FM
141 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
142 unsigned short initialized; /* 1=SSC has been initialized */
143 unsigned short daifmt;
144 unsigned short cmr_div;
145 unsigned short tcmr_period;
146 unsigned short rcmr_period;
9f0ac6e1
FM
147 struct at91_pcm_dma_params *dma_params[2];
148 struct at91_ssc_state ssc_state;
0cbbec09 149
9f0ac6e1 150} ssc_info[NUM_SSC_DEVICES] = {
0cbbec09
FM
151 {
152 .name = "ssc0",
0cbbec09
FM
153 .lock = SPIN_LOCK_UNLOCKED,
154 .dir_mask = 0,
0cbbec09
FM
155 .initialized = 0,
156 },
9f0ac6e1 157#if NUM_SSC_DEVICES == 3
0cbbec09
FM
158 {
159 .name = "ssc1",
0cbbec09
FM
160 .lock = SPIN_LOCK_UNLOCKED,
161 .dir_mask = 0,
0cbbec09
FM
162 .initialized = 0,
163 },
164 {
165 .name = "ssc2",
0cbbec09
FM
166 .lock = SPIN_LOCK_UNLOCKED,
167 .dir_mask = 0,
0cbbec09
FM
168 .initialized = 0,
169 },
9f0ac6e1 170#endif
0cbbec09
FM
171};
172
171eb8f8 173static unsigned int at91_i2s_sysclk;
0cbbec09 174
171eb8f8
FM
175/*
176 * SSC interrupt handler. Passes PDC interrupts to the DMA
177 * interrupt handler in the PCM driver.
178 */
9f0ac6e1 179static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
0cbbec09 180{
9f0ac6e1
FM
181 struct at91_ssc_info *ssc_p = dev_id;
182 struct at91_pcm_dma_params *dma_params;
0cbbec09
FM
183 u32 ssc_sr;
184 int i;
185
9f0ac6e1
FM
186 ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
187 & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
0cbbec09
FM
188
189 /*
190 * Loop through the substreams attached to this SSC. If
191 * a DMA-related interrupt occurred on that substream, call
192 * the DMA interrupt handler function, if one has been
193 * registered in the dma_params structure by the PCM driver.
194 */
195 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
196 dma_params = ssc_p->dma_params[i];
197
198 if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
199 (ssc_sr &
200 (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
201
202 dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
203 }
204
205 return IRQ_HANDLED;
206}
207
171eb8f8
FM
208/*
209 * Startup. Only that one substream allowed in each direction.
210 */
9f0ac6e1 211static int at91_i2s_startup(struct snd_pcm_substream *substream)
0cbbec09
FM
212{
213 struct snd_soc_pcm_runtime *rtd = substream->private_data;
171eb8f8 214 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
0cbbec09
FM
215 int dir_mask;
216
217 DBG("i2s_startup: SSC_SR=0x%08lx\n",
9f0ac6e1 218 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
0cbbec09
FM
219 dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
220
221 spin_lock_irq(&ssc_p->lock);
222 if (ssc_p->dir_mask & dir_mask) {
223 spin_unlock_irq(&ssc_p->lock);
224 return -EBUSY;
225 }
226 ssc_p->dir_mask |= dir_mask;
227 spin_unlock_irq(&ssc_p->lock);
228
229 return 0;
230}
231
171eb8f8
FM
232/*
233 * Shutdown. Clear DMA parameters and shutdown the SSC if there
234 * are no other substreams open.
235 */
9f0ac6e1 236static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
0cbbec09
FM
237{
238 struct snd_soc_pcm_runtime *rtd = substream->private_data;
171eb8f8
FM
239 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
240 struct at91_pcm_dma_params *dma_params;
0cbbec09
FM
241 int dir, dir_mask;
242
243 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
171eb8f8 244 dma_params = ssc_p->dma_params[dir];
0cbbec09
FM
245
246 if (dma_params != NULL) {
9f0ac6e1
FM
247 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
248 dma_params->mask->ssc_disable);
0cbbec09 249 DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
9f0ac6e1 250 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
0cbbec09 251
9f0ac6e1 252 dma_params->ssc_base = NULL;
0cbbec09
FM
253 dma_params->substream = NULL;
254 ssc_p->dma_params[dir] = NULL;
255 }
256
257 dir_mask = 1 << dir;
258
259 spin_lock_irq(&ssc_p->lock);
260 ssc_p->dir_mask &= ~dir_mask;
261 if (!ssc_p->dir_mask) {
262 /* Shutdown the SSC clock. */
9f0ac6e1
FM
263 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
264 at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
0cbbec09 265
171eb8f8 266 if (ssc_p->initialized) {
9f0ac6e1 267 free_irq(ssc_p->ssc.pid, ssc_p);
171eb8f8
FM
268 ssc_p->initialized = 0;
269 }
0cbbec09
FM
270
271 /* Reset the SSC */
9f0ac6e1 272 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
0cbbec09 273
171eb8f8
FM
274 /* Clear the SSC dividers */
275 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
0cbbec09
FM
276 }
277 spin_unlock_irq(&ssc_p->lock);
278}
279
171eb8f8
FM
280/*
281 * Record the SSC system clock rate.
282 */
283static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
284 int clk_id, unsigned int freq, int dir)
0cbbec09 285{
171eb8f8
FM
286 /*
287 * The only clock supplied to the SSC is the AT91 master clock,
288 * which is only used if the SSC is generating BCLK and/or
289 * LRC clocks.
290 */
291 switch (clk_id) {
292 case AT91_SYSCLK_MCK:
293 at91_i2s_sysclk = freq;
294 break;
295 default:
296 return -EINVAL;
297 }
0cbbec09
FM
298
299 return 0;
300}
301
171eb8f8
FM
302/*
303 * Record the DAI format for use in hw_params().
304 */
305static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
306 unsigned int fmt)
0cbbec09 307{
171eb8f8 308 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
0cbbec09 309
171eb8f8
FM
310 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
311 return -EINVAL;
0cbbec09 312
171eb8f8 313 ssc_p->daifmt = fmt;
0cbbec09
FM
314 return 0;
315}
316
171eb8f8
FM
317/*
318 * Record SSC clock dividers for use in hw_params().
319 */
320static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
321 int div_id, int div)
0cbbec09 322{
171eb8f8
FM
323 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
324
325 switch (div_id) {
326 case AT91SSC_CMR_DIV:
327 /*
328 * The same master clock divider is used for both
329 * transmit and receive, so if a value has already
330 * been set, it must match this value.
331 */
332 if (ssc_p->cmr_div == 0)
333 ssc_p->cmr_div = div;
334 else
335 if (div != ssc_p->cmr_div)
336 return -EBUSY;
337 break;
338
339 case AT91SSC_TCMR_PERIOD:
340 ssc_p->tcmr_period = div;
341 break;
342
343 case AT91SSC_RCMR_PERIOD:
344 ssc_p->rcmr_period = div;
345 break;
346
347 default:
348 return -EINVAL;
349 }
350
351 return 0;
0cbbec09
FM
352}
353
171eb8f8
FM
354/*
355 * Configure the SSC.
356 */
9f0ac6e1 357static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
0cbbec09
FM
358 struct snd_pcm_hw_params *params)
359{
360 struct snd_soc_pcm_runtime *rtd = substream->private_data;
171eb8f8 361 int id = rtd->dai->cpu_dai->id;
9f0ac6e1
FM
362 struct at91_ssc_info *ssc_p = &ssc_info[id];
363 struct at91_pcm_dma_params *dma_params;
0cbbec09 364 int dir, channels, bits;
171eb8f8
FM
365 u32 tfmr, rfmr, tcmr, rcmr;
366 int start_event;
0cbbec09
FM
367 int ret;
368
369 /*
370 * Currently, there is only one set of dma params for
371 * each direction. If more are added, this code will
372 * have to be changed to select the proper set.
373 */
374 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
375
376 dma_params = &ssc_dma_params[id][dir];
9f0ac6e1 377 dma_params->ssc_base = ssc_p->ssc.base;
0cbbec09
FM
378 dma_params->substream = substream;
379
380 ssc_p->dma_params[dir] = dma_params;
0cbbec09 381
171eb8f8
FM
382 /*
383 * The cpu_dai->dma_data field is only used to communicate the
384 * appropriate DMA parameters to the pcm driver hw_params()
385 * function. It should not be used for other purposes
386 * as it is common to all substreams.
387 */
388 rtd->dai->cpu_dai->dma_data = dma_params;
0cbbec09 389
171eb8f8 390 channels = params_channels(params);
0cbbec09 391
171eb8f8
FM
392 /*
393 * The SSC only supports up to 16-bit samples in I2S format, due
394 * to the size of the Frame Mode Register FSLEN field. Also, I2S
395 * implies signed data.
396 */
397 bits = 16;
398 dma_params->pdc_xfer_size = 2;
0cbbec09
FM
399
400 /*
171eb8f8 401 * Compute SSC register settings.
0cbbec09 402 */
171eb8f8
FM
403 switch (ssc_p->daifmt) {
404 case SND_SOC_DAIFMT_CBS_CFS:
405 /*
406 * SSC provides BCLK and LRC clocks.
407 *
408 * The SSC transmit and receive clocks are generated from the
409 * MCK divider, and the BCLK signal is output on the SSC TK line.
410 */
411 rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
412 | (( 1 << 16) & AT91_SSC_STTDLY)
413 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
414 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
415 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
416 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
417
418 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
419 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
420 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
421 | (((channels - 1) << 8) & AT91_SSC_DATNB)
422 | (( 1 << 7) & AT91_SSC_MSBF)
423 | (( 0 << 5) & AT91_SSC_LOOP)
424 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
425
426 tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
427 | (( 1 << 16) & AT91_SSC_STTDLY)
428 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
429 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
430 | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
431 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
432
433 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
434 | (( 0 << 23) & AT91_SSC_FSDEN)
435 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
436 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
437 | (((channels - 1) << 8) & AT91_SSC_DATNB)
438 | (( 1 << 7) & AT91_SSC_MSBF)
439 | (( 0 << 5) & AT91_SSC_DATDEF)
440 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
441 break;
442
443 case SND_SOC_DAIFMT_CBM_CFM:
444
445 /*
446 * CODEC supplies BCLK and LRC clocks.
447 *
448 * The SSC transmit clock is obtained from the BCLK signal on
449 * on the TK line, and the SSC receive clock is generated from the
450 * transmit clock.
451 *
452 * For single channel data, one sample is transferred on the falling
453 * edge of the LRC clock. For two channel data, one sample is
454 * transferred on both edges of the LRC clock.
455 */
456 start_event = channels == 1
457 ? AT91_SSC_START_FALLING_RF
458 : AT91_SSC_START_EDGE_RF;
459
460 rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
461 | (( 1 << 16) & AT91_SSC_STTDLY)
462 | (( start_event ) & AT91_SSC_START)
463 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
464 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
465 | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
466
467 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
468 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
469 | (( 0 << 16) & AT91_SSC_FSLEN)
470 | (( 0 << 8) & AT91_SSC_DATNB)
471 | (( 1 << 7) & AT91_SSC_MSBF)
472 | (( 0 << 5) & AT91_SSC_LOOP)
473 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
474
475 tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
476 | (( 1 << 16) & AT91_SSC_STTDLY)
477 | (( start_event ) & AT91_SSC_START)
478 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
479 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
480 | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
481
482 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
483 | (( 0 << 23) & AT91_SSC_FSDEN)
484 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
485 | (( 0 << 16) & AT91_SSC_FSLEN)
486 | (( 0 << 8) & AT91_SSC_DATNB)
487 | (( 1 << 7) & AT91_SSC_MSBF)
488 | (( 0 << 5) & AT91_SSC_DATDEF)
489 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
490 break;
491
492 case SND_SOC_DAIFMT_CBS_CFM:
493 case SND_SOC_DAIFMT_CBM_CFS:
494 default:
495 printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n",
496 ssc_p->daifmt);
497 return -EINVAL;
498 break;
499 }
500 DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
501
502 if (!ssc_p->initialized) {
503
0cbbec09 504 /* Enable PMC peripheral clock for this SSC */
9f0ac6e1
FM
505 DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
506 at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
0cbbec09 507
171eb8f8 508 /* Reset the SSC and its PDC registers */
9f0ac6e1 509 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
0cbbec09 510
9f0ac6e1
FM
511 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RPR, 0);
512 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RCR, 0);
513 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNPR, 0);
514 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNCR, 0);
515 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TPR, 0);
516 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TCR, 0);
517 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNPR, 0);
518 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNCR, 0);
0cbbec09 519
9f0ac6e1 520 if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt,
0cbbec09 521 0, ssc_p->name, ssc_p)) < 0) {
9f0ac6e1 522 printk(KERN_WARNING "at91-i2s: request_irq failure\n");
171eb8f8
FM
523
524 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
525 at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
0cbbec09
FM
526 return ret;
527 }
528
0cbbec09 529 ssc_p->initialized = 1;
0cbbec09
FM
530 }
531
171eb8f8
FM
532 /* set SSC clock mode register */
533 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
534
535 /* set receive clock mode and format */
536 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
537 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
538
539 /* set transmit clock mode and format */
540 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
541 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
0cbbec09 542
171eb8f8 543 DBG("hw_params: SSC initialized\n");
0cbbec09
FM
544 return 0;
545}
546
547
9f0ac6e1 548static int at91_i2s_prepare(struct snd_pcm_substream *substream)
0cbbec09
FM
549{
550 struct snd_soc_pcm_runtime *rtd = substream->private_data;
171eb8f8
FM
551 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
552 struct at91_pcm_dma_params *dma_params;
553 int dir;
554
555 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
556 dma_params = ssc_p->dma_params[dir];
0cbbec09 557
9f0ac6e1
FM
558 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
559 dma_params->mask->ssc_enable);
0cbbec09 560
171eb8f8
FM
561 DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
562 at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
0cbbec09
FM
563 return 0;
564}
565
566
171eb8f8
FM
567#ifdef CONFIG_PM
568static int at91_i2s_suspend(struct platform_device *pdev,
569 struct snd_soc_cpu_dai *cpu_dai)
570{
571 struct at91_ssc_info *ssc_p;
572
573 if(!cpu_dai->active)
574 return 0;
575
576 ssc_p = &ssc_info[cpu_dai->id];
577
578 /* Save the status register before disabling transmit and receive. */
579 ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
580 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
581 AT91_SSC_TXDIS | AT91_SSC_RXDIS);
582
583 /* Save the current interrupt mask, then disable unmasked interrupts. */
584 ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
585 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
586
587 ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
588 ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
589 ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
590 ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
591 ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
592
593 return 0;
594}
595
596static int at91_i2s_resume(struct platform_device *pdev,
597 struct snd_soc_cpu_dai *cpu_dai)
598{
599 struct at91_ssc_info *ssc_p;
600
601 if(!cpu_dai->active)
602 return 0;
603
604 ssc_p = &ssc_info[cpu_dai->id];
605
606 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
607 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
608 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
609 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
610 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
611
612 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
613
614 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
615 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
616 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
617
618 return 0;
619}
620
621#else
622#define at91_i2s_suspend NULL
623#define at91_i2s_resume NULL
624#endif
625
626#define AT91_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
627 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
628 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
629 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
630 SNDRV_PCM_RATE_96000)
631
9f0ac6e1
FM
632struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = {
633 { .name = "at91_ssc0/i2s",
0cbbec09
FM
634 .id = 0,
635 .type = SND_SOC_DAI_I2S,
9f0ac6e1
FM
636 .suspend = at91_i2s_suspend,
637 .resume = at91_i2s_resume,
0cbbec09
FM
638 .playback = {
639 .channels_min = 1,
171eb8f8
FM
640 .channels_max = 2,
641 .rates = AT91_I2S_RATES,
642 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
0cbbec09
FM
643 .capture = {
644 .channels_min = 1,
171eb8f8
FM
645 .channels_max = 2,
646 .rates = AT91_I2S_RATES,
647 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
0cbbec09 648 .ops = {
9f0ac6e1
FM
649 .startup = at91_i2s_startup,
650 .shutdown = at91_i2s_shutdown,
651 .prepare = at91_i2s_prepare,
652 .hw_params = at91_i2s_hw_params,},
171eb8f8
FM
653 .dai_ops = {
654 .set_sysclk = at91_i2s_set_dai_sysclk,
655 .set_fmt = at91_i2s_set_dai_fmt,
656 .set_clkdiv = at91_i2s_set_dai_clkdiv,},
9f0ac6e1 657 .private_data = &ssc_info[0].ssc,
0cbbec09 658 },
9f0ac6e1
FM
659#if NUM_SSC_DEVICES == 3
660 { .name = "at91_ssc1/i2s",
0cbbec09
FM
661 .id = 1,
662 .type = SND_SOC_DAI_I2S,
9f0ac6e1
FM
663 .suspend = at91_i2s_suspend,
664 .resume = at91_i2s_resume,
0cbbec09
FM
665 .playback = {
666 .channels_min = 1,
171eb8f8
FM
667 .channels_max = 2,
668 .rates = AT91_I2S_RATES,
669 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
0cbbec09
FM
670 .capture = {
671 .channels_min = 1,
171eb8f8
FM
672 .channels_max = 2,
673 .rates = AT91_I2S_RATES,
674 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
0cbbec09 675 .ops = {
9f0ac6e1
FM
676 .startup = at91_i2s_startup,
677 .shutdown = at91_i2s_shutdown,
678 .prepare = at91_i2s_prepare,
679 .hw_params = at91_i2s_hw_params,},
171eb8f8
FM
680 .dai_ops = {
681 .set_sysclk = at91_i2s_set_dai_sysclk,
682 .set_fmt = at91_i2s_set_dai_fmt,
683 .set_clkdiv = at91_i2s_set_dai_clkdiv,},
9f0ac6e1 684 .private_data = &ssc_info[1].ssc,
0cbbec09 685 },
9f0ac6e1 686 { .name = "at91_ssc2/i2s",
0cbbec09
FM
687 .id = 2,
688 .type = SND_SOC_DAI_I2S,
9f0ac6e1
FM
689 .suspend = at91_i2s_suspend,
690 .resume = at91_i2s_resume,
0cbbec09
FM
691 .playback = {
692 .channels_min = 1,
171eb8f8
FM
693 .channels_max = 2,
694 .rates = AT91_I2S_RATES,
695 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
0cbbec09
FM
696 .capture = {
697 .channels_min = 1,
171eb8f8
FM
698 .channels_max = 2,
699 .rates = AT91_I2S_RATES,
700 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
0cbbec09 701 .ops = {
9f0ac6e1
FM
702 .startup = at91_i2s_startup,
703 .shutdown = at91_i2s_shutdown,
704 .prepare = at91_i2s_prepare,
705 .hw_params = at91_i2s_hw_params,},
171eb8f8
FM
706 .dai_ops = {
707 .set_sysclk = at91_i2s_set_dai_sysclk,
708 .set_fmt = at91_i2s_set_dai_fmt,
709 .set_clkdiv = at91_i2s_set_dai_clkdiv,},
9f0ac6e1 710 .private_data = &ssc_info[2].ssc,
0cbbec09 711 },
9f0ac6e1 712#endif
0cbbec09
FM
713};
714
9f0ac6e1 715EXPORT_SYMBOL_GPL(at91_i2s_dai);
0cbbec09
FM
716
717/* Module information */
718MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
9f0ac6e1 719MODULE_DESCRIPTION("AT91 I2S ASoC Interface");
0cbbec09 720MODULE_LICENSE("GPL");