diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/fsl,ssi.txt | 4 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 346 |
2 files changed, 280 insertions, 70 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt index 088a2c038f01..4303b6ab6208 100644 --- a/Documentation/devicetree/bindings/sound/fsl,ssi.txt +++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt | |||
@@ -43,6 +43,10 @@ Required properties: | |||
43 | together. This would still allow different sample sizes, | 43 | together. This would still allow different sample sizes, |
44 | but not different sample rates. | 44 | but not different sample rates. |
45 | 45 | ||
46 | Required are also ac97 link bindings if ac97 is used. See | ||
47 | Documentation/devicetree/bindings/sound/soc-ac97link.txt for the necessary | ||
48 | bindings. | ||
49 | |||
46 | Optional properties: | 50 | Optional properties: |
47 | - codec-handle: Phandle to a 'codec' node that defines an audio | 51 | - codec-handle: Phandle to a 'codec' node that defines an audio |
48 | codec connected to this SSI. This node is typically | 52 | codec connected to this SSI. This node is typically |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 3168998dcf1d..9e410e1e49a9 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -141,6 +141,7 @@ struct fsl_ssi_private { | |||
141 | 141 | ||
142 | bool new_binding; | 142 | bool new_binding; |
143 | bool ssi_on_imx; | 143 | bool ssi_on_imx; |
144 | bool imx_ac97; | ||
144 | bool use_dma; | 145 | bool use_dma; |
145 | struct clk *clk; | 146 | struct clk *clk; |
146 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 147 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
@@ -320,6 +321,124 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
320 | return ret; | 321 | return ret; |
321 | } | 322 | } |
322 | 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 non-ac97 setups, we keep the SSI disabled because if we enable | ||
387 | * it, then the DMA controller will start. It's not supposed to start | ||
388 | * until the SCR.TE (or SCR.RE) bit is set, but it does anyway. The DMA | ||
389 | * controller will transfer one "BWC" of data (i.e. the amount of data | ||
390 | * that the MR.BWC bits are set to). The reason this is bad is because | ||
391 | * at this point, the PCM driver has not finished initializing the DMA | ||
392 | * controller. | ||
393 | */ | ||
394 | |||
395 | |||
396 | /* | ||
397 | * For ac97 interrupts are enabled with the startup of the substream | ||
398 | * because it is also running without an active substream. Normally SSI | ||
399 | * is only enabled when there is a substream. | ||
400 | */ | ||
401 | if (!ssi_private->imx_ac97) { | ||
402 | /* Enable the interrupts and DMA requests */ | ||
403 | if (ssi_private->use_dma) | ||
404 | write_ssi(SIER_FLAGS, &ssi->sier); | ||
405 | else | ||
406 | write_ssi(CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN | | ||
407 | CCSR_SSI_SIER_RIE | | ||
408 | CCSR_SSI_SIER_RFF0_EN, &ssi->sier); | ||
409 | } else { | ||
410 | /* | ||
411 | * Setup the clock control register | ||
412 | */ | ||
413 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
414 | &ssi->stccr); | ||
415 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
416 | &ssi->srccr); | ||
417 | |||
418 | /* | ||
419 | * Enable AC97 mode and startup the SSI | ||
420 | */ | ||
421 | write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, | ||
422 | &ssi->sacnt); | ||
423 | write_ssi(0xff, &ssi->saccdis); | ||
424 | write_ssi(0x300, &ssi->saccen); | ||
425 | |||
426 | /* | ||
427 | * Enable SSI | ||
428 | */ | ||
429 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN); | ||
430 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | ||
431 | |||
432 | /* | ||
433 | * Enable Transmit and Receive | ||
434 | */ | ||
435 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | |||
323 | /** | 442 | /** |
324 | * fsl_ssi_startup: create a new substream | 443 | * fsl_ssi_startup: create a new substream |
325 | * | 444 | * |
@@ -341,75 +460,14 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
341 | * and initialize the SSI registers. | 460 | * and initialize the SSI registers. |
342 | */ | 461 | */ |
343 | if (!ssi_private->first_stream) { | 462 | if (!ssi_private->first_stream) { |
344 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
345 | |||
346 | ssi_private->first_stream = substream; | 463 | ssi_private->first_stream = substream; |
347 | 464 | ||
348 | /* | 465 | /* |
349 | * Section 16.5 of the MPC8610 reference manual says that the | 466 | * fsl_ssi_setup was already called by ac97_init earlier if |
350 | * SSI needs to be disabled before updating the registers we set | 467 | * the driver is in ac97 mode. |
351 | * here. | ||
352 | */ | ||
353 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
354 | |||
355 | /* | ||
356 | * Program the SSI into I2S Slave Non-Network Synchronous mode. | ||
357 | * Also enable the transmit and receive FIFO. | ||
358 | * | ||
359 | * FIXME: Little-endian samples require a different shift dir | ||
360 | */ | ||
361 | write_ssi_mask(&ssi->scr, | ||
362 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | ||
363 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | ||
364 | | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | ||
365 | |||
366 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | ||
367 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | ||
368 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | ||
369 | |||
370 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
371 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
372 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
373 | |||
374 | /* | ||
375 | * The DC and PM bits are only used if the SSI is the clock | ||
376 | * master. | ||
377 | */ | ||
378 | |||
379 | /* Enable the interrupts and DMA requests */ | ||
380 | if (ssi_private->use_dma) | ||
381 | write_ssi(SIER_FLAGS, &ssi->sier); | ||
382 | else | ||
383 | write_ssi(CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN | | ||
384 | CCSR_SSI_SIER_RIE | | ||
385 | CCSR_SSI_SIER_RFF0_EN, &ssi->sier); | ||
386 | |||
387 | /* | ||
388 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We | ||
389 | * don't use FIFO 1. We program the transmit water to signal a | ||
390 | * DMA transfer if there are only two (or fewer) elements left | ||
391 | * in the FIFO. Two elements equals one frame (left channel, | ||
392 | * right channel). This value, however, depends on the depth of | ||
393 | * the transmit buffer. | ||
394 | * | ||
395 | * We program the receive FIFO to notify us if at least two | ||
396 | * elements (one frame) have been written to the FIFO. We could | ||
397 | * make this value larger (and maybe we should), but this way | ||
398 | * data will be written to memory as soon as it's available. | ||
399 | */ | ||
400 | write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | | ||
401 | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2), | ||
402 | &ssi->sfcsr); | ||
403 | |||
404 | /* | ||
405 | * We keep the SSI disabled because if we enable it, then the | ||
406 | * DMA controller will start. It's not supposed to start until | ||
407 | * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The | ||
408 | * DMA controller will transfer one "BWC" of data (i.e. the | ||
409 | * amount of data that the MR.BWC bits are set to). The reason | ||
410 | * this is bad is because at this point, the PCM driver has not | ||
411 | * finished initializing the DMA controller. | ||
412 | */ | 468 | */ |
469 | if (!ssi_private->imx_ac97) | ||
470 | fsl_ssi_setup(ssi_private); | ||
413 | } else { | 471 | } else { |
414 | if (synchronous) { | 472 | if (synchronous) { |
415 | struct snd_pcm_runtime *first_runtime = | 473 | struct snd_pcm_runtime *first_runtime = |
@@ -538,7 +596,8 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
538 | else | 596 | else |
539 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); | 597 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); |
540 | 598 | ||
541 | if ((read_ssi(&ssi->scr) & (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) | 599 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & |
600 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) | ||
542 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | 601 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); |
543 | break; | 602 | break; |
544 | 603 | ||
@@ -608,6 +667,133 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
608 | .name = "fsl-ssi", | 667 | .name = "fsl-ssi", |
609 | }; | 668 | }; |
610 | 669 | ||
670 | /** | ||
671 | * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit. | ||
672 | * | ||
673 | * This function is called by ALSA to start, stop, pause, and resume the | ||
674 | * transfer of data. | ||
675 | */ | ||
676 | static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | ||
677 | struct snd_soc_dai *dai) | ||
678 | { | ||
679 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
680 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata( | ||
681 | rtd->cpu_dai); | ||
682 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
683 | |||
684 | switch (cmd) { | ||
685 | case SNDRV_PCM_TRIGGER_START: | ||
686 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
687 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
688 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE | | ||
689 | CCSR_SSI_SIER_TFE0_EN); | ||
690 | else | ||
691 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE | | ||
692 | CCSR_SSI_SIER_RFF0_EN); | ||
693 | break; | ||
694 | |||
695 | case SNDRV_PCM_TRIGGER_STOP: | ||
696 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
697 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
698 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE | | ||
699 | CCSR_SSI_SIER_TFE0_EN, 0); | ||
700 | else | ||
701 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE | | ||
702 | CCSR_SSI_SIER_RFF0_EN, 0); | ||
703 | break; | ||
704 | |||
705 | default: | ||
706 | return -EINVAL; | ||
707 | } | ||
708 | |||
709 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
710 | write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); | ||
711 | else | ||
712 | write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { | ||
718 | .startup = fsl_ssi_startup, | ||
719 | .shutdown = fsl_ssi_shutdown, | ||
720 | .trigger = fsl_ssi_ac97_trigger, | ||
721 | }; | ||
722 | |||
723 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | ||
724 | .ac97_control = 1, | ||
725 | .playback = { | ||
726 | .stream_name = "AC97 Playback", | ||
727 | .channels_min = 2, | ||
728 | .channels_max = 2, | ||
729 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
730 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
731 | }, | ||
732 | .capture = { | ||
733 | .stream_name = "AC97 Capture", | ||
734 | .channels_min = 2, | ||
735 | .channels_max = 2, | ||
736 | .rates = SNDRV_PCM_RATE_48000, | ||
737 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
738 | }, | ||
739 | .ops = &fsl_ssi_ac97_dai_ops, | ||
740 | }; | ||
741 | |||
742 | |||
743 | static struct fsl_ssi_private *fsl_ac97_data; | ||
744 | |||
745 | static void fsl_ssi_ac97_init(void) | ||
746 | { | ||
747 | fsl_ssi_setup(fsl_ac97_data); | ||
748 | } | ||
749 | |||
750 | void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
751 | unsigned short val) | ||
752 | { | ||
753 | struct ccsr_ssi *ssi = fsl_ac97_data->ssi; | ||
754 | unsigned int lreg; | ||
755 | unsigned int lval; | ||
756 | |||
757 | if (reg > 0x7f) | ||
758 | return; | ||
759 | |||
760 | |||
761 | lreg = reg << 12; | ||
762 | write_ssi(lreg, &ssi->sacadd); | ||
763 | |||
764 | lval = val << 4; | ||
765 | write_ssi(lval , &ssi->sacdat); | ||
766 | |||
767 | write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK, | ||
768 | CCSR_SSI_SACNT_WR); | ||
769 | udelay(100); | ||
770 | } | ||
771 | |||
772 | unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, | ||
773 | unsigned short reg) | ||
774 | { | ||
775 | struct ccsr_ssi *ssi = fsl_ac97_data->ssi; | ||
776 | |||
777 | unsigned short val = -1; | ||
778 | unsigned int lreg; | ||
779 | |||
780 | lreg = (reg & 0x7f) << 12; | ||
781 | write_ssi(lreg, &ssi->sacadd); | ||
782 | write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK, | ||
783 | CCSR_SSI_SACNT_RD); | ||
784 | |||
785 | udelay(100); | ||
786 | |||
787 | val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff; | ||
788 | |||
789 | return val; | ||
790 | } | ||
791 | |||
792 | static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { | ||
793 | .read = fsl_ssi_ac97_read, | ||
794 | .write = fsl_ssi_ac97_write, | ||
795 | }; | ||
796 | |||
611 | /* Show the statistics of a flag only if its interrupt is enabled. The | 797 | /* Show the statistics of a flag only if its interrupt is enabled. The |
612 | * compiler will optimze this code to a no-op if the interrupt is not | 798 | * compiler will optimze this code to a no-op if the interrupt is not |
613 | * enabled. | 799 | * enabled. |
@@ -684,6 +870,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
684 | struct resource res; | 870 | struct resource res; |
685 | char name[64]; | 871 | char name[64]; |
686 | bool shared; | 872 | bool shared; |
873 | bool ac97 = false; | ||
687 | 874 | ||
688 | /* SSIs that are not connected on the board should have a | 875 | /* SSIs that are not connected on the board should have a |
689 | * status = "disabled" | 876 | * status = "disabled" |
@@ -694,7 +881,13 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
694 | 881 | ||
695 | /* We only support the SSI in "I2S Slave" mode */ | 882 | /* We only support the SSI in "I2S Slave" mode */ |
696 | sprop = of_get_property(np, "fsl,mode", NULL); | 883 | sprop = of_get_property(np, "fsl,mode", NULL); |
697 | if (!sprop || strcmp(sprop, "i2s-slave")) { | 884 | if (!sprop) { |
885 | dev_err(&pdev->dev, "fsl,mode property is necessary\n"); | ||
886 | return -EINVAL; | ||
887 | } | ||
888 | if (!strcmp(sprop, "ac97-slave")) { | ||
889 | ac97 = true; | ||
890 | } else if (strcmp(sprop, "i2s-slave")) { | ||
698 | dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); | 891 | dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); |
699 | return -ENODEV; | 892 | return -ENODEV; |
700 | } | 893 | } |
@@ -713,9 +906,19 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
713 | ssi_private->use_dma = !of_property_read_bool(np, | 906 | ssi_private->use_dma = !of_property_read_bool(np, |
714 | "fsl,fiq-stream-filter"); | 907 | "fsl,fiq-stream-filter"); |
715 | 908 | ||
716 | /* Initialize this copy of the CPU DAI driver structure */ | 909 | if (ac97) { |
717 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | 910 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, |
718 | sizeof(fsl_ssi_dai_template)); | 911 | sizeof(fsl_ssi_ac97_dai)); |
912 | |||
913 | fsl_ac97_data = ssi_private; | ||
914 | ssi_private->imx_ac97 = true; | ||
915 | |||
916 | snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev); | ||
917 | } else { | ||
918 | /* Initialize this copy of the CPU DAI driver structure */ | ||
919 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | ||
920 | sizeof(fsl_ssi_dai_template)); | ||
921 | } | ||
719 | ssi_private->cpu_dai_drv.name = ssi_private->name; | 922 | ssi_private->cpu_dai_drv.name = ssi_private->name; |
720 | 923 | ||
721 | /* Get the addresses and IRQ */ | 924 | /* Get the addresses and IRQ */ |
@@ -901,6 +1104,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
901 | } | 1104 | } |
902 | 1105 | ||
903 | done: | 1106 | done: |
1107 | if (ssi_private->imx_ac97) | ||
1108 | fsl_ssi_ac97_init(); | ||
1109 | |||
904 | return 0; | 1110 | return 0; |
905 | 1111 | ||
906 | error_dai: | 1112 | error_dai: |