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

Commit 1bd202e4 authored by Mark Brown's avatar Mark Brown
Browse files

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

parents 57769541 1b3bc060
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -769,9 +769,12 @@ static struct snd_platform_data da850_evm_snd_data = {
	.tdm_slots		= 2,
	.serial_dir		= da850_iis_serializer_direction,
	.asp_chan_q		= EVENTQ_0,
	.ram_chan_q		= EVENTQ_1,
	.version		= MCASP_VERSION_2,
	.txnumevt		= 1,
	.rxnumevt		= 1,
	.sram_size_playback	= SZ_8K,
	.sram_size_capture	= SZ_8K,
};

static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1509,6 +1512,7 @@ static __init void da850_evm_init(void)
		pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
				ret);

	da850_evm_snd_data.sram_pool = sram_get_gen_pool();
	da8xx_register_mcasp(0, &da850_evm_snd_data);

	ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
+3 −1
Original line number Diff line number Diff line
@@ -16,12 +16,13 @@
#ifndef __DAVINCI_ASP_H
#define __DAVINCI_ASP_H

#include <linux/genalloc.h>

struct snd_platform_data {
	u32 tx_dma_offset;
	u32 rx_dma_offset;
	int asp_chan_q;	/* event queue number for ASP channel */
	int ram_chan_q;	/* event queue number for RAM channel */
	unsigned int codec_fmt;
	/*
	 * Allowing this is more efficient and eliminates left and right swaps
	 * caused by underruns, but will swap the left and right channels
@@ -30,6 +31,7 @@ struct snd_platform_data {
	unsigned enable_channel_combine:1;
	unsigned sram_size_playback;
	unsigned sram_size_capture;
	struct gen_pool *sram_pool;

	/*
	 * If McBSP peripheral gets the clock from an external pin,
+5 −0
Original line number Diff line number Diff line
@@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
	if (ret < 0)
		return ret;

	/* set the CPU system clock */
	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
	if (ret < 0)
		return ret;

	return 0;
}

+97 −55
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@
#define ACLKXE		BIT(5)
#define TX_ASYNC	BIT(6)
#define ACLKXPOL	BIT(7)
#define ACLKXDIV_MASK	0x1f

/*
 * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
@@ -207,6 +208,7 @@
#define ACLKRE		BIT(5)
#define RX_ASYNC	BIT(6)
#define ACLKRPOL	BIT(7)
#define ACLKRDIV_MASK	0x1f

/*
 * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
@@ -215,6 +217,7 @@
#define AHCLKXDIV(val)	(val)
#define AHCLKXPOL	BIT(14)
#define AHCLKXE		BIT(15)
#define AHCLKXDIV_MASK	0xfff

/*
 * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
@@ -223,6 +226,7 @@
#define AHCLKRDIV(val)	(val)
#define AHCLKRPOL	BIT(14)
#define AHCLKRE		BIT(15)
#define AHCLKRDIV_MASK	0xfff

/*
 * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
@@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
	void __iomem *base = dev->base;

	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_DSP_B:
	case SND_SOC_DAIFMT_AC97:
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
		break;
	default:
		/* configure a full-word SYNC pulse (LRCLK) */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);

		/* make 1st data bit occur one ACLK cycle after the frame sync */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
		break;
	}

	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		/* codec is clock and frame slave */
@@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
				ACLKX | AHCLKX | AFSX);
		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		/* codec is clock master and frame slave */
@@ -554,59 +574,75 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
	return 0;
}

static int davinci_config_channel_size(struct davinci_audio_dev *dev,
				       int channel_size)
static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
{
	u32 fmt = 0;
	u32 mask, rotate;

	switch (channel_size) {
	case DAVINCI_AUDIO_WORD_8:
		fmt = 0x03;
		rotate = 6;
		mask = 0x000000ff;
		break;
	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);

	case DAVINCI_AUDIO_WORD_12:
		fmt = 0x05;
		rotate = 5;
		mask = 0x00000fff;
	switch (div_id) {
	case 0:		/* MCLK divider */
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
			       AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
			       AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
		break;

	case DAVINCI_AUDIO_WORD_16:
		fmt = 0x07;
		rotate = 4;
		mask = 0x0000ffff;
	case 1:		/* BCLK divider */
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
			       ACLKXDIV(div - 1), ACLKXDIV_MASK);
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
			       ACLKRDIV(div - 1), ACLKRDIV_MASK);
		break;

	case DAVINCI_AUDIO_WORD_20:
		fmt = 0x09;
		rotate = 3;
		mask = 0x000fffff;
	case 2:		/* BCLK/LRCLK ratio */
		dev->bclk_lrclk_ratio = div;
		break;

	case DAVINCI_AUDIO_WORD_24:
		fmt = 0x0B;
		rotate = 2;
		mask = 0x00ffffff;
		break;
	default:
		return -EINVAL;
	}

	case DAVINCI_AUDIO_WORD_28:
		fmt = 0x0D;
		rotate = 1;
		mask = 0x0fffffff;
		break;
	return 0;
}

	case DAVINCI_AUDIO_WORD_32:
		fmt = 0x0F;
		rotate = 0;
		mask = 0xffffffff;
		break;
static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
				    unsigned int freq, int dir)
{
	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);

	default:
		return -EINVAL;
	if (dir == SND_SOC_CLOCK_OUT) {
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
	} else {
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
	}

	return 0;
}

static int davinci_config_channel_size(struct davinci_audio_dev *dev,
				       int word_length)
{
	u32 fmt;
	u32 rotate = (32 - word_length) / 4;
	u32 mask = (1ULL << word_length) - 1;

	/*
	 * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
	 * callback, take it into account here. That allows us to for example
	 * send 32 bits per channel to the codec, while only 16 of them carry
	 * audio payload.
	 * The clock ratio is given for a full period of data (both left and
	 * right channels), so it has to be divided by 2.
	 */
	if (dev->bclk_lrclk_ratio)
		word_length = dev->bclk_lrclk_ratio / 2;

	/* mapping of the XSSZ bit-field as described in the datasheet */
	fmt = (word_length >> 1) - 1;

	mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
					RXSSZ(fmt), RXSSZ(0x0F));
	mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
@@ -709,8 +745,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* bit stream is MSB first  with no delay */
		/* DSP_B mode */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXE);
		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);

@@ -720,14 +754,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
		else
			printk(KERN_ERR "playback tdm slot %d not supported\n",
				dev->tdm_slots);

		mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
	} else {
		/* bit stream is MSB first with no delay */
		/* DSP_B mode */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRE);
		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);

		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
@@ -736,8 +766,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
		else
			printk(KERN_ERR "capture tdm slot %d not supported\n",
				dev->tdm_slots);

		mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
	}
}

@@ -800,19 +828,27 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
	case SNDRV_PCM_FORMAT_U8:
	case SNDRV_PCM_FORMAT_S8:
		dma_params->data_type = 1;
		word_length = DAVINCI_AUDIO_WORD_8;
		word_length = 8;
		break;

	case SNDRV_PCM_FORMAT_U16_LE:
	case SNDRV_PCM_FORMAT_S16_LE:
		dma_params->data_type = 2;
		word_length = DAVINCI_AUDIO_WORD_16;
		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:
	case SNDRV_PCM_FORMAT_U32_LE:
	case SNDRV_PCM_FORMAT_S32_LE:
		dma_params->data_type = 4;
		word_length = DAVINCI_AUDIO_WORD_32;
		word_length = 32;
		break;

	default:
@@ -880,13 +916,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
	.trigger	= davinci_mcasp_trigger,
	.hw_params	= davinci_mcasp_hw_params,
	.set_fmt	= davinci_mcasp_set_dai_fmt,

	.set_clkdiv	= davinci_mcasp_set_clkdiv,
	.set_sysclk	= davinci_mcasp_set_sysclk,
};

#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
				SNDRV_PCM_FMTBIT_U8 | \
				SNDRV_PCM_FMTBIT_S16_LE | \
				SNDRV_PCM_FMTBIT_U16_LE | \
				SNDRV_PCM_FMTBIT_S24_LE | \
				SNDRV_PCM_FMTBIT_U24_LE | \
				SNDRV_PCM_FMTBIT_S24_3LE | \
				SNDRV_PCM_FMTBIT_U24_3LE | \
				SNDRV_PCM_FMTBIT_S32_LE | \
				SNDRV_PCM_FMTBIT_U32_LE)

@@ -1089,7 +1130,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
	dev->tdm_slots = pdata->tdm_slots;
	dev->num_serializer = pdata->num_serializer;
	dev->serial_dir = pdata->serial_dir;
	dev->codec_fmt = pdata->codec_fmt;
	dev->version = pdata->version;
	dev->txnumevt = pdata->txnumevt;
	dev->rxnumevt = pdata->rxnumevt;
@@ -1098,6 +1138,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
	dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
	dma_data->asp_chan_q = pdata->asp_chan_q;
	dma_data->ram_chan_q = pdata->ram_chan_q;
	dma_data->sram_pool = pdata->sram_pool;
	dma_data->sram_size = pdata->sram_size_playback;
	dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
							mem->start);
@@ -1115,6 +1156,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
	dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
	dma_data->asp_chan_q = pdata->asp_chan_q;
	dma_data->ram_chan_q = pdata->ram_chan_q;
	dma_data->sram_pool = pdata->sram_pool;
	dma_data->sram_size = pdata->sram_size_capture;
	dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
							mem->start);
+2 −13
Original line number Diff line number Diff line
@@ -23,26 +23,14 @@

#include "davinci-pcm.h"

#define DAVINCI_MCASP_RATES	SNDRV_PCM_RATE_8000_96000
#define DAVINCI_MCASP_RATES	SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_I2S_DAI	0
#define DAVINCI_MCASP_DIT_DAI	1

enum {
	DAVINCI_AUDIO_WORD_8 = 0,
	DAVINCI_AUDIO_WORD_12,
	DAVINCI_AUDIO_WORD_16,
	DAVINCI_AUDIO_WORD_20,
	DAVINCI_AUDIO_WORD_24,
	DAVINCI_AUDIO_WORD_32,
	DAVINCI_AUDIO_WORD_28,  /* This is only valid for McASP */
};

struct davinci_audio_dev {
	struct davinci_pcm_dma_params dma_params[2];
	void __iomem *base;
	int sample_rate;
	struct device *dev;
	unsigned int codec_fmt;

	/* McASP specific data */
	int	tdm_slots;
@@ -50,6 +38,7 @@ struct davinci_audio_dev {
	u8	num_serializer;
	u8	*serial_dir;
	u8	version;
	u8	bclk_lrclk_ratio;

	/* McASP FIFO related */
	u8	txnumevt;
Loading