Эх сурвалжийг харах

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>"
Mark Brown 10 жил өмнө
parent
commit
89a88dd3d6
74 өөрчлөгдсөн 1170 нэмэгдсэн , 1652 устгасан
  1. 1 0
      Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt
  2. 7 0
      include/sound/pcm_params.h
  3. 13 3
      include/sound/soc.h
  4. 107 4
      sound/soc/atmel/atmel_ssc_dai.c
  5. 1 0
      sound/soc/atmel/atmel_ssc_dai.h
  6. 15 3
      sound/soc/codecs/Kconfig
  7. 4 0
      sound/soc/codecs/Makefile
  8. 5 12
      sound/soc/codecs/adau1977.c
  9. 6 13
      sound/soc/codecs/cs35l32.c
  10. 6 13
      sound/soc/codecs/cs4265.c
  11. 4 7
      sound/soc/codecs/max98357a.c
  12. 159 19
      sound/soc/codecs/pcm512x.c
  13. 14 3
      sound/soc/codecs/rt286.c
  14. 3 0
      sound/soc/codecs/rt5670.h
  15. 30 14
      sound/soc/codecs/rt5677.c
  16. 6 0
      sound/soc/codecs/rt5677.h
  17. 8 6
      sound/soc/codecs/sn95031.c
  18. 2 1
      sound/soc/codecs/sn95031.h
  19. 9 21
      sound/soc/codecs/sta350.c
  20. 3 10
      sound/soc/codecs/tas2552.c
  21. 64 0
      sound/soc/codecs/wm8804-i2c.c
  22. 56 0
      sound/soc/codecs/wm8804-spi.c
  23. 79 202
      sound/soc/codecs/wm8804.c
  24. 7 0
      sound/soc/codecs/wm8804.h
  25. 3 10
      sound/soc/codecs/wm_adsp.c
  26. 10 8
      sound/soc/davinci/Kconfig
  27. 0 2
      sound/soc/davinci/Makefile
  28. 26 41
      sound/soc/davinci/davinci-i2s.c
  29. 31 68
      sound/soc/davinci/davinci-mcasp.c
  30. 0 861
      sound/soc/davinci/davinci-pcm.c
  31. 0 41
      sound/soc/davinci/davinci-pcm.h
  32. 24 31
      sound/soc/davinci/davinci-vcif.c
  33. 6 0
      sound/soc/fsl/fsl-asoc-card.c
  34. 3 3
      sound/soc/fsl/imx-es8328.c
  35. 5 7
      sound/soc/fsl/wm1133-ev1.c
  36. 10 10
      sound/soc/generic/simple-card.c
  37. 4 12
      sound/soc/intel/broadwell.c
  38. 3 8
      sound/soc/intel/byt-max98090.c
  39. 1 3
      sound/soc/intel/bytcr_dpcm_rt5640.c
  40. 7 9
      sound/soc/intel/cht_bsw_rt5645.c
  41. 3 6
      sound/soc/intel/cht_bsw_rt5672.c
  42. 1 3
      sound/soc/intel/haswell.c
  43. 10 14
      sound/soc/intel/mfld_machine.c
  44. 60 0
      sound/soc/intel/sst-mfld-platform-pcm.c
  45. 1 0
      sound/soc/intel/sst-mfld-platform.h
  46. 120 8
      sound/soc/intel/sst/sst.c
  47. 12 0
      sound/soc/intel/sst/sst.h
  48. 60 5
      sound/soc/intel/sst/sst_drv_interface.c
  49. 9 1
      sound/soc/intel/sst/sst_loader.c
  50. 3 1
      sound/soc/omap/Kconfig
  51. 2 2
      sound/soc/omap/ams-delta.c
  52. 5 5
      sound/soc/omap/omap-abe-twl6040.c
  53. 20 1
      sound/soc/omap/omap-pcm.c
  54. 4 8
      sound/soc/omap/omap-twl4030.c
  55. 3 3
      sound/soc/omap/rx51.c
  56. 3 8
      sound/soc/pxa/hx4700.c
  57. 3 8
      sound/soc/pxa/palm27x.c
  58. 6 9
      sound/soc/pxa/ttc-dkb.c
  59. 3 7
      sound/soc/pxa/z2.c
  60. 2 7
      sound/soc/samsung/h1940_uda1380.c
  61. 6 6
      sound/soc/samsung/littlemill.c
  62. 4 10
      sound/soc/samsung/lowland.c
  63. 2 7
      sound/soc/samsung/rx1950_uda1380.c
  64. 4 7
      sound/soc/samsung/smartq_wm8987.c
  65. 4 10
      sound/soc/samsung/speyside.c
  66. 4 9
      sound/soc/samsung/tobermory.c
  67. 12 4
      sound/soc/soc-core.c
  68. 26 16
      sound/soc/soc-jack.c
  69. 1 0
      sound/soc/soc-pcm.c
  70. 4 5
      sound/soc/tegra/tegra_alc5632.c
  71. 14 12
      sound/soc/tegra/tegra_max98090.c
  72. 3 7
      sound/soc/tegra/tegra_rt5640.c
  73. 6 8
      sound/soc/tegra/tegra_rt5677.c
  74. 8 10
      sound/soc/tegra/tegra_wm8903.c

+ 1 - 0
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt

@@ -18,6 +18,7 @@ Required properties:
   * Headphones
   * Speakers
   * Mic Jack
+  * Int Mic
 
 - nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
   connected to the CODEC.

+ 7 - 0
include/sound/pcm_params.h

@@ -366,4 +366,11 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p)
 	return snd_pcm_format_physical_width(params_format(p));
 }
 
+static inline void
+params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
+{
+	snd_mask_set(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT),
+		(__force int)fmt);
+}
+
 #endif /* __SOUND_PCM_PARAMS_H */

+ 13 - 3
include/sound/soc.h

@@ -450,8 +450,10 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream,
 		      struct snd_soc_dai *dai);
 
 /* Jack reporting */
-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);
+
 void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
 int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
 			  struct snd_soc_jack_pin *pins);
@@ -659,7 +661,7 @@ struct snd_soc_jack_gpio {
 struct snd_soc_jack {
 	struct mutex mutex;
 	struct snd_jack *jack;
-	struct snd_soc_codec *codec;
+	struct snd_soc_card *card;
 	struct list_head pins;
 	int status;
 	struct blocking_notifier_head notifier;
@@ -954,6 +956,9 @@ struct snd_soc_dai_link {
 	unsigned int symmetric_channels:1;
 	unsigned int symmetric_samplebits:1;
 
+	/* Mark this pcm with non atomic ops */
+	bool nonatomic;
+
 	/* Do not create a PCM for this DAI link (Backend link) */
 	unsigned int no_pcm:1;
 
@@ -1071,11 +1076,16 @@ struct snd_soc_card {
 
 	/*
 	 * Card-specific routes and widgets.
+	 * Note: of_dapm_xxx for Device Tree; Otherwise for driver build-in.
 	 */
 	const struct snd_soc_dapm_widget *dapm_widgets;
 	int num_dapm_widgets;
 	const struct snd_soc_dapm_route *dapm_routes;
 	int num_dapm_routes;
+	const struct snd_soc_dapm_widget *of_dapm_widgets;
+	int num_of_dapm_widgets;
+	const struct snd_soc_dapm_route *of_dapm_routes;
+	int num_of_dapm_routes;
 	bool fully_routed;
 
 	struct work_struct deferred_resume_work;

+ 107 - 4
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,
 };

+ 1 - 0
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);

+ 15 - 3
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

+ 4 - 0
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

+ 5 - 12
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)

+ 6 - 13
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);

+ 6 - 13
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);

+ 4 - 7
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);

+ 159 - 19
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;

+ 14 - 3
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;
 }

+ 3 - 0
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,

+ 30 - 14
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;
 

+ 6 - 0
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

+ 8 - 6
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;

+ 2 - 1
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

+ 9 - 21
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++)

+ 3 - 10
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);

+ 64 - 0
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");

+ 56 - 0
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");

+ 79 - 202
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>");

+ 7 - 0
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 */

+ 3 - 10
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++;
 	}
 

+ 10 - 8
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

+ 0 - 2
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

+ 26 - 41
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;

+ 31 - 68
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;

+ 0 - 861
sound/soc/davinci/davinci-pcm.c

@@ -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");

+ 0 - 41
sound/soc/davinci/davinci-pcm.h

@@ -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

+ 24 - 31
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);

+ 6 - 0
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;

+ 3 - 3
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;
 

+ 5 - 7
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);
 

+ 10 - 10
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,

+ 4 - 12
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;
 }
 

+ 3 - 8
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;
 

+ 1 - 3
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;
 }
 

+ 7 - 9
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;
 }
 

+ 3 - 6
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,
 };

+ 1 - 3
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;
 }
 

+ 10 - 14
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;

+ 60 - 0
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,

+ 1 - 0
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);

+ 120 - 8
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);

+ 12 - 0
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

+ 60 - 5
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,

+ 9 - 1
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

+ 3 - 1
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"

+ 2 - 2
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, "

+ 5 - 5
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[] = {

+ 20 - 1
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);

+ 4 - 8
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;
 

+ 3 - 3
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;

+ 3 - 8
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;
 

+ 3 - 8
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;
 

+ 6 - 9
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,

+ 3 - 7
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;
 

+ 2 - 7
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);

+ 6 - 6
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;
 

+ 4 - 10
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;
 

+ 2 - 7
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);

+ 4 - 7
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;
 

+ 4 - 10
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;
 

+ 4 - 9
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;
 

+ 12 - 4
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;
 }

+ 26 - 16
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);
 		}

+ 1 - 0
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;
 

+ 4 - 5
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;

+ 14 - 12
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,

+ 3 - 7
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;

+ 6 - 8
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;

+ 8 - 10
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);