]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - sound/soc/davinci/davinci-mcasp.c
ASoC: davinci-mcasp: Add location for data port registers to DT
[karo-tx-linux.git] / sound / soc / davinci / davinci-mcasp.c
index 32ddb7fe5034865a7f13dc7243f1f8161482c7f2..806bec34e4d9bd644e052b0d28b3181ac4b920e4 100644 (file)
@@ -1001,18 +1001,40 @@ static const struct snd_soc_component_driver davinci_mcasp_component = {
        .name           = "davinci-mcasp",
 };
 
+/* Some HW specific values and defaults. The rest is filled in from DT. */
+static struct snd_platform_data dm646x_mcasp_pdata = {
+       .tx_dma_offset = 0x400,
+       .rx_dma_offset = 0x400,
+       .asp_chan_q = EVENTQ_0,
+       .version = MCASP_VERSION_1,
+};
+
+static struct snd_platform_data da830_mcasp_pdata = {
+       .tx_dma_offset = 0x2000,
+       .rx_dma_offset = 0x2000,
+       .asp_chan_q = EVENTQ_0,
+       .version = MCASP_VERSION_2,
+};
+
+static struct snd_platform_data omap2_mcasp_pdata = {
+       .tx_dma_offset = 0,
+       .rx_dma_offset = 0,
+       .asp_chan_q = EVENTQ_0,
+       .version = MCASP_VERSION_3,
+};
+
 static const struct of_device_id mcasp_dt_ids[] = {
        {
                .compatible = "ti,dm646x-mcasp-audio",
-               .data = (void *)MCASP_VERSION_1,
+               .data = &dm646x_mcasp_pdata,
        },
        {
                .compatible = "ti,da830-mcasp-audio",
-               .data = (void *)MCASP_VERSION_2,
+               .data = &da830_mcasp_pdata,
        },
        {
                .compatible = "ti,omap2-mcasp-audio",
-               .data = (void *)MCASP_VERSION_3,
+               .data = &omap2_mcasp_pdata,
        },
        { /* sentinel */ }
 };
@@ -1035,20 +1057,13 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
                pdata = pdev->dev.platform_data;
                return pdata;
        } else if (match) {
-               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-               if (!pdata) {
-                       ret = -ENOMEM;
-                       goto nodata;
-               }
+               pdata = (struct snd_platform_data *) match->data;
        } else {
                /* control shouldn't reach here. something is wrong */
                ret = -EINVAL;
                goto nodata;
        }
 
-       if (match->data)
-               pdata->version = (u8)((int)match->data);
-
        ret = of_property_read_u32(np, "op-mode", &val);
        if (ret >= 0)
                pdata->op_mode = val;
@@ -1124,7 +1139,7 @@ nodata:
 static int davinci_mcasp_probe(struct platform_device *pdev)
 {
        struct davinci_pcm_dma_params *dma_data;
-       struct resource *mem, *ioarea, *res;
+       struct resource *mem, *ioarea, *res, *dat;
        struct snd_platform_data *pdata;
        struct davinci_audio_dev *dev;
        int ret;
@@ -1145,10 +1160,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
        if (!mem) {
-               dev_err(&pdev->dev, "no mem resource?\n");
-               return -ENODEV;
+               dev_warn(dev->dev,
+                        "\"mpu\" mem resource not found, using index 0\n");
+               mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!mem) {
+                       dev_err(&pdev->dev, "no mem resource?\n");
+                       return -ENODEV;
+               }
        }
 
        ioarea = devm_request_mem_region(&pdev->dev, mem->start,
@@ -1182,13 +1202,16 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dev->rxnumevt = pdata->rxnumevt;
        dev->dev = &pdev->dev;
 
+       dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+       if (!dat)
+               dat = mem;
+
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
        dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
-       dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
-                                                       mem->start);
+       dma_data->dma_addr = dat->start + pdata->tx_dma_offset;
 
        /* first TX, then RX */
        res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -1205,8 +1228,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data->ram_chan_q = pdata->ram_chan_q;
        dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
-       dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
-                                                       mem->start);
+       dma_data->dma_addr = dat->start + pdata->rx_dma_offset;
 
        res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
        if (!res) {
@@ -1251,12 +1273,51 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int davinci_mcasp_suspend(struct device *dev)
+{
+       struct davinci_audio_dev *a = dev_get_drvdata(dev);
+       void __iomem *base = a->base;
+
+       a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG);
+       a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG);
+       a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG);
+       a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG);
+       a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG);
+       a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG);
+       a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG);
+
+       return 0;
+}
+
+static int davinci_mcasp_resume(struct device *dev)
+{
+       struct davinci_audio_dev *a = dev_get_drvdata(dev);
+       void __iomem *base = a->base;
+
+       mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl);
+       mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl);
+       mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt);
+       mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt);
+       mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl);
+       mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl);
+       mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir);
+
+       return 0;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops,
+                 davinci_mcasp_suspend,
+                 davinci_mcasp_resume);
+
 static struct platform_driver davinci_mcasp_driver = {
        .probe          = davinci_mcasp_probe,
        .remove         = davinci_mcasp_remove,
        .driver         = {
                .name   = "davinci-mcasp",
                .owner  = THIS_MODULE,
+               .pm     = &davinci_mcasp_pm_ops,
                .of_match_table = mcasp_dt_ids,
        },
 };
@@ -1266,4 +1327,3 @@ module_platform_driver(davinci_mcasp_driver);
 MODULE_AUTHOR("Steve Chen");
 MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
 MODULE_LICENSE("GPL");
-