diff options
Diffstat (limited to 'sound/soc/fsl/fsl_ssi.c')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 500 |
1 files changed, 373 insertions, 127 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 2f2d837df07f..5cf626c4dc96 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -8,6 +8,26 @@ | |||
8 | * This file is licensed under the terms of the GNU General Public License | 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 | 9 | * version 2. This program is licensed "as is" without any warranty of any |
10 | * kind, whether express or implied. | 10 | * kind, whether express or implied. |
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. | ||
11 | */ | 31 | */ |
12 | 32 | ||
13 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -36,7 +56,7 @@ | |||
36 | #define read_ssi(addr) in_be32(addr) | 56 | #define read_ssi(addr) in_be32(addr) |
37 | #define write_ssi(val, addr) out_be32(addr, val) | 57 | #define write_ssi(val, addr) out_be32(addr, val) |
38 | #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) | 58 | #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) |
39 | #elif defined ARM | 59 | #else |
40 | #define read_ssi(addr) readl(addr) | 60 | #define read_ssi(addr) readl(addr) |
41 | #define write_ssi(val, addr) writel(val, addr) | 61 | #define write_ssi(val, addr) writel(val, addr) |
42 | /* | 62 | /* |
@@ -121,11 +141,14 @@ struct fsl_ssi_private { | |||
121 | 141 | ||
122 | bool new_binding; | 142 | bool new_binding; |
123 | bool ssi_on_imx; | 143 | bool ssi_on_imx; |
144 | bool imx_ac97; | ||
145 | bool use_dma; | ||
124 | struct clk *clk; | 146 | struct clk *clk; |
125 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 147 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
126 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 148 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
127 | struct imx_dma_data filter_data_tx; | 149 | struct imx_dma_data filter_data_tx; |
128 | struct imx_dma_data filter_data_rx; | 150 | struct imx_dma_data filter_data_rx; |
151 | struct imx_pcm_fiq_params fiq_params; | ||
129 | 152 | ||
130 | struct { | 153 | struct { |
131 | unsigned int rfrc; | 154 | unsigned int rfrc; |
@@ -298,6 +321,102 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
298 | return ret; | 321 | return ret; |
299 | } | 322 | } |
300 | 323 | ||
324 | static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | ||
325 | { | ||
326 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
327 | u8 i2s_mode; | ||
328 | u8 wm; | ||
329 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | ||
330 | |||
331 | if (ssi_private->imx_ac97) | ||
332 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; | ||
333 | else | ||
334 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; | ||
335 | |||
336 | /* | ||
337 | * Section 16.5 of the MPC8610 reference manual says that the SSI needs | ||
338 | * to be disabled before updating the registers we set here. | ||
339 | */ | ||
340 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
341 | |||
342 | /* | ||
343 | * Program the SSI into I2S Slave Non-Network Synchronous mode. Also | ||
344 | * enable the transmit and receive FIFO. | ||
345 | * | ||
346 | * FIXME: Little-endian samples require a different shift dir | ||
347 | */ | ||
348 | write_ssi_mask(&ssi->scr, | ||
349 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | ||
350 | CCSR_SSI_SCR_TFR_CLK_DIS | | ||
351 | i2s_mode | | ||
352 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | ||
353 | |||
354 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | ||
355 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | ||
356 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | ||
357 | |||
358 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
359 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
360 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
361 | /* | ||
362 | * The DC and PM bits are only used if the SSI is the clock master. | ||
363 | */ | ||
364 | |||
365 | /* | ||
366 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't | ||
367 | * use FIFO 1. We program the transmit water to signal a DMA transfer | ||
368 | * if there are only two (or fewer) elements left in the FIFO. Two | ||
369 | * elements equals one frame (left channel, right channel). This value, | ||
370 | * however, depends on the depth of the transmit buffer. | ||
371 | * | ||
372 | * We set the watermark on the same level as the DMA burstsize. For | ||
373 | * fiq it is probably better to use the biggest possible watermark | ||
374 | * size. | ||
375 | */ | ||
376 | if (ssi_private->use_dma) | ||
377 | wm = ssi_private->fifo_depth - 2; | ||
378 | else | ||
379 | wm = ssi_private->fifo_depth; | ||
380 | |||
381 | write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) | | ||
382 | CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm), | ||
383 | &ssi->sfcsr); | ||
384 | |||
385 | /* | ||
386 | * For ac97 interrupts are enabled with the startup of the substream | ||
387 | * because it is also running without an active substream. Normally SSI | ||
388 | * is only enabled when there is a substream. | ||
389 | */ | ||
390 | if (ssi_private->imx_ac97) { | ||
391 | /* | ||
392 | * Setup the clock control register | ||
393 | */ | ||
394 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
395 | &ssi->stccr); | ||
396 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
397 | &ssi->srccr); | ||
398 | |||
399 | /* | ||
400 | * Enable AC97 mode and startup the SSI | ||
401 | */ | ||
402 | write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, | ||
403 | &ssi->sacnt); | ||
404 | write_ssi(0xff, &ssi->saccdis); | ||
405 | write_ssi(0x300, &ssi->saccen); | ||
406 | |||
407 | /* | ||
408 | * Enable SSI, Transmit and Receive | ||
409 | */ | ||
410 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | | ||
411 | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); | ||
412 | |||
413 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | ||
414 | } | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | |||
301 | /** | 420 | /** |
302 | * fsl_ssi_startup: create a new substream | 421 | * fsl_ssi_startup: create a new substream |
303 | * | 422 | * |
@@ -319,70 +438,14 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
319 | * and initialize the SSI registers. | 438 | * and initialize the SSI registers. |
320 | */ | 439 | */ |
321 | if (!ssi_private->first_stream) { | 440 | if (!ssi_private->first_stream) { |
322 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
323 | |||
324 | ssi_private->first_stream = substream; | 441 | ssi_private->first_stream = substream; |
325 | 442 | ||
326 | /* | 443 | /* |
327 | * Section 16.5 of the MPC8610 reference manual says that the | 444 | * fsl_ssi_setup was already called by ac97_init earlier if |
328 | * SSI needs to be disabled before updating the registers we set | 445 | * the driver is in ac97 mode. |
329 | * here. | ||
330 | */ | ||
331 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
332 | |||
333 | /* | ||
334 | * Program the SSI into I2S Slave Non-Network Synchronous mode. | ||
335 | * Also enable the transmit and receive FIFO. | ||
336 | * | ||
337 | * FIXME: Little-endian samples require a different shift dir | ||
338 | */ | ||
339 | write_ssi_mask(&ssi->scr, | ||
340 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | ||
341 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | ||
342 | | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | ||
343 | |||
344 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | ||
345 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | ||
346 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | ||
347 | |||
348 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
349 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
350 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
351 | |||
352 | /* | ||
353 | * The DC and PM bits are only used if the SSI is the clock | ||
354 | * master. | ||
355 | */ | ||
356 | |||
357 | /* Enable the interrupts and DMA requests */ | ||
358 | write_ssi(SIER_FLAGS, &ssi->sier); | ||
359 | |||
360 | /* | ||
361 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We | ||
362 | * don't use FIFO 1. We program the transmit water to signal a | ||
363 | * DMA transfer if there are only two (or fewer) elements left | ||
364 | * in the FIFO. Two elements equals one frame (left channel, | ||
365 | * right channel). This value, however, depends on the depth of | ||
366 | * the transmit buffer. | ||
367 | * | ||
368 | * We program the receive FIFO to notify us if at least two | ||
369 | * elements (one frame) have been written to the FIFO. We could | ||
370 | * make this value larger (and maybe we should), but this way | ||
371 | * data will be written to memory as soon as it's available. | ||
372 | */ | ||
373 | write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | | ||
374 | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2), | ||
375 | &ssi->sfcsr); | ||
376 | |||
377 | /* | ||
378 | * We keep the SSI disabled because if we enable it, then the | ||
379 | * DMA controller will start. It's not supposed to start until | ||
380 | * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The | ||
381 | * DMA controller will transfer one "BWC" of data (i.e. the | ||
382 | * amount of data that the MR.BWC bits are set to). The reason | ||
383 | * this is bad is because at this point, the PCM driver has not | ||
384 | * finished initializing the DMA controller. | ||
385 | */ | 446 | */ |
447 | if (!ssi_private->imx_ac97) | ||
448 | fsl_ssi_setup(ssi_private); | ||
386 | } else { | 449 | } else { |
387 | if (synchronous) { | 450 | if (synchronous) { |
388 | struct snd_pcm_runtime *first_runtime = | 451 | struct snd_pcm_runtime *first_runtime = |
@@ -492,6 +555,27 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
492 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 555 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
493 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 556 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
494 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 557 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
558 | unsigned int sier_bits; | ||
559 | |||
560 | /* | ||
561 | * Enable only the interrupts and DMA requests | ||
562 | * that are needed for the channel. As the fiq | ||
563 | * is polling for this bits, we have to ensure | ||
564 | * that this are aligned with the preallocated | ||
565 | * buffers | ||
566 | */ | ||
567 | |||
568 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
569 | if (ssi_private->use_dma) | ||
570 | sier_bits = SIER_FLAGS; | ||
571 | else | ||
572 | sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; | ||
573 | } else { | ||
574 | if (ssi_private->use_dma) | ||
575 | sier_bits = SIER_FLAGS; | ||
576 | else | ||
577 | sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; | ||
578 | } | ||
495 | 579 | ||
496 | switch (cmd) { | 580 | switch (cmd) { |
497 | case SNDRV_PCM_TRIGGER_START: | 581 | case SNDRV_PCM_TRIGGER_START: |
@@ -510,12 +594,18 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
510 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); | 594 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); |
511 | else | 595 | else |
512 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); | 596 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); |
597 | |||
598 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & | ||
599 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) | ||
600 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
513 | break; | 601 | break; |
514 | 602 | ||
515 | default: | 603 | default: |
516 | return -EINVAL; | 604 | return -EINVAL; |
517 | } | 605 | } |
518 | 606 | ||
607 | write_ssi(sier_bits, &ssi->sier); | ||
608 | |||
519 | return 0; | 609 | return 0; |
520 | } | 610 | } |
521 | 611 | ||
@@ -534,22 +624,13 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
534 | ssi_private->first_stream = ssi_private->second_stream; | 624 | ssi_private->first_stream = ssi_private->second_stream; |
535 | 625 | ||
536 | ssi_private->second_stream = NULL; | 626 | ssi_private->second_stream = NULL; |
537 | |||
538 | /* | ||
539 | * If this is the last active substream, disable the SSI. | ||
540 | */ | ||
541 | if (!ssi_private->first_stream) { | ||
542 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
543 | |||
544 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
545 | } | ||
546 | } | 627 | } |
547 | 628 | ||
548 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | 629 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) |
549 | { | 630 | { |
550 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | 631 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); |
551 | 632 | ||
552 | if (ssi_private->ssi_on_imx) { | 633 | if (ssi_private->ssi_on_imx && ssi_private->use_dma) { |
553 | dai->playback_dma_data = &ssi_private->dma_params_tx; | 634 | dai->playback_dma_data = &ssi_private->dma_params_tx; |
554 | dai->capture_dma_data = &ssi_private->dma_params_rx; | 635 | dai->capture_dma_data = &ssi_private->dma_params_rx; |
555 | } | 636 | } |
@@ -587,6 +668,133 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
587 | .name = "fsl-ssi", | 668 | .name = "fsl-ssi", |
588 | }; | 669 | }; |
589 | 670 | ||
671 | /** | ||
672 | * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit. | ||
673 | * | ||
674 | * This function is called by ALSA to start, stop, pause, and resume the | ||
675 | * transfer of data. | ||
676 | */ | ||
677 | static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | ||
678 | struct snd_soc_dai *dai) | ||
679 | { | ||
680 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
681 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata( | ||
682 | rtd->cpu_dai); | ||
683 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
684 | |||
685 | switch (cmd) { | ||
686 | case SNDRV_PCM_TRIGGER_START: | ||
687 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
688 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
689 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE | | ||
690 | CCSR_SSI_SIER_TFE0_EN); | ||
691 | else | ||
692 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE | | ||
693 | CCSR_SSI_SIER_RFF0_EN); | ||
694 | break; | ||
695 | |||
696 | case SNDRV_PCM_TRIGGER_STOP: | ||
697 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
698 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
699 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE | | ||
700 | CCSR_SSI_SIER_TFE0_EN, 0); | ||
701 | else | ||
702 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE | | ||
703 | CCSR_SSI_SIER_RFF0_EN, 0); | ||
704 | break; | ||
705 | |||
706 | default: | ||
707 | return -EINVAL; | ||
708 | } | ||
709 | |||
710 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
711 | write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); | ||
712 | else | ||
713 | write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); | ||
714 | |||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { | ||
719 | .startup = fsl_ssi_startup, | ||
720 | .shutdown = fsl_ssi_shutdown, | ||
721 | .trigger = fsl_ssi_ac97_trigger, | ||
722 | }; | ||
723 | |||
724 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | ||
725 | .ac97_control = 1, | ||
726 | .playback = { | ||
727 | .stream_name = "AC97 Playback", | ||
728 | .channels_min = 2, | ||
729 | .channels_max = 2, | ||
730 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
731 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
732 | }, | ||
733 | .capture = { | ||
734 | .stream_name = "AC97 Capture", | ||
735 | .channels_min = 2, | ||
736 | .channels_max = 2, | ||
737 | .rates = SNDRV_PCM_RATE_48000, | ||
738 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
739 | }, | ||
740 | .ops = &fsl_ssi_ac97_dai_ops, | ||
741 | }; | ||
742 | |||
743 | |||
744 | static struct fsl_ssi_private *fsl_ac97_data; | ||
745 | |||
746 | static void fsl_ssi_ac97_init(void) | ||
747 | { | ||
748 | fsl_ssi_setup(fsl_ac97_data); | ||
749 | } | ||
750 | |||
751 | void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
752 | unsigned short val) | ||
753 | { | ||
754 | struct ccsr_ssi *ssi = fsl_ac97_data->ssi; | ||
755 | unsigned int lreg; | ||
756 | unsigned int lval; | ||
757 | |||
758 | if (reg > 0x7f) | ||
759 | return; | ||
760 | |||
761 | |||
762 | lreg = reg << 12; | ||
763 | write_ssi(lreg, &ssi->sacadd); | ||
764 | |||
765 | lval = val << 4; | ||
766 | write_ssi(lval , &ssi->sacdat); | ||
767 | |||
768 | write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK, | ||
769 | CCSR_SSI_SACNT_WR); | ||
770 | udelay(100); | ||
771 | } | ||
772 | |||
773 | unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, | ||
774 | unsigned short reg) | ||
775 | { | ||
776 | struct ccsr_ssi *ssi = fsl_ac97_data->ssi; | ||
777 | |||
778 | unsigned short val = -1; | ||
779 | unsigned int lreg; | ||
780 | |||
781 | lreg = (reg & 0x7f) << 12; | ||
782 | write_ssi(lreg, &ssi->sacadd); | ||
783 | write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK, | ||
784 | CCSR_SSI_SACNT_RD); | ||
785 | |||
786 | udelay(100); | ||
787 | |||
788 | val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff; | ||
789 | |||
790 | return val; | ||
791 | } | ||
792 | |||
793 | static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { | ||
794 | .read = fsl_ssi_ac97_read, | ||
795 | .write = fsl_ssi_ac97_write, | ||
796 | }; | ||
797 | |||
590 | /* Show the statistics of a flag only if its interrupt is enabled. The | 798 | /* Show the statistics of a flag only if its interrupt is enabled. The |
591 | * compiler will optimze this code to a no-op if the interrupt is not | 799 | * compiler will optimze this code to a no-op if the interrupt is not |
592 | * enabled. | 800 | * enabled. |
@@ -663,6 +871,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
663 | struct resource res; | 871 | struct resource res; |
664 | char name[64]; | 872 | char name[64]; |
665 | bool shared; | 873 | bool shared; |
874 | bool ac97 = false; | ||
666 | 875 | ||
667 | /* SSIs that are not connected on the board should have a | 876 | /* SSIs that are not connected on the board should have a |
668 | * status = "disabled" | 877 | * status = "disabled" |
@@ -673,14 +882,20 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
673 | 882 | ||
674 | /* We only support the SSI in "I2S Slave" mode */ | 883 | /* We only support the SSI in "I2S Slave" mode */ |
675 | sprop = of_get_property(np, "fsl,mode", NULL); | 884 | sprop = of_get_property(np, "fsl,mode", NULL); |
676 | if (!sprop || strcmp(sprop, "i2s-slave")) { | 885 | if (!sprop) { |
886 | dev_err(&pdev->dev, "fsl,mode property is necessary\n"); | ||
887 | return -EINVAL; | ||
888 | } | ||
889 | if (!strcmp(sprop, "ac97-slave")) { | ||
890 | ac97 = true; | ||
891 | } else if (strcmp(sprop, "i2s-slave")) { | ||
677 | dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); | 892 | dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); |
678 | return -ENODEV; | 893 | return -ENODEV; |
679 | } | 894 | } |
680 | 895 | ||
681 | /* The DAI name is the last part of the full name of the node. */ | 896 | /* The DAI name is the last part of the full name of the node. */ |
682 | p = strrchr(np->full_name, '/') + 1; | 897 | p = strrchr(np->full_name, '/') + 1; |
683 | ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), | 898 | ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private) + strlen(p), |
684 | GFP_KERNEL); | 899 | GFP_KERNEL); |
685 | if (!ssi_private) { | 900 | if (!ssi_private) { |
686 | dev_err(&pdev->dev, "could not allocate DAI object\n"); | 901 | dev_err(&pdev->dev, "could not allocate DAI object\n"); |
@@ -689,38 +904,41 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
689 | 904 | ||
690 | strcpy(ssi_private->name, p); | 905 | strcpy(ssi_private->name, p); |
691 | 906 | ||
692 | /* Initialize this copy of the CPU DAI driver structure */ | 907 | ssi_private->use_dma = !of_property_read_bool(np, |
693 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | 908 | "fsl,fiq-stream-filter"); |
694 | sizeof(fsl_ssi_dai_template)); | 909 | |
910 | if (ac97) { | ||
911 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, | ||
912 | sizeof(fsl_ssi_ac97_dai)); | ||
913 | |||
914 | fsl_ac97_data = ssi_private; | ||
915 | ssi_private->imx_ac97 = true; | ||
916 | |||
917 | snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev); | ||
918 | } else { | ||
919 | /* Initialize this copy of the CPU DAI driver structure */ | ||
920 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | ||
921 | sizeof(fsl_ssi_dai_template)); | ||
922 | } | ||
695 | ssi_private->cpu_dai_drv.name = ssi_private->name; | 923 | ssi_private->cpu_dai_drv.name = ssi_private->name; |
696 | 924 | ||
697 | /* Get the addresses and IRQ */ | 925 | /* Get the addresses and IRQ */ |
698 | ret = of_address_to_resource(np, 0, &res); | 926 | ret = of_address_to_resource(np, 0, &res); |
699 | if (ret) { | 927 | if (ret) { |
700 | dev_err(&pdev->dev, "could not determine device resources\n"); | 928 | dev_err(&pdev->dev, "could not determine device resources\n"); |
701 | goto error_kmalloc; | 929 | return ret; |
702 | } | 930 | } |
703 | ssi_private->ssi = of_iomap(np, 0); | 931 | ssi_private->ssi = of_iomap(np, 0); |
704 | if (!ssi_private->ssi) { | 932 | if (!ssi_private->ssi) { |
705 | dev_err(&pdev->dev, "could not map device resources\n"); | 933 | dev_err(&pdev->dev, "could not map device resources\n"); |
706 | ret = -ENOMEM; | 934 | return -ENOMEM; |
707 | goto error_kmalloc; | ||
708 | } | 935 | } |
709 | ssi_private->ssi_phys = res.start; | 936 | ssi_private->ssi_phys = res.start; |
710 | 937 | ||
711 | ssi_private->irq = irq_of_parse_and_map(np, 0); | 938 | ssi_private->irq = irq_of_parse_and_map(np, 0); |
712 | if (ssi_private->irq == NO_IRQ) { | 939 | if (ssi_private->irq == NO_IRQ) { |
713 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 940 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); |
714 | ret = -ENXIO; | 941 | return -ENXIO; |
715 | goto error_iomap; | ||
716 | } | ||
717 | |||
718 | /* The 'name' should not have any slashes in it. */ | ||
719 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, | ||
720 | ssi_private); | ||
721 | if (ret < 0) { | ||
722 | dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); | ||
723 | goto error_irqmap; | ||
724 | } | 942 | } |
725 | 943 | ||
726 | /* Are the RX and the TX clocks locked? */ | 944 | /* Are the RX and the TX clocks locked? */ |
@@ -739,13 +957,18 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
739 | u32 dma_events[2]; | 957 | u32 dma_events[2]; |
740 | ssi_private->ssi_on_imx = true; | 958 | ssi_private->ssi_on_imx = true; |
741 | 959 | ||
742 | ssi_private->clk = clk_get(&pdev->dev, NULL); | 960 | ssi_private->clk = devm_clk_get(&pdev->dev, NULL); |
743 | if (IS_ERR(ssi_private->clk)) { | 961 | if (IS_ERR(ssi_private->clk)) { |
744 | ret = PTR_ERR(ssi_private->clk); | 962 | ret = PTR_ERR(ssi_private->clk); |
745 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); | 963 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); |
746 | goto error_irq; | 964 | goto error_irqmap; |
965 | } | ||
966 | ret = clk_prepare_enable(ssi_private->clk); | ||
967 | if (ret) { | ||
968 | dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", | ||
969 | ret); | ||
970 | goto error_irqmap; | ||
747 | } | 971 | } |
748 | clk_prepare_enable(ssi_private->clk); | ||
749 | 972 | ||
750 | /* | 973 | /* |
751 | * We have burstsize be "fifo_depth - 2" to match the SSI | 974 | * We have burstsize be "fifo_depth - 2" to match the SSI |
@@ -763,24 +986,38 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
763 | &ssi_private->filter_data_tx; | 986 | &ssi_private->filter_data_tx; |
764 | ssi_private->dma_params_rx.filter_data = | 987 | ssi_private->dma_params_rx.filter_data = |
765 | &ssi_private->filter_data_rx; | 988 | &ssi_private->filter_data_rx; |
766 | /* | 989 | if (!of_property_read_bool(pdev->dev.of_node, "dmas") && |
767 | * TODO: This is a temporary solution and should be changed | 990 | ssi_private->use_dma) { |
768 | * to use generic DMA binding later when the helplers get in. | 991 | /* |
769 | */ | 992 | * FIXME: This is a temporary solution until all |
770 | ret = of_property_read_u32_array(pdev->dev.of_node, | 993 | * necessary dma drivers support the generic dma |
994 | * bindings. | ||
995 | */ | ||
996 | ret = of_property_read_u32_array(pdev->dev.of_node, | ||
771 | "fsl,ssi-dma-events", dma_events, 2); | 997 | "fsl,ssi-dma-events", dma_events, 2); |
772 | if (ret) { | 998 | if (ret && ssi_private->use_dma) { |
773 | dev_err(&pdev->dev, "could not get dma events\n"); | 999 | dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n"); |
774 | goto error_clk; | 1000 | goto error_clk; |
1001 | } | ||
775 | } | 1002 | } |
776 | 1003 | ||
777 | shared = of_device_is_compatible(of_get_parent(np), | 1004 | shared = of_device_is_compatible(of_get_parent(np), |
778 | "fsl,spba-bus"); | 1005 | "fsl,spba-bus"); |
779 | 1006 | ||
780 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, | 1007 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, |
781 | dma_events[0], shared); | 1008 | dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); |
782 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, | 1009 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, |
783 | dma_events[1], shared); | 1010 | dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); |
1011 | } else if (ssi_private->use_dma) { | ||
1012 | /* The 'name' should not have any slashes in it. */ | ||
1013 | ret = devm_request_irq(&pdev->dev, ssi_private->irq, | ||
1014 | fsl_ssi_isr, 0, ssi_private->name, | ||
1015 | ssi_private); | ||
1016 | if (ret < 0) { | ||
1017 | dev_err(&pdev->dev, "could not claim irq %u\n", | ||
1018 | ssi_private->irq); | ||
1019 | goto error_irqmap; | ||
1020 | } | ||
784 | } | 1021 | } |
785 | 1022 | ||
786 | /* Initialize the the device_attribute structure */ | 1023 | /* Initialize the the device_attribute structure */ |
@@ -794,7 +1031,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
794 | if (ret) { | 1031 | if (ret) { |
795 | dev_err(&pdev->dev, "could not create sysfs %s file\n", | 1032 | dev_err(&pdev->dev, "could not create sysfs %s file\n", |
796 | ssi_private->dev_attr.attr.name); | 1033 | ssi_private->dev_attr.attr.name); |
797 | goto error_irq; | 1034 | goto error_clk; |
798 | } | 1035 | } |
799 | 1036 | ||
800 | /* Register with ASoC */ | 1037 | /* Register with ASoC */ |
@@ -808,9 +1045,30 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
808 | } | 1045 | } |
809 | 1046 | ||
810 | if (ssi_private->ssi_on_imx) { | 1047 | if (ssi_private->ssi_on_imx) { |
811 | ret = imx_pcm_dma_init(pdev); | 1048 | if (!ssi_private->use_dma) { |
812 | if (ret) | 1049 | |
813 | goto error_dev; | 1050 | /* |
1051 | * Some boards use an incompatible codec. To get it | ||
1052 | * working, we are using imx-fiq-pcm-audio, that | ||
1053 | * can handle those codecs. DMA is not possible in this | ||
1054 | * situation. | ||
1055 | */ | ||
1056 | |||
1057 | ssi_private->fiq_params.irq = ssi_private->irq; | ||
1058 | ssi_private->fiq_params.base = ssi_private->ssi; | ||
1059 | ssi_private->fiq_params.dma_params_rx = | ||
1060 | &ssi_private->dma_params_rx; | ||
1061 | ssi_private->fiq_params.dma_params_tx = | ||
1062 | &ssi_private->dma_params_tx; | ||
1063 | |||
1064 | ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params); | ||
1065 | if (ret) | ||
1066 | goto error_dev; | ||
1067 | } else { | ||
1068 | ret = imx_pcm_dma_init(pdev); | ||
1069 | if (ret) | ||
1070 | goto error_dev; | ||
1071 | } | ||
814 | } | 1072 | } |
815 | 1073 | ||
816 | /* | 1074 | /* |
@@ -845,6 +1103,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
845 | } | 1103 | } |
846 | 1104 | ||
847 | done: | 1105 | done: |
1106 | if (ssi_private->imx_ac97) | ||
1107 | fsl_ssi_ac97_init(); | ||
1108 | |||
848 | return 0; | 1109 | return 0; |
849 | 1110 | ||
850 | error_dai: | 1111 | error_dai: |
@@ -857,23 +1118,12 @@ error_dev: | |||
857 | device_remove_file(&pdev->dev, dev_attr); | 1118 | device_remove_file(&pdev->dev, dev_attr); |
858 | 1119 | ||
859 | error_clk: | 1120 | error_clk: |
860 | if (ssi_private->ssi_on_imx) { | 1121 | if (ssi_private->ssi_on_imx) |
861 | clk_disable_unprepare(ssi_private->clk); | 1122 | clk_disable_unprepare(ssi_private->clk); |
862 | clk_put(ssi_private->clk); | ||
863 | } | ||
864 | |||
865 | error_irq: | ||
866 | free_irq(ssi_private->irq, ssi_private); | ||
867 | 1123 | ||
868 | error_irqmap: | 1124 | error_irqmap: |
869 | irq_dispose_mapping(ssi_private->irq); | 1125 | irq_dispose_mapping(ssi_private->irq); |
870 | 1126 | ||
871 | error_iomap: | ||
872 | iounmap(ssi_private->ssi); | ||
873 | |||
874 | error_kmalloc: | ||
875 | kfree(ssi_private); | ||
876 | |||
877 | return ret; | 1127 | return ret; |
878 | } | 1128 | } |
879 | 1129 | ||
@@ -883,20 +1133,15 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
883 | 1133 | ||
884 | if (!ssi_private->new_binding) | 1134 | if (!ssi_private->new_binding) |
885 | platform_device_unregister(ssi_private->pdev); | 1135 | platform_device_unregister(ssi_private->pdev); |
886 | if (ssi_private->ssi_on_imx) { | 1136 | if (ssi_private->ssi_on_imx) |
887 | imx_pcm_dma_exit(pdev); | 1137 | imx_pcm_dma_exit(pdev); |
888 | clk_disable_unprepare(ssi_private->clk); | ||
889 | clk_put(ssi_private->clk); | ||
890 | } | ||
891 | snd_soc_unregister_component(&pdev->dev); | 1138 | snd_soc_unregister_component(&pdev->dev); |
1139 | dev_set_drvdata(&pdev->dev, NULL); | ||
892 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); | 1140 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); |
893 | 1141 | if (ssi_private->ssi_on_imx) | |
894 | free_irq(ssi_private->irq, ssi_private); | 1142 | clk_disable_unprepare(ssi_private->clk); |
895 | irq_dispose_mapping(ssi_private->irq); | 1143 | irq_dispose_mapping(ssi_private->irq); |
896 | 1144 | ||
897 | kfree(ssi_private); | ||
898 | dev_set_drvdata(&pdev->dev, NULL); | ||
899 | |||
900 | return 0; | 1145 | return 0; |
901 | } | 1146 | } |
902 | 1147 | ||
@@ -919,6 +1164,7 @@ static struct platform_driver fsl_ssi_driver = { | |||
919 | 1164 | ||
920 | module_platform_driver(fsl_ssi_driver); | 1165 | module_platform_driver(fsl_ssi_driver); |
921 | 1166 | ||
1167 | MODULE_ALIAS("platform:fsl-ssi-dai"); | ||
922 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 1168 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
923 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); | 1169 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); |
924 | MODULE_LICENSE("GPL v2"); | 1170 | MODULE_LICENSE("GPL v2"); |