Path: blob/master/sound/firewire/motu/motu-protocol-v1.c
26424 views
// SPDX-License-Identifier: GPL-2.0-only1// motu-protocol-v1.c - a part of driver for MOTU FireWire series2//3// Copyright (c) 2021 Takashi Sakamoto <[email protected]>45#include "motu.h"67#include <linux/delay.h>89// Status register for MOTU 828 (0x'ffff'f000'0b00).10//11// 0xffff0000: ISOC_COMM_CONTROL_MASK in motu-stream.c.12// 0x00008000: mode of optical input interface.13// 0x00008000: for S/PDIF signal.14// 0x00000000: disabled or for ADAT signal.15// 0x00004000: mode of optical output interface.16// 0x00004000: for S/PDIF signal.17// 0x00000000: disabled or for ADAT signal.18// 0x00003f00: monitor input mode.19// 0x00000800: analog-1/220// 0x00001a00: analog-3/421// 0x00002c00: analog-5/622// 0x00003e00: analog-7/823// 0x00000000: analog-124// 0x00000900: analog-225// 0x00001200: analog-326// 0x00001b00: analog-427// 0x00002400: analog-528// 0x00002d00: analog-629// 0x00003600: analog-730// 0x00003f00: analog-831// 0x00000080: enable stream input.32// 0x00000040: disable monitor input.33// 0x00000008: enable main out.34// 0x00000004: rate of sampling clock.35// 0x00000004: 48.0 kHz36// 0x00000000: 44.1 kHz37// 0x00000023: source of sampling clock.38// 0x00000003: source packet header (SPH)39// 0x00000002: S/PDIF on optical/coaxial interface.40// 0x00000021: ADAT on optical interface41// 0x00000001: ADAT on Dsub 9pin42// 0x00000000: internal4344#define CLK_828_STATUS_OFFSET 0x0b0045#define CLK_828_STATUS_MASK 0x0000ffff46#define CLK_828_STATUS_FLAG_OPT_IN_IFACE_IS_SPDIF 0x0000800047#define CLK_828_STATUS_FLAG_OPT_OUT_IFACE_IS_SPDIF 0x0000400048#define CLK_828_STATUS_FLAG_FETCH_PCM_FRAMES 0x0000008049#define CLK_828_STATUS_FLAG_ENABLE_OUTPUT 0x0000000850#define CLK_828_STATUS_FLAG_RATE_48000 0x0000000451#define CLK_828_STATUS_MASK_SRC 0x0000002352#define CLK_828_STATUS_FLAG_SRC_ADAT_ON_OPT 0x0000002153#define CLK_828_STATUS_FLAG_SRC_SPH 0x0000000354#define CLK_828_STATUS_FLAG_SRC_SPDIF 0x0000000255#define CLK_828_STATUS_FLAG_SRC_ADAT_ON_DSUB 0x0000000156#define CLK_828_STATUS_FLAG_SRC_INTERNAL 0x000000005758// Status register for MOTU 896 (0x'ffff'f000'0b14).59//60// 0xf0000000: enable physical and stream input to DAC.61// 0x80000000: disable62// 0x40000000: disable63// 0x20000000: enable (prior to the other bits)64// 0x10000000: disable65// 0x00000000: disable66// 0x08000000: speed of word clock signal output on BNC interface.67// 0x00000000: force to low rate (44.1/48.0 kHz).68// 0x08000000: follow to system clock.69// 0x04000000: something relevant to clock.70// 0x03000000: enable output.71// 0x02000000: enabled irreversibly once standing unless the device voluntarily disables it.72// 0x01000000: enabled irreversibly once standing unless the device voluntarily disables it.73// 0x00ffff00: monitor input mode.74// 0x00000000: disabled75// 0x00004800: analog-1/276// 0x00005a00: analog-3/477// 0x00006c00: analog-5/678// 0x00007e00: analog-7/879// 0x00104800: AES/EBU-1/280// 0x00004000: analog-181// 0x00004900: analog-282// 0x00005200: analog-383// 0x00005b00: analog-484// 0x00006400: analog-585// 0x00006d00: analog-686// 0x00007600: analog-787// 0x00007f00: analog-888// 0x00104000: AES/EBU-189// 0x00104900: AES/EBU-290// 0x00000060: sample rate conversion for AES/EBU input/output.91// 0x00000000: None92// 0x00000020: input signal is converted to system rate93// 0x00000040: output is slave to input, ignoring system rate94// 0x00000060: output is double rate than system rate95// 0x00000018: nominal rate of sampling clock.96// 0x00000000: 44.1 kHz97// 0x00000008: 48.0 kHz98// 0x00000010: 88.2 kHz99// 0x00000018: 96.0 kHz100// 0x00000007: source of sampling clock.101// 0x00000000: internal102// 0x00000001: ADAT on optical interface103// 0x00000002: AES/EBU on XLR104// 0x00000003: source packet header (SPH)105// 0x00000004: word clock on BNC106// 0x00000005: ADAT on Dsub 9pin107108#define CLK_896_STATUS_OFFSET 0x0b14109#define CLK_896_STATUS_FLAG_FETCH_ENABLE 0x20000000110#define CLK_896_STATUS_FLAG_OUTPUT_ON 0x03000000111#define CLK_896_STATUS_MASK_SRC 0x00000007112#define CLK_896_STATUS_FLAG_SRC_INTERNAL 0x00000000113#define CLK_896_STATUS_FLAG_SRC_ADAT_ON_OPT 0x00000001114#define CLK_896_STATUS_FLAG_SRC_AESEBU 0x00000002115#define CLK_896_STATUS_FLAG_SRC_SPH 0x00000003116#define CLK_896_STATUS_FLAG_SRC_WORD 0x00000004117#define CLK_896_STATUS_FLAG_SRC_ADAT_ON_DSUB 0x00000005118#define CLK_896_STATUS_MASK_RATE 0x00000018119#define CLK_896_STATUS_FLAG_RATE_44100 0x00000000120#define CLK_896_STATUS_FLAG_RATE_48000 0x00000008121#define CLK_896_STATUS_FLAG_RATE_88200 0x00000010122#define CLK_896_STATUS_FLAG_RATE_96000 0x00000018123124static void parse_clock_rate_828(u32 data, unsigned int *rate)125{126if (data & CLK_828_STATUS_FLAG_RATE_48000)127*rate = 48000;128else129*rate = 44100;130}131132static int get_clock_rate_828(struct snd_motu *motu, unsigned int *rate)133{134__be32 reg;135int err;136137err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));138if (err < 0)139return err;140parse_clock_rate_828(be32_to_cpu(reg), rate);141142return 0;143}144145static int parse_clock_rate_896(u32 data, unsigned int *rate)146{147switch (data & CLK_896_STATUS_MASK_RATE) {148case CLK_896_STATUS_FLAG_RATE_44100:149*rate = 44100;150break;151case CLK_896_STATUS_FLAG_RATE_48000:152*rate = 48000;153break;154case CLK_896_STATUS_FLAG_RATE_88200:155*rate = 88200;156break;157case CLK_896_STATUS_FLAG_RATE_96000:158*rate = 96000;159break;160default:161return -ENXIO;162}163164return 0;165}166167static int get_clock_rate_896(struct snd_motu *motu, unsigned int *rate)168{169__be32 reg;170int err;171172err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg));173if (err < 0)174return err;175return parse_clock_rate_896(be32_to_cpu(reg), rate);176}177178int snd_motu_protocol_v1_get_clock_rate(struct snd_motu *motu, unsigned int *rate)179{180if (motu->spec == &snd_motu_spec_828)181return get_clock_rate_828(motu, rate);182else if (motu->spec == &snd_motu_spec_896)183return get_clock_rate_896(motu, rate);184else185return -ENXIO;186}187188static int set_clock_rate_828(struct snd_motu *motu, unsigned int rate)189{190__be32 reg;191u32 data;192int err;193194err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));195if (err < 0)196return err;197data = be32_to_cpu(reg) & CLK_828_STATUS_MASK;198199data &= ~CLK_828_STATUS_FLAG_RATE_48000;200if (rate == 48000)201data |= CLK_828_STATUS_FLAG_RATE_48000;202203reg = cpu_to_be32(data);204return snd_motu_transaction_write(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));205}206207static int set_clock_rate_896(struct snd_motu *motu, unsigned int rate)208{209unsigned int flag;210__be32 reg;211u32 data;212int err;213214err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg));215if (err < 0)216return err;217data = be32_to_cpu(reg);218219switch (rate) {220case 44100:221flag = CLK_896_STATUS_FLAG_RATE_44100;222break;223case 48000:224flag = CLK_896_STATUS_FLAG_RATE_48000;225break;226case 88200:227flag = CLK_896_STATUS_FLAG_RATE_88200;228break;229case 96000:230flag = CLK_896_STATUS_FLAG_RATE_96000;231break;232default:233return -EINVAL;234}235236data &= ~CLK_896_STATUS_MASK_RATE;237data |= flag;238239reg = cpu_to_be32(data);240return snd_motu_transaction_write(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg));241}242243int snd_motu_protocol_v1_set_clock_rate(struct snd_motu *motu, unsigned int rate)244{245if (motu->spec == &snd_motu_spec_828)246return set_clock_rate_828(motu, rate);247else if (motu->spec == &snd_motu_spec_896)248return set_clock_rate_896(motu, rate);249else250return -ENXIO;251}252253static int get_clock_source_828(struct snd_motu *motu, enum snd_motu_clock_source *src)254{255__be32 reg;256u32 data;257int err;258259err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));260if (err < 0)261return err;262data = be32_to_cpu(reg) & CLK_828_STATUS_MASK;263264switch (data & CLK_828_STATUS_MASK_SRC) {265case CLK_828_STATUS_FLAG_SRC_ADAT_ON_OPT:266*src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT;267break;268case CLK_828_STATUS_FLAG_SRC_SPH:269*src = SND_MOTU_CLOCK_SOURCE_SPH;270break;271case CLK_828_STATUS_FLAG_SRC_SPDIF:272{273if (data & CLK_828_STATUS_FLAG_OPT_IN_IFACE_IS_SPDIF)274*src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;275else276*src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT;277break;278}279case CLK_828_STATUS_FLAG_SRC_ADAT_ON_DSUB:280*src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;281break;282case CLK_828_STATUS_FLAG_SRC_INTERNAL:283*src = SND_MOTU_CLOCK_SOURCE_INTERNAL;284break;285default:286return -ENXIO;287}288289return 0;290}291292static int get_clock_source_896(struct snd_motu *motu, enum snd_motu_clock_source *src)293{294__be32 reg;295u32 data;296int err;297298err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg));299if (err < 0)300return err;301data = be32_to_cpu(reg);302303switch (data & CLK_896_STATUS_MASK_SRC) {304case CLK_896_STATUS_FLAG_SRC_INTERNAL:305*src = SND_MOTU_CLOCK_SOURCE_INTERNAL;306break;307case CLK_896_STATUS_FLAG_SRC_ADAT_ON_OPT:308*src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT;309break;310case CLK_896_STATUS_FLAG_SRC_AESEBU:311*src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;312break;313case CLK_896_STATUS_FLAG_SRC_SPH:314*src = SND_MOTU_CLOCK_SOURCE_SPH;315break;316case CLK_896_STATUS_FLAG_SRC_WORD:317*src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC;318break;319case CLK_896_STATUS_FLAG_SRC_ADAT_ON_DSUB:320*src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;321break;322default:323return -ENXIO;324}325326return 0;327}328329int snd_motu_protocol_v1_get_clock_source(struct snd_motu *motu, enum snd_motu_clock_source *src)330{331if (motu->spec == &snd_motu_spec_828)332return get_clock_source_828(motu, src);333else if (motu->spec == &snd_motu_spec_896)334return get_clock_source_896(motu, src);335else336return -ENXIO;337}338339static int switch_fetching_mode_828(struct snd_motu *motu, bool enable)340{341__be32 reg;342u32 data;343int err;344345err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));346if (err < 0)347return err;348data = be32_to_cpu(reg) & CLK_828_STATUS_MASK;349350data &= ~(CLK_828_STATUS_FLAG_FETCH_PCM_FRAMES | CLK_828_STATUS_FLAG_ENABLE_OUTPUT);351if (enable) {352// This transaction should be initiated after the device receives batch of packets353// since the device voluntarily mutes outputs. As a workaround, yield processor over354// 100 msec.355msleep(100);356data |= CLK_828_STATUS_FLAG_FETCH_PCM_FRAMES | CLK_828_STATUS_FLAG_ENABLE_OUTPUT;357}358359reg = cpu_to_be32(data);360return snd_motu_transaction_write(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));361}362363static int switch_fetching_mode_896(struct snd_motu *motu, bool enable)364{365__be32 reg;366u32 data;367int err;368369err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg));370if (err < 0)371return err;372data = be32_to_cpu(reg);373374data &= ~CLK_896_STATUS_FLAG_FETCH_ENABLE;375if (enable)376data |= CLK_896_STATUS_FLAG_FETCH_ENABLE | CLK_896_STATUS_FLAG_OUTPUT_ON;377378reg = cpu_to_be32(data);379return snd_motu_transaction_write(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg));380}381382int snd_motu_protocol_v1_switch_fetching_mode(struct snd_motu *motu, bool enable)383{384if (motu->spec == &snd_motu_spec_828)385return switch_fetching_mode_828(motu, enable);386else if (motu->spec == &snd_motu_spec_896)387return switch_fetching_mode_896(motu, enable);388else389return -ENXIO;390}391392static int detect_packet_formats_828(struct snd_motu *motu)393{394__be32 reg;395u32 data;396int err;397398motu->tx_packet_formats.pcm_byte_offset = 4;399motu->tx_packet_formats.msg_chunks = 2;400401motu->rx_packet_formats.pcm_byte_offset = 4;402motu->rx_packet_formats.msg_chunks = 0;403404err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg));405if (err < 0)406return err;407data = be32_to_cpu(reg) & CLK_828_STATUS_MASK;408409// The number of chunks is just reduced when SPDIF is activated.410if (!(data & CLK_828_STATUS_FLAG_OPT_IN_IFACE_IS_SPDIF))411motu->tx_packet_formats.pcm_chunks[0] += 8;412413if (!(data & CLK_828_STATUS_FLAG_OPT_OUT_IFACE_IS_SPDIF))414motu->rx_packet_formats.pcm_chunks[0] += 8;415416return 0;417}418419static int detect_packet_formats_896(struct snd_motu *motu)420{421// 24bit PCM frames follow to source packet header without message chunk.422motu->tx_packet_formats.pcm_byte_offset = 4;423motu->rx_packet_formats.pcm_byte_offset = 4;424425// No message chunk in data block.426motu->tx_packet_formats.msg_chunks = 0;427motu->rx_packet_formats.msg_chunks = 0;428429// Always enable optical interface for ADAT signal since the device have no registers430// to refer to current configuration.431motu->tx_packet_formats.pcm_chunks[0] += 8;432motu->tx_packet_formats.pcm_chunks[1] += 8;433434motu->rx_packet_formats.pcm_chunks[0] += 8;435motu->rx_packet_formats.pcm_chunks[1] += 8;436437return 0;438}439440int snd_motu_protocol_v1_cache_packet_formats(struct snd_motu *motu)441{442memcpy(motu->tx_packet_formats.pcm_chunks, motu->spec->tx_fixed_pcm_chunks,443sizeof(motu->tx_packet_formats.pcm_chunks));444memcpy(motu->rx_packet_formats.pcm_chunks, motu->spec->rx_fixed_pcm_chunks,445sizeof(motu->rx_packet_formats.pcm_chunks));446447if (motu->spec == &snd_motu_spec_828)448return detect_packet_formats_828(motu);449else if (motu->spec == &snd_motu_spec_896)450return detect_packet_formats_896(motu);451else452return 0;453}454455const struct snd_motu_spec snd_motu_spec_828 = {456.name = "828",457.protocol_version = SND_MOTU_PROTOCOL_V1,458.tx_fixed_pcm_chunks = {10, 0, 0},459.rx_fixed_pcm_chunks = {10, 0, 0},460};461462const struct snd_motu_spec snd_motu_spec_896 = {463.name = "896",464.tx_fixed_pcm_chunks = {10, 10, 0},465.rx_fixed_pcm_chunks = {10, 10, 0},466};467468469