From patchwork Sun Mar 15 16:01:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 6013491 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.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C18139F318 for ; Sun, 15 Mar 2015 16:06:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D78332022A for ; Sun, 15 Mar 2015 16:06:42 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id A460C20114 for ; Sun, 15 Mar 2015 16:06:41 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id E56A626506E; Sun, 15 Mar 2015 17:06:35 +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, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 41B5F2614C1; Sun, 15 Mar 2015 17:01:50 +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 611F52612C6; Sun, 15 Mar 2015 17:01:40 +0100 (CET) Received: from smtp303.phy.lolipop.jp (smtp303.phy.lolipop.jp [210.157.22.87]) by alsa0.perex.cz (Postfix) with ESMTP id 38ADA260881 for ; Sun, 15 Mar 2015 17:01:21 +0100 (CET) Received: from smtp303.phy.lolipop.lan (HELO smtp303.phy.lolipop.jp) (172.17.1.87) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp303.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Mon, 16 Mar 2015 01:01:16 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp303.phy.lolipop.jp (LOLIPOP-Fsecure); Mon, 16 Mar 2015 01:01:10 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de, robin@gareus.org, damien@zamaudio.com Date: Mon, 16 Mar 2015 01:01:08 +0900 Message-Id: <1426435269-17059-11-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1426435269-17059-1-git-send-email-o-takashi@sakamocchi.jp> References: <1426435269-17059-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 10/11] digi00x: improve MIDI capture/playback 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 Digi 002/003 family are not conformant to IEC 61883-6:2005 or MMA/AMEI RP-027. In fact, they uses AM824 format data, but data channel includes port number in its LSB. The MSB is always 0x80, even if the data channel includes any MIDI messages. As a result, every MIDI conformant data channel can transfer maximum 2 bytes. This commit adds own callback functions to handle this quirk. Signed-off-by: Takashi Sakamoto --- sound/firewire/digi00x/digi00x-protocol.c | 48 +++++++++++++++++++++++++++++++ sound/firewire/digi00x/digi00x-stream.c | 3 ++ sound/firewire/digi00x/digi00x.h | 4 +++ 3 files changed, 55 insertions(+) diff --git a/sound/firewire/digi00x/digi00x-protocol.c b/sound/firewire/digi00x/digi00x-protocol.c index 3e5b3bec..4dd373d 100644 --- a/sound/firewire/digi00x/digi00x-protocol.c +++ b/sound/firewire/digi00x/digi00x-protocol.c @@ -8,6 +8,54 @@ #include "digi00x.h" +void snd_dg00x_protocol_fill_midi(struct amdtp_stream *s, + __be32 *buffer, unsigned int frames) +{ + unsigned int f, port; + u8 *b; + + for (f = 0; f < frames; f++) { + port = (s->data_block_counter + f) % 4; + b = (u8 *)&buffer[s->midi_position]; + + /* + * The device allows to transfer MIDI messages by maximum two + * bytes per data channel. But this module transfers one byte + * one time because MIDI data rate is quite lower than IEEE + * 1394 bus data rate. + */ + if (amdtp_midi_ratelimit_per_packet(s, port) && + s->midi[port] != NULL && + snd_rawmidi_transmit(s->midi[port], &b[1], 1) == 1) { + amdtp_midi_rate_use_one_byte(s, port); + b[3] = 0x01 | (0x10 << port); + } else { + b[1] = 0; + b[3] = 0; + } + b[0] = 0x80; + b[2] = 0; + + buffer += s->data_block_quadlets; + } +} + +void snd_dg00x_protocol_pull_midi(struct amdtp_stream *s, + __be32 *buffer, unsigned int frames) +{ + unsigned int f; + u8 *b; + + for (f = 0; f < frames; f++) { + b = (u8 *)&buffer[s->midi_position]; + + if (s->midi[0] && (b[3] > 0)) + snd_rawmidi_receive(s->midi[0], b + 1, b[3]); + + buffer += s->data_block_quadlets; + } +} + struct workqueue_struct *midi_wq; static void send_midi_control(struct work_struct *work) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 92eb86d..410b971 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -204,6 +204,9 @@ static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate) dg00x->rx_stream.midi_position = 0; dg00x->tx_stream.midi_position = 0; + dg00x->rx_stream.transfer_midi = snd_dg00x_protocol_fill_midi; + dg00x->tx_stream.transfer_midi = snd_dg00x_protocol_pull_midi; + return 0; error: release_resources(dg00x); diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 20b178f..a658f44 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -84,6 +84,10 @@ enum snd_dg00x_optical_mode { SND_DG00X_OPTICAL_MODE_SPDIF, }; +void snd_dg00x_protocol_fill_midi(struct amdtp_stream *s, + __be32 *buffer, unsigned int frames); +void snd_dg00x_protocol_pull_midi(struct amdtp_stream *s, + __be32 *buffer, unsigned int frames); void snd_dg00x_protocol_queue_midi_message(struct snd_dg00x *dg00x); int snd_dg00x_protocol_add_instance(struct snd_dg00x *dg00x); void snd_dg00x_protocol_remove_instance(struct snd_dg00x *dg00x);