]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - sound/firewire/fireface/ff-transaction.c
ALSA: fireface: share register for async transaction of MIDI messages
[linux.git] / sound / firewire / fireface / ff-transaction.c
index 332b29f8ed754da9c3a9d4c38807fe30935b2a18..fa0bc956696fee9cb0bcc0d541dfc2b4757918af 100644 (file)
@@ -8,6 +8,72 @@
 
 #include "ff.h"
 
+#define SND_FF_REG_MIDI_RX_PORT_0      0x000080180000ull
+#define SND_FF_REG_MIDI_RX_PORT_1      0x000080190000ull
+
+int snd_ff_transaction_get_clock(struct snd_ff *ff, unsigned int *rate,
+                                enum snd_ff_clock_src *src)
+{
+       __le32 reg;
+       u32 data;
+       int err;
+
+       err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
+                                SND_FF_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
+       if (err < 0)
+               return err;
+       data = le32_to_cpu(reg);
+
+       /* Calculate sampling rate. */
+       switch ((data >> 1) & 0x03) {
+       case 0x01:
+               *rate = 32000;
+               break;
+       case 0x00:
+               *rate = 44100;
+               break;
+       case 0x03:
+               *rate = 48000;
+               break;
+       case 0x02:
+       default:
+               return -EIO;
+       }
+
+       if (data & 0x08)
+               *rate *= 2;
+       else if (data & 0x10)
+               *rate *= 4;
+
+       /* Calculate source of clock. */
+       if (data & 0x01) {
+               *src = SND_FF_CLOCK_SRC_INTERNAL;
+       } else {
+               /* TODO: 0x02, 0x06, 0x07? */
+               switch ((data >> 10) & 0x07) {
+               case 0x00:
+                       *src = SND_FF_CLOCK_SRC_ADAT1;
+                       break;
+               case 0x01:
+                       *src = SND_FF_CLOCK_SRC_ADAT2;
+                       break;
+               case 0x03:
+                       *src = SND_FF_CLOCK_SRC_SPDIF;
+                       break;
+               case 0x04:
+                       *src = SND_FF_CLOCK_SRC_WORD;
+                       break;
+               case 0x05:
+                       *src = SND_FF_CLOCK_SRC_LTC;
+                       break;
+               default:
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+
 static void finish_transmit_midi_msg(struct snd_ff *ff, unsigned int port,
                                     int rcode)
 {
@@ -90,10 +156,10 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
                fill_midi_buf(ff, port, i, buf[i]);
 
        if (port == 0) {
-               addr = ff->spec->protocol->midi_rx_port_0_reg;
+               addr = SND_FF_REG_MIDI_RX_PORT_0;
                callback = finish_transmit_midi0_msg;
        } else {
-               addr = ff->spec->protocol->midi_rx_port_1_reg;
+               addr = SND_FF_REG_MIDI_RX_PORT_1;
                callback = finish_transmit_midi1_msg;
        }