From patchwork Sat Mar 5 11:58:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 8510151 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 90333C0553 for ; Sat, 5 Mar 2016 11:59:18 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 74BF42022A for ; Sat, 5 Mar 2016 11:59:17 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id DDD7D20268 for ; Sat, 5 Mar 2016 11:59:15 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 3C809266A5D; Sat, 5 Mar 2016 12:59:11 +0100 (CET) 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, RCVD_IN_DNSWL_NONE, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 293C82608B4; Sat, 5 Mar 2016 12:58:24 +0100 (CET) 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 1F8D1260831; Sat, 5 Mar 2016 12:58:21 +0100 (CET) Received: from smtp311.phy.lolipop.jp (smtp311.phy.lolipop.jp [210.157.22.79]) by alsa0.perex.cz (Postfix) with ESMTP id 7C6D9260831 for ; Sat, 5 Mar 2016 12:58:11 +0100 (CET) Received: from smtp311.phy.lolipop.lan (HELO smtp311.phy.lolipop.jp) (172.17.1.11) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp311.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Sat, 05 Mar 2016 20:58:09 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp311.phy.lolipop.jp (LOLIPOP-Fsecure); Sat, 05 Mar 2016 20:58:07 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de Date: Sat, 5 Mar 2016 20:58:06 +0900 Message-Id: <1457179087-27604-4-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1457179087-27604-1-git-send-email-o-takashi@sakamocchi.jp> References: <1457179087-27604-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, stefanr@s5r6.in-berlin.de, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 3/4] ALSA: dice: handle several PCM substreams when any isochronous streams are available 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 In former commits, ALSA dice driver can handle available isochronous streams. This commit adds support for several PCM substreams on the streams. The additional PCM substreams are available via subdevice of ALSA PCM character devices. For example, two PCM substreams are available on the streams, the second PCM substream is handled via second subdevice of the character device. In configuration space of alsa-lib, it's represented with 'hw:0,0,1' The PCM substreams are constraint to parameters of the corresponding streams. If for some reasons, the PCM substreams are unavailable, open(2) to ALSA PCM character device returns error and reports ENXIO. Signed-off-by: Takashi Sakamoto --- sound/firewire/dice/dice-pcm.c | 82 +++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index e252949..3762bd3 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -11,28 +11,34 @@ static int limit_channels_and_rates(struct snd_dice *dice, struct snd_pcm_runtime *runtime, - struct amdtp_stream *stream) + enum amdtp_stream_direction dir, + unsigned int index, unsigned int size) { struct snd_pcm_hardware *hw = &runtime->hw; + struct amdtp_stream *stream; unsigned int rate; - __be32 reg[2]; + __be32 reg; int err; /* * Retrieve current Multi Bit Linear Audio data channel and limit to * it. */ - if (stream == &dice->tx_stream[0]) { - err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO, - reg, sizeof(reg)); + if (dir == AMDTP_IN_STREAM) { + stream = &dice->tx_stream[index]; + err = snd_dice_transaction_read_tx(dice, + size * index + TX_NUMBER_AUDIO, + ®, sizeof(reg)); } else { - err = snd_dice_transaction_read_rx(dice, RX_NUMBER_AUDIO, - reg, sizeof(reg)); + stream = &dice->rx_stream[index]; + err = snd_dice_transaction_read_rx(dice, + size * index + RX_NUMBER_AUDIO, + ®, sizeof(reg)); } if (err < 0) return err; - hw->channels_min = hw->channels_max = be32_to_cpu(reg[0]); + hw->channels_min = hw->channels_max = be32_to_cpu(reg); /* Retrieve current sampling transfer frequency and limit to it. */ err = snd_dice_transaction_get_rate(dice, &rate); @@ -62,7 +68,10 @@ static int init_hw_info(struct snd_dice *dice, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_hardware *hw = &runtime->hw; + enum amdtp_stream_direction dir; struct amdtp_stream *stream; + __be32 reg[2]; + unsigned int count, size; int err; hw->info = SNDRV_PCM_INFO_MMAP | @@ -74,13 +83,28 @@ static int init_hw_info(struct snd_dice *dice, if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { hw->formats = AM824_IN_PCM_FORMAT_BITS; - stream = &dice->tx_stream[0]; + dir = AMDTP_IN_STREAM; + stream = &dice->tx_stream[substream->number]; + err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, + sizeof(reg)); } else { hw->formats = AM824_OUT_PCM_FORMAT_BITS; - stream = &dice->rx_stream[0]; + dir = AMDTP_OUT_STREAM; + stream = &dice->rx_stream[substream->number]; + err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, + sizeof(reg)); } - err = limit_channels_and_rates(dice, runtime, stream); + if (err < 0) + return err; + + count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS); + if (substream->number >= count) + return -ENXIO; + + size = be32_to_cpu(reg[1]) * 4; + err = limit_channels_and_rates(dice, substream->runtime, dir, + substream->number, size); if (err < 0) return err; limit_period_and_buffer(hw); @@ -122,7 +146,7 @@ static int capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->tx_stream[0]; + struct amdtp_stream *stream = &dice->tx_stream[substream->number]; int err; err = snd_pcm_lib_alloc_vmalloc_buffer(substream, @@ -144,7 +168,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->rx_stream[0]; + struct amdtp_stream *stream = &dice->rx_stream[substream->number]; int err; err = snd_pcm_lib_alloc_vmalloc_buffer(substream, @@ -198,7 +222,7 @@ static int playback_hw_free(struct snd_pcm_substream *substream) static int capture_prepare(struct snd_pcm_substream *substream) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->tx_stream[0]; + struct amdtp_stream *stream = &dice->tx_stream[substream->number]; int err; mutex_lock(&dice->mutex); @@ -212,7 +236,7 @@ static int capture_prepare(struct snd_pcm_substream *substream) static int playback_prepare(struct snd_pcm_substream *substream) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->rx_stream[0]; + struct amdtp_stream *stream = &dice->rx_stream[substream->number]; int err; mutex_lock(&dice->mutex); @@ -227,7 +251,7 @@ static int playback_prepare(struct snd_pcm_substream *substream) static int capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->tx_stream[0]; + struct amdtp_stream *stream = &dice->tx_stream[substream->number]; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -245,7 +269,7 @@ static int capture_trigger(struct snd_pcm_substream *substream, int cmd) static int playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->rx_stream[0]; + struct amdtp_stream *stream = &dice->rx_stream[substream->number]; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -264,14 +288,14 @@ static int playback_trigger(struct snd_pcm_substream *substream, int cmd) static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->tx_stream[0]; + struct amdtp_stream *stream = &dice->tx_stream[substream->number]; return amdtp_stream_pcm_pointer(stream); } static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->rx_stream[0]; + struct amdtp_stream *stream = &dice->rx_stream[substream->number]; return amdtp_stream_pcm_pointer(stream); } @@ -307,25 +331,17 @@ int snd_dice_create_pcm(struct snd_dice *dice) unsigned int capture, playback; int err; - /* - * Check whether PCM substreams are required. - * - * TODO: in the case that any PCM substreams are not avail at a certain - * sampling transfer frequency? - */ - err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO, - ®, sizeof(reg)); + /* Check whether PCM substreams are required. */ + capture = playback = 0; + err = snd_dice_transaction_read_tx(dice, TX_NUMBER, ®, sizeof(reg)); if (err < 0) return err; - if (be32_to_cpu(reg) > 0) - capture = 1; + capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); - err = snd_dice_transaction_read_rx(dice, RX_NUMBER_AUDIO, - ®, sizeof(reg)); + err = snd_dice_transaction_read_rx(dice, RX_NUMBER, ®, sizeof(reg)); if (err < 0) return err; - if (be32_to_cpu(reg) > 0) - playback = 1; + playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); err = snd_pcm_new(dice->card, "DICE", 0, playback, capture, &pcm); if (err < 0)