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 {
next prev 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