From patchwork Sat Jul 11 14:12:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 6770691 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 C7AABC05AC for ; Sat, 11 Jul 2015 14:28:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A48DA204E0 for ; Sat, 11 Jul 2015 14:28:10 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 281D0203A5 for ; Sat, 11 Jul 2015 14:28:09 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 30347266A9C; Sat, 11 Jul 2015 16:28:08 +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 9EA092666D7; Sat, 11 Jul 2015 16:13:58 +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 CFC9E260711; Sat, 11 Jul 2015 16:13:44 +0200 (CEST) Received: from smtp301.phy.lolipop.jp (smtp301.phy.lolipop.jp [210.157.22.84]) by alsa0.perex.cz (Postfix) with ESMTP id 0C3B12605C2 for ; Sat, 11 Jul 2015 16:13:07 +0200 (CEST) Received: from smtp301.phy.lolipop.lan (HELO smtp301.phy.lolipop.jp) (172.17.1.84) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp301.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Sat, 11 Jul 2015 23:13:02 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp301.phy.lolipop.jp (LOLIPOP-Fsecure); Sat, 11 Jul 2015 23:12:49 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de Date: Sat, 11 Jul 2015 23:12:37 +0900 Message-Id: <1436623968-10780-27-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1436623968-10780-1-git-send-email-o-takashi@sakamocchi.jp> References: <1436623968-10780-1-git-send-email-o-takashi@sakamocchi.jp> Cc: Yoshifuji Hideaki , alsa-devel@alsa-project.org, ffado-devel@lists.sf.net Subject: [alsa-devel] [RFC][PATCH 26/37] ALSA: firewire-tascam: add MMAP support to show status and control message 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 TASCAM FireWire series transfers status and control messages in isochronous packets. One packet includes one message, and the message is periodic every 64 packets. As a result, the messages construct image with 64 quadlets. For example: 00 00000000, 32 00000000 01 00000000, 33 00000000 02 00000000, 34 00000000 03 00020000, 35 00000000 04 00000000, 36 25ea0000 05 ffff0000, 37 27dfff00 06 ffffffff, 38 1d9d0000 07 ffffffff, 39 00000000 08 ffffffff, 40 25ea0000 09 ffffffff, 41 27dfff00 10 00000000, 42 00000000 11 00000000, 43 00000000 12 00000000, 44 00000000 13 00000000, 45 00000000 14 00000000, 46 00000000 15 00010000, 47 00000000 16 00012e00, 48 00000000 17 00010400, 49 00000000 18 00011e00, 50 00000000 19 00011200, 51 00000000 20 00014900, 52 01010101 21 00011e00, 53 00000000 22 00010c00, 54 25ea0000 23 00013000, 55 27dfff00 24 00000000, 56 00000000 25 00000000, 57 00000000 26 00000000, 58 00000000 27 00000000, 59 00000001 28 00000000, 60 00000000 29 00000000, 61 00000000 30 00000000, 62 00000000 31 00000000, 63 00000000 Quadlet 00-15 show control messages. Quadlet 16-23 show analog input level. Quadlet 24-31 shows digital ADAT input level. Quadlet 32-33 shows digital S/PDIF input level. Quadlet 34-35 is unknown. Quadlet 36-43 shows analog output level. The other quadlets are unknown. This image is updated every 1 msec or less, depending on current sampling transfer frequency. This commit adds MMAP support to show this image via hwdep interface. An userspace application can map a page frame to its virtual address space with read-only flag. This driver write every control and status messages into the page frame, and the userspace application can parse them. The control messages are both of edge-triggered/level-trigerred, according to physical implementation. For example, the control message corresponding to toggle switch acts as edge-trigger, while the control message corresponding to level fader acts as level-trigger. These control messages are updated every 1 msec or less, alghough the scheduling granuality in Linux operating system is not always so small. This may cause the userspace parser misses some messages when many tasks are running without voluntary programs. Typically, such messages should be converted to MIDI control change messages for userspace applications. Thus, this driver should have a converter with appropriate MIDI map. Currently I have no good idea for the map and it is not implemented yet. Developers helps are required. Cc: Yoshifuji Hideaki Signed-off-by: Takashi Sakamoto --- include/uapi/sound/firewire.h | 4 ++++ sound/firewire/tascam/amdtp-tascam.c | 4 +++- sound/firewire/tascam/tascam-hwdep.c | 30 ++++++++++++++++++++++++++++++ sound/firewire/tascam/tascam-stream.c | 15 +++++++++++++++ sound/firewire/tascam/tascam.h | 3 +++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index db79a12..c5cb86d 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -79,4 +79,8 @@ struct snd_firewire_get_info { * Returns -EBUSY if the driver is already streaming. */ +struct snd_firewire_tascam_status { + __u32 status[64]; +}; + #endif /* _UAPI_SOUND_FIREWIRE_H_INCLUDED */ diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 22c2eaf..ca54b85 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -155,14 +155,16 @@ void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) static void read_control_messages(struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks) { + struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream); unsigned int first, index = 0; unsigned int i; first = (buffer[0] >> 15) % 64; - /* TODO */ for (i = 0; i < data_blocks; i++) { index = be32_to_cpu(buffer[0]) % 64; + tscm->status->status[index] = + be32_to_cpu(buffer[s->data_block_quadlets - 1]); buffer += s->data_block_quadlets; } } diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 4b539f5..fe51fee 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -175,12 +175,42 @@ static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, #define hwdep_compat_ioctl NULL #endif +static int hwdep_vm_fault(struct vm_area_struct *area, struct vm_fault *vmf) +{ + struct snd_tscm *tscm = area->vm_private_data; + void *virt_addr; + struct page *page; + + /* The page is already allocated by streaming layer. */ + virt_addr = (char *)(tscm->status) + (vmf->pgoff << PAGE_SHIFT); + page = virt_to_page(virt_addr); + get_page(page); + vmf->page = page; + + return 0; +} + +static const struct vm_operations_struct hwdep_vm_ops = { + .fault = hwdep_vm_fault, +}; + +static int hwdep_mmap(struct snd_hwdep *hwdep, struct file *filp, + struct vm_area_struct *area) +{ + area->vm_ops = &hwdep_vm_ops; + area->vm_flags = VM_READ | VM_RAND_READ | VM_DONTEXPAND; + area->vm_private_data = hwdep->private_data; + + return 0; +} + static const struct snd_hwdep_ops hwdep_ops = { .read = hwdep_read, .release = hwdep_release, .poll = hwdep_poll, .ioctl = hwdep_ioctl, .ioctl_compat = hwdep_compat_ioctl, + .mmap = hwdep_mmap, }; int snd_tscm_create_hwdep_device(struct snd_tscm *tscm) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index 23124fb..83f437e 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -314,6 +314,7 @@ error: int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) { unsigned int pcm_channels; + unsigned int size; int err; /* For out-stream. */ @@ -344,6 +345,15 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) if (err < 0) amdtp_stream_destroy(&tscm->rx_stream); + /* For control messages. */ + size = sizeof(struct snd_firewire_tascam_status); + tscm->status = snd_malloc_pages(size, GFP_KERNEL); + if (tscm->status == NULL) { + amdtp_stream_destroy(&tscm->tx_stream); + amdtp_stream_destroy(&tscm->rx_stream); + return -ENOMEM; + } + return 0; } @@ -363,11 +373,16 @@ void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) */ void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) { + unsigned int size; + amdtp_stream_destroy(&tscm->rx_stream); amdtp_stream_destroy(&tscm->tx_stream); fw_iso_resources_destroy(&tscm->rx_resources); fw_iso_resources_destroy(&tscm->tx_resources); + + size = sizeof(struct snd_firewire_tascam_status); + snd_free_pages(tscm->status, size); } int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 053a8bf..0340693 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -70,6 +70,9 @@ struct snd_tscm { int dev_lock_count; bool dev_lock_changed; wait_queue_head_t hwdep_wait; + + /* For control messages. */ + struct snd_firewire_tascam_status *status; }; #define TSCM_ADDR_BASE 0xffff00000000ull