From patchwork Mon Aug 17 11:51:18 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Valentin X-Patchwork-Id: 42000 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n7HC64fE009166 for ; Mon, 17 Aug 2009 12:06:06 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757935AbZHQMFj (ORCPT ); Mon, 17 Aug 2009 08:05:39 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757915AbZHQMFi (ORCPT ); Mon, 17 Aug 2009 08:05:38 -0400 Received: from smtp.nokia.com ([192.100.122.230]:23237 "EHLO mgw-mx03.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757906AbZHQMFW (ORCPT ); Mon, 17 Aug 2009 08:05:22 -0400 Received: from esebh105.NOE.Nokia.com (esebh105.ntc.nokia.com [172.21.138.211]) by mgw-mx03.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id n7HC58JG022864; Mon, 17 Aug 2009 15:05:12 +0300 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by esebh105.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 17 Aug 2009 15:05:16 +0300 Received: from vaebe101.NOE.Nokia.com ([10.160.244.11]) by esebh102.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 17 Aug 2009 15:05:15 +0300 Received: from localhost.localdomain ([172.21.41.168]) by vaebe101.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 17 Aug 2009 15:05:15 +0300 From: Eduardo Valentin To: Takashi Iwai Cc: Linux-OMAP , ALSA-Devel , Jarkko Nikula , "Nurkkala Eero.An (EXT-Offcode/Oulu)" , "Ujfalusi Peter (Nokia-D/Tampere)" , Mark Brown , Eduardo Valentin Subject: [PATCHv4 19/20] ASoC: OMAP: Use McBSP threshold to playback and capture Date: Mon, 17 Aug 2009 14:51:18 +0300 Message-Id: <1250509879-6703-20-git-send-email-eduardo.valentin@nokia.com> X-Mailer: git-send-email 1.6.2.GIT In-Reply-To: <1250509879-6703-1-git-send-email-eduardo.valentin@nokia.com> References: <1250509879-6703-1-git-send-email-eduardo.valentin@nokia.com> X-OriginalArrivalTime: 17 Aug 2009 12:05:15.0067 (UTC) FILETIME=[FAD688B0:01CA1F32] X-Nokia-AV: Clean Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org From: Eduardo Valentin This patch changes the way DMA is done in omap-pcm.c in order to reduce power consumption. There is no need to have so much SW control in order to have DMA in idle state during audio streaming. Configuring McBSP threshold value and DMA to FRAME_SYNC are sufficient. Signed-off-by: Eduardo Valentin --- sound/soc/omap/omap-mcbsp.c | 47 +++++++++++++++++++++++++++++++++++++----- sound/soc/omap/omap-pcm.c | 7 +++++- sound/soc/omap/omap-pcm.h | 2 + 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 76c32f8..2aec7a6 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -139,28 +139,59 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { static const unsigned long omap34xx_mcbsp_port[][2] = {}; #endif +static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + int samples = snd_pcm_lib_period_bytes(substream) >> 1; + + /* Configure McBSP internal buffer usage */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1); + else + omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1); +} + static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + int bus_id = mcbsp_data->bus_id; int err = 0; - if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { + if (!cpu_dai->active) + err = omap_mcbsp_request(bus_id); + + if (cpu_is_omap343x()) { + int max_period; + /* * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. * Set constraint for minimum buffer size to the same than FIFO * size in order to avoid underruns in playback startup because * HW is keeping the DMA request active until FIFO is filled. */ + if (bus_id == 1) + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + 4096, UINT_MAX); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + max_period = omap_mcbsp_get_max_tx_threshold(bus_id); + else + max_period = omap_mcbsp_get_max_rx_threshold(bus_id); + + max_period++; + max_period <<= 1; + snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + 32, max_period); } - if (!cpu_dai->active) - err = omap_mcbsp_request(mcbsp_data->bus_id); - return err; } @@ -219,7 +250,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; - int wlen, channels, wpf; + int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; unsigned long port; unsigned int format; @@ -235,6 +266,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, } else if (cpu_is_omap343x()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; + omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = + omap_mcbsp_set_threshold; + sync_mode = OMAP_DMA_SYNC_FRAME; } else { return -ENODEV; } @@ -242,6 +276,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, substream->stream ? "Audio Capture" : "Audio Playback"; omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; + omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; if (mcbsp_data->configured) { diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index f037db0..7ebd169 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -164,7 +164,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) */ dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; dma_params.trigger = dma_data->dma_req; - dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; + dma_params.sync_mode = dma_data->sync_mode; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; @@ -203,6 +203,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct omap_runtime_data *prtd = runtime->private_data; + struct omap_pcm_dma_data *dma_data = prtd->dma_data; unsigned long flags; int ret = 0; @@ -212,6 +213,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->period_index = 0; + /* Configure McBSP internal buffer usage */ + if (dma_data->set_threshold) + dma_data->set_threshold(substream); + omap_start_dma(prtd->dma_ch); break; diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index 8d9d269..38a821d 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -29,6 +29,8 @@ struct omap_pcm_dma_data { char *name; /* stream identifier */ int dma_req; /* DMA request line */ unsigned long port_addr; /* transmit/receive register */ + int sync_mode; /* DMA sync mode */ + void (*set_threshold)(struct snd_pcm_substream *substream); }; extern struct snd_soc_platform omap_soc_platform;