ASoC: fsl/mxs: Remove unnecessarily gendered language
[deliverable/linux.git] / sound / soc / fsl / fsl_ssi.c
CommitLineData
17467f23
TT
1/*
2 * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
f0fba2ad
LG
6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
de623ece
MP
11 *
12 *
13 * Some notes why imx-pcm-fiq is used instead of DMA on some boards:
14 *
15 * The i.MX SSI core has some nasty limitations in AC97 mode. While most
16 * sane processor vendors have a FIFO per AC97 slot, the i.MX has only
17 * one FIFO which combines all valid receive slots. We cannot even select
18 * which slots we want to receive. The WM9712 with which this driver
19 * was developed with always sends GPIO status data in slot 12 which
20 * we receive in our (PCM-) data stream. The only chance we have is to
21 * manually skip this data in the FIQ handler. With sampling rates different
22 * from 48000Hz not every frame has valid receive data, so the ratio
23 * between pcm data and GPIO status data changes. Our FIQ handler is not
24 * able to handle this, hence this driver only works with 48000Hz sampling
25 * rate.
26 * Reading and writing AC97 registers is another challenge. The core
27 * provides us status bits when the read register is updated with *another*
28 * value. When we read the same register two times (and the register still
29 * contains the same value) these status bits are not set. We work
30 * around this by not polling these bits but only wait a fixed delay.
17467f23
TT
31 */
32
33#include <linux/init.h>
dfa1a107 34#include <linux/io.h>
17467f23
TT
35#include <linux/module.h>
36#include <linux/interrupt.h>
95cd98f9 37#include <linux/clk.h>
17467f23
TT
38#include <linux/device.h>
39#include <linux/delay.h>
5a0e3ad6 40#include <linux/slab.h>
dfa1a107
SG
41#include <linux/of_address.h>
42#include <linux/of_irq.h>
f0fba2ad 43#include <linux/of_platform.h>
17467f23 44
17467f23
TT
45#include <sound/core.h>
46#include <sound/pcm.h>
47#include <sound/pcm_params.h>
48#include <sound/initval.h>
49#include <sound/soc.h>
a8909c9b 50#include <sound/dmaengine_pcm.h>
17467f23 51
17467f23 52#include "fsl_ssi.h"
09ce1111 53#include "imx-pcm.h"
17467f23 54
dfa1a107
SG
55#ifdef PPC
56#define read_ssi(addr) in_be32(addr)
57#define write_ssi(val, addr) out_be32(addr, val)
58#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
0a9eaa39 59#else
dfa1a107
SG
60#define read_ssi(addr) readl(addr)
61#define write_ssi(val, addr) writel(val, addr)
62/*
63 * FIXME: Proper locking should be added at write_ssi_mask caller level
64 * to ensure this register read/modify/write sequence is race free.
65 */
66static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
67{
68 u32 val = readl(addr);
69 val = (val & ~clear) | set;
70 writel(val, addr);
71}
72#endif
73
17467f23
TT
74/**
75 * FSLSSI_I2S_RATES: sample rates supported by the I2S
76 *
77 * This driver currently only supports the SSI running in I2S slave mode,
78 * which means the codec determines the sample rate. Therefore, we tell
79 * ALSA that we support all rates and let the codec driver decide what rates
80 * are really supported.
81 */
82#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
83 SNDRV_PCM_RATE_CONTINUOUS)
84
85/**
86 * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
87 *
88 * This driver currently only supports the SSI running in I2S slave mode.
89 *
90 * The SSI has a limitation in that the samples must be in the same byte
91 * order as the host CPU. This is because when multiple bytes are written
92 * to the STX register, the bytes and bits must be written in the same
93 * order. The STX is a shift register, so all the bits need to be aligned
94 * (bit-endianness must match byte-endianness). Processors typically write
95 * the bits within a byte in the same order that the bytes of a word are
96 * written in. So if the host CPU is big-endian, then only big-endian
97 * samples will be written to STX properly.
98 */
99#ifdef __BIG_ENDIAN
100#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
101 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
102 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
103#else
104#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
105 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
106 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
107#endif
108
d5a908b2
TT
109/* SIER bitflag of interrupts to enable */
110#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
111 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
112 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
113 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
114 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
115
17467f23
TT
116/**
117 * fsl_ssi_private: per-SSI private data
118 *
17467f23
TT
119 * @ssi: pointer to the SSI's registers
120 * @ssi_phys: physical address of the SSI registers
121 * @irq: IRQ of this SSI
17467f23
TT
122 * @playback: the number of playback streams opened
123 * @capture: the number of capture streams opened
124 * @cpu_dai: the CPU DAI for this device
125 * @dev_attr: the sysfs device attribute structure
126 * @stats: SSI statistics
f0fba2ad 127 * @name: name for this device
17467f23
TT
128 */
129struct fsl_ssi_private {
17467f23
TT
130 struct ccsr_ssi __iomem *ssi;
131 dma_addr_t ssi_phys;
132 unsigned int irq;
8e9d8690 133 unsigned int fifo_depth;
f0fba2ad 134 struct snd_soc_dai_driver cpu_dai_drv;
17467f23 135 struct device_attribute dev_attr;
f0fba2ad 136 struct platform_device *pdev;
17467f23 137
09ce1111
SG
138 bool new_binding;
139 bool ssi_on_imx;
cd7f0295 140 bool imx_ac97;
de623ece 141 bool use_dma;
2924a998 142 u8 i2s_mode;
95cd98f9 143 struct clk *clk;
a8909c9b
LPC
144 struct snd_dmaengine_dai_dma_data dma_params_tx;
145 struct snd_dmaengine_dai_dma_data dma_params_rx;
146 struct imx_dma_data filter_data_tx;
147 struct imx_dma_data filter_data_rx;
de623ece 148 struct imx_pcm_fiq_params fiq_params;
09ce1111 149
17467f23
TT
150 struct {
151 unsigned int rfrc;
152 unsigned int tfrc;
153 unsigned int cmdau;
154 unsigned int cmddu;
155 unsigned int rxt;
156 unsigned int rdr1;
157 unsigned int rdr0;
158 unsigned int tde1;
159 unsigned int tde0;
160 unsigned int roe1;
161 unsigned int roe0;
162 unsigned int tue1;
163 unsigned int tue0;
164 unsigned int tfs;
165 unsigned int rfs;
166 unsigned int tls;
167 unsigned int rls;
168 unsigned int rff1;
169 unsigned int rff0;
170 unsigned int tfe1;
171 unsigned int tfe0;
172 } stats;
f0fba2ad
LG
173
174 char name[1];
17467f23
TT
175};
176
177/**
178 * fsl_ssi_isr: SSI interrupt handler
179 *
180 * Although it's possible to use the interrupt handler to send and receive
181 * data to/from the SSI, we use the DMA instead. Programming is more
182 * complicated, but the performance is much better.
183 *
184 * This interrupt handler is used only to gather statistics.
185 *
186 * @irq: IRQ of the SSI device
187 * @dev_id: pointer to the ssi_private structure for this SSI device
188 */
189static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
190{
191 struct fsl_ssi_private *ssi_private = dev_id;
192 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
193 irqreturn_t ret = IRQ_NONE;
194 __be32 sisr;
195 __be32 sisr2 = 0;
196
197 /* We got an interrupt, so read the status register to see what we
198 were interrupted for. We mask it with the Interrupt Enable register
199 so that we only check for events that we're interested in.
200 */
dfa1a107 201 sisr = read_ssi(&ssi->sisr) & SIER_FLAGS;
17467f23
TT
202
203 if (sisr & CCSR_SSI_SISR_RFRC) {
204 ssi_private->stats.rfrc++;
205 sisr2 |= CCSR_SSI_SISR_RFRC;
206 ret = IRQ_HANDLED;
207 }
208
209 if (sisr & CCSR_SSI_SISR_TFRC) {
210 ssi_private->stats.tfrc++;
211 sisr2 |= CCSR_SSI_SISR_TFRC;
212 ret = IRQ_HANDLED;
213 }
214
215 if (sisr & CCSR_SSI_SISR_CMDAU) {
216 ssi_private->stats.cmdau++;
217 ret = IRQ_HANDLED;
218 }
219
220 if (sisr & CCSR_SSI_SISR_CMDDU) {
221 ssi_private->stats.cmddu++;
222 ret = IRQ_HANDLED;
223 }
224
225 if (sisr & CCSR_SSI_SISR_RXT) {
226 ssi_private->stats.rxt++;
227 ret = IRQ_HANDLED;
228 }
229
230 if (sisr & CCSR_SSI_SISR_RDR1) {
231 ssi_private->stats.rdr1++;
232 ret = IRQ_HANDLED;
233 }
234
235 if (sisr & CCSR_SSI_SISR_RDR0) {
236 ssi_private->stats.rdr0++;
237 ret = IRQ_HANDLED;
238 }
239
240 if (sisr & CCSR_SSI_SISR_TDE1) {
241 ssi_private->stats.tde1++;
242 ret = IRQ_HANDLED;
243 }
244
245 if (sisr & CCSR_SSI_SISR_TDE0) {
246 ssi_private->stats.tde0++;
247 ret = IRQ_HANDLED;
248 }
249
250 if (sisr & CCSR_SSI_SISR_ROE1) {
251 ssi_private->stats.roe1++;
252 sisr2 |= CCSR_SSI_SISR_ROE1;
253 ret = IRQ_HANDLED;
254 }
255
256 if (sisr & CCSR_SSI_SISR_ROE0) {
257 ssi_private->stats.roe0++;
258 sisr2 |= CCSR_SSI_SISR_ROE0;
259 ret = IRQ_HANDLED;
260 }
261
262 if (sisr & CCSR_SSI_SISR_TUE1) {
263 ssi_private->stats.tue1++;
264 sisr2 |= CCSR_SSI_SISR_TUE1;
265 ret = IRQ_HANDLED;
266 }
267
268 if (sisr & CCSR_SSI_SISR_TUE0) {
269 ssi_private->stats.tue0++;
270 sisr2 |= CCSR_SSI_SISR_TUE0;
271 ret = IRQ_HANDLED;
272 }
273
274 if (sisr & CCSR_SSI_SISR_TFS) {
275 ssi_private->stats.tfs++;
276 ret = IRQ_HANDLED;
277 }
278
279 if (sisr & CCSR_SSI_SISR_RFS) {
280 ssi_private->stats.rfs++;
281 ret = IRQ_HANDLED;
282 }
283
284 if (sisr & CCSR_SSI_SISR_TLS) {
285 ssi_private->stats.tls++;
286 ret = IRQ_HANDLED;
287 }
288
289 if (sisr & CCSR_SSI_SISR_RLS) {
290 ssi_private->stats.rls++;
291 ret = IRQ_HANDLED;
292 }
293
294 if (sisr & CCSR_SSI_SISR_RFF1) {
295 ssi_private->stats.rff1++;
296 ret = IRQ_HANDLED;
297 }
298
299 if (sisr & CCSR_SSI_SISR_RFF0) {
300 ssi_private->stats.rff0++;
301 ret = IRQ_HANDLED;
302 }
303
304 if (sisr & CCSR_SSI_SISR_TFE1) {
305 ssi_private->stats.tfe1++;
306 ret = IRQ_HANDLED;
307 }
308
309 if (sisr & CCSR_SSI_SISR_TFE0) {
310 ssi_private->stats.tfe0++;
311 ret = IRQ_HANDLED;
312 }
313
314 /* Clear the bits that we set */
315 if (sisr2)
dfa1a107 316 write_ssi(sisr2, &ssi->sisr);
17467f23
TT
317
318 return ret;
319}
320
d8764646
MP
321static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
322{
323 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
324
325 /*
326 * Setup the clock control register
327 */
328 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
329 &ssi->stccr);
330 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
331 &ssi->srccr);
332
333 /*
334 * Enable AC97 mode and startup the SSI
335 */
336 write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
337 &ssi->sacnt);
338 write_ssi(0xff, &ssi->saccdis);
339 write_ssi(0x300, &ssi->saccen);
340
341 /*
342 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
343 * codec before a stream is started.
344 */
345 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
346 CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
347
348 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
349}
350
cd7f0295
MP
351static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
352{
353 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
cd7f0295
MP
354 u8 wm;
355 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
356
357 if (ssi_private->imx_ac97)
2924a998 358 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
cd7f0295 359 else
2924a998 360 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
cd7f0295
MP
361
362 /*
363 * Section 16.5 of the MPC8610 reference manual says that the SSI needs
364 * to be disabled before updating the registers we set here.
365 */
366 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
367
368 /*
369 * Program the SSI into I2S Slave Non-Network Synchronous mode. Also
370 * enable the transmit and receive FIFO.
371 *
372 * FIXME: Little-endian samples require a different shift dir
373 */
374 write_ssi_mask(&ssi->scr,
375 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
376 CCSR_SSI_SCR_TFR_CLK_DIS |
2924a998 377 ssi_private->i2s_mode |
cd7f0295
MP
378 (synchronous ? CCSR_SSI_SCR_SYN : 0));
379
380 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
381 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
382 CCSR_SSI_STCR_TSCKP, &ssi->stcr);
383
384 write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
385 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
386 CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
387 /*
388 * The DC and PM bits are only used if the SSI is the clock master.
389 */
390
391 /*
392 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
393 * use FIFO 1. We program the transmit water to signal a DMA transfer
394 * if there are only two (or fewer) elements left in the FIFO. Two
395 * elements equals one frame (left channel, right channel). This value,
396 * however, depends on the depth of the transmit buffer.
397 *
398 * We set the watermark on the same level as the DMA burstsize. For
399 * fiq it is probably better to use the biggest possible watermark
400 * size.
401 */
402 if (ssi_private->use_dma)
403 wm = ssi_private->fifo_depth - 2;
404 else
405 wm = ssi_private->fifo_depth;
406
407 write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
408 CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
409 &ssi->sfcsr);
410
cd7f0295
MP
411 /*
412 * For ac97 interrupts are enabled with the startup of the substream
413 * because it is also running without an active substream. Normally SSI
414 * is only enabled when there is a substream.
415 */
d8764646
MP
416 if (ssi_private->imx_ac97)
417 fsl_ssi_setup_ac97(ssi_private);
cd7f0295
MP
418
419 return 0;
420}
421
422
17467f23
TT
423/**
424 * fsl_ssi_startup: create a new substream
425 *
426 * This is the first function called when a stream is opened.
427 *
428 * If this is the first stream open, then grab the IRQ and program most of
429 * the SSI registers.
430 */
dee89c4d
MB
431static int fsl_ssi_startup(struct snd_pcm_substream *substream,
432 struct snd_soc_dai *dai)
17467f23
TT
433{
434 struct snd_soc_pcm_runtime *rtd = substream->private_data;
5e538eca
TT
435 struct fsl_ssi_private *ssi_private =
436 snd_soc_dai_get_drvdata(rtd->cpu_dai);
17467f23 437
07a9483a
NC
438 /* First, we only do fsl_ssi_setup() when SSI is going to be active.
439 * Second, fsl_ssi_setup was already called by ac97_init earlier if
440 * the driver is in ac97 mode.
17467f23 441 */
07a9483a
NC
442 if (!dai->active && !ssi_private->imx_ac97)
443 fsl_ssi_setup(ssi_private);
be41e941 444
17467f23
TT
445 return 0;
446}
447
448/**
85ef2375 449 * fsl_ssi_hw_params - program the sample size
17467f23
TT
450 *
451 * Most of the SSI registers have been programmed in the startup function,
452 * but the word length must be programmed here. Unfortunately, programming
453 * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can
454 * cause a problem with supporting simultaneous playback and capture. If
455 * the SSI is already playing a stream, then that stream may be temporarily
456 * stopped when you start capture.
457 *
458 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
459 * clock master.
460 */
85ef2375
TT
461static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
462 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
17467f23 463{
f0fba2ad 464 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
5e538eca 465 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
2924a998 466 unsigned int channels = params_channels(hw_params);
5e538eca
TT
467 unsigned int sample_size =
468 snd_pcm_format_width(params_format(hw_params));
469 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
dfa1a107 470 int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
17467f23 471
5e538eca
TT
472 /*
473 * If we're in synchronous mode, and the SSI is already enabled,
474 * then STCCR is already set properly.
475 */
476 if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
477 return 0;
17467f23 478
5e538eca
TT
479 /*
480 * FIXME: The documentation says that SxCCR[WL] should not be
481 * modified while the SSI is enabled. The only time this can
482 * happen is if we're trying to do simultaneous playback and
483 * capture in asynchronous mode. Unfortunately, I have been enable
484 * to get that to work at all on the P1022DS. Therefore, we don't
485 * bother to disable/enable the SSI when setting SxCCR[WL], because
486 * the SSI will stop anyway. Maybe one day, this will get fixed.
487 */
17467f23 488
5e538eca
TT
489 /* In synchronous mode, the SSI uses STCCR for capture */
490 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
491 ssi_private->cpu_dai_drv.symmetric_rates)
dfa1a107 492 write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
5e538eca 493 else
dfa1a107 494 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
17467f23 495
2924a998
NC
496 if (!ssi_private->imx_ac97)
497 write_ssi_mask(&ssi->scr,
498 CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
499 channels == 1 ? 0 : ssi_private->i2s_mode);
500
17467f23
TT
501 return 0;
502}
503
504/**
505 * fsl_ssi_trigger: start and stop the DMA transfer.
506 *
507 * This function is called by ALSA to start, stop, pause, and resume the DMA
508 * transfer of data.
509 *
510 * The DMA channel is in external master start and pause mode, which
511 * means the SSI completely controls the flow of data.
512 */
dee89c4d
MB
513static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
514 struct snd_soc_dai *dai)
17467f23
TT
515{
516 struct snd_soc_pcm_runtime *rtd = substream->private_data;
f0fba2ad 517 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
17467f23 518 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
9b443e3d
MG
519 unsigned int sier_bits;
520
521 /*
522 * Enable only the interrupts and DMA requests
523 * that are needed for the channel. As the fiq
524 * is polling for this bits, we have to ensure
525 * that this are aligned with the preallocated
526 * buffers
527 */
528
529 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
530 if (ssi_private->use_dma)
531 sier_bits = SIER_FLAGS;
532 else
533 sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN;
534 } else {
535 if (ssi_private->use_dma)
536 sier_bits = SIER_FLAGS;
537 else
538 sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN;
539 }
17467f23
TT
540
541 switch (cmd) {
542 case SNDRV_PCM_TRIGGER_START:
17467f23 543 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
a4d11fe5 544 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dfa1a107 545 write_ssi_mask(&ssi->scr, 0,
be41e941 546 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
a4d11fe5 547 else
dfa1a107 548 write_ssi_mask(&ssi->scr, 0,
be41e941 549 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
17467f23
TT
550 break;
551
552 case SNDRV_PCM_TRIGGER_STOP:
17467f23
TT
553 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
554 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dfa1a107 555 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
17467f23 556 else
dfa1a107 557 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
b2c119b0 558
cd7f0295
MP
559 if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) &
560 (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0)
b2c119b0 561 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
17467f23
TT
562 break;
563
564 default:
565 return -EINVAL;
566 }
567
9b443e3d
MG
568 write_ssi(sier_bits, &ssi->sier);
569
17467f23
TT
570 return 0;
571}
572
fc8ba7f9
LPC
573static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
574{
575 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
576
de623ece 577 if (ssi_private->ssi_on_imx && ssi_private->use_dma) {
fc8ba7f9
LPC
578 dai->playback_dma_data = &ssi_private->dma_params_tx;
579 dai->capture_dma_data = &ssi_private->dma_params_rx;
580 }
581
582 return 0;
583}
584
85e7652d 585static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
6335d055
EM
586 .startup = fsl_ssi_startup,
587 .hw_params = fsl_ssi_hw_params,
6335d055 588 .trigger = fsl_ssi_trigger,
6335d055
EM
589};
590
f0fba2ad
LG
591/* Template for the CPU dai driver structure */
592static struct snd_soc_dai_driver fsl_ssi_dai_template = {
fc8ba7f9 593 .probe = fsl_ssi_dai_probe,
17467f23 594 .playback = {
2924a998 595 .channels_min = 1,
17467f23
TT
596 .channels_max = 2,
597 .rates = FSLSSI_I2S_RATES,
598 .formats = FSLSSI_I2S_FORMATS,
599 },
600 .capture = {
2924a998 601 .channels_min = 1,
17467f23
TT
602 .channels_max = 2,
603 .rates = FSLSSI_I2S_RATES,
604 .formats = FSLSSI_I2S_FORMATS,
605 },
6335d055 606 .ops = &fsl_ssi_dai_ops,
17467f23
TT
607};
608
3580aa10
KM
609static const struct snd_soc_component_driver fsl_ssi_component = {
610 .name = "fsl-ssi",
611};
612
cd7f0295
MP
613/**
614 * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit.
615 *
616 * This function is called by ALSA to start, stop, pause, and resume the
617 * transfer of data.
618 */
619static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
620 struct snd_soc_dai *dai)
621{
622 struct snd_soc_pcm_runtime *rtd = substream->private_data;
623 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(
624 rtd->cpu_dai);
625 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
626
627 switch (cmd) {
628 case SNDRV_PCM_TRIGGER_START:
629 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
630 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
631 write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE |
632 CCSR_SSI_SIER_TFE0_EN);
633 else
634 write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE |
635 CCSR_SSI_SIER_RFF0_EN);
636 break;
637
638 case SNDRV_PCM_TRIGGER_STOP:
639 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
640 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
641 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE |
642 CCSR_SSI_SIER_TFE0_EN, 0);
643 else
644 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE |
645 CCSR_SSI_SIER_RFF0_EN, 0);
646 break;
647
648 default:
649 return -EINVAL;
650 }
651
652 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
653 write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
654 else
655 write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
656
657 return 0;
658}
659
660static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
661 .startup = fsl_ssi_startup,
cd7f0295
MP
662 .trigger = fsl_ssi_ac97_trigger,
663};
664
665static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
666 .ac97_control = 1,
667 .playback = {
668 .stream_name = "AC97 Playback",
669 .channels_min = 2,
670 .channels_max = 2,
671 .rates = SNDRV_PCM_RATE_8000_48000,
672 .formats = SNDRV_PCM_FMTBIT_S16_LE,
673 },
674 .capture = {
675 .stream_name = "AC97 Capture",
676 .channels_min = 2,
677 .channels_max = 2,
678 .rates = SNDRV_PCM_RATE_48000,
679 .formats = SNDRV_PCM_FMTBIT_S16_LE,
680 },
681 .ops = &fsl_ssi_ac97_dai_ops,
682};
683
684
685static struct fsl_ssi_private *fsl_ac97_data;
686
687static void fsl_ssi_ac97_init(void)
688{
689 fsl_ssi_setup(fsl_ac97_data);
690}
691
a851a2bb 692static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
cd7f0295
MP
693 unsigned short val)
694{
695 struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
696 unsigned int lreg;
697 unsigned int lval;
698
699 if (reg > 0x7f)
700 return;
701
702
703 lreg = reg << 12;
704 write_ssi(lreg, &ssi->sacadd);
705
706 lval = val << 4;
707 write_ssi(lval , &ssi->sacdat);
708
709 write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
710 CCSR_SSI_SACNT_WR);
711 udelay(100);
712}
713
a851a2bb 714static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
cd7f0295
MP
715 unsigned short reg)
716{
717 struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
718
719 unsigned short val = -1;
720 unsigned int lreg;
721
722 lreg = (reg & 0x7f) << 12;
723 write_ssi(lreg, &ssi->sacadd);
724 write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
725 CCSR_SSI_SACNT_RD);
726
727 udelay(100);
728
729 val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff;
730
731 return val;
732}
733
734static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
735 .read = fsl_ssi_ac97_read,
736 .write = fsl_ssi_ac97_write,
737};
738
d5a908b2
TT
739/* Show the statistics of a flag only if its interrupt is enabled. The
740 * compiler will optimze this code to a no-op if the interrupt is not
741 * enabled.
742 */
743#define SIER_SHOW(flag, name) \
744 do { \
745 if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \
746 length += sprintf(buf + length, #name "=%u\n", \
747 ssi_private->stats.name); \
748 } while (0)
749
750
17467f23
TT
751/**
752 * fsl_sysfs_ssi_show: display SSI statistics
753 *
d5a908b2
TT
754 * Display the statistics for the current SSI device. To avoid confusion,
755 * we only show those counts that are enabled.
17467f23
TT
756 */
757static ssize_t fsl_sysfs_ssi_show(struct device *dev,
758 struct device_attribute *attr, char *buf)
759{
760 struct fsl_ssi_private *ssi_private =
d5a908b2
TT
761 container_of(attr, struct fsl_ssi_private, dev_attr);
762 ssize_t length = 0;
763
764 SIER_SHOW(RFRC_EN, rfrc);
765 SIER_SHOW(TFRC_EN, tfrc);
766 SIER_SHOW(CMDAU_EN, cmdau);
767 SIER_SHOW(CMDDU_EN, cmddu);
768 SIER_SHOW(RXT_EN, rxt);
769 SIER_SHOW(RDR1_EN, rdr1);
770 SIER_SHOW(RDR0_EN, rdr0);
771 SIER_SHOW(TDE1_EN, tde1);
772 SIER_SHOW(TDE0_EN, tde0);
773 SIER_SHOW(ROE1_EN, roe1);
774 SIER_SHOW(ROE0_EN, roe0);
775 SIER_SHOW(TUE1_EN, tue1);
776 SIER_SHOW(TUE0_EN, tue0);
777 SIER_SHOW(TFS_EN, tfs);
778 SIER_SHOW(RFS_EN, rfs);
779 SIER_SHOW(TLS_EN, tls);
780 SIER_SHOW(RLS_EN, rls);
781 SIER_SHOW(RFF1_EN, rff1);
782 SIER_SHOW(RFF0_EN, rff0);
783 SIER_SHOW(TFE1_EN, tfe1);
784 SIER_SHOW(TFE0_EN, tfe0);
17467f23
TT
785
786 return length;
787}
788
789/**
f0fba2ad 790 * Make every character in a string lower-case
17467f23 791 */
f0fba2ad
LG
792static void make_lowercase(char *s)
793{
794 char *p = s;
795 char c;
796
797 while ((c = *p)) {
798 if ((c >= 'A') && (c <= 'Z'))
799 *p = c + ('a' - 'A');
800 p++;
801 }
802}
803
a0a3d518 804static int fsl_ssi_probe(struct platform_device *pdev)
17467f23 805{
17467f23
TT
806 struct fsl_ssi_private *ssi_private;
807 int ret = 0;
87a0632b 808 struct device_attribute *dev_attr = NULL;
38fec727 809 struct device_node *np = pdev->dev.of_node;
f0fba2ad 810 const char *p, *sprop;
8e9d8690 811 const uint32_t *iprop;
f0fba2ad
LG
812 struct resource res;
813 char name[64];
312bb4f6 814 bool shared;
cd7f0295 815 bool ac97 = false;
17467f23 816
ff71334a
TT
817 /* SSIs that are not connected on the board should have a
818 * status = "disabled"
819 * property in their device tree nodes.
f0fba2ad 820 */
ff71334a 821 if (!of_device_is_available(np))
f0fba2ad
LG
822 return -ENODEV;
823
824 /* We only support the SSI in "I2S Slave" mode */
825 sprop = of_get_property(np, "fsl,mode", NULL);
cd7f0295
MP
826 if (!sprop) {
827 dev_err(&pdev->dev, "fsl,mode property is necessary\n");
828 return -EINVAL;
829 }
830 if (!strcmp(sprop, "ac97-slave")) {
831 ac97 = true;
832 } else if (strcmp(sprop, "i2s-slave")) {
38fec727 833 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
f0fba2ad
LG
834 return -ENODEV;
835 }
836
837 /* The DAI name is the last part of the full name of the node. */
838 p = strrchr(np->full_name, '/') + 1;
b0a4747a 839 ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private) + strlen(p),
f0fba2ad 840 GFP_KERNEL);
17467f23 841 if (!ssi_private) {
38fec727 842 dev_err(&pdev->dev, "could not allocate DAI object\n");
f0fba2ad 843 return -ENOMEM;
17467f23 844 }
17467f23 845
f0fba2ad 846 strcpy(ssi_private->name, p);
17467f23 847
de623ece
MP
848 ssi_private->use_dma = !of_property_read_bool(np,
849 "fsl,fiq-stream-filter");
850
cd7f0295
MP
851 if (ac97) {
852 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai,
853 sizeof(fsl_ssi_ac97_dai));
854
855 fsl_ac97_data = ssi_private;
856 ssi_private->imx_ac97 = true;
857
858 snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev);
859 } else {
860 /* Initialize this copy of the CPU DAI driver structure */
861 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
862 sizeof(fsl_ssi_dai_template));
863 }
f0fba2ad
LG
864 ssi_private->cpu_dai_drv.name = ssi_private->name;
865
866 /* Get the addresses and IRQ */
867 ret = of_address_to_resource(np, 0, &res);
868 if (ret) {
38fec727 869 dev_err(&pdev->dev, "could not determine device resources\n");
b0a4747a 870 return ret;
f0fba2ad 871 }
147dfe90
TT
872 ssi_private->ssi = of_iomap(np, 0);
873 if (!ssi_private->ssi) {
874 dev_err(&pdev->dev, "could not map device resources\n");
b0a4747a 875 return -ENOMEM;
147dfe90 876 }
f0fba2ad 877 ssi_private->ssi_phys = res.start;
1fab6caf 878
f0fba2ad 879 ssi_private->irq = irq_of_parse_and_map(np, 0);
d60336e2 880 if (!ssi_private->irq) {
1fab6caf 881 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
b0a4747a 882 return -ENXIO;
1fab6caf
TT
883 }
884
f0fba2ad 885 /* Are the RX and the TX clocks locked? */
07a9483a 886 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
f0fba2ad 887 ssi_private->cpu_dai_drv.symmetric_rates = 1;
07a9483a
NC
888 ssi_private->cpu_dai_drv.symmetric_channels = 1;
889 ssi_private->cpu_dai_drv.symmetric_samplebits = 1;
890 }
17467f23 891
8e9d8690
TT
892 /* Determine the FIFO depth. */
893 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
894 if (iprop)
147dfe90 895 ssi_private->fifo_depth = be32_to_cpup(iprop);
8e9d8690
TT
896 else
897 /* Older 8610 DTs didn't have the fifo-depth property */
898 ssi_private->fifo_depth = 8;
899
09ce1111
SG
900 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
901 u32 dma_events[2];
902 ssi_private->ssi_on_imx = true;
95cd98f9 903
b0a4747a 904 ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
95cd98f9
SG
905 if (IS_ERR(ssi_private->clk)) {
906 ret = PTR_ERR(ssi_private->clk);
907 dev_err(&pdev->dev, "could not get clock: %d\n", ret);
b0a4747a 908 goto error_irqmap;
95cd98f9 909 }
ede32d3a
FE
910 ret = clk_prepare_enable(ssi_private->clk);
911 if (ret) {
912 dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n",
913 ret);
914 goto error_irqmap;
915 }
95cd98f9 916
09ce1111
SG
917 /*
918 * We have burstsize be "fifo_depth - 2" to match the SSI
919 * watermark setting in fsl_ssi_startup().
920 */
a8909c9b 921 ssi_private->dma_params_tx.maxburst =
09ce1111 922 ssi_private->fifo_depth - 2;
a8909c9b 923 ssi_private->dma_params_rx.maxburst =
09ce1111 924 ssi_private->fifo_depth - 2;
a8909c9b 925 ssi_private->dma_params_tx.addr =
09ce1111 926 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
a8909c9b 927 ssi_private->dma_params_rx.addr =
09ce1111 928 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
a8909c9b
LPC
929 ssi_private->dma_params_tx.filter_data =
930 &ssi_private->filter_data_tx;
931 ssi_private->dma_params_rx.filter_data =
932 &ssi_private->filter_data_rx;
3a5e517b
MP
933 if (!of_property_read_bool(pdev->dev.of_node, "dmas") &&
934 ssi_private->use_dma) {
935 /*
936 * FIXME: This is a temporary solution until all
937 * necessary dma drivers support the generic dma
938 * bindings.
939 */
940 ret = of_property_read_u32_array(pdev->dev.of_node,
09ce1111 941 "fsl,ssi-dma-events", dma_events, 2);
3a5e517b
MP
942 if (ret && ssi_private->use_dma) {
943 dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n");
944 goto error_clk;
945 }
09ce1111 946 }
312bb4f6
LPC
947
948 shared = of_device_is_compatible(of_get_parent(np),
949 "fsl,spba-bus");
950
a8909c9b 951 imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
32bd8cd2 952 dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
a8909c9b 953 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
32bd8cd2 954 dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
f0377086
MG
955 } else if (ssi_private->use_dma) {
956 /* The 'name' should not have any slashes in it. */
957 ret = devm_request_irq(&pdev->dev, ssi_private->irq,
958 fsl_ssi_isr, 0, ssi_private->name,
959 ssi_private);
960 if (ret < 0) {
961 dev_err(&pdev->dev, "could not claim irq %u\n",
962 ssi_private->irq);
963 goto error_irqmap;
964 }
09ce1111
SG
965 }
966
17467f23 967 /* Initialize the the device_attribute structure */
f0fba2ad 968 dev_attr = &ssi_private->dev_attr;
0f768a72 969 sysfs_attr_init(&dev_attr->attr);
f0fba2ad 970 dev_attr->attr.name = "statistics";
17467f23
TT
971 dev_attr->attr.mode = S_IRUGO;
972 dev_attr->show = fsl_sysfs_ssi_show;
973
38fec727 974 ret = device_create_file(&pdev->dev, dev_attr);
17467f23 975 if (ret) {
38fec727 976 dev_err(&pdev->dev, "could not create sysfs %s file\n",
17467f23 977 ssi_private->dev_attr.attr.name);
b0a4747a 978 goto error_clk;
17467f23
TT
979 }
980
f0fba2ad 981 /* Register with ASoC */
38fec727 982 dev_set_drvdata(&pdev->dev, ssi_private);
3f4b783c 983
3580aa10
KM
984 ret = snd_soc_register_component(&pdev->dev, &fsl_ssi_component,
985 &ssi_private->cpu_dai_drv, 1);
87a0632b 986 if (ret) {
38fec727 987 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
1fab6caf 988 goto error_dev;
f0fba2ad
LG
989 }
990
09ce1111 991 if (ssi_private->ssi_on_imx) {
de623ece
MP
992 if (!ssi_private->use_dma) {
993
994 /*
995 * Some boards use an incompatible codec. To get it
996 * working, we are using imx-fiq-pcm-audio, that
997 * can handle those codecs. DMA is not possible in this
998 * situation.
999 */
1000
1001 ssi_private->fiq_params.irq = ssi_private->irq;
1002 ssi_private->fiq_params.base = ssi_private->ssi;
1003 ssi_private->fiq_params.dma_params_rx =
1004 &ssi_private->dma_params_rx;
1005 ssi_private->fiq_params.dma_params_tx =
1006 &ssi_private->dma_params_tx;
1007
1008 ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
1009 if (ret)
1010 goto error_dev;
1011 } else {
1012 ret = imx_pcm_dma_init(pdev);
1013 if (ret)
1014 goto error_dev;
1015 }
09ce1111
SG
1016 }
1017
1018 /*
1019 * If codec-handle property is missing from SSI node, we assume
1020 * that the machine driver uses new binding which does not require
1021 * SSI driver to trigger machine driver's probe.
1022 */
1023 if (!of_get_property(np, "codec-handle", NULL)) {
1024 ssi_private->new_binding = true;
1025 goto done;
1026 }
1027
f0fba2ad 1028 /* Trigger the machine driver's probe function. The platform driver
2b81ec69 1029 * name of the machine driver is taken from /compatible property of the
f0fba2ad
LG
1030 * device tree. We also pass the address of the CPU DAI driver
1031 * structure.
1032 */
2b81ec69
SG
1033 sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
1034 /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
f0fba2ad
LG
1035 p = strrchr(sprop, ',');
1036 if (p)
1037 sprop = p + 1;
1038 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
1039 make_lowercase(name);
1040
1041 ssi_private->pdev =
38fec727 1042 platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
f0fba2ad
LG
1043 if (IS_ERR(ssi_private->pdev)) {
1044 ret = PTR_ERR(ssi_private->pdev);
38fec727 1045 dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
1fab6caf 1046 goto error_dai;
3f4b783c 1047 }
17467f23 1048
09ce1111 1049done:
cd7f0295
MP
1050 if (ssi_private->imx_ac97)
1051 fsl_ssi_ac97_init();
1052
f0fba2ad 1053 return 0;
87a0632b 1054
1fab6caf 1055error_dai:
3580aa10 1056 snd_soc_unregister_component(&pdev->dev);
1fab6caf
TT
1057
1058error_dev:
1fab6caf
TT
1059 device_remove_file(&pdev->dev, dev_attr);
1060
95cd98f9 1061error_clk:
b0a4747a 1062 if (ssi_private->ssi_on_imx)
95cd98f9 1063 clk_disable_unprepare(ssi_private->clk);
1fab6caf
TT
1064
1065error_irqmap:
87a0632b 1066 irq_dispose_mapping(ssi_private->irq);
1fab6caf 1067
87a0632b 1068 return ret;
17467f23 1069}
17467f23 1070
38fec727 1071static int fsl_ssi_remove(struct platform_device *pdev)
17467f23 1072{
38fec727 1073 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
17467f23 1074
09ce1111
SG
1075 if (!ssi_private->new_binding)
1076 platform_device_unregister(ssi_private->pdev);
3580aa10 1077 snd_soc_unregister_component(&pdev->dev);
38fec727 1078 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
0783e648
FE
1079 if (ssi_private->ssi_on_imx)
1080 clk_disable_unprepare(ssi_private->clk);
1fab6caf 1081 irq_dispose_mapping(ssi_private->irq);
f0fba2ad
LG
1082
1083 return 0;
17467f23 1084}
f0fba2ad
LG
1085
1086static const struct of_device_id fsl_ssi_ids[] = {
1087 { .compatible = "fsl,mpc8610-ssi", },
09ce1111 1088 { .compatible = "fsl,imx21-ssi", },
f0fba2ad
LG
1089 {}
1090};
1091MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
1092
f07eb223 1093static struct platform_driver fsl_ssi_driver = {
f0fba2ad
LG
1094 .driver = {
1095 .name = "fsl-ssi-dai",
1096 .owner = THIS_MODULE,
1097 .of_match_table = fsl_ssi_ids,
1098 },
1099 .probe = fsl_ssi_probe,
1100 .remove = fsl_ssi_remove,
1101};
17467f23 1102
ba0a7e02 1103module_platform_driver(fsl_ssi_driver);
a454dad1 1104
f3142807 1105MODULE_ALIAS("platform:fsl-ssi-dai");
17467f23
TT
1106MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
1107MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
f0fba2ad 1108MODULE_LICENSE("GPL v2");
This page took 0.347454 seconds and 5 git commands to generate.