summaryrefslogtreecommitdiff
path: root/sound/soc/ux500/ux500_msp_dai.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ux500/ux500_msp_dai.c')
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c233
1 files changed, 82 insertions, 151 deletions
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index c6fb5cce980e..7798957c6504 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) ST-Ericsson SA 2012
*
* Author: Ola Lilja <ola.o.lilja@stericsson.com>,
* Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
- *
- * License terms:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
*/
#include <linux/module.h>
@@ -17,12 +12,13 @@
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/dbx500-prcmu.h>
-#include <linux/platform_data/asoc-ux500-msp.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
+#include <sound/dmaengine_pcm.h>
#include "ux500_msp_i2s.h"
#include "ux500_msp_dai.h"
@@ -131,6 +127,7 @@ static int setup_pcm_framing(struct snd_soc_dai *dai, unsigned int rate,
struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
u32 frame_length = MSP_FRAME_LEN_1;
+
prot_desc->frame_width = 0;
switch (drvdata->slots) {
@@ -185,14 +182,14 @@ static int setup_clocking(struct snd_soc_dai *dai,
default:
dev_err(dai->dev,
- "%s: Error: Unsopported inversion (fmt = 0x%x)!\n",
+ "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
__func__, fmt);
return -EINVAL;
}
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+ case SND_SOC_DAIFMT_BC_FC:
dev_dbg(dai->dev, "%s: Codec is master.\n", __func__);
msp_config->iodelay = 0x20;
@@ -204,7 +201,7 @@ static int setup_clocking(struct snd_soc_dai *dai,
break;
- case SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_BP_FP:
dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__);
msp_config->tx_clk_sel = TX_CLK_SEL_SRG;
@@ -216,7 +213,7 @@ static int setup_clocking(struct snd_soc_dai *dai,
break;
default:
- dev_err(dai->dev, "%s: Error: Unsopported master (fmt = 0x%x)!\n",
+ dev_err(dai->dev, "%s: Error: Unsupported master (fmt = 0x%x)!\n",
__func__, fmt);
return -EINVAL;
@@ -328,15 +325,15 @@ static int setup_msp_config(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__,
runtime->rate, runtime->channels);
switch (fmt &
- (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) {
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BP_FP:
dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
msp_config->default_protdesc = 1;
msp_config->protocol = MSP_I2S_PROTOCOL;
break;
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC:
dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
msp_config->data_size = MSP_DATA_BITS_16;
@@ -348,10 +345,10 @@ static int setup_msp_config(struct snd_pcm_substream *substream,
break;
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
- case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BC_FC:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BP_FP:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BC_FC:
dev_dbg(dai->dev, "%s: PCM format.\n", __func__);
msp_config->data_size = MSP_DATA_BITS_16;
@@ -372,7 +369,7 @@ static int setup_msp_config(struct snd_pcm_substream *substream,
break;
default:
- dev_err(dai->dev, "%s: Error: Unsopported format (%d)!\n",
+ dev_err(dai->dev, "%s: Error: Unsupported format (%d)!\n",
__func__, fmt);
return -EINVAL;
}
@@ -477,10 +474,11 @@ static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
}
/* Set OPP-level */
- if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) &&
+ if ((drvdata->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) &&
(drvdata->msp->f_bitclk > 19200000)) {
/* If the bit-clock is higher than 19.2MHz, Vape should be
- * run in 100% OPP. Only when bit-clock is used (MSP master) */
+ * run in 100% OPP. Only when bit-clock is used (MSP master)
+ */
prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
"ux500-msp-i2s", 100);
drvdata->vape_opp_constraint = 1;
@@ -520,9 +518,9 @@ static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
slots_active = hweight32(mask);
dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
- snd_pcm_hw_constraint_minmax(runtime,
+ snd_pcm_hw_constraint_single(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS,
- slots_active, slots_active);
+ slots_active);
break;
default:
@@ -543,13 +541,13 @@ static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
- SND_SOC_DAIFMT_MASTER_MASK)) {
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
- case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) {
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BP_FP:
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BP_FP:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BC_FC:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BC_FC:
break;
default:
@@ -654,21 +652,38 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
return ret;
}
-static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
+static int ux500_msp_dai_of_probe(struct snd_soc_dai *dai)
{
struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+ struct snd_dmaengine_dai_dma_data *playback_dma_data;
+ struct snd_dmaengine_dai_dma_data *capture_dma_data;
+
+ playback_dma_data = devm_kzalloc(dai->dev,
+ sizeof(*playback_dma_data),
+ GFP_KERNEL);
+ if (!playback_dma_data)
+ return -ENOMEM;
+
+ capture_dma_data = devm_kzalloc(dai->dev,
+ sizeof(*capture_dma_data),
+ GFP_KERNEL);
+ if (!capture_dma_data)
+ return -ENOMEM;
- dai->playback_dma_data = &drvdata->msp->playback_dma_data;
- dai->capture_dma_data = &drvdata->msp->capture_dma_data;
+ playback_dma_data->addr = drvdata->msp->tx_rx_addr;
+ capture_dma_data->addr = drvdata->msp->tx_rx_addr;
- drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
- drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
+ playback_dma_data->maxburst = 4;
+ capture_dma_data->maxburst = 4;
+
+ snd_soc_dai_init_dma_data(dai, playback_dma_data, capture_dma_data);
return 0;
}
-static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
+static const struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
{
+ .probe = ux500_msp_dai_of_probe,
.set_sysclk = ux500_msp_dai_set_dai_sysclk,
.set_fmt = ux500_msp_dai_set_dai_fmt,
.set_tdm_slot = ux500_msp_dai_set_tdm_slot,
@@ -680,91 +695,21 @@ static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
}
};
-static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
- {
- .name = "ux500-msp-i2s.0",
- .probe = ux500_msp_dai_probe,
- .id = 0,
- .suspend = NULL,
- .resume = NULL,
- .playback = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .capture = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .ops = ux500_msp_dai_ops,
- },
- {
- .name = "ux500-msp-i2s.1",
- .probe = ux500_msp_dai_probe,
- .id = 1,
- .suspend = NULL,
- .resume = NULL,
- .playback = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .capture = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .ops = ux500_msp_dai_ops,
- },
- {
- .name = "ux500-msp-i2s.2",
- .id = 2,
- .probe = ux500_msp_dai_probe,
- .suspend = NULL,
- .resume = NULL,
- .playback = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .capture = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .ops = ux500_msp_dai_ops,
- },
- {
- .name = "ux500-msp-i2s.3",
- .probe = ux500_msp_dai_probe,
- .id = 3,
- .suspend = NULL,
- .resume = NULL,
- .playback = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .capture = {
- .channels_min = UX500_MSP_MIN_CHANNELS,
- .channels_max = UX500_MSP_MAX_CHANNELS,
- .rates = UX500_I2S_RATES,
- .formats = UX500_I2S_FORMATS,
- },
- .ops = ux500_msp_dai_ops,
- },
+static struct snd_soc_dai_driver ux500_msp_dai_drv = {
+ .playback.channels_min = UX500_MSP_MIN_CHANNELS,
+ .playback.channels_max = UX500_MSP_MAX_CHANNELS,
+ .playback.rates = UX500_I2S_RATES,
+ .playback.formats = UX500_I2S_FORMATS,
+ .capture.channels_min = UX500_MSP_MIN_CHANNELS,
+ .capture.channels_max = UX500_MSP_MAX_CHANNELS,
+ .capture.rates = UX500_I2S_RATES,
+ .capture.formats = UX500_I2S_FORMATS,
+ .ops = ux500_msp_dai_ops,
};
static const struct snd_soc_component_driver ux500_msp_component = {
- .name = "ux500-msp",
+ .name = "ux500-msp",
+ .legacy_dai_naming = 1,
};
@@ -773,9 +718,6 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
struct ux500_msp_i2s_drvdata *drvdata;
int ret = 0;
- dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__,
- pdev->name);
-
drvdata = devm_kzalloc(&pdev->dev,
sizeof(struct ux500_msp_i2s_drvdata),
GFP_KERNEL);
@@ -791,7 +733,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
if (IS_ERR(drvdata->reg_vape)) {
- ret = (int)PTR_ERR(drvdata->reg_vape);
+ ret = PTR_ERR(drvdata->reg_vape);
dev_err(&pdev->dev,
"%s: ERROR: Failed to get Vape supply (%d)!\n",
__func__, ret);
@@ -799,38 +741,39 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
}
prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
- drvdata->pclk = clk_get(&pdev->dev, "apb_pclk");
+ drvdata->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(drvdata->pclk)) {
- ret = (int)PTR_ERR(drvdata->pclk);
- dev_err(&pdev->dev, "%s: ERROR: clk_get of pclk failed (%d)!\n",
+ ret = PTR_ERR(drvdata->pclk);
+ dev_err(&pdev->dev,
+ "%s: ERROR: devm_clk_get of pclk failed (%d)!\n",
__func__, ret);
- goto err_pclk;
+ return ret;
}
- drvdata->clk = clk_get(&pdev->dev, NULL);
+ drvdata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->clk)) {
- ret = (int)PTR_ERR(drvdata->clk);
- dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n",
+ ret = PTR_ERR(drvdata->clk);
+ dev_err(&pdev->dev,
+ "%s: ERROR: devm_clk_get failed (%d)!\n",
__func__, ret);
- goto err_clk;
+ return ret;
}
- ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
- pdev->dev.platform_data);
+ ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp);
if (!drvdata->msp) {
dev_err(&pdev->dev,
"%s: ERROR: Failed to init MSP-struct (%d)!",
__func__, ret);
- goto err_init_msp;
+ return ret;
}
dev_set_drvdata(&pdev->dev, drvdata);
ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component,
- &ux500_msp_dai_drv[drvdata->msp->id], 1);
+ &ux500_msp_dai_drv, 1);
if (ret < 0) {
dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
__func__, drvdata->msp->id);
- goto err_init_msp;
+ return ret;
}
ret = ux500_pcm_register_platform(pdev);
@@ -845,17 +788,10 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
err_reg_plat:
snd_soc_unregister_component(&pdev->dev);
-err_init_msp:
- clk_put(drvdata->clk);
-err_clk:
- clk_put(drvdata->pclk);
-err_pclk:
- devm_regulator_put(drvdata->reg_vape);
-
return ret;
}
-static int ux500_msp_drv_remove(struct platform_device *pdev)
+static void ux500_msp_drv_remove(struct platform_device *pdev)
{
struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
@@ -863,26 +799,20 @@ static int ux500_msp_drv_remove(struct platform_device *pdev)
snd_soc_unregister_component(&pdev->dev);
- devm_regulator_put(drvdata->reg_vape);
prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
- clk_put(drvdata->clk);
- clk_put(drvdata->pclk);
-
ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
-
- return 0;
}
static const struct of_device_id ux500_msp_i2s_match[] = {
{ .compatible = "stericsson,ux500-msp-i2s", },
{},
};
+MODULE_DEVICE_TABLE(of, ux500_msp_i2s_match);
static struct platform_driver msp_i2s_driver = {
.driver = {
.name = "ux500-msp-i2s",
- .owner = THIS_MODULE,
.of_match_table = ux500_msp_i2s_match,
},
.probe = ux500_msp_drv_probe,
@@ -890,4 +820,5 @@ static struct platform_driver msp_i2s_driver = {
};
module_platform_driver(msp_i2s_driver);
+MODULE_DESCRIPTION("ASoC Ux500 I2S driver");
MODULE_LICENSE("GPL v2");