Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 458bcee9 authored by Mark Brown's avatar Mark Brown
Browse files

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

parents 93d4c1e0 eef6473f
Loading
Loading
Loading
Loading
+46 −33
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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;
Loading