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