aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2008-01-11 12:15:26 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:55 -0500
commit17467f23395f05ba7b361f7b504fe0f1095d5bb7 (patch)
tree8afcd6fa89cfd6e152635719fd935f5cb3cb2532 /sound/soc/fsl
parentce22e03e62fd37fb2612abb7af1c66cc17038606 (diff)
[ALSA] Add ASoC drivers for the Freescale MPC8610 SoC
Add the ASoC drivers for the Freescale MPC8610 SoC and the MPC8610 HPCD reference board. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/Kconfig20
-rw-r--r--sound/soc/fsl/Makefile6
-rw-r--r--sound/soc/fsl/fsl_dma.c839
-rw-r--r--sound/soc/fsl/fsl_dma.h149
-rw-r--r--sound/soc/fsl/fsl_ssi.c644
-rw-r--r--sound/soc/fsl/fsl_ssi.h224
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c631
7 files changed, 2513 insertions, 0 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
new file mode 100644
index 000000000000..257101f44e9e
--- /dev/null
+++ b/sound/soc/fsl/Kconfig
@@ -0,0 +1,20 @@
1menu "ALSA SoC audio for Freescale SOCs"
2
3config SND_SOC_MPC8610
4 bool "ALSA SoC support for the MPC8610 SOC"
5 depends on SND_SOC && MPC8610_HPCD
6 default y if MPC8610
7 help
8 Say Y if you want to add support for codecs attached to the SSI
9 device on an MPC8610.
10
11config SND_SOC_MPC8610_HPCD
12 bool "ALSA SoC support for the Freescale MPC8610 HPCD board"
13 depends on SND_SOC_MPC8610
14 select SND_SOC_CS4270
15 select SND_SOC_CS4270_VD33_ERRATA
16 default y if MPC8610_HPCD
17 help
18 Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
19
20endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
new file mode 100644
index 000000000000..62f680a4a776
--- /dev/null
+++ b/sound/soc/fsl/Makefile
@@ -0,0 +1,6 @@
1# MPC8610 HPCD Machine Support
2obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o
3
4# MPC8610 Platform Support
5obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o
6
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
new file mode 100644
index 000000000000..2173203b29ab
--- /dev/null
+++ b/sound/soc/fsl/fsl_dma.c
@@ -0,0 +1,839 @@
1/*
2 * Freescale DMA ALSA SoC PCM driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed
7 * under the terms of the GNU General Public License version 2. This
8 * program is licensed "as is" without any warranty of any kind, whether
9 * express or implied.
10 *
11 * This driver implements ASoC support for the Elo DMA controller, which is
12 * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms,
13 * the PCM driver is what handles the DMA buffer.
14 */
15
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/platform_device.h>
19#include <linux/dma-mapping.h>
20#include <linux/interrupt.h>
21#include <linux/delay.h>
22
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28
29#include <asm/io.h>
30
31#include "fsl_dma.h"
32
33/*
34 * The formats that the DMA controller supports, which is anything
35 * that is 8, 16, or 32 bits.
36 */
37#define FSLDMA_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
38 SNDRV_PCM_FMTBIT_U8 | \
39 SNDRV_PCM_FMTBIT_S16_LE | \
40 SNDRV_PCM_FMTBIT_S16_BE | \
41 SNDRV_PCM_FMTBIT_U16_LE | \
42 SNDRV_PCM_FMTBIT_U16_BE | \
43 SNDRV_PCM_FMTBIT_S24_LE | \
44 SNDRV_PCM_FMTBIT_S24_BE | \
45 SNDRV_PCM_FMTBIT_U24_LE | \
46 SNDRV_PCM_FMTBIT_U24_BE | \
47 SNDRV_PCM_FMTBIT_S32_LE | \
48 SNDRV_PCM_FMTBIT_S32_BE | \
49 SNDRV_PCM_FMTBIT_U32_LE | \
50 SNDRV_PCM_FMTBIT_U32_BE)
51
52#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
53 SNDRV_PCM_RATE_CONTINUOUS)
54
55/* DMA global data. This structure is used by fsl_dma_open() to determine
56 * which DMA channels to assign to a substream. Unfortunately, ASoC V1 does
57 * not allow the machine driver to provide this information to the PCM
58 * driver in advance, and there's no way to differentiate between the two
59 * DMA controllers. So for now, this driver only supports one SSI device
60 * using two DMA channels. We cannot support multiple DMA devices.
61 *
62 * ssi_stx_phys: bus address of SSI STX register
63 * ssi_srx_phys: bus address of SSI SRX register
64 * dma_channel: pointer to the DMA channel's registers
65 * irq: IRQ for this DMA channel
66 * assigned: set to 1 if that DMA channel is assigned to a substream
67 */
68static struct {
69 dma_addr_t ssi_stx_phys;
70 dma_addr_t ssi_srx_phys;
71 struct ccsr_dma_channel __iomem *dma_channel[2];
72 unsigned int irq[2];
73 unsigned int assigned[2];
74} dma_global_data;
75
76/*
77 * The number of DMA links to use. Two is the bare minimum, but if you
78 * have really small links you might need more.
79 */
80#define NUM_DMA_LINKS 2
81
82/** fsl_dma_private: p-substream DMA data
83 *
84 * Each substream has a 1-to-1 association with a DMA channel.
85 *
86 * The link[] array is first because it needs to be aligned on a 32-byte
87 * boundary, so putting it first will ensure alignment without padding the
88 * structure.
89 *
90 * @link[]: array of link descriptors
91 * @controller_id: which DMA controller (0, 1, ...)
92 * @channel_id: which DMA channel on the controller (0, 1, 2, ...)
93 * @dma_channel: pointer to the DMA channel's registers
94 * @irq: IRQ for this DMA channel
95 * @substream: pointer to the substream object, needed by the ISR
96 * @ssi_sxx_phys: bus address of the STX or SRX register to use
97 * @ld_buf_phys: physical address of the LD buffer
98 * @current_link: index into link[] of the link currently being processed
99 * @dma_buf_phys: physical address of the DMA buffer
100 * @dma_buf_next: physical address of the next period to process
101 * @dma_buf_end: physical address of the byte after the end of the DMA
102 * @buffer period_size: the size of a single period
103 * @num_periods: the number of periods in the DMA buffer
104 */
105struct fsl_dma_private {
106 struct fsl_dma_link_descriptor link[NUM_DMA_LINKS];
107 unsigned int controller_id;
108 unsigned int channel_id;
109 struct ccsr_dma_channel __iomem *dma_channel;
110 unsigned int irq;
111 struct snd_pcm_substream *substream;
112 dma_addr_t ssi_sxx_phys;
113 dma_addr_t ld_buf_phys;
114 unsigned int current_link;
115 dma_addr_t dma_buf_phys;
116 dma_addr_t dma_buf_next;
117 dma_addr_t dma_buf_end;
118 size_t period_size;
119 unsigned int num_periods;
120};
121
122/**
123 * fsl_dma_hardare: define characteristics of the PCM hardware.
124 *
125 * The PCM hardware is the Freescale DMA controller. This structure defines
126 * the capabilities of that hardware.
127 *
128 * Since the sampling rate and data format are not controlled by the DMA
129 * controller, we specify no limits for those values. The only exception is
130 * period_bytes_min, which is set to a reasonably low value to prevent the
131 * DMA controller from generating too many interrupts per second.
132 *
133 * Since each link descriptor has a 32-bit byte count field, we set
134 * period_bytes_max to the largest 32-bit number. We also have no maximum
135 * number of periods.
136 */
137static const struct snd_pcm_hardware fsl_dma_hardware = {
138
139 .info = SNDRV_PCM_INFO_INTERLEAVED,
140 .formats = FSLDMA_PCM_FORMATS,
141 .rates = FSLDMA_PCM_RATES,
142 .rate_min = 5512,
143 .rate_max = 192000,
144 .period_bytes_min = 512, /* A reasonable limit */
145 .period_bytes_max = (u32) -1,
146 .periods_min = NUM_DMA_LINKS,
147 .periods_max = (unsigned int) -1,
148 .buffer_bytes_max = 128 * 1024, /* A reasonable limit */
149};
150
151/**
152 * fsl_dma_abort_stream: tell ALSA that the DMA transfer has aborted
153 *
154 * This function should be called by the ISR whenever the DMA controller
155 * halts data transfer.
156 */
157static void fsl_dma_abort_stream(struct snd_pcm_substream *substream)
158{
159 unsigned long flags;
160
161 snd_pcm_stream_lock_irqsave(substream, flags);
162
163 if (snd_pcm_running(substream))
164 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
165
166 snd_pcm_stream_unlock_irqrestore(substream, flags);
167}
168
169/**
170 * fsl_dma_update_pointers - update LD pointers to point to the next period
171 *
172 * As each period is completed, this function changes the the link
173 * descriptor pointers for that period to point to the next period.
174 */
175static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
176{
177 struct fsl_dma_link_descriptor *link =
178 &dma_private->link[dma_private->current_link];
179
180 /* Update our link descriptors to point to the next period */
181 if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
182 link->source_addr =
183 cpu_to_be32(dma_private->dma_buf_next);
184 else
185 link->dest_addr =
186 cpu_to_be32(dma_private->dma_buf_next);
187
188 /* Update our variables for next time */
189 dma_private->dma_buf_next += dma_private->period_size;
190
191 if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
192 dma_private->dma_buf_next = dma_private->dma_buf_phys;
193
194 if (++dma_private->current_link >= NUM_DMA_LINKS)
195 dma_private->current_link = 0;
196}
197
198/**
199 * fsl_dma_isr: interrupt handler for the DMA controller
200 *
201 * @irq: IRQ of the DMA channel
202 * @dev_id: pointer to the dma_private structure for this DMA channel
203 */
204static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
205{
206 struct fsl_dma_private *dma_private = dev_id;
207 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
208 irqreturn_t ret = IRQ_NONE;
209 u32 sr, sr2 = 0;
210
211 /* We got an interrupt, so read the status register to see what we
212 were interrupted for.
213 */
214 sr = in_be32(&dma_channel->sr);
215
216 if (sr & CCSR_DMA_SR_TE) {
217 dev_err(dma_private->substream->pcm->card->dev,
218 "DMA transmit error (controller=%u channel=%u irq=%u\n",
219 dma_private->controller_id,
220 dma_private->channel_id, irq);
221 fsl_dma_abort_stream(dma_private->substream);
222 sr2 |= CCSR_DMA_SR_TE;
223 ret = IRQ_HANDLED;
224 }
225
226 if (sr & CCSR_DMA_SR_CH)
227 ret = IRQ_HANDLED;
228
229 if (sr & CCSR_DMA_SR_PE) {
230 dev_err(dma_private->substream->pcm->card->dev,
231 "DMA%u programming error (channel=%u irq=%u)\n",
232 dma_private->controller_id,
233 dma_private->channel_id, irq);
234 fsl_dma_abort_stream(dma_private->substream);
235 sr2 |= CCSR_DMA_SR_PE;
236 ret = IRQ_HANDLED;
237 }
238
239 if (sr & CCSR_DMA_SR_EOLNI) {
240 sr2 |= CCSR_DMA_SR_EOLNI;
241 ret = IRQ_HANDLED;
242 }
243
244 if (sr & CCSR_DMA_SR_CB)
245 ret = IRQ_HANDLED;
246
247 if (sr & CCSR_DMA_SR_EOSI) {
248 struct snd_pcm_substream *substream = dma_private->substream;
249
250 /* Tell ALSA we completed a period. */
251 snd_pcm_period_elapsed(substream);
252
253 /*
254 * Update our link descriptors to point to the next period. We
255 * only need to do this if the number of periods is not equal to
256 * the number of links.
257 */
258 if (dma_private->num_periods != NUM_DMA_LINKS)
259 fsl_dma_update_pointers(dma_private);
260
261 sr2 |= CCSR_DMA_SR_EOSI;
262 ret = IRQ_HANDLED;
263 }
264
265 if (sr & CCSR_DMA_SR_EOLSI) {
266 sr2 |= CCSR_DMA_SR_EOLSI;
267 ret = IRQ_HANDLED;
268 }
269
270 /* Clear the bits that we set */
271 if (sr2)
272 out_be32(&dma_channel->sr, sr2);
273
274 return ret;
275}
276
277/**
278 * fsl_dma_new: initialize this PCM driver.
279 *
280 * This function is called when the codec driver calls snd_soc_new_pcms(),
281 * once for each .dai_link in the machine driver's snd_soc_machine
282 * structure.
283 */
284static int fsl_dma_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
285 struct snd_pcm *pcm)
286{
287 static u64 fsl_dma_dmamask = DMA_BIT_MASK(32);
288 int ret;
289
290 if (!card->dev->dma_mask)
291 card->dev->dma_mask = &fsl_dma_dmamask;
292
293 if (!card->dev->coherent_dma_mask)
294 card->dev->coherent_dma_mask = fsl_dma_dmamask;
295
296 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev,
297 fsl_dma_hardware.buffer_bytes_max,
298 &pcm->streams[0].substream->dma_buffer);
299 if (ret) {
300 dev_err(card->dev,
301 "Can't allocate playback DMA buffer (size=%u)\n",
302 fsl_dma_hardware.buffer_bytes_max);
303 return -ENOMEM;
304 }
305
306 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev,
307 fsl_dma_hardware.buffer_bytes_max,
308 &pcm->streams[1].substream->dma_buffer);
309 if (ret) {
310 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
311 dev_err(card->dev,
312 "Can't allocate capture DMA buffer (size=%u)\n",
313 fsl_dma_hardware.buffer_bytes_max);
314 return -ENOMEM;
315 }
316
317 return 0;
318}
319
320/**
321 * fsl_dma_open: open a new substream.
322 *
323 * Each substream has its own DMA buffer.
324 */
325static int fsl_dma_open(struct snd_pcm_substream *substream)
326{
327 struct snd_pcm_runtime *runtime = substream->runtime;
328 struct fsl_dma_private *dma_private;
329 dma_addr_t ld_buf_phys;
330 unsigned int channel;
331 int ret = 0;
332
333 /*
334 * Reject any DMA buffer whose size is not a multiple of the period
335 * size. We need to make sure that the DMA buffer can be evenly divided
336 * into periods.
337 */
338 ret = snd_pcm_hw_constraint_integer(runtime,
339 SNDRV_PCM_HW_PARAM_PERIODS);
340 if (ret < 0) {
341 dev_err(substream->pcm->card->dev, "invalid buffer size\n");
342 return ret;
343 }
344
345 channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
346
347 if (dma_global_data.assigned[channel]) {
348 dev_err(substream->pcm->card->dev,
349 "DMA channel already assigned\n");
350 return -EBUSY;
351 }
352
353 dma_private = dma_alloc_coherent(substream->pcm->dev,
354 sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL);
355 if (!dma_private) {
356 dev_err(substream->pcm->card->dev,
357 "can't allocate DMA private data\n");
358 return -ENOMEM;
359 }
360 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
361 dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys;
362 else
363 dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys;
364
365 dma_private->dma_channel = dma_global_data.dma_channel[channel];
366 dma_private->irq = dma_global_data.irq[channel];
367 dma_private->substream = substream;
368 dma_private->ld_buf_phys = ld_buf_phys;
369 dma_private->dma_buf_phys = substream->dma_buffer.addr;
370
371 /* We only support one DMA controller for now */
372 dma_private->controller_id = 0;
373 dma_private->channel_id = channel;
374
375 ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private);
376 if (ret) {
377 dev_err(substream->pcm->card->dev,
378 "can't register ISR for IRQ %u (ret=%i)\n",
379 dma_private->irq, ret);
380 dma_free_coherent(substream->pcm->dev,
381 sizeof(struct fsl_dma_private),
382 dma_private, dma_private->ld_buf_phys);
383 return ret;
384 }
385
386 dma_global_data.assigned[channel] = 1;
387
388 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
389 snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
390 runtime->private_data = dma_private;
391
392 return 0;
393}
394
395/**
396 * fsl_dma_hw_params: allocate the DMA buffer and the DMA link descriptors.
397 *
398 * ALSA divides the DMA buffer into N periods. We create NUM_DMA_LINKS link
399 * descriptors that ping-pong from one period to the next. For example, if
400 * there are six periods and two link descriptors, this is how they look
401 * before playback starts:
402 *
403 * The last link descriptor
404 * ____________ points back to the first
405 * | |
406 * V |
407 * ___ ___ |
408 * | |->| |->|
409 * |___| |___|
410 * | |
411 * | |
412 * V V
413 * _________________________________________
414 * | | | | | | | The DMA buffer is
415 * | | | | | | | divided into 6 parts
416 * |______|______|______|______|______|______|
417 *
418 * and here's how they look after the first period is finished playing:
419 *
420 * ____________
421 * | |
422 * V |
423 * ___ ___ |
424 * | |->| |->|
425 * |___| |___|
426 * | |
427 * |______________
428 * | |
429 * V V
430 * _________________________________________
431 * | | | | | | |
432 * | | | | | | |
433 * |______|______|______|______|______|______|
434 *
435 * The first link descriptor now points to the third period. The DMA
436 * controller is currently playing the second period. When it finishes, it
437 * will jump back to the first descriptor and play the third period.
438 *
439 * There are four reasons we do this:
440 *
441 * 1. The only way to get the DMA controller to automatically restart the
442 * transfer when it gets to the end of the buffer is to use chaining
443 * mode. Basic direct mode doesn't offer that feature.
444 * 2. We need to receive an interrupt at the end of every period. The DMA
445 * controller can generate an interrupt at the end of every link transfer
446 * (aka segment). Making each period into a DMA segment will give us the
447 * interrupts we need.
448 * 3. By creating only two link descriptors, regardless of the number of
449 * periods, we do not need to reallocate the link descriptors if the
450 * number of periods changes.
451 * 4. All of the audio data is still stored in a single, contiguous DMA
452 * buffer, which is what ALSA expects. We're just dividing it into
453 * contiguous parts, and creating a link descriptor for each one.
454 *
455 * Note that due to a quirk of the SSI's STX register, the target address
456 * for the DMA operations depends on the sample size. So we don't program
457 * the dest_addr (for playback -- source_addr for capture) fields in the
458 * link descriptors here. We do that in fsl_dma_prepare()
459 */
460static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
461 struct snd_pcm_hw_params *hw_params)
462{
463 struct snd_pcm_runtime *runtime = substream->runtime;
464 struct fsl_dma_private *dma_private = runtime->private_data;
465 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
466
467 dma_addr_t temp_addr; /* Pointer to next period */
468 u64 temp_link; /* Pointer to next link descriptor */
469 u32 mr; /* Temporary variable for MR register */
470
471 unsigned int i;
472
473 /* Get all the parameters we need */
474 size_t buffer_size = params_buffer_bytes(hw_params);
475 size_t period_size = params_period_bytes(hw_params);
476
477 /* Initialize our DMA tracking variables */
478 dma_private->period_size = period_size;
479 dma_private->num_periods = params_periods(hw_params);
480 dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size;
481 dma_private->dma_buf_next = dma_private->dma_buf_phys +
482 (NUM_DMA_LINKS * period_size);
483 if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
484 dma_private->dma_buf_next = dma_private->dma_buf_phys;
485
486 /*
487 * Initialize each link descriptor.
488 *
489 * The actual address in STX0 (destination for playback, source for
490 * capture) is based on the sample size, but we don't know the sample
491 * size in this function, so we'll have to adjust that later. See
492 * comments in fsl_dma_prepare().
493 *
494 * The DMA controller does not have a cache, so the CPU does not
495 * need to tell it to flush its cache. However, the DMA
496 * controller does need to tell the CPU to flush its cache.
497 * That's what the SNOOP bit does.
498 *
499 * Also, even though the DMA controller supports 36-bit addressing, for
500 * simplicity we currently support only 32-bit addresses for the audio
501 * buffer itself.
502 */
503 temp_addr = substream->dma_buffer.addr;
504 temp_link = dma_private->ld_buf_phys +
505 sizeof(struct fsl_dma_link_descriptor);
506
507 for (i = 0; i < NUM_DMA_LINKS; i++) {
508 struct fsl_dma_link_descriptor *link = &dma_private->link[i];
509
510 link->count = cpu_to_be32(period_size);
511 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
512 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
513 link->next = cpu_to_be64(temp_link);
514
515 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
516 link->source_addr = cpu_to_be32(temp_addr);
517 else
518 link->dest_addr = cpu_to_be32(temp_addr);
519
520 temp_addr += period_size;
521 temp_link += sizeof(struct fsl_dma_link_descriptor);
522 }
523 /* The last link descriptor points to the first */
524 dma_private->link[i - 1].next = cpu_to_be64(dma_private->ld_buf_phys);
525
526 /* Tell the DMA controller where the first link descriptor is */
527 out_be32(&dma_channel->clndar,
528 CCSR_DMA_CLNDAR_ADDR(dma_private->ld_buf_phys));
529 out_be32(&dma_channel->eclndar,
530 CCSR_DMA_ECLNDAR_ADDR(dma_private->ld_buf_phys));
531
532 /* The manual says the BCR must be clear before enabling EMP */
533 out_be32(&dma_channel->bcr, 0);
534
535 /*
536 * Program the mode register for interrupts, external master control,
537 * and source/destination hold. Also clear the Channel Abort bit.
538 */
539 mr = in_be32(&dma_channel->mr) &
540 ~(CCSR_DMA_MR_CA | CCSR_DMA_MR_DAHE | CCSR_DMA_MR_SAHE);
541
542 /*
543 * We want External Master Start and External Master Pause enabled,
544 * because the SSI is controlling the DMA controller. We want the DMA
545 * controller to be set up in advance, and then we signal only the SSI
546 * to start transfering.
547 *
548 * We want End-Of-Segment Interrupts enabled, because this will generate
549 * an interrupt at the end of each segment (each link descriptor
550 * represents one segment). Each DMA segment is the same thing as an
551 * ALSA period, so this is how we get an interrupt at the end of every
552 * period.
553 *
554 * We want Error Interrupt enabled, so that we can get an error if
555 * the DMA controller is mis-programmed somehow.
556 */
557 mr |= CCSR_DMA_MR_EOSIE | CCSR_DMA_MR_EIE | CCSR_DMA_MR_EMP_EN |
558 CCSR_DMA_MR_EMS_EN;
559
560 /* For playback, we want the destination address to be held. For
561 capture, set the source address to be held. */
562 mr |= (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
563 CCSR_DMA_MR_DAHE : CCSR_DMA_MR_SAHE;
564
565 out_be32(&dma_channel->mr, mr);
566
567 return 0;
568}
569
570/**
571 * fsl_dma_prepare - prepare the DMA registers for playback.
572 *
573 * This function is called after the specifics of the audio data are known,
574 * i.e. snd_pcm_runtime is initialized.
575 *
576 * In this function, we finish programming the registers of the DMA
577 * controller that are dependent on the sample size.
578 *
579 * One of the drawbacks with big-endian is that when copying integers of
580 * different sizes to a fixed-sized register, the address to which the
581 * integer must be copied is dependent on the size of the integer.
582 *
583 * For example, if P is the address of a 32-bit register, and X is a 32-bit
584 * integer, then X should be copied to address P. However, if X is a 16-bit
585 * integer, then it should be copied to P+2. If X is an 8-bit register,
586 * then it should be copied to P+3.
587 *
588 * So for playback of 8-bit samples, the DMA controller must transfer single
589 * bytes from the DMA buffer to the last byte of the STX0 register, i.e.
590 * offset by 3 bytes. For 16-bit samples, the offset is two bytes.
591 *
592 * For 24-bit samples, the offset is 1 byte. However, the DMA controller
593 * does not support 3-byte copies (the DAHTS register supports only 1, 2, 4,
594 * and 8 bytes at a time). So we do not support packed 24-bit samples.
595 * 24-bit data must be padded to 32 bits.
596 */
597static int fsl_dma_prepare(struct snd_pcm_substream *substream)
598{
599 struct snd_pcm_runtime *runtime = substream->runtime;
600 struct fsl_dma_private *dma_private = runtime->private_data;
601 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
602 u32 mr;
603 unsigned int i;
604 dma_addr_t ssi_sxx_phys; /* Bus address of SSI STX register */
605 unsigned int frame_size; /* Number of bytes per frame */
606
607 ssi_sxx_phys = dma_private->ssi_sxx_phys;
608
609 mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK |
610 CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK);
611
612 switch (runtime->sample_bits) {
613 case 8:
614 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
615 ssi_sxx_phys += 3;
616 break;
617 case 16:
618 mr |= CCSR_DMA_MR_DAHTS_2 | CCSR_DMA_MR_SAHTS_2;
619 ssi_sxx_phys += 2;
620 break;
621 case 32:
622 mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4;
623 break;
624 default:
625 dev_err(substream->pcm->card->dev,
626 "unsupported sample size %u\n", runtime->sample_bits);
627 return -EINVAL;
628 }
629
630 frame_size = runtime->frame_bits / 8;
631 /*
632 * BWC should always be a multiple of the frame size. BWC determines
633 * how many bytes are sent/received before the DMA controller checks the
634 * SSI to see if it needs to stop. For playback, the transmit FIFO can
635 * hold three frames, so we want to send two frames at a time. For
636 * capture, the receive FIFO is triggered when it contains one frame, so
637 * we want to receive one frame at a time.
638 */
639
640 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
641 mr |= CCSR_DMA_MR_BWC(2 * frame_size);
642 else
643 mr |= CCSR_DMA_MR_BWC(frame_size);
644
645 out_be32(&dma_channel->mr, mr);
646
647 /*
648 * Program the address of the DMA transfer to/from the SSI.
649 */
650 for (i = 0; i < NUM_DMA_LINKS; i++) {
651 struct fsl_dma_link_descriptor *link = &dma_private->link[i];
652
653 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
654 link->dest_addr = cpu_to_be32(ssi_sxx_phys);
655 else
656 link->source_addr = cpu_to_be32(ssi_sxx_phys);
657 }
658
659 return 0;
660}
661
662/**
663 * fsl_dma_pointer: determine the current position of the DMA transfer
664 *
665 * This function is called by ALSA when ALSA wants to know where in the
666 * stream buffer the hardware currently is.
667 *
668 * For playback, the SAR register contains the physical address of the most
669 * recent DMA transfer. For capture, the value is in the DAR register.
670 *
671 * The base address of the buffer is stored in the source_addr field of the
672 * first link descriptor.
673 */
674static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
675{
676 struct snd_pcm_runtime *runtime = substream->runtime;
677 struct fsl_dma_private *dma_private = runtime->private_data;
678 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
679 dma_addr_t position;
680 snd_pcm_uframes_t frames;
681
682 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
683 position = in_be32(&dma_channel->sar);
684 else
685 position = in_be32(&dma_channel->dar);
686
687 frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys);
688
689 /*
690 * If the current address is just past the end of the buffer, wrap it
691 * around.
692 */
693 if (frames == runtime->buffer_size)
694 frames = 0;
695
696 return frames;
697}
698
699/**
700 * fsl_dma_hw_free: release resources allocated in fsl_dma_hw_params()
701 *
702 * Release the resources allocated in fsl_dma_hw_params() and de-program the
703 * registers.
704 *
705 * This function can be called multiple times.
706 */
707static int fsl_dma_hw_free(struct snd_pcm_substream *substream)
708{
709 struct snd_pcm_runtime *runtime = substream->runtime;
710 struct fsl_dma_private *dma_private = runtime->private_data;
711
712 if (dma_private) {
713 struct ccsr_dma_channel __iomem *dma_channel;
714
715 dma_channel = dma_private->dma_channel;
716
717 /* Stop the DMA */
718 out_be32(&dma_channel->mr, CCSR_DMA_MR_CA);
719 out_be32(&dma_channel->mr, 0);
720
721 /* Reset all the other registers */
722 out_be32(&dma_channel->sr, -1);
723 out_be32(&dma_channel->clndar, 0);
724 out_be32(&dma_channel->eclndar, 0);
725 out_be32(&dma_channel->satr, 0);
726 out_be32(&dma_channel->sar, 0);
727 out_be32(&dma_channel->datr, 0);
728 out_be32(&dma_channel->dar, 0);
729 out_be32(&dma_channel->bcr, 0);
730 out_be32(&dma_channel->nlndar, 0);
731 out_be32(&dma_channel->enlndar, 0);
732 }
733
734 return 0;
735}
736
737/**
738 * fsl_dma_close: close the stream.
739 */
740static int fsl_dma_close(struct snd_pcm_substream *substream)
741{
742 struct snd_pcm_runtime *runtime = substream->runtime;
743 struct fsl_dma_private *dma_private = runtime->private_data;
744 int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
745
746 if (dma_private) {
747 if (dma_private->irq)
748 free_irq(dma_private->irq, dma_private);
749
750 if (dma_private->ld_buf_phys) {
751 dma_unmap_single(substream->pcm->dev,
752 dma_private->ld_buf_phys,
753 sizeof(dma_private->link), DMA_TO_DEVICE);
754 }
755
756 /* Deallocate the fsl_dma_private structure */
757 dma_free_coherent(substream->pcm->dev,
758 sizeof(struct fsl_dma_private),
759 dma_private, dma_private->ld_buf_phys);
760 substream->runtime->private_data = NULL;
761 }
762
763 dma_global_data.assigned[dir] = 0;
764
765 return 0;
766}
767
768/*
769 * Remove this PCM driver.
770 */
771static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
772{
773 struct snd_pcm_substream *substream;
774 unsigned int i;
775
776 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
777 substream = pcm->streams[i].substream;
778 if (substream) {
779 snd_dma_free_pages(&substream->dma_buffer);
780 substream->dma_buffer.area = NULL;
781 substream->dma_buffer.addr = 0;
782 }
783 }
784}
785
786static struct snd_pcm_ops fsl_dma_ops = {
787 .open = fsl_dma_open,
788 .close = fsl_dma_close,
789 .ioctl = snd_pcm_lib_ioctl,
790 .hw_params = fsl_dma_hw_params,
791 .hw_free = fsl_dma_hw_free,
792 .prepare = fsl_dma_prepare,
793 .pointer = fsl_dma_pointer,
794};
795
796struct snd_soc_platform fsl_soc_platform = {
797 .name = "fsl-dma",
798 .pcm_ops = &fsl_dma_ops,
799 .pcm_new = fsl_dma_new,
800 .pcm_free = fsl_dma_free_dma_buffers,
801};
802EXPORT_SYMBOL_GPL(fsl_soc_platform);
803
804/**
805 * fsl_dma_configure: store the DMA parameters from the fabric driver.
806 *
807 * This function is called by the ASoC fabric driver to give us the DMA and
808 * SSI channel information.
809 *
810 * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI
811 * data when a substream is created, so for now we need to store this data
812 * into a global variable. This means that we can only support one DMA
813 * controller, and hence only one SSI.
814 */
815int fsl_dma_configure(struct fsl_dma_info *dma_info)
816{
817 static int initialized;
818
819 /* We only support one DMA controller for now */
820 if (initialized)
821 return 0;
822
823 dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys;
824 dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys;
825 dma_global_data.dma_channel[0] = dma_info->dma_channel[0];
826 dma_global_data.dma_channel[1] = dma_info->dma_channel[1];
827 dma_global_data.irq[0] = dma_info->dma_irq[0];
828 dma_global_data.irq[1] = dma_info->dma_irq[1];
829 dma_global_data.assigned[0] = 0;
830 dma_global_data.assigned[1] = 0;
831
832 initialized = 1;
833 return 1;
834}
835EXPORT_SYMBOL_GPL(fsl_dma_configure);
836
837MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
838MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module");
839MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h
new file mode 100644
index 000000000000..430a6ce8b0d0
--- /dev/null
+++ b/sound/soc/fsl/fsl_dma.h
@@ -0,0 +1,149 @@
1/*
2 * mpc8610-pcm.h - ALSA PCM interface for the Freescale MPC8610 SoC
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _MPC8610_PCM_H
10#define _MPC8610_PCM_H
11
12struct ccsr_dma {
13 u8 res0[0x100];
14 struct ccsr_dma_channel {
15 __be32 mr; /* Mode register */
16 __be32 sr; /* Status register */
17 __be32 eclndar; /* Current link descriptor extended addr reg */
18 __be32 clndar; /* Current link descriptor address register */
19 __be32 satr; /* Source attributes register */
20 __be32 sar; /* Source address register */
21 __be32 datr; /* Destination attributes register */
22 __be32 dar; /* Destination address register */
23 __be32 bcr; /* Byte count register */
24 __be32 enlndar; /* Next link descriptor extended address reg */
25 __be32 nlndar; /* Next link descriptor address register */
26 u8 res1[4];
27 __be32 eclsdar; /* Current list descriptor extended addr reg */
28 __be32 clsdar; /* Current list descriptor address register */
29 __be32 enlsdar; /* Next list descriptor extended address reg */
30 __be32 nlsdar; /* Next list descriptor address register */
31 __be32 ssr; /* Source stride register */
32 __be32 dsr; /* Destination stride register */
33 u8 res2[0x38];
34 } channel[4];
35 __be32 dgsr;
36};
37
38#define CCSR_DMA_MR_BWC_DISABLED 0x0F000000
39#define CCSR_DMA_MR_BWC_SHIFT 24
40#define CCSR_DMA_MR_BWC_MASK 0x0F000000
41#define CCSR_DMA_MR_BWC(x) \
42 ((ilog2(x) << CCSR_DMA_MR_BWC_SHIFT) & CCSR_DMA_MR_BWC_MASK)
43#define CCSR_DMA_MR_EMP_EN 0x00200000
44#define CCSR_DMA_MR_EMS_EN 0x00040000
45#define CCSR_DMA_MR_DAHTS_MASK 0x00030000
46#define CCSR_DMA_MR_DAHTS_1 0x00000000
47#define CCSR_DMA_MR_DAHTS_2 0x00010000
48#define CCSR_DMA_MR_DAHTS_4 0x00020000
49#define CCSR_DMA_MR_DAHTS_8 0x00030000
50#define CCSR_DMA_MR_SAHTS_MASK 0x0000C000
51#define CCSR_DMA_MR_SAHTS_1 0x00000000
52#define CCSR_DMA_MR_SAHTS_2 0x00004000
53#define CCSR_DMA_MR_SAHTS_4 0x00008000
54#define CCSR_DMA_MR_SAHTS_8 0x0000C000
55#define CCSR_DMA_MR_DAHE 0x00002000
56#define CCSR_DMA_MR_SAHE 0x00001000
57#define CCSR_DMA_MR_SRW 0x00000400
58#define CCSR_DMA_MR_EOSIE 0x00000200
59#define CCSR_DMA_MR_EOLNIE 0x00000100
60#define CCSR_DMA_MR_EOLSIE 0x00000080
61#define CCSR_DMA_MR_EIE 0x00000040
62#define CCSR_DMA_MR_XFE 0x00000020
63#define CCSR_DMA_MR_CDSM_SWSM 0x00000010
64#define CCSR_DMA_MR_CA 0x00000008
65#define CCSR_DMA_MR_CTM 0x00000004
66#define CCSR_DMA_MR_CC 0x00000002
67#define CCSR_DMA_MR_CS 0x00000001
68
69#define CCSR_DMA_SR_TE 0x00000080
70#define CCSR_DMA_SR_CH 0x00000020
71#define CCSR_DMA_SR_PE 0x00000010
72#define CCSR_DMA_SR_EOLNI 0x00000008
73#define CCSR_DMA_SR_CB 0x00000004
74#define CCSR_DMA_SR_EOSI 0x00000002
75#define CCSR_DMA_SR_EOLSI 0x00000001
76
77/* ECLNDAR takes bits 32-36 of the CLNDAR register */
78static inline u32 CCSR_DMA_ECLNDAR_ADDR(u64 x)
79{
80 return (x >> 32) & 0xf;
81}
82
83#define CCSR_DMA_CLNDAR_ADDR(x) ((x) & 0xFFFFFFFE)
84#define CCSR_DMA_CLNDAR_EOSIE 0x00000008
85
86/* SATR and DATR, combined */
87#define CCSR_DMA_ATR_PBATMU 0x20000000
88#define CCSR_DMA_ATR_TFLOWLVL_0 0x00000000
89#define CCSR_DMA_ATR_TFLOWLVL_1 0x06000000
90#define CCSR_DMA_ATR_TFLOWLVL_2 0x08000000
91#define CCSR_DMA_ATR_TFLOWLVL_3 0x0C000000
92#define CCSR_DMA_ATR_PCIORDER 0x02000000
93#define CCSR_DMA_ATR_SME 0x01000000
94#define CCSR_DMA_ATR_NOSNOOP 0x00040000
95#define CCSR_DMA_ATR_SNOOP 0x00050000
96#define CCSR_DMA_ATR_ESAD_MASK 0x0000000F
97
98/**
99 * List Descriptor for extended chaining mode DMA operations.
100 *
101 * The CLSDAR register points to the first (in a linked-list) List
102 * Descriptor. Each object must be aligned on a 32-byte boundary. Each
103 * list descriptor points to a linked-list of link Descriptors.
104 */
105struct fsl_dma_list_descriptor {
106 __be64 next; /* Address of next list descriptor */
107 __be64 first_link; /* Address of first link descriptor */
108 __be32 source; /* Source stride */
109 __be32 dest; /* Destination stride */
110 u8 res[8]; /* Reserved */
111} __attribute__ ((aligned(32), packed));
112
113/**
114 * Link Descriptor for basic and extended chaining mode DMA operations.
115 *
116 * A Link Descriptor points to a single DMA buffer. Each link descriptor
117 * must be aligned on a 32-byte boundary.
118 */
119struct fsl_dma_link_descriptor {
120 __be32 source_attr; /* Programmed into SATR register */
121 __be32 source_addr; /* Programmed into SAR register */
122 __be32 dest_attr; /* Programmed into DATR register */
123 __be32 dest_addr; /* Programmed into DAR register */
124 __be64 next; /* Address of next link descriptor */
125 __be32 count; /* Byte count */
126 u8 res[4]; /* Reserved */
127} __attribute__ ((aligned(32), packed));
128
129/* DMA information needed to create a snd_soc_cpu_dai object
130 *
131 * ssi_stx_phys: bus address of SSI STX register to use
132 * ssi_srx_phys: bus address of SSI SRX register to use
133 * dma[0]: points to the DMA channel to use for playback
134 * dma[1]: points to the DMA channel to use for capture
135 * dma_irq[0]: IRQ of the DMA channel to use for playback
136 * dma_irq[1]: IRQ of the DMA channel to use for capture
137 */
138struct fsl_dma_info {
139 dma_addr_t ssi_stx_phys;
140 dma_addr_t ssi_srx_phys;
141 struct ccsr_dma_channel __iomem *dma_channel[2];
142 unsigned int dma_irq[2];
143};
144
145extern struct snd_soc_platform fsl_soc_platform;
146
147int fsl_dma_configure(struct fsl_dma_info *dma_info);
148
149#endif
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
new file mode 100644
index 000000000000..145ad13d52d1
--- /dev/null
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -0,0 +1,644 @@
1/*
2 * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed
7 * under the terms of the GNU General Public License version 2. This
8 * program is licensed "as is" without any warranty of any kind, whether
9 * express or implied.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/device.h>
16#include <linux/delay.h>
17
18#include <sound/driver.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/initval.h>
23#include <sound/soc.h>
24
25#include <asm/immap_86xx.h>
26
27#include "fsl_ssi.h"
28
29/**
30 * FSLSSI_I2S_RATES: sample rates supported by the I2S
31 *
32 * This driver currently only supports the SSI running in I2S slave mode,
33 * which means the codec determines the sample rate. Therefore, we tell
34 * ALSA that we support all rates and let the codec driver decide what rates
35 * are really supported.
36 */
37#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
38 SNDRV_PCM_RATE_CONTINUOUS)
39
40/**
41 * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
42 *
43 * This driver currently only supports the SSI running in I2S slave mode.
44 *
45 * The SSI has a limitation in that the samples must be in the same byte
46 * order as the host CPU. This is because when multiple bytes are written
47 * to the STX register, the bytes and bits must be written in the same
48 * order. The STX is a shift register, so all the bits need to be aligned
49 * (bit-endianness must match byte-endianness). Processors typically write
50 * the bits within a byte in the same order that the bytes of a word are
51 * written in. So if the host CPU is big-endian, then only big-endian
52 * samples will be written to STX properly.
53 */
54#ifdef __BIG_ENDIAN
55#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
56 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
57 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
58#else
59#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
60 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
61 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
62#endif
63
64/**
65 * fsl_ssi_private: per-SSI private data
66 *
67 * @name: short name for this device ("SSI0", "SSI1", etc)
68 * @ssi: pointer to the SSI's registers
69 * @ssi_phys: physical address of the SSI registers
70 * @irq: IRQ of this SSI
71 * @dev: struct device pointer
72 * @playback: the number of playback streams opened
73 * @capture: the number of capture streams opened
74 * @cpu_dai: the CPU DAI for this device
75 * @dev_attr: the sysfs device attribute structure
76 * @stats: SSI statistics
77 */
78struct fsl_ssi_private {
79 char name[8];
80 struct ccsr_ssi __iomem *ssi;
81 dma_addr_t ssi_phys;
82 unsigned int irq;
83 struct device *dev;
84 unsigned int playback;
85 unsigned int capture;
86 struct snd_soc_cpu_dai cpu_dai;
87 struct device_attribute dev_attr;
88
89 struct {
90 unsigned int rfrc;
91 unsigned int tfrc;
92 unsigned int cmdau;
93 unsigned int cmddu;
94 unsigned int rxt;
95 unsigned int rdr1;
96 unsigned int rdr0;
97 unsigned int tde1;
98 unsigned int tde0;
99 unsigned int roe1;
100 unsigned int roe0;
101 unsigned int tue1;
102 unsigned int tue0;
103 unsigned int tfs;
104 unsigned int rfs;
105 unsigned int tls;
106 unsigned int rls;
107 unsigned int rff1;
108 unsigned int rff0;
109 unsigned int tfe1;
110 unsigned int tfe0;
111 } stats;
112};
113
114/**
115 * fsl_ssi_isr: SSI interrupt handler
116 *
117 * Although it's possible to use the interrupt handler to send and receive
118 * data to/from the SSI, we use the DMA instead. Programming is more
119 * complicated, but the performance is much better.
120 *
121 * This interrupt handler is used only to gather statistics.
122 *
123 * @irq: IRQ of the SSI device
124 * @dev_id: pointer to the ssi_private structure for this SSI device
125 */
126static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
127{
128 struct fsl_ssi_private *ssi_private = dev_id;
129 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
130 irqreturn_t ret = IRQ_NONE;
131 __be32 sisr;
132 __be32 sisr2 = 0;
133
134 /* We got an interrupt, so read the status register to see what we
135 were interrupted for. We mask it with the Interrupt Enable register
136 so that we only check for events that we're interested in.
137 */
138 sisr = in_be32(&ssi->sisr) & in_be32(&ssi->sier);
139
140 if (sisr & CCSR_SSI_SISR_RFRC) {
141 ssi_private->stats.rfrc++;
142 sisr2 |= CCSR_SSI_SISR_RFRC;
143 ret = IRQ_HANDLED;
144 }
145
146 if (sisr & CCSR_SSI_SISR_TFRC) {
147 ssi_private->stats.tfrc++;
148 sisr2 |= CCSR_SSI_SISR_TFRC;
149 ret = IRQ_HANDLED;
150 }
151
152 if (sisr & CCSR_SSI_SISR_CMDAU) {
153 ssi_private->stats.cmdau++;
154 ret = IRQ_HANDLED;
155 }
156
157 if (sisr & CCSR_SSI_SISR_CMDDU) {
158 ssi_private->stats.cmddu++;
159 ret = IRQ_HANDLED;
160 }
161
162 if (sisr & CCSR_SSI_SISR_RXT) {
163 ssi_private->stats.rxt++;
164 ret = IRQ_HANDLED;
165 }
166
167 if (sisr & CCSR_SSI_SISR_RDR1) {
168 ssi_private->stats.rdr1++;
169 ret = IRQ_HANDLED;
170 }
171
172 if (sisr & CCSR_SSI_SISR_RDR0) {
173 ssi_private->stats.rdr0++;
174 ret = IRQ_HANDLED;
175 }
176
177 if (sisr & CCSR_SSI_SISR_TDE1) {
178 ssi_private->stats.tde1++;
179 ret = IRQ_HANDLED;
180 }
181
182 if (sisr & CCSR_SSI_SISR_TDE0) {
183 ssi_private->stats.tde0++;
184 ret = IRQ_HANDLED;
185 }
186
187 if (sisr & CCSR_SSI_SISR_ROE1) {
188 ssi_private->stats.roe1++;
189 sisr2 |= CCSR_SSI_SISR_ROE1;
190 ret = IRQ_HANDLED;
191 }
192
193 if (sisr & CCSR_SSI_SISR_ROE0) {
194 ssi_private->stats.roe0++;
195 sisr2 |= CCSR_SSI_SISR_ROE0;
196 ret = IRQ_HANDLED;
197 }
198
199 if (sisr & CCSR_SSI_SISR_TUE1) {
200 ssi_private->stats.tue1++;
201 sisr2 |= CCSR_SSI_SISR_TUE1;
202 ret = IRQ_HANDLED;
203 }
204
205 if (sisr & CCSR_SSI_SISR_TUE0) {
206 ssi_private->stats.tue0++;
207 sisr2 |= CCSR_SSI_SISR_TUE0;
208 ret = IRQ_HANDLED;
209 }
210
211 if (sisr & CCSR_SSI_SISR_TFS) {
212 ssi_private->stats.tfs++;
213 ret = IRQ_HANDLED;
214 }
215
216 if (sisr & CCSR_SSI_SISR_RFS) {
217 ssi_private->stats.rfs++;
218 ret = IRQ_HANDLED;
219 }
220
221 if (sisr & CCSR_SSI_SISR_TLS) {
222 ssi_private->stats.tls++;
223 ret = IRQ_HANDLED;
224 }
225
226 if (sisr & CCSR_SSI_SISR_RLS) {
227 ssi_private->stats.rls++;
228 ret = IRQ_HANDLED;
229 }
230
231 if (sisr & CCSR_SSI_SISR_RFF1) {
232 ssi_private->stats.rff1++;
233 ret = IRQ_HANDLED;
234 }
235
236 if (sisr & CCSR_SSI_SISR_RFF0) {
237 ssi_private->stats.rff0++;
238 ret = IRQ_HANDLED;
239 }
240
241 if (sisr & CCSR_SSI_SISR_TFE1) {
242 ssi_private->stats.tfe1++;
243 ret = IRQ_HANDLED;
244 }
245
246 if (sisr & CCSR_SSI_SISR_TFE0) {
247 ssi_private->stats.tfe0++;
248 ret = IRQ_HANDLED;
249 }
250
251 /* Clear the bits that we set */
252 if (sisr2)
253 out_be32(&ssi->sisr, sisr2);
254
255 return ret;
256}
257
258/**
259 * fsl_ssi_startup: create a new substream
260 *
261 * This is the first function called when a stream is opened.
262 *
263 * If this is the first stream open, then grab the IRQ and program most of
264 * the SSI registers.
265 */
266static int fsl_ssi_startup(struct snd_pcm_substream *substream)
267{
268 struct snd_soc_pcm_runtime *rtd = substream->private_data;
269 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
270
271 /*
272 * If this is the first stream opened, then request the IRQ
273 * and initialize the SSI registers.
274 */
275 if (!ssi_private->playback && !ssi_private->capture) {
276 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
277 int ret;
278
279 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
280 ssi_private->name, ssi_private);
281 if (ret < 0) {
282 dev_err(substream->pcm->card->dev,
283 "could not claim irq %u\n", ssi_private->irq);
284 return ret;
285 }
286
287 /*
288 * Section 16.5 of the MPC8610 reference manual says that the
289 * SSI needs to be disabled before updating the registers we set
290 * here.
291 */
292 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
293
294 /*
295 * Program the SSI into I2S Slave Non-Network Synchronous mode.
296 * Also enable the transmit and receive FIFO.
297 *
298 * FIXME: Little-endian samples require a different shift dir
299 */
300 clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK,
301 CCSR_SSI_SCR_TFR_CLK_DIS |
302 CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN);
303
304 out_be32(&ssi->stcr,
305 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
306 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
307 CCSR_SSI_STCR_TSCKP);
308
309 out_be32(&ssi->srcr,
310 CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
311 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
312 CCSR_SSI_SRCR_RSCKP);
313
314 /*
315 * The DC and PM bits are only used if the SSI is the clock
316 * master.
317 */
318
319 /* 4. Enable the interrupts and DMA requests */
320 out_be32(&ssi->sier,
321 CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE |
322 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN |
323 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN |
324 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE |
325 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN);
326
327 /*
328 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
329 * don't use FIFO 1. Since the SSI only supports stereo, the
330 * watermark should never be an odd number.
331 */
332 out_be32(&ssi->sfcsr,
333 CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2));
334
335 /*
336 * We keep the SSI disabled because if we enable it, then the
337 * DMA controller will start. It's not supposed to start until
338 * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The
339 * DMA controller will transfer one "BWC" of data (i.e. the
340 * amount of data that the MR.BWC bits are set to). The reason
341 * this is bad is because at this point, the PCM driver has not
342 * finished initializing the DMA controller.
343 */
344 }
345
346 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
347 ssi_private->playback++;
348
349 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
350 ssi_private->capture++;
351
352 return 0;
353}
354
355/**
356 * fsl_ssi_prepare: prepare the SSI.
357 *
358 * Most of the SSI registers have been programmed in the startup function,
359 * but the word length must be programmed here. Unfortunately, programming
360 * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can
361 * cause a problem with supporting simultaneous playback and capture. If
362 * the SSI is already playing a stream, then that stream may be temporarily
363 * stopped when you start capture.
364 *
365 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
366 * clock master.
367 */
368static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
369{
370 struct snd_pcm_runtime *runtime = substream->runtime;
371 struct snd_soc_pcm_runtime *rtd = substream->private_data;
372 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
373
374 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
375 u32 wl;
376
377 wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format));
378
379 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
380
381 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
382 clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
383 else
384 clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
385
386 setbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
387
388 return 0;
389}
390
391/**
392 * fsl_ssi_trigger: start and stop the DMA transfer.
393 *
394 * This function is called by ALSA to start, stop, pause, and resume the DMA
395 * transfer of data.
396 *
397 * The DMA channel is in external master start and pause mode, which
398 * means the SSI completely controls the flow of data.
399 */
400static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
401{
402 struct snd_soc_pcm_runtime *rtd = substream->private_data;
403 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
404 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
405
406 switch (cmd) {
407 case SNDRV_PCM_TRIGGER_START:
408 case SNDRV_PCM_TRIGGER_RESUME:
409 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
410 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
411 setbits32(&ssi->scr, CCSR_SSI_SCR_TE);
412 } else {
413 setbits32(&ssi->scr, CCSR_SSI_SCR_RE);
414
415 /*
416 * I think we need this delay to allow time for the SSI
417 * to put data into its FIFO. Without it, ALSA starts
418 * to complain about overruns.
419 */
420 msleep(1);
421 }
422 break;
423
424 case SNDRV_PCM_TRIGGER_STOP:
425 case SNDRV_PCM_TRIGGER_SUSPEND:
426 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
427 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
428 clrbits32(&ssi->scr, CCSR_SSI_SCR_TE);
429 else
430 clrbits32(&ssi->scr, CCSR_SSI_SCR_RE);
431 break;
432
433 default:
434 return -EINVAL;
435 }
436
437 return 0;
438}
439
440/**
441 * fsl_ssi_shutdown: shutdown the SSI
442 *
443 * Shutdown the SSI if there are no other substreams open.
444 */
445static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
446{
447 struct snd_soc_pcm_runtime *rtd = substream->private_data;
448 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
449
450 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
451 ssi_private->playback--;
452
453 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
454 ssi_private->capture--;
455
456 /*
457 * If this is the last active substream, disable the SSI and release
458 * the IRQ.
459 */
460 if (!ssi_private->playback && !ssi_private->capture) {
461 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
462
463 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
464
465 free_irq(ssi_private->irq, ssi_private);
466 }
467}
468
469/**
470 * fsl_ssi_set_sysclk: set the clock frequency and direction
471 *
472 * This function is called by the machine driver to tell us what the clock
473 * frequency and direction are.
474 *
475 * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
476 * and we don't care about the frequency. Return an error if the direction
477 * is not SND_SOC_CLOCK_IN.
478 *
479 * @clk_id: reserved, should be zero
480 * @freq: the frequency of the given clock ID, currently ignored
481 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
482 */
483static int fsl_ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
484 int clk_id, unsigned int freq, int dir)
485{
486
487 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
488}
489
490/**
491 * fsl_ssi_set_fmt: set the serial format.
492 *
493 * This function is called by the machine driver to tell us what serial
494 * format to use.
495 *
496 * Currently, we only support I2S mode. Return an error if the format is
497 * not SND_SOC_DAIFMT_I2S.
498 *
499 * @format: one of SND_SOC_DAIFMT_xxx
500 */
501static int fsl_ssi_set_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int format)
502{
503 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
504}
505
506/**
507 * fsl_ssi_dai_template: template CPU DAI for the SSI
508 */
509static struct snd_soc_cpu_dai fsl_ssi_dai_template = {
510 .playback = {
511 /* The SSI does not support monaural audio. */
512 .channels_min = 2,
513 .channels_max = 2,
514 .rates = FSLSSI_I2S_RATES,
515 .formats = FSLSSI_I2S_FORMATS,
516 },
517 .capture = {
518 .channels_min = 2,
519 .channels_max = 2,
520 .rates = FSLSSI_I2S_RATES,
521 .formats = FSLSSI_I2S_FORMATS,
522 },
523 .ops = {
524 .startup = fsl_ssi_startup,
525 .prepare = fsl_ssi_prepare,
526 .shutdown = fsl_ssi_shutdown,
527 .trigger = fsl_ssi_trigger,
528 },
529 .dai_ops = {
530 .set_sysclk = fsl_ssi_set_sysclk,
531 .set_fmt = fsl_ssi_set_fmt,
532 },
533};
534
535/**
536 * fsl_sysfs_ssi_show: display SSI statistics
537 *
538 * Display the statistics for the current SSI device.
539 */
540static ssize_t fsl_sysfs_ssi_show(struct device *dev,
541 struct device_attribute *attr, char *buf)
542{
543 struct fsl_ssi_private *ssi_private =
544 container_of(attr, struct fsl_ssi_private, dev_attr);
545 ssize_t length;
546
547 length = sprintf(buf, "rfrc=%u", ssi_private->stats.rfrc);
548 length += sprintf(buf + length, "\ttfrc=%u", ssi_private->stats.tfrc);
549 length += sprintf(buf + length, "\tcmdau=%u", ssi_private->stats.cmdau);
550 length += sprintf(buf + length, "\tcmddu=%u", ssi_private->stats.cmddu);
551 length += sprintf(buf + length, "\trxt=%u", ssi_private->stats.rxt);
552 length += sprintf(buf + length, "\trdr1=%u", ssi_private->stats.rdr1);
553 length += sprintf(buf + length, "\trdr0=%u", ssi_private->stats.rdr0);
554 length += sprintf(buf + length, "\ttde1=%u", ssi_private->stats.tde1);
555 length += sprintf(buf + length, "\ttde0=%u", ssi_private->stats.tde0);
556 length += sprintf(buf + length, "\troe1=%u", ssi_private->stats.roe1);
557 length += sprintf(buf + length, "\troe0=%u", ssi_private->stats.roe0);
558 length += sprintf(buf + length, "\ttue1=%u", ssi_private->stats.tue1);
559 length += sprintf(buf + length, "\ttue0=%u", ssi_private->stats.tue0);
560 length += sprintf(buf + length, "\ttfs=%u", ssi_private->stats.tfs);
561 length += sprintf(buf + length, "\trfs=%u", ssi_private->stats.rfs);
562 length += sprintf(buf + length, "\ttls=%u", ssi_private->stats.tls);
563 length += sprintf(buf + length, "\trls=%u", ssi_private->stats.rls);
564 length += sprintf(buf + length, "\trff1=%u", ssi_private->stats.rff1);
565 length += sprintf(buf + length, "\trff0=%u", ssi_private->stats.rff0);
566 length += sprintf(buf + length, "\ttfe1=%u", ssi_private->stats.tfe1);
567 length += sprintf(buf + length, "\ttfe0=%u\n", ssi_private->stats.tfe0);
568
569 return length;
570}
571
572/**
573 * fsl_ssi_create_dai: create a snd_soc_cpu_dai structure
574 *
575 * This function is called by the machine driver to create a snd_soc_cpu_dai
576 * structure. The function creates an ssi_private object, which contains
577 * the snd_soc_cpu_dai. It also creates the sysfs statistics device.
578 */
579struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
580{
581 struct snd_soc_cpu_dai *fsl_ssi_dai;
582 struct fsl_ssi_private *ssi_private;
583 int ret = 0;
584 struct device_attribute *dev_attr;
585
586 ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL);
587 if (!ssi_private) {
588 dev_err(ssi_info->dev, "could not allocate DAI object\n");
589 return NULL;
590 }
591 memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
592 sizeof(struct snd_soc_cpu_dai));
593
594 fsl_ssi_dai = &ssi_private->cpu_dai;
595 dev_attr = &ssi_private->dev_attr;
596
597 sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id);
598 ssi_private->ssi = ssi_info->ssi;
599 ssi_private->ssi_phys = ssi_info->ssi_phys;
600 ssi_private->irq = ssi_info->irq;
601 ssi_private->dev = ssi_info->dev;
602
603 ssi_private->dev->driver_data = fsl_ssi_dai;
604
605 /* Initialize the the device_attribute structure */
606 dev_attr->attr.name = "ssi-stats";
607 dev_attr->attr.mode = S_IRUGO;
608 dev_attr->show = fsl_sysfs_ssi_show;
609
610 ret = device_create_file(ssi_private->dev, dev_attr);
611 if (ret) {
612 dev_err(ssi_info->dev, "could not create sysfs %s file\n",
613 ssi_private->dev_attr.attr.name);
614 kfree(fsl_ssi_dai);
615 return NULL;
616 }
617
618 fsl_ssi_dai->private_data = ssi_private;
619 fsl_ssi_dai->name = ssi_private->name;
620 fsl_ssi_dai->id = ssi_info->id;
621
622 return fsl_ssi_dai;
623}
624EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
625
626/**
627 * fsl_ssi_destroy_dai: destroy the snd_soc_cpu_dai object
628 *
629 * This function undoes the operations of fsl_ssi_create_dai()
630 */
631void fsl_ssi_destroy_dai(struct snd_soc_cpu_dai *fsl_ssi_dai)
632{
633 struct fsl_ssi_private *ssi_private =
634 container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
635
636 device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
637
638 kfree(ssi_private);
639}
640EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
641
642MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
643MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
644MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
new file mode 100644
index 000000000000..c5ce88e15651
--- /dev/null
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -0,0 +1,224 @@
1/*
2 * fsl_ssi.h - ALSA SSI interface for the Freescale MPC8610 SoC
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed
7 * under the terms of the GNU General Public License version 2. This
8 * program is licensed "as is" without any warranty of any kind, whether
9 * express or implied.
10 */
11
12#ifndef _MPC8610_I2S_H
13#define _MPC8610_I2S_H
14
15/* SSI Register Map */
16struct ccsr_ssi {
17 __be32 stx0; /* 0x.0000 - SSI Transmit Data Register 0 */
18 __be32 stx1; /* 0x.0004 - SSI Transmit Data Register 1 */
19 __be32 srx0; /* 0x.0008 - SSI Receive Data Register 0 */
20 __be32 srx1; /* 0x.000C - SSI Receive Data Register 1 */
21 __be32 scr; /* 0x.0010 - SSI Control Register */
22 __be32 sisr; /* 0x.0014 - SSI Interrupt Status Register Mixed */
23 __be32 sier; /* 0x.0018 - SSI Interrupt Enable Register */
24 __be32 stcr; /* 0x.001C - SSI Transmit Configuration Register */
25 __be32 srcr; /* 0x.0020 - SSI Receive Configuration Register */
26 __be32 stccr; /* 0x.0024 - SSI Transmit Clock Control Register */
27 __be32 srccr; /* 0x.0028 - SSI Receive Clock Control Register */
28 __be32 sfcsr; /* 0x.002C - SSI FIFO Control/Status Register */
29 __be32 str; /* 0x.0030 - SSI Test Register */
30 __be32 sor; /* 0x.0034 - SSI Option Register */
31 __be32 sacnt; /* 0x.0038 - SSI AC97 Control Register */
32 __be32 sacadd; /* 0x.003C - SSI AC97 Command Address Register */
33 __be32 sacdat; /* 0x.0040 - SSI AC97 Command Data Register */
34 __be32 satag; /* 0x.0044 - SSI AC97 Tag Register */
35 __be32 stmsk; /* 0x.0048 - SSI Transmit Time Slot Mask Register */
36 __be32 srmsk; /* 0x.004C - SSI Receive Time Slot Mask Register */
37 __be32 saccst; /* 0x.0050 - SSI AC97 Channel Status Register */
38 __be32 saccen; /* 0x.0054 - SSI AC97 Channel Enable Register */
39 __be32 saccdis; /* 0x.0058 - SSI AC97 Channel Disable Register */
40};
41
42#define CCSR_SSI_SCR_RFR_CLK_DIS 0x00000800
43#define CCSR_SSI_SCR_TFR_CLK_DIS 0x00000400
44#define CCSR_SSI_SCR_TCH_EN 0x00000100
45#define CCSR_SSI_SCR_SYS_CLK_EN 0x00000080
46#define CCSR_SSI_SCR_I2S_MODE_MASK 0x00000060
47#define CCSR_SSI_SCR_I2S_MODE_NORMAL 0x00000000
48#define CCSR_SSI_SCR_I2S_MODE_MASTER 0x00000020
49#define CCSR_SSI_SCR_I2S_MODE_SLAVE 0x00000040
50#define CCSR_SSI_SCR_SYN 0x00000010
51#define CCSR_SSI_SCR_NET 0x00000008
52#define CCSR_SSI_SCR_RE 0x00000004
53#define CCSR_SSI_SCR_TE 0x00000002
54#define CCSR_SSI_SCR_SSIEN 0x00000001
55
56#define CCSR_SSI_SISR_RFRC 0x01000000
57#define CCSR_SSI_SISR_TFRC 0x00800000
58#define CCSR_SSI_SISR_CMDAU 0x00040000
59#define CCSR_SSI_SISR_CMDDU 0x00020000
60#define CCSR_SSI_SISR_RXT 0x00010000
61#define CCSR_SSI_SISR_RDR1 0x00008000
62#define CCSR_SSI_SISR_RDR0 0x00004000
63#define CCSR_SSI_SISR_TDE1 0x00002000
64#define CCSR_SSI_SISR_TDE0 0x00001000
65#define CCSR_SSI_SISR_ROE1 0x00000800
66#define CCSR_SSI_SISR_ROE0 0x00000400
67#define CCSR_SSI_SISR_TUE1 0x00000200
68#define CCSR_SSI_SISR_TUE0 0x00000100
69#define CCSR_SSI_SISR_TFS 0x00000080
70#define CCSR_SSI_SISR_RFS 0x00000040
71#define CCSR_SSI_SISR_TLS 0x00000020
72#define CCSR_SSI_SISR_RLS 0x00000010
73#define CCSR_SSI_SISR_RFF1 0x00000008
74#define CCSR_SSI_SISR_RFF0 0x00000004
75#define CCSR_SSI_SISR_TFE1 0x00000002
76#define CCSR_SSI_SISR_TFE0 0x00000001
77
78#define CCSR_SSI_SIER_RFRC_EN 0x01000000
79#define CCSR_SSI_SIER_TFRC_EN 0x00800000
80#define CCSR_SSI_SIER_RDMAE 0x00400000
81#define CCSR_SSI_SIER_RIE 0x00200000
82#define CCSR_SSI_SIER_TDMAE 0x00100000
83#define CCSR_SSI_SIER_TIE 0x00080000
84#define CCSR_SSI_SIER_CMDAU_EN 0x00040000
85#define CCSR_SSI_SIER_CMDDU_EN 0x00020000
86#define CCSR_SSI_SIER_RXT_EN 0x00010000
87#define CCSR_SSI_SIER_RDR1_EN 0x00008000
88#define CCSR_SSI_SIER_RDR0_EN 0x00004000
89#define CCSR_SSI_SIER_TDE1_EN 0x00002000
90#define CCSR_SSI_SIER_TDE0_EN 0x00001000
91#define CCSR_SSI_SIER_ROE1_EN 0x00000800
92#define CCSR_SSI_SIER_ROE0_EN 0x00000400
93#define CCSR_SSI_SIER_TUE1_EN 0x00000200
94#define CCSR_SSI_SIER_TUE0_EN 0x00000100
95#define CCSR_SSI_SIER_TFS_EN 0x00000080
96#define CCSR_SSI_SIER_RFS_EN 0x00000040
97#define CCSR_SSI_SIER_TLS_EN 0x00000020
98#define CCSR_SSI_SIER_RLS_EN 0x00000010
99#define CCSR_SSI_SIER_RFF1_EN 0x00000008
100#define CCSR_SSI_SIER_RFF0_EN 0x00000004
101#define CCSR_SSI_SIER_TFE1_EN 0x00000002
102#define CCSR_SSI_SIER_TFE0_EN 0x00000001
103
104#define CCSR_SSI_STCR_TXBIT0 0x00000200
105#define CCSR_SSI_STCR_TFEN1 0x00000100
106#define CCSR_SSI_STCR_TFEN0 0x00000080
107#define CCSR_SSI_STCR_TFDIR 0x00000040
108#define CCSR_SSI_STCR_TXDIR 0x00000020
109#define CCSR_SSI_STCR_TSHFD 0x00000010
110#define CCSR_SSI_STCR_TSCKP 0x00000008
111#define CCSR_SSI_STCR_TFSI 0x00000004
112#define CCSR_SSI_STCR_TFSL 0x00000002
113#define CCSR_SSI_STCR_TEFS 0x00000001
114
115#define CCSR_SSI_SRCR_RXEXT 0x00000400
116#define CCSR_SSI_SRCR_RXBIT0 0x00000200
117#define CCSR_SSI_SRCR_RFEN1 0x00000100
118#define CCSR_SSI_SRCR_RFEN0 0x00000080
119#define CCSR_SSI_SRCR_RFDIR 0x00000040
120#define CCSR_SSI_SRCR_RXDIR 0x00000020
121#define CCSR_SSI_SRCR_RSHFD 0x00000010
122#define CCSR_SSI_SRCR_RSCKP 0x00000008
123#define CCSR_SSI_SRCR_RFSI 0x00000004
124#define CCSR_SSI_SRCR_RFSL 0x00000002
125#define CCSR_SSI_SRCR_REFS 0x00000001
126
127/* STCCR and SRCCR */
128#define CCSR_SSI_SxCCR_DIV2 0x00040000
129#define CCSR_SSI_SxCCR_PSR 0x00020000
130#define CCSR_SSI_SxCCR_WL_SHIFT 13
131#define CCSR_SSI_SxCCR_WL_MASK 0x0001E000
132#define CCSR_SSI_SxCCR_WL(x) \
133 (((((x) / 2) - 1) << CCSR_SSI_SxCCR_WL_SHIFT) & CCSR_SSI_SxCCR_WL_MASK)
134#define CCSR_SSI_SxCCR_DC_SHIFT 8
135#define CCSR_SSI_SxCCR_DC_MASK 0x00001F00
136#define CCSR_SSI_SxCCR_DC(x) \
137 ((((x) - 1) << CCSR_SSI_SxCCR_DC_SHIFT) & CCSR_SSI_SxCCR_DC_MASK)
138#define CCSR_SSI_SxCCR_PM_SHIFT 0
139#define CCSR_SSI_SxCCR_PM_MASK 0x000000FF
140#define CCSR_SSI_SxCCR_PM(x) \
141 ((((x) - 1) << CCSR_SSI_SxCCR_PM_SHIFT) & CCSR_SSI_SxCCR_PM_MASK)
142
143/*
144 * The xFCNT bits are read-only, and the xFWM bits are read/write. Use the
145 * CCSR_SSI_SFCSR_xFCNTy() macros to read the FIFO counters, and use the
146 * CCSR_SSI_SFCSR_xFWMy() macros to set the watermarks.
147 */
148#define CCSR_SSI_SFCSR_RFCNT1_SHIFT 28
149#define CCSR_SSI_SFCSR_RFCNT1_MASK 0xF0000000
150#define CCSR_SSI_SFCSR_RFCNT1(x) \
151 (((x) & CCSR_SSI_SFCSR_RFCNT1_MASK) >> CCSR_SSI_SFCSR_RFCNT1_SHIFT)
152#define CCSR_SSI_SFCSR_TFCNT1_SHIFT 24
153#define CCSR_SSI_SFCSR_TFCNT1_MASK 0x0F000000
154#define CCSR_SSI_SFCSR_TFCNT1(x) \
155 (((x) & CCSR_SSI_SFCSR_TFCNT1_MASK) >> CCSR_SSI_SFCSR_TFCNT1_SHIFT)
156#define CCSR_SSI_SFCSR_RFWM1_SHIFT 20
157#define CCSR_SSI_SFCSR_RFWM1_MASK 0x00F00000
158#define CCSR_SSI_SFCSR_RFWM1(x) \
159 (((x) << CCSR_SSI_SFCSR_RFWM1_SHIFT) & CCSR_SSI_SFCSR_RFWM1_MASK)
160#define CCSR_SSI_SFCSR_TFWM1_SHIFT 16
161#define CCSR_SSI_SFCSR_TFWM1_MASK 0x000F0000
162#define CCSR_SSI_SFCSR_TFWM1(x) \
163 (((x) << CCSR_SSI_SFCSR_TFWM1_SHIFT) & CCSR_SSI_SFCSR_TFWM1_MASK)
164#define CCSR_SSI_SFCSR_RFCNT0_SHIFT 12
165#define CCSR_SSI_SFCSR_RFCNT0_MASK 0x0000F000
166#define CCSR_SSI_SFCSR_RFCNT0(x) \
167 (((x) & CCSR_SSI_SFCSR_RFCNT0_MASK) >> CCSR_SSI_SFCSR_RFCNT0_SHIFT)
168#define CCSR_SSI_SFCSR_TFCNT0_SHIFT 8
169#define CCSR_SSI_SFCSR_TFCNT0_MASK 0x00000F00
170#define CCSR_SSI_SFCSR_TFCNT0(x) \
171 (((x) & CCSR_SSI_SFCSR_TFCNT0_MASK) >> CCSR_SSI_SFCSR_TFCNT0_SHIFT)
172#define CCSR_SSI_SFCSR_RFWM0_SHIFT 4
173#define CCSR_SSI_SFCSR_RFWM0_MASK 0x000000F0
174#define CCSR_SSI_SFCSR_RFWM0(x) \
175 (((x) << CCSR_SSI_SFCSR_RFWM0_SHIFT) & CCSR_SSI_SFCSR_RFWM0_MASK)
176#define CCSR_SSI_SFCSR_TFWM0_SHIFT 0
177#define CCSR_SSI_SFCSR_TFWM0_MASK 0x0000000F
178#define CCSR_SSI_SFCSR_TFWM0(x) \
179 (((x) << CCSR_SSI_SFCSR_TFWM0_SHIFT) & CCSR_SSI_SFCSR_TFWM0_MASK)
180
181#define CCSR_SSI_STR_TEST 0x00008000
182#define CCSR_SSI_STR_RCK2TCK 0x00004000
183#define CCSR_SSI_STR_RFS2TFS 0x00002000
184#define CCSR_SSI_STR_RXSTATE(x) (((x) >> 8) & 0x1F)
185#define CCSR_SSI_STR_TXD2RXD 0x00000080
186#define CCSR_SSI_STR_TCK2RCK 0x00000040
187#define CCSR_SSI_STR_TFS2RFS 0x00000020
188#define CCSR_SSI_STR_TXSTATE(x) ((x) & 0x1F)
189
190#define CCSR_SSI_SOR_CLKOFF 0x00000040
191#define CCSR_SSI_SOR_RX_CLR 0x00000020
192#define CCSR_SSI_SOR_TX_CLR 0x00000010
193#define CCSR_SSI_SOR_INIT 0x00000008
194#define CCSR_SSI_SOR_WAIT_SHIFT 1
195#define CCSR_SSI_SOR_WAIT_MASK 0x00000006
196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT)
197#define CCSR_SSI_SOR_SYNRST 0x00000001
198
199/* Instantiation data for an SSI interface
200 *
201 * This structure contains all the information that the the SSI driver needs
202 * to instantiate an SSI interface with ALSA. The machine driver should
203 * create this structure, fill it in, call fsl_ssi_create_dai(), and then
204 * delete the structure.
205 *
206 * id: which SSI this is (0, 1, etc. )
207 * ssi: pointer to the SSI's registers
208 * ssi_phys: physical address of the SSI registers
209 * irq: IRQ of this SSI
210 * dev: struct device, used to create the sysfs statistics file
211*/
212struct fsl_ssi_info {
213 unsigned int id;
214 struct ccsr_ssi __iomem *ssi;
215 dma_addr_t ssi_phys;
216 unsigned int irq;
217 struct device *dev;
218};
219
220struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
221void fsl_ssi_destroy_dai(struct snd_soc_cpu_dai *fsl_ssi_dai);
222
223#endif
224
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
new file mode 100644
index 000000000000..f26c4b2e8b6e
--- /dev/null
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -0,0 +1,631 @@
1/**
2 * Freescale MPC8610HPCD ALSA SoC Fabric driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed
7 * under the terms of the GNU General Public License version 2. This
8 * program is licensed "as is" without any warranty of any kind, whether
9 * express or implied.
10 */
11
12#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/of_device.h>
15#include <linux/of_platform.h>
16#include <sound/soc.h>
17#include <asm/immap_86xx.h>
18
19#include "../codecs/cs4270.h"
20#include "fsl_dma.h"
21#include "fsl_ssi.h"
22
23/**
24 * mpc8610_hpcd_data: fabric-specific ASoC device data
25 *
26 * This structure contains data for a single sound platform device on an
27 * MPC8610 HPCD. Some of the data is taken from the device tree.
28 */
29struct mpc8610_hpcd_data {
30 struct snd_soc_device sound_devdata;
31 struct snd_soc_dai_link dai;
32 struct snd_soc_machine machine;
33 unsigned int dai_format;
34 unsigned int codec_clk_direction;
35 unsigned int cpu_clk_direction;
36 unsigned int clk_frequency;
37 struct ccsr_guts __iomem *guts;
38 struct ccsr_ssi __iomem *ssi;
39 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
40 unsigned int ssi_irq;
41 unsigned int dma_id; /* 0 = DMA1, 1 = DMA2, etc */
42 unsigned int dma_irq[2];
43 struct ccsr_dma_channel __iomem *dma[2];
44 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
45};
46
47/**
48 * mpc8610_hpcd_machine_probe: initalize the board
49 *
50 * This function is called when platform_device_add() is called. It is used
51 * to initialize the board-specific hardware.
52 *
53 * Here we program the DMACR and PMUXCR registers.
54 */
55static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
56{
57 struct mpc8610_hpcd_data *machine_data =
58 sound_device->dev.platform_data;
59
60 /* Program the signal routing between the SSI and the DMA */
61 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
62 machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI);
63 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
64 machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI);
65
66 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
67 machine_data->dma_channel_id[0], 0);
68 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
69 machine_data->dma_channel_id[1], 0);
70
71 guts_set_pmuxcr_dma(machine_data->guts, 1, 0, 0);
72 guts_set_pmuxcr_dma(machine_data->guts, 1, 3, 0);
73 guts_set_pmuxcr_dma(machine_data->guts, 0, 3, 0);
74
75 switch (machine_data->ssi_id) {
76 case 0:
77 clrsetbits_be32(&machine_data->guts->pmuxcr,
78 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI);
79 break;
80 case 1:
81 clrsetbits_be32(&machine_data->guts->pmuxcr,
82 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI);
83 break;
84 }
85
86 return 0;
87}
88
89/**
90 * mpc8610_hpcd_startup: program the board with various hardware parameters
91 *
92 * This function takes board-specific information, like clock frequencies
93 * and serial data formats, and passes that information to the codec and
94 * transport drivers.
95 */
96static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
97{
98 struct snd_soc_pcm_runtime *rtd = substream->private_data;
99 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
100 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
101 struct mpc8610_hpcd_data *machine_data =
102 rtd->socdev->dev->platform_data;
103 int ret = 0;
104
105 /* Tell the CPU driver what the serial protocol is. */
106 if (cpu_dai->dai_ops.set_fmt) {
107 ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
108 machine_data->dai_format);
109 if (ret < 0) {
110 dev_err(substream->pcm->card->dev,
111 "could not set CPU driver audio format\n");
112 return ret;
113 }
114 }
115
116 /* Tell the codec driver what the serial protocol is. */
117 if (codec_dai->dai_ops.set_fmt) {
118 ret = codec_dai->dai_ops.set_fmt(codec_dai,
119 machine_data->dai_format);
120 if (ret < 0) {
121 dev_err(substream->pcm->card->dev,
122 "could not set codec driver audio format\n");
123 return ret;
124 }
125 }
126
127 /*
128 * Tell the CPU driver what the clock frequency is, and whether it's a
129 * slave or master.
130 */
131 if (cpu_dai->dai_ops.set_sysclk) {
132 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, 0,
133 machine_data->clk_frequency,
134 machine_data->cpu_clk_direction);
135 if (ret < 0) {
136 dev_err(substream->pcm->card->dev,
137 "could not set CPU driver clock parameters\n");
138 return ret;
139 }
140 }
141
142 /*
143 * Tell the codec driver what the MCLK frequency is, and whether it's
144 * a slave or master.
145 */
146 if (codec_dai->dai_ops.set_sysclk) {
147 ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0,
148 machine_data->clk_frequency,
149 machine_data->codec_clk_direction);
150 if (ret < 0) {
151 dev_err(substream->pcm->card->dev,
152 "could not set codec driver clock params\n");
153 return ret;
154 }
155 }
156
157 return 0;
158}
159
160/**
161 * mpc8610_hpcd_machine_remove: Remove the sound device
162 *
163 * This function is called to remove the sound device for one SSI. We
164 * de-program the DMACR and PMUXCR register.
165 */
166int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
167{
168 struct mpc8610_hpcd_data *machine_data =
169 sound_device->dev.platform_data;
170
171 /* Restore the signal routing */
172
173 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
174 machine_data->dma_channel_id[0], 0);
175 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
176 machine_data->dma_channel_id[1], 0);
177
178 switch (machine_data->ssi_id) {
179 case 0:
180 clrsetbits_be32(&machine_data->guts->pmuxcr,
181 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);
182 break;
183 case 1:
184 clrsetbits_be32(&machine_data->guts->pmuxcr,
185 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);
186 break;
187 }
188
189 return 0;
190}
191
192/**
193 * mpc8610_hpcd_ops: ASoC fabric driver operations
194 */
195static struct snd_soc_ops mpc8610_hpcd_ops = {
196 .startup = mpc8610_hpcd_startup,
197};
198
199/**
200 * mpc8610_hpcd_machine: ASoC machine data
201 */
202static struct snd_soc_machine mpc8610_hpcd_machine = {
203 .probe = mpc8610_hpcd_machine_probe,
204 .remove = mpc8610_hpcd_machine_remove,
205 .name = "MPC8610 HPCD",
206 .num_links = 1,
207};
208
209/**
210 * mpc8610_hpcd_probe: OF probe function for the fabric driver
211 *
212 * This function gets called when an SSI node is found in the device tree.
213 *
214 * Although this is a fabric driver, the SSI node is the "master" node with
215 * respect to audio hardware connections. Therefore, we create a new ASoC
216 * device for each new SSI node that has a codec attached.
217 *
218 * FIXME: Currently, we only support one DMA controller, so if there are
219 * multiple SSI nodes with codecs, only the first will be supported.
220 *
221 * FIXME: Even if we did support multiple DMA controllers, we have no
222 * mechanism for assigning DMA controllers and channels to the individual
223 * SSI devices. We also probably aren't compatible with the generic Elo DMA
224 * device driver.
225 */
226static int mpc8610_hpcd_probe(struct of_device *ofdev,
227 const struct of_device_id *match)
228{
229 struct device_node *np = ofdev->node;
230 struct device_node *codec_np = NULL;
231 struct device_node *guts_np = NULL;
232 struct device_node *dma_np = NULL;
233 struct device_node *dma_channel_np = NULL;
234 const phandle *codec_ph;
235 const char *sprop;
236 const u32 *iprop;
237 struct resource res;
238 struct platform_device *sound_device = NULL;
239 struct mpc8610_hpcd_data *machine_data;
240 struct fsl_ssi_info ssi_info;
241 struct fsl_dma_info dma_info;
242 int ret = -ENODEV;
243
244 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);
245 if (!machine_data)
246 return -ENOMEM;
247
248 memset(&ssi_info, 0, sizeof(ssi_info));
249 memset(&dma_info, 0, sizeof(dma_info));
250
251 ssi_info.dev = &ofdev->dev;
252
253 /*
254 * We are only interested in SSIs with a codec phandle in them, so let's
255 * make sure this SSI has one.
256 */
257 codec_ph = of_get_property(np, "codec-handle", NULL);
258 if (!codec_ph)
259 goto error;
260
261 codec_np = of_find_node_by_phandle(*codec_ph);
262 if (!codec_np)
263 goto error;
264
265 /* The MPC8610 HPCD only knows about the CS4270 codec, so reject
266 anything else. */
267 if (!of_device_is_compatible(codec_np, "cirrus,cs4270"))
268 goto error;
269
270 /* Get the device ID */
271 iprop = of_get_property(np, "cell-index", NULL);
272 if (!iprop) {
273 dev_err(&ofdev->dev, "cell-index property not found\n");
274 ret = -EINVAL;
275 goto error;
276 }
277 machine_data->ssi_id = *iprop;
278 ssi_info.id = *iprop;
279
280 /* Get the serial format and clock direction. */
281 sprop = of_get_property(np, "fsl,mode", NULL);
282 if (!sprop) {
283 dev_err(&ofdev->dev, "fsl,mode property not found\n");
284 ret = -EINVAL;
285 goto error;
286 }
287
288 if (strcasecmp(sprop, "i2s-slave") == 0) {
289 machine_data->dai_format = SND_SOC_DAIFMT_I2S;
290 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
291 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
292
293 /*
294 * In i2s-slave mode, the codec has its own clock source, so we
295 * need to get the frequency from the device tree and pass it to
296 * the codec driver.
297 */
298 iprop = of_get_property(codec_np, "clock-frequency", NULL);
299 if (!iprop || !*iprop) {
300 dev_err(&ofdev->dev, "codec bus-frequency property "
301 "is missing or invalid\n");
302 ret = -EINVAL;
303 goto error;
304 }
305 machine_data->clk_frequency = *iprop;
306 } else if (strcasecmp(sprop, "i2s-master") == 0) {
307 machine_data->dai_format = SND_SOC_DAIFMT_I2S;
308 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
309 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
310 } else if (strcasecmp(sprop, "lj-slave") == 0) {
311 machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J;
312 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
313 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
314 } else if (strcasecmp(sprop, "lj-master") == 0) {
315 machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J;
316 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
317 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
318 } else if (strcasecmp(sprop, "rj-master") == 0) {
319 machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J;
320 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
321 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
322 } else if (strcasecmp(sprop, "rj-master") == 0) {
323 machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J;
324 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
325 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
326 } else if (strcasecmp(sprop, "ac97-slave") == 0) {
327 machine_data->dai_format = SND_SOC_DAIFMT_AC97;
328 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
329 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
330 } else if (strcasecmp(sprop, "ac97-master") == 0) {
331 machine_data->dai_format = SND_SOC_DAIFMT_AC97;
332 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
333 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
334 } else {
335 dev_err(&ofdev->dev,
336 "unrecognized fsl,mode property \"%s\"\n", sprop);
337 ret = -EINVAL;
338 goto error;
339 }
340
341 if (!machine_data->clk_frequency) {
342 dev_err(&ofdev->dev, "unknown clock frequency\n");
343 ret = -EINVAL;
344 goto error;
345 }
346
347 /* Read the SSI information from the device tree */
348 ret = of_address_to_resource(np, 0, &res);
349 if (ret) {
350 dev_err(&ofdev->dev, "could not obtain SSI address\n");
351 goto error;
352 }
353 if (!res.start) {
354 dev_err(&ofdev->dev, "invalid SSI address\n");
355 goto error;
356 }
357 ssi_info.ssi_phys = res.start;
358
359 machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi));
360 if (!machine_data->ssi) {
361 dev_err(&ofdev->dev, "could not map SSI address %x\n",
362 ssi_info.ssi_phys);
363 ret = -EINVAL;
364 goto error;
365 }
366 ssi_info.ssi = machine_data->ssi;
367
368
369 /* Get the IRQ of the SSI */
370 machine_data->ssi_irq = irq_of_parse_and_map(np, 0);
371 if (!machine_data->ssi_irq) {
372 dev_err(&ofdev->dev, "could not get SSI IRQ\n");
373 ret = -EINVAL;
374 goto error;
375 }
376 ssi_info.irq = machine_data->ssi_irq;
377
378
379 /* Map the global utilities registers. */
380 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
381 if (!guts_np) {
382 dev_err(&ofdev->dev, "could not obtain address of GUTS\n");
383 ret = -EINVAL;
384 goto error;
385 }
386 machine_data->guts = of_iomap(guts_np, 0);
387 of_node_put(guts_np);
388 if (!machine_data->guts) {
389 dev_err(&ofdev->dev, "could not map GUTS\n");
390 ret = -EINVAL;
391 goto error;
392 }
393
394 /* Find the DMA channels to use. For now, we always use the first DMA
395 controller. */
396 for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") {
397 iprop = of_get_property(dma_np, "cell-index", NULL);
398 if (iprop && (*iprop == 0)) {
399 of_node_put(dma_np);
400 break;
401 }
402 }
403 if (!dma_np) {
404 dev_err(&ofdev->dev, "could not find DMA node\n");
405 ret = -EINVAL;
406 goto error;
407 }
408 machine_data->dma_id = *iprop;
409
410 /*
411 * Find the DMA channels to use. For now, we always use DMA channel 0
412 * for playback, and DMA channel 1 for capture.
413 */
414 while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) {
415 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
416 /* Is it DMA channel 0? */
417 if (iprop && (*iprop == 0)) {
418 /* dma_channel[0] and dma_irq[0] are for playback */
419 dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0);
420 dma_info.dma_irq[0] =
421 irq_of_parse_and_map(dma_channel_np, 0);
422 machine_data->dma_channel_id[0] = *iprop;
423 continue;
424 }
425 if (iprop && (*iprop == 1)) {
426 /* dma_channel[1] and dma_irq[1] are for capture */
427 dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0);
428 dma_info.dma_irq[1] =
429 irq_of_parse_and_map(dma_channel_np, 0);
430 machine_data->dma_channel_id[1] = *iprop;
431 continue;
432 }
433 }
434 if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] ||
435 !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) {
436 dev_err(&ofdev->dev, "could not find DMA channels\n");
437 ret = -EINVAL;
438 goto error;
439 }
440
441 dma_info.ssi_stx_phys = ssi_info.ssi_phys +
442 offsetof(struct ccsr_ssi, stx0);
443 dma_info.ssi_srx_phys = ssi_info.ssi_phys +
444 offsetof(struct ccsr_ssi, srx0);
445
446 /* We have the DMA information, so tell the DMA driver what it is */
447 if (!fsl_dma_configure(&dma_info)) {
448 dev_err(&ofdev->dev, "could not instantiate DMA device\n");
449 ret = -EBUSY;
450 goto error;
451 }
452
453 /*
454 * Initialize our DAI data structure. We should probably get this
455 * information from the device tree.
456 */
457 machine_data->dai.name = "CS4270";
458 machine_data->dai.stream_name = "CS4270";
459
460 machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info);
461 machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */
462 machine_data->dai.ops = &mpc8610_hpcd_ops;
463
464 mpc8610_hpcd_machine.dai_link = &machine_data->dai;
465
466 /* Allocate a new audio platform device structure */
467 sound_device = platform_device_alloc("soc-audio", -1);
468 if (!sound_device) {
469 dev_err(&ofdev->dev, "platform device allocation failed\n");
470 ret = -ENOMEM;
471 goto error;
472 }
473
474 machine_data->sound_devdata.machine = &mpc8610_hpcd_machine;
475 machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270;
476 machine_data->sound_devdata.platform = &fsl_soc_platform;
477
478 sound_device->dev.platform_data = machine_data;
479
480
481 /* Set the platform device and ASoC device to point to each other */
482 platform_set_drvdata(sound_device, &machine_data->sound_devdata);
483
484 machine_data->sound_devdata.dev = &sound_device->dev;
485
486
487 /* Tell ASoC to probe us. This will call mpc8610_hpcd_machine.probe(),
488 if it exists. */
489 ret = platform_device_add(sound_device);
490
491 if (ret) {
492 dev_err(&ofdev->dev, "platform device add failed\n");
493 goto error;
494 }
495
496 dev_set_drvdata(&ofdev->dev, sound_device);
497
498 return 0;
499
500error:
501 of_node_put(codec_np);
502 of_node_put(guts_np);
503 of_node_put(dma_np);
504 of_node_put(dma_channel_np);
505
506 if (sound_device)
507 platform_device_unregister(sound_device);
508
509 if (machine_data->dai.cpu_dai)
510 fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
511
512 if (ssi_info.ssi)
513 iounmap(ssi_info.ssi);
514
515 if (ssi_info.irq)
516 irq_dispose_mapping(ssi_info.irq);
517
518 if (dma_info.dma_channel[0])
519 iounmap(dma_info.dma_channel[0]);
520
521 if (dma_info.dma_channel[1])
522 iounmap(dma_info.dma_channel[1]);
523
524 if (dma_info.dma_irq[0])
525 irq_dispose_mapping(dma_info.dma_irq[0]);
526
527 if (dma_info.dma_irq[1])
528 irq_dispose_mapping(dma_info.dma_irq[1]);
529
530 if (machine_data->guts)
531 iounmap(machine_data->guts);
532
533 kfree(machine_data);
534
535 return ret;
536}
537
538/**
539 * mpc8610_hpcd_remove: remove the OF device
540 *
541 * This function is called when the OF device is removed.
542 */
543static int mpc8610_hpcd_remove(struct of_device *ofdev)
544{
545 struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev);
546 struct mpc8610_hpcd_data *machine_data =
547 sound_device->dev.platform_data;
548
549 platform_device_unregister(sound_device);
550
551 if (machine_data->dai.cpu_dai)
552 fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
553
554 if (machine_data->ssi)
555 iounmap(machine_data->ssi);
556
557 if (machine_data->dma[0])
558 iounmap(machine_data->dma[0]);
559
560 if (machine_data->dma[1])
561 iounmap(machine_data->dma[1]);
562
563 if (machine_data->dma_irq[0])
564 irq_dispose_mapping(machine_data->dma_irq[0]);
565
566 if (machine_data->dma_irq[1])
567 irq_dispose_mapping(machine_data->dma_irq[1]);
568
569 if (machine_data->guts)
570 iounmap(machine_data->guts);
571
572 kfree(machine_data);
573 sound_device->dev.platform_data = NULL;
574
575 dev_set_drvdata(&ofdev->dev, NULL);
576
577 return 0;
578}
579
580static struct of_device_id mpc8610_hpcd_match[] = {
581 {
582 .compatible = "fsl,mpc8610-ssi",
583 },
584 {}
585};
586MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match);
587
588static struct of_platform_driver mpc8610_hpcd_of_driver = {
589 .owner = THIS_MODULE,
590 .name = "mpc8610_hpcd",
591 .match_table = mpc8610_hpcd_match,
592 .probe = mpc8610_hpcd_probe,
593 .remove = mpc8610_hpcd_remove,
594};
595
596/**
597 * mpc8610_hpcd_init: fabric driver initialization.
598 *
599 * This function is called when this module is loaded.
600 */
601static int __init mpc8610_hpcd_init(void)
602{
603 int ret;
604
605 printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n");
606
607 ret = of_register_platform_driver(&mpc8610_hpcd_of_driver);
608
609 if (ret)
610 printk(KERN_ERR
611 "mpc8610-hpcd: failed to register platform driver\n");
612
613 return ret;
614}
615
616/**
617 * mpc8610_hpcd_exit: fabric driver exit
618 *
619 * This function is called when this driver is unloaded.
620 */
621static void __exit mpc8610_hpcd_exit(void)
622{
623 of_unregister_platform_driver(&mpc8610_hpcd_of_driver);
624}
625
626module_init(mpc8610_hpcd_init);
627module_exit(mpc8610_hpcd_exit);
628
629MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
630MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver");
631MODULE_LICENSE("GPL");