From patchwork Sat Oct 4 11:27:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 5032321 X-Patchwork-Delegate: tiwai@suse.de Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 792C29F327 for ; Sat, 4 Oct 2014 11:32:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 933B1201FE for ; Sat, 4 Oct 2014 11:32:38 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 4D3882017E for ; Sat, 4 Oct 2014 11:32:37 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 6E262261548; Sat, 4 Oct 2014 13:32:36 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 5B8802605A7; Sat, 4 Oct 2014 13:27:59 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C062B260561; Sat, 4 Oct 2014 13:27:55 +0200 (CEST) Received: from smtp310.phy.lolipop.jp (smtp310.phy.lolipop.jp [210.157.22.78]) by alsa0.perex.cz (Postfix) with ESMTP id D0310260563 for ; Sat, 4 Oct 2014 13:27:43 +0200 (CEST) Received: from smtp310.phy.lolipop.lan (HELO smtp310.phy.lolipop.jp) (172.17.1.10) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp310.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Sat, 04 Oct 2014 20:27:42 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp310.phy.lolipop.jp (LOLIPOP-Fsecure); Sat, 04 Oct 2014 20:27:25 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de Date: Sat, 4 Oct 2014 20:27:18 +0900 Message-Id: <1412422044-15133-9-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1412422044-15133-1-git-send-email-o-takashi@sakamocchi.jp> References: <1412422044-15133-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, ffado-devel@lists.sourceforge.net Subject: [alsa-devel] [PATCH 08/14] ALSA: dice: Add new functions for restriction of PCM parameters X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This commit adds a new functions and some arrangement for PCM restriction. This arrangement is due to the number of channels which each Dice device has. I note that minimum number for period becomes 2, instead of 1 because its PCM functionality has SNDRV_PCM_INFO_BATCH, this means that the driver uses double (or more) buffering so the minimum number for period should be 2. Signed-off-by: Takashi Sakamoto --- sound/firewire/dice/dice-pcm.c | 109 +++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index beff320..2e531bd 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -67,69 +67,92 @@ static int dice_channels_constraint(struct snd_pcm_hw_params *params, return snd_interval_refine(c, &channels); } - -static int pcm_open(struct snd_pcm_substream *substream) +static void limit_channels_and_rates(struct snd_dice *dice, + struct snd_pcm_runtime *runtime, + unsigned int *pcm_channels) { - static const struct snd_pcm_hardware hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = AMDTP_OUT_PCM_FORMAT_BITS, - .channels_min = UINT_MAX, - .channels_max = 0, - .buffer_bytes_max = 16 * 1024 * 1024, - .period_bytes_min = 1, - .period_bytes_max = UINT_MAX, - .periods_min = 1, - .periods_max = UINT_MAX, - }; - struct snd_dice *dice = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int i; - int err; + struct snd_pcm_hardware *hw = &runtime->hw; + unsigned int i, rate, mode; - err = snd_dice_stream_lock_try(dice); - if (err < 0) - goto error; + hw->channels_min = UINT_MAX; + hw->channels_max = 0; + + for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { + rate = snd_dice_rates[i]; + if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0) + continue; + hw->rates |= snd_pcm_rate_to_rate_bit(rate); - runtime->hw = hardware; + if (pcm_channels[mode] == 0) + continue; + hw->channels_min = min(hw->channels_min, pcm_channels[mode]); + hw->channels_max = max(hw->channels_max, pcm_channels[mode]); + } - for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) - if (dice->clock_caps & (1 << i)) - runtime->hw.rates |= - snd_pcm_rate_to_rate_bit(snd_dice_rates[i]); snd_pcm_limit_hw_rates(runtime); +} - for (i = 0; i < 3; ++i) - if (dice->rx_channels[i]) { - runtime->hw.channels_min = min(runtime->hw.channels_min, - dice->rx_channels[i]); - runtime->hw.channels_max = max(runtime->hw.channels_max, - dice->rx_channels[i]); - } +static void limit_period_and_buffer(struct snd_pcm_hardware *hw) +{ + hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ + hw->periods_max = UINT_MAX; + + hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ + + /* Just to prevent from allocating much pages. */ + hw->period_bytes_max = hw->period_bytes_min * 2048; + hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; +} + +static int init_hw_info(struct snd_dice *dice, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hardware *hw = &runtime->hw; + int err; + + hw->info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER; + hw->formats = AMDTP_OUT_PCM_FORMAT_BITS; + + limit_channels_and_rates(dice, runtime, dice->rx_channels); + limit_period_and_buffer(hw); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, dice_rate_constraint, dice, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (err < 0) - goto err_lock; + goto end; err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, dice_channels_constraint, dice, SNDRV_PCM_HW_PARAM_RATE, -1); if (err < 0) - goto err_lock; + goto end; err = amdtp_stream_add_pcm_hw_constraints(&dice->rx_stream, runtime); - if (err < 0) - goto err_lock; +end: + return err; +} - return 0; +static int pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_dice *dice = substream->private_data; + int err; -err_lock: + err = snd_dice_stream_lock_try(dice); + if (err < 0) + goto end; + + err = init_hw_info(dice, substream); + if (err < 0) + goto err_locked; +end: + return err; +err_locked: snd_dice_stream_lock_release(dice); -error: return err; }