summaryrefslogtreecommitdiff
path: root/sound/firewire/tascam/amdtp-tascam.c
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2018-11-23 07:13:05 +0300
committerTakashi Iwai <tiwai@suse.de>2018-11-23 17:31:12 +0300
commitd7167422433cdb61e58baee9c25543d0eba95c9d (patch)
treeeeb1851aa855cddd2d70148194eefb02c1b1be5e /sound/firewire/tascam/amdtp-tascam.c
parent90e8ac5c9d446124a5b43a6f135bf67e060c0c9d (diff)
downloadlinux-d7167422433cdb61e58baee9c25543d0eba95c9d.tar.xz
ALSA: firewire-tascam: queue events for change of control surface
Units of TASCAM FireWire series transfer image of states of the unit in tx isochronous packets. Demultiplexing of the states from the packets is done in software interrupt context regardless of any process context. In a view of userspace applications, it needs to have notification mechanism to catch change of the states. This commit implements a queue to store events for the notification. The image of states includes fluctuating data such as level of gain/volume for physical input/output and position of knobs. Therefore the events are queued corresponding to some control features only. Furthermore, the queued events are planned to be consumed by userspace applications via ALSA hwdep interface. This commit suppresses event queueing when no applications open the hwdep interface. However, the queue is maintained in an optimistic scenario, thus without any care against overrrun. This is reasonable because target events are useless just to handle PCM frames. It starts queueing when an usespace application opens hwdep interface, thus it's expected to read the queued events steadily. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/tascam/amdtp-tascam.c')
-rw-r--r--sound/firewire/tascam/amdtp-tascam.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c
index 516cb931fd5e..0e8088c9ada9 100644
--- a/sound/firewire/tascam/amdtp-tascam.c
+++ b/sound/firewire/tascam/amdtp-tascam.c
@@ -121,13 +121,45 @@ static void read_status_messages(struct amdtp_stream *s,
__be32 *buffer, unsigned int data_blocks)
{
struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream);
+ bool used = READ_ONCE(tscm->hwdep->used);
int i;
for (i = 0; i < data_blocks; i++) {
unsigned int index;
+ __be32 before;
+ __be32 after;
index = be32_to_cpu(buffer[0]) % SNDRV_FIREWIRE_TASCAM_STATE_COUNT;
- tscm->state[index] = buffer[s->data_block_quadlets - 1];
+ before = tscm->state[index];
+ after = buffer[s->data_block_quadlets - 1];
+
+ if (used && index > 4 && index < 16) {
+ __be32 mask;
+
+ if (index == 5)
+ mask = cpu_to_be32(~0x0000ffff);
+ else if (index == 6)
+ mask = cpu_to_be32(~0x0000ffff);
+ else if (index == 8)
+ mask = cpu_to_be32(~0x000f0f00);
+ else
+ mask = cpu_to_be32(~0x00000000);
+
+ if ((before ^ after) & mask) {
+ struct snd_firewire_tascam_change *entry =
+ &tscm->queue[tscm->push_pos];
+
+ spin_lock_irq(&tscm->lock);
+ entry->index = index;
+ entry->before = before;
+ entry->after = after;
+ if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT)
+ tscm->push_pos = 0;
+ spin_unlock_irq(&tscm->lock);
+ }
+ }
+
+ tscm->state[index] = after;
buffer += s->data_block_quadlets;
}
}