Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Steve Chen <schen-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org>
To: Troy Kisky
	<troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org,
	davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org,
	broonie-GFdadSzt00ze9xe1eoZjHA@public.gmane.org
Subject: Re: [PATCH V1 08/11] ASoc: DaVinci: i2s, Improve underrun, support mono
Date: Mon, 06 Jul 2009 06:09:16 -0500	[thread overview]
Message-ID: <1246878557.3192.25.camel@linux-1lbu> (raw)
In-Reply-To: <1246761001-21982-9-git-send-email-troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>

On Sat, 2009-07-04 at 19:29 -0700, Troy Kisky wrote:
> This patch will reduce the number of underruns by
> shifting out 32 bit values instead of 16 bit. It also
> adds mono support.

Doesn't ALSA already automatically handle mono-stero conversions?  I
don't think we need to provide the same functionality in the driver.

> 
> Signed-off-by: Troy Kisky <troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>
> ---
>  sound/soc/davinci/davinci-i2s.c |  124 +++++++++++++++++++++++++++------------
>  sound/soc/davinci/davinci-pcm.c |   31 +++++++---
>  sound/soc/davinci/davinci-pcm.h |    3 +-
>  3 files changed, 110 insertions(+), 48 deletions(-)
> 
> diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
> index 6fa1b6a..a2ad53e 100644
> --- a/sound/soc/davinci/davinci-i2s.c
> +++ b/sound/soc/davinci/davinci-i2s.c
> @@ -356,26 +356,29 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
>  	struct snd_interval *i = NULL;
>  	int mcbsp_word_length;
> +	int bits_per_sample;
> +	int bits_per_frame;
>  	unsigned int rcr, xcr, srgr;
> +	int channels;
> +	int format;
> +	int element_cnt = 1;
>  	u32 spcr;
>  
> -	/* general line settings */
> -	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
> -	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
> -		spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
> -		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
> -	} else {
> -		spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
> -		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
> -	}
> -
>  	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
> -	srgr = DAVINCI_MCBSP_SRGR_FSGM;
> -	srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
> +	bits_per_sample = snd_interval_value(i);
> +	/* always 2 samples/frame, mono will convert to stereo */
> +	bits_per_frame = bits_per_sample << 1;
> +	srgr = DAVINCI_MCBSP_SRGR_FSGM |
> +		DAVINCI_MCBSP_SRGR_FPER(bits_per_frame - 1) |
> +		DAVINCI_MCBSP_SRGR_FWID(bits_per_sample - 1);
>  
> -	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
> -	srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
> -	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
> +	/* general line settings */
> +	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
> +	spcr |= DAVINCI_MCBSP_SPCR_FREE;
> +	spcr |= (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
> +			DAVINCI_MCBSP_SPCR_XINTM(3) :
> +			DAVINCI_MCBSP_SPCR_RINTM(3);
> +	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
>  
>  	rcr = DAVINCI_MCBSP_RCR_RFIG;
>  	xcr = DAVINCI_MCBSP_XCR_XFIG;
> @@ -386,33 +389,80 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
>  		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
>  	}
> +	channels = params_channels(params);
> +	format = params_format(params);
>  	/* Determine xfer data type */
> -	switch (params_format(params)) {
> -	case SNDRV_PCM_FORMAT_S8:
> -		dma_params->data_type = 1;
> -		mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
> -		break;
> -	case SNDRV_PCM_FORMAT_S16_LE:
> -		dma_params->data_type = 2;
> -		mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
> -		break;
> -	case SNDRV_PCM_FORMAT_S32_LE:
> -		dma_params->data_type = 4;
> -		mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
> -		break;
> -	default:
> -		printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
> -		return -EINVAL;
> +	if (channels == 2) {
> +		/* Combining both channels into 1 element can allow x10 the
> +		 * amount of time between servicing the dma channel, increase
> +		 * effiency, and reduce the chance of overrun/underrun. But,
> +		 * it will result in the left & right channels being swapped.
> +		 * So, you may want to let the codec know to swap them back.
> +		 *
> +		 * It may be x10 instead of x2 because the clock from the codec
> +		 * may run at mclk speed (ie. tlvaic23b), independent of the
> +		 * sample rate. So, having an entire frame at once means it can
> +		 * be serviced at the sample rate instead of the mclk speed.
> +		 *
> +		 * In the now very unlikely case that an underrun still
> +		 * occurs, both the left and right samples will be repeated
> +		 * so that no pops are heard, and the left and right channels
> +		 * won't end up being swapped because of the underrun.
> +		 */
> +		dma_params->convert_mono_stereo = 0;
> +		switch (format) {
> +		case SNDRV_PCM_FORMAT_S8:
> +			dma_params->data_type = 2;	/* 2 byte frame */
> +			mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
> +			break;
> +		case SNDRV_PCM_FORMAT_S16_LE:
> +			dma_params->data_type = 4;	/* 4 byte frame */
> +			mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
> +			break;
> +		case SNDRV_PCM_FORMAT_S32_LE:
> +			element_cnt = 2;
> +			dma_params->data_type = 4;	/* 4 byte element */
> +			mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
> +			break;
> +		default:
> +			printk(KERN_WARNING
> +					"davinci-i2s: unsupported PCM format");
> +			return -EINVAL;
> +		}
> +	} else {
> +		dma_params->convert_mono_stereo = 1;
> +		/* 1 element in ram becomes 2 for stereo */
> +		element_cnt = 2;
> +		switch (format) {
> +		case SNDRV_PCM_FORMAT_S8:
> +			/* 1 byte frame in ram */
> +			dma_params->data_type = 1;
> +			mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
> +			break;
> +		case SNDRV_PCM_FORMAT_S16_LE:
> +			/* 2 byte frame in ram */
> +			dma_params->data_type = 2;
> +			mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
> +			break;
> +		case SNDRV_PCM_FORMAT_S32_LE:
> +			/* 4 byte element */
> +			dma_params->data_type = 4;
> +			mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
> +			break;
> +		default:
> +			printk(KERN_WARNING
> +					"davinci-i2s: unsupported PCM format");
> +			return -EINVAL;
> +		}
>  	}
> -
> -	rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
> -	xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
> +	rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
> +	xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
>  
>  	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
>  		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
>  	xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
>  		DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);
> -
> +	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
>  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>  		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
>  	else
> @@ -542,12 +592,12 @@ struct snd_soc_dai davinci_i2s_dai = {
>  	.probe = davinci_i2s_probe,
>  	.remove = davinci_i2s_remove,
>  	.playback = {
> -		.channels_min = 2,
> +		.channels_min = 1,
>  		.channels_max = 2,
>  		.rates = DAVINCI_I2S_RATES,
>  		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
>  	.capture = {
> -		.channels_min = 2,
> +		.channels_min = 1,
>  		.channels_max = 2,
>  		.rates = DAVINCI_I2S_RATES,
>  		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
> diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
> index a059965..2002fdc 100644
> --- a/sound/soc/davinci/davinci-pcm.c
> +++ b/sound/soc/davinci/davinci-pcm.c
> @@ -65,9 +65,9 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
>  	unsigned int dma_offset;
>  	dma_addr_t dma_pos;
>  	dma_addr_t src, dst;
> -	unsigned short src_bidx, dst_bidx;
> -	unsigned int data_type;
>  	unsigned int count;
> +	unsigned int data_type = prtd->params->data_type;
> +	unsigned int convert_mono_stereo = prtd->params->convert_mono_stereo;
>  
>  	period_size = snd_pcm_lib_period_bytes(substream);
>  	dma_offset = prtd->period * period_size;
> @@ -76,26 +76,37 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
>  	pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
>  		"dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);
>  
> -	data_type = prtd->params->data_type;
>  	count = period_size / data_type;
>  
>  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  		src = dma_pos;
>  		dst = prtd->params->dma_addr;
> -		src_bidx = data_type;
> -		dst_bidx = 0;
> +		if (convert_mono_stereo)
> +			edma_set_src_index(lch, 0, data_type);
> +		else
> +			edma_set_src_index(lch, data_type, 0);
> +		edma_set_dest_index(lch, 0, 0);
>  	} else {
>  		src = prtd->params->dma_addr;
>  		dst = dma_pos;
> -		src_bidx = 0;
> -		dst_bidx = data_type;
> +		edma_set_src_index(lch, 0, 0);
> +		if (convert_mono_stereo)
> +			edma_set_dest_index(lch, 0, data_type);
> +		else
> +			edma_set_dest_index(lch, data_type, 0);
>  	}
>  
>  	edma_set_src(lch, src, INCR, W8BIT);
>  	edma_set_dest(lch, dst, INCR, W8BIT);
> -	edma_set_src_index(lch, src_bidx, 0);
> -	edma_set_dest_index(lch, dst_bidx, 0);
> -	edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);
> +	if (convert_mono_stereo) {
> +		/*
> +		 * Each byte is sent twice, so
> +		 * A_CNT * B_CNT * C_CNT = 2 * period_size
> +		 */
> +		edma_set_transfer_params(lch, data_type, 2, count, 2, ASYNC);
> +	} else {
> +		edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);
> +	}
>  
>  	prtd->period++;
>  	if (unlikely(prtd->period >= runtime->periods))
> diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
> index 62cb4eb..fc70161 100644
> --- a/sound/soc/davinci/davinci-pcm.h
> +++ b/sound/soc/davinci/davinci-pcm.h
> @@ -16,7 +16,8 @@ struct davinci_pcm_dma_params {
>  	char *name;		/* stream identifier */
>  	int channel;		/* sync dma channel ID */
>  	dma_addr_t dma_addr;	/* device physical address for DMA */
> -	unsigned int data_type;	/* xfer data type */
> +	unsigned char data_type;	/* xfer data type */
> +	unsigned char convert_mono_stereo;
>  };
>  
>  struct evm_snd_platform_data {

  parent reply	other threads:[~2009-07-06 11:09 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-05  2:29 davinci-i2c,pcm updates Troy Kisky
2009-07-05  2:29 ` [PATCH V1 01/11] ASoC: DaVinci: i2s, remove MOD_REG_BIT macro Troy Kisky
2009-07-05  2:29   ` [PATCH V1 02/11] ASoC: DaVinci: i2s toggle clock to complete reset Troy Kisky
2009-07-05  2:29     ` [PATCH V1 03/11] ASoc: DaVinci: i2s, minor cleanup Troy Kisky
2009-07-05  2:29       ` [PATCH V1 04/11] ASoC: DaVinci: i2s cleanup Troy Kisky
2009-07-05  2:29         ` [PATCH V1 05/11] ASoC: DaVinci: i2s, only start sample generator if needed Troy Kisky
2009-07-05  2:29           ` [PATCH V1 06/11] ASoC: DaVinci: i2s, minor cleanup of davinci_i2s_startup Troy Kisky
2009-07-05  2:29             ` [PATCH V1 07/11] ASoC: DaVinci: i2s, fix mcbsp_word_length update Troy Kisky
2009-07-05  2:29               ` [PATCH V1 08/11] ASoc: DaVinci: i2s, Improve underrun, support mono Troy Kisky
2009-07-05  2:29                 ` [PATCH V1 09/11] ASoC: DaVinci: i2s, add davinci_i2s_prepare and shutdown Troy Kisky
     [not found]                   ` <1246761001-21982-10-git-send-email-troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>
2009-07-05  2:30                     ` [PATCH V1 10/11] ASoC: DaVinci: i2s don't limit rates Troy Kisky
2009-07-05  2:30                       ` [PATCH V1 11/11] ASoC: DaVinci: pcm, fix underruns by using sram Troy Kisky
2009-07-05 13:03                         ` Mark Brown
2009-07-07  1:10                           ` Troy Kisky
2009-07-07  9:31                             ` Mark Brown
2009-07-07 19:07                               ` Troy Kisky
2009-07-07 19:14                                 ` Troy Kisky
2009-07-07 19:21                                   ` Troy Kisky
2009-07-05 11:57                       ` [PATCH V1 10/11] ASoC: DaVinci: i2s don't limit rates Mark Brown
2009-07-06 22:01                         ` Troy Kisky
2009-07-06 22:19                           ` Mark Brown
2009-07-06 22:27                             ` Troy Kisky
2009-07-05 12:17                   ` [PATCH V1 09/11] ASoC: DaVinci: i2s, add davinci_i2s_prepare and shutdown Mark Brown
2010-09-24 16:48                   ` Ambrose, Martin
2010-09-24 19:14                     ` Troy Kisky
2010-09-24 19:43                       ` Ambrose, Martin
2010-09-24 23:13                         ` Troy Kisky
2010-09-27  0:56                         ` Mark Brown
2010-09-27 18:50                           ` Troy Kisky
2010-09-27 20:35                             ` Mark Brown
2010-09-27  0:27                       ` Mark Brown
2009-07-05 12:12                 ` [PATCH V1 08/11] ASoc: DaVinci: i2s, Improve underrun, support mono Mark Brown
     [not found]                 ` <1246761001-21982-9-git-send-email-troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>
2009-07-06 11:09                   ` Steve Chen [this message]
2009-07-06 11:54                     ` Mark Brown
     [not found]                       ` <20090706115442.GA8925-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2009-07-06 12:45                         ` Steve Chen
2009-07-06 13:26                       ` snd_pcm_format_set_silence parameter Guilherme Longo
2009-07-06 13:52                         ` Clemens Ladisch
2009-07-05 11:41 ` davinci-i2c,pcm updates Mark Brown
2009-07-05 12:03   ` performance between access mothods! Guilherme Longo
2009-07-07 11:26     ` Takashi Iwai
2009-07-06 21:30   ` davinci-i2c,pcm updates Troy Kisky
2009-07-06 21:41     ` Mark Brown
2009-07-06 22:51       ` Kevin Hilman
2009-07-07  9:20         ` Mark Brown
2009-07-06 21:47   ` Kevin Hilman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1246878557.3192.25.camel@linux-1lbu \
    --to=schen-igf4poytycdqt0dzr+alfa@public.gmane.org \
    --cc=alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org \
    --cc=broonie-GFdadSzt00ze9xe1eoZjHA@public.gmane.org \
    --cc=davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org \
    --cc=troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox