From patchwork Tue May 24 18:50:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardiner X-Patchwork-Id: 813272 Received: from devils.ext.ti.com (devils.ext.ti.com [198.47.26.153]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4OIrTEO002045 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 24 May 2011 18:53:51 GMT Received: from dlep36.itg.ti.com ([157.170.170.91]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id p4OIpgED023774 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 24 May 2011 13:51:43 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep36.itg.ti.com (8.13.8/8.13.7) with ESMTP id p4OIpg6f009844; Tue, 24 May 2011 13:51:42 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id BA7EC80635; Tue, 24 May 2011 13:51:17 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp52.itg.ti.com (dflp52.itg.ti.com [128.247.22.96]) by linux.omap.com (Postfix) with ESMTP id 7DFD98062B for ; Tue, 24 May 2011 13:50:33 -0500 (CDT) Received: from red.ext.ti.com (red.ext.ti.com [192.94.93.37]) by dflp52.itg.ti.com (8.13.7/8.13.8) with ESMTP id p4OIoWED013991 for ; Tue, 24 May 2011 13:50:32 -0500 (CDT) Received: from psmtp.com (na3sys009amx240.postini.com [74.125.149.124]) by red.ext.ti.com (8.13.7/8.13.7) with SMTP id p4OIoVFN022478 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 24 May 2011 13:50:31 -0500 Received: from na3sys009aog110.obsmtp.com ([209.85.212.45]) (using TLSv1) by na3sys009amx240.postini.com ([74.125.148.10]) with SMTP; Tue, 24 May 2011 12:50:31 MDT Received: from mail-vw0-f45.google.com ([209.85.212.45]) (using TLSv1) by na3sys009aob110.postini.com ([74.125.148.12]) with SMTP ID DSNKTdv99w4Qs9AEMQh7SnzVv4xhIFy9Sndl@postini.com; Tue, 24 May 2011 11:50:31 PDT Received: by mail-vw0-f45.google.com with SMTP id 17so6419532vws.32 for ; Tue, 24 May 2011 11:50:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nanometrics.ca; s=google; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=WEKqenhWpkukOidK+CXnhxUh2E8TtK8SvW/hKnomABs=; b=X2SnQ1L6EZ8S2s1qPVIlIKb4XFPBcp7foilYouiKSFSM5Klb6xRWHz/J0pQ+s40D95 DV84DT3YfeRUX6emQqV1z3WmwLiFg4U2UnB/2bu7QGWNpx39VRayoq6n0HeV1pUqB8EK AjKKVTQscMch7Dbj5hiW9lVl6ysoTyxKa88hg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=nanometrics.ca; s=google; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=OPft+zGsYIbPyajzdC1bpnOAnqq2i3LAiPaRfpRVBVqtAZwPZJroJ9e8spS7Gltlhf YqgqEfkcpJruuk6gwLzLuxWw2Yc/Azk9cpOVpENXnUywuCY8KIBIa07BXCW6f3yNxTwm 3Hv5XmmYFnhGJtplepS38YLRbeaZbGiA8eL2o= Received: by 10.52.98.231 with SMTP id el7mr5837753vdb.229.1306263030900; Tue, 24 May 2011 11:50:30 -0700 (PDT) Received: from localhost.localdomain ([206.191.47.130]) by mx.google.com with ESMTPS id d18sm1646004vcs.40.2011.05.24.11.50.29 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 24 May 2011 11:50:30 -0700 (PDT) From: Ben Gardiner To: Mark Brown , Sekhar Nori , Liam Girdwood , alsa-devel@alsa-project.org, davinci-linux-open-source@linux.davincidsp.com Subject: [PATCH 6/6] ASoC: davinci-pcm: convert to BATCH mode Date: Tue, 24 May 2011 14:50:20 -0400 Message-Id: <0f61ef7bb618fc7895a339f4eac55abb2092353c.1306258759.git.bengardiner@nanometrics.ca> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: References: X-pstn-levels: (S:99.90000/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) X-pstn-settings: 2 (0.5000:0.0750) s cv GT3 gt2 gt1 r p m c X-pstn-addresses: from [db-null] Cc: Steven Faludi X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com X-Greylist: Sender succeeded STARTTLS authentication, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 24 May 2011 18:53:51 +0000 (UTC) The davinci-pcm driver's snd_pcm_ops pointer function currently calls into the edma controller driver to read the current positions of the edma channels to determine pos to return to the ALSA framework. In particular, davinci_pcm_pointer() calls edma_get_position() and the latter has a comment indicating that "Its channel should not be active when this is called" whereas the channel is surely active when snd_pcm_ops.pointer is called. The operation of davinci-pcm in capture and playback appears to follow close the other pcm drivers who export SNDRV_PCM_INFO_BATCH except that davinci-pcm does not report it's positions from pointer() using the last transferred chunk. Instead it peeks directly into the edma controller to determine the current position as discussed above. Convert the davinci-pcm driver to BATCH mode: count the periods elapsed in the prtd->period member and use its value to report the 'pos' to the alsa framework in the davinci_pcm_pointer function. There is a phase offset of 2 periods between the position used by dma setup and the position reported in the pointer function. Either +2 in the dma setup or -2 in the pointer function (with wrapping, both) accounts for this offset -- I opted for the latter since it makes the first-time setup clearer. Signed-off-by: Ben Gardiner Reviewed-by: Steven Faludi --- sound/soc/davinci/davinci-pcm.c | 67 +++++++++++---------------------------- 1 files changed, 19 insertions(+), 48 deletions(-) diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index fedca81..fa8fc61 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -65,7 +65,8 @@ static void print_buf_info(int slot, char *name) static struct snd_pcm_hardware pcm_hardware_playback = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| + SNDRV_PCM_INFO_BATCH), .formats = DAVINCI_PCM_FMTBITS, .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | @@ -87,7 +88,8 @@ static struct snd_pcm_hardware pcm_hardware_playback = { static struct snd_pcm_hardware pcm_hardware_capture = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_BATCH), .formats = DAVINCI_PCM_FMTBITS, .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | @@ -231,8 +233,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) else edma_set_transfer_params(link, acnt, fifo_level, count, fifo_level, ABSYNC); - - davinci_pcm_period_elapsed(substream); } static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) @@ -247,12 +247,13 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) return; if (snd_pcm_running(substream)) { + spin_lock(&prtd->lock); if (prtd->ram_channel < 0) { /* No ping/pong must fix up link dma data*/ - spin_lock(&prtd->lock); davinci_pcm_enqueue_dma(substream); - spin_unlock(&prtd->lock); } + davinci_pcm_period_elapsed(substream); + spin_unlock(&prtd->lock); snd_pcm_period_elapsed(substream); } } @@ -588,6 +589,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) { struct davinci_runtime_data *prtd = substream->runtime->private_data; + davinci_pcm_period_reset(substream); if (prtd->ram_channel >= 0) { int ret = ping_pong_dma_setup(substream); if (ret < 0) @@ -603,15 +605,19 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) print_buf_info(prtd->asp_link[0], "asp_link[0]"); print_buf_info(prtd->asp_link[1], "asp_link[1]"); + davinci_pcm_period_elapsed(substream); + davinci_pcm_period_elapsed(substream); + return 0; } - davinci_pcm_period_reset(substream); davinci_pcm_enqueue_dma(substream); + davinci_pcm_period_elapsed(substream); /* Copy self-linked parameter RAM entry into master channel */ edma_read_slot(prtd->asp_link[0], &prtd->asp_params); edma_write_slot(prtd->asp_channel, &prtd->asp_params); davinci_pcm_enqueue_dma(substream); + davinci_pcm_period_elapsed(substream); return 0; } @@ -623,51 +629,16 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream) struct davinci_runtime_data *prtd = runtime->private_data; unsigned int offset; int asp_count; - dma_addr_t asp_src, asp_dst; + unsigned int period_size = snd_pcm_lib_period_bytes(substream); spin_lock(&prtd->lock); - if (prtd->ram_channel >= 0) { - int ram_count; - int mod_ram; - dma_addr_t ram_src, ram_dst; - unsigned int period_size = snd_pcm_lib_period_bytes(substream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* reading ram before asp should be safe - * as long as the asp transfers less than a ping size - * of bytes between the 2 reads - */ - edma_get_position(prtd->ram_channel, - &ram_src, &ram_dst); - edma_get_position(prtd->asp_channel, - &asp_src, &asp_dst); - asp_count = asp_src - prtd->asp_params.src; - ram_count = ram_src - prtd->ram_params.src; - mod_ram = ram_count % period_size; - mod_ram -= asp_count; - if (mod_ram < 0) - mod_ram += period_size; - else if (mod_ram == 0) { - if (snd_pcm_running(substream)) - mod_ram += period_size; - } - ram_count -= mod_ram; - if (ram_count < 0) - ram_count += period_size * runtime->periods; - } else { - edma_get_position(prtd->ram_channel, - &ram_src, &ram_dst); - ram_count = ram_dst - prtd->ram_params.dst; - } - asp_count = ram_count; - } else { - edma_get_position(prtd->asp_channel, &asp_src, &asp_dst); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - asp_count = asp_src - runtime->dma_addr; - else - asp_count = asp_dst - runtime->dma_addr; - } + asp_count = prtd->period - 2; spin_unlock(&prtd->lock); + if (asp_count < 0) + asp_count += runtime->periods; + asp_count *= period_size; + offset = bytes_to_frames(runtime, asp_count); if (offset >= runtime->buffer_size) offset = 0;