]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - sound/soc/davinci/davinci-i2s.c
ASoC: DaVinci: McASP FIFO related updates
[mirror_ubuntu-bionic-kernel.git] / sound / soc / davinci / davinci-i2s.c
index 88ccef79a5ebe12a9e711edc8344833346af096c..2ab809359c08a487a8bb4c75a1a631b228de697d 100644 (file)
@@ -22,6 +22,8 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
+#include <mach/asp.h>
+
 #include "davinci-pcm.h"
 
 
@@ -95,22 +97,19 @@ enum {
        DAVINCI_MCBSP_WORD_32,
 };
 
-static struct davinci_pcm_dma_params davinci_i2s_pcm_out = {
-       .name = "I2S PCM Stereo out",
-};
-
-static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
-       .name = "I2S PCM Stereo in",
-};
-
 struct davinci_mcbsp_dev {
+       /*
+        * dma_params must be first because rtd->dai->cpu_dai->private_data
+        * is cast to a pointer of an array of struct davinci_pcm_dma_params in
+        * davinci_pcm_open.
+        */
+       struct davinci_pcm_dma_params   dma_params[2];
        void __iomem                    *base;
 #define MOD_DSP_A      0
 #define MOD_DSP_B      1
        int                             mode;
        u32                             pcr;
        struct clk                      *clk;
-       struct davinci_pcm_dma_params   *dma_params[2];
 };
 
 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -213,14 +212,6 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
        toggle_clock(dev, playback);
 }
 
-static int davinci_i2s_startup(struct snd_pcm_substream *substream,
-                              struct snd_soc_dai *cpu_dai)
-{
-       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
-       cpu_dai->dma_data = dev->dma_params[substream->stream];
-       return 0;
-}
-
 #define DEFAULT_BITPERSAMPLE   16
 
 static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
@@ -351,9 +342,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = dai->private_data;
+       struct davinci_pcm_dma_params *dma_params =
+                                       &dev->dma_params[substream->stream];
        struct snd_interval *i = NULL;
        int mcbsp_word_length;
        unsigned int rcr, xcr, srgr;
@@ -405,6 +396,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       dma_params->acnt  = dma_params->data_type;
+       dma_params->fifo_level = 0;
+
        rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
        xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
 
@@ -423,8 +417,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
 static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = dai->private_data;
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        davinci_mcbsp_stop(dev, playback);
        if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
@@ -437,8 +430,7 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
 static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = dai->private_data;
        int ret = 0;
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
@@ -464,21 +456,45 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = dai->private_data;
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        davinci_mcbsp_stop(dev, playback);
 }
 
-static int davinci_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+#define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
+
+static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+       .shutdown       = davinci_i2s_shutdown,
+       .prepare        = davinci_i2s_prepare,
+       .trigger        = davinci_i2s_trigger,
+       .hw_params      = davinci_i2s_hw_params,
+       .set_fmt        = davinci_i2s_set_dai_fmt,
+
+};
+
+struct snd_soc_dai davinci_i2s_dai = {
+       .name = "davinci-i2s",
+       .id = 0,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = &davinci_i2s_dai_ops,
+
+};
+EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+
+static int davinci_i2s_probe(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
+       struct snd_platform_data *pdata = pdev->dev.platform_data;
        struct davinci_mcbsp_dev *dev;
-       struct resource *mem, *ioarea;
-       struct evm_snd_platform_data *pdata;
+       struct resource *mem, *ioarea, *res;
        int ret;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -500,8 +516,6 @@ static int davinci_i2s_probe(struct platform_device *pdev,
                goto err_release_region;
        }
 
-       cpu_dai->private_data = dev;
-
        dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                ret = -ENODEV;
@@ -510,18 +524,35 @@ static int davinci_i2s_probe(struct platform_device *pdev,
        clk_enable(dev->clk);
 
        dev->base = (void __iomem *)IO_ADDRESS(mem->start);
-       pdata = pdev->dev.platform_data;
 
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
            (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
 
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
            (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
 
+       /* first TX, then RX */
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENXIO;
+               goto err_free_mem;
+       }
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENXIO;
+               goto err_free_mem;
+       }
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
+
+       davinci_i2s_dai.private_data = dev;
+       ret = snd_soc_register_dai(&davinci_i2s_dai);
+       if (ret != 0)
+               goto err_free_mem;
+
        return 0;
 
 err_free_mem:
@@ -532,64 +563,40 @@ err_release_region:
        return ret;
 }
 
-static void davinci_i2s_remove(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
+static int davinci_i2s_remove(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
-       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
        struct resource *mem;
 
+       snd_soc_unregister_dai(&davinci_i2s_dai);
        clk_disable(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
-
        kfree(dev);
-
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, (mem->end - mem->start) + 1);
-}
 
-#define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
-
-static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
-       .startup        = davinci_i2s_startup,
-       .shutdown       = davinci_i2s_shutdown,
-       .prepare        = davinci_i2s_prepare,
-       .trigger        = davinci_i2s_trigger,
-       .hw_params      = davinci_i2s_hw_params,
-       .set_fmt        = davinci_i2s_set_dai_fmt,
-};
+       return 0;
+}
 
-struct snd_soc_dai davinci_i2s_dai = {
-       .name = "davinci-i2s",
-       .id = 0,
-       .probe = davinci_i2s_probe,
-       .remove = davinci_i2s_remove,
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
-       .ops = &davinci_i2s_dai_ops,
+static struct platform_driver davinci_mcbsp_driver = {
+       .probe          = davinci_i2s_probe,
+       .remove         = davinci_i2s_remove,
+       .driver         = {
+               .name   = "davinci-asp",
+               .owner  = THIS_MODULE,
+       },
 };
-EXPORT_SYMBOL_GPL(davinci_i2s_dai);
 
 static int __init davinci_i2s_init(void)
 {
-       return snd_soc_register_dai(&davinci_i2s_dai);
+       return platform_driver_register(&davinci_mcbsp_driver);
 }
 module_init(davinci_i2s_init);
 
 static void __exit davinci_i2s_exit(void)
 {
-       snd_soc_unregister_dai(&davinci_i2s_dai);
+       platform_driver_unregister(&davinci_mcbsp_driver);
 }
 module_exit(davinci_i2s_exit);