From patchwork Fri Apr 25 13:44:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 4062791 X-Patchwork-Delegate: tiwai@suse.de 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.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8BEF2BFF02 for ; Fri, 25 Apr 2014 13:58:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 806A920383 for ; Fri, 25 Apr 2014 13:58:26 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 2A8AA20222 for ; Fri, 25 Apr 2014 13:58:25 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 7AFDF26562B; Fri, 25 Apr 2014 15:58:23 +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, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id EB9EB2654C5; Fri, 25 Apr 2014 15:46:02 +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 08C0D2654BC; Fri, 25 Apr 2014 15:45:59 +0200 (CEST) Received: from smtp310.phy.lolipop.jp (smtp310.phy.lolipop.jp [210.157.22.78]) by alsa0.perex.cz (Postfix) with ESMTP id 3C3C026548E for ; Fri, 25 Apr 2014 15:45:46 +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; Fri, 25 Apr 2014 22:45:45 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp310.phy.lolipop.jp (LOLIPOP-Fsecure); Fri, 25 Apr 2014 22:45:31 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de, perex@perex.cz Date: Fri, 25 Apr 2014 22:44:45 +0900 Message-Id: <1398433530-13136-5-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1398433530-13136-1-git-send-email-o-takashi@sakamocchi.jp> References: <1398433530-13136-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, linux1394-devel@lists.sourceforge.net, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 04/49] firewire-lib: Split some codes into functions to reuse for both streams 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 Some codes can be reused to handle in-stream. This commit adds new functions. This commit also renames some functions to keep naming consistency. Signed-off-by: Takashi Sakamoto --- sound/firewire/amdtp.c | 154 ++++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 73 deletions(-) diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index 95c5a15..790aa86 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c @@ -47,6 +47,8 @@ #define INTERRUPT_INTERVAL 16 #define QUEUE_LENGTH 48 +#define OUT_PACKET_HEADER_SIZE 0 + static void pcm_period_tasklet(unsigned long data); /** @@ -440,13 +442,73 @@ static void amdtp_fill_midi(struct amdtp_stream *s, cpu_to_be32(0x80000000); } -static void queue_out_packet(struct amdtp_stream *s, unsigned int cycle) +static void update_pcm_pointers(struct amdtp_stream *s, + struct snd_pcm_substream *pcm, + unsigned int frames) +{ unsigned int ptr; + + if (s->dual_wire) + frames *= 2; + + ptr = s->pcm_buffer_pointer + frames; + if (ptr >= pcm->runtime->buffer_size) + ptr -= pcm->runtime->buffer_size; + ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; + + s->pcm_period_pointer += frames; + if (s->pcm_period_pointer >= pcm->runtime->period_size) { + s->pcm_period_pointer -= pcm->runtime->period_size; + s->pointer_flush = false; + tasklet_hi_schedule(&s->period_tasklet); + } +} + +static void pcm_period_tasklet(unsigned long data) +{ + struct amdtp_stream *s = (void *)data; + struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm); + + if (pcm) + snd_pcm_period_elapsed(pcm); +} + +static int queue_packet(struct amdtp_stream *s, + unsigned int header_length, + unsigned int payload_length, bool skip) +{ + struct fw_iso_packet p = {0}; + int err; + + p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); + p.tag = TAG_CIP; + p.header_length = header_length; + p.payload_length = (!skip) ? payload_length : 0; + p.skip = skip; + err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer, + s->buffer.packets[s->packet_index].offset); + if (err < 0) { + dev_err(&s->unit->device, "queueing error: %d\n", err); + goto end; + } + + if (++s->packet_index >= QUEUE_LENGTH) + s->packet_index = 0; +end: + return err; +} + +static inline int queue_out_packet(struct amdtp_stream *s, + unsigned int payload_length, bool skip) +{ + return queue_packet(s, OUT_PACKET_HEADER_SIZE, + payload_length, skip); +} + +static void handle_out_packet(struct amdtp_stream *s, unsigned int cycle) { __be32 *buffer; - unsigned int index, data_blocks, syt, ptr; + unsigned int index, data_blocks, syt, payload_length; struct snd_pcm_substream *pcm; - struct fw_iso_packet packet; - int err; if (s->packet_index < 0) return; @@ -479,55 +541,20 @@ static void queue_out_packet(struct amdtp_stream *s, unsigned int cycle) s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; - packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL); - packet.skip = 0; - packet.tag = TAG_CIP; - packet.sy = 0; - packet.header_length = 0; - - err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer, - s->buffer.packets[index].offset); - if (err < 0) { - dev_err(&s->unit->device, "queueing error: %d\n", err); + payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; + if (queue_out_packet(s, payload_length, false) < 0) { s->packet_index = -1; amdtp_stream_pcm_abort(s); return; } - if (++index >= QUEUE_LENGTH) - index = 0; - s->packet_index = index; - - if (pcm) { - if (s->dual_wire) - data_blocks *= 2; - - ptr = s->pcm_buffer_pointer + data_blocks; - if (ptr >= pcm->runtime->buffer_size) - ptr -= pcm->runtime->buffer_size; - ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; - - s->pcm_period_pointer += data_blocks; - if (s->pcm_period_pointer >= pcm->runtime->period_size) { - s->pcm_period_pointer -= pcm->runtime->period_size; - s->pointer_flush = false; - tasklet_hi_schedule(&s->period_tasklet); - } - } -} - -static void pcm_period_tasklet(unsigned long data) -{ - struct amdtp_stream *s = (void *)data; - struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm); - if (pcm) - snd_pcm_period_elapsed(pcm); + update_pcm_pointers(s, pcm, data_blocks); } -static void out_packet_callback(struct fw_iso_context *context, u32 cycle, - size_t header_length, void *header, void *private_data) +static void out_stream_callback(struct fw_iso_context *context, u32 cycle, + size_t header_length, void *header, + void *private_data) { struct amdtp_stream *s = private_data; unsigned int i, packets = header_length / 4; @@ -540,31 +567,10 @@ static void out_packet_callback(struct fw_iso_context *context, u32 cycle, cycle += QUEUE_LENGTH - packets; for (i = 0; i < packets; ++i) - queue_out_packet(s, ++cycle); + handle_out_packet(s, ++cycle); fw_iso_context_queue_flush(s->context); } -static int queue_initial_skip_packets(struct amdtp_stream *s) -{ - struct fw_iso_packet skip_packet = { - .skip = 1, - }; - unsigned int i; - int err; - - for (i = 0; i < QUEUE_LENGTH; ++i) { - skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1, - INTERRUPT_INTERVAL); - err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0); - if (err < 0) - return err; - if (++s->packet_index >= QUEUE_LENGTH) - s->packet_index = 0; - } - - return 0; -} - /** * amdtp_stream_start - start transferring packets * @s: the AMDTP stream to start @@ -594,11 +600,12 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) mutex_lock(&s->mutex); if (WARN_ON(amdtp_stream_running(s) || - (!s->pcm_channels && !s->midi_ports))) { + (s->data_block_quadlets < 1))) { err = -EBADFD; goto err_unlock; } + s->data_block_counter = 0; s->data_block_state = initial_state[s->sfc].data_block; s->syt_offset_state = initial_state[s->sfc].syt_offset; s->last_syt_offset = TICKS_PER_CYCLE; @@ -612,7 +619,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, FW_ISO_CONTEXT_TRANSMIT, channel, speed, 0, - out_packet_callback, s); + out_stream_callback, s); if (IS_ERR(s->context)) { err = PTR_ERR(s->context); if (err == -EBUSY) @@ -624,10 +631,11 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) amdtp_stream_update(s); s->packet_index = 0; - s->data_block_counter = 0; - err = queue_initial_skip_packets(s); - if (err < 0) - goto err_context; + do { + err = queue_out_packet(s, 0, true); + if (err < 0) + goto err_context; + } while (s->packet_index > 0); err = fw_iso_context_start(s->context, -1, 0, 0); if (err < 0)