1 /*
2  * tascam-stream.c - a part of driver for TASCAM FireWire series
3  *
4  * Copyright (c) 2015 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8 
9 #include <linux/delay.h>
10 #include "tascam.h"
11 
12 #define CALLBACK_TIMEOUT 500
13 
14 static int get_clock(struct snd_tscm *tscm, u32 *data)
15 {
16 	__be32 reg;
17 	int err;
18 
19 	err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST,
20 				 TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
21 				 &reg, sizeof(reg), 0);
22 	if (err >= 0)
23 		*data = be32_to_cpu(reg);
24 
25 	return err;
26 }
27 
28 static int set_clock(struct snd_tscm *tscm, unsigned int rate,
29 		     enum snd_tscm_clock clock)
30 {
31 	u32 data;
32 	__be32 reg;
33 	int err;
34 
35 	err = get_clock(tscm, &data);
36 	if (err < 0)
37 		return err;
38 	data &= 0x0000ffff;
39 
40 	if (rate > 0) {
41 		data &= 0x000000ff;
42 		/* Base rate. */
43 		if ((rate % 44100) == 0) {
44 			data |= 0x00000100;
45 			/* Multiplier. */
46 			if (rate / 44100 == 2)
47 				data |= 0x00008000;
48 		} else if ((rate % 48000) == 0) {
49 			data |= 0x00000200;
50 			/* Multiplier. */
51 			if (rate / 48000 == 2)
52 				data |= 0x00008000;
53 		} else {
54 			return -EAGAIN;
55 		}
56 	}
57 
58 	if (clock != INT_MAX) {
59 		data &= 0x0000ff00;
60 		data |= clock + 1;
61 	}
62 
63 	reg = cpu_to_be32(data);
64 
65 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
66 				 TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
67 				 &reg, sizeof(reg), 0);
68 	if (err < 0)
69 		return err;
70 
71 	if (data & 0x00008000)
72 		reg = cpu_to_be32(0x0000001a);
73 	else
74 		reg = cpu_to_be32(0x0000000d);
75 
76 	return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
77 				  TSCM_ADDR_BASE + TSCM_OFFSET_MULTIPLEX_MODE,
78 				  &reg, sizeof(reg), 0);
79 }
80 
81 int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate)
82 {
83 	u32 data = 0x0;
84 	unsigned int trials = 0;
85 	int err;
86 
87 	while (data == 0x0 || trials++ < 5) {
88 		err = get_clock(tscm, &data);
89 		if (err < 0)
90 			return err;
91 
92 		data = (data & 0xff000000) >> 24;
93 	}
94 
95 	/* Check base rate. */
96 	if ((data & 0x0f) == 0x01)
97 		*rate = 44100;
98 	else if ((data & 0x0f) == 0x02)
99 		*rate = 48000;
100 	else
101 		return -EAGAIN;
102 
103 	/* Check multiplier. */
104 	if ((data & 0xf0) == 0x80)
105 		*rate *= 2;
106 	else if ((data & 0xf0) != 0x00)
107 		return -EAGAIN;
108 
109 	return err;
110 }
111 
112 int snd_tscm_stream_get_clock(struct snd_tscm *tscm, enum snd_tscm_clock *clock)
113 {
114 	u32 data;
115 	int err;
116 
117 	err = get_clock(tscm, &data);
118 	if (err < 0)
119 		return err;
120 
121 	*clock = ((data & 0x00ff0000) >> 16) - 1;
122 	if (*clock < 0 || *clock > SND_TSCM_CLOCK_ADAT)
123 		return -EIO;
124 
125 	return 0;
126 }
127 
128 static int enable_data_channels(struct snd_tscm *tscm)
129 {
130 	__be32 reg;
131 	u32 data;
132 	unsigned int i;
133 	int err;
134 
135 	data = 0;
136 	for (i = 0; i < tscm->spec->pcm_capture_analog_channels; ++i)
137 		data |= BIT(i);
138 	if (tscm->spec->has_adat)
139 		data |= 0x0000ff00;
140 	if (tscm->spec->has_spdif)
141 		data |= 0x00030000;
142 
143 	reg = cpu_to_be32(data);
144 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
145 				 TSCM_ADDR_BASE + TSCM_OFFSET_TX_PCM_CHANNELS,
146 				 &reg, sizeof(reg), 0);
147 	if (err < 0)
148 		return err;
149 
150 	data = 0;
151 	for (i = 0; i < tscm->spec->pcm_playback_analog_channels; ++i)
152 		data |= BIT(i);
153 	if (tscm->spec->has_adat)
154 		data |= 0x0000ff00;
155 	if (tscm->spec->has_spdif)
156 		data |= 0x00030000;
157 
158 	reg = cpu_to_be32(data);
159 	return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
160 				  TSCM_ADDR_BASE + TSCM_OFFSET_RX_PCM_CHANNELS,
161 				  &reg, sizeof(reg), 0);
162 }
163 
164 static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate)
165 {
166 	__be32 reg;
167 	int err;
168 
169 	/* Set an option for unknown purpose. */
170 	reg = cpu_to_be32(0x00200000);
171 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
172 				 TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
173 				 &reg, sizeof(reg), 0);
174 	if (err < 0)
175 		return err;
176 
177 	err = enable_data_channels(tscm);
178 	if (err < 0)
179 		return err;
180 
181 	return set_clock(tscm, rate, INT_MAX);
182 }
183 
184 static void finish_session(struct snd_tscm *tscm)
185 {
186 	__be32 reg;
187 
188 	reg = 0;
189 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
190 			   TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
191 			   &reg, sizeof(reg), 0);
192 
193 	reg = 0;
194 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
195 			   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
196 			   &reg, sizeof(reg), 0);
197 
198 }
199 
200 static int begin_session(struct snd_tscm *tscm)
201 {
202 	__be32 reg;
203 	int err;
204 
205 	reg = cpu_to_be32(0x00000001);
206 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
207 				 TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
208 				 &reg, sizeof(reg), 0);
209 	if (err < 0)
210 		return err;
211 
212 	reg = cpu_to_be32(0x00000001);
213 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
214 				 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
215 				 &reg, sizeof(reg), 0);
216 	if (err < 0)
217 		return err;
218 
219 	/* Set an option for unknown purpose. */
220 	reg = cpu_to_be32(0x00002000);
221 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
222 				 TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
223 				 &reg, sizeof(reg), 0);
224 	if (err < 0)
225 		return err;
226 
227 	/* Start multiplexing PCM samples on packets. */
228 	reg = cpu_to_be32(0x00000001);
229 	return snd_fw_transaction(tscm->unit,
230 				  TCODE_WRITE_QUADLET_REQUEST,
231 				  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_ON,
232 				  &reg, sizeof(reg), 0);
233 }
234 
235 static void release_resources(struct snd_tscm *tscm)
236 {
237 	__be32 reg;
238 
239 	/* Unregister channels. */
240 	reg = cpu_to_be32(0x00000000);
241 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
242 			   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
243 			   &reg, sizeof(reg), 0);
244 	reg = cpu_to_be32(0x00000000);
245 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
246 			   TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
247 			   &reg, sizeof(reg), 0);
248 	reg = cpu_to_be32(0x00000000);
249 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
250 			   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
251 			   &reg, sizeof(reg), 0);
252 
253 	/* Release isochronous resources. */
254 	fw_iso_resources_free(&tscm->tx_resources);
255 	fw_iso_resources_free(&tscm->rx_resources);
256 }
257 
258 static int keep_resources(struct snd_tscm *tscm, unsigned int rate)
259 {
260 	__be32 reg;
261 	int err;
262 
263 	/* Keep resources for in-stream. */
264 	err = amdtp_tscm_set_parameters(&tscm->tx_stream, rate);
265 	if (err < 0)
266 		return err;
267 	err = fw_iso_resources_allocate(&tscm->tx_resources,
268 			amdtp_stream_get_max_payload(&tscm->tx_stream),
269 			fw_parent_device(tscm->unit)->max_speed);
270 	if (err < 0)
271 		goto error;
272 
273 	/* Keep resources for out-stream. */
274 	err = amdtp_tscm_set_parameters(&tscm->rx_stream, rate);
275 	if (err < 0)
276 		return err;
277 	err = fw_iso_resources_allocate(&tscm->rx_resources,
278 			amdtp_stream_get_max_payload(&tscm->rx_stream),
279 			fw_parent_device(tscm->unit)->max_speed);
280 	if (err < 0)
281 		return err;
282 
283 	/* Register the isochronous channel for transmitting stream. */
284 	reg = cpu_to_be32(tscm->tx_resources.channel);
285 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
286 				 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
287 				 &reg, sizeof(reg), 0);
288 	if (err < 0)
289 		goto error;
290 
291 	/* Unknown */
292 	reg = cpu_to_be32(0x00000002);
293 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
294 				 TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
295 				 &reg, sizeof(reg), 0);
296 	if (err < 0)
297 		goto error;
298 
299 	/* Register the isochronous channel for receiving stream. */
300 	reg = cpu_to_be32(tscm->rx_resources.channel);
301 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
302 				 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
303 				 &reg, sizeof(reg), 0);
304 	if (err < 0)
305 		goto error;
306 
307 	return 0;
308 error:
309 	release_resources(tscm);
310 	return err;
311 }
312 
313 int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
314 {
315 	unsigned int pcm_channels;
316 	int err;
317 
318 	/* For out-stream. */
319 	err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit);
320 	if (err < 0)
321 		return err;
322 	pcm_channels = tscm->spec->pcm_playback_analog_channels;
323 	if (tscm->spec->has_adat)
324 		pcm_channels += 8;
325 	if (tscm->spec->has_spdif)
326 		pcm_channels += 2;
327 	err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM,
328 			      pcm_channels);
329 	if (err < 0)
330 		return err;
331 
332 	/* For in-stream. */
333 	err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit);
334 	if (err < 0)
335 		return err;
336 	pcm_channels = tscm->spec->pcm_capture_analog_channels;
337 	if (tscm->spec->has_adat)
338 		pcm_channels += 8;
339 	if (tscm->spec->has_spdif)
340 		pcm_channels += 2;
341 	err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM,
342 			      pcm_channels);
343 	if (err < 0)
344 		amdtp_stream_destroy(&tscm->rx_stream);
345 
346 	return err;
347 }
348 
349 /* At bus reset, streaming is stopped and some registers are clear. */
350 void snd_tscm_stream_update_duplex(struct snd_tscm *tscm)
351 {
352 	amdtp_stream_pcm_abort(&tscm->tx_stream);
353 	amdtp_stream_stop(&tscm->tx_stream);
354 
355 	amdtp_stream_pcm_abort(&tscm->rx_stream);
356 	amdtp_stream_stop(&tscm->rx_stream);
357 }
358 
359 /*
360  * This function should be called before starting streams or after stopping
361  * streams.
362  */
363 void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
364 {
365 	amdtp_stream_destroy(&tscm->rx_stream);
366 	amdtp_stream_destroy(&tscm->tx_stream);
367 
368 	fw_iso_resources_destroy(&tscm->rx_resources);
369 	fw_iso_resources_destroy(&tscm->tx_resources);
370 }
371 
372 int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
373 {
374 	unsigned int curr_rate;
375 	int err;
376 
377 	if (tscm->substreams_counter == 0)
378 		return 0;
379 
380 	err = snd_tscm_stream_get_rate(tscm, &curr_rate);
381 	if (err < 0)
382 		return err;
383 	if (curr_rate != rate ||
384 	    amdtp_streaming_error(&tscm->rx_stream) ||
385 	    amdtp_streaming_error(&tscm->tx_stream)) {
386 		finish_session(tscm);
387 
388 		amdtp_stream_stop(&tscm->rx_stream);
389 		amdtp_stream_stop(&tscm->tx_stream);
390 
391 		release_resources(tscm);
392 	}
393 
394 	if (!amdtp_stream_running(&tscm->rx_stream)) {
395 		err = keep_resources(tscm, rate);
396 		if (err < 0)
397 			goto error;
398 
399 		err = set_stream_formats(tscm, rate);
400 		if (err < 0)
401 			goto error;
402 
403 		err = begin_session(tscm);
404 		if (err < 0)
405 			goto error;
406 
407 		err = amdtp_stream_start(&tscm->rx_stream,
408 				tscm->rx_resources.channel,
409 				fw_parent_device(tscm->unit)->max_speed);
410 		if (err < 0)
411 			goto error;
412 
413 		if (!amdtp_stream_wait_callback(&tscm->rx_stream,
414 						CALLBACK_TIMEOUT)) {
415 			err = -ETIMEDOUT;
416 			goto error;
417 		}
418 	}
419 
420 	if (!amdtp_stream_running(&tscm->tx_stream)) {
421 		err = amdtp_stream_start(&tscm->tx_stream,
422 				tscm->tx_resources.channel,
423 				fw_parent_device(tscm->unit)->max_speed);
424 		if (err < 0)
425 			goto error;
426 
427 		if (!amdtp_stream_wait_callback(&tscm->tx_stream,
428 						CALLBACK_TIMEOUT)) {
429 			err = -ETIMEDOUT;
430 			goto error;
431 		}
432 	}
433 
434 	return 0;
435 error:
436 	amdtp_stream_stop(&tscm->rx_stream);
437 	amdtp_stream_stop(&tscm->tx_stream);
438 
439 	finish_session(tscm);
440 	release_resources(tscm);
441 
442 	return err;
443 }
444 
445 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
446 {
447 	if (tscm->substreams_counter > 0)
448 		return;
449 
450 	amdtp_stream_stop(&tscm->tx_stream);
451 	amdtp_stream_stop(&tscm->rx_stream);
452 
453 	finish_session(tscm);
454 	release_resources(tscm);
455 }
456 
457 void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
458 {
459 	tscm->dev_lock_changed = true;
460 	wake_up(&tscm->hwdep_wait);
461 }
462 
463 int snd_tscm_stream_lock_try(struct snd_tscm *tscm)
464 {
465 	int err;
466 
467 	spin_lock_irq(&tscm->lock);
468 
469 	/* user land lock this */
470 	if (tscm->dev_lock_count < 0) {
471 		err = -EBUSY;
472 		goto end;
473 	}
474 
475 	/* this is the first time */
476 	if (tscm->dev_lock_count++ == 0)
477 		snd_tscm_stream_lock_changed(tscm);
478 	err = 0;
479 end:
480 	spin_unlock_irq(&tscm->lock);
481 	return err;
482 }
483 
484 void snd_tscm_stream_lock_release(struct snd_tscm *tscm)
485 {
486 	spin_lock_irq(&tscm->lock);
487 
488 	if (WARN_ON(tscm->dev_lock_count <= 0))
489 		goto end;
490 	if (--tscm->dev_lock_count == 0)
491 		snd_tscm_stream_lock_changed(tscm);
492 end:
493 	spin_unlock_irq(&tscm->lock);
494 }
495