From patchwork Mon Aug 31 23:31:43 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Troy Kisky X-Patchwork-Id: 44966 Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n7VNXeP8019735 for ; Mon, 31 Aug 2009 23:33:41 GMT Received: from dlep34.itg.ti.com ([157.170.170.115]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id n7VNVkYR014527; Mon, 31 Aug 2009 18:31:51 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep34.itg.ti.com (8.13.7/8.13.7) with ESMTP id n7VNVhJO027101; Mon, 31 Aug 2009 18:31:43 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 445DE80627; Mon, 31 Aug 2009 18:31:43 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp53.itg.ti.com (dflp53.itg.ti.com [128.247.5.6]) by linux.omap.com (Postfix) with ESMTP id E24FF80626 for ; Mon, 31 Aug 2009 18:31:41 -0500 (CDT) Received: from white.ext.ti.com (localhost [127.0.0.1]) by dflp53.itg.ti.com (8.13.8/8.13.8) with ESMTP id n7VNVfFY002470 for ; Mon, 31 Aug 2009 18:31:41 -0500 (CDT) Received: from mail125-tx2-R.bigfish.com (mail-tx2.bigfish.com [65.55.88.113]) by white.ext.ti.com (8.13.7/8.13.7) with ESMTP id n7VNVaW1029424 for ; Mon, 31 Aug 2009 18:31:41 -0500 Received: from mail125-tx2 (localhost.localdomain [127.0.0.1]) by mail125-tx2-R.bigfish.com (Postfix) with ESMTP id 5C34B1C382FB for ; Mon, 31 Aug 2009 23:31:36 +0000 (UTC) X-SpamScore: -8 X-BigFish: vps-8(zz14e0Pzz1202hzzz2dh247h64h) X-Spam-TCS-SCL: 3:0 X-FB-SS: 5, X-MS-Exchange-Organization-Antispam-Report: OrigIP: 63.231.195.113; Service: EHS Received: by mail125-tx2 (MessageSwitch) id 1251761494110959_18162; Mon, 31 Aug 2009 23:31:34 +0000 (UCT) Received: from mpls-qmqp-02.inet.qwest.net (mpls-qmqp-02.inet.qwest.net [63.231.195.113]) by mail125-tx2.bigfish.com (Postfix) with ESMTP id D936D1380055 for ; Mon, 31 Aug 2009 23:31:33 +0000 (UTC) Received: from localhost (unknown [67.42.45.38]) by mpls-qmqp-02.inet.qwest.net (Postfix) with ESMTP id 2C69F53BC59; Mon, 31 Aug 2009 23:31:29 +0000 (UTC) Received: by localhost (Postfix, from userid 1002) id F31A75886E8; Mon, 31 Aug 2009 16:31:45 -0700 (MST) From: Troy Kisky To: davinci-linux-open-source@linux.davincidsp.com Date: Mon, 31 Aug 2009 16:31:43 -0700 Message-Id: <1251761505-11353-1-git-send-email-troy.kisky@boundarydevices.com> X-Mailer: git-send-email 1.5.6.3 Cc: alsa-devel@alsa-project.org, broonie@sirena.org.uk Subject: [PATCH 1/3] ASoC: DaVinci: i2s, reduce underruns by combining into 1 element X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.4 Precedence: list List-Id: davinci-linux-open-source.linux.davincidsp.com List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com Allow the left and right 16 bit samples to be shifted out as 1 32 bit sample. Signed-off-by: Troy Kisky --- This applies to Kevin's temp/asoc branch --- arch/arm/mach-davinci/include/mach/asp.h | 6 ++ sound/soc/davinci/davinci-i2s.c | 74 ++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h index 18e4ce3..a3d2aa1 100644 --- a/arch/arm/mach-davinci/include/mach/asp.h +++ b/arch/arm/mach-davinci/include/mach/asp.h @@ -51,6 +51,12 @@ struct snd_platform_data { u32 rx_dma_offset; enum dma_event_q eventq_no; /* event queue number */ 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 + * when compared to previous behavior. + */ + unsigned disable_channel_combine:1; /* McASP specific fields */ int tdm_slots; diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 12a6c54..081b2d4 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -97,6 +97,23 @@ enum { DAVINCI_MCBSP_WORD_32, }; +static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = { + [SNDRV_PCM_FORMAT_S8] = 1, + [SNDRV_PCM_FORMAT_S16_LE] = 2, + [SNDRV_PCM_FORMAT_S32_LE] = 4, +}; + +static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = { + [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8, + [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16, + [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32, +}; + +static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = { + [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE, + [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE, +}; + static struct davinci_pcm_dma_params davinci_i2s_pcm_out = { .name = "I2S PCM Stereo out", }; @@ -113,6 +130,27 @@ struct davinci_mcbsp_dev { u32 pcr; struct clk *clk; struct davinci_pcm_dma_params *dma_params[2]; + /* + * Combining both channels into 1 element will at least double 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. + * + * If relabeling the left and right channels is not possible, + * you may want to let the codec know to swap them back. + * + * It may allow x10 the amount of time to service dma requests, + * if the codec is master and is using an unnecessarily fast bit clock + * (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 bit clock rate. + * + * In the now 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. + */ + unsigned disable_channel_combine:1; }; static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, @@ -359,6 +397,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, int mcbsp_word_length; unsigned int rcr, xcr, srgr; u32 spcr; + snd_pcm_format_t fmt; + unsigned element_cnt = 1; /* general line settings */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); @@ -388,27 +428,22 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); } /* 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: + fmt = params_format(params); + if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) { printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); return -EINVAL; } - - dma_params->acnt = dma_params->data_type; - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1); + if (params_channels(params) == 2) { + element_cnt = 2; + if (double_fmt[fmt] && !dev->disable_channel_combine) { + element_cnt = 1; + fmt = double_fmt[fmt]; + } + } + dma_params->acnt = dma_params->data_type = data_type[fmt]; + mcbsp_word_length = asp_word_length[fmt]; + 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); @@ -524,7 +559,8 @@ static int davinci_i2s_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_release_region; } - + if (pdata) + dev->disable_channel_combine = pdata->disable_channel_combine; dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { ret = -ENODEV;