diff options
author | Frank Mandarino <fmandarino@endrelia.com> | 2007-02-02 11:18:38 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:03:43 -0500 |
commit | 171eb8f81d7b0706c1085d272e4955251ed9f05f (patch) | |
tree | bf7fa567eb1decfa0785be6dab845725dcaaaf5e /sound/soc/at91 | |
parent | d3d35adc79aa2e48e8177a9506e9bcb5eebba406 (diff) |
[ALSA] soc - ASoC 0.13 AT91xxxx I2S
This patch updates the AT91xxxx I2S driver to the new API in ASoC 0.13.
Changes:-
o Removed DAI capabilities matching code in favour of manual matching in
the machine drivers.
o Added DAI operations for codec and CPU interfaces.
o Removed config_sysclk() function and struct snd_soc_clock_info. No
longer needed as clocking is now configured manually in the machine
drivers. Also removed other clocking data from structures.
Signed-off-by: Frank Mandarino <fmandarino@endrelia.com>
Signed-off-by: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/soc/at91')
-rw-r--r-- | sound/soc/at91/at91-i2s.c | 618 | ||||
-rw-r--r-- | sound/soc/at91/at91-i2s.h | 27 |
2 files changed, 356 insertions, 289 deletions
diff --git a/sound/soc/at91/at91-i2s.c b/sound/soc/at91/at91-i2s.c index 876d391c7013..fcc544a96ba3 100644 --- a/sound/soc/at91/at91-i2s.c +++ b/sound/soc/at91/at91-i2s.c | |||
@@ -12,8 +12,6 @@ | |||
12 | * Free Software Foundation; either version 2 of the License, or (at your | 12 | * Free Software Foundation; either version 2 of the License, or (at your |
13 | * option) any later version. | 13 | * option) any later version. |
14 | * | 14 | * |
15 | * Revision history | ||
16 | * 3rd Mar 2006 Initial version. | ||
17 | */ | 15 | */ |
18 | 16 | ||
19 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -34,6 +32,7 @@ | |||
34 | #include <asm/arch/at91_pdc.h> | 32 | #include <asm/arch/at91_pdc.h> |
35 | 33 | ||
36 | #include "at91-pcm.h" | 34 | #include "at91-pcm.h" |
35 | #include "at91-i2s.h" | ||
37 | 36 | ||
38 | #if 0 | 37 | #if 0 |
39 | #define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x) | 38 | #define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x) |
@@ -48,65 +47,6 @@ | |||
48 | #endif | 47 | #endif |
49 | 48 | ||
50 | 49 | ||
51 | #define AT91_I2S_DAIFMT \ | ||
52 | (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF) | ||
53 | |||
54 | #define AT91_I2S_DIR \ | ||
55 | (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) | ||
56 | |||
57 | /* priv is (SSC_CMR.DIV << 16 | SSC_TCMR.PERIOD ) */ | ||
58 | static struct snd_soc_dai_mode at91_i2s[] = { | ||
59 | |||
60 | /* 8k: BCLK = (MCLK/10) = (60MHz/50) = 1.2MHz */ | ||
61 | { | ||
62 | .fmt = AT91_I2S_DAIFMT, | ||
63 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | ||
64 | .pcmrate = SNDRV_PCM_RATE_8000, | ||
65 | .pcmdir = AT91_I2S_DIR, | ||
66 | .flags = SND_SOC_DAI_BFS_DIV, | ||
67 | .fs = 1500, | ||
68 | .bfs = SND_SOC_FSBD(10), | ||
69 | .priv = (25 << 16 | 74), | ||
70 | }, | ||
71 | |||
72 | /* 16k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */ | ||
73 | { | ||
74 | .fmt = AT91_I2S_DAIFMT, | ||
75 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | ||
76 | .pcmrate = SNDRV_PCM_RATE_16000, | ||
77 | .pcmdir = AT91_I2S_DIR, | ||
78 | .flags = SND_SOC_DAI_BFS_DIV, | ||
79 | .fs = 750, | ||
80 | .bfs = SND_SOC_FSBD(3), | ||
81 | .priv = (7 << 16 | 133), | ||
82 | }, | ||
83 | |||
84 | /* 32k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */ | ||
85 | { | ||
86 | .fmt = AT91_I2S_DAIFMT, | ||
87 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | ||
88 | .pcmrate = SNDRV_PCM_RATE_32000, | ||
89 | .pcmdir = AT91_I2S_DIR, | ||
90 | .flags = SND_SOC_DAI_BFS_DIV, | ||
91 | .fs = 375, | ||
92 | .bfs = SND_SOC_FSBD(3), | ||
93 | .priv = (7 << 16 | 66), | ||
94 | }, | ||
95 | |||
96 | /* 48k: BCLK = (MCLK/5) ~= (60MHz/26) = 2.3076923MHz */ | ||
97 | { | ||
98 | .fmt = AT91_I2S_DAIFMT, | ||
99 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | ||
100 | .pcmrate = SNDRV_PCM_RATE_48000, | ||
101 | .pcmdir = AT91_I2S_DIR, | ||
102 | .flags = SND_SOC_DAI_BFS_DIV, | ||
103 | .fs = 250, | ||
104 | .bfs = SND_SOC_FSBD(5), | ||
105 | .priv = (13 << 16 | 23), | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | |||
110 | /* | 50 | /* |
111 | * SSC PDC registers required by the PCM DMA engine. | 51 | * SSC PDC registers required by the PCM DMA engine. |
112 | */ | 52 | */ |
@@ -184,21 +124,6 @@ static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { | |||
184 | #endif | 124 | #endif |
185 | }; | 125 | }; |
186 | 126 | ||
187 | |||
188 | /* | ||
189 | * A MUTEX is used to protect an SSC initialzed flag which allows | ||
190 | * the substream hw_params() call to initialize the SSC only if | ||
191 | * there are no other substreams open. If there are other | ||
192 | * substreams open, the hw_param() call can only check that | ||
193 | * it is using the same format and rate. | ||
194 | */ | ||
195 | static DECLARE_MUTEX(ssc0_mutex); | ||
196 | #if NUM_SSC_DEVICES == 3 | ||
197 | static DECLARE_MUTEX(ssc1_mutex); | ||
198 | static DECLARE_MUTEX(ssc2_mutex); | ||
199 | #endif | ||
200 | |||
201 | |||
202 | struct at91_ssc_state { | 127 | struct at91_ssc_state { |
203 | u32 ssc_cmr; | 128 | u32 ssc_cmr; |
204 | u32 ssc_rcmr; | 129 | u32 ssc_rcmr; |
@@ -209,16 +134,16 @@ struct at91_ssc_state { | |||
209 | u32 ssc_imr; | 134 | u32 ssc_imr; |
210 | }; | 135 | }; |
211 | 136 | ||
212 | |||
213 | static struct at91_ssc_info { | 137 | static struct at91_ssc_info { |
214 | char *name; | 138 | char *name; |
215 | struct at91_ssc_periph ssc; | 139 | struct at91_ssc_periph ssc; |
216 | spinlock_t lock; /* lock for dir_mask */ | 140 | spinlock_t lock; /* lock for dir_mask */ |
217 | int dir_mask; /* 0=unused, 1=playback, 2=capture */ | 141 | unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */ |
218 | struct semaphore *mutex; | 142 | unsigned short initialized; /* 1=SSC has been initialized */ |
219 | int initialized; | 143 | unsigned short daifmt; |
220 | int pcmfmt; | 144 | unsigned short cmr_div; |
221 | int rate; | 145 | unsigned short tcmr_period; |
146 | unsigned short rcmr_period; | ||
222 | struct at91_pcm_dma_params *dma_params[2]; | 147 | struct at91_pcm_dma_params *dma_params[2]; |
223 | struct at91_ssc_state ssc_state; | 148 | struct at91_ssc_state ssc_state; |
224 | 149 | ||
@@ -227,7 +152,6 @@ static struct at91_ssc_info { | |||
227 | .name = "ssc0", | 152 | .name = "ssc0", |
228 | .lock = SPIN_LOCK_UNLOCKED, | 153 | .lock = SPIN_LOCK_UNLOCKED, |
229 | .dir_mask = 0, | 154 | .dir_mask = 0, |
230 | .mutex = &ssc0_mutex, | ||
231 | .initialized = 0, | 155 | .initialized = 0, |
232 | }, | 156 | }, |
233 | #if NUM_SSC_DEVICES == 3 | 157 | #if NUM_SSC_DEVICES == 3 |
@@ -235,20 +159,23 @@ static struct at91_ssc_info { | |||
235 | .name = "ssc1", | 159 | .name = "ssc1", |
236 | .lock = SPIN_LOCK_UNLOCKED, | 160 | .lock = SPIN_LOCK_UNLOCKED, |
237 | .dir_mask = 0, | 161 | .dir_mask = 0, |
238 | .mutex = &ssc1_mutex, | ||
239 | .initialized = 0, | 162 | .initialized = 0, |
240 | }, | 163 | }, |
241 | { | 164 | { |
242 | .name = "ssc2", | 165 | .name = "ssc2", |
243 | .lock = SPIN_LOCK_UNLOCKED, | 166 | .lock = SPIN_LOCK_UNLOCKED, |
244 | .dir_mask = 0, | 167 | .dir_mask = 0, |
245 | .mutex = &ssc2_mutex, | ||
246 | .initialized = 0, | 168 | .initialized = 0, |
247 | }, | 169 | }, |
248 | #endif | 170 | #endif |
249 | }; | 171 | }; |
250 | 172 | ||
173 | static unsigned int at91_i2s_sysclk; | ||
251 | 174 | ||
175 | /* | ||
176 | * SSC interrupt handler. Passes PDC interrupts to the DMA | ||
177 | * interrupt handler in the PCM driver. | ||
178 | */ | ||
252 | static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) | 179 | static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) |
253 | { | 180 | { |
254 | struct at91_ssc_info *ssc_p = dev_id; | 181 | struct at91_ssc_info *ssc_p = dev_id; |
@@ -278,10 +205,13 @@ static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) | |||
278 | return IRQ_HANDLED; | 205 | return IRQ_HANDLED; |
279 | } | 206 | } |
280 | 207 | ||
208 | /* | ||
209 | * Startup. Only that one substream allowed in each direction. | ||
210 | */ | ||
281 | static int at91_i2s_startup(struct snd_pcm_substream *substream) | 211 | static int at91_i2s_startup(struct snd_pcm_substream *substream) |
282 | { | 212 | { |
283 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 213 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
284 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id]; | 214 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; |
285 | int dir_mask; | 215 | int dir_mask; |
286 | 216 | ||
287 | DBG("i2s_startup: SSC_SR=0x%08lx\n", | 217 | DBG("i2s_startup: SSC_SR=0x%08lx\n", |
@@ -296,24 +226,22 @@ static int at91_i2s_startup(struct snd_pcm_substream *substream) | |||
296 | ssc_p->dir_mask |= dir_mask; | 226 | ssc_p->dir_mask |= dir_mask; |
297 | spin_unlock_irq(&ssc_p->lock); | 227 | spin_unlock_irq(&ssc_p->lock); |
298 | 228 | ||
299 | /* | ||
300 | * dma_data is not set until hw_params() is called and | ||
301 | * shutdown() depends on this value being NULL if hw_params() | ||
302 | * was not called. | ||
303 | */ | ||
304 | rtd->cpu_dai->dma_data = NULL; | ||
305 | |||
306 | return 0; | 229 | return 0; |
307 | } | 230 | } |
308 | 231 | ||
232 | /* | ||
233 | * Shutdown. Clear DMA parameters and shutdown the SSC if there | ||
234 | * are no other substreams open. | ||
235 | */ | ||
309 | static void at91_i2s_shutdown(struct snd_pcm_substream *substream) | 236 | static void at91_i2s_shutdown(struct snd_pcm_substream *substream) |
310 | { | 237 | { |
311 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 238 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
312 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id]; | 239 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; |
313 | struct at91_pcm_dma_params *dma_params = rtd->cpu_dai->dma_data; | 240 | struct at91_pcm_dma_params *dma_params; |
314 | int dir, dir_mask; | 241 | int dir, dir_mask; |
315 | 242 | ||
316 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | 243 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; |
244 | dma_params = ssc_p->dma_params[dir]; | ||
317 | 245 | ||
318 | if (dma_params != NULL) { | 246 | if (dma_params != NULL) { |
319 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, | 247 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, |
@@ -335,99 +263,107 @@ static void at91_i2s_shutdown(struct snd_pcm_substream *substream) | |||
335 | DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); | 263 | DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); |
336 | at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid); | 264 | at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid); |
337 | 265 | ||
338 | if (ssc_p->initialized) | 266 | if (ssc_p->initialized) { |
339 | free_irq(ssc_p->ssc.pid, ssc_p); | 267 | free_irq(ssc_p->ssc.pid, ssc_p); |
268 | ssc_p->initialized = 0; | ||
269 | } | ||
340 | 270 | ||
341 | /* Reset the SSC */ | 271 | /* Reset the SSC */ |
342 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); | 272 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); |
343 | 273 | ||
344 | /* Force a re-init on the next hw_params() call. */ | 274 | /* Clear the SSC dividers */ |
345 | ssc_p->initialized = 0; | 275 | ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; |
346 | } | 276 | } |
347 | spin_unlock_irq(&ssc_p->lock); | 277 | spin_unlock_irq(&ssc_p->lock); |
348 | } | 278 | } |
349 | 279 | ||
350 | #ifdef CONFIG_PM | 280 | /* |
351 | static int at91_i2s_suspend(struct platform_device *pdev, | 281 | * Record the SSC system clock rate. |
352 | struct snd_soc_cpu_dai *dai) | 282 | */ |
283 | static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, | ||
284 | int clk_id, unsigned int freq, int dir) | ||
353 | { | 285 | { |
354 | struct at91_ssc_info *ssc_p; | 286 | /* |
355 | 287 | * The only clock supplied to the SSC is the AT91 master clock, | |
356 | if(!dai->active) | 288 | * which is only used if the SSC is generating BCLK and/or |
357 | return 0; | 289 | * LRC clocks. |
358 | 290 | */ | |
359 | ssc_p = &ssc_info[dai->id]; | 291 | switch (clk_id) { |
360 | 292 | case AT91_SYSCLK_MCK: | |
361 | /* Save the status register before disabling transmit and receive. */ | 293 | at91_i2s_sysclk = freq; |
362 | ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR); | 294 | break; |
363 | at91_ssc_write(ssc_p->ssc.base + | 295 | default: |
364 | AT91_SSC_CR, AT91_SSC_TXDIS | AT91_SSC_RXDIS); | 296 | return -EINVAL; |
365 | 297 | } | |
366 | /* Save the current interrupt mask, then disable unmasked interrupts. */ | ||
367 | ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR); | ||
368 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr); | ||
369 | |||
370 | ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR); | ||
371 | ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); | ||
372 | ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); | ||
373 | ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); | ||
374 | ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); | ||
375 | 298 | ||
376 | return 0; | 299 | return 0; |
377 | } | 300 | } |
378 | 301 | ||
379 | static int at91_i2s_resume(struct platform_device *pdev, | 302 | /* |
380 | struct snd_soc_cpu_dai *dai) | 303 | * Record the DAI format for use in hw_params(). |
304 | */ | ||
305 | static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, | ||
306 | unsigned int fmt) | ||
381 | { | 307 | { |
382 | struct at91_ssc_info *ssc_p; | 308 | struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; |
383 | u32 cr_mask; | ||
384 | |||
385 | if(!dai->active) | ||
386 | return 0; | ||
387 | |||
388 | ssc_p = &ssc_info[dai->id]; | ||
389 | 309 | ||
390 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_tfmr); | 310 | if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) |
391 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_tcmr); | 311 | return -EINVAL; |
392 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rfmr); | ||
393 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr); | ||
394 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr); | ||
395 | |||
396 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr); | ||
397 | |||
398 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, | ||
399 | ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) | | ||
400 | ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0)); | ||
401 | 312 | ||
313 | ssc_p->daifmt = fmt; | ||
402 | return 0; | 314 | return 0; |
403 | } | 315 | } |
404 | 316 | ||
405 | #else | 317 | /* |
406 | #define at91_i2s_suspend NULL | 318 | * Record SSC clock dividers for use in hw_params(). |
407 | #define at91_i2s_resume NULL | 319 | */ |
408 | #endif | 320 | static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, |
409 | 321 | int div_id, int div) | |
410 | static unsigned int at91_i2s_config_sysclk( | ||
411 | struct snd_soc_cpu_dai *iface, struct snd_soc_clock_info *info, | ||
412 | unsigned int clk) | ||
413 | { | 322 | { |
414 | /* Currently, there is only support for USB (12Mhz) mode */ | 323 | struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; |
415 | if (clk != 12000000) | 324 | |
416 | return 0; | 325 | switch (div_id) { |
417 | return 12000000; | 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; | ||
418 | } | 352 | } |
419 | 353 | ||
354 | /* | ||
355 | * Configure the SSC. | ||
356 | */ | ||
420 | static int at91_i2s_hw_params(struct snd_pcm_substream *substream, | 357 | static int at91_i2s_hw_params(struct snd_pcm_substream *substream, |
421 | struct snd_pcm_hw_params *params) | 358 | struct snd_pcm_hw_params *params) |
422 | { | 359 | { |
423 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 360 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
424 | int id = rtd->cpu_dai->id; | 361 | int id = rtd->dai->cpu_dai->id; |
425 | struct at91_ssc_info *ssc_p = &ssc_info[id]; | 362 | struct at91_ssc_info *ssc_p = &ssc_info[id]; |
426 | struct at91_pcm_dma_params *dma_params; | 363 | struct at91_pcm_dma_params *dma_params; |
427 | unsigned int pcmfmt, rate; | ||
428 | int dir, channels, bits; | 364 | int dir, channels, bits; |
429 | struct clk *mck_clk; | 365 | u32 tfmr, rfmr, tcmr, rcmr; |
430 | u32 div, period, tfmr, rfmr, tcmr, rcmr; | 366 | int start_event; |
431 | int ret; | 367 | int ret; |
432 | 368 | ||
433 | /* | 369 | /* |
@@ -442,44 +378,134 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, | |||
442 | dma_params->substream = substream; | 378 | dma_params->substream = substream; |
443 | 379 | ||
444 | ssc_p->dma_params[dir] = dma_params; | 380 | ssc_p->dma_params[dir] = dma_params; |
445 | rtd->cpu_dai->dma_data = dma_params; | ||
446 | 381 | ||
447 | rate = params_rate(params); | 382 | /* |
448 | channels = params_channels(params); | 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; | ||
449 | 389 | ||
450 | pcmfmt = rtd->cpu_dai->dai_runtime.pcmfmt; | 390 | channels = params_channels(params); |
451 | switch (pcmfmt) { | ||
452 | case SNDRV_PCM_FMTBIT_S16_LE: | ||
453 | /* likely this is all we'll ever support, but ... */ | ||
454 | bits = 16; | ||
455 | dma_params->pdc_xfer_size = 2; | ||
456 | break; | ||
457 | default: | ||
458 | printk(KERN_WARNING "at91-i2s: unsupported format %x\n", | ||
459 | pcmfmt); | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | 391 | ||
463 | /* Don't allow both SSC substreams to initialize at the same time. */ | 392 | /* |
464 | down(ssc_p->mutex); | 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; | ||
465 | 399 | ||
466 | /* | 400 | /* |
467 | * If this SSC is alreadly initialized, then this substream must use | 401 | * Compute SSC register settings. |
468 | * the same format and rate. | ||
469 | */ | 402 | */ |
470 | if (ssc_p->initialized) { | 403 | switch (ssc_p->daifmt) { |
471 | if (pcmfmt != ssc_p->pcmfmt || rate != ssc_p->rate) { | 404 | case SND_SOC_DAIFMT_CBS_CFS: |
472 | printk(KERN_WARNING "at91-i2s: " | 405 | /* |
473 | "incompatible substream in other direction\n"); | 406 | * SSC provides BCLK and LRC clocks. |
474 | up(ssc_p->mutex); | 407 | * |
475 | return -EINVAL; | 408 | * The SSC transmit and receive clocks are generated from the |
476 | } | 409 | * MCK divider, and the BCLK signal is output on the SSC TK line. |
477 | } else { | 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 | |||
478 | /* Enable PMC peripheral clock for this SSC */ | 504 | /* Enable PMC peripheral clock for this SSC */ |
479 | DBG("Starting pid %d clock\n", ssc_p->ssc.pid); | 505 | DBG("Starting pid %d clock\n", ssc_p->ssc.pid); |
480 | at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); | 506 | at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); |
481 | 507 | ||
482 | /* Reset the SSC */ | 508 | /* Reset the SSC and its PDC registers */ |
483 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); | 509 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); |
484 | 510 | ||
485 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RPR, 0); | 511 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RPR, 0); |
@@ -491,97 +517,30 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, | |||
491 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNPR, 0); | 517 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNPR, 0); |
492 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNCR, 0); | 518 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNCR, 0); |
493 | 519 | ||
494 | div = rtd->cpu_dai->dai_runtime.priv >> 16; | ||
495 | period = rtd->cpu_dai->dai_runtime.priv & 0xffff; | ||
496 | |||
497 | mck_clk = clk_get(NULL, "mck"); | ||
498 | |||
499 | DBG("mck %lu fsbd %u bfs %llu bfs_real %u bclk %lu div %u period %u\n", | ||
500 | clk_get_rate(mck_clk), | ||
501 | SND_SOC_FSBD(6), | ||
502 | rtd->cpu_dai->dai_runtime.bfs, | ||
503 | SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs), | ||
504 | clk_get_rate(mck_clk) / (2 * div), | ||
505 | div, | ||
506 | period); | ||
507 | |||
508 | clk_put(mck_clk); | ||
509 | |||
510 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, div); | ||
511 | |||
512 | /* | ||
513 | * Setup the TFMR and RFMR for the proper data format. | ||
514 | */ | ||
515 | tfmr = | ||
516 | (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
517 | | (( 0 << 23) & AT91_SSC_FSDEN) | ||
518 | | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS) | ||
519 | | (((bits - 1) << 16) & AT91_SSC_FSLEN) | ||
520 | | (((channels - 1) << 8) & AT91_SSC_DATNB) | ||
521 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
522 | | (( 0 << 5) & AT91_SSC_DATDEF) | ||
523 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
524 | DBG("SSC_TFMR=0x%08x\n", tfmr); | ||
525 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr); | ||
526 | |||
527 | rfmr = | ||
528 | (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
529 | | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS) | ||
530 | | (( 0 << 16) & AT91_SSC_FSLEN) | ||
531 | | (((channels - 1) << 8) & AT91_SSC_DATNB) | ||
532 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
533 | | (( 0 << 5) & AT91_SSC_LOOP) | ||
534 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
535 | |||
536 | DBG("SSC_RFMR=0x%08x\n", rfmr); | ||
537 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr); | ||
538 | |||
539 | /* | ||
540 | * Setup the TCMR and RCMR to generate the proper BCLK | ||
541 | * and LRC signals. | ||
542 | */ | ||
543 | tcmr = | ||
544 | (( period << 24) & AT91_SSC_PERIOD) | ||
545 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
546 | | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START) | ||
547 | | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI) | ||
548 | | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) | ||
549 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); | ||
550 | |||
551 | DBG("SSC_TCMR=0x%08x\n", tcmr); | ||
552 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr); | ||
553 | |||
554 | rcmr = | ||
555 | (( 0 << 24) & AT91_SSC_PERIOD) | ||
556 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
557 | | (( AT91_SSC_START_TX_RX ) & AT91_SSC_START) | ||
558 | | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | ||
559 | | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | ||
560 | | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS); | ||
561 | |||
562 | DBG("SSC_RCMR=0x%08x\n", rcmr); | ||
563 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr); | ||
564 | |||
565 | if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt, | 520 | if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt, |
566 | 0, ssc_p->name, ssc_p)) < 0) { | 521 | 0, ssc_p->name, ssc_p)) < 0) { |
567 | printk(KERN_WARNING "at91-i2s: request_irq failure\n"); | 522 | printk(KERN_WARNING "at91-i2s: request_irq failure\n"); |
523 | |||
524 | DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); | ||
525 | at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); | ||
568 | return ret; | 526 | return ret; |
569 | } | 527 | } |
570 | 528 | ||
571 | /* | ||
572 | * Save the current substream parameters in order to check | ||
573 | * that the substream in the opposite direction uses the | ||
574 | * same parameters. | ||
575 | */ | ||
576 | ssc_p->pcmfmt = pcmfmt; | ||
577 | ssc_p->rate = rate; | ||
578 | ssc_p->initialized = 1; | 529 | ssc_p->initialized = 1; |
579 | |||
580 | DBG("hw_params: SSC initialized\n"); | ||
581 | } | 530 | } |
582 | 531 | ||
583 | up(ssc_p->mutex); | 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); | ||
584 | 542 | ||
543 | DBG("hw_params: SSC initialized\n"); | ||
585 | return 0; | 544 | return 0; |
586 | } | 545 | } |
587 | 546 | ||
@@ -589,39 +548,112 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, | |||
589 | static int at91_i2s_prepare(struct snd_pcm_substream *substream) | 548 | static int at91_i2s_prepare(struct snd_pcm_substream *substream) |
590 | { | 549 | { |
591 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 550 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
592 | struct at91_pcm_dma_params *dma_params = rtd->cpu_dai->dma_data; | 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]; | ||
593 | 557 | ||
594 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, | 558 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, |
595 | dma_params->mask->ssc_enable); | 559 | dma_params->mask->ssc_enable); |
596 | 560 | ||
597 | DBG("%s enabled SSC_SR=0x%08lx\n", | 561 | DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit", |
598 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "transmit" : "receive", | 562 | at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR)); |
599 | at91_ssc_read(ssc_info[rtd->cpu_dai->id].ssc.base + AT91_SSC_SR)); | ||
600 | return 0; | 563 | return 0; |
601 | } | 564 | } |
602 | 565 | ||
603 | 566 | ||
567 | #ifdef CONFIG_PM | ||
568 | static 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 | |||
596 | static 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 | |||
604 | struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { | 632 | struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { |
605 | { .name = "at91_ssc0/i2s", | 633 | { .name = "at91_ssc0/i2s", |
606 | .id = 0, | 634 | .id = 0, |
607 | .type = SND_SOC_DAI_I2S, | 635 | .type = SND_SOC_DAI_I2S, |
608 | .suspend = at91_i2s_suspend, | 636 | .suspend = at91_i2s_suspend, |
609 | .resume = at91_i2s_resume, | 637 | .resume = at91_i2s_resume, |
610 | .config_sysclk = at91_i2s_config_sysclk, | ||
611 | .playback = { | 638 | .playback = { |
612 | .channels_min = 1, | 639 | .channels_min = 1, |
613 | .channels_max = 2,}, | 640 | .channels_max = 2, |
641 | .rates = AT91_I2S_RATES, | ||
642 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
614 | .capture = { | 643 | .capture = { |
615 | .channels_min = 1, | 644 | .channels_min = 1, |
616 | .channels_max = 2,}, | 645 | .channels_max = 2, |
646 | .rates = AT91_I2S_RATES, | ||
647 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
617 | .ops = { | 648 | .ops = { |
618 | .startup = at91_i2s_startup, | 649 | .startup = at91_i2s_startup, |
619 | .shutdown = at91_i2s_shutdown, | 650 | .shutdown = at91_i2s_shutdown, |
620 | .prepare = at91_i2s_prepare, | 651 | .prepare = at91_i2s_prepare, |
621 | .hw_params = at91_i2s_hw_params,}, | 652 | .hw_params = at91_i2s_hw_params,}, |
622 | .caps = { | 653 | .dai_ops = { |
623 | .mode = &at91_i2s[0], | 654 | .set_sysclk = at91_i2s_set_dai_sysclk, |
624 | .num_modes = ARRAY_SIZE(at91_i2s),}, | 655 | .set_fmt = at91_i2s_set_dai_fmt, |
656 | .set_clkdiv = at91_i2s_set_dai_clkdiv,}, | ||
625 | .private_data = &ssc_info[0].ssc, | 657 | .private_data = &ssc_info[0].ssc, |
626 | }, | 658 | }, |
627 | #if NUM_SSC_DEVICES == 3 | 659 | #if NUM_SSC_DEVICES == 3 |
@@ -630,21 +662,25 @@ struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { | |||
630 | .type = SND_SOC_DAI_I2S, | 662 | .type = SND_SOC_DAI_I2S, |
631 | .suspend = at91_i2s_suspend, | 663 | .suspend = at91_i2s_suspend, |
632 | .resume = at91_i2s_resume, | 664 | .resume = at91_i2s_resume, |
633 | .config_sysclk = at91_i2s_config_sysclk, | ||
634 | .playback = { | 665 | .playback = { |
635 | .channels_min = 1, | 666 | .channels_min = 1, |
636 | .channels_max = 2,}, | 667 | .channels_max = 2, |
668 | .rates = AT91_I2S_RATES, | ||
669 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
637 | .capture = { | 670 | .capture = { |
638 | .channels_min = 1, | 671 | .channels_min = 1, |
639 | .channels_max = 2,}, | 672 | .channels_max = 2, |
673 | .rates = AT91_I2S_RATES, | ||
674 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
640 | .ops = { | 675 | .ops = { |
641 | .startup = at91_i2s_startup, | 676 | .startup = at91_i2s_startup, |
642 | .shutdown = at91_i2s_shutdown, | 677 | .shutdown = at91_i2s_shutdown, |
643 | .prepare = at91_i2s_prepare, | 678 | .prepare = at91_i2s_prepare, |
644 | .hw_params = at91_i2s_hw_params,}, | 679 | .hw_params = at91_i2s_hw_params,}, |
645 | .caps = { | 680 | .dai_ops = { |
646 | .mode = &at91_i2s[0], | 681 | .set_sysclk = at91_i2s_set_dai_sysclk, |
647 | .num_modes = ARRAY_SIZE(at91_i2s),}, | 682 | .set_fmt = at91_i2s_set_dai_fmt, |
683 | .set_clkdiv = at91_i2s_set_dai_clkdiv,}, | ||
648 | .private_data = &ssc_info[1].ssc, | 684 | .private_data = &ssc_info[1].ssc, |
649 | }, | 685 | }, |
650 | { .name = "at91_ssc2/i2s", | 686 | { .name = "at91_ssc2/i2s", |
@@ -652,21 +688,25 @@ struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { | |||
652 | .type = SND_SOC_DAI_I2S, | 688 | .type = SND_SOC_DAI_I2S, |
653 | .suspend = at91_i2s_suspend, | 689 | .suspend = at91_i2s_suspend, |
654 | .resume = at91_i2s_resume, | 690 | .resume = at91_i2s_resume, |
655 | .config_sysclk = at91_i2s_config_sysclk, | ||
656 | .playback = { | 691 | .playback = { |
657 | .channels_min = 1, | 692 | .channels_min = 1, |
658 | .channels_max = 2,}, | 693 | .channels_max = 2, |
694 | .rates = AT91_I2S_RATES, | ||
695 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
659 | .capture = { | 696 | .capture = { |
660 | .channels_min = 1, | 697 | .channels_min = 1, |
661 | .channels_max = 2,}, | 698 | .channels_max = 2, |
699 | .rates = AT91_I2S_RATES, | ||
700 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
662 | .ops = { | 701 | .ops = { |
663 | .startup = at91_i2s_startup, | 702 | .startup = at91_i2s_startup, |
664 | .shutdown = at91_i2s_shutdown, | 703 | .shutdown = at91_i2s_shutdown, |
665 | .prepare = at91_i2s_prepare, | 704 | .prepare = at91_i2s_prepare, |
666 | .hw_params = at91_i2s_hw_params,}, | 705 | .hw_params = at91_i2s_hw_params,}, |
667 | .caps = { | 706 | .dai_ops = { |
668 | .mode = &at91_i2s[0], | 707 | .set_sysclk = at91_i2s_set_dai_sysclk, |
669 | .num_modes = ARRAY_SIZE(at91_i2s),}, | 708 | .set_fmt = at91_i2s_set_dai_fmt, |
709 | .set_clkdiv = at91_i2s_set_dai_clkdiv,}, | ||
670 | .private_data = &ssc_info[2].ssc, | 710 | .private_data = &ssc_info[2].ssc, |
671 | }, | 711 | }, |
672 | #endif | 712 | #endif |
diff --git a/sound/soc/at91/at91-i2s.h b/sound/soc/at91/at91-i2s.h new file mode 100644 index 000000000000..f8a875ba0ccc --- /dev/null +++ b/sound/soc/at91/at91-i2s.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * at91-i2s.h - ALSA I2S 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_I2S_H | ||
14 | #define _AT91_I2S_H | ||
15 | |||
16 | /* I2S system clock ids */ | ||
17 | #define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */ | ||
18 | |||
19 | /* I2S 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 | |||
24 | extern struct snd_soc_cpu_dai at91_i2s_dai[]; | ||
25 | |||
26 | #endif /* _AT91_I2S_H */ | ||
27 | |||