ALSA: firewire-motu: fix detection for S/PDIF source on optical interface in v2 protocol
[platform/kernel/linux-rpi.git] / sound / firewire / motu / motu-protocol-v2.c
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
27 static 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
38 int 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
52 int 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
81 static 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
123 static 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
147 static 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
158 int 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.
173 static 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.
182 static 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
203 int 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
237 static 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
254 static 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
271 static 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
288 int 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
323 const 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
332 const 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
341 const 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
350 const 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 };