summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-04-12 19:48:29 +0100
committerMark Brown <broonie@kernel.org>2015-04-12 19:48:29 +0100
commit89a88dd3d6823f46bfb1405c4b358f89d5526cd6 (patch)
treea1b6550b08da296aa14e8f59fe97ada6c67d5f63 /sound
parent3eaecb4b50693378bb55cc633992e7f72be35687 (diff)
parentd7e3281b52fea8917fb4a7a5b09df5e6a9d2850c (diff)
Merge tag 'asoc-v4.1' into asoc-next
ASoC: Changes for v4.1 A selection of changes for v4.1 so far. The main things are: - Move of jack registration to the card where it belongs. - Support for DAPM routes specified by both the machine driver and DT. # gpg: Signature made Thu 05 Mar 2015 01:10:27 GMT using RSA key ID 5D5487D0 # gpg: WARNING: digest algorithm MD5 is deprecated # gpg: please see https://gnupg.org/faq/weak-digest-algos.html for more information # gpg: Oops: keyid_from_fingerprint: no pubkey # gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>" # gpg: aka "Mark Brown <broonie@debian.org>" # gpg: aka "Mark Brown <broonie@kernel.org>" # gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>" # gpg: aka "Mark Brown <broonie@linaro.org>" # gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c111
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h1
-rw-r--r--sound/soc/codecs/Kconfig18
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/adau1977.c17
-rw-r--r--sound/soc/codecs/cs35l32.c19
-rw-r--r--sound/soc/codecs/cs4265.c19
-rw-r--r--sound/soc/codecs/max98357a.c11
-rw-r--r--sound/soc/codecs/pcm512x.c178
-rw-r--r--sound/soc/codecs/rt286.c17
-rw-r--r--sound/soc/codecs/rt5670.h3
-rw-r--r--sound/soc/codecs/rt5677.c44
-rw-r--r--sound/soc/codecs/rt5677.h6
-rw-r--r--sound/soc/codecs/sn95031.c14
-rw-r--r--sound/soc/codecs/sn95031.h3
-rw-r--r--sound/soc/codecs/sta350.c30
-rw-r--r--sound/soc/codecs/tas2552.c13
-rw-r--r--sound/soc/codecs/wm8804-i2c.c64
-rw-r--r--sound/soc/codecs/wm8804-spi.c56
-rw-r--r--sound/soc/codecs/wm8804.c281
-rw-r--r--sound/soc/codecs/wm8804.h7
-rw-r--r--sound/soc/codecs/wm_adsp.c13
-rw-r--r--sound/soc/davinci/Kconfig18
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-i2s.c67
-rw-r--r--sound/soc/davinci/davinci-mcasp.c99
-rw-r--r--sound/soc/davinci/davinci-pcm.c861
-rw-r--r--sound/soc/davinci/davinci-pcm.h41
-rw-r--r--sound/soc/davinci/davinci-vcif.c55
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c6
-rw-r--r--sound/soc/fsl/imx-es8328.c6
-rw-r--r--sound/soc/fsl/wm1133-ev1.c12
-rw-r--r--sound/soc/generic/simple-card.c20
-rw-r--r--sound/soc/intel/broadwell.c16
-rw-r--r--sound/soc/intel/byt-max98090.c11
-rw-r--r--sound/soc/intel/bytcr_dpcm_rt5640.c4
-rw-r--r--sound/soc/intel/cht_bsw_rt5645.c16
-rw-r--r--sound/soc/intel/cht_bsw_rt5672.c9
-rw-r--r--sound/soc/intel/haswell.c4
-rw-r--r--sound/soc/intel/mfld_machine.c24
-rw-r--r--sound/soc/intel/sst-mfld-platform-pcm.c60
-rw-r--r--sound/soc/intel/sst-mfld-platform.h1
-rw-r--r--sound/soc/intel/sst/sst.c128
-rw-r--r--sound/soc/intel/sst/sst.h12
-rw-r--r--sound/soc/intel/sst/sst_drv_interface.c65
-rw-r--r--sound/soc/intel/sst/sst_loader.c10
-rw-r--r--sound/soc/omap/Kconfig4
-rw-r--r--sound/soc/omap/ams-delta.c4
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c10
-rw-r--r--sound/soc/omap/omap-pcm.c21
-rw-r--r--sound/soc/omap/omap-twl4030.c12
-rw-r--r--sound/soc/omap/rx51.c6
-rw-r--r--sound/soc/pxa/hx4700.c11
-rw-r--r--sound/soc/pxa/palm27x.c11
-rw-r--r--sound/soc/pxa/ttc-dkb.c15
-rw-r--r--sound/soc/pxa/z2.c10
-rw-r--r--sound/soc/samsung/h1940_uda1380.c9
-rw-r--r--sound/soc/samsung/littlemill.c12
-rw-r--r--sound/soc/samsung/lowland.c14
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c9
-rw-r--r--sound/soc/samsung/smartq_wm8987.c11
-rw-r--r--sound/soc/samsung/speyside.c14
-rw-r--r--sound/soc/samsung/tobermory.c13
-rw-r--r--sound/soc/soc-core.c16
-rw-r--r--sound/soc/soc-jack.c42
-rw-r--r--sound/soc/soc-pcm.c1
-rw-r--r--sound/soc/tegra/tegra_alc5632.c9
-rw-r--r--sound/soc/tegra/tegra_max98090.c26
-rw-r--r--sound/soc/tegra/tegra_rt5640.c10
-rw-r--r--sound/soc/tegra/tegra_rt5677.c14
-rw-r--r--sound/soc/tegra/tegra_wm8903.c18
71 files changed, 1149 insertions, 1649 deletions
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index fb0b7e8b08ff..841d05946b88 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -187,6 +187,94 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/*
+ * When the bit clock is input, limit the maximum rate according to the
+ * Serial Clock Ratio Considerations section from the SSC documentation:
+ *
+ * The Transmitter and the Receiver can be programmed to operate
+ * with the clock signals provided on either the TK or RK pins.
+ * This allows the SSC to support many slave-mode data transfers.
+ * In this case, the maximum clock speed allowed on the RK pin is:
+ * - Peripheral clock divided by 2 if Receiver Frame Synchro is input
+ * - Peripheral clock divided by 3 if Receiver Frame Synchro is output
+ * In addition, the maximum clock speed allowed on the TK pin is:
+ * - Peripheral clock divided by 6 if Transmit Frame Synchro is input
+ * - Peripheral clock divided by 2 if Transmit Frame Synchro is output
+ *
+ * When the bit clock is output, limit the rate according to the
+ * SSC divider restrictions.
+ */
+static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct atmel_ssc_info *ssc_p = rule->private;
+ struct ssc_device *ssc = ssc_p->ssc;
+ struct snd_interval *i = hw_param_interval(params, rule->var);
+ struct snd_interval t;
+ struct snd_ratnum r = {
+ .den_min = 1,
+ .den_max = 4095,
+ .den_step = 1,
+ };
+ unsigned int num = 0, den = 0;
+ int frame_size;
+ int mck_div = 2;
+ int ret;
+
+ frame_size = snd_soc_params_to_frame_size(params);
+ if (frame_size < 0)
+ return frame_size;
+
+ switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFS:
+ if ((ssc_p->dir_mask & SSC_DIR_MASK_CAPTURE)
+ && ssc->clk_from_rk_pin)
+ /* Receiver Frame Synchro (i.e. capture)
+ * is output (format is _CFS) and the RK pin
+ * is used for input (format is _CBM_).
+ */
+ mck_div = 3;
+ break;
+
+ case SND_SOC_DAIFMT_CBM_CFM:
+ if ((ssc_p->dir_mask & SSC_DIR_MASK_PLAYBACK)
+ && !ssc->clk_from_rk_pin)
+ /* Transmit Frame Synchro (i.e. playback)
+ * is input (format is _CFM) and the TK pin
+ * is used for input (format _CBM_ but not
+ * using the RK pin).
+ */
+ mck_div = 6;
+ break;
+ }
+
+ switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ r.num = ssc_p->mck_rate / mck_div / frame_size;
+
+ ret = snd_interval_ratnum(i, 1, &r, &num, &den);
+ if (ret >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
+ params->rate_num = num;
+ params->rate_den = den;
+ }
+ break;
+
+ case SND_SOC_DAIFMT_CBM_CFS:
+ case SND_SOC_DAIFMT_CBM_CFM:
+ t.min = 8000;
+ t.max = ssc_p->mck_rate / mck_div / frame_size;
+ t.openmin = t.openmax = 0;
+ t.integer = 0;
+ ret = snd_interval_refine(i, &t);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
/*-------------------------------------------------------------------------*\
* DAI functions
@@ -200,6 +288,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
struct atmel_pcm_dma_params *dma_params;
int dir, dir_mask;
+ int ret;
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
ssc_readl(ssc_p->ssc->regs, SR));
@@ -207,6 +296,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
/* Enable PMC peripheral clock for this SSC */
pr_debug("atmel_ssc_dai: Starting clock\n");
clk_enable(ssc_p->ssc->clk);
+ ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
/* Reset the SSC to keep it at a clean status */
ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
@@ -219,6 +309,17 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
dir_mask = SSC_DIR_MASK_CAPTURE;
}
+ ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ atmel_ssc_hw_rule_rate,
+ ssc_p,
+ SNDRV_PCM_HW_PARAM_FRAME_BITS,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+ if (ret < 0) {
+ dev_err(dai->dev, "Failed to specify rate rule: %d\n", ret);
+ return ret;
+ }
+
dma_params = &ssc_dma_params[dai->id][dir];
dma_params->ssc = ssc_p->ssc;
dma_params->substream = substream;
@@ -783,8 +884,6 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
# define atmel_ssc_resume NULL
#endif /* CONFIG_PM */
-#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
-
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -804,12 +903,16 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
.playback = {
.channels_min = 1,
.channels_max = 2,
- .rates = ATMEL_SSC_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 8000,
+ .rate_max = 384000,
.formats = ATMEL_SSC_FORMATS,},
.capture = {
.channels_min = 1,
.channels_max = 2,
- .rates = ATMEL_SSC_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 8000,
+ .rate_max = 384000,
.formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops,
};
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
index b1f08d511495..80b153857a88 100644
--- a/sound/soc/atmel/atmel_ssc_dai.h
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -115,6 +115,7 @@ struct atmel_ssc_info {
unsigned short rcmr_period;
struct atmel_pcm_dma_params *dma_params[2];
struct atmel_ssc_state ssc_state;
+ unsigned long mck_rate;
};
int atmel_ssc_set_audio(int ssc_id);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index ea9f0e31f9d4..0bddd929837f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -141,7 +141,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8770 if SPI_MASTER
select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8782
- select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
+ select SND_SOC_WM8804_I2C if I2C
+ select SND_SOC_WM8804_SPI if SPI_MASTER
select SND_SOC_WM8900 if I2C
select SND_SOC_WM8903 if I2C
select SND_SOC_WM8904 if I2C
@@ -744,8 +745,19 @@ config SND_SOC_WM8782
tristate
config SND_SOC_WM8804
- tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver"
- depends on SND_SOC_I2C_AND_SPI
+ tristate
+
+config SND_SOC_WM8804_I2C
+ tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver I2C"
+ depends on I2C
+ select SND_SOC_WM8804
+ select REGMAP_I2C
+
+config SND_SOC_WM8804_SPI
+ tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver SPI"
+ depends on SPI_MASTER
+ select SND_SOC_WM8804
+ select REGMAP_SPI
config SND_SOC_WM8900
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 69b8666d187a..7acb6c174cb4 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -145,6 +145,8 @@ snd-soc-wm8770-objs := wm8770.o
snd-soc-wm8776-objs := wm8776.o
snd-soc-wm8782-objs := wm8782.o
snd-soc-wm8804-objs := wm8804.o
+snd-soc-wm8804-i2c-objs := wm8804-i2c.o
+snd-soc-wm8804-spi-objs := wm8804-spi.o
snd-soc-wm8900-objs := wm8900.o
snd-soc-wm8903-objs := wm8903.o
snd-soc-wm8904-objs := wm8904.o
@@ -323,6 +325,8 @@ obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o
obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o
obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o
+obj-$(CONFIG_SND_SOC_WM8804_I2C) += snd-soc-wm8804-i2c.o
+obj-$(CONFIG_SND_SOC_WM8804_SPI) += snd-soc-wm8804-spi.o
obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c
index 70ab35744aba..7ad8e156e2df 100644
--- a/sound/soc/codecs/adau1977.c
+++ b/sound/soc/codecs/adau1977.c
@@ -938,22 +938,15 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
adau1977->dvdd_reg = NULL;
}
- adau1977->reset_gpio = devm_gpiod_get(dev, "reset");
- if (IS_ERR(adau1977->reset_gpio)) {
- ret = PTR_ERR(adau1977->reset_gpio);
- if (ret != -ENOENT && ret != -ENOSYS)
- return PTR_ERR(adau1977->reset_gpio);
- adau1977->reset_gpio = NULL;
- }
+ adau1977->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(adau1977->reset_gpio))
+ return PTR_ERR(adau1977->reset_gpio);
dev_set_drvdata(dev, adau1977);
- if (adau1977->reset_gpio) {
- ret = gpiod_direction_output(adau1977->reset_gpio, 0);
- if (ret)
- return ret;
+ if (adau1977->reset_gpio)
ndelay(100);
- }
ret = adau1977_power_enable(adau1977);
if (ret)
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c
index f2b8aad21274..60598b230341 100644
--- a/sound/soc/codecs/cs35l32.c
+++ b/sound/soc/codecs/cs35l32.c
@@ -437,20 +437,13 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
}
/* Reset the Device */
- cs35l32->reset_gpio = devm_gpiod_get(&i2c_client->dev,
- "reset-gpios");
- if (IS_ERR(cs35l32->reset_gpio)) {
- ret = PTR_ERR(cs35l32->reset_gpio);
- if (ret != -ENOENT && ret != -ENOSYS)
- return ret;
-
- cs35l32->reset_gpio = NULL;
- } else {
- ret = gpiod_direction_output(cs35l32->reset_gpio, 0);
- if (ret)
- return ret;
+ cs35l32->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(cs35l32->reset_gpio))
+ return PTR_ERR(cs35l32->reset_gpio);
+
+ if (cs35l32->reset_gpio)
gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
- }
/* initialize codec */
ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, &reg);
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
index ce6086835ebd..cac48ddf3ba6 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -605,21 +605,14 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client,
return ret;
}
- cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev,
- "reset-gpios");
- if (IS_ERR(cs4265->reset_gpio)) {
- ret = PTR_ERR(cs4265->reset_gpio);
- if (ret != -ENOENT && ret != -ENOSYS)
- return ret;
-
- cs4265->reset_gpio = NULL;
- } else {
- ret = gpiod_direction_output(cs4265->reset_gpio, 0);
- if (ret)
- return ret;
+ cs4265->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(cs4265->reset_gpio))
+ return PTR_ERR(cs4265->reset_gpio);
+
+ if (cs4265->reset_gpio) {
mdelay(1);
gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
-
}
i2c_set_clientdata(i2c_client, cs4265);
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index e9e6efbc21dd..bf3e933ee895 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -26,8 +26,6 @@
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
-#define DRV_NAME "max98357a"
-
static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
@@ -87,9 +85,9 @@ static struct snd_soc_dai_ops max98357a_dai_ops = {
};
static struct snd_soc_dai_driver max98357a_dai_driver = {
- .name = DRV_NAME,
+ .name = "HiFi",
.playback = {
- .stream_name = DRV_NAME "-playback",
+ .stream_name = "HiFi Playback",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
@@ -127,7 +125,7 @@ static int max98357a_platform_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id max98357a_device_id[] = {
- { .compatible = "maxim," DRV_NAME, },
+ { .compatible = "maxim,max98357a" },
{}
};
MODULE_DEVICE_TABLE(of, max98357a_device_id);
@@ -135,7 +133,7 @@ MODULE_DEVICE_TABLE(of, max98357a_device_id);
static struct platform_driver max98357a_platform_driver = {
.driver = {
- .name = DRV_NAME,
+ .name = "max98357a",
.of_match_table = of_match_ptr(max98357a_device_id),
},
.probe = max98357a_platform_probe,
@@ -145,4 +143,3 @@ module_platform_driver(max98357a_platform_driver);
MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 8c09e3ffdcaa..5a30fdd0da00 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -54,6 +54,9 @@ struct pcm512x_priv {
int pll_d;
int pll_p;
unsigned long real_pll;
+ unsigned long overclock_pll;
+ unsigned long overclock_dac;
+ unsigned long overclock_dsp;
};
/*
@@ -224,6 +227,90 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg)
}
}
+static int pcm512x_overclock_pll_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = pcm512x->overclock_pll;
+ return 0;
+}
+
+static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+ switch (codec->dapm.bias_level) {
+ case SND_SOC_BIAS_OFF:
+ case SND_SOC_BIAS_STANDBY:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ pcm512x->overclock_pll = ucontrol->value.integer.value[0];
+ return 0;
+}
+
+static int pcm512x_overclock_dsp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = pcm512x->overclock_dsp;
+ return 0;
+}
+
+static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+ switch (codec->dapm.bias_level) {
+ case SND_SOC_BIAS_OFF:
+ case SND_SOC_BIAS_STANDBY:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ pcm512x->overclock_dsp = ucontrol->value.integer.value[0];
+ return 0;
+}
+
+static int pcm512x_overclock_dac_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = pcm512x->overclock_dac;
+ return 0;
+}
+
+static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+ switch (codec->dapm.bias_level) {
+ case SND_SOC_BIAS_OFF:
+ case SND_SOC_BIAS_STANDBY:
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ pcm512x->overclock_dac = ucontrol->value.integer.value[0];
+ return 0;
+}
+
static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
@@ -328,6 +415,13 @@ SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
+
+SOC_SINGLE_EXT("Max Overclock PLL", SND_SOC_NOPM, 0, 20, 0,
+ pcm512x_overclock_pll_get, pcm512x_overclock_pll_put),
+SOC_SINGLE_EXT("Max Overclock DSP", SND_SOC_NOPM, 0, 40, 0,
+ pcm512x_overclock_dsp_get, pcm512x_overclock_dsp_put),
+SOC_SINGLE_EXT("Max Overclock DAC", SND_SOC_NOPM, 0, 40, 0,
+ pcm512x_overclock_dac_get, pcm512x_overclock_dac_put),
};
static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
@@ -346,6 +440,45 @@ static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
{ "OUTR", NULL, "DACR" },
};
+static unsigned long pcm512x_pll_max(struct pcm512x_priv *pcm512x)
+{
+ return 25000000 + 25000000 * pcm512x->overclock_pll / 100;
+}
+
+static unsigned long pcm512x_dsp_max(struct pcm512x_priv *pcm512x)
+{
+ return 50000000 + 50000000 * pcm512x->overclock_dsp / 100;
+}
+
+static unsigned long pcm512x_dac_max(struct pcm512x_priv *pcm512x,
+ unsigned long rate)
+{
+ return rate + rate * pcm512x->overclock_dac / 100;
+}
+
+static unsigned long pcm512x_sck_max(struct pcm512x_priv *pcm512x)
+{
+ if (!pcm512x->pll_out)
+ return 25000000;
+ return pcm512x_pll_max(pcm512x);
+}
+
+static unsigned long pcm512x_ncp_target(struct pcm512x_priv *pcm512x,
+ unsigned long dac_rate)
+{
+ /*
+ * If the DAC is not actually overclocked, use the good old
+ * NCP target rate...
+ */
+ if (dac_rate <= 6144000)
+ return 1536000;
+ /*
+ * ...but if the DAC is in fact overclocked, bump the NCP target
+ * rate to get the recommended dividers even when overclocking.
+ */
+ return pcm512x_dac_max(pcm512x, 1536000);
+}
+
static const u32 pcm512x_dai_rates[] = {
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
88200, 96000, 176400, 192000, 384000,
@@ -359,6 +492,7 @@ static const struct snd_pcm_hw_constraint_list constraints_slave = {
static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
+ struct pcm512x_priv *pcm512x = rule->private;
struct snd_interval ranges[2];
int frame_size;
@@ -377,7 +511,7 @@ static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
*/
memset(ranges, 0, sizeof(ranges));
ranges[0].min = 8000;
- ranges[0].max = 25000000 / frame_size / 2;
+ ranges[0].max = pcm512x_sck_max(pcm512x) / frame_size / 2;
ranges[1].min = DIV_ROUND_UP(16000000, frame_size);
ranges[1].max = 384000;
break;
@@ -408,7 +542,7 @@ static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
return snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
pcm512x_hw_rule_rate,
- NULL,
+ pcm512x,
SNDRV_PCM_HW_PARAM_FRAME_BITS,
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
@@ -517,6 +651,8 @@ static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
unsigned long bclk_rate)
{
struct device *dev = dai->dev;
+ struct snd_soc_codec *codec = dai->codec;
+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
unsigned long sck_rate;
int pow2;
@@ -527,9 +663,10 @@ static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
* as many factors of 2 as possible, as that makes it easier
* to find a fast DAC rate
*/
- pow2 = 1 << fls((25000000 - 16000000) / bclk_rate);
+ pow2 = 1 << fls((pcm512x_pll_max(pcm512x) - 16000000) / bclk_rate);
for (; pow2; pow2 >>= 1) {
- sck_rate = rounddown(25000000, bclk_rate * pow2);
+ sck_rate = rounddown(pcm512x_pll_max(pcm512x),
+ bclk_rate * pow2);
if (sck_rate >= 16000000)
break;
}
@@ -678,7 +815,7 @@ static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
return 0; /* futile, quit early */
/* run DAC no faster than 6144000 Hz */
- for (dac_rate = rounddown(6144000, osr_rate);
+ for (dac_rate = rounddown(pcm512x_dac_max(pcm512x, 6144000), osr_rate);
dac_rate;
dac_rate -= osr_rate) {
@@ -805,7 +942,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
osr_rate = 16 * sample_rate;
/* run DSP no faster than 50 MHz */
- dsp_div = mck_rate > 50000000 ? 2 : 1;
+ dsp_div = mck_rate > pcm512x_dsp_max(pcm512x) ? 2 : 1;
dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
if (dac_rate) {
@@ -836,7 +973,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
dacsrc_rate = pllin_rate;
} else {
/* run DAC no faster than 6144000 Hz */
- unsigned long dac_mul = 6144000 / osr_rate;
+ unsigned long dac_mul = pcm512x_dac_max(pcm512x, 6144000)
+ / osr_rate;
unsigned long sck_mul = sck_rate / osr_rate;
for (; dac_mul; dac_mul--) {
@@ -863,28 +1001,30 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
dacsrc_rate = sck_rate;
}
+ osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
+ if (osr_div > 128) {
+ dev_err(dev, "Failed to find OSR divider\n");
+ return -EINVAL;
+ }
+
dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
if (dac_div > 128) {
dev_err(dev, "Failed to find DAC divider\n");
return -EINVAL;
}
+ dac_rate = dacsrc_rate / dac_div;
- ncp_div = DIV_ROUND_CLOSEST(dacsrc_rate / dac_div, 1536000);
- if (ncp_div > 128 || dacsrc_rate / dac_div / ncp_div > 2048000) {
+ ncp_div = DIV_ROUND_CLOSEST(dac_rate,
+ pcm512x_ncp_target(pcm512x, dac_rate));
+ if (ncp_div > 128 || dac_rate / ncp_div > 2048000) {
/* run NCP no faster than 2048000 Hz, but why? */
- ncp_div = DIV_ROUND_UP(dacsrc_rate / dac_div, 2048000);
+ ncp_div = DIV_ROUND_UP(dac_rate, 2048000);
if (ncp_div > 128) {
dev_err(dev, "Failed to find NCP divider\n");
return -EINVAL;
}
}
- osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
- if (osr_div > 128) {
- dev_err(dev, "Failed to find OSR divider\n");
- return -EINVAL;
- }
-
idac = mck_rate / (dsp_div * sample_rate);
ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1);
@@ -937,11 +1077,11 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
return ret;
}
- if (sample_rate <= 48000)
+ if (sample_rate <= pcm512x_dac_max(pcm512x, 48000))
fssp = PCM512x_FSSP_48KHZ;
- else if (sample_rate <= 96000)
+ else if (sample_rate <= pcm512x_dac_max(pcm512x, 96000))
fssp = PCM512x_FSSP_96KHZ;
- else if (sample_rate <= 192000)
+ else if (sample_rate <= pcm512x_dac_max(pcm512x, 192000))
fssp = PCM512x_FSSP_192KHZ;
else
fssp = PCM512x_FSSP_384KHZ;
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 9b541e52da8c..826037090c83 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -395,9 +395,20 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
rt286->jack = jack;
- /* Send an initial empty report */
- snd_soc_jack_report(rt286->jack, 0,
- SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+ if (jack) {
+ /* enable IRQ */
+ if (rt286->jack->status | SND_JACK_HEADPHONE)
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO1");
+ regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x2);
+ /* Send an initial empty report */
+ snd_soc_jack_report(rt286->jack, rt286->jack->status,
+ SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+ } else {
+ /* disable IRQ */
+ regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x0);
+ snd_soc_dapm_disable_pin(&codec->dapm, "LDO1");
+ }
+ snd_soc_dapm_sync(&codec->dapm);
return 0;
}
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h
index 21f8e18c13c4..0a67adbcfbc3 100644
--- a/sound/soc/codecs/rt5670.h
+++ b/sound/soc/codecs/rt5670.h
@@ -1950,17 +1950,20 @@ enum {
};
enum {
+ RT5670_DMIC1_DISABLED,
RT5670_DMIC_DATA_GPIO6,
RT5670_DMIC_DATA_IN2P,
RT5670_DMIC_DATA_GPIO7,
};
enum {
+ RT5670_DMIC2_DISABLED,
RT5670_DMIC_DATA_GPIO8,
RT5670_DMIC_DATA_IN3N,
};
enum {
+ RT5670_DMIC3_DISABLED,
RT5670_DMIC_DATA_GPIO9,
RT5670_DMIC_DATA_GPIO10,
RT5670_DMIC_DATA_GPIO5,
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index fb9c20eace3f..c2a6e4091357 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -718,11 +718,24 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
RT5677_LDO1_SEL_MASK, 0x0);
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
RT5677_PWR_LDO1, RT5677_PWR_LDO1);
- regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
- RT5677_MCLK_SRC_MASK, RT5677_MCLK2_SRC);
- regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2,
- RT5677_PLL2_PR_SRC_MASK | RT5677_DSP_CLK_SRC_MASK,
- RT5677_PLL2_PR_SRC_MCLK2 | RT5677_DSP_CLK_SRC_BYPASS);
+ switch (rt5677->type) {
+ case RT5677:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
+ RT5677_MCLK_SRC_MASK, RT5677_MCLK2_SRC);
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2,
+ RT5677_PLL2_PR_SRC_MASK |
+ RT5677_DSP_CLK_SRC_MASK,
+ RT5677_PLL2_PR_SRC_MCLK2 |
+ RT5677_DSP_CLK_SRC_BYPASS);
+ break;
+ case RT5676:
+ regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2,
+ RT5677_DSP_CLK_SRC_MASK,
+ RT5677_DSP_CLK_SRC_BYPASS);
+ break;
+ default:
+ break;
+ }
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x07ff);
regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x07fd);
rt5677_set_dsp_mode(codec, true);
@@ -4500,10 +4513,10 @@ static int rt5677_suspend(struct snd_soc_codec *codec)
if (!rt5677->dsp_vad_en) {
regcache_cache_only(rt5677->regmap, true);
regcache_mark_dirty(rt5677->regmap);
- }
- if (gpio_is_valid(rt5677->pow_ldo2))
- gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
+ if (gpio_is_valid(rt5677->pow_ldo2))
+ gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
+ }
return 0;
}
@@ -4512,12 +4525,12 @@ static int rt5677_resume(struct snd_soc_codec *codec)
{
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
- if (gpio_is_valid(rt5677->pow_ldo2)) {
- gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
- msleep(10);
- }
-
if (!rt5677->dsp_vad_en) {
+ if (gpio_is_valid(rt5677->pow_ldo2)) {
+ gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
+ msleep(10);
+ }
+
regcache_cache_only(rt5677->regmap, false);
regcache_sync(rt5677->regmap);
}
@@ -4733,7 +4746,8 @@ static const struct regmap_config rt5677_regmap = {
};
static const struct i2c_device_id rt5677_i2c_id[] = {
- { "rt5677", 0 },
+ { "rt5677", RT5677 },
+ { "rt5676", RT5676 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
@@ -4850,6 +4864,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt5677);
+ rt5677->type = id->driver_data;
+
if (pdata)
rt5677->pdata = *pdata;
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h
index c0a625f290cc..07df96b43f59 100644
--- a/sound/soc/codecs/rt5677.h
+++ b/sound/soc/codecs/rt5677.h
@@ -1665,6 +1665,11 @@ enum {
RT5677_IRQ_JD3,
};
+enum rt5677_type {
+ RT5677,
+ RT5676,
+};
+
struct rt5677_priv {
struct snd_soc_codec *codec;
struct rt5677_platform_data pdata;
@@ -1681,6 +1686,7 @@ struct rt5677_priv {
int pll_in;
int pll_out;
int pow_ldo2; /* POW_LDO2 pin */
+ enum rt5677_type type;
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 82095d6cd070..7947c0ebb1ed 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -783,19 +783,21 @@ static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec)
snd_soc_write(codec, SN95031_BTNCTRL2, 0x01);
}
-static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack)
+static int sn95031_get_headset_state(struct snd_soc_codec *codec,
+ struct snd_soc_jack *mfld_jack)
{
- int micbias = sn95031_get_mic_bias(mfld_jack->codec);
+ int micbias = sn95031_get_mic_bias(codec);
int jack_type = snd_soc_jack_get_type(mfld_jack, micbias);
pr_debug("jack type detected = %d\n", jack_type);
if (jack_type == SND_JACK_HEADSET)
- sn95031_enable_jack_btn(mfld_jack->codec);
+ sn95031_enable_jack_btn(codec);
return jack_type;
}
-void sn95031_jack_detection(struct mfld_jack_data *jack_data)
+void sn95031_jack_detection(struct snd_soc_codec *codec,
+ struct mfld_jack_data *jack_data)
{
unsigned int status;
unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
@@ -809,11 +811,11 @@ void sn95031_jack_detection(struct mfld_jack_data *jack_data)
status = SND_JACK_HEADSET | SND_JACK_BTN_1;
} else if (jack_data->intr_id & 0x4) {
pr_debug("headset or headphones inserted\n");
- status = sn95031_get_headset_state(jack_data->mfld_jack);
+ status = sn95031_get_headset_state(codec, jack_data->mfld_jack);
} else if (jack_data->intr_id & 0x8) {
pr_debug("headset or headphones removed\n");
status = 0;
- sn95031_disable_jack_btn(jack_data->mfld_jack->codec);
+ sn95031_disable_jack_btn(codec);
} else {
pr_err("unidentified interrupt\n");
return;
diff --git a/sound/soc/codecs/sn95031.h b/sound/soc/codecs/sn95031.h
index 20376d234fb8..7651fe4e6a45 100644
--- a/sound/soc/codecs/sn95031.h
+++ b/sound/soc/codecs/sn95031.h
@@ -127,6 +127,7 @@ struct mfld_jack_data {
struct snd_soc_jack *mfld_jack;
};
-extern void sn95031_jack_detection(struct mfld_jack_data *jack_data);
+extern void sn95031_jack_detection(struct snd_soc_codec *codec,
+ struct mfld_jack_data *jack_data);
#endif
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c
index bda2ee18769e..669e3228241e 100644
--- a/sound/soc/codecs/sta350.c
+++ b/sound/soc/codecs/sta350.c
@@ -1213,27 +1213,15 @@ static int sta350_i2c_probe(struct i2c_client *i2c,
#endif
/* GPIOs */
- sta350->gpiod_nreset = devm_gpiod_get(dev, "reset");
- if (IS_ERR(sta350->gpiod_nreset)) {
- ret = PTR_ERR(sta350->gpiod_nreset);
- if (ret != -ENOENT && ret != -ENOSYS)
- return ret;
-
- sta350->gpiod_nreset = NULL;
- } else {
- gpiod_direction_output(sta350->gpiod_nreset, 0);
- }
-
- sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down");
- if (IS_ERR(sta350->gpiod_power_down)) {
- ret = PTR_ERR(sta350->gpiod_power_down);
- if (ret != -ENOENT && ret != -ENOSYS)
- return ret;
-
- sta350->gpiod_power_down = NULL;
- } else {
- gpiod_direction_output(sta350->gpiod_power_down, 0);
- }
+ sta350->gpiod_nreset = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(sta350->gpiod_nreset))
+ return PTR_ERR(sta350->gpiod_nreset);
+
+ sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(sta350->gpiod_power_down))
+ return PTR_ERR(sta350->gpiod_power_down);
/* regulators */
for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++)
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
index ae23acdd2708..dfb4ff5cc9ea 100644
--- a/sound/soc/codecs/tas2552.c
+++ b/sound/soc/codecs/tas2552.c
@@ -485,16 +485,9 @@ static int tas2552_probe(struct i2c_client *client,
if (data == NULL)
return -ENOMEM;
- data->enable_gpio = devm_gpiod_get(dev, "enable");
- if (IS_ERR(data->enable_gpio)) {
- ret = PTR_ERR(data->enable_gpio);
- if (ret != -ENOENT && ret != -ENOSYS)
- return ret;
-
- data->enable_gpio = NULL;
- } else {
- gpiod_direction_output(data->enable_gpio, 0);
- }
+ data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(data->enable_gpio))
+ return PTR_ERR(data->enable_gpio);
data->tas2552_client = client;
data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c
new file mode 100644
index 000000000000..5bd4af2b4059
--- /dev/null
+++ b/sound/soc/codecs/wm8804-i2c.c
@@ -0,0 +1,64 @@
+/*
+ * wm8804-i2c.c -- WM8804 S/PDIF transceiver driver - I2C
+ *
+ * Copyright 2015 Cirrus Logic Inc
+ *
+ * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+
+#include "wm8804.h"
+
+static int wm8804_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return wm8804_probe(&i2c->dev, regmap);
+}
+
+static int wm8804_i2c_remove(struct i2c_client *i2c)
+{
+ wm8804_remove(&i2c->dev);
+ return 0;
+}
+
+static const struct i2c_device_id wm8804_i2c_id[] = {
+ { "wm8804", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
+
+static const struct of_device_id wm8804_of_match[] = {
+ { .compatible = "wlf,wm8804", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8804_of_match);
+
+static struct i2c_driver wm8804_i2c_driver = {
+ .driver = {
+ .name = "wm8804",
+ .owner = THIS_MODULE,
+ .of_match_table = wm8804_of_match,
+ },
+ .probe = wm8804_i2c_probe,
+ .remove = wm8804_i2c_remove,
+ .id_table = wm8804_i2c_id
+};
+
+module_i2c_driver(wm8804_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC WM8804 driver - I2C");
+MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8804-spi.c b/sound/soc/codecs/wm8804-spi.c
new file mode 100644
index 000000000000..287e11e90794
--- /dev/null
+++ b/sound/soc/codecs/wm8804-spi.c
@@ -0,0 +1,56 @@
+/*
+ * wm8804-spi.c -- WM8804 S/PDIF transceiver driver - SPI
+ *
+ * Copyright 2015 Cirrus Logic Inc
+ *
+ * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "wm8804.h"
+
+static int wm8804_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return wm8804_probe(&spi->dev, regmap);
+}
+
+static int wm8804_spi_remove(struct spi_device *spi)
+{
+ wm8804_remove(&spi->dev);
+ return 0;
+}
+
+static const struct of_device_id wm8804_of_match[] = {
+ { .compatible = "wlf,wm8804", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8804_of_match);
+
+static struct spi_driver wm8804_spi_driver = {
+ .driver = {
+ .name = "wm8804",
+ .owner = THIS_MODULE,
+ .of_match_table = wm8804_of_match,
+ },
+ .probe = wm8804_spi_probe,
+ .remove = wm8804_spi_remove
+};
+
+module_spi_driver(wm8804_spi_driver);
+
+MODULE_DESCRIPTION("ASoC WM8804 driver - SPI");
+MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index b2b0e68f707e..1bd4ace29594 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -15,10 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
-#include <linux/i2c.h>
#include <linux/of_device.h>
-#include <linux/spi/spi.h>
-#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -185,9 +182,9 @@ static bool wm8804_volatile(struct device *dev, unsigned int reg)
}
}
-static int wm8804_reset(struct snd_soc_codec *codec)
+static int wm8804_reset(struct wm8804_priv *wm8804)
{
- return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0);
+ return regmap_write(wm8804->regmap, WM8804_RST_DEVID1, 0x0);
}
static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -518,100 +515,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm8804_remove(struct snd_soc_codec *codec)
-{
- struct wm8804_priv *wm8804;
- int i;
-
- wm8804 = snd_soc_codec_get_drvdata(codec);
-
- for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
- regulator_unregister_notifier(wm8804->supplies[i].consumer,
- &wm8804->disable_nb[i]);
- return 0;
-}
-
-static int wm8804_probe(struct snd_soc_codec *codec)
-{
- struct wm8804_priv *wm8804;
- int i, id1, id2, ret;
-
- wm8804 = snd_soc_codec_get_drvdata(codec);
-
- for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
- wm8804->supplies[i].supply = wm8804_supply_names[i];
-
- ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
- wm8804->supplies);
- if (ret) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- return ret;
- }
-
- wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
- wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
-
- /* This should really be moved into the regulator core */
- for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
- ret = regulator_register_notifier(wm8804->supplies[i].consumer,
- &wm8804->disable_nb[i]);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to register regulator notifier: %d\n",
- ret);
- }
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
- wm8804->supplies);
- if (ret) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- return ret;
- }
-
- id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
- if (id1 < 0) {
- dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
- ret = id1;
- goto err_reg_enable;
- }
-
- id2 = snd_soc_read(codec, WM8804_DEVID2);
- if (id2 < 0) {
- dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
- ret = id2;
- goto err_reg_enable;
- }
-
- id2 = (id2 << 8) | id1;
-
- if (id2 != 0x8805) {
- dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
- ret = -EINVAL;
- goto err_reg_enable;
- }
-
- ret = snd_soc_read(codec, WM8804_DEVREV);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to read device revision: %d\n",
- ret);
- goto err_reg_enable;
- }
- dev_info(codec->dev, "revision %c\n", ret + 'A');
-
- ret = wm8804_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
- goto err_reg_enable;
- }
-
- return 0;
-
-err_reg_enable:
- regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
- return ret;
-}
-
static const struct snd_soc_dai_ops wm8804_dai_ops = {
.hw_params = wm8804_hw_params,
.set_fmt = wm8804_set_fmt,
@@ -649,8 +552,6 @@ static struct snd_soc_dai_driver wm8804_dai = {
};
static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
- .probe = wm8804_probe,
- .remove = wm8804_remove,
.set_bias_level = wm8804_set_bias_level,
.idle_bias_off = true,
@@ -658,13 +559,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.num_controls = ARRAY_SIZE(wm8804_snd_controls),
};
-static const struct of_device_id wm8804_of_match[] = {
- { .compatible = "wlf,wm8804", },
- { }
-};
-MODULE_DEVICE_TABLE(of, wm8804_of_match);
-
-static const struct regmap_config wm8804_regmap_config = {
+const struct regmap_config wm8804_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -675,128 +570,110 @@ static const struct regmap_config wm8804_regmap_config = {
.reg_defaults = wm8804_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
};
+EXPORT_SYMBOL_GPL(wm8804_regmap_config);
-#if defined(CONFIG_SPI_MASTER)
-static int wm8804_spi_probe(struct spi_device *spi)
+int wm8804_probe(struct device *dev, struct regmap *regmap)
{
struct wm8804_priv *wm8804;
- int ret;
+ unsigned int id1, id2;
+ int i, ret;
- wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL);
+ wm8804 = devm_kzalloc(dev, sizeof(*wm8804), GFP_KERNEL);
if (!wm8804)
return -ENOMEM;
- wm8804->regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config);
- if (IS_ERR(wm8804->regmap)) {
- ret = PTR_ERR(wm8804->regmap);
+ dev_set_drvdata(dev, wm8804);
+
+ wm8804->regmap = regmap;
+
+ for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
+ wm8804->supplies[i].supply = wm8804_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8804->supplies),
+ wm8804->supplies);
+ if (ret) {
+ dev_err(dev, "Failed to request supplies: %d\n", ret);
return ret;
}
- spi_set_drvdata(spi, wm8804);
+ wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
+ wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
- ret = snd_soc_register_codec(&spi->dev,
- &soc_codec_dev_wm8804, &wm8804_dai, 1);
+ /* This should really be moved into the regulator core */
+ for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
+ ret = regulator_register_notifier(wm8804->supplies[i].consumer,
+ &wm8804->disable_nb[i]);
+ if (ret != 0) {
+ dev_err(dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ }
+ }
- return ret;
-}
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
+ wm8804->supplies);
+ if (ret) {
+ dev_err(dev, "Failed to enable supplies: %d\n", ret);
+ goto err_reg_enable;
+ }
-static int wm8804_spi_remove(struct spi_device *spi)
-{
- snd_soc_unregister_codec(&spi->dev);
- return 0;
-}
+ ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read device ID: %d\n", ret);
+ goto err_reg_enable;
+ }
-static struct spi_driver wm8804_spi_driver = {
- .driver = {
- .name = "wm8804",
- .owner = THIS_MODULE,
- .of_match_table = wm8804_of_match,
- },
- .probe = wm8804_spi_probe,
- .remove = wm8804_spi_remove
-};
-#endif
+ ret = regmap_read(regmap, WM8804_DEVID2, &id2);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read device ID: %d\n", ret);
+ goto err_reg_enable;
+ }
-#if IS_ENABLED(CONFIG_I2C)
-static int wm8804_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct wm8804_priv *wm8804;
- int ret;
+ id2 = (id2 << 8) | id1;
- wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL);
- if (!wm8804)
- return -ENOMEM;
+ if (id2 != 0x8805) {
+ dev_err(dev, "Invalid device ID: %#x\n", id2);
+ ret = -EINVAL;
+ goto err_reg_enable;
+ }
- wm8804->regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config);
- if (IS_ERR(wm8804->regmap)) {
- ret = PTR_ERR(wm8804->regmap);
- return ret;
+ ret = regmap_read(regmap, WM8804_DEVREV, &id1);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read device revision: %d\n",
+ ret);
+ goto err_reg_enable;
}
+ dev_info(dev, "revision %c\n", id1 + 'A');
- i2c_set_clientdata(i2c, wm8804);
+ ret = wm8804_reset(wm8804);
+ if (ret < 0) {
+ dev_err(dev, "Failed to issue reset: %d\n", ret);
+ goto err_reg_enable;
+ }
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_wm8804, &wm8804_dai, 1);
+ return snd_soc_register_codec(dev, &soc_codec_dev_wm8804,
+ &wm8804_dai, 1);
+
+err_reg_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
return ret;
}
+EXPORT_SYMBOL_GPL(wm8804_probe);
-static int wm8804_i2c_remove(struct i2c_client *i2c)
+void wm8804_remove(struct device *dev)
{
- snd_soc_unregister_codec(&i2c->dev);
- return 0;
-}
-
-static const struct i2c_device_id wm8804_i2c_id[] = {
- { "wm8804", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
-
-static struct i2c_driver wm8804_i2c_driver = {
- .driver = {
- .name = "wm8804",
- .owner = THIS_MODULE,
- .of_match_table = wm8804_of_match,
- },
- .probe = wm8804_i2c_probe,
- .remove = wm8804_i2c_remove,
- .id_table = wm8804_i2c_id
-};
-#endif
+ struct wm8804_priv *wm8804;
+ int i;
-static int __init wm8804_modinit(void)
-{
- int ret = 0;
+ wm8804 = dev_get_drvdata(dev);
-#if IS_ENABLED(CONFIG_I2C)
- ret = i2c_add_driver(&wm8804_i2c_driver);
- if (ret) {
- printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
- ret);
- }
-#endif
-#if defined(CONFIG_SPI_MASTER)
- ret = spi_register_driver(&wm8804_spi_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(wm8804_modinit);
+ for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
+ regulator_unregister_notifier(wm8804->supplies[i].consumer,
+ &wm8804->disable_nb[i]);
-static void __exit wm8804_exit(void)
-{
-#if IS_ENABLED(CONFIG_I2C)
- i2c_del_driver(&wm8804_i2c_driver);
-#endif
-#if defined(CONFIG_SPI_MASTER)
- spi_unregister_driver(&wm8804_spi_driver);
-#endif
+ snd_soc_unregister_codec(dev);
}
-module_exit(wm8804_exit);
+EXPORT_SYMBOL_GPL(wm8804_remove);
MODULE_DESCRIPTION("ASoC WM8804 driver");
MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h
index e72d4f4ba6b1..a39a2563dc67 100644
--- a/sound/soc/codecs/wm8804.h
+++ b/sound/soc/codecs/wm8804.h
@@ -13,6 +13,8 @@
#ifndef _WM8804_H
#define _WM8804_H
+#include <linux/regmap.h>
+
/*
* Register values.
*/
@@ -62,4 +64,9 @@
#define WM8804_MCLKDIV_256FS 0
#define WM8804_MCLKDIV_128FS 1
+extern const struct regmap_config wm8804_regmap_config;
+
+int wm8804_probe(struct device *dev, struct regmap *regmap);
+void wm8804_remove(struct device *dev);
+
#endif /* _WM8804_H */
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index ff67b334065b..d01c2095452f 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -420,10 +420,9 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol,
memcpy(ctl->cache, p, ctl->len);
- if (!ctl->enabled) {
- ctl->set = 1;
+ ctl->set = 1;
+ if (!ctl->enabled)
return 0;
- }
return wm_coeff_write_control(kcontrol, p, ctl->len);
}
@@ -1185,7 +1184,6 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
int ret, pos, blocks, type, offset, reg;
char *file;
struct wm_adsp_buf *buf;
- int tmp;
file = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (file == NULL)
@@ -1335,12 +1333,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
}
}
- tmp = le32_to_cpu(blk->len) % 4;
- if (tmp)
- pos += le32_to_cpu(blk->len) + (4 - tmp) + sizeof(*blk);
- else
- pos += le32_to_cpu(blk->len) + sizeof(*blk);
-
+ pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
blocks++;
}
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 2b81ca418d2a..3736d9aabc56 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -1,14 +1,16 @@
config SND_DAVINCI_SOC
- tristate "SoC Audio for TI DAVINCI"
+ tristate
depends on ARCH_DAVINCI
+ select SND_EDMA_SOC
config SND_EDMA_SOC
- tristate "SoC Audio for Texas Instruments chips using eDMA (AM33XX/43XX)"
- depends on SOC_AM33XX || SOC_AM43XX
+ tristate "SoC Audio for Texas Instruments chips using eDMA"
+ depends on SOC_AM33XX || SOC_AM43XX || ARCH_DAVINCI
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M here if you want audio support for TI SoC which uses eDMA.
The following line of SoCs are supported by this platform driver:
+ - daVinci devices
- AM335x
- AM437x/AM438x
@@ -17,7 +19,7 @@ config SND_DAVINCI_SOC_I2S
config SND_DAVINCI_SOC_MCASP
tristate "Multichannel Audio Serial Port (McASP) support"
- depends on SND_DAVINCI_SOC || SND_OMAP_SOC || SND_EDMA_SOC
+ depends on SND_OMAP_SOC || SND_EDMA_SOC
help
Say Y or M here if you want to have support for McASP IP found in
various Texas Instruments SoCs like:
@@ -45,7 +47,7 @@ config SND_AM33XX_SOC_EVM
config SND_DAVINCI_SOC_EVM
tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
- depends on SND_DAVINCI_SOC && I2C
+ depends on SND_EDMA_SOC && I2C
depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
select SND_DAVINCI_SOC_GENERIC_EVM
help
@@ -73,7 +75,7 @@ endchoice
config SND_DM6467_SOC_EVM
tristate "SoC Audio support for DaVinci DM6467 EVM"
- depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM && I2C
+ depends on SND_EDMA_SOC && MACH_DAVINCI_DM6467_EVM && I2C
select SND_DAVINCI_SOC_GENERIC_EVM
select SND_SOC_SPDIF
@@ -82,7 +84,7 @@ config SND_DM6467_SOC_EVM
config SND_DA830_SOC_EVM
tristate "SoC Audio support for DA830/OMAP-L137 EVM"
- depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM && I2C
+ depends on SND_EDMA_SOC && MACH_DAVINCI_DA830_EVM && I2C
select SND_DAVINCI_SOC_GENERIC_EVM
help
@@ -91,7 +93,7 @@ config SND_DA830_SOC_EVM
config SND_DA850_SOC_EVM
tristate "SoC Audio support for DA850/OMAP-L138 EVM"
- depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM && I2C
+ depends on SND_EDMA_SOC && MACH_DAVINCI_DA850_EVM && I2C
select SND_DAVINCI_SOC_GENERIC_EVM
help
Say Y if you want to add support for SoC audio on TI
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index 09bf2ba92d38..f883933c1a19 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -1,11 +1,9 @@
# DAVINCI Platform Support
-snd-soc-davinci-objs := davinci-pcm.o
snd-soc-edma-objs := edma-pcm.o
snd-soc-davinci-i2s-objs := davinci-i2s.o
snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
snd-soc-davinci-vcif-objs:= davinci-vcif.o
-obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o
obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 15fb28fc8e1b..56cb4d95637d 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -23,8 +23,9 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
-#include "davinci-pcm.h"
+#include "edma-pcm.h"
#include "davinci-i2s.h"
@@ -122,7 +123,8 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
struct davinci_mcbsp_dev {
struct device *dev;
- struct davinci_pcm_dma_params dma_params[2];
+ struct snd_dmaengine_dai_dma_data dma_data[2];
+ int dma_request[2];
void __iomem *base;
#define MOD_DSP_A 0
#define MOD_DSP_B 1
@@ -419,8 +421,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
- struct davinci_pcm_dma_params *dma_params =
- &dev->dma_params[substream->stream];
struct snd_interval *i = NULL;
int mcbsp_word_length, master;
unsigned int rcr, xcr, srgr, clk_div, freq, framesize;
@@ -532,8 +532,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
}
- dma_params->acnt = dma_params->data_type = data_type[fmt];
- dma_params->fifo_level = 0;
mcbsp_word_length = asp_word_length[fmt];
switch (master) {
@@ -600,15 +598,6 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
-static int davinci_i2s_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
-
- snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
- return 0;
-}
-
static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -620,7 +609,6 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
- .startup = davinci_i2s_startup,
.shutdown = davinci_i2s_shutdown,
.prepare = davinci_i2s_prepare,
.trigger = davinci_i2s_trigger,
@@ -630,7 +618,18 @@ static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
};
+static int davinci_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+ struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
+ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
+
+ return 0;
+}
+
static struct snd_soc_dai_driver davinci_i2s_dai = {
+ .probe = davinci_i2s_dai_probe,
.playback = {
.channels_min = 2,
.channels_max = 2,
@@ -651,11 +650,9 @@ static const struct snd_soc_component_driver davinci_i2s_component = {
static int davinci_i2s_probe(struct platform_device *pdev)
{
- struct snd_platform_data *pdata = pdev->dev.platform_data;
struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea, *res;
- enum dma_event_q asp_chan_q = EVENTQ_0;
- enum dma_event_q ram_chan_q = EVENTQ_1;
+ int *dma;
int ret;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -676,22 +673,6 @@ static int davinci_i2s_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!dev)
return -ENOMEM;
- if (pdata) {
- dev->enable_channel_combine = pdata->enable_channel_combine;
- dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].sram_size =
- pdata->sram_size_playback;
- dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
- pdata->sram_size_capture;
- dev->clk_input_pin = pdata->clk_input_pin;
- dev->i2s_accurate_sck = pdata->i2s_accurate_sck;
- asp_chan_q = pdata->asp_chan_q;
- ram_chan_q = pdata->ram_chan_q;
- }
-
- dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q;
- dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q;
- dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q;
- dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q;
dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk))
@@ -705,10 +686,10 @@ static int davinci_i2s_probe(struct platform_device *pdev)
goto err_release_clk;
}
- dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
(dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);
- dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
(dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);
/* first TX, then RX */
@@ -718,7 +699,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
ret = -ENXIO;
goto err_release_clk;
}
- dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start;
+ dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
+ *dma = res->start;
+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = dma;
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!res) {
@@ -726,9 +709,11 @@ static int davinci_i2s_probe(struct platform_device *pdev)
ret = -ENXIO;
goto err_release_clk;
}
- dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
- dev->dev = &pdev->dev;
+ dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];
+ *dma = res->start;
+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = dma;
+ dev->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, dev);
ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,
@@ -736,7 +721,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
if (ret != 0)
goto err_release_clk;
- ret = davinci_soc_platform_register(&pdev->dev);
+ ret = edma_pcm_platform_register(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
goto err_unregister_component;
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index de3b155a5011..0c882995a357 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -26,6 +26,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
+#include <linux/platform_data/davinci_asp.h>
#include <sound/asoundef.h>
#include <sound/core.h>
@@ -36,7 +37,6 @@
#include <sound/dmaengine_pcm.h>
#include <sound/omap-pcm.h>
-#include "davinci-pcm.h"
#include "edma-pcm.h"
#include "davinci-mcasp.h"
@@ -65,7 +65,6 @@ struct davinci_mcasp_context {
};
struct davinci_mcasp {
- struct davinci_pcm_dma_params dma_params[2];
struct snd_dmaengine_dai_dma_data dma_data[2];
void __iomem *base;
u32 fifo_base;
@@ -82,6 +81,7 @@ struct davinci_mcasp {
u16 bclk_lrclk_ratio;
int streams;
u32 irq_request[2];
+ int dma_request[2];
int sysclk_freq;
bool bclk_master;
@@ -441,6 +441,18 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
mcasp->bclk_master = 1;
break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ /* codec is clock slave and frame master */
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ mcasp->bclk_master = 1;
+ break;
case SND_SOC_DAIFMT_CBM_CFS:
/* codec is clock master and frame slave */
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
@@ -631,7 +643,6 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
int period_words, int channels)
{
- struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream];
struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream];
int i;
u8 tx_ser = 0;
@@ -699,10 +710,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
* For example if three serializers are enabled the DMA
* need to transfer three words per DMA request.
*/
- dma_params->fifo_level = active_serializers;
dma_data->maxburst = active_serializers;
} else {
- dma_params->fifo_level = 0;
dma_data->maxburst = 0;
}
return 0;
@@ -734,7 +743,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
/* Configure the burst size for platform drivers */
if (numevt == 1)
numevt = 0;
- dma_params->fifo_level = numevt;
dma_data->maxburst = numevt;
return 0;
@@ -860,8 +868,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
- struct davinci_pcm_dma_params *dma_params =
- &mcasp->dma_params[substream->stream];
int word_length;
int channels = params_channels(params);
int period_size = params_period_size(params);
@@ -902,31 +908,26 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S8:
- dma_params->data_type = 1;
word_length = 8;
break;
case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_S16_LE:
- dma_params->data_type = 2;
word_length = 16;
break;
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_S24_3LE:
- dma_params->data_type = 3;
word_length = 24;
break;
case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_S24_LE:
- dma_params->data_type = 4;
word_length = 24;
break;
case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_S32_LE:
- dma_params->data_type = 4;
word_length = 32;
break;
@@ -935,11 +936,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- if (mcasp->version == MCASP_VERSION_2 && !dma_params->fifo_level)
- dma_params->acnt = 4;
- else
- dma_params->acnt = dma_params->data_type;
-
davinci_config_channel_size(mcasp, word_length);
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
@@ -1043,17 +1039,8 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
- if (mcasp->version >= MCASP_VERSION_3) {
- /* Using dmaengine PCM */
- dai->playback_dma_data =
- &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
- dai->capture_dma_data =
- &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
- } else {
- /* Using davinci-pcm */
- dai->playback_dma_data = mcasp->dma_params;
- dai->capture_dma_data = mcasp->dma_params;
- }
+ dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
+ dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
return 0;
}
@@ -1172,28 +1159,24 @@ static const struct snd_soc_component_driver davinci_mcasp_component = {
static struct davinci_mcasp_pdata dm646x_mcasp_pdata = {
.tx_dma_offset = 0x400,
.rx_dma_offset = 0x400,
- .asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_1,
};
static struct davinci_mcasp_pdata da830_mcasp_pdata = {
.tx_dma_offset = 0x2000,
.rx_dma_offset = 0x2000,
- .asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_2,
};
static struct davinci_mcasp_pdata am33xx_mcasp_pdata = {
.tx_dma_offset = 0,
.rx_dma_offset = 0,
- .asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_3,
};
static struct davinci_mcasp_pdata dra7_mcasp_pdata = {
.tx_dma_offset = 0x200,
.rx_dma_offset = 0x284,
- .asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_4,
};
@@ -1370,12 +1353,12 @@ nodata:
static int davinci_mcasp_probe(struct platform_device *pdev)
{
- struct davinci_pcm_dma_params *dma_params;
struct snd_dmaengine_dai_dma_data *dma_data;
struct resource *mem, *ioarea, *res, *dat;
struct davinci_mcasp_pdata *pdata;
struct davinci_mcasp *mcasp;
char *irq_name;
+ int *dma;
int irq;
int ret;
@@ -1509,59 +1492,45 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
if (dat)
mcasp->dat_port = true;
- dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
- dma_params->asp_chan_q = pdata->asp_chan_q;
- dma_params->ram_chan_q = pdata->ram_chan_q;
- dma_params->sram_pool = pdata->sram_pool;
- dma_params->sram_size = pdata->sram_size_playback;
if (dat)
- dma_params->dma_addr = dat->start;
+ dma_data->addr = dat->start;
else
- dma_params->dma_addr = mem->start + pdata->tx_dma_offset;
-
- /* Unconditional dmaengine stuff */
- dma_data->addr = dma_params->dma_addr;
+ dma_data->addr = mem->start + pdata->tx_dma_offset;
+ dma = &mcasp->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (res)
- dma_params->channel = res->start;
+ *dma = res->start;
else
- dma_params->channel = pdata->tx_dma_channel;
+ *dma = pdata->tx_dma_channel;
/* dmaengine filter data for DT and non-DT boot */
if (pdev->dev.of_node)
dma_data->filter_data = "tx";
else
- dma_data->filter_data = &dma_params->channel;
+ dma_data->filter_data = dma;
/* RX is not valid in DIT mode */
if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
- dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE];
dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
- dma_params->asp_chan_q = pdata->asp_chan_q;
- dma_params->ram_chan_q = pdata->ram_chan_q;
- dma_params->sram_pool = pdata->sram_pool;
- dma_params->sram_size = pdata->sram_size_capture;
if (dat)
- dma_params->dma_addr = dat->start;
+ dma_data->addr = dat->start;
else
- dma_params->dma_addr = mem->start + pdata->rx_dma_offset;
-
- /* Unconditional dmaengine stuff */
- dma_data->addr = dma_params->dma_addr;
+ dma_data->addr = mem->start + pdata->rx_dma_offset;
+ dma = &mcasp->dma_request[SNDRV_PCM_STREAM_CAPTURE];
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (res)
- dma_params->channel = res->start;
+ *dma = res->start;
else
- dma_params->channel = pdata->rx_dma_channel;
+ *dma = pdata->rx_dma_channel;
/* dmaengine filter data for DT and non-DT boot */
if (pdev->dev.of_node)
dma_data->filter_data = "rx";
else
- dma_data->filter_data = &dma_params->channel;
+ dma_data->filter_data = dma;
}
if (mcasp->version < MCASP_VERSION_3) {
@@ -1584,17 +1553,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
goto err;
switch (mcasp->version) {
-#if IS_BUILTIN(CONFIG_SND_DAVINCI_SOC) || \
- (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
- IS_MODULE(CONFIG_SND_DAVINCI_SOC))
- case MCASP_VERSION_1:
- case MCASP_VERSION_2:
- ret = davinci_soc_platform_register(&pdev->dev);
- break;
-#endif
#if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \
(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
IS_MODULE(CONFIG_SND_EDMA_SOC))
+ case MCASP_VERSION_1:
+ case MCASP_VERSION_2:
case MCASP_VERSION_3:
ret = edma_pcm_platform_register(&pdev->dev);
break;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
deleted file mode 100644
index 7809e9d935fc..000000000000
--- a/sound/soc/davinci/davinci-pcm.c
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- * ALSA PCM interface for the TI DAVINCI processor
- *
- * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
- * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
- * added SRAM ping/pong (C) 2008 Troy Kisky <troy.kisky@boundarydevices.com>
- *
- * 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>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/genalloc.h>
-#include <linux/platform_data/edma.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/dma.h>
-
-#include "davinci-pcm.h"
-
-#ifdef DEBUG
-static void print_buf_info(int slot, char *name)
-{
- struct edmacc_param p;
- if (slot < 0)
- return;
- edma_read_slot(slot, &p);
- printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n",
- name, slot, p.opt, p.src, p.a_b_cnt, p.dst);
- printk(KERN_DEBUG " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n",
- p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt);
-}
-#else
-static void print_buf_info(int slot, char *name)
-{
-}
-#endif
-
-static struct snd_pcm_hardware pcm_hardware_playback = {
- .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
- SNDRV_PCM_INFO_BATCH),
- .buffer_bytes_max = 128 * 1024,
- .period_bytes_min = 32,
- .period_bytes_max = 8 * 1024,
- .periods_min = 16,
- .periods_max = 255,
- .fifo_size = 0,
-};
-
-static struct snd_pcm_hardware pcm_hardware_capture = {
- .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_BATCH),
- .buffer_bytes_max = 128 * 1024,
- .period_bytes_min = 32,
- .period_bytes_max = 8 * 1024,
- .periods_min = 16,
- .periods_max = 255,
- .fifo_size = 0,
-};
-
-/*
- * How ping/pong works....
- *
- * Playback:
- * ram_params - copys 2*ping_size from start of SDRAM to iram,
- * links to ram_link2
- * ram_link2 - copys rest of SDRAM to iram in ping_size units,
- * links to ram_link
- * ram_link - copys entire SDRAM to iram in ping_size uints,
- * links to self
- *
- * asp_params - same as asp_link[0]
- * asp_link[0] - copys from lower half of iram to asp port
- * links to asp_link[1], triggers iram copy event on completion
- * asp_link[1] - copys from upper half of iram to asp port
- * links to asp_link[0], triggers iram copy event on completion
- * triggers interrupt only needed to let upper SOC levels update position
- * in stream on completion
- *
- * When playback is started:
- * ram_params started
- * asp_params started
- *
- * Capture:
- * ram_params - same as ram_link,
- * links to ram_link
- * ram_link - same as playback
- * links to self
- *
- * asp_params - same as playback
- * asp_link[0] - same as playback
- * asp_link[1] - same as playback
- *
- * When capture is started:
- * asp_params started
- */
-struct davinci_runtime_data {
- spinlock_t lock;
- int period; /* current DMA period */
- int asp_channel; /* Master DMA channel */
- int asp_link[2]; /* asp parameter link channel, ping/pong */
- struct davinci_pcm_dma_params *params; /* DMA params */
- int ram_channel;
- int ram_link;
- int ram_link2;
- struct edmacc_param asp_params;
- struct edmacc_param ram_params;
-};
-
-static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream)
-{
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- prtd->period++;
- if (unlikely(prtd->period >= runtime->periods))
- prtd->period = 0;
-}
-
-static void davinci_pcm_period_reset(struct snd_pcm_substream *substream)
-{
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
-
- prtd->period = 0;
-}
-/*
- * Not used with ping/pong
- */
-static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
-{
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int period_size;
- unsigned int dma_offset;
- dma_addr_t dma_pos;
- dma_addr_t src, dst;
- unsigned short src_bidx, dst_bidx;
- unsigned short src_cidx, dst_cidx;
- unsigned int data_type;
- unsigned short acnt;
- unsigned int count;
- unsigned int fifo_level;
-
- period_size = snd_pcm_lib_period_bytes(substream);
- dma_offset = prtd->period * period_size;
- dma_pos = runtime->dma_addr + dma_offset;
- fifo_level = prtd->params->fifo_level;
-
- pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
- "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos,
- period_size);
-
- data_type = prtd->params->data_type;
- count = period_size / data_type;
- if (fifo_level)
- count /= fifo_level;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- src = dma_pos;
- dst = prtd->params->dma_addr;
- src_bidx = data_type;
- dst_bidx = 4;
- src_cidx = data_type * fifo_level;
- dst_cidx = 0;
- } else {
- src = prtd->params->dma_addr;
- dst = dma_pos;
- src_bidx = 0;
- dst_bidx = data_type;
- src_cidx = 0;
- dst_cidx = data_type * fifo_level;
- }
-
- acnt = prtd->params->acnt;
- edma_set_src(prtd->asp_link[0], src, INCR, W8BIT);
- edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT);
-
- edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx);
- edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx);
-
- if (!fifo_level)
- edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
- ASYNC);
- else
- edma_set_transfer_params(prtd->asp_link[0], acnt,
- fifo_level,
- count, fifo_level,
- ABSYNC);
-}
-
-static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
-{
- struct snd_pcm_substream *substream = data;
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
-
- print_buf_info(prtd->ram_channel, "i ram_channel");
- pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
-
- if (unlikely(ch_status != EDMA_DMA_COMPLETE))
- return;
-
- if (snd_pcm_running(substream)) {
- spin_lock(&prtd->lock);
- if (prtd->ram_channel < 0) {
- /* No ping/pong must fix up link dma data*/
- davinci_pcm_enqueue_dma(substream);
- }
- davinci_pcm_period_elapsed(substream);
- spin_unlock(&prtd->lock);
- snd_pcm_period_elapsed(substream);
- }
-}
-
-#ifdef CONFIG_GENERIC_ALLOCATOR
-static int allocate_sram(struct snd_pcm_substream *substream,
- struct gen_pool *sram_pool, unsigned size,
- struct snd_pcm_hardware *ppcm)
-{
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- struct snd_dma_buffer *iram_dma = NULL;
- dma_addr_t iram_phys = 0;
- void *iram_virt = NULL;
-
- if (buf->private_data || !size)
- return 0;
-
- ppcm->period_bytes_max = size;
- iram_virt = gen_pool_dma_alloc(sram_pool, size, &iram_phys);
- if (!iram_virt)
- goto exit1;
- iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
- if (!iram_dma)
- goto exit2;
- iram_dma->area = iram_virt;
- iram_dma->addr = iram_phys;
- memset(iram_dma->area, 0, size);
- iram_dma->bytes = size;
- buf->private_data = iram_dma;
- return 0;
-exit2:
- if (iram_virt)
- gen_pool_free(sram_pool, (unsigned)iram_virt, size);
-exit1:
- return -ENOMEM;
-}
-
-static void davinci_free_sram(struct snd_pcm_substream *substream,
- struct snd_dma_buffer *iram_dma)
-{
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
- struct gen_pool *sram_pool = prtd->params->sram_pool;
-
- gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
-}
-#else
-static int allocate_sram(struct snd_pcm_substream *substream,
- struct gen_pool *sram_pool, unsigned size,
- struct snd_pcm_hardware *ppcm)
-{
- return 0;
-}
-
-static void davinci_free_sram(struct snd_pcm_substream *substream,
- struct snd_dma_buffer *iram_dma)
-{
-}
-#endif
-
-/*
- * Only used with ping/pong.
- * This is called after runtime->dma_addr, period_bytes and data_type are valid
- */
-static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
-{
- unsigned short ram_src_cidx, ram_dst_cidx;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct davinci_runtime_data *prtd = runtime->private_data;
- struct snd_dma_buffer *iram_dma =
- (struct snd_dma_buffer *)substream->dma_buffer.private_data;
- struct davinci_pcm_dma_params *params = prtd->params;
- unsigned int data_type = params->data_type;
- unsigned int acnt = params->acnt;
- /* divide by 2 for ping/pong */
- unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
- unsigned int fifo_level = prtd->params->fifo_level;
- unsigned int count;
- if ((data_type == 0) || (data_type > 4)) {
- printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type);
- return -EINVAL;
- }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
- ram_src_cidx = ping_size;
- ram_dst_cidx = -ping_size;
- edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT);
-
- edma_set_src_index(prtd->asp_link[0], data_type,
- data_type * fifo_level);
- edma_set_src_index(prtd->asp_link[1], data_type,
- data_type * fifo_level);
-
- edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
- } else {
- dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
- ram_src_cidx = -ping_size;
- ram_dst_cidx = ping_size;
- edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT);
-
- edma_set_dest_index(prtd->asp_link[0], data_type,
- data_type * fifo_level);
- edma_set_dest_index(prtd->asp_link[1], data_type,
- data_type * fifo_level);
-
- edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
- }
-
- if (!fifo_level) {
- count = ping_size / data_type;
- edma_set_transfer_params(prtd->asp_link[0], acnt, count,
- 1, 0, ASYNC);
- edma_set_transfer_params(prtd->asp_link[1], acnt, count,
- 1, 0, ASYNC);
- } else {
- count = ping_size / (data_type * fifo_level);
- edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
- count, fifo_level, ABSYNC);
- edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level,
- count, fifo_level, ABSYNC);
- }
-
- edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx);
- edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx);
- edma_set_transfer_params(prtd->ram_link, ping_size, 2,
- runtime->periods, 2, ASYNC);
-
- /* init master params */
- edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
- edma_read_slot(prtd->ram_link, &prtd->ram_params);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- struct edmacc_param p_ram;
- /* Copy entire iram buffer before playback started */
- prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1);
- /* 0 dst_bidx */
- prtd->ram_params.src_dst_bidx = (ping_size << 1);
- /* 0 dst_cidx */
- prtd->ram_params.src_dst_cidx = (ping_size << 1);
- prtd->ram_params.ccnt = 1;
-
- /* Skip 1st period */
- edma_read_slot(prtd->ram_link, &p_ram);
- p_ram.src += (ping_size << 1);
- p_ram.ccnt -= 1;
- edma_write_slot(prtd->ram_link2, &p_ram);
- /*
- * When 1st started, ram -> iram dma channel will fill the
- * entire iram. Then, whenever a ping/pong asp buffer finishes,
- * 1/2 iram will be filled.
- */
- prtd->ram_params.link_bcntrld =
- EDMA_CHAN_SLOT(prtd->ram_link2) << 5;
- }
- return 0;
-}
-
-/* 1 asp tx or rx channel using 2 parameter channels
- * 1 ram to/from iram channel using 1 parameter channel
- *
- * Playback
- * ram copy channel kicks off first,
- * 1st ram copy of entire iram buffer completion kicks off asp channel
- * asp tcc always kicks off ram copy of 1/2 iram buffer
- *
- * Record
- * asp channel starts, tcc kicks off ram copy
- */
-static int request_ping_pong(struct snd_pcm_substream *substream,
- struct davinci_runtime_data *prtd,
- struct snd_dma_buffer *iram_dma)
-{
- dma_addr_t asp_src_ping;
- dma_addr_t asp_dst_ping;
- int ret;
- struct davinci_pcm_dma_params *params = prtd->params;
-
- /* Request ram master channel */
- ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
- davinci_pcm_dma_irq, substream,
- prtd->params->ram_chan_q);
- if (ret < 0)
- goto exit1;
-
- /* Request ram link channel */
- ret = prtd->ram_link = edma_alloc_slot(
- EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
- if (ret < 0)
- goto exit2;
-
- ret = prtd->asp_link[1] = edma_alloc_slot(
- EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
- if (ret < 0)
- goto exit3;
-
- prtd->ram_link2 = -1;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- ret = prtd->ram_link2 = edma_alloc_slot(
- EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
- if (ret < 0)
- goto exit4;
- }
- /* circle ping-pong buffers */
- edma_link(prtd->asp_link[0], prtd->asp_link[1]);
- edma_link(prtd->asp_link[1], prtd->asp_link[0]);
- /* circle ram buffers */
- edma_link(prtd->ram_link, prtd->ram_link);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- asp_src_ping = iram_dma->addr;
- asp_dst_ping = params->dma_addr; /* fifo */
- } else {
- asp_src_ping = params->dma_addr; /* fifo */
- asp_dst_ping = iram_dma->addr;
- }
- /* ping */
- edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT);
- edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT);
- edma_set_src_index(prtd->asp_link[0], 0, 0);
- edma_set_dest_index(prtd->asp_link[0], 0, 0);
-
- edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
- prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
- prtd->asp_params.opt |= TCCHEN |
- EDMA_TCC(prtd->ram_channel & 0x3f);
- edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
-
- /* pong */
- edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT);
- edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT);
- edma_set_src_index(prtd->asp_link[1], 0, 0);
- edma_set_dest_index(prtd->asp_link[1], 0, 0);
-
- edma_read_slot(prtd->asp_link[1], &prtd->asp_params);
- prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
- /* interrupt after every pong completion */
- prtd->asp_params.opt |= TCINTEN | TCCHEN |
- EDMA_TCC(prtd->ram_channel & 0x3f);
- edma_write_slot(prtd->asp_link[1], &prtd->asp_params);
-
- /* ram */
- edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
- edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
- pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
- "for asp:%u %u %u\n", __func__,
- prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
- prtd->asp_channel, prtd->asp_link[0],
- prtd->asp_link[1]);
- return 0;
-exit4:
- edma_free_channel(prtd->asp_link[1]);
- prtd->asp_link[1] = -1;
-exit3:
- edma_free_channel(prtd->ram_link);
- prtd->ram_link = -1;
-exit2:
- edma_free_channel(prtd->ram_channel);
- prtd->ram_channel = -1;
-exit1:
- return ret;
-}
-
-static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
-{
- struct snd_dma_buffer *iram_dma;
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
- struct davinci_pcm_dma_params *params = prtd->params;
- int ret;
-
- if (!params)
- return -ENODEV;
-
- /* Request asp master DMA channel */
- ret = prtd->asp_channel = edma_alloc_channel(params->channel,
- davinci_pcm_dma_irq, substream,
- prtd->params->asp_chan_q);
- if (ret < 0)
- goto exit1;
-
- /* Request asp link channels */
- ret = prtd->asp_link[0] = edma_alloc_slot(
- EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
- if (ret < 0)
- goto exit2;
-
- iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
- if (iram_dma) {
- if (request_ping_pong(substream, prtd, iram_dma) == 0)
- return 0;
- printk(KERN_WARNING "%s: dma channel allocation failed,"
- "not using sram\n", __func__);
- }
-
- /* Issue transfer completion IRQ when the channel completes a
- * transfer, then always reload from the same slot (by a kind
- * of loopback link). The completion IRQ handler will update
- * the reload slot with a new buffer.
- *
- * REVISIT save p_ram here after setting up everything except
- * the buffer and its length (ccnt) ... use it as a template
- * so davinci_pcm_enqueue_dma() takes less time in IRQ.
- */
- edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
- prtd->asp_params.opt |= TCINTEN |
- EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
- prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5;
- edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
- return 0;
-exit2:
- edma_free_channel(prtd->asp_channel);
- prtd->asp_channel = -1;
-exit1:
- return ret;
-}
-
-static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
- int ret = 0;
-
- spin_lock(&prtd->lock);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- edma_start(prtd->asp_channel);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- prtd->ram_channel >= 0) {
- /* copy 1st iram buffer */
- edma_start(prtd->ram_channel);
- }
- break;
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- edma_resume(prtd->asp_channel);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- edma_pause(prtd->asp_channel);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- spin_unlock(&prtd->lock);
-
- return ret;
-}
-
-static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct davinci_runtime_data *prtd = substream->runtime->private_data;
-
- davinci_pcm_period_reset(substream);
- if (prtd->ram_channel >= 0) {
- int ret = ping_pong_dma_setup(substream);
- if (ret < 0)
- return ret;
-
- edma_write_slot(prtd->ram_channel, &prtd->ram_params);
- edma_write_slot(prtd->asp_channel, &prtd->asp_params);
-
- print_buf_info(prtd->ram_channel, "ram_channel");
- print_buf_info(prtd->ram_link, "ram_link");
- print_buf_info(prtd->ram_link2, "ram_link2");
- print_buf_info(prtd->asp_channel, "asp_channel");
- print_buf_info(prtd->asp_link[0], "asp_link[0]");
- print_buf_info(prtd->asp_link[1], "asp_link[1]");
-
- /*
- * There is a phase offset of 2 periods between the position
- * used by dma setup and the position reported in the pointer
- * function.
- *
- * The phase offset, when not using ping-pong buffers, is due to
- * the two consecutive calls to davinci_pcm_enqueue_dma() below.
- *
- * Whereas here, with ping-pong buffers, the phase is due to
- * there being an entire buffer transfer complete before the
- * first dma completion event triggers davinci_pcm_dma_irq().
- */
- davinci_pcm_period_elapsed(substream);
- davinci_pcm_period_elapsed(substream);
-
- return 0;
- }
- davinci_pcm_enqueue_dma(substream);
- davinci_pcm_period_elapsed(substream);
-
- /* Copy self-linked parameter RAM entry into master channel */
- edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
- edma_write_slot(prtd->asp_channel, &prtd->asp_params);
- davinci_pcm_enqueue_dma(substream);
- davinci_pcm_period_elapsed(substream);
-
- return 0;
-}
-
-static snd_pcm_uframes_t
-davinci_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct davinci_runtime_data *prtd = runtime->private_data;
- unsigned int offset;
- int asp_count;
- unsigned int period_size = snd_pcm_lib_period_bytes(substream);
-
- /*
- * There is a phase offset of 2 periods between the position used by dma
- * setup and the position reported in the pointer function. Either +2 in
- * the dma setup or -2 here in the pointer function (with wrapping,
- * both) accounts for this offset -- choose the latter since it makes
- * the first-time setup clearer.
- */
- spin_lock(&prtd->lock);
- asp_count = prtd->period - 2;
- spin_unlock(&prtd->lock);
-
- if (asp_count < 0)
- asp_count += runtime->periods;
- asp_count *= period_size;
-
- offset = bytes_to_frames(runtime, asp_count);
- if (offset >= runtime->buffer_size)
- offset = 0;
-
- return offset;
-}
-
-static int davinci_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct davinci_runtime_data *prtd;
- struct snd_pcm_hardware *ppcm;
- int ret = 0;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct davinci_pcm_dma_params *pa;
- struct davinci_pcm_dma_params *params;
-
- pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- if (!pa)
- return -ENODEV;
- params = &pa[substream->stream];
-
- ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- &pcm_hardware_playback : &pcm_hardware_capture;
- allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
- snd_soc_set_runtime_hwparams(substream, ppcm);
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- return ret;
-
- prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
- if (prtd == NULL)
- return -ENOMEM;
-
- spin_lock_init(&prtd->lock);
- prtd->params = params;
- prtd->asp_channel = -1;
- prtd->asp_link[0] = prtd->asp_link[1] = -1;
- prtd->ram_channel = -1;
- prtd->ram_link = -1;
- prtd->ram_link2 = -1;
-
- runtime->private_data = prtd;
-
- ret = davinci_pcm_dma_request(substream);
- if (ret) {
- printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
- kfree(prtd);
- }
-
- return ret;
-}
-
-static int davinci_pcm_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct davinci_runtime_data *prtd = runtime->private_data;
-
- if (prtd->ram_channel >= 0)
- edma_stop(prtd->ram_channel);
- if (prtd->asp_channel >= 0)
- edma_stop(prtd->asp_channel);
- if (prtd->asp_link[0] >= 0)
- edma_unlink(prtd->asp_link[0]);
- if (prtd->asp_link[1] >= 0)
- edma_unlink(prtd->asp_link[1]);
- if (prtd->ram_link >= 0)
- edma_unlink(prtd->ram_link);
-
- if (prtd->asp_link[0] >= 0)
- edma_free_slot(prtd->asp_link[0]);
- if (prtd->asp_link[1] >= 0)
- edma_free_slot(prtd->asp_link[1]);
- if (prtd->asp_channel >= 0)
- edma_free_channel(prtd->asp_channel);
- if (prtd->ram_link >= 0)
- edma_free_slot(prtd->ram_link);
- if (prtd->ram_link2 >= 0)
- edma_free_slot(prtd->ram_link2);
- if (prtd->ram_channel >= 0)
- edma_free_channel(prtd->ram_channel);
-
- kfree(prtd);
-
- return 0;
-}
-
-static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- return snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
-}
-
-static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
-}
-
-static struct snd_pcm_ops davinci_pcm_ops = {
- .open = davinci_pcm_open,
- .close = davinci_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = davinci_pcm_hw_params,
- .hw_free = davinci_pcm_hw_free,
- .prepare = davinci_pcm_prepare,
- .trigger = davinci_pcm_trigger,
- .pointer = davinci_pcm_pointer,
- .mmap = davinci_pcm_mmap,
-};
-
-static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
- size_t size)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
-
- pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
- "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
-
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-
-static void davinci_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- struct snd_dma_buffer *iram_dma;
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- iram_dma = buf->private_data;
- if (iram_dma) {
- davinci_free_sram(substream, iram_dma);
- kfree(iram_dma);
- }
- }
-}
-
-static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
- int ret;
-
- ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = davinci_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK,
- pcm_hardware_playback.buffer_bytes_max);
- if (ret)
- return ret;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = davinci_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE,
- pcm_hardware_capture.buffer_bytes_max);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_platform_driver davinci_soc_platform = {
- .ops = &davinci_pcm_ops,
- .pcm_new = davinci_pcm_new,
- .pcm_free = davinci_pcm_free,
-};
-
-int davinci_soc_platform_register(struct device *dev)
-{
- return devm_snd_soc_register_platform(dev, &davinci_soc_platform);
-}
-EXPORT_SYMBOL_GPL(davinci_soc_platform_register);
-
-MODULE_AUTHOR("Vladimir Barinov");
-MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
deleted file mode 100644
index 0fe2346a9aa2..000000000000
--- a/sound/soc/davinci/davinci-pcm.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * ALSA PCM interface for the TI DAVINCI processor
- *
- * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
- * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
- *
- * 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.
- */
-
-#ifndef _DAVINCI_PCM_H
-#define _DAVINCI_PCM_H
-
-#include <linux/genalloc.h>
-#include <linux/platform_data/davinci_asp.h>
-#include <linux/platform_data/edma.h>
-
-struct davinci_pcm_dma_params {
- int channel; /* sync dma channel ID */
- unsigned short acnt;
- dma_addr_t dma_addr; /* device physical address for DMA */
- unsigned sram_size;
- struct gen_pool *sram_pool; /* SRAM gen_pool for ping pong */
- enum dma_event_q asp_chan_q; /* event queue number for ASP channel */
- enum dma_event_q ram_chan_q; /* event queue number for RAM channel */
- unsigned char data_type; /* xfer data type */
- unsigned char convert_mono_stereo;
- unsigned int fifo_level;
-};
-
-#if IS_ENABLED(CONFIG_SND_DAVINCI_SOC)
-int davinci_soc_platform_register(struct device *dev);
-#else
-static inline int davinci_soc_platform_register(struct device *dev)
-{
- return 0;
-}
-#endif /* CONFIG_SND_DAVINCI_SOC */
-
-#endif
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 5bee04279ebe..fabd05f24aeb 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -33,8 +33,9 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
-#include "davinci-pcm.h"
+#include "edma-pcm.h"
#include "davinci-i2s.h"
#define MOD_REG_BIT(val, mask, set) do { \
@@ -47,7 +48,8 @@
struct davinci_vcif_dev {
struct davinci_vc *davinci_vc;
- struct davinci_pcm_dma_params dma_params[2];
+ struct snd_dmaengine_dai_dma_data dma_data[2];
+ int dma_request[2];
};
static void davinci_vcif_start(struct snd_pcm_substream *substream)
@@ -93,8 +95,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
{
struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai);
struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
- struct davinci_pcm_dma_params *dma_params =
- &davinci_vcif_dev->dma_params[substream->stream];
u32 w;
/* Restart the codec before setup */
@@ -113,16 +113,12 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
/* Determine xfer data type */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_U8:
- dma_params->data_type = 0;
-
MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
DAVINCI_VC_CTRL_RD_UNSIGNED |
DAVINCI_VC_CTRL_WD_BITS_8 |
DAVINCI_VC_CTRL_WD_UNSIGNED, 1);
break;
case SNDRV_PCM_FORMAT_S8:
- dma_params->data_type = 1;
-
MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
DAVINCI_VC_CTRL_WD_BITS_8, 1);
@@ -130,8 +126,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
DAVINCI_VC_CTRL_WD_UNSIGNED, 0);
break;
case SNDRV_PCM_FORMAT_S16_LE:
- dma_params->data_type = 2;
-
MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
DAVINCI_VC_CTRL_RD_UNSIGNED |
DAVINCI_VC_CTRL_WD_BITS_8 |
@@ -142,8 +136,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- dma_params->acnt = dma_params->data_type;
-
writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
return 0;
@@ -172,24 +164,25 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
-static int davinci_vcif_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai);
-
- snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
- return 0;
-}
-
#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000
static const struct snd_soc_dai_ops davinci_vcif_dai_ops = {
- .startup = davinci_vcif_startup,
.trigger = davinci_vcif_trigger,
.hw_params = davinci_vcif_hw_params,
};
+static int davinci_vcif_dai_probe(struct snd_soc_dai *dai)
+{
+ struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
+ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
+
+ return 0;
+}
+
static struct snd_soc_dai_driver davinci_vcif_dai = {
+ .probe = davinci_vcif_dai_probe,
.playback = {
.channels_min = 1,
.channels_max = 2,
@@ -225,16 +218,16 @@ static int davinci_vcif_probe(struct platform_device *pdev)
/* DMA tx params */
davinci_vcif_dev->davinci_vc = davinci_vc;
- davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel =
- davinci_vc->davinci_vcif.dma_tx_channel;
- davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
- davinci_vc->davinci_vcif.dma_tx_addr;
+ davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data =
+ &davinci_vc->davinci_vcif.dma_tx_channel;
+ davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
+ davinci_vc->davinci_vcif.dma_tx_addr;
/* DMA rx params */
- davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel =
- davinci_vc->davinci_vcif.dma_rx_channel;
- davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
- davinci_vc->davinci_vcif.dma_rx_addr;
+ davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data =
+ &davinci_vc->davinci_vcif.dma_rx_channel;
+ davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
+ davinci_vc->davinci_vcif.dma_rx_addr;
dev_set_drvdata(&pdev->dev, davinci_vcif_dev);
@@ -245,7 +238,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
return ret;
}
- ret = davinci_soc_platform_register(&pdev->dev);
+ ret = edma_pcm_platform_register(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
snd_soc_unregister_component(&pdev->dev);
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 3f6959c8e2f7..de438871040b 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -512,6 +512,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
memcpy(priv->dai_link, fsl_asoc_card_dai,
sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
+ ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
+ goto asrc_fail;
+ }
+
/* Normal DAI Link */
priv->dai_link[0].cpu_of_node = cpu_np;
priv->dai_link[0].codec_of_node = codec_np;
diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c
index f8cf10e16ce9..20e7400e2611 100644
--- a/sound/soc/fsl/imx-es8328.c
+++ b/sound/soc/fsl/imx-es8328.c
@@ -53,9 +53,9 @@ static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd)
/* Headphone jack detection */
if (gpio_is_valid(data->jack_gpio)) {
- ret = snd_soc_jack_new(rtd->codec, "Headphone",
- SND_JACK_HEADPHONE | SND_JACK_BTN_0,
- &headset_jack);
+ ret = snd_soc_card_jack_new(rtd->card, "Headphone",
+ SND_JACK_HEADPHONE | SND_JACK_BTN_0,
+ &headset_jack, NULL, 0);
if (ret)
return ret;
diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c
index a958937ab405..0653aa83c927 100644
--- a/sound/soc/fsl/wm1133-ev1.c
+++ b/sound/soc/fsl/wm1133-ev1.c
@@ -205,16 +205,14 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
/* Headphone jack detection */
- snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
- snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
- hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphone", SND_JACK_HEADPHONE,
+ &hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);
/* Microphone jack detection */
- snd_soc_jack_new(codec, "Microphone",
- SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack);
- snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
- mic_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Microphone",
+ SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack,
+ mic_jack_pins, ARRAY_SIZE(mic_jack_pins));
wm8350_mic_jack_detect(codec, &mic_jack, SND_JACK_MICROPHONE,
SND_JACK_BTN_0);
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index fb550b5869d2..c49a408fc7a6 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -176,11 +176,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
return ret;
if (gpio_is_valid(priv->gpio_hp_det)) {
- snd_soc_jack_new(codec->codec, "Headphones", SND_JACK_HEADPHONE,
- &simple_card_hp_jack);
- snd_soc_jack_add_pins(&simple_card_hp_jack,
- ARRAY_SIZE(simple_card_hp_jack_pins),
- simple_card_hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphones",
+ SND_JACK_HEADPHONE,
+ &simple_card_hp_jack,
+ simple_card_hp_jack_pins,
+ ARRAY_SIZE(simple_card_hp_jack_pins));
simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det;
simple_card_hp_jack_gpio.invert = priv->gpio_hp_det_invert;
@@ -189,11 +189,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
}
if (gpio_is_valid(priv->gpio_mic_det)) {
- snd_soc_jack_new(codec->codec, "Mic Jack", SND_JACK_MICROPHONE,
- &simple_card_mic_jack);
- snd_soc_jack_add_pins(&simple_card_mic_jack,
- ARRAY_SIZE(simple_card_mic_jack_pins),
- simple_card_mic_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Mic Jack",
+ SND_JACK_MICROPHONE,
+ &simple_card_mic_jack,
+ simple_card_mic_jack_pins,
+ ARRAY_SIZE(simple_card_mic_jack_pins));
simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det;
simple_card_mic_jack_gpio.invert = priv->gpio_mic_det_invert;
snd_soc_jack_add_gpios(&simple_card_mic_jack, 1,
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c
index 9cf7d01479ad..fc5542034b9b 100644
--- a/sound/soc/intel/broadwell.c
+++ b/sound/soc/intel/broadwell.c
@@ -80,15 +80,9 @@ static int broadwell_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
int ret = 0;
- ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset);
-
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&broadwell_headset,
- ARRAY_SIZE(broadwell_headset_pins),
- broadwell_headset_pins);
+ ret = snd_soc_card_jack_new(rtd->card, "Headset",
+ SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset,
+ broadwell_headset_pins, ARRAY_SIZE(broadwell_headset_pins));
if (ret)
return ret;
@@ -110,9 +104,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2;
/* set SSP0 to 16 bit */
- snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
- SNDRV_PCM_HW_PARAM_FIRST_MASK],
- SNDRV_PCM_FORMAT_S16_LE);
+ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
return 0;
}
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c
index 9832afe7d22c..d8b1f038da1c 100644
--- a/sound/soc/intel/byt-max98090.c
+++ b/sound/soc/intel/byt-max98090.c
@@ -84,7 +84,6 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = {
static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
{
int ret;
- struct snd_soc_codec *codec = runtime->codec;
struct snd_soc_card *card = runtime->card;
struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card);
struct snd_soc_jack *jack = &drv->jack;
@@ -100,13 +99,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
}
/* Enable jack detection */
- ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_LINEOUT | SND_JACK_HEADSET, jack);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
+ ret = snd_soc_card_jack_new(runtime->card, "Headset",
+ SND_JACK_LINEOUT | SND_JACK_HEADSET, jack,
+ hs_jack_pins, ARRAY_SIZE(hs_jack_pins));
if (ret)
return ret;
diff --git a/sound/soc/intel/bytcr_dpcm_rt5640.c b/sound/soc/intel/bytcr_dpcm_rt5640.c
index 59308629043e..3b262d01c1b3 100644
--- a/sound/soc/intel/bytcr_dpcm_rt5640.c
+++ b/sound/soc/intel/bytcr_dpcm_rt5640.c
@@ -113,9 +113,7 @@ static int byt_codec_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2;
/* set SSP2 to 24-bit */
- snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
- SNDRV_PCM_HW_PARAM_FIRST_MASK],
- SNDRV_PCM_FORMAT_S24_LE);
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
diff --git a/sound/soc/intel/cht_bsw_rt5645.c b/sound/soc/intel/cht_bsw_rt5645.c
index bd29617a9ab9..012227997ed9 100644
--- a/sound/soc/intel/cht_bsw_rt5645.c
+++ b/sound/soc/intel/cht_bsw_rt5645.c
@@ -169,17 +169,17 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
return ret;
}
- ret = snd_soc_jack_new(codec, "Headphone Jack",
- SND_JACK_HEADPHONE,
- &ctx->hp_jack);
+ ret = snd_soc_card_jack_new(runtime->card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &ctx->hp_jack,
+ NULL, 0);
if (ret) {
dev_err(runtime->dev, "HP jack creation failed %d\n", ret);
return ret;
}
- ret = snd_soc_jack_new(codec, "Mic Jack",
- SND_JACK_MICROPHONE,
- &ctx->mic_jack);
+ ret = snd_soc_card_jack_new(runtime->card, "Mic Jack",
+ SND_JACK_MICROPHONE, &ctx->mic_jack,
+ NULL, 0);
if (ret) {
dev_err(runtime->dev, "Mic jack creation failed %d\n", ret);
return ret;
@@ -203,9 +203,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2;
/* set SSP2 to 24-bit */
- snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
- SNDRV_PCM_HW_PARAM_FIRST_MASK],
- SNDRV_PCM_FORMAT_S24_LE);
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
diff --git a/sound/soc/intel/cht_bsw_rt5672.c b/sound/soc/intel/cht_bsw_rt5672.c
index ff016621583a..bc8dcacd5e6a 100644
--- a/sound/soc/intel/cht_bsw_rt5672.c
+++ b/sound/soc/intel/cht_bsw_rt5672.c
@@ -178,9 +178,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2;
/* set SSP2 to 24-bit */
- snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
- SNDRV_PCM_HW_PARAM_FIRST_MASK],
- SNDRV_PCM_FORMAT_S24_LE);
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
@@ -217,7 +215,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
+ .nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
@@ -240,13 +238,13 @@ static struct snd_soc_dai_link cht_dailink[] = {
.cpu_dai_name = "ssp2-port",
.platform_name = "sst-mfld-platform",
.no_pcm = 1,
+ .nonatomic = true,
.codec_dai_name = "rt5670-aif1",
.codec_name = "i2c-10EC5670:00",
.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
| SND_SOC_DAIFMT_CBS_CFS,
.init = cht_codec_init,
.be_hw_params_fixup = cht_codec_fixup,
- .ignore_suspend = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ops = &cht_be_ssp2_ops,
@@ -285,7 +283,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_cht_mc_driver = {
.driver = {
.name = "cht-bsw-rt5672",
- .pm = &snd_soc_pm_ops,
},
.probe = snd_cht_mc_probe,
};
diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/haswell.c
index 35edf51a52aa..00fddd3f5dfb 100644
--- a/sound/soc/intel/haswell.c
+++ b/sound/soc/intel/haswell.c
@@ -56,9 +56,7 @@ static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2;
/* set SSP0 to 16 bit */
- snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
- SNDRV_PCM_HW_PARAM_FIRST_MASK],
- SNDRV_PCM_FORMAT_S16_LE);
+ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
return 0;
}
diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c
index 90b7a57713a0..49c09a0add79 100644
--- a/sound/soc/intel/mfld_machine.c
+++ b/sound/soc/intel/mfld_machine.c
@@ -228,10 +228,13 @@ static void mfld_jack_check(unsigned int intr_status)
{
struct mfld_jack_data jack_data;
+ if (!mfld_codec)
+ return;
+
jack_data.mfld_jack = &mfld_jack;
jack_data.intr_id = intr_status;
- sn95031_jack_detection(&jack_data);
+ sn95031_jack_detection(mfld_codec, &jack_data);
/* TODO: add american headset detection post gpiolib support */
}
@@ -240,8 +243,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
struct snd_soc_dapm_context *dapm = &runtime->card->dapm;
int ret_val;
- mfld_codec = runtime->codec;
-
/* default is earpiece pin, userspace sets it explcitly */
snd_soc_dapm_disable_pin(dapm, "Headphones");
/* default is lineout NC, userspace sets it explcitly */
@@ -254,20 +255,15 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
snd_soc_dapm_disable_pin(dapm, "LINEINR");
/* Headset and button jack detection */
- ret_val = snd_soc_jack_new(mfld_codec, "Intel(R) MID Audio Jack",
- SND_JACK_HEADSET | SND_JACK_BTN_0 |
- SND_JACK_BTN_1, &mfld_jack);
+ ret_val = snd_soc_card_jack_new(runtime->card,
+ "Intel(R) MID Audio Jack", SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1, &mfld_jack,
+ mfld_jack_pins, ARRAY_SIZE(mfld_jack_pins));
if (ret_val) {
pr_err("jack creation failed\n");
return ret_val;
}
- ret_val = snd_soc_jack_add_pins(&mfld_jack,
- ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins);
- if (ret_val) {
- pr_err("adding jack pins failed\n");
- return ret_val;
- }
ret_val = snd_soc_jack_add_zones(&mfld_jack,
ARRAY_SIZE(mfld_zones), mfld_zones);
if (ret_val) {
@@ -275,6 +271,8 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
return ret_val;
}
+ mfld_codec = runtime->codec;
+
/* we want to check if anything is inserted at boot,
* so send a fake event to codec and it will read adc
* to find if anything is there or not */
@@ -359,8 +357,6 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
{
struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
- if (mfld_jack.codec == NULL)
- return IRQ_HANDLED;
mfld_jack_check(mc_drv_ctx->interrupt_status);
return IRQ_HANDLED;
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c
index 7523cbef8780..2fbaf2c75d17 100644
--- a/sound/soc/intel/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/sst-mfld-platform-pcm.c
@@ -594,11 +594,13 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
ret_val = stream->ops->stream_drop(sst->dev, str_id);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
dev_dbg(rtd->dev, "sst: in pause\n");
status = SST_PLATFORM_PAUSED;
ret_val = stream->ops->stream_pause(sst->dev, str_id);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
dev_dbg(rtd->dev, "sst: in pause release\n");
status = SST_PLATFORM_RUNNING;
ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
@@ -665,6 +667,9 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int sst_soc_probe(struct snd_soc_platform *platform)
{
+ struct sst_data *drv = dev_get_drvdata(platform->dev);
+
+ drv->soc_card = platform->component.card;
return sst_dsp_init_v2_dpcm(platform);
}
@@ -727,9 +732,64 @@ static int sst_platform_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+
+static int sst_soc_prepare(struct device *dev)
+{
+ struct sst_data *drv = dev_get_drvdata(dev);
+ int i;
+
+ /* suspend all pcms first */
+ snd_soc_suspend(drv->soc_card->dev);
+ snd_soc_poweroff(drv->soc_card->dev);
+
+ /* set the SSPs to idle */
+ for (i = 0; i < drv->soc_card->num_rtd; i++) {
+ struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+
+ if (dai->active) {
+ send_ssp_cmd(dai, dai->name, 0);
+ sst_handle_vb_timer(dai, false);
+ }
+ }
+
+ return 0;
+}
+
+static void sst_soc_complete(struct device *dev)
+{
+ struct sst_data *drv = dev_get_drvdata(dev);
+ int i;
+
+ /* restart SSPs */
+ for (i = 0; i < drv->soc_card->num_rtd; i++) {
+ struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+
+ if (dai->active) {
+ sst_handle_vb_timer(dai, true);
+ send_ssp_cmd(dai, dai->name, 1);
+ }
+ }
+ snd_soc_resume(drv->soc_card->dev);
+}
+
+#else
+
+#define sst_soc_prepare NULL
+#define sst_soc_complete NULL
+
+#endif
+
+
+static const struct dev_pm_ops sst_platform_pm = {
+ .prepare = sst_soc_prepare,
+ .complete = sst_soc_complete,
+};
+
static struct platform_driver sst_platform_driver = {
.driver = {
.name = "sst-mfld-platform",
+ .pm = &sst_platform_pm,
},
.probe = sst_platform_probe,
.remove = sst_platform_remove,
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h
index 79c8d1246a8f..9094314be2b0 100644
--- a/sound/soc/intel/sst-mfld-platform.h
+++ b/sound/soc/intel/sst-mfld-platform.h
@@ -174,6 +174,7 @@ struct sst_data {
struct sst_platform_data *pdata;
struct snd_sst_bytes_v2 *byte_stream;
struct mutex lock;
+ struct snd_soc_card *soc_card;
};
int sst_register_dsp(struct sst_device *sst);
int sst_unregister_dsp(struct sst_device *sst);
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c
index 11c578651c1c..1a7eeec444b1 100644
--- a/sound/soc/intel/sst/sst.c
+++ b/sound/soc/intel/sst/sst.c
@@ -423,23 +423,135 @@ static int intel_sst_runtime_suspend(struct device *dev)
return ret;
}
-static int intel_sst_runtime_resume(struct device *dev)
+static int intel_sst_suspend(struct device *dev)
{
- int ret = 0;
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+ struct sst_fw_save *fw_save;
+ int i, ret = 0;
- if (ctx->sst_state == SST_RESET) {
- ret = sst_load_fw(ctx);
- if (ret) {
- dev_err(dev, "FW download fail %d\n", ret);
- sst_set_fw_state_locked(ctx, SST_RESET);
+ /* check first if we are already in SW reset */
+ if (ctx->sst_state == SST_RESET)
+ return 0;
+
+ /*
+ * check if any stream is active and running
+ * they should already by suspend by soc_suspend
+ */
+ for (i = 1; i <= ctx->info.max_streams; i++) {
+ struct stream_info *stream = &ctx->streams[i];
+
+ if (stream->status == STREAM_RUNNING) {
+ dev_err(dev, "stream %d is running, cant susupend, abort\n", i);
+ return -EBUSY;
}
}
+ synchronize_irq(ctx->irq_num);
+ flush_workqueue(ctx->post_msg_wq);
+
+ /* Move the SST state to Reset */
+ sst_set_fw_state_locked(ctx, SST_RESET);
+
+ /* tell DSP we are suspending */
+ if (ctx->ops->save_dsp_context(ctx))
+ return -EBUSY;
+
+ /* save the memories */
+ fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
+ if (!fw_save)
+ return -ENOMEM;
+ fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
+ if (!fw_save->iram) {
+ ret = -ENOMEM;
+ goto iram;
+ }
+ fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
+ if (!fw_save->dram) {
+ ret = -ENOMEM;
+ goto dram;
+ }
+ fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
+ if (!fw_save->sram) {
+ ret = -ENOMEM;
+ goto sram;
+ }
+
+ fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
+ if (!fw_save->ddr) {
+ ret = -ENOMEM;
+ goto ddr;
+ }
+
+ memcpy32_fromio(fw_save->iram, ctx->iram, ctx->iram_end - ctx->iram_base);
+ memcpy32_fromio(fw_save->dram, ctx->dram, ctx->dram_end - ctx->dram_base);
+ memcpy32_fromio(fw_save->sram, ctx->mailbox, SST_MAILBOX_SIZE);
+ memcpy32_fromio(fw_save->ddr, ctx->ddr, ctx->ddr_end - ctx->ddr_base);
+
+ ctx->fw_save = fw_save;
+ ctx->ops->reset(ctx);
+ return 0;
+ddr:
+ kfree(fw_save->sram);
+sram:
+ kfree(fw_save->dram);
+dram:
+ kfree(fw_save->iram);
+iram:
+ kfree(fw_save);
+ return ret;
+}
+
+static int intel_sst_resume(struct device *dev)
+{
+ struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+ struct sst_fw_save *fw_save = ctx->fw_save;
+ int ret = 0;
+ struct sst_block *block;
+
+ if (!fw_save)
+ return 0;
+
+ sst_set_fw_state_locked(ctx, SST_FW_LOADING);
+
+ /* we have to restore the memory saved */
+ ctx->ops->reset(ctx);
+
+ ctx->fw_save = NULL;
+
+ memcpy32_toio(ctx->iram, fw_save->iram, ctx->iram_end - ctx->iram_base);
+ memcpy32_toio(ctx->dram, fw_save->dram, ctx->dram_end - ctx->dram_base);
+ memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
+ memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
+
+ kfree(fw_save->sram);
+ kfree(fw_save->dram);
+ kfree(fw_save->iram);
+ kfree(fw_save->ddr);
+ kfree(fw_save);
+
+ block = sst_create_block(ctx, 0, FW_DWNL_ID);
+ if (block == NULL)
+ return -ENOMEM;
+
+
+ /* start and wait for ack */
+ ctx->ops->start(ctx);
+ ret = sst_wait_timeout(ctx, block);
+ if (ret) {
+ dev_err(ctx->dev, "fw download failed %d\n", ret);
+ /* FW download failed due to timeout */
+ ret = -EBUSY;
+
+ } else {
+ sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
+ }
+
+ sst_free_block(ctx, block);
return ret;
}
const struct dev_pm_ops intel_sst_pm = {
+ .suspend = intel_sst_suspend,
+ .resume = intel_sst_resume,
.runtime_suspend = intel_sst_runtime_suspend,
- .runtime_resume = intel_sst_runtime_resume,
};
EXPORT_SYMBOL_GPL(intel_sst_pm);
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/sst/sst.h
index 562bc483d6b7..3f493862e98d 100644
--- a/sound/soc/intel/sst/sst.h
+++ b/sound/soc/intel/sst/sst.h
@@ -337,6 +337,13 @@ struct sst_shim_regs64 {
u64 csr2;
};
+struct sst_fw_save {
+ void *iram;
+ void *dram;
+ void *sram;
+ void *ddr;
+};
+
/**
* struct intel_sst_drv - driver ops
*
@@ -428,6 +435,8 @@ struct intel_sst_drv {
* persistent till worker thread gets called
*/
char firmware_name[FW_NAME_SIZE];
+
+ struct sst_fw_save *fw_save;
};
/* misc definitions */
@@ -544,4 +553,7 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx,
int sst_context_init(struct intel_sst_drv *ctx);
void sst_context_cleanup(struct intel_sst_drv *ctx);
void sst_configure_runtime_pm(struct intel_sst_drv *ctx);
+void memcpy32_toio(void __iomem *dst, const void *src, int count);
+void memcpy32_fromio(void *dst, const void __iomem *src, int count);
+
#endif
diff --git a/sound/soc/intel/sst/sst_drv_interface.c b/sound/soc/intel/sst/sst_drv_interface.c
index 5f75ef3cdd22..f0e4b99b3aeb 100644
--- a/sound/soc/intel/sst/sst_drv_interface.c
+++ b/sound/soc/intel/sst/sst_drv_interface.c
@@ -138,12 +138,36 @@ int sst_get_stream(struct intel_sst_drv *ctx,
static int sst_power_control(struct device *dev, bool state)
{
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
- dev_dbg(ctx->dev, "state:%d", state);
- if (state == true)
- return pm_runtime_get_sync(dev);
- else
+ int ret = 0;
+ int usage_count = 0;
+
+#ifdef CONFIG_PM
+ usage_count = atomic_read(&dev->power.usage_count);
+#else
+ usage_count = 1;
+#endif
+
+ if (state == true) {
+ ret = pm_runtime_get_sync(dev);
+
+ dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
+ return ret;
+ }
+ if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
+ ret = sst_load_fw(ctx);
+ if (ret) {
+ dev_err(dev, "FW download fail %d\n", ret);
+ sst_set_fw_state_locked(ctx, SST_RESET);
+ ret = sst_pm_runtime_put(ctx);
+ }
+ }
+ } else {
+ dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
return sst_pm_runtime_put(ctx);
+ }
+ return ret;
}
/*
@@ -572,6 +596,35 @@ static int sst_stream_drop(struct device *dev, int str_id)
return sst_drop_stream(ctx, str_id);
}
+static int sst_stream_pause(struct device *dev, int str_id)
+{
+ struct stream_info *str_info;
+ struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+ if (ctx->sst_state != SST_FW_RUNNING)
+ return 0;
+
+ str_info = get_stream_info(ctx, str_id);
+ if (!str_info)
+ return -EINVAL;
+
+ return sst_pause_stream(ctx, str_id);
+}
+
+static int sst_stream_resume(struct device *dev, int str_id)
+{
+ struct stream_info *str_info;
+ struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+ if (ctx->sst_state != SST_FW_RUNNING)
+ return 0;
+
+ str_info = get_stream_info(ctx, str_id);
+ if (!str_info)
+ return -EINVAL;
+ return sst_resume_stream(ctx, str_id);
+}
+
static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
{
int str_id = 0;
@@ -633,6 +686,8 @@ static struct sst_ops pcm_ops = {
.stream_init = sst_stream_init,
.stream_start = sst_stream_start,
.stream_drop = sst_stream_drop,
+ .stream_pause = sst_stream_pause,
+ .stream_pause_release = sst_stream_resume,
.stream_read_tstamp = sst_read_timestamp,
.send_byte_stream = sst_send_byte_stream,
.close = sst_close_pcm_stream,
diff --git a/sound/soc/intel/sst/sst_loader.c b/sound/soc/intel/sst/sst_loader.c
index 7888cd707853..e88907ae8b15 100644
--- a/sound/soc/intel/sst/sst_loader.c
+++ b/sound/soc/intel/sst/sst_loader.c
@@ -39,7 +39,15 @@
#include "sst.h"
#include "../sst-dsp.h"
-static inline void memcpy32_toio(void __iomem *dst, const void *src, int count)
+void memcpy32_toio(void __iomem *dst, const void *src, int count)
+{
+ /* __iowrite32_copy uses 32-bit count values so divide by 4 for
+ * right count in words
+ */
+ __iowrite32_copy(dst, src, count/4);
+}
+
+void memcpy32_fromio(void *dst, const void __iomem *src, int count)
{
/* __iowrite32_copy uses 32-bit count values so divide by 4 for
* right count in words
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index a2cd3486ac55..e7c78b0406b5 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -100,17 +100,19 @@ config SND_OMAP_SOC_OMAP_TWL4030
config SND_OMAP_SOC_OMAP_ABE_TWL6040
tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
- depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST)
+ depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST)
select SND_OMAP_SOC_DMIC
select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040
select SND_SOC_DMIC
+ select COMMON_CLK_PALMAS if SOC_OMAP5
help
Say Y if you want to add support for SoC audio on OMAP boards using
ABE and twl6040 codec. This driver currently supports:
- SDP4430/Blaze boards
- PandaBoard (4430)
- PandaBoardES (4460)
+ - omap5-uevm (5432)
config SND_OMAP_SOC_OMAP3_PANDORA
tristate "SoC Audio support for OMAP3 Pandora"
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 706613077c15..16cc95fa4573 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -479,8 +479,8 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
/* Add hook switch - can be used to control the codec from userspace
* even if line discipline fails */
- ret = snd_soc_jack_new(rtd->codec, "hook_switch",
- SND_JACK_HEADSET, &ams_delta_hook_switch);
+ ret = snd_soc_card_jack_new(card, "hook_switch", SND_JACK_HEADSET,
+ &ams_delta_hook_switch, NULL, 0);
if (ret)
dev_warn(card->dev,
"Failed to allocate resources for hook switch, "
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index b9c65f1ad5a8..0843a68f277c 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -182,17 +182,17 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
/* Headset jack detection only if it is supported */
if (priv->jack_detection) {
- ret = snd_soc_jack_new(codec, "Headset Jack",
- SND_JACK_HEADSET, &hs_jack);
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET, &hs_jack,
+ hs_jack_pins,
+ ARRAY_SIZE(hs_jack_pins));
if (ret)
return ret;
- ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
}
- return ret;
+ return 0;
}
static const struct snd_soc_dapm_route dmic_audio_map[] = {
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 1343ecbf0bd5..6bb623a2a4df 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -39,7 +39,7 @@
#define pcm_omap1510() 0
#endif
-static const struct snd_pcm_hardware omap_pcm_hardware = {
+static struct snd_pcm_hardware omap_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -53,6 +53,24 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
.buffer_bytes_max = 128 * 1024,
};
+/* sDMA supports only 1, 2, and 4 byte transfer elements. */
+static void omap_pcm_limit_supported_formats(void)
+{
+ int i;
+
+ for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
+ switch (snd_pcm_format_physical_width(i)) {
+ case 8:
+ case 16:
+ case 32:
+ omap_pcm_hardware.formats |= (1LL << i);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/* this may get called several times by oss emulation */
static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -235,6 +253,7 @@ static struct snd_soc_platform_driver omap_soc_platform = {
int omap_pcm_platform_register(struct device *dev)
{
+ omap_pcm_limit_supported_formats();
return devm_snd_soc_register_platform(dev, &omap_soc_platform);
}
EXPORT_SYMBOL_GPL(omap_pcm_platform_register);
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index fb1f6bb87cd4..3673ada43bfb 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -170,14 +170,10 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd)
if (priv->jack_detect > 0) {
hs_jack_gpios[0].gpio = priv->jack_detect;
- ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
- &priv->hs_jack);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&priv->hs_jack,
- ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET, &priv->hs_jack,
+ hs_jack_pins,
+ ARRAY_SIZE(hs_jack_pins));
if (ret)
return ret;
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 7f299357c2d2..c2ddf0fbfa28 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -311,9 +311,9 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
}
/* AV jack detection */
- err = snd_soc_jack_new(codec, "AV Jack",
- SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
- &rx51_av_jack);
+ err = snd_soc_card_jack_new(rtd->card, "AV Jack",
+ SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
+ &rx51_av_jack, NULL, 0);
if (err) {
dev_err(card->dev, "Failed to add AV Jack\n");
return err;
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c
index 73eb5ddf9753..9f8be7cd567e 100644
--- a/sound/soc/pxa/hx4700.c
+++ b/sound/soc/pxa/hx4700.c
@@ -126,17 +126,12 @@ static const struct snd_soc_dapm_route hx4700_audio_map[] = {
*/
static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
int err;
/* Jack detection API stuff */
- err = snd_soc_jack_new(codec, "Headphone Jack",
- SND_JACK_HEADPHONE, &hs_jack);
- if (err)
- return err;
-
- err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pin),
- hs_jack_pin);
+ err = snd_soc_card_jack_new(rtd->card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &hs_jack, hs_jack_pin,
+ ARRAY_SIZE(hs_jack_pin));
if (err)
return err;
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 910336c5ebeb..c20bbc042425 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -75,17 +75,12 @@ static struct snd_soc_card palm27x_asoc;
static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
int err;
/* Jack detection API stuff */
- err = snd_soc_jack_new(codec, "Headphone Jack",
- SND_JACK_HEADPHONE, &hs_jack);
- if (err)
- return err;
-
- err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
+ err = snd_soc_card_jack_new(rtd->card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &hs_jack, hs_jack_pins,
+ ARRAY_SIZE(hs_jack_pins));
if (err)
return err;
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
index 5001dbb9b257..1753c7d9e760 100644
--- a/sound/soc/pxa/ttc-dkb.c
+++ b/sound/soc/pxa/ttc-dkb.c
@@ -78,15 +78,12 @@ static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
/* Headset jack detection */
- snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
- | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
- &hs_jack);
- snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
- snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
- &mic_jack);
- snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
- mic_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
+ &hs_jack, hs_jack_pins, ARRAY_SIZE(hs_jack_pins));
+ snd_soc_card_jack_new(rtd->card, "Microphone Jack", SND_JACK_MICROPHONE,
+ &mic_jack, mic_jack_pins,
+ ARRAY_SIZE(mic_jack_pins));
/* headphone, microphone detection & headset short detection */
pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c
index 76ccb172d0a7..bcbfbe8303f7 100644
--- a/sound/soc/pxa/z2.c
+++ b/sound/soc/pxa/z2.c
@@ -143,13 +143,9 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "MONO1");
/* Jack detection API stuff */
- ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
- &hs_jack);
- if (ret)
- goto err;
-
- ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET,
+ &hs_jack, hs_jack_pins,
+ ARRAY_SIZE(hs_jack_pins));
if (ret)
goto err;
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index 59b044255b78..c72e9fb26658 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -162,13 +162,8 @@ static struct platform_device *s3c24xx_snd_device;
static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
-
- snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
- &hp_jack);
-
- snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
- hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
+ &hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
hp_jack_gpios);
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index 141519c21e21..31a820eb0ac3 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -260,12 +260,12 @@ static int littlemill_late_probe(struct snd_soc_card *card)
if (ret < 0)
return ret;
- ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_HEADSET | SND_JACK_MECHANICAL |
- SND_JACK_BTN_0 | SND_JACK_BTN_1 |
- SND_JACK_BTN_2 | SND_JACK_BTN_3 |
- SND_JACK_BTN_4 | SND_JACK_BTN_5,
- &littlemill_headset);
+ ret = snd_soc_card_jack_new(card, "Headset",
+ SND_JACK_HEADSET | SND_JACK_MECHANICAL |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4 | SND_JACK_BTN_5,
+ &littlemill_headset, NULL, 0);
if (ret)
return ret;
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
index 243dea7ba38f..5f156093101e 100644
--- a/sound/soc/samsung/lowland.c
+++ b/sound/soc/samsung/lowland.c
@@ -56,16 +56,10 @@ static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
- ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_LINEOUT | SND_JACK_HEADSET |
- SND_JACK_BTN_0,
- &lowland_headset);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&lowland_headset,
- ARRAY_SIZE(lowland_headset_pins),
- lowland_headset_pins);
+ ret = snd_soc_card_jack_new(rtd->card, "Headset", SND_JACK_LINEOUT |
+ SND_JACK_HEADSET | SND_JACK_BTN_0,
+ &lowland_headset, lowland_headset_pins,
+ ARRAY_SIZE(lowland_headset_pins));
if (ret)
return ret;
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index 873f2cb4bebe..35e37c457f1f 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -211,13 +211,8 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream,
static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
-
- snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
- &hp_jack);
-
- snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
- hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
+ &hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
hp_jack_gpios);
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index 8291d2a5f152..dfbe2db1c407 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -151,13 +151,10 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
/* Headphone jack detection */
- err = snd_soc_jack_new(codec, "Headphone Jack",
- SND_JACK_HEADPHONE, &smartq_jack);
- if (err)
- return err;
-
- err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins),
- smartq_jack_pins);
+ err = snd_soc_card_jack_new(rtd->card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &smartq_jack,
+ smartq_jack_pins,
+ ARRAY_SIZE(smartq_jack_pins));
if (err)
return err;
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index 5ec7c52282f2..2dcb988bdff2 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -153,16 +153,10 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
pr_err("Failed to request HP_SEL GPIO: %d\n", ret);
gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
- ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_LINEOUT | SND_JACK_HEADSET |
- SND_JACK_BTN_0,
- &speyside_headset);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&speyside_headset,
- ARRAY_SIZE(speyside_headset_pins),
- speyside_headset_pins);
+ ret = snd_soc_card_jack_new(rtd->card, "Headset", SND_JACK_LINEOUT |
+ SND_JACK_HEADSET | SND_JACK_BTN_0,
+ &speyside_headset, speyside_headset_pins,
+ ARRAY_SIZE(speyside_headset_pins));
if (ret)
return ret;
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index 9c80506527c4..85ccfb7188cb 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -179,15 +179,10 @@ static int tobermory_late_probe(struct snd_soc_card *card)
if (ret < 0)
return ret;
- ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_HEADSET | SND_JACK_BTN_0,
- &tobermory_headset);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&tobermory_headset,
- ARRAY_SIZE(tobermory_headset_pins),
- tobermory_headset_pins);
+ ret = snd_soc_card_jack_new(card, "Headset", SND_JACK_HEADSET |
+ SND_JACK_BTN_0, &tobermory_headset,
+ tobermory_headset_pins,
+ ARRAY_SIZE(tobermory_headset_pins));
if (ret)
return ret;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e5c990889dcc..07aa54385ae0 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1578,6 +1578,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets,
card->num_dapm_widgets);
+ if (card->of_dapm_widgets)
+ snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets,
+ card->num_of_dapm_widgets);
+
/* initialise the sound card only once */
if (card->probe) {
ret = card->probe(card);
@@ -1633,6 +1637,10 @@ 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);
+ if (card->of_dapm_routes)
+ snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
+ card->num_of_dapm_routes);
+
for (i = 0; i < card->num_links; i++) {
if (card->dai_link[i].dai_fmt)
snd_soc_runtime_set_dai_fmt(&card->rtd[i],
@@ -3242,8 +3250,8 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
widgets[i].name = wname;
}
- card->dapm_widgets = widgets;
- card->num_dapm_widgets = num_widgets;
+ card->of_dapm_widgets = widgets;
+ card->num_of_dapm_widgets = num_widgets;
return 0;
}
@@ -3327,8 +3335,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
}
}
- card->num_dapm_routes = num_routes;
- card->dapm_routes = routes;
+ card->num_of_dapm_routes = num_routes;
+ card->of_dapm_routes = routes;
return 0;
}
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 4380dcc064a5..9f60c25c4568 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -22,30 +22,42 @@
#include <trace/events/asoc.h>
/**
- * snd_soc_jack_new - Create a new jack
- * @codec: ASoC codec
+ * snd_soc_card_jack_new - Create a new jack
+ * @card: ASoC card
* @id: an identifying string for this jack
* @type: a bitmask of enum snd_jack_type values that can be detected by
* this jack
* @jack: structure to use for the jack
+ * @pins: Array of jack pins to be added to the jack or NULL
+ * @num_pins: Number of elements in the @pins array
*
* Creates a new jack object.
*
* Returns zero if successful, or a negative error code on failure.
* On success jack will be initialised.
*/
-int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
- struct snd_soc_jack *jack)
+int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
+ struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins,
+ unsigned int num_pins)
{
+ int ret;
+
mutex_init(&jack->mutex);
- jack->codec = codec;
+ jack->card = card;
INIT_LIST_HEAD(&jack->pins);
INIT_LIST_HEAD(&jack->jack_zones);
BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
- return snd_jack_new(codec->component.card->snd_card, id, type, &jack->jack);
+ ret = snd_jack_new(card->snd_card, id, type, &jack->jack);
+ if (ret)
+ return ret;
+
+ if (num_pins)
+ return snd_soc_jack_add_pins(jack, num_pins, pins);
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_jack_new);
+EXPORT_SYMBOL_GPL(snd_soc_card_jack_new);
/**
* snd_soc_jack_report - Report the current status for a jack
@@ -63,7 +75,6 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new);
*/
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
{
- struct snd_soc_codec *codec;
struct snd_soc_dapm_context *dapm;
struct snd_soc_jack_pin *pin;
unsigned int sync = 0;
@@ -74,8 +85,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
if (!jack)
return;
- codec = jack->codec;
- dapm = &codec->dapm;
+ dapm = &jack->card->dapm;
mutex_lock(&jack->mutex);
@@ -175,12 +185,12 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
for (i = 0; i < count; i++) {
if (!pins[i].pin) {
- dev_err(jack->codec->dev, "ASoC: No name for pin %d\n",
+ dev_err(jack->card->dev, "ASoC: No name for pin %d\n",
i);
return -EINVAL;
}
if (!pins[i].mask) {
- dev_err(jack->codec->dev, "ASoC: No mask for pin %d"
+ dev_err(jack->card->dev, "ASoC: No mask for pin %d"
" (%s)\n", i, pins[i].pin);
return -EINVAL;
}
@@ -260,7 +270,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
static irqreturn_t gpio_handler(int irq, void *data)
{
struct snd_soc_jack_gpio *gpio = data;
- struct device *dev = gpio->jack->codec->component.card->dev;
+ struct device *dev = gpio->jack->card->dev;
trace_snd_soc_jack_irq(gpio->name);
@@ -299,7 +309,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
for (i = 0; i < count; i++) {
if (!gpios[i].name) {
- dev_err(jack->codec->dev,
+ dev_err(jack->card->dev,
"ASoC: No name for gpio at index %d\n", i);
ret = -EINVAL;
goto undo;
@@ -320,7 +330,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
} else {
/* legacy GPIO number */
if (!gpio_is_valid(gpios[i].gpio)) {
- dev_err(jack->codec->dev,
+ dev_err(jack->card->dev,
"ASoC: Invalid gpio %d\n",
gpios[i].gpio);
ret = -EINVAL;
@@ -350,7 +360,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
if (gpios[i].wake) {
ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1);
if (ret != 0)
- dev_err(jack->codec->dev,
+ dev_err(jack->card->dev,
"ASoC: Failed to mark GPIO at index %d as wake source: %d\n",
i, ret);
}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 6b0136e7cb88..6e3781e88f9a 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2511,6 +2511,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
/* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+ pcm->nonatomic = rtd->dai_link->nonatomic;
rtd->pcm = pcm;
pcm->private_data = rtd;
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 769aca2fc5f5..6dcd06a966c7 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -106,11 +106,10 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card);
- snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
- &tegra_alc5632_hs_jack);
- snd_soc_jack_add_pins(&tegra_alc5632_hs_jack,
- ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
- tegra_alc5632_hs_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET,
+ &tegra_alc5632_hs_jack,
+ tegra_alc5632_hs_jack_pins,
+ ARRAY_SIZE(tegra_alc5632_hs_jack_pins));
if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c
index af3fb997b752..902da36581d1 100644
--- a/sound/soc/tegra/tegra_max98090.c
+++ b/sound/soc/tegra/tegra_max98090.c
@@ -133,24 +133,26 @@ static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_SPK("Speakers", NULL),
SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_MIC("Int Mic", NULL),
};
static const struct snd_kcontrol_new tegra_max98090_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphones"),
SOC_DAPM_PIN_SWITCH("Speakers"),
+ SOC_DAPM_PIN_SWITCH("Mic Jack"),
+ SOC_DAPM_PIN_SWITCH("Int Mic"),
};
static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_codec *codec = codec_dai->codec;
struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card);
if (gpio_is_valid(machine->gpio_hp_det)) {
- snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
- &tegra_max98090_hp_jack);
- snd_soc_jack_add_pins(&tegra_max98090_hp_jack,
- ARRAY_SIZE(tegra_max98090_hp_jack_pins),
- tegra_max98090_hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphones",
+ SND_JACK_HEADPHONE,
+ &tegra_max98090_hp_jack,
+ tegra_max98090_hp_jack_pins,
+ ARRAY_SIZE(tegra_max98090_hp_jack_pins));
tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det;
snd_soc_jack_add_gpios(&tegra_max98090_hp_jack,
@@ -159,11 +161,11 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
}
if (gpio_is_valid(machine->gpio_mic_det)) {
- snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
- &tegra_max98090_mic_jack);
- snd_soc_jack_add_pins(&tegra_max98090_mic_jack,
- ARRAY_SIZE(tegra_max98090_mic_jack_pins),
- tegra_max98090_mic_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Mic Jack",
+ SND_JACK_MICROPHONE,
+ &tegra_max98090_mic_jack,
+ tegra_max98090_mic_jack_pins,
+ ARRAY_SIZE(tegra_max98090_mic_jack_pins));
tegra_max98090_mic_jack_gpio.gpio = machine->gpio_mic_det;
snd_soc_jack_add_gpios(&tegra_max98090_mic_jack,
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index ed759a3076b8..773daecaa5e8 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -108,15 +108,11 @@ static const struct snd_kcontrol_new tegra_rt5640_controls[] = {
static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_codec *codec = codec_dai->codec;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
- snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
- &tegra_rt5640_hp_jack);
- snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
- ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
- tegra_rt5640_hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphones", SND_JACK_HEADPHONE,
+ &tegra_rt5640_hp_jack, tegra_rt5640_hp_jack_pins,
+ ARRAY_SIZE(tegra_rt5640_hp_jack_pins));
if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_rt5640_hp_jack_gpio.gpio = machine->gpio_hp_det;
diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c
index e4cf978a6e3a..68d8b67e79c1 100644
--- a/sound/soc/tegra/tegra_rt5677.c
+++ b/sound/soc/tegra/tegra_rt5677.c
@@ -146,10 +146,9 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(rtd->card);
- snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
- &tegra_rt5677_hp_jack);
- snd_soc_jack_add_pins(&tegra_rt5677_hp_jack, 1,
- &tegra_rt5677_hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
+ &tegra_rt5677_hp_jack,
+ &tegra_rt5677_hp_jack_pins, 1);
if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_rt5677_hp_jack_gpio.gpio = machine->gpio_hp_det;
@@ -158,10 +157,9 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd)
}
- snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
- &tegra_rt5677_mic_jack);
- snd_soc_jack_add_pins(&tegra_rt5677_mic_jack, 1,
- &tegra_rt5677_mic_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Mic Jack", SND_JACK_MICROPHONE,
+ &tegra_rt5677_mic_jack,
+ &tegra_rt5677_mic_jack_pins, 1);
if (gpio_is_valid(machine->gpio_mic_present)) {
tegra_rt5677_mic_jack_gpio.gpio = machine->gpio_mic_present;
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index e52420dae2b4..4a95b70f0cf0 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -177,21 +177,19 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_wm8903_hp_jack_gpio.gpio = machine->gpio_hp_det;
- snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
- &tegra_wm8903_hp_jack);
- snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
- ARRAY_SIZE(tegra_wm8903_hp_jack_pins),
- tegra_wm8903_hp_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &tegra_wm8903_hp_jack,
+ tegra_wm8903_hp_jack_pins,
+ ARRAY_SIZE(tegra_wm8903_hp_jack_pins));
snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
1,
&tegra_wm8903_hp_jack_gpio);
}
- snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
- &tegra_wm8903_mic_jack);
- snd_soc_jack_add_pins(&tegra_wm8903_mic_jack,
- ARRAY_SIZE(tegra_wm8903_mic_jack_pins),
- tegra_wm8903_mic_jack_pins);
+ snd_soc_card_jack_new(rtd->card, "Mic Jack", SND_JACK_MICROPHONE,
+ &tegra_wm8903_mic_jack,
+ tegra_wm8903_mic_jack_pins,
+ ARRAY_SIZE(tegra_wm8903_mic_jack_pins));
wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
0);