Commit d66e065c authored by Mark Brown's avatar Mark Brown
Browse files

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

parents 7b451962 f5023af6
Loading
Loading
Loading
Loading
+59 −23
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@
#define DISMOD		(val)(val<<2)
#define TXSTATE		BIT(4)
#define RXSTATE		BIT(5)
#define SRMOD_MASK	3
#define SRMOD_INACTIVE	0

/*
 * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
@@ -643,26 +645,33 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
	/* mapping of the XSSZ bit-field as described in the datasheet */
	fmt = (word_length >> 1) - 1;

	if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) {
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
				RXSSZ(fmt), RXSSZ(0x0F));
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
				TXSSZ(fmt), TXSSZ(0x0F));
	mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate),
							TXROT(7));
	mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate),
							RXROT(7));
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
				TXROT(rotate), TXROT(7));
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
				RXROT(rotate), RXROT(7));
		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
				mask);
	}

	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
	mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask);

	return 0;
}

static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
				    int channels)
{
	int i;
	u8 tx_ser = 0;
	u8 rx_ser = 0;

	u8 ser;
	u8 slots = dev->tdm_slots;
	u8 max_active_serializers = (channels + slots - 1) / slots;
	/* Default configuration */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);

@@ -682,15 +691,31 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
	for (i = 0; i < dev->num_serializer; i++) {
		mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
					dev->serial_dir[i]);
		if (dev->serial_dir[i] == TX_MODE) {
		if (dev->serial_dir[i] == TX_MODE &&
					tx_ser < max_active_serializers) {
			mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
					AXR(i));
			tx_ser++;
		} else if (dev->serial_dir[i] == RX_MODE) {
		} else if (dev->serial_dir[i] == RX_MODE &&
					rx_ser < max_active_serializers) {
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
					AXR(i));
			rx_ser++;
		} else {
			mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
					SRMOD_INACTIVE, SRMOD_MASK);
		}
	}

	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
		ser = tx_ser;
	else
		ser = rx_ser;

	if (ser < max_active_serializers) {
		dev_warn(dev->dev, "stream has more channels (%d) than are "
			"enabled in mcasp (%d)\n", channels, ser * slots);
		return -EINVAL;
	}

	if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -729,6 +754,8 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
				((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
		}
	}

	return 0;
}

static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
@@ -772,12 +799,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
/* S/PDIF */
static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
{
	/* Set the PDIR for Serialiser as output */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);

	/* TXMASK for 24 bits */
	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);

	/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
	   and LSB first */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
@@ -812,8 +833,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
					&dev->dma_params[substream->stream];
	int word_length;
	u8 fifo_level;
	u8 slots = dev->tdm_slots;
	int channels;
	struct snd_interval *pcm_channels = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_CHANNELS);
	channels = pcm_channels->min;

	davinci_hw_common_param(dev, substream->stream);
	if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL)
		return -EINVAL;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		fifo_level = dev->txnumevt;
	else
@@ -862,6 +889,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
		dma_params->acnt = dma_params->data_type;

	dma_params->fifo_level = fifo_level;
	dma_params->active_serializers = (channels + slots - 1) / slots;
	davinci_config_channel_size(dev, word_length);

	return 0;
@@ -936,13 +964,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
		.name		= "davinci-mcasp.0",
		.playback	= {
			.channels_min	= 2,
			.channels_max 	= 2,
			.channels_max	= 32 * 16,
			.rates 		= DAVINCI_MCASP_RATES,
			.formats	= DAVINCI_MCASP_PCM_FMTS,
		},
		.capture 	= {
			.channels_min 	= 2,
			.channels_max 	= 2,
			.channels_max	= 32 * 16,
			.rates 		= DAVINCI_MCASP_RATES,
			.formats	= DAVINCI_MCASP_PCM_FMTS,
		},
@@ -1019,8 +1047,16 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
		pdata->op_mode = val;

	ret = of_property_read_u32(np, "tdm-slots", &val);
	if (ret >= 0)
	if (ret >= 0) {
		if (val < 2 || val > 32) {
			dev_err(&pdev->dev,
				"tdm-slots must be in rage [2-32]\n");
			ret = -EINVAL;
			goto nodata;
		}

		pdata->tdm_slots = val;
	}

	ret = of_property_read_u32(np, "num-serializer", &val);
	if (ret >= 0)
+9 −7
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
	unsigned short acnt;
	unsigned int count;
	unsigned int fifo_level;
	unsigned char serializers = prtd->params->active_serializers;

	period_size = snd_pcm_lib_period_bytes(substream);
	dma_offset = prtd->period * period_size;
@@ -194,14 +195,14 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
	data_type = prtd->params->data_type;
	count = period_size / data_type;
	if (fifo_level)
		count /= fifo_level;
		count /= fifo_level * serializers;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		src = dma_pos;
		dst = prtd->params->dma_addr;
		src_bidx = data_type;
		dst_bidx = 0;
		src_cidx = data_type * fifo_level;
		dst_bidx = 4;
		src_cidx = data_type * fifo_level * serializers;
		dst_cidx = 0;
	} else {
		src = prtd->params->dma_addr;
@@ -209,7 +210,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
		src_bidx = 0;
		dst_bidx = data_type;
		src_cidx = 0;
		dst_cidx = data_type * fifo_level;
		dst_cidx = data_type * fifo_level * serializers;
	}

	acnt = prtd->params->acnt;
@@ -223,8 +224,9 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
		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,
		edma_set_transfer_params(prtd->asp_link[0], acnt,
						fifo_level * serializers,
						count, fifo_level * serializers,
						ABSYNC);
}

+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ struct davinci_pcm_dma_params {
	unsigned char data_type;	/* xfer data type */
	unsigned char convert_mono_stereo;
	unsigned int fifo_level;
	unsigned char active_serializers; /* num. of active audio serializers */
};

int davinci_soc_platform_register(struct device *dev);