Browse Source

Merge remote-tracking branch 'asoc/topic/ux500' into asoc-next

Mark Brown 12 years ago
parent
commit
458bcee95d

+ 46 - 33
sound/soc/codecs/ab8500-codec.c

@@ -2236,7 +2236,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
 		int slots, int slot_width)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	unsigned int val, mask, slots_active;
+	unsigned int val, mask, slot, slots_active;
 
 	mask = BIT(AB8500_DIGIFCONF2_IF0WL0) |
 		BIT(AB8500_DIGIFCONF2_IF0WL1);
@@ -2292,27 +2292,34 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
 	snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
 
 	/* Setup TDM DA according to active tx slots */
+
+	if (tx_mask & ~0xff)
+		return -EINVAL;
+
 	mask = AB8500_DASLOTCONFX_SLTODAX_MASK;
+	tx_mask = tx_mask << AB8500_DA_DATA0_OFFSET;
 	slots_active = hweight32(tx_mask);
+
 	dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__,
 		slots_active);
+
 	switch (slots_active) {
 	case 0:
 		break;
 	case 1:
-		/* Slot 9 -> DA_IN1 & DA_IN3 */
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11);
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11);
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
+		slot = find_first_bit((unsigned long *)&tx_mask, 32);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
 		break;
 	case 2:
-		/* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9);
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9);
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
-		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
-
+		slot = find_first_bit((unsigned long *)&tx_mask, 32);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
+		slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
 		break;
 	case 8:
 		dev_dbg(dai->codec->dev,
@@ -2327,25 +2334,36 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
 	}
 
 	/* Setup TDM AD according to active RX-slots */
+
+	if (rx_mask & ~0xff)
+		return -EINVAL;
+
+	rx_mask = rx_mask << AB8500_AD_DATA0_OFFSET;
 	slots_active = hweight32(rx_mask);
+
 	dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__,
 		slots_active);
+
 	switch (slots_active) {
 	case 0:
 		break;
 	case 1:
-		/* AD_OUT3 -> slot 0 & 1 */
-		snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL,
-				AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
-				AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD);
+		slot = find_first_bit((unsigned long *)&rx_mask, 32);
+		snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot),
+				AB8500_MASK_SLOT(slot),
+				AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
 		break;
 	case 2:
-		/* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */
+		slot = find_first_bit((unsigned long *)&rx_mask, 32);
+		snd_soc_update_bits(codec,
+				AB8500_ADSLOTSEL(slot),
+				AB8500_MASK_SLOT(slot),
+				AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
+		slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1);
 		snd_soc_update_bits(codec,
-				AB8500_ADSLOTSEL1,
-				AB8500_MASK_ALL,
-				AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
-				AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD);
+				AB8500_ADSLOTSEL(slot),
+				AB8500_MASK_SLOT(slot),
+				AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT2, slot));
 		break;
 	case 8:
 		dev_dbg(dai->codec->dev,
@@ -2362,6 +2380,11 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
 	return 0;
 }
 
+static const struct snd_soc_dai_ops ab8500_codec_ops = {
+	.set_fmt = ab8500_codec_set_dai_fmt,
+	.set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
+};
+
 static struct snd_soc_dai_driver ab8500_codec_dai[] = {
 	{
 		.name = "ab8500-codec-dai.0",
@@ -2373,12 +2396,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
 			.rates = AB8500_SUPPORTED_RATE,
 			.formats = AB8500_SUPPORTED_FMT,
 		},
-		.ops = (struct snd_soc_dai_ops[]) {
-			{
-				.set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
-				.set_fmt = ab8500_codec_set_dai_fmt,
-			}
-		},
+		.ops = &ab8500_codec_ops,
 		.symmetric_rates = 1
 	},
 	{
@@ -2391,12 +2409,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
 			.rates = AB8500_SUPPORTED_RATE,
 			.formats = AB8500_SUPPORTED_FMT,
 		},
-		.ops = (struct snd_soc_dai_ops[]) {
-			{
-				.set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
-				.set_fmt = ab8500_codec_set_dai_fmt,
-			}
-		},
+		.ops = &ab8500_codec_ops,
 		.symmetric_rates = 1
 	}
 };

+ 22 - 20
sound/soc/codecs/ab8500-codec.h

@@ -24,6 +24,13 @@
 #define AB8500_SUPPORTED_RATE			(SNDRV_PCM_RATE_48000)
 #define AB8500_SUPPORTED_FMT			(SNDRV_PCM_FMTBIT_S16_LE)
 
+/* AB8500 interface slot offset definitions */
+
+#define AB8500_AD_DATA0_OFFSET	0
+#define AB8500_DA_DATA0_OFFSET	8
+#define AB8500_AD_DATA1_OFFSET	16
+#define AB8500_DA_DATA1_OFFSET	24
+
 /* AB8500 audio bank (0x0d) register definitions */
 
 #define AB8500_POWERUP				0x00
@@ -73,6 +80,7 @@
 #define AB8500_ADSLOTSEL14			0x2C
 #define AB8500_ADSLOTSEL15			0x2D
 #define AB8500_ADSLOTSEL16			0x2E
+#define AB8500_ADSLOTSEL(slot)			(AB8500_ADSLOTSEL1 + (slot >> 1))
 #define AB8500_ADSLOTHIZCTRL1			0x2F
 #define AB8500_ADSLOTHIZCTRL2			0x30
 #define AB8500_ADSLOTHIZCTRL3			0x31
@@ -144,6 +152,7 @@
 #define AB8500_CACHEREGNUM			(AB8500_LAST_REG + 1)
 
 #define AB8500_MASK_ALL				0xFF
+#define AB8500_MASK_SLOT(slot)			((slot & 1) ? 0xF0 : 0x0F)
 #define AB8500_MASK_NONE			0x00
 
 /* AB8500_POWERUP */
@@ -347,28 +356,21 @@
 #define AB8500_DIGIFCONF4_IF1WL0		0
 
 /* AB8500_ADSLOTSELX */
-#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD	0x00
-#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD	0x10
-#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD	0x20
-#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD	0x30
-#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD	0x40
-#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD	0x50
-#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD	0x60
-#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD	0x70
-#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD	0x80
-#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD	0xF0
-#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN	0x00
-#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN	0x01
-#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN	0x02
-#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN	0x03
-#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN	0x04
-#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN	0x05
-#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN	0x06
-#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN	0x07
-#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN	0x08
-#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN	0x0F
+#define AB8500_AD_OUT1	0x0
+#define AB8500_AD_OUT2	0x1
+#define AB8500_AD_OUT3	0x2
+#define AB8500_AD_OUT4	0x3
+#define AB8500_AD_OUT5	0x4
+#define AB8500_AD_OUT6	0x5
+#define AB8500_AD_OUT7	0x6
+#define AB8500_AD_OUT8	0x7
+#define AB8500_ZEROES	0x8
+#define AB8500_TRISTATE	0xF
 #define AB8500_ADSLOTSELX_EVEN_SHIFT		0
 #define AB8500_ADSLOTSELX_ODD_SHIFT		4
+#define AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(out, slot)	\
+	((out) << (((slot) & 1) ? \
+	 AB8500_ADSLOTSELX_ODD_SHIFT : AB8500_ADSLOTSELX_EVEN_SHIFT))
 
 /* AB8500_ADSLOTHIZCTRL1 */
 /* AB8500_ADSLOTHIZCTRL2 */

+ 36 - 0
sound/soc/ux500/mop500_ab8500.c

@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/mutex.h>
 
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -24,6 +25,7 @@
 
 #include "ux500_pcm.h"
 #include "ux500_msp_dai.h"
+#include "mop500_ab8500.h"
 #include "../codecs/ab8500-codec.h"
 
 #define TX_SLOT_MONO	0x0008
@@ -43,6 +45,12 @@
 static unsigned int tx_slots = DEF_TX_SLOTS;
 static unsigned int rx_slots = DEF_RX_SLOTS;
 
+/* Configuration consistency parameters */
+static DEFINE_MUTEX(mop500_ab8500_params_lock);
+static unsigned long mop500_ab8500_usage;
+static int mop500_ab8500_rate;
+static int mop500_ab8500_channels;
+
 /* Clocks */
 static const char * const enum_mclk[] = {
 	"SYSCLK",
@@ -230,6 +238,21 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
 		substream->name,
 		substream->number);
 
+	/* Ensure configuration consistency between DAIs */
+	mutex_lock(&mop500_ab8500_params_lock);
+	if (mop500_ab8500_usage) {
+		if (mop500_ab8500_rate != params_rate(params) ||
+		    mop500_ab8500_channels != params_channels(params)) {
+			mutex_unlock(&mop500_ab8500_params_lock);
+			return -EBUSY;
+		}
+	} else {
+		mop500_ab8500_rate = params_rate(params);
+		mop500_ab8500_channels = params_channels(params);
+	}
+	__set_bit(cpu_dai->id, &mop500_ab8500_usage);
+	mutex_unlock(&mop500_ab8500_params_lock);
+
 	channels = params_channels(params);
 
 	switch (params_format(params)) {
@@ -328,9 +351,22 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+
+	mutex_lock(&mop500_ab8500_params_lock);
+	__clear_bit(cpu_dai->id, &mop500_ab8500_usage);
+	mutex_unlock(&mop500_ab8500_params_lock);
+
+	return 0;
+}
+
 struct snd_soc_ops mop500_ab8500_ops[] = {
 	{
 		.hw_params = mop500_ab8500_hw_params,
+		.hw_free = mop500_ab8500_hw_free,
 		.startup = mop500_ab8500_startup,
 		.shutdown = mop500_ab8500_shutdown,
 	}

+ 4 - 7
sound/soc/ux500/ux500_msp_dai.c

@@ -658,14 +658,11 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
 {
 	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
 
-	drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx;
-	drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx;
+	dai->playback_dma_data = &drvdata->msp->playback_dma_data;
+	dai->capture_dma_data = &drvdata->msp->capture_dma_data;
 
-	dai->playback_dma_data = &drvdata->playback_dma_data;
-	dai->capture_dma_data = &drvdata->capture_dma_data;
-
-	drvdata->playback_dma_data.data_size = drvdata->slot_width;
-	drvdata->capture_dma_data.data_size = drvdata->slot_width;
+	drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
+	drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
 
 	return 0;
 }

+ 0 - 4
sound/soc/ux500/ux500_msp_dai.h

@@ -51,15 +51,11 @@ enum ux500_msp_clock_id {
 struct ux500_msp_i2s_drvdata {
 	struct ux500_msp *msp;
 	struct regulator *reg_vape;
-	struct ux500_msp_dma_params playback_dma_data;
-	struct ux500_msp_dma_params capture_dma_data;
 	unsigned int fmt;
 	unsigned int tx_mask;
 	unsigned int rx_mask;
 	int slots;
 	int slot_width;
-	u8 configured;
-	int data_delay;
 
 	/* Clocks */
 	unsigned int master_clk;

+ 11 - 77
sound/soc/ux500/ux500_msp_i2s.c

@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -26,9 +25,6 @@
 
 #include "ux500_msp_i2s.h"
 
-/* MSP1/3 Tx/Rx usage protection */
-static DEFINE_SPINLOCK(msp_rxtx_lock);
-
  /* Protocol desciptors */
 static const struct msp_protdesc prot_descs[] = {
 	{ /* I2S */
@@ -356,24 +352,8 @@ static int configure_multichannel(struct ux500_msp *msp,
 
 static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
 {
-	int status = 0, retval = 0;
+	int status = 0;
 	u32 reg_val_DMACR, reg_val_GCR;
-	unsigned long flags;
-
-	/* Check msp state whether in RUN or CONFIGURED Mode */
-	if (msp->msp_state == MSP_STATE_IDLE) {
-		spin_lock_irqsave(&msp_rxtx_lock, flags);
-		if (msp->pinctrl_rxtx_ref == 0 &&
-			!(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) {
-			retval = pinctrl_select_state(msp->pinctrl_p,
-						msp->pinctrl_def);
-			if (retval)
-				pr_err("could not set MSP defstate\n");
-		}
-		if (!retval)
-			msp->pinctrl_rxtx_ref++;
-		spin_unlock_irqrestore(&msp_rxtx_lock, flags);
-	}
 
 	/* Configure msp with protocol dependent settings */
 	configure_protocol(msp, config);
@@ -387,12 +367,14 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
 	}
 
 	/* Make sure the correct DMA-directions are configured */
-	if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) {
+	if ((config->direction & MSP_DIR_RX) &&
+			!msp->capture_dma_data.dma_cfg) {
 		dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!",
 			__func__);
 		return -EINVAL;
 	}
-	if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) {
+	if ((config->direction == MSP_DIR_TX) &&
+			!msp->playback_dma_data.dma_cfg) {
 		dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!",
 			__func__);
 		return -EINVAL;
@@ -630,8 +612,7 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)
 
 int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
 {
-	int status = 0, retval = 0;
-	unsigned long flags;
+	int status = 0;
 
 	dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);
 
@@ -643,18 +624,6 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
 			       (~(FRAME_GEN_ENABLE | SRG_ENABLE))),
 			      msp->registers + MSP_GCR);
 
-		spin_lock_irqsave(&msp_rxtx_lock, flags);
-		WARN_ON(!msp->pinctrl_rxtx_ref);
-		msp->pinctrl_rxtx_ref--;
-		if (msp->pinctrl_rxtx_ref == 0 &&
-			!(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) {
-			retval = pinctrl_select_state(msp->pinctrl_p,
-						msp->pinctrl_sleep);
-			if (retval)
-				pr_err("could not set MSP sleepstate\n");
-		}
-		spin_unlock_irqrestore(&msp_rxtx_lock, flags);
-
 		writel(0, msp->registers + MSP_GCR);
 		writel(0, msp->registers + MSP_TCF);
 		writel(0, msp->registers + MSP_RCF);
@@ -682,7 +651,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
 			struct msp_i2s_platform_data *platform_data)
 {
 	struct resource *res = NULL;
-	struct i2s_controller *i2s_cont;
 	struct device_node *np = pdev->dev.of_node;
 	struct ux500_msp *msp;
 
@@ -707,8 +675,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
 
 	msp->id = platform_data->id;
 	msp->dev = &pdev->dev;
-	msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx;
-	msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx;
+	msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx;
+	msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
@@ -717,6 +685,9 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
 		return -ENOMEM;
 	}
 
+	msp->playback_dma_data.tx_rx_addr = res->start + MSP_DR;
+	msp->capture_dma_data.tx_rx_addr = res->start + MSP_DR;
+
 	msp->registers = devm_ioremap(&pdev->dev, res->start,
 				      resource_size(res));
 	if (msp->registers == NULL) {
@@ -727,41 +698,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
 	msp->msp_state = MSP_STATE_IDLE;
 	msp->loopback_enable = 0;
 
-	/* I2S-controller is allocated and added in I2S controller class. */
-	i2s_cont = devm_kzalloc(&pdev->dev, sizeof(*i2s_cont), GFP_KERNEL);
-	if (!i2s_cont) {
-		dev_err(&pdev->dev,
-			"%s: ERROR: Failed to allocate I2S-controller!\n",
-			__func__);
-		return -ENOMEM;
-	}
-	i2s_cont->dev.parent = &pdev->dev;
-	i2s_cont->data = (void *)msp;
-	i2s_cont->id = (s16)msp->id;
-	snprintf(i2s_cont->name, sizeof(i2s_cont->name), "ux500-msp-i2s.%04x",
-		msp->id);
-	dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);
-	msp->i2s_cont = i2s_cont;
-
-	msp->pinctrl_p = pinctrl_get(msp->dev);
-	if (IS_ERR(msp->pinctrl_p))
-		dev_err(&pdev->dev, "could not get MSP pinctrl\n");
-	else {
-		msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p,
-						PINCTRL_STATE_DEFAULT);
-		if (IS_ERR(msp->pinctrl_def)) {
-			dev_err(&pdev->dev,
-				"could not get MSP defstate (%li)\n",
-				PTR_ERR(msp->pinctrl_def));
-		}
-		msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p,
-						PINCTRL_STATE_SLEEP);
-		if (IS_ERR(msp->pinctrl_sleep))
-			dev_err(&pdev->dev,
-				"could not get MSP idlestate (%li)\n",
-				PTR_ERR(msp->pinctrl_def));
-	}
-
 	return 0;
 }
 
@@ -769,8 +705,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
 			struct ux500_msp *msp)
 {
 	dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
-
-	device_unregister(&msp->i2s_cont->dev);
 }
 
 MODULE_LICENSE("GPL v2");

+ 10 - 64
sound/soc/ux500/ux500_msp_i2s.h

@@ -16,6 +16,7 @@
 #define UX500_MSP_I2S_H
 
 #include <linux/platform_device.h>
+#include <linux/platform_data/asoc-ux500-msp.h>
 
 #define MSP_INPUT_FREQ_APB 48000000
 
@@ -341,11 +342,6 @@ enum msp_compress_mode {
 	MSP_COMPRESS_MODE_A_LAW = 3
 };
 
-enum msp_spi_burst_mode {
-	MSP_SPI_BURST_MODE_DISABLE = 0,
-	MSP_SPI_BURST_MODE_ENABLE = 1
-};
-
 enum msp_expand_mode {
 	MSP_EXPAND_MODE_LINEAR = 0,
 	MSP_EXPAND_MODE_LINEAR_SIGNED = 1,
@@ -370,13 +366,6 @@ enum msp_protocol {
  */
 #define MAX_MSP_BACKUP_REGS 36
 
-enum enum_i2s_controller {
-	MSP_0_I2S_CONTROLLER = 0,
-	MSP_1_I2S_CONTROLLER,
-	MSP_2_I2S_CONTROLLER,
-	MSP_3_I2S_CONTROLLER,
-};
-
 enum i2s_direction_t {
 	MSP_DIR_TX = 0x01,
 	MSP_DIR_RX = 0x02,
@@ -454,32 +443,6 @@ struct msp_protdesc {
 	u32 clocks_per_frame;
 };
 
-struct i2s_message {
-	enum i2s_direction_t i2s_direction;
-	void *txdata;
-	void *rxdata;
-	size_t txbytes;
-	size_t rxbytes;
-	int dma_flag;
-	int tx_offset;
-	int rx_offset;
-	bool cyclic_dma;
-	dma_addr_t buf_addr;
-	size_t buf_len;
-	size_t period_len;
-};
-
-struct i2s_controller {
-	struct module *owner;
-	unsigned int id;
-	unsigned int class;
-	const struct i2s_algorithm *algo; /* the algorithm to access the bus */
-	void *data;
-	struct mutex bus_lock;
-	struct device dev; /* the controller device */
-	char name[48];
-};
-
 struct ux500_msp_config {
 	unsigned int f_inputclk;
 	unsigned int rx_clk_sel;
@@ -491,8 +454,6 @@ struct ux500_msp_config {
 	unsigned int tx_fsync_sel;
 	unsigned int rx_fifo_config;
 	unsigned int tx_fifo_config;
-	unsigned int spi_clk_mode;
-	unsigned int spi_burst_mode;
 	unsigned int loopback_enable;
 	unsigned int tx_data_enable;
 	unsigned int default_protdesc;
@@ -502,43 +463,28 @@ struct ux500_msp_config {
 	unsigned int direction;
 	unsigned int protocol;
 	unsigned int frame_freq;
-	unsigned int frame_size;
 	enum msp_data_size data_size;
 	unsigned int def_elem_len;
 	unsigned int iodelay;
-	void (*handler) (void *data);
-	void *tx_callback_data;
-	void *rx_callback_data;
+};
+
+struct ux500_msp_dma_params {
+	unsigned int data_size;
+	dma_addr_t tx_rx_addr;
+	struct stedma40_chan_cfg *dma_cfg;
 };
 
 struct ux500_msp {
-	enum enum_i2s_controller id;
+	enum msp_i2s_id id;
 	void __iomem *registers;
 	struct device *dev;
-	struct i2s_controller *i2s_cont;
-	struct stedma40_chan_cfg *dma_cfg_rx;
-	struct stedma40_chan_cfg *dma_cfg_tx;
-	struct dma_chan *tx_pipeid;
-	struct dma_chan *rx_pipeid;
+	struct ux500_msp_dma_params playback_dma_data;
+	struct ux500_msp_dma_params capture_dma_data;
 	enum msp_state msp_state;
-	int (*transfer) (struct ux500_msp *msp, struct i2s_message *message);
-	struct timer_list notify_timer;
 	int def_elem_len;
 	unsigned int dir_busy;
 	int loopback_enable;
-	u32 backup_regs[MAX_MSP_BACKUP_REGS];
 	unsigned int f_bitclk;
-	/* Pin modes */
-	struct pinctrl *pinctrl_p;
-	struct pinctrl_state *pinctrl_def;
-	struct pinctrl_state *pinctrl_sleep;
-	/* Reference Count */
-	int pinctrl_rxtx_ref;
-};
-
-struct ux500_msp_dma_params {
-	unsigned int data_size;
-	struct stedma40_chan_cfg *dma_cfg;
 };
 
 struct msp_i2s_platform_data;

+ 30 - 0
sound/soc/ux500/ux500_pcm.c

@@ -103,10 +103,40 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
 	return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg);
 }
 
+static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params,
+		struct dma_slave_config *slave_config)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct ux500_msp_dma_params *dma_params;
+	struct stedma40_chan_cfg *dma_cfg;
+	int ret;
+
+	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	dma_cfg = dma_params->dma_cfg;
+
+	ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
+	if (ret)
+		return ret;
+
+	slave_config->dst_maxburst = 4;
+	slave_config->dst_addr_width = dma_cfg->dst_info.data_width;
+	slave_config->src_maxburst = 4;
+	slave_config->src_addr_width = dma_cfg->src_info.data_width;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		slave_config->dst_addr = dma_params->tx_rx_addr;
+	else
+		slave_config->src_addr = dma_params->tx_rx_addr;
+
+	return 0;
+}
+
 static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = {
 	.pcm_hardware = &ux500_pcm_hw,
 	.compat_request_channel = ux500_pcm_request_chan,
 	.prealloc_buffer_size = 128 * 1024,
+	.prepare_slave_config = ux500_pcm_prepare_slave_config,
 };
 
 int ux500_pcm_register_platform(struct platform_device *pdev)