ASoC: Blackfin: push down SPORT settings from global variables
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / sound / soc / blackfin / bf5xx-i2s.c
index d453b1e9d607d0d0e9d712bf981a3e6dda4ae17f..00cc3e00b2fead767ca60cbc54e603b3521f960a 100644 (file)
@@ -51,59 +51,24 @@ struct bf5xx_i2s_port {
        int configured;
 };
 
-static struct bf5xx_i2s_port bf5xx_i2s;
-static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-
-static struct sport_param sport_params[2] = {
-       {
-               .dma_rx_chan    = CH_SPORT0_RX,
-               .dma_tx_chan    = CH_SPORT0_TX,
-               .err_irq        = IRQ_SPORT0_ERROR,
-               .regs           = (struct sport_register *)SPORT0_TCR1,
-       },
-       {
-               .dma_rx_chan    = CH_SPORT1_RX,
-               .dma_tx_chan    = CH_SPORT1_TX,
-               .err_irq        = IRQ_SPORT1_ERROR,
-               .regs           = (struct sport_register *)SPORT1_TCR1,
-       }
-};
-
-/*
- * Setting the TFS pin selector for SPORT 0 based on whether the selected
- * port id F or G. If the port is F then no conflict should exist for the
- * TFS. When Port G is selected and EMAC then there is a conflict between
- * the PHY interrupt line and TFS.  Current settings prevent the conflict
- * by ignoring the TFS pin when Port G is selected. This allows both
- * codecs and EMAC using Port G concurrently.
- */
-#ifdef CONFIG_BF527_SPORT0_PORTG
-#define LOCAL_SPORT0_TFS (0)
-#else
-#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
-#endif
-
-static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-               P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0},
-               {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI,
-               P_SPORT1_RSCLK, P_SPORT1_TFS, 0} };
-
 static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
+       struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
+       struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
        int ret = 0;
 
        /* interface format:support I2S,slave mode */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
-               bf5xx_i2s.tcr1 |= TFSR | TCKFE;
-               bf5xx_i2s.rcr1 |= RFSR | RCKFE;
-               bf5xx_i2s.tcr2 |= TSFSE;
-               bf5xx_i2s.rcr2 |= RSFSE;
+               bf5xx_i2s->tcr1 |= TFSR | TCKFE;
+               bf5xx_i2s->rcr1 |= RFSR | RCKFE;
+               bf5xx_i2s->tcr2 |= TSFSE;
+               bf5xx_i2s->rcr2 |= RSFSE;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               bf5xx_i2s.tcr1 |= TFSR;
-               bf5xx_i2s.rcr1 |= RFSR;
+               bf5xx_i2s->tcr1 |= TFSR;
+               bf5xx_i2s->rcr1 |= RFSR;
                break;
        case SND_SOC_DAIFMT_LEFT_J:
                ret = -EINVAL;
@@ -135,29 +100,35 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
 {
+       struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
+       struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
        int ret = 0;
 
-       bf5xx_i2s.tcr2 &= ~0x1f;
-       bf5xx_i2s.rcr2 &= ~0x1f;
+       bf5xx_i2s->tcr2 &= ~0x1f;
+       bf5xx_i2s->rcr2 &= ~0x1f;
        switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               bf5xx_i2s->tcr2 |= 7;
+               bf5xx_i2s->rcr2 |= 7;
+               sport_handle->wdsize = 1;
        case SNDRV_PCM_FORMAT_S16_LE:
-               bf5xx_i2s.tcr2 |= 15;
-               bf5xx_i2s.rcr2 |= 15;
+               bf5xx_i2s->tcr2 |= 15;
+               bf5xx_i2s->rcr2 |= 15;
                sport_handle->wdsize = 2;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               bf5xx_i2s.tcr2 |= 23;
-               bf5xx_i2s.rcr2 |= 23;
+               bf5xx_i2s->tcr2 |= 23;
+               bf5xx_i2s->rcr2 |= 23;
                sport_handle->wdsize = 3;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               bf5xx_i2s.tcr2 |= 31;
-               bf5xx_i2s.rcr2 |= 31;
+               bf5xx_i2s->tcr2 |= 31;
+               bf5xx_i2s->rcr2 |= 31;
                sport_handle->wdsize = 4;
                break;
        }
 
-       if (!bf5xx_i2s.configured) {
+       if (!bf5xx_i2s->configured) {
                /*
                 * TX and RX are not independent,they are enabled at the
                 * same time, even if only one side is running. So, we
@@ -166,16 +137,16 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
                 *
                 * CPU DAI:slave mode.
                 */
-               bf5xx_i2s.configured = 1;
-               ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
-                                     bf5xx_i2s.rcr2, 0, 0);
+               bf5xx_i2s->configured = 1;
+               ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
+                                     bf5xx_i2s->rcr2, 0, 0);
                if (ret) {
                        pr_err("SPORT is busy!\n");
                        return -EBUSY;
                }
 
-               ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
-                                     bf5xx_i2s.tcr2, 0, 0);
+               ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
+                                     bf5xx_i2s->tcr2, 0, 0);
                if (ret) {
                        pr_err("SPORT is busy!\n");
                        return -EBUSY;
@@ -188,41 +159,19 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
 static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *dai)
 {
+       struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
+       struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
+
        pr_debug("%s enter\n", __func__);
        /* No active stream, SPORT is allowed to be configured again. */
        if (!dai->active)
-               bf5xx_i2s.configured = 0;
-}
-
-static int bf5xx_i2s_probe(struct snd_soc_dai *dai)
-{
-       pr_debug("%s enter\n", __func__);
-       if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
-               pr_err("Requesting Peripherals failed\n");
-               return -EFAULT;
-       }
-
-       /* request DMA for SPORT */
-       sport_handle = sport_init(&sport_params[sport_num], 4, \
-                       2 * sizeof(u32), NULL);
-       if (!sport_handle) {
-               peripheral_free_list(&sport_req[sport_num][0]);
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static int bf5xx_i2s_remove(struct snd_soc_dai *dai)
-{
-       pr_debug("%s enter\n", __func__);
-       peripheral_free_list(&sport_req[sport_num][0]);
-       return 0;
+               bf5xx_i2s->configured = 0;
 }
 
 #ifdef CONFIG_PM
 static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
 {
+       struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
 
@@ -235,19 +184,21 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
 
 static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
 {
+       struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
+       struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
        int ret;
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
 
-       ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
-                                     bf5xx_i2s.rcr2, 0, 0);
+       ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
+                                     bf5xx_i2s->rcr2, 0, 0);
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
        }
 
-       ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
-                                     bf5xx_i2s.tcr2, 0, 0);
+       ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
+                                     bf5xx_i2s->tcr2, 0, 0);
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
@@ -266,8 +217,11 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
                SNDRV_PCM_RATE_96000)
 
-#define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
-       SNDRV_PCM_FMTBIT_S32_LE)
+#define BF5XX_I2S_FORMATS \
+       (SNDRV_PCM_FMTBIT_S8 | \
+        SNDRV_PCM_FMTBIT_S16_LE | \
+        SNDRV_PCM_FMTBIT_S24_LE | \
+        SNDRV_PCM_FMTBIT_S32_LE)
 
 static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
        .shutdown       = bf5xx_i2s_shutdown,
@@ -276,8 +230,6 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
 };
 
 static struct snd_soc_dai_driver bf5xx_i2s_dai = {
-       .probe = bf5xx_i2s_probe,
-       .remove = bf5xx_i2s_remove,
        .suspend = bf5xx_i2s_suspend,
        .resume = bf5xx_i2s_resume,
        .playback = {
@@ -293,23 +245,45 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
        .ops = &bf5xx_i2s_dai_ops,
 };
 
-static int bfin_i2s_drv_probe(struct platform_device *pdev)
+static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
+       struct sport_device *sport_handle;
+       int ret;
+
+       /* configure SPORT for I2S */
+       sport_handle = sport_init(pdev, 4, 2 * sizeof(u32),
+               sizeof(struct bf5xx_i2s_port));
+       if (!sport_handle)
+               return -ENODEV;
+
+       /* register with the ASoC layers */
+       ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
+       if (ret) {
+               pr_err("Failed to register DAI: %d\n", ret);
+               sport_done(sport_handle);
+               return ret;
+       }
+
+       return 0;
 }
 
-static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev)
+static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
 {
+       struct sport_device *sport_handle = platform_get_drvdata(pdev);
+
+       pr_debug("%s enter\n", __func__);
+
        snd_soc_unregister_dai(&pdev->dev);
+       sport_done(sport_handle);
+
        return 0;
 }
 
 static struct platform_driver bfin_i2s_driver = {
-       .probe = bfin_i2s_drv_probe,
-       .remove = __devexit_p(bfin_i2s_drv_remove),
-
+       .probe  = bf5xx_i2s_probe,
+       .remove = __devexit_p(bf5xx_i2s_remove),
        .driver = {
-               .name = "bf5xx-i2s",
+               .name = "bfin-i2s",
                .owner = THIS_MODULE,
        },
 };