^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * motu-protocol-v2.c - a part of driver for MOTU FireWire series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "motu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define V2_CLOCK_STATUS_OFFSET 0x0b14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define V2_CLOCK_RATE_MASK 0x00000038
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define V2_CLOCK_RATE_SHIFT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define V2_CLOCK_SRC_MASK 0x00000007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define V2_CLOCK_SRC_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define V2_CLOCK_FETCH_ENABLE 0x02000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define V2_CLOCK_MODEL_SPECIFIC 0x04000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define V2_IN_OUT_CONF_OFFSET 0x0c04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define V2_OPT_OUT_IFACE_MASK 0x00000c00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define V2_OPT_OUT_IFACE_SHIFT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define V2_OPT_IN_IFACE_MASK 0x00000300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define V2_OPT_IN_IFACE_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define V2_OPT_IFACE_MODE_NONE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define V2_OPT_IFACE_MODE_ADAT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define V2_OPT_IFACE_MODE_SPDIF 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int get_clock_rate(u32 data, unsigned int *rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int index = (data & V2_CLOCK_RATE_MASK) >> V2_CLOCK_RATE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (index >= ARRAY_SIZE(snd_motu_clock_rates))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *rate = snd_motu_clock_rates[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned int *rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return get_clock_rate(be32_to_cpu(reg), rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (snd_motu_clock_rates[i] == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (i == ARRAY_SIZE(snd_motu_clock_rates))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) data &= ~V2_CLOCK_RATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) data |= i << V2_CLOCK_RATE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int detect_clock_source_optical_model(struct snd_motu *motu, u32 data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) enum snd_motu_clock_source *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) switch (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) // To check the configuration of optical interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == V2_OPT_IFACE_MODE_SPDIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *src = SND_MOTU_CLOCK_SOURCE_SPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int v2_detect_clock_source(struct snd_motu *motu, u32 data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) enum snd_motu_clock_source *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) switch (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *src = SND_MOTU_CLOCK_SOURCE_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *src = SND_MOTU_CLOCK_SOURCE_SPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int get_clock_source(struct snd_motu *motu, u32 data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) enum snd_motu_clock_source *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) data &= V2_CLOCK_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (motu->spec == &snd_motu_spec_828mk2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) motu->spec == &snd_motu_spec_traveler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return detect_clock_source_optical_model(motu, data, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return v2_detect_clock_source(motu, data, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) enum snd_motu_clock_source *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return get_clock_source(motu, be32_to_cpu(reg), src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) // Expected for Traveler and 896HD, which implements Altera Cyclone EP1C3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int switch_fetching_mode_cyclone(struct snd_motu *motu, u32 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *data |= V2_CLOCK_MODEL_SPECIFIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) // For UltraLite and 8pre, which implements Xilinx Spartan XC3S200.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int switch_fetching_mode_spartan(struct snd_motu *motu, u32 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) enum snd_motu_clock_source src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) err = get_clock_source(motu, *data, &src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) err = get_clock_rate(*data, &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (src == SND_MOTU_CLOCK_SOURCE_SPH && rate > 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *data |= V2_CLOCK_MODEL_SPECIFIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (motu->spec == &snd_motu_spec_828mk2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) // 828mkII implements Altera ACEX 1K EP1K30. Nothing to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) data &= ~(V2_CLOCK_FETCH_ENABLE | V2_CLOCK_MODEL_SPECIFIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) data |= V2_CLOCK_FETCH_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (motu->spec == &snd_motu_spec_traveler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) err = switch_fetching_mode_cyclone(motu, &data, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) err = switch_fetching_mode_spartan(motu, &data, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static int detect_packet_formats_828mk2(struct snd_motu *motu, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) V2_OPT_IFACE_MODE_ADAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) motu->tx_packet_formats.pcm_chunks[0] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) motu->tx_packet_formats.pcm_chunks[1] += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) V2_OPT_IFACE_MODE_ADAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) motu->rx_packet_formats.pcm_chunks[0] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) motu->rx_packet_formats.pcm_chunks[1] += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int detect_packet_formats_traveler(struct snd_motu *motu, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) V2_OPT_IFACE_MODE_ADAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) motu->tx_packet_formats.pcm_chunks[0] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) motu->tx_packet_formats.pcm_chunks[1] += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) V2_OPT_IFACE_MODE_ADAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) motu->rx_packet_formats.pcm_chunks[0] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) motu->rx_packet_formats.pcm_chunks[1] += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int detect_packet_formats_8pre(struct snd_motu *motu, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) V2_OPT_IFACE_MODE_ADAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) motu->tx_packet_formats.pcm_chunks[0] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) motu->tx_packet_formats.pcm_chunks[1] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) V2_OPT_IFACE_MODE_ADAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) motu->rx_packet_formats.pcm_chunks[0] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) motu->rx_packet_formats.pcm_chunks[1] += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) motu->tx_packet_formats.pcm_byte_offset = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) motu->rx_packet_formats.pcm_byte_offset = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) motu->tx_packet_formats.msg_chunks = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) motu->rx_packet_formats.msg_chunks = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) memcpy(motu->tx_packet_formats.pcm_chunks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) motu->spec->tx_fixed_pcm_chunks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) sizeof(motu->tx_packet_formats.pcm_chunks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) memcpy(motu->rx_packet_formats.pcm_chunks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) motu->spec->rx_fixed_pcm_chunks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) sizeof(motu->rx_packet_formats.pcm_chunks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (motu->spec == &snd_motu_spec_828mk2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return detect_packet_formats_828mk2(motu, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) else if (motu->spec == &snd_motu_spec_traveler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return detect_packet_formats_traveler(motu, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) else if (motu->spec == &snd_motu_spec_8pre)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return detect_packet_formats_8pre(motu, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) const struct snd_motu_spec snd_motu_spec_828mk2 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .name = "828mk2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .protocol_version = SND_MOTU_PROTOCOL_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) SND_MOTU_SPEC_TX_MIDI_2ND_Q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .tx_fixed_pcm_chunks = {14, 14, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .rx_fixed_pcm_chunks = {14, 14, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) const struct snd_motu_spec snd_motu_spec_traveler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .name = "Traveler",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .protocol_version = SND_MOTU_PROTOCOL_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) SND_MOTU_SPEC_TX_MIDI_2ND_Q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .tx_fixed_pcm_chunks = {14, 14, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .rx_fixed_pcm_chunks = {14, 14, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) const struct snd_motu_spec snd_motu_spec_ultralite = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .name = "UltraLite",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .protocol_version = SND_MOTU_PROTOCOL_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) SND_MOTU_SPEC_TX_MIDI_2ND_Q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .tx_fixed_pcm_chunks = {14, 14, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .rx_fixed_pcm_chunks = {14, 14, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) const struct snd_motu_spec snd_motu_spec_8pre = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) .name = "8pre",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) .protocol_version = SND_MOTU_PROTOCOL_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) SND_MOTU_SPEC_TX_MIDI_2ND_Q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) // Two dummy chunks always in the end of data block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .tx_fixed_pcm_chunks = {10, 10, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .rx_fixed_pcm_chunks = {6, 6, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) };