Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * motu-protocol-v3.c - a part of driver for MOTU FireWire series
0004  *
0005  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
0006  */
0007 
0008 #include <linux/delay.h>
0009 #include "motu.h"
0010 
0011 #define V3_CLOCK_STATUS_OFFSET      0x0b14
0012 #define  V3_FETCH_PCM_FRAMES        0x02000000
0013 #define  V3_CLOCK_RATE_MASK     0x0000ff00
0014 #define  V3_CLOCK_RATE_SHIFT        8
0015 #define  V3_CLOCK_SOURCE_MASK       0x000000ff
0016 #define   V3_CLOCK_SRC_INTERNAL     0x00
0017 #define   V3_CLOCK_SRC_WORD_ON_BNC  0x01
0018 #define   V3_CLOCK_SRC_SPH      0x02
0019 #define   V3_CLOCK_SRC_AESEBU_ON_XLR    0x08
0020 #define   V3_CLOCK_SRC_SPDIF_ON_COAX    0x10
0021 #define   V3_CLOCK_SRC_OPT_IFACE_A  0x18
0022 #define   V3_CLOCK_SRC_OPT_IFACE_B  0x19
0023 
0024 #define V3_OPT_IFACE_MODE_OFFSET    0x0c94
0025 #define  V3_ENABLE_OPT_IN_IFACE_A   0x00000001
0026 #define  V3_ENABLE_OPT_IN_IFACE_B   0x00000002
0027 #define  V3_ENABLE_OPT_OUT_IFACE_A  0x00000100
0028 #define  V3_ENABLE_OPT_OUT_IFACE_B  0x00000200
0029 #define  V3_NO_ADAT_OPT_IN_IFACE_A  0x00010000
0030 #define  V3_NO_ADAT_OPT_IN_IFACE_B  0x00100000
0031 #define  V3_NO_ADAT_OPT_OUT_IFACE_A 0x00040000
0032 #define  V3_NO_ADAT_OPT_OUT_IFACE_B 0x00400000
0033 
0034 #define V3_MSG_FLAG_CLK_CHANGED     0x00000002
0035 #define V3_CLK_WAIT_MSEC        4000
0036 
0037 int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
0038                     unsigned int *rate)
0039 {
0040     __be32 reg;
0041     u32 data;
0042     int err;
0043 
0044     err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, &reg,
0045                     sizeof(reg));
0046     if (err < 0)
0047         return err;
0048     data = be32_to_cpu(reg);
0049 
0050     data = (data & V3_CLOCK_RATE_MASK) >> V3_CLOCK_RATE_SHIFT;
0051     if (data >= ARRAY_SIZE(snd_motu_clock_rates))
0052         return -EIO;
0053 
0054     *rate = snd_motu_clock_rates[data];
0055 
0056     return 0;
0057 }
0058 
0059 int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
0060                     unsigned int rate)
0061 {
0062     __be32 reg;
0063     u32 data;
0064     bool need_to_wait;
0065     int i, err;
0066 
0067     for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
0068         if (snd_motu_clock_rates[i] == rate)
0069             break;
0070     }
0071     if (i == ARRAY_SIZE(snd_motu_clock_rates))
0072         return -EINVAL;
0073 
0074     err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, &reg,
0075                     sizeof(reg));
0076     if (err < 0)
0077         return err;
0078     data = be32_to_cpu(reg);
0079 
0080     data &= ~(V3_CLOCK_RATE_MASK | V3_FETCH_PCM_FRAMES);
0081     data |= i << V3_CLOCK_RATE_SHIFT;
0082 
0083     need_to_wait = data != be32_to_cpu(reg);
0084 
0085     reg = cpu_to_be32(data);
0086     err = snd_motu_transaction_write(motu, V3_CLOCK_STATUS_OFFSET, &reg,
0087                      sizeof(reg));
0088     if (err < 0)
0089         return err;
0090 
0091     if (need_to_wait) {
0092         int result;
0093 
0094         motu->msg = 0;
0095         result = wait_event_interruptible_timeout(motu->hwdep_wait,
0096                     motu->msg & V3_MSG_FLAG_CLK_CHANGED,
0097                     msecs_to_jiffies(V3_CLK_WAIT_MSEC));
0098         if (result < 0)
0099             return result;
0100         if (result == 0)
0101             return -ETIMEDOUT;
0102     }
0103 
0104     return 0;
0105 }
0106 
0107 int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
0108                       enum snd_motu_clock_source *src)
0109 {
0110     __be32 reg;
0111     u32 data;
0112     int err;
0113 
0114     err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, &reg,
0115                     sizeof(reg));
0116     if (err < 0)
0117         return err;
0118     data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK;
0119 
0120     switch (data) {
0121     case V3_CLOCK_SRC_INTERNAL:
0122         *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
0123         break;
0124     case V3_CLOCK_SRC_WORD_ON_BNC:
0125         *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
0126         break;
0127     case V3_CLOCK_SRC_SPH:
0128         *src = SND_MOTU_CLOCK_SOURCE_SPH;
0129         break;
0130     case V3_CLOCK_SRC_AESEBU_ON_XLR:
0131         *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
0132         break;
0133     case V3_CLOCK_SRC_SPDIF_ON_COAX:
0134         *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
0135         break;
0136     case V3_CLOCK_SRC_OPT_IFACE_A:
0137     case V3_CLOCK_SRC_OPT_IFACE_B:
0138     {
0139         __be32 reg;
0140         u32 options;
0141 
0142         err = snd_motu_transaction_read(motu,
0143                 V3_OPT_IFACE_MODE_OFFSET, &reg, sizeof(reg));
0144         if (err < 0)
0145             return err;
0146         options = be32_to_cpu(reg);
0147 
0148         if (data == V3_CLOCK_SRC_OPT_IFACE_A) {
0149             if (options & V3_NO_ADAT_OPT_IN_IFACE_A)
0150                 *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A;
0151             else
0152                 *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A;
0153         } else {
0154             if (options & V3_NO_ADAT_OPT_IN_IFACE_B)
0155                 *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B;
0156             else
0157                 *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B;
0158         }
0159         break;
0160     }
0161     default:
0162         *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
0163         break;
0164     }
0165 
0166     return 0;
0167 }
0168 
0169 int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
0170                           bool enable)
0171 {
0172     __be32 reg;
0173     u32 data;
0174     int err;
0175 
0176     err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, &reg,
0177                     sizeof(reg));
0178     if (err < 0)
0179         return 0;
0180     data = be32_to_cpu(reg);
0181 
0182     if (enable)
0183         data |= V3_FETCH_PCM_FRAMES;
0184     else
0185         data &= ~V3_FETCH_PCM_FRAMES;
0186 
0187     reg = cpu_to_be32(data);
0188     return snd_motu_transaction_write(motu, V3_CLOCK_STATUS_OFFSET, &reg,
0189                       sizeof(reg));
0190 }
0191 
0192 static int detect_packet_formats_with_opt_ifaces(struct snd_motu *motu, u32 data)
0193 {
0194     if (data & V3_ENABLE_OPT_IN_IFACE_A) {
0195         if (data & V3_NO_ADAT_OPT_IN_IFACE_A) {
0196             motu->tx_packet_formats.pcm_chunks[0] += 4;
0197             motu->tx_packet_formats.pcm_chunks[1] += 4;
0198         } else {
0199             motu->tx_packet_formats.pcm_chunks[0] += 8;
0200             motu->tx_packet_formats.pcm_chunks[1] += 4;
0201         }
0202     }
0203 
0204     if (data & V3_ENABLE_OPT_IN_IFACE_B) {
0205         if (data & V3_NO_ADAT_OPT_IN_IFACE_B) {
0206             motu->tx_packet_formats.pcm_chunks[0] += 4;
0207             motu->tx_packet_formats.pcm_chunks[1] += 4;
0208         } else {
0209             motu->tx_packet_formats.pcm_chunks[0] += 8;
0210             motu->tx_packet_formats.pcm_chunks[1] += 4;
0211         }
0212     }
0213 
0214     if (data & V3_ENABLE_OPT_OUT_IFACE_A) {
0215         if (data & V3_NO_ADAT_OPT_OUT_IFACE_A) {
0216             motu->rx_packet_formats.pcm_chunks[0] += 4;
0217             motu->rx_packet_formats.pcm_chunks[1] += 4;
0218         } else {
0219             motu->rx_packet_formats.pcm_chunks[0] += 8;
0220             motu->rx_packet_formats.pcm_chunks[1] += 4;
0221         }
0222     }
0223 
0224     if (data & V3_ENABLE_OPT_OUT_IFACE_B) {
0225         if (data & V3_NO_ADAT_OPT_OUT_IFACE_B) {
0226             motu->rx_packet_formats.pcm_chunks[0] += 4;
0227             motu->rx_packet_formats.pcm_chunks[1] += 4;
0228         } else {
0229             motu->rx_packet_formats.pcm_chunks[0] += 8;
0230             motu->rx_packet_formats.pcm_chunks[1] += 4;
0231         }
0232     }
0233 
0234     return 0;
0235 }
0236 
0237 int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu)
0238 {
0239     __be32 reg;
0240     u32 data;
0241     int err;
0242 
0243     motu->tx_packet_formats.pcm_byte_offset = 10;
0244     motu->rx_packet_formats.pcm_byte_offset = 10;
0245 
0246     motu->tx_packet_formats.msg_chunks = 2;
0247     motu->rx_packet_formats.msg_chunks = 2;
0248 
0249     err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, &reg,
0250                     sizeof(reg));
0251     if (err < 0)
0252         return err;
0253     data = be32_to_cpu(reg);
0254 
0255     memcpy(motu->tx_packet_formats.pcm_chunks,
0256            motu->spec->tx_fixed_pcm_chunks,
0257            sizeof(motu->tx_packet_formats.pcm_chunks));
0258     memcpy(motu->rx_packet_formats.pcm_chunks,
0259            motu->spec->rx_fixed_pcm_chunks,
0260            sizeof(motu->rx_packet_formats.pcm_chunks));
0261 
0262     if (motu->spec == &snd_motu_spec_828mk3_fw ||
0263         motu->spec == &snd_motu_spec_828mk3_hybrid ||
0264         motu->spec == &snd_motu_spec_traveler_mk3 ||
0265         motu->spec == &snd_motu_spec_track16)
0266         return detect_packet_formats_with_opt_ifaces(motu, data);
0267     else
0268         return 0;
0269 }
0270 
0271 const struct snd_motu_spec snd_motu_spec_828mk3_fw = {
0272     .name = "828mk3",
0273     .protocol_version = SND_MOTU_PROTOCOL_V3,
0274     .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0275          SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0276          SND_MOTU_SPEC_COMMAND_DSP,
0277     .tx_fixed_pcm_chunks = {18, 18, 14},
0278     .rx_fixed_pcm_chunks = {14, 14, 10},
0279 };
0280 
0281 const struct snd_motu_spec snd_motu_spec_828mk3_hybrid = {
0282     .name = "828mk3",
0283     .protocol_version = SND_MOTU_PROTOCOL_V3,
0284     .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0285          SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0286          SND_MOTU_SPEC_COMMAND_DSP,
0287     .tx_fixed_pcm_chunks = {18, 18, 14},
0288     .rx_fixed_pcm_chunks = {14, 14, 14},    // Additional 4 dummy chunks at higher rate.
0289 };
0290 
0291 const struct snd_motu_spec snd_motu_spec_traveler_mk3 = {
0292     .name = "TravelerMk3",
0293     .protocol_version = SND_MOTU_PROTOCOL_V3,
0294     .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0295          SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0296          SND_MOTU_SPEC_COMMAND_DSP,
0297     .tx_fixed_pcm_chunks = {18, 14, 10},
0298     .rx_fixed_pcm_chunks = {14, 14, 10},
0299 };
0300 
0301 const struct snd_motu_spec snd_motu_spec_ultralite_mk3 = {
0302     .name = "UltraLiteMk3",
0303     .protocol_version = SND_MOTU_PROTOCOL_V3,
0304     .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0305          SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0306          SND_MOTU_SPEC_COMMAND_DSP,
0307     .tx_fixed_pcm_chunks = {18, 14, 10},
0308     .rx_fixed_pcm_chunks = {14, 14, 14},
0309 };
0310 
0311 const struct snd_motu_spec snd_motu_spec_audio_express = {
0312     .name = "AudioExpress",
0313     .protocol_version = SND_MOTU_PROTOCOL_V3,
0314     .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
0315          SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0316          SND_MOTU_SPEC_REGISTER_DSP,
0317     .tx_fixed_pcm_chunks = {10, 10, 0},
0318     .rx_fixed_pcm_chunks = {10, 10, 0},
0319 };
0320 
0321 const struct snd_motu_spec snd_motu_spec_track16 = {
0322     .name = "Track16",
0323     .protocol_version = SND_MOTU_PROTOCOL_V3,
0324     .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q |
0325          SND_MOTU_SPEC_TX_MIDI_3RD_Q |
0326          SND_MOTU_SPEC_COMMAND_DSP,
0327     .tx_fixed_pcm_chunks = {14, 14, 14},
0328     .rx_fixed_pcm_chunks = {6, 6, 6},
0329 };
0330 
0331 const struct snd_motu_spec snd_motu_spec_4pre = {
0332     .name = "4pre",
0333     .protocol_version = SND_MOTU_PROTOCOL_V3,
0334     .flags = SND_MOTU_SPEC_REGISTER_DSP,
0335     .tx_fixed_pcm_chunks = {10, 10, 0},
0336     .rx_fixed_pcm_chunks = {10, 10, 0},
0337 };