From patchwork Thu Jun 3 04:39:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Ujfalusi X-Patchwork-Id: 103953 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o534dvF4031876 for ; Thu, 3 Jun 2010 04:41:18 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751809Ab0FCEk3 (ORCPT ); Thu, 3 Jun 2010 00:40:29 -0400 Received: from smtp.nokia.com ([192.100.105.134]:26011 "EHLO mgw-mx09.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751776Ab0FCEk2 (ORCPT ); Thu, 3 Jun 2010 00:40:28 -0400 Received: from esebh105.NOE.Nokia.com (esebh105.ntc.nokia.com [172.21.138.211]) by mgw-mx09.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id o534drMU027822; Wed, 2 Jun 2010 23:40:20 -0500 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by esebh105.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.4675); Thu, 3 Jun 2010 07:39:56 +0300 Received: from mgw-da01.ext.nokia.com ([147.243.128.24]) by esebh102.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Thu, 3 Jun 2010 07:39:55 +0300 Received: from cseresznye.nmp.nokia.com (cseresznye.nmp.nokia.com [172.22.211.20]) by mgw-da01.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id o534daRG008370; Thu, 3 Jun 2010 07:39:50 +0300 From: Peter Ujfalusi To: alsa-devel@alsa-project.org, linux-omap@vger.kernel.org, tony@atomide.com Cc: broonie@opensource.wolfsonmicro.com, lrg@slimlogic.co.uk, jhnikula@gmail.com, ext-eero.nurkkala@nokia.com, eduardo.valentin@nokia.com Subject: [PATCH v5 5/5] ASoC: omap-mcbsp: Place correct constraints for streams Date: Thu, 3 Jun 2010 07:39:36 +0300 Message-Id: <1275539976-2075-6-git-send-email-peter.ujfalusi@nokia.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1275539976-2075-1-git-send-email-peter.ujfalusi@nokia.com> References: <1275539976-2075-1-git-send-email-peter.ujfalusi@nokia.com> X-OriginalArrivalTime: 03 Jun 2010 04:39:56.0278 (UTC) FILETIME=[D0FE6160:01CB02D6] X-Nokia-AV: Clean Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 03 Jun 2010 04:41:26 +0000 (UTC) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index b06d8f1..aebd3af 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -173,6 +173,50 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words); } +static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *buffer_size = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct omap_mcbsp_data *mcbsp_data = rule->private; + struct snd_interval frames; + int size; + + snd_interval_any(&frames); + size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id); + + frames.min = size / channels->min; + frames.integer = 1; + return snd_interval_refine(buffer_size, &frames); +} + +static int omap_mcbsp_hwrule_max_periodsize(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *period_size = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_pcm_substream *substream = rule->private; + 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); + struct snd_interval frames; + int size; + + snd_interval_any(&frames); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + size = omap_mcbsp_get_max_tx_threshold(mcbsp_data->bus_id); + else + size = omap_mcbsp_get_max_rx_threshold(mcbsp_data->bus_id); + + frames.max = size / channels->min; + frames.integer = 1; + return snd_interval_refine(period_size, &frames); +} + static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -185,33 +229,45 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, if (!cpu_dai->active) err = omap_mcbsp_request(bus_id); + /* + * OMAP3 McBSP FIFO is word structured. + * McBSP2 has 1024 + 256 = 1280 word long buffer, + * McBSP1,3,4,5 has 128 word long buffer + * This means that the size of the FIFO depends on the sample format. + * For example on McBSP3: + * 16bit samples: size is 128 * 2 = 256 bytes + * 32bit samples: size is 128 * 4 = 512 bytes + * It is simpler to place constraint for buffer and period based on + * channels. + * McBSP3 as example again (16 or 32 bit samples): + * 1 channel (mono): size is 128 frames (128 words) + * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) + * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) + */ if (cpu_is_omap343x()) { int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); - 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; + * The first rule is for the buffer size, we should not allow + * smaller buffer than the FIFO size to avoid underruns + */ + snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + omap_mcbsp_hwrule_min_buffersize, + mcbsp_data, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); + /* + * In case of threshold mode, the rule will ensure, that the + * period size is not bigger than the maximum allowed threshold + * value. + */ if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - 32, max_period); + snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + omap_mcbsp_hwrule_max_periodsize, + substream, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); } return err;