1 /*
2  * bebob_focusrite.c - a part of driver for BeBoB based devices
3  *
4  * Copyright (c) 2013-2014 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8 
9 #include "./bebob.h"
10 
11 #define ANA_IN	"Analog In"
12 #define DIG_IN	"Digital In"
13 #define ANA_OUT	"Analog Out"
14 #define DIG_OUT	"Digital Out"
15 #define STM_IN	"Stream In"
16 
17 #define SAFFIRE_ADDRESS_BASE			0x000100000000ULL
18 
19 #define SAFFIRE_OFFSET_CLOCK_SOURCE		0x00f8
20 #define SAFFIREPRO_OFFSET_CLOCK_SOURCE		0x0174
21 
22 /* whether sync to external device or not */
23 #define SAFFIRE_OFFSET_CLOCK_SYNC_EXT		0x013c
24 #define SAFFIRE_LE_OFFSET_CLOCK_SYNC_EXT	0x0432
25 #define SAFFIREPRO_OFFSET_CLOCK_SYNC_EXT	0x0164
26 
27 #define SAFFIRE_CLOCK_SOURCE_INTERNAL		0
28 #define SAFFIRE_CLOCK_SOURCE_SPDIF		1
29 
30 /* clock sources as returned from register of Saffire Pro 10 and 26 */
31 #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL	0
32 #define SAFFIREPRO_CLOCK_SOURCE_SKIP		1 /* never used on hardware */
33 #define SAFFIREPRO_CLOCK_SOURCE_SPDIF		2
34 #define SAFFIREPRO_CLOCK_SOURCE_ADAT1		3 /* not used on s.pro. 10 */
35 #define SAFFIREPRO_CLOCK_SOURCE_ADAT2		4 /* not used on s.pro. 10 */
36 #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK	5
37 #define SAFFIREPRO_CLOCK_SOURCE_COUNT		6
38 
39 /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
40 #define SAFFIREPRO_ENABLE_DIG_IFACES		0x01a4
41 
42 /* saffirepro has its own parameter for sampling frequency */
43 #define SAFFIREPRO_RATE_NOREBOOT		0x01cc
44 /* index is the value for this register */
45 static const unsigned int rates[] = {
46 	[0] = 0,
47 	[1] = 44100,
48 	[2] = 48000,
49 	[3] = 88200,
50 	[4] = 96000,
51 	[5] = 176400,
52 	[6] = 192000
53 };
54 
55 /* saffire(no label)/saffire LE has metering */
56 #define SAFFIRE_OFFSET_METER			0x0100
57 #define SAFFIRE_LE_OFFSET_METER			0x0168
58 
59 static inline int
60 saffire_read_block(struct snd_bebob *bebob, u64 offset,
61 		   u32 *buf, unsigned int size)
62 {
63 	unsigned int i;
64 	int err;
65 	__be32 *tmp = (__be32 *)buf;
66 
67 	err =  snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST,
68 				  SAFFIRE_ADDRESS_BASE + offset,
69 				  tmp, size, 0);
70 	if (err < 0)
71 		goto end;
72 
73 	for (i = 0; i < size / sizeof(u32); i++)
74 		buf[i] = be32_to_cpu(tmp[i]);
75 end:
76 	return err;
77 }
78 
79 static inline int
80 saffire_read_quad(struct snd_bebob *bebob, u64 offset, u32 *value)
81 {
82 	int err;
83 	__be32 tmp;
84 
85 	err = snd_fw_transaction(bebob->unit, TCODE_READ_QUADLET_REQUEST,
86 				 SAFFIRE_ADDRESS_BASE + offset,
87 				 &tmp, sizeof(__be32), 0);
88 	if (err < 0)
89 		goto end;
90 
91 	*value = be32_to_cpu(tmp);
92 end:
93 	return err;
94 }
95 
96 static inline int
97 saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
98 {
99 	__be32 data = cpu_to_be32(value);
100 
101 	return snd_fw_transaction(bebob->unit, TCODE_WRITE_QUADLET_REQUEST,
102 				  SAFFIRE_ADDRESS_BASE + offset,
103 				  &data, sizeof(__be32), 0);
104 }
105 
106 static enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = {
107 	SND_BEBOB_CLOCK_TYPE_INTERNAL,
108 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,	/* S/PDIF */
109 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,	/* Word Clock */
110 };
111 static enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = {
112 	SND_BEBOB_CLOCK_TYPE_INTERNAL,
113 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,	/* S/PDIF */
114 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,	/* ADAT1 */
115 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,	/* ADAT2 */
116 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,	/* Word Clock */
117 };
118 /* Value maps between registers and labels for SaffirePro 10/26. */
119 static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
120 	/* SaffirePro 10 */
121 	[0] = {
122 		[SAFFIREPRO_CLOCK_SOURCE_INTERNAL]  =  0,
123 		[SAFFIREPRO_CLOCK_SOURCE_SKIP]      = -1, /* not supported */
124 		[SAFFIREPRO_CLOCK_SOURCE_SPDIF]     =  1,
125 		[SAFFIREPRO_CLOCK_SOURCE_ADAT1]     = -1, /* not supported */
126 		[SAFFIREPRO_CLOCK_SOURCE_ADAT2]     = -1, /* not supported */
127 		[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] =  2,
128 	},
129 	/* SaffirePro 26 */
130 	[1] = {
131 		[SAFFIREPRO_CLOCK_SOURCE_INTERNAL]  =  0,
132 		[SAFFIREPRO_CLOCK_SOURCE_SKIP]      = -1, /* not supported */
133 		[SAFFIREPRO_CLOCK_SOURCE_SPDIF]     =  1,
134 		[SAFFIREPRO_CLOCK_SOURCE_ADAT1]     =  2,
135 		[SAFFIREPRO_CLOCK_SOURCE_ADAT2]     =  3,
136 		[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] =  4,
137 	}
138 };
139 
140 static int
141 saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
142 {
143 	u32 id;
144 	int err;
145 
146 	err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id);
147 	if (err < 0)
148 		goto end;
149 	if (id >= ARRAY_SIZE(rates))
150 		err = -EIO;
151 	else
152 		*rate = rates[id];
153 end:
154 	return err;
155 }
156 static int
157 saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
158 {
159 	u32 id;
160 
161 	for (id = 0; id < ARRAY_SIZE(rates); id++) {
162 		if (rates[id] == rate)
163 			break;
164 	}
165 	if (id == ARRAY_SIZE(rates))
166 		return -EINVAL;
167 
168 	return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
169 }
170 
171 /*
172  * query hardware for current clock source, return our internally
173  * used clock index in *id, depending on hardware.
174  */
175 static int
176 saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
177 {
178 	int err;
179 	u32 value;       /* clock source read from hw register */
180 	const signed char *map;
181 
182 	err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
183 	if (err < 0)
184 		goto end;
185 
186 	/* depending on hardware, use a different mapping */
187 	if (bebob->spec->clock->types == saffirepro_10_clk_src_types)
188 		map = saffirepro_clk_maps[0];
189 	else
190 		map = saffirepro_clk_maps[1];
191 
192 	/* In a case that this driver cannot handle the value of register. */
193 	if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
194 		err = -EIO;
195 		goto end;
196 	}
197 
198 	*id = (unsigned int)map[value];
199 end:
200 	return err;
201 }
202 
203 const struct snd_bebob_spec saffire_le_spec;
204 static enum snd_bebob_clock_type saffire_both_clk_src_types[] = {
205 	SND_BEBOB_CLOCK_TYPE_INTERNAL,
206 	SND_BEBOB_CLOCK_TYPE_EXTERNAL,
207 };
208 static int
209 saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
210 {
211 	int err;
212 	u32 value;
213 
214 	err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value);
215 	if (err >= 0)
216 		*id = 0xff & value;
217 
218 	return err;
219 };
220 static const char *const saffire_le_meter_labels[] = {
221 	ANA_IN, ANA_IN, DIG_IN,
222 	ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT,
223 	STM_IN, STM_IN
224 };
225 static const char *const saffire_meter_labels[] = {
226 	ANA_IN, ANA_IN,
227 	STM_IN, STM_IN, STM_IN, STM_IN, STM_IN,
228 };
229 static int
230 saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size)
231 {
232 	const struct snd_bebob_meter_spec *spec = bebob->spec->meter;
233 	unsigned int channels;
234 	u64 offset;
235 	int err;
236 
237 	if (spec->labels == saffire_le_meter_labels)
238 		offset = SAFFIRE_LE_OFFSET_METER;
239 	else
240 		offset = SAFFIRE_OFFSET_METER;
241 
242 	channels = spec->num * 2;
243 	if (size < channels * sizeof(u32))
244 		return -EIO;
245 
246 	err = saffire_read_block(bebob, offset, buf, size);
247 	if (err >= 0 && spec->labels == saffire_le_meter_labels) {
248 		swap(buf[1], buf[3]);
249 		swap(buf[2], buf[3]);
250 		swap(buf[3], buf[4]);
251 
252 		swap(buf[7], buf[10]);
253 		swap(buf[8], buf[10]);
254 		swap(buf[9], buf[11]);
255 		swap(buf[11], buf[12]);
256 
257 		swap(buf[15], buf[16]);
258 	}
259 
260 	return err;
261 }
262 
263 static const struct snd_bebob_rate_spec saffirepro_both_rate_spec = {
264 	.get	= &saffirepro_both_clk_freq_get,
265 	.set	= &saffirepro_both_clk_freq_set,
266 };
267 /* Saffire Pro 26 I/O  */
268 static const struct snd_bebob_clock_spec saffirepro_26_clk_spec = {
269 	.num	= ARRAY_SIZE(saffirepro_26_clk_src_types),
270 	.types	= saffirepro_26_clk_src_types,
271 	.get	= &saffirepro_both_clk_src_get,
272 };
273 const struct snd_bebob_spec saffirepro_26_spec = {
274 	.clock	= &saffirepro_26_clk_spec,
275 	.rate	= &saffirepro_both_rate_spec,
276 	.meter	= NULL
277 };
278 /* Saffire Pro 10 I/O */
279 static const struct snd_bebob_clock_spec saffirepro_10_clk_spec = {
280 	.num	= ARRAY_SIZE(saffirepro_10_clk_src_types),
281 	.types	= saffirepro_10_clk_src_types,
282 	.get	= &saffirepro_both_clk_src_get,
283 };
284 const struct snd_bebob_spec saffirepro_10_spec = {
285 	.clock	= &saffirepro_10_clk_spec,
286 	.rate	= &saffirepro_both_rate_spec,
287 	.meter	= NULL
288 };
289 
290 static const struct snd_bebob_rate_spec saffire_both_rate_spec = {
291 	.get	= &snd_bebob_stream_get_rate,
292 	.set	= &snd_bebob_stream_set_rate,
293 };
294 static const struct snd_bebob_clock_spec saffire_both_clk_spec = {
295 	.num	= ARRAY_SIZE(saffire_both_clk_src_types),
296 	.types	= saffire_both_clk_src_types,
297 	.get	= &saffire_both_clk_src_get,
298 };
299 /* Saffire LE */
300 static const struct snd_bebob_meter_spec saffire_le_meter_spec = {
301 	.num	= ARRAY_SIZE(saffire_le_meter_labels),
302 	.labels	= saffire_le_meter_labels,
303 	.get	= &saffire_meter_get,
304 };
305 const struct snd_bebob_spec saffire_le_spec = {
306 	.clock	= &saffire_both_clk_spec,
307 	.rate	= &saffire_both_rate_spec,
308 	.meter	= &saffire_le_meter_spec
309 };
310 /* Saffire */
311 static const struct snd_bebob_meter_spec saffire_meter_spec = {
312 	.num	= ARRAY_SIZE(saffire_meter_labels),
313 	.labels	= saffire_meter_labels,
314 	.get	= &saffire_meter_get,
315 };
316 const struct snd_bebob_spec saffire_spec = {
317 	.clock	= &saffire_both_clk_spec,
318 	.rate	= &saffire_both_rate_spec,
319 	.meter	= &saffire_meter_spec
320 };
321