Merge branch 'fix/asoc' into for-linus
[pandora-kernel.git] / sound / soc / pxa / pxa-ssp.c
index e69397f..544fd95 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
  * SSP audio private data
  */
 struct ssp_priv {
-       struct ssp_dev dev;
+       struct ssp_device *ssp;
        unsigned int sysclk;
        int dai_fmt;
 #ifdef CONFIG_PM
-       struct ssp_state state;
+       uint32_t        cr0;
+       uint32_t        cr1;
+       uint32_t        to;
+       uint32_t        psp;
 #endif
 };
 
@@ -61,6 +65,22 @@ static void dump_registers(struct ssp_device *ssp)
                 ssp_read_reg(ssp, SSACD));
 }
 
+static void ssp_enable(struct ssp_device *ssp)
+{
+       uint32_t sscr0;
+
+       sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE;
+       __raw_writel(sscr0, ssp->mmio_base + SSCR0);
+}
+
+static void ssp_disable(struct ssp_device *ssp)
+{
+       uint32_t sscr0;
+
+       sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE;
+       __raw_writel(sscr0, ssp->mmio_base + SSCR0);
+}
+
 struct pxa2xx_pcm_dma_data {
        struct pxa2xx_pcm_dma_params params;
        char name[20];
@@ -94,19 +114,17 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_device *ssp = priv->ssp;
        int ret = 0;
 
        if (!cpu_dai->active) {
-               priv->dev.port = cpu_dai->id + 1;
-               priv->dev.irq = NO_IRQ;
-               clk_enable(priv->dev.ssp->clk);
-               ssp_disable(&priv->dev);
+               clk_enable(ssp->clk);
+               ssp_disable(ssp);
        }
 
-       if (cpu_dai->dma_data) {
-               kfree(cpu_dai->dma_data);
-               cpu_dai->dma_data = NULL;
-       }
+       kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
+       snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
+
        return ret;
 }
 
@@ -116,16 +134,15 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_device *ssp = priv->ssp;
 
        if (!cpu_dai->active) {
-               ssp_disable(&priv->dev);
-               clk_disable(priv->dev.ssp->clk);
+               ssp_disable(ssp);
+               clk_disable(ssp->clk);
        }
 
-       if (cpu_dai->dma_data) {
-               kfree(cpu_dai->dma_data);
-               cpu_dai->dma_data = NULL;
-       }
+       kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
+       snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
 }
 
 #ifdef CONFIG_PM
@@ -133,27 +150,39 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
 static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_device *ssp = priv->ssp;
 
        if (!cpu_dai->active)
-               clk_enable(priv->dev.ssp->clk);
+               clk_enable(ssp->clk);
 
-       ssp_save_state(&priv->dev, &priv->state);
-       clk_disable(priv->dev.ssp->clk);
+       priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0);
+       priv->cr1 = __raw_readl(ssp->mmio_base + SSCR1);
+       priv->to  = __raw_readl(ssp->mmio_base + SSTO);
+       priv->psp = __raw_readl(ssp->mmio_base + SSPSP);
 
+       ssp_disable(ssp);
+       clk_disable(ssp->clk);
        return 0;
 }
 
 static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_device *ssp = priv->ssp;
+       uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
 
-       clk_enable(priv->dev.ssp->clk);
-       ssp_restore_state(&priv->dev, &priv->state);
+       clk_enable(ssp->clk);
+
+       __raw_writel(sssr, ssp->mmio_base + SSSR);
+       __raw_writel(priv->cr0 & ~SSCR0_SSE, ssp->mmio_base + SSCR0);
+       __raw_writel(priv->cr1, ssp->mmio_base + SSCR1);
+       __raw_writel(priv->to,  ssp->mmio_base + SSTO);
+       __raw_writel(priv->psp, ssp->mmio_base + SSPSP);
 
        if (cpu_dai->active)
-               ssp_enable(&priv->dev);
+               ssp_enable(ssp);
        else
-               clk_disable(priv->dev.ssp->clk);
+               clk_disable(ssp->clk);
 
        return 0;
 }
@@ -203,7 +232,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        int clk_id, unsigned int freq, int dir)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        int val;
 
        u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
@@ -244,11 +273,11 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        /* The SSP clock must be disabled when changing SSP clock mode
         * on PXA2xx.  On PXA3xx it must be enabled when doing so. */
        if (!cpu_is_pxa3xx())
-               clk_disable(priv->dev.ssp->clk);
+               clk_disable(ssp->clk);
        val = ssp_read_reg(ssp, SSCR0) | sscr0;
        ssp_write_reg(ssp, SSCR0, val);
        if (!cpu_is_pxa3xx())
-               clk_enable(priv->dev.ssp->clk);
+               clk_enable(ssp->clk);
 
        return 0;
 }
@@ -260,7 +289,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
        int div_id, int div)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        int val;
 
        switch (div_id) {
@@ -311,7 +340,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
        int source, unsigned int freq_in, unsigned int freq_out)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
 
 #if defined(CONFIG_PXA3xx)
@@ -380,7 +409,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
        unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        u32 sscr0;
 
        sscr0 = ssp_read_reg(ssp, SSCR0);
@@ -415,7 +444,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
        int tristate)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        u32 sscr1;
 
        sscr1 = ssp_read_reg(ssp, SSCR1);
@@ -437,7 +466,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        u32 sscr0;
        u32 sscr1;
        u32 sspsp;
@@ -532,25 +561,29 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        int chn = params_channels(params);
        u32 sscr0;
        u32 sspsp;
        int width = snd_pcm_format_physical_width(params_format(params));
        int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
+       struct pxa2xx_pcm_dma_params *dma_data;
+
+       dma_data = snd_soc_dai_get_dma_data(dai, substream);
 
        /* generate correct DMA params */
-       if (cpu_dai->dma_data)
-               kfree(cpu_dai->dma_data);
+       kfree(dma_data);
 
        /* Network mode with one active slot (ttsa == 1) can be used
         * to force 16-bit frame width on the wire (for S16_LE), even
         * with two channels. Use 16-bit DMA transfers for this case.
         */
-       cpu_dai->dma_data = ssp_get_dma_params(ssp,
+       dma_data = ssp_get_dma_params(ssp,
                        ((chn == 2) && (ttsa != 1)) || (width == 32),
                        substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
        /* we can only change the settings if the port is not in use */
        if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
                return 0;
@@ -642,12 +675,12 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        int ret = 0;
        struct ssp_priv *priv = cpu_dai->private_data;
-       struct ssp_device *ssp = priv->dev.ssp;
+       struct ssp_device *ssp = priv->ssp;
        int val;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
-               ssp_enable(&priv->dev);
+               ssp_enable(ssp);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                val = ssp_read_reg(ssp, SSCR1);
@@ -666,7 +699,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
                else
                        val |= SSCR1_RSRE;
                ssp_write_reg(ssp, SSCR1, val);
-               ssp_enable(&priv->dev);
+               ssp_enable(ssp);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
                val = ssp_read_reg(ssp, SSCR1);
@@ -677,7 +710,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
                ssp_write_reg(ssp, SSCR1, val);
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               ssp_disable(&priv->dev);
+               ssp_disable(ssp);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                val = ssp_read_reg(ssp, SSCR1);
@@ -707,8 +740,8 @@ static int pxa_ssp_probe(struct platform_device *pdev,
        if (!priv)
                return -ENOMEM;
 
-       priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio");
-       if (priv->dev.ssp == NULL) {
+       priv->ssp = ssp_request(dai->id + 1, "SoC audio");
+       if (priv->ssp == NULL) {
                ret = -ENODEV;
                goto err_priv;
        }
@@ -727,7 +760,7 @@ static void pxa_ssp_remove(struct platform_device *pdev,
                              struct snd_soc_dai *dai)
 {
        struct ssp_priv *priv = dai->private_data;
-       ssp_free(priv->dev.ssp);
+       ssp_free(priv->ssp);
 }
 
 #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\