summaryrefslogtreecommitdiff
path: root/sound/soc/davinci/davinci-mcasp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
-rw-r--r--sound/soc/davinci/davinci-mcasp.c174
1 files changed, 152 insertions, 22 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index ce5e5cd254dd..c3eae1d8e077 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -21,7 +21,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/io.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -782,20 +785,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (!dev->clk_active) {
- clk_enable(dev->clk);
- dev->clk_active = 1;
- }
+ ret = pm_runtime_get_sync(dev->dev);
+ if (IS_ERR_VALUE(ret))
+ dev_err(dev->dev, "pm_runtime_get_sync() failed\n");
davinci_mcasp_start(dev, substream->stream);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
davinci_mcasp_stop(dev, substream->stream);
- if (dev->clk_active) {
- clk_disable(dev->clk);
- dev->clk_active = 0;
- }
-
+ ret = pm_runtime_put_sync(dev->dev);
+ if (IS_ERR_VALUE(ret))
+ dev_err(dev->dev, "pm_runtime_put_sync() failed\n");
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -865,6 +865,114 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
};
+static const struct of_device_id mcasp_dt_ids[] = {
+ {
+ .compatible = "ti,dm646x-mcasp-audio",
+ .data = (void *)MCASP_VERSION_1,
+ },
+ {
+ .compatible = "ti,da830-mcasp-audio",
+ .data = (void *)MCASP_VERSION_2,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
+
+static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
+ struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct snd_platform_data *pdata = NULL;
+ const struct of_device_id *match =
+ of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev);
+
+ const u32 *of_serial_dir32;
+ u8 *of_serial_dir;
+ u32 val;
+ int i, ret = 0;
+
+ if (pdev->dev.platform_data) {
+ 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;
+ }
+ } 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;
+
+ ret = of_property_read_u32(np, "tdm-slots", &val);
+ if (ret >= 0)
+ pdata->tdm_slots = val;
+
+ ret = of_property_read_u32(np, "num-serializer", &val);
+ if (ret >= 0)
+ pdata->num_serializer = val;
+
+ of_serial_dir32 = of_get_property(np, "serial-dir", &val);
+ val /= sizeof(u32);
+ if (val != pdata->num_serializer) {
+ dev_err(&pdev->dev,
+ "num-serializer(%d) != serial-dir size(%d)\n",
+ pdata->num_serializer, val);
+ ret = -EINVAL;
+ goto nodata;
+ }
+
+ if (of_serial_dir32) {
+ of_serial_dir = devm_kzalloc(&pdev->dev,
+ (sizeof(*of_serial_dir) * val),
+ GFP_KERNEL);
+ if (!of_serial_dir) {
+ ret = -ENOMEM;
+ goto nodata;
+ }
+
+ for (i = 0; i < pdata->num_serializer; i++)
+ of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]);
+
+ pdata->serial_dir = of_serial_dir;
+ }
+
+ ret = of_property_read_u32(np, "tx-num-evt", &val);
+ if (ret >= 0)
+ pdata->txnumevt = val;
+
+ ret = of_property_read_u32(np, "rx-num-evt", &val);
+ if (ret >= 0)
+ pdata->rxnumevt = val;
+
+ ret = of_property_read_u32(np, "sram-size-playback", &val);
+ if (ret >= 0)
+ pdata->sram_size_playback = val;
+
+ ret = of_property_read_u32(np, "sram-size-capture", &val);
+ if (ret >= 0)
+ pdata->sram_size_capture = val;
+
+ return pdata;
+
+nodata:
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error populating platform data, err %d\n",
+ ret);
+ pdata = NULL;
+ }
+ return pdata;
+}
+
static int davinci_mcasp_probe(struct platform_device *pdev)
{
struct davinci_pcm_dma_params *dma_data;
@@ -873,11 +981,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
struct davinci_audio_dev *dev;
int ret;
+ if (!pdev->dev.platform_data && !pdev->dev.of_node) {
+ dev_err(&pdev->dev, "No platform data supplied\n");
+ return -EINVAL;
+ }
+
dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev),
GFP_KERNEL);
if (!dev)
return -ENOMEM;
+ pdata = davinci_mcasp_set_pdata_from_of(pdev);
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -EINVAL;
+ }
+
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?\n");
@@ -891,13 +1010,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
return -EBUSY;
}
- pdata = pdev->dev.platform_data;
- dev->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dev->clk))
- return -ENODEV;
+ pm_runtime_enable(&pdev->dev);
- clk_enable(dev->clk);
- dev->clk_active = 1;
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ return ret;
+ }
dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
if (!dev->base) {
@@ -914,6 +1033,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dev->version = pdata->version;
dev->txnumevt = pdata->txnumevt;
dev->rxnumevt = pdata->rxnumevt;
+ dev->dev = &pdev->dev;
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_data->asp_chan_q = pdata->asp_chan_q;
@@ -952,22 +1072,31 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
if (ret != 0)
goto err_release_clk;
+
+ ret = davinci_soc_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
+ goto err_unregister_dai;
+ }
+
return 0;
+err_unregister_dai:
+ snd_soc_unregister_dai(&pdev->dev);
err_release_clk:
- clk_disable(dev->clk);
- clk_put(dev->clk);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return ret;
}
static int davinci_mcasp_remove(struct platform_device *pdev)
{
- struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
- clk_disable(dev->clk);
- clk_put(dev->clk);
- dev->clk = NULL;
+ davinci_soc_platform_unregister(&pdev->dev);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
@@ -978,6 +1107,7 @@ static struct platform_driver davinci_mcasp_driver = {
.driver = {
.name = "davinci-mcasp",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(mcasp_dt_ids),
},
};