summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-08-30 12:35:49 +0200
committerTakashi Iwai <tiwai@suse.de>2013-08-30 12:35:49 +0200
commit3fd8a8041b3775840c8f85b6338b61beb5057160 (patch)
tree2eb4fd3eae3168ae2837c4f98188fd25f62d5939 /sound
parent1c9a341bbdc14051a4d8c74ea67269786c7d3736 (diff)
parent6d52825fd4e78b251f4844f6662a3bc4e31671c7 (diff)
Merge tag 'asoc-v3.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for v3.12 A few more updates for v3.12, mostly small cleanups plus the addition of the DT bindings for kirkwood and the new i.MX S/PDIF driver.
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c2
-rw-r--r--sound/soc/codecs/dmic.c17
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c22
-rw-r--r--sound/soc/codecs/wm8904.c1
-rw-r--r--sound/soc/dwc/designware_i2s.c5
-rw-r--r--sound/soc/fsl/Kconfig10
-rw-r--r--sound/soc/fsl/Makefile2
-rw-r--r--sound/soc/fsl/fsl_spdif.c17
-rw-r--r--sound/soc/fsl/fsl_ssi.c1
-rw-r--r--sound/soc/fsl/imx-spdif.c148
-rw-r--r--sound/soc/generic/simple-card.c2
-rw-r--r--sound/soc/kirkwood/Kconfig4
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c26
-rw-r--r--sound/soc/samsung/dma.c7
-rw-r--r--sound/soc/sh/fsi.c51
-rw-r--r--sound/soc/soc-core.c9
-rw-r--r--sound/soc/soc-dapm.c9
-rw-r--r--sound/soc/soc-jack.c2
18 files changed, 245 insertions, 90 deletions
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index f23f331e9a97..a57643d6402f 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -408,7 +408,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
return 0;
fail_put_lrclk:
- dev_set_drvdata(&pdev->dev, NULL);
clk_put(info->lrclk);
fail_put_sclk:
clk_put(info->sclk);
@@ -423,7 +422,6 @@ static int ep93xx_i2s_remove(struct platform_device *pdev)
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
- dev_set_drvdata(&pdev->dev, NULL);
clk_put(info->lrclk);
clk_put(info->sclk);
clk_put(info->mclk);
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
index 66967ba6f757..b2090b2a5e2d 100644
--- a/sound/soc/codecs/dmic.c
+++ b/sound/soc/codecs/dmic.c
@@ -50,20 +50,11 @@ static const struct snd_soc_dapm_route intercon[] = {
{"DMIC AIF", NULL, "DMic"},
};
-static int dmic_probe(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets,
- ARRAY_SIZE(dmic_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
- snd_soc_dapm_new_widgets(dapm);
-
- return 0;
-}
-
static struct snd_soc_codec_driver soc_dmic = {
- .probe = dmic_probe,
+ .dapm_widgets = dmic_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets),
+ .dapm_routes = intercon,
+ .num_dapm_routes = ARRAY_SIZE(intercon),
};
static int dmic_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 17df4e32feac..2ed57d4aa445 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -338,18 +338,6 @@ static inline int aic32x4_get_divs(int mclk, int rate)
return -EINVAL;
}
-static int aic32x4_add_widgets(struct snd_soc_codec *codec)
-{
- snd_soc_dapm_new_controls(&codec->dapm, aic32x4_dapm_widgets,
- ARRAY_SIZE(aic32x4_dapm_widgets));
-
- snd_soc_dapm_add_routes(&codec->dapm, aic32x4_dapm_routes,
- ARRAY_SIZE(aic32x4_dapm_routes));
-
- snd_soc_dapm_new_widgets(&codec->dapm);
- return 0;
-}
-
static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
@@ -683,9 +671,6 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
}
aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_codec_controls(codec, aic32x4_snd_controls,
- ARRAY_SIZE(aic32x4_snd_controls));
- aic32x4_add_widgets(codec);
/*
* Workaround: for an unknown reason, the ADC needs to be powered up
@@ -714,6 +699,13 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
.suspend = aic32x4_suspend,
.resume = aic32x4_resume,
.set_bias_level = aic32x4_set_bias_level,
+
+ .controls = aic32x4_snd_controls,
+ .num_controls = ARRAY_SIZE(aic32x4_snd_controls),
+ .dapm_widgets = aic32x4_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets),
+ .dapm_routes = aic32x4_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
};
static int aic32x4_i2c_probe(struct i2c_client *i2c,
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 91dfbfeda6f8..4dfa8dceeabf 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1202,7 +1202,6 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
break;
}
- snd_soc_dapm_new_widgets(dapm);
return 0;
}
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index 70eb37a5dd16..25c31f1655f6 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -421,13 +421,11 @@ static int dw_i2s_probe(struct platform_device *pdev)
dw_i2s_dai, 1);
if (ret != 0) {
dev_err(&pdev->dev, "not able to register dai\n");
- goto err_set_drvdata;
+ goto err_clk_disable;
}
return 0;
-err_set_drvdata:
- dev_set_drvdata(&pdev->dev, NULL);
err_clk_disable:
clk_disable(dev->clk);
err_clk_put:
@@ -440,7 +438,6 @@ static int dw_i2s_remove(struct platform_device *pdev)
struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
- dev_set_drvdata(&pdev->dev, NULL);
clk_put(dev->clk);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index cd088cc8c866..704e246f5b1e 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -193,6 +193,16 @@ config SND_SOC_IMX_SGTL5000
Say Y if you want to add support for SoC audio on an i.MX board with
a sgtl5000 codec.
+config SND_SOC_IMX_SPDIF
+ tristate "SoC Audio support for i.MX boards with S/PDIF"
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_SPDIF
+ select SND_SOC_SPDIF
+ help
+ SoC Audio support for i.MX boards with S/PDIF
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a S/DPDIF.
+
config SND_SOC_IMX_MC13783
tristate "SoC Audio support for I.MX boards with mc13783"
depends on MFD_MC13783 && ARM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 4b5970e014dd..e2aaff717f8a 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -45,6 +45,7 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
snd-soc-wm1133-ev1-objs := wm1133-ev1.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
snd-soc-imx-wm8962-objs := imx-wm8962.o
+snd-soc-imx-spdif-objs :=imx-spdif.o
snd-soc-imx-mc13783-objs := imx-mc13783.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
@@ -53,4 +54,5 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
+obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 42a43820d993..e93dc0dfb0d9 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -555,7 +555,6 @@ struct snd_soc_dai_ops fsl_spdif_dai_ops = {
/*
- * ============================================
* FSL SPDIF IEC958 controller(mixer) functions
*
* Channel status get/put control
@@ -563,7 +562,6 @@ struct snd_soc_dai_ops fsl_spdif_dai_ops = {
* Valid bit value get control
* DPLL lock status get control
* User bit sync mode selection control
- * ============================================
*/
static int fsl_spdif_info(struct snd_kcontrol *kcontrol,
@@ -942,11 +940,7 @@ static const struct snd_soc_component_driver fsl_spdif_component = {
.name = "fsl-spdif",
};
-/*
- * ================
- * FSL SPDIF REGMAP
- * ================
- */
+/* FSL SPDIF REGMAP */
static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
{
@@ -1119,10 +1113,8 @@ static int fsl_spdif_probe(struct platform_device *pdev)
}
regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(regs)) {
- dev_err(&pdev->dev, "could not map device resources\n");
+ if (IS_ERR(regs))
return PTR_ERR(regs);
- }
spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
"core", regs, &fsl_spdif_regmap_config);
@@ -1184,7 +1176,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
&spdif_priv->cpu_dai_drv, 1);
if (ret) {
dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
- goto error_dev;
+ return ret;
}
ret = imx_pcm_dma_init(pdev);
@@ -1197,8 +1189,6 @@ static int fsl_spdif_probe(struct platform_device *pdev)
error_component:
snd_soc_unregister_component(&pdev->dev);
-error_dev:
- dev_set_drvdata(&pdev->dev, NULL);
return ret;
}
@@ -1207,7 +1197,6 @@ static int fsl_spdif_remove(struct platform_device *pdev)
{
imx_pcm_dma_exit(pdev);
snd_soc_unregister_component(&pdev->dev);
- dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 5cf626c4dc96..c6b743978d5e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1114,7 +1114,6 @@ error_dai:
snd_soc_unregister_component(&pdev->dev);
error_dev:
- dev_set_drvdata(&pdev->dev, NULL);
device_remove_file(&pdev->dev, dev_attr);
error_clk:
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
new file mode 100644
index 000000000000..816013b0ebba
--- /dev/null
+++ b/sound/soc/fsl/imx-spdif.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <sound/soc.h>
+
+struct imx_spdif_data {
+ struct snd_soc_dai_link dai[2];
+ struct snd_soc_card card;
+ struct platform_device *txdev;
+ struct platform_device *rxdev;
+};
+
+static int imx_spdif_audio_probe(struct platform_device *pdev)
+{
+ struct device_node *spdif_np, *np = pdev->dev.of_node;
+ struct imx_spdif_data *data;
+ int ret = 0, num_links = 0;
+
+ spdif_np = of_parse_phandle(np, "spdif-controller", 0);
+ if (!spdif_np) {
+ dev_err(&pdev->dev, "failed to find spdif-controller\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ if (of_property_read_bool(np, "spdif-out")) {
+ data->dai[num_links].name = "S/PDIF TX";
+ data->dai[num_links].stream_name = "S/PDIF PCM Playback";
+ data->dai[num_links].codec_dai_name = "dit-hifi";
+ data->dai[num_links].codec_name = "spdif-dit";
+ data->dai[num_links].cpu_of_node = spdif_np;
+ data->dai[num_links].platform_of_node = spdif_np;
+ num_links++;
+
+ data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0);
+ if (IS_ERR(data->txdev)) {
+ ret = PTR_ERR(data->txdev);
+ dev_err(&pdev->dev, "register dit failed: %d\n", ret);
+ goto end;
+ }
+ }
+
+ if (of_property_read_bool(np, "spdif-in")) {
+ data->dai[num_links].name = "S/PDIF RX";
+ data->dai[num_links].stream_name = "S/PDIF PCM Capture";
+ data->dai[num_links].codec_dai_name = "dir-hifi";
+ data->dai[num_links].codec_name = "spdif-dir";
+ data->dai[num_links].cpu_of_node = spdif_np;
+ data->dai[num_links].platform_of_node = spdif_np;
+ num_links++;
+
+ data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0);
+ if (IS_ERR(data->rxdev)) {
+ ret = PTR_ERR(data->rxdev);
+ dev_err(&pdev->dev, "register dir failed: %d\n", ret);
+ goto error_dit;
+ }
+ }
+
+ if (!num_links) {
+ dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n");
+ goto error_dir;
+ }
+
+ data->card.dev = &pdev->dev;
+ data->card.num_links = num_links;
+ data->card.dai_link = data->dai;
+
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto error_dir;
+
+ ret = snd_soc_register_card(&data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
+ goto error_dir;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ goto end;
+
+error_dir:
+ if (data->rxdev)
+ platform_device_unregister(data->rxdev);
+error_dit:
+ if (data->txdev)
+ platform_device_unregister(data->txdev);
+end:
+ if (spdif_np)
+ of_node_put(spdif_np);
+
+ return ret;
+}
+
+static int imx_spdif_audio_remove(struct platform_device *pdev)
+{
+ struct imx_spdif_data *data = platform_get_drvdata(pdev);
+
+ if (data->rxdev)
+ platform_device_unregister(data->rxdev);
+ if (data->txdev)
+ platform_device_unregister(data->txdev);
+
+ snd_soc_unregister_card(&data->card);
+
+ return 0;
+}
+
+static const struct of_device_id imx_spdif_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-spdif", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_spdif_dt_ids);
+
+static struct platform_driver imx_spdif_driver = {
+ .driver = {
+ .name = "imx-spdif",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_spdif_dt_ids,
+ },
+ .probe = imx_spdif_audio_probe,
+ .remove = imx_spdif_audio_remove,
+};
+
+module_platform_driver(imx_spdif_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX S/PDIF machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-spdif");
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 6cf8355a8542..8c49147db84c 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -105,6 +105,7 @@ static int asoc_simple_card_remove(struct platform_device *pdev)
static struct platform_driver asoc_simple_card = {
.driver = {
.name = "asoc-simple-card",
+ .owner = THIS_MODULE,
},
.probe = asoc_simple_card_probe,
.remove = asoc_simple_card_remove,
@@ -112,6 +113,7 @@ static struct platform_driver asoc_simple_card = {
module_platform_driver(asoc_simple_card);
+MODULE_ALIAS("platform:asoc-simple-card");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ASoC Simple Sound Card");
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index 9e1970c44e86..78ed4a42ad21 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,6 +1,6 @@
config SND_KIRKWOOD_SOC
- tristate "SoC Audio for the Marvell Kirkwood chip"
- depends on ARCH_KIRKWOOD || COMPILE_TEST
+ tristate "SoC Audio for the Marvell Kirkwood and Dove chips"
+ depends on ARCH_KIRKWOOD || ARCH_DOVE || COMPILE_TEST
help
Say Y or M if you want to add support for codecs attached to
the Kirkwood I2S interface. You will also need to select the
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index e5f3f7a9ea26..7fce340ab3ef 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -22,6 +22,8 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <linux/platform_data/asoc-kirkwood.h>
+#include <linux/of.h>
+
#include "kirkwood.h"
#define DRV_NAME "mvebu-audio"
@@ -453,6 +455,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
struct kirkwood_dma_data *priv;
struct resource *mem;
+ struct device_node *np = pdev->dev.of_node;
int err;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -473,14 +476,16 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
return -ENXIO;
}
- if (!data) {
- dev_err(&pdev->dev, "no platform data ?!\n");
+ if (np) {
+ priv->burst = 128; /* might be 32 or 128 */
+ } else if (data) {
+ priv->burst = data->burst;
+ } else {
+ dev_err(&pdev->dev, "no DT nor platform data ?!\n");
return -EINVAL;
}
- priv->burst = data->burst;
-
- priv->clk = devm_clk_get(&pdev->dev, NULL);
+ priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "no clock\n");
return PTR_ERR(priv->clk);
@@ -507,7 +512,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
/* Select the burst size */
- if (data->burst == 32) {
+ if (priv->burst == 32) {
priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
} else {
@@ -552,12 +557,21 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static struct of_device_id mvebu_audio_of_match[] = {
+ { .compatible = "marvell,mvebu-audio" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
+#endif
+
static struct platform_driver kirkwood_i2s_driver = {
.probe = kirkwood_i2s_dev_probe,
.remove = kirkwood_i2s_dev_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(mvebu_audio_of_match),
},
};
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index a0c67f60f594..9338d11e9216 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -90,6 +90,13 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
dma_info.period = prtd->dma_period;
dma_info.len = prtd->dma_period*limit;
+ if (dma_info.cap == DMA_CYCLIC) {
+ dma_info.buf = pos;
+ prtd->params->ops->prepare(prtd->params->ch, &dma_info);
+ prtd->dma_loaded += limit;
+ return;
+ }
+
while (prtd->dma_loaded < limit) {
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 30390260bb67..b33ca7cd085b 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -235,6 +235,8 @@ struct fsi_stream {
struct sh_dmae_slave slave; /* see fsi_handler_init() */
struct work_struct work;
dma_addr_t dma;
+ int loop_cnt;
+ int additional_pos;
};
struct fsi_clk {
@@ -1289,6 +1291,8 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
+ io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */
+ io->additional_pos = 0;
io->dma = dma_map_single(dai->dev, runtime->dma_area,
snd_pcm_lib_buffer_bytes(io->substream), dir);
return 0;
@@ -1305,11 +1309,15 @@ static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
return 0;
}
-static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional)
{
struct snd_pcm_runtime *runtime = io->substream->runtime;
+ int period = io->period_pos + additional;
- return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+ if (period >= runtime->periods)
+ period = 0;
+
+ return io->dma + samples_to_bytes(runtime, period * io->period_samples);
}
static void fsi_dma_complete(void *data)
@@ -1321,7 +1329,7 @@ static void fsi_dma_complete(void *data)
enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE;
- dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io),
+ dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io, 0),
samples_to_bytes(runtime, io->period_samples), dir);
io->buff_sample_pos += io->period_samples;
@@ -1347,7 +1355,7 @@ static void fsi_dma_do_work(struct work_struct *work)
struct snd_pcm_runtime *runtime;
enum dma_data_direction dir;
int is_play = fsi_stream_is_play(fsi, io);
- int len;
+ int len, i;
dma_addr_t buf;
if (!fsi_stream_is_working(fsi, io))
@@ -1357,26 +1365,33 @@ static void fsi_dma_do_work(struct work_struct *work)
runtime = io->substream->runtime;
dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
len = samples_to_bytes(runtime, io->period_samples);
- buf = fsi_dma_get_area(io);
- dma_sync_single_for_device(dai->dev, buf, len, dir);
+ for (i = 0; i < io->loop_cnt; i++) {
+ buf = fsi_dma_get_area(io, io->additional_pos);
- desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
- return;
- }
+ dma_sync_single_for_device(dai->dev, buf, len, dir);
- desc->callback = fsi_dma_complete;
- desc->callback_param = io;
+ desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
+ return;
+ }
- if (dmaengine_submit(desc) < 0) {
- dev_err(dai->dev, "tx_submit() fail\n");
- return;
+ desc->callback = fsi_dma_complete;
+ desc->callback_param = io;
+
+ if (dmaengine_submit(desc) < 0) {
+ dev_err(dai->dev, "tx_submit() fail\n");
+ return;
+ }
+
+ dma_async_issue_pending(io->chan);
+
+ io->additional_pos = 1;
}
- dma_async_issue_pending(io->chan);
+ io->loop_cnt = 1;
/*
* FIXME
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 5471940dc0f7..4d0561312f3b 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1245,9 +1245,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
}
rtd->card = card;
- /* Make sure all DAPM widgets are instantiated */
- snd_soc_dapm_new_widgets(&codec->dapm);
-
/* machine controls, routes and widgets are not prefixed */
temp = codec->name_prefix;
codec->name_prefix = NULL;
@@ -1743,8 +1740,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
card->num_dapm_routes);
- snd_soc_dapm_new_widgets(&card->dapm);
-
for (i = 0; i < card->num_links; i++) {
dai_link = &card->dai_link[i];
dai_fmt = dai_link->dai_fmt;
@@ -1823,12 +1818,12 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
- snd_soc_dapm_new_widgets(&card->dapm);
-
if (card->fully_routed)
list_for_each_entry(codec, &card->codec_dev_list, card_list)
snd_soc_dapm_auto_nc_codec_pins(codec);
+ snd_soc_dapm_new_widgets(card);
+
ret = snd_card_register(card->snd_card);
if (ret < 0) {
dev_err(card->dev, "ASoC: failed to register soundcard %d\n",
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d84bd0f167b6..548b1c9e875e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2374,6 +2374,9 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
wsource->ext = 1;
}
+ dapm_mark_dirty(wsource, "Route added");
+ dapm_mark_dirty(wsink, "Route added");
+
/* connect static paths */
if (control == NULL) {
list_add(&path->list, &dapm->card->paths);
@@ -2436,9 +2439,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
return 0;
}
- dapm_mark_dirty(wsource, "Route added");
- dapm_mark_dirty(wsink, "Route added");
-
return 0;
err:
kfree(path);
@@ -2712,9 +2712,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
*
* Returns 0 for success.
*/
-int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
+int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
{
- struct snd_soc_card *card = dapm->card;
struct snd_soc_dapm_widget *w;
unsigned int val;
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 7aa26b5178aa..71358e3b54d9 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -183,8 +183,6 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
list_add(&(pins[i].list), &jack->pins);
}
- snd_soc_dapm_new_widgets(&jack->codec->card->dapm);
-
/* Update to reflect the last reported status; canned jack
* implementations are likely to set their state before the
* card has an opportunity to associate pins.