162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * motu-protocol-v3.c - a part of driver for MOTU FireWire series 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include "motu.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define V3_CLOCK_STATUS_OFFSET 0x0b14 1262306a36Sopenharmony_ci#define V3_FETCH_PCM_FRAMES 0x02000000 1362306a36Sopenharmony_ci#define V3_CLOCK_RATE_MASK 0x0000ff00 1462306a36Sopenharmony_ci#define V3_CLOCK_RATE_SHIFT 8 1562306a36Sopenharmony_ci#define V3_CLOCK_SOURCE_MASK 0x000000ff 1662306a36Sopenharmony_ci#define V3_CLOCK_SRC_INTERNAL 0x00 1762306a36Sopenharmony_ci#define V3_CLOCK_SRC_WORD_ON_BNC 0x01 1862306a36Sopenharmony_ci#define V3_CLOCK_SRC_SPH 0x02 1962306a36Sopenharmony_ci#define V3_CLOCK_SRC_AESEBU_ON_XLR 0x08 2062306a36Sopenharmony_ci#define V3_CLOCK_SRC_SPDIF_ON_COAX 0x10 2162306a36Sopenharmony_ci#define V3_CLOCK_SRC_OPT_IFACE_A 0x18 2262306a36Sopenharmony_ci#define V3_CLOCK_SRC_OPT_IFACE_B 0x19 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define V3_OPT_IFACE_MODE_OFFSET 0x0c94 2562306a36Sopenharmony_ci#define V3_ENABLE_OPT_IN_IFACE_A 0x00000001 2662306a36Sopenharmony_ci#define V3_ENABLE_OPT_IN_IFACE_B 0x00000002 2762306a36Sopenharmony_ci#define V3_ENABLE_OPT_OUT_IFACE_A 0x00000100 2862306a36Sopenharmony_ci#define V3_ENABLE_OPT_OUT_IFACE_B 0x00000200 2962306a36Sopenharmony_ci#define V3_NO_ADAT_OPT_IN_IFACE_A 0x00010000 3062306a36Sopenharmony_ci#define V3_NO_ADAT_OPT_IN_IFACE_B 0x00100000 3162306a36Sopenharmony_ci#define V3_NO_ADAT_OPT_OUT_IFACE_A 0x00040000 3262306a36Sopenharmony_ci#define V3_NO_ADAT_OPT_OUT_IFACE_B 0x00400000 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define V3_MSG_FLAG_CLK_CHANGED 0x00000002 3562306a36Sopenharmony_ci#define V3_CLK_WAIT_MSEC 4000 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciint snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu, 3862306a36Sopenharmony_ci unsigned int *rate) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci __be32 reg; 4162306a36Sopenharmony_ci u32 data; 4262306a36Sopenharmony_ci int err; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, 4562306a36Sopenharmony_ci sizeof(reg)); 4662306a36Sopenharmony_ci if (err < 0) 4762306a36Sopenharmony_ci return err; 4862306a36Sopenharmony_ci data = be32_to_cpu(reg); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci data = (data & V3_CLOCK_RATE_MASK) >> V3_CLOCK_RATE_SHIFT; 5162306a36Sopenharmony_ci if (data >= ARRAY_SIZE(snd_motu_clock_rates)) 5262306a36Sopenharmony_ci return -EIO; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci *rate = snd_motu_clock_rates[data]; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciint snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu, 6062306a36Sopenharmony_ci unsigned int rate) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci __be32 reg; 6362306a36Sopenharmony_ci u32 data; 6462306a36Sopenharmony_ci bool need_to_wait; 6562306a36Sopenharmony_ci int i, err; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) { 6862306a36Sopenharmony_ci if (snd_motu_clock_rates[i] == rate) 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci if (i == ARRAY_SIZE(snd_motu_clock_rates)) 7262306a36Sopenharmony_ci return -EINVAL; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, 7562306a36Sopenharmony_ci sizeof(reg)); 7662306a36Sopenharmony_ci if (err < 0) 7762306a36Sopenharmony_ci return err; 7862306a36Sopenharmony_ci data = be32_to_cpu(reg); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci data &= ~(V3_CLOCK_RATE_MASK | V3_FETCH_PCM_FRAMES); 8162306a36Sopenharmony_ci data |= i << V3_CLOCK_RATE_SHIFT; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci need_to_wait = data != be32_to_cpu(reg); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci reg = cpu_to_be32(data); 8662306a36Sopenharmony_ci err = snd_motu_transaction_write(motu, V3_CLOCK_STATUS_OFFSET, ®, 8762306a36Sopenharmony_ci sizeof(reg)); 8862306a36Sopenharmony_ci if (err < 0) 8962306a36Sopenharmony_ci return err; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (need_to_wait) { 9262306a36Sopenharmony_ci int result; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci motu->msg = 0; 9562306a36Sopenharmony_ci result = wait_event_interruptible_timeout(motu->hwdep_wait, 9662306a36Sopenharmony_ci motu->msg & V3_MSG_FLAG_CLK_CHANGED, 9762306a36Sopenharmony_ci msecs_to_jiffies(V3_CLK_WAIT_MSEC)); 9862306a36Sopenharmony_ci if (result < 0) 9962306a36Sopenharmony_ci return result; 10062306a36Sopenharmony_ci if (result == 0) 10162306a36Sopenharmony_ci return -ETIMEDOUT; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciint snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu, 10862306a36Sopenharmony_ci enum snd_motu_clock_source *src) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci __be32 reg; 11162306a36Sopenharmony_ci u32 data; 11262306a36Sopenharmony_ci int err; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, 11562306a36Sopenharmony_ci sizeof(reg)); 11662306a36Sopenharmony_ci if (err < 0) 11762306a36Sopenharmony_ci return err; 11862306a36Sopenharmony_ci data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci switch (data) { 12162306a36Sopenharmony_ci case V3_CLOCK_SRC_INTERNAL: 12262306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; 12362306a36Sopenharmony_ci break; 12462306a36Sopenharmony_ci case V3_CLOCK_SRC_WORD_ON_BNC: 12562306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; 12662306a36Sopenharmony_ci break; 12762306a36Sopenharmony_ci case V3_CLOCK_SRC_SPH: 12862306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_SPH; 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci case V3_CLOCK_SRC_AESEBU_ON_XLR: 13162306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR; 13262306a36Sopenharmony_ci break; 13362306a36Sopenharmony_ci case V3_CLOCK_SRC_SPDIF_ON_COAX: 13462306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci case V3_CLOCK_SRC_OPT_IFACE_A: 13762306a36Sopenharmony_ci case V3_CLOCK_SRC_OPT_IFACE_B: 13862306a36Sopenharmony_ci { 13962306a36Sopenharmony_ci __be32 reg; 14062306a36Sopenharmony_ci u32 options; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci err = snd_motu_transaction_read(motu, 14362306a36Sopenharmony_ci V3_OPT_IFACE_MODE_OFFSET, ®, sizeof(reg)); 14462306a36Sopenharmony_ci if (err < 0) 14562306a36Sopenharmony_ci return err; 14662306a36Sopenharmony_ci options = be32_to_cpu(reg); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (data == V3_CLOCK_SRC_OPT_IFACE_A) { 14962306a36Sopenharmony_ci if (options & V3_NO_ADAT_OPT_IN_IFACE_A) 15062306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A; 15162306a36Sopenharmony_ci else 15262306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A; 15362306a36Sopenharmony_ci } else { 15462306a36Sopenharmony_ci if (options & V3_NO_ADAT_OPT_IN_IFACE_B) 15562306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B; 15662306a36Sopenharmony_ci else 15762306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci default: 16262306a36Sopenharmony_ci *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; 16362306a36Sopenharmony_ci break; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ciint snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu, 17062306a36Sopenharmony_ci bool enable) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci __be32 reg; 17362306a36Sopenharmony_ci u32 data; 17462306a36Sopenharmony_ci int err; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, 17762306a36Sopenharmony_ci sizeof(reg)); 17862306a36Sopenharmony_ci if (err < 0) 17962306a36Sopenharmony_ci return 0; 18062306a36Sopenharmony_ci data = be32_to_cpu(reg); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (enable) 18362306a36Sopenharmony_ci data |= V3_FETCH_PCM_FRAMES; 18462306a36Sopenharmony_ci else 18562306a36Sopenharmony_ci data &= ~V3_FETCH_PCM_FRAMES; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci reg = cpu_to_be32(data); 18862306a36Sopenharmony_ci return snd_motu_transaction_write(motu, V3_CLOCK_STATUS_OFFSET, ®, 18962306a36Sopenharmony_ci sizeof(reg)); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int detect_packet_formats_with_opt_ifaces(struct snd_motu *motu, u32 data) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci if (data & V3_ENABLE_OPT_IN_IFACE_A) { 19562306a36Sopenharmony_ci if (data & V3_NO_ADAT_OPT_IN_IFACE_A) { 19662306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[0] += 4; 19762306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[1] += 4; 19862306a36Sopenharmony_ci } else { 19962306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[0] += 8; 20062306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[1] += 4; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (data & V3_ENABLE_OPT_IN_IFACE_B) { 20562306a36Sopenharmony_ci if (data & V3_NO_ADAT_OPT_IN_IFACE_B) { 20662306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[0] += 4; 20762306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[1] += 4; 20862306a36Sopenharmony_ci } else { 20962306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[0] += 8; 21062306a36Sopenharmony_ci motu->tx_packet_formats.pcm_chunks[1] += 4; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (data & V3_ENABLE_OPT_OUT_IFACE_A) { 21562306a36Sopenharmony_ci if (data & V3_NO_ADAT_OPT_OUT_IFACE_A) { 21662306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[0] += 4; 21762306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[1] += 4; 21862306a36Sopenharmony_ci } else { 21962306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[0] += 8; 22062306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[1] += 4; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (data & V3_ENABLE_OPT_OUT_IFACE_B) { 22562306a36Sopenharmony_ci if (data & V3_NO_ADAT_OPT_OUT_IFACE_B) { 22662306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[0] += 4; 22762306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[1] += 4; 22862306a36Sopenharmony_ci } else { 22962306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[0] += 8; 23062306a36Sopenharmony_ci motu->rx_packet_formats.pcm_chunks[1] += 4; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return 0; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ciint snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci __be32 reg; 24062306a36Sopenharmony_ci u32 data; 24162306a36Sopenharmony_ci int err; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci motu->tx_packet_formats.pcm_byte_offset = 10; 24462306a36Sopenharmony_ci motu->rx_packet_formats.pcm_byte_offset = 10; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci motu->tx_packet_formats.msg_chunks = 2; 24762306a36Sopenharmony_ci motu->rx_packet_formats.msg_chunks = 2; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, ®, 25062306a36Sopenharmony_ci sizeof(reg)); 25162306a36Sopenharmony_ci if (err < 0) 25262306a36Sopenharmony_ci return err; 25362306a36Sopenharmony_ci data = be32_to_cpu(reg); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci memcpy(motu->tx_packet_formats.pcm_chunks, 25662306a36Sopenharmony_ci motu->spec->tx_fixed_pcm_chunks, 25762306a36Sopenharmony_ci sizeof(motu->tx_packet_formats.pcm_chunks)); 25862306a36Sopenharmony_ci memcpy(motu->rx_packet_formats.pcm_chunks, 25962306a36Sopenharmony_ci motu->spec->rx_fixed_pcm_chunks, 26062306a36Sopenharmony_ci sizeof(motu->rx_packet_formats.pcm_chunks)); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (motu->spec == &snd_motu_spec_828mk3_fw || 26362306a36Sopenharmony_ci motu->spec == &snd_motu_spec_828mk3_hybrid || 26462306a36Sopenharmony_ci motu->spec == &snd_motu_spec_traveler_mk3 || 26562306a36Sopenharmony_ci motu->spec == &snd_motu_spec_track16) 26662306a36Sopenharmony_ci return detect_packet_formats_with_opt_ifaces(motu, data); 26762306a36Sopenharmony_ci else 26862306a36Sopenharmony_ci return 0; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_828mk3_fw = { 27262306a36Sopenharmony_ci .name = "828mk3", 27362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 27462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | 27562306a36Sopenharmony_ci SND_MOTU_SPEC_TX_MIDI_3RD_Q | 27662306a36Sopenharmony_ci SND_MOTU_SPEC_COMMAND_DSP, 27762306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {18, 18, 14}, 27862306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {14, 14, 10}, 27962306a36Sopenharmony_ci}; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_828mk3_hybrid = { 28262306a36Sopenharmony_ci .name = "828mk3", 28362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 28462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | 28562306a36Sopenharmony_ci SND_MOTU_SPEC_TX_MIDI_3RD_Q | 28662306a36Sopenharmony_ci SND_MOTU_SPEC_COMMAND_DSP, 28762306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {18, 18, 14}, 28862306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {14, 14, 14}, // Additional 4 dummy chunks at higher rate. 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_traveler_mk3 = { 29262306a36Sopenharmony_ci .name = "TravelerMk3", 29362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 29462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | 29562306a36Sopenharmony_ci SND_MOTU_SPEC_TX_MIDI_3RD_Q | 29662306a36Sopenharmony_ci SND_MOTU_SPEC_COMMAND_DSP, 29762306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {18, 14, 10}, 29862306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {14, 14, 10}, 29962306a36Sopenharmony_ci}; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_ultralite_mk3 = { 30262306a36Sopenharmony_ci .name = "UltraLiteMk3", 30362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 30462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | 30562306a36Sopenharmony_ci SND_MOTU_SPEC_TX_MIDI_3RD_Q | 30662306a36Sopenharmony_ci SND_MOTU_SPEC_COMMAND_DSP, 30762306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {18, 14, 10}, 30862306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {14, 14, 14}, 30962306a36Sopenharmony_ci}; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_audio_express = { 31262306a36Sopenharmony_ci .name = "AudioExpress", 31362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 31462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | 31562306a36Sopenharmony_ci SND_MOTU_SPEC_TX_MIDI_3RD_Q | 31662306a36Sopenharmony_ci SND_MOTU_SPEC_REGISTER_DSP, 31762306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {10, 10, 0}, 31862306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {10, 10, 0}, 31962306a36Sopenharmony_ci}; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_track16 = { 32262306a36Sopenharmony_ci .name = "Track16", 32362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 32462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | 32562306a36Sopenharmony_ci SND_MOTU_SPEC_TX_MIDI_3RD_Q | 32662306a36Sopenharmony_ci SND_MOTU_SPEC_COMMAND_DSP, 32762306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {14, 14, 14}, 32862306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {6, 6, 6}, 32962306a36Sopenharmony_ci}; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ciconst struct snd_motu_spec snd_motu_spec_4pre = { 33262306a36Sopenharmony_ci .name = "4pre", 33362306a36Sopenharmony_ci .protocol_version = SND_MOTU_PROTOCOL_V3, 33462306a36Sopenharmony_ci .flags = SND_MOTU_SPEC_REGISTER_DSP, 33562306a36Sopenharmony_ci .tx_fixed_pcm_chunks = {10, 10, 0}, 33662306a36Sopenharmony_ci .rx_fixed_pcm_chunks = {10, 10, 0}, 33762306a36Sopenharmony_ci}; 338