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 	return enable_data_channels(tscm);
178 }
179 
180 static void finish_session(struct snd_tscm *tscm)
181 {
182 	__be32 reg;
183 
184 	amdtp_stream_stop(&tscm->rx_stream);
185 	amdtp_stream_stop(&tscm->tx_stream);
186 
187 	reg = 0;
188 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
189 			   TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
190 			   &reg, sizeof(reg), 0);
191 
192 	reg = 0;
193 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
194 			   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
195 			   &reg, sizeof(reg), 0);
196 
197 	// Unregister channels.
198 	reg = cpu_to_be32(0x00000000);
199 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
200 			   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
201 			   &reg, sizeof(reg), 0);
202 	reg = cpu_to_be32(0x00000000);
203 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
204 			   TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
205 			   &reg, sizeof(reg), 0);
206 	reg = cpu_to_be32(0x00000000);
207 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
208 			   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
209 			   &reg, sizeof(reg), 0);
210 }
211 
212 static int begin_session(struct snd_tscm *tscm)
213 {
214 	__be32 reg;
215 	int err;
216 
217 	// Register the isochronous channel for transmitting stream.
218 	reg = cpu_to_be32(tscm->tx_resources.channel);
219 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
220 				 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
221 				 &reg, sizeof(reg), 0);
222 	if (err < 0)
223 		return err;
224 
225 	// Unknown.
226 	reg = cpu_to_be32(0x00000002);
227 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
228 				 TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
229 				 &reg, sizeof(reg), 0);
230 	if (err < 0)
231 		return err;
232 
233 	// Register the isochronous channel for receiving stream.
234 	reg = cpu_to_be32(tscm->rx_resources.channel);
235 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
236 				 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
237 				 &reg, sizeof(reg), 0);
238 	if (err < 0)
239 		return err;
240 
241 	reg = cpu_to_be32(0x00000001);
242 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
243 				 TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
244 				 &reg, sizeof(reg), 0);
245 	if (err < 0)
246 		return err;
247 
248 	reg = cpu_to_be32(0x00000001);
249 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
250 				 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
251 				 &reg, sizeof(reg), 0);
252 	if (err < 0)
253 		return err;
254 
255 	// Set an option for unknown purpose.
256 	reg = cpu_to_be32(0x00002000);
257 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
258 				 TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
259 				 &reg, sizeof(reg), 0);
260 	if (err < 0)
261 		return err;
262 
263 	// Start multiplexing PCM samples on packets.
264 	reg = cpu_to_be32(0x00000001);
265 	return snd_fw_transaction(tscm->unit,
266 				  TCODE_WRITE_QUADLET_REQUEST,
267 				  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_ON,
268 				  &reg, sizeof(reg), 0);
269 }
270 
271 static int keep_resources(struct snd_tscm *tscm, unsigned int rate,
272 			  struct amdtp_stream *stream)
273 {
274 	struct fw_iso_resources *resources;
275 	int err;
276 
277 	if (stream == &tscm->tx_stream)
278 		resources = &tscm->tx_resources;
279 	else
280 		resources = &tscm->rx_resources;
281 
282 	err = amdtp_tscm_set_parameters(stream, rate);
283 	if (err < 0)
284 		return err;
285 
286 	return fw_iso_resources_allocate(resources,
287 				amdtp_stream_get_max_payload(stream),
288 				fw_parent_device(tscm->unit)->max_speed);
289 }
290 
291 int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
292 {
293 	unsigned int pcm_channels;
294 	int err;
295 
296 	/* For out-stream. */
297 	err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit);
298 	if (err < 0)
299 		return err;
300 	pcm_channels = tscm->spec->pcm_playback_analog_channels;
301 	if (tscm->spec->has_adat)
302 		pcm_channels += 8;
303 	if (tscm->spec->has_spdif)
304 		pcm_channels += 2;
305 	err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM,
306 			      pcm_channels);
307 	if (err < 0)
308 		return err;
309 
310 	/* For in-stream. */
311 	err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit);
312 	if (err < 0)
313 		return err;
314 	pcm_channels = tscm->spec->pcm_capture_analog_channels;
315 	if (tscm->spec->has_adat)
316 		pcm_channels += 8;
317 	if (tscm->spec->has_spdif)
318 		pcm_channels += 2;
319 	err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM,
320 			      pcm_channels);
321 	if (err < 0)
322 		amdtp_stream_destroy(&tscm->rx_stream);
323 
324 	return err;
325 }
326 
327 // At bus reset, streaming is stopped and some registers are clear.
328 void snd_tscm_stream_update_duplex(struct snd_tscm *tscm)
329 {
330 	amdtp_stream_pcm_abort(&tscm->tx_stream);
331 	amdtp_stream_stop(&tscm->tx_stream);
332 
333 	amdtp_stream_pcm_abort(&tscm->rx_stream);
334 	amdtp_stream_stop(&tscm->rx_stream);
335 }
336 
337 /*
338  * This function should be called before starting streams or after stopping
339  * streams.
340  */
341 void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
342 {
343 	amdtp_stream_destroy(&tscm->rx_stream);
344 	amdtp_stream_destroy(&tscm->tx_stream);
345 
346 	fw_iso_resources_destroy(&tscm->rx_resources);
347 	fw_iso_resources_destroy(&tscm->tx_resources);
348 }
349 
350 int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate)
351 {
352 	unsigned int curr_rate;
353 	int err;
354 
355 	err = snd_tscm_stream_get_rate(tscm, &curr_rate);
356 	if (err < 0)
357 		return err;
358 
359 	if (tscm->substreams_counter == 0 || rate != curr_rate) {
360 		finish_session(tscm);
361 
362 		fw_iso_resources_free(&tscm->tx_resources);
363 		fw_iso_resources_free(&tscm->rx_resources);
364 
365 		err = set_clock(tscm, rate, INT_MAX);
366 		if (err < 0)
367 			return err;
368 
369 		err = keep_resources(tscm, rate, &tscm->tx_stream);
370 		if (err < 0)
371 			return err;
372 
373 		err = keep_resources(tscm, rate, &tscm->rx_stream);
374 		if (err < 0) {
375 			fw_iso_resources_free(&tscm->tx_resources);
376 			return err;
377 		}
378 	}
379 
380 	return 0;
381 }
382 
383 int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
384 {
385 	unsigned int generation = tscm->rx_resources.generation;
386 	int err;
387 
388 	if (tscm->substreams_counter == 0)
389 		return 0;
390 
391 	if (amdtp_streaming_error(&tscm->rx_stream) ||
392 	    amdtp_streaming_error(&tscm->tx_stream))
393 		finish_session(tscm);
394 
395 	if (generation != fw_parent_device(tscm->unit)->card->generation) {
396 		err = fw_iso_resources_update(&tscm->tx_resources);
397 		if (err < 0)
398 			goto error;
399 
400 		err = fw_iso_resources_update(&tscm->rx_resources);
401 		if (err < 0)
402 			goto error;
403 	}
404 
405 	if (!amdtp_stream_running(&tscm->rx_stream)) {
406 		err = set_stream_formats(tscm, rate);
407 		if (err < 0)
408 			goto error;
409 
410 		err = begin_session(tscm);
411 		if (err < 0)
412 			goto error;
413 
414 		err = amdtp_stream_start(&tscm->rx_stream,
415 				tscm->rx_resources.channel,
416 				fw_parent_device(tscm->unit)->max_speed);
417 		if (err < 0)
418 			goto error;
419 
420 		if (!amdtp_stream_wait_callback(&tscm->rx_stream,
421 						CALLBACK_TIMEOUT)) {
422 			err = -ETIMEDOUT;
423 			goto error;
424 		}
425 	}
426 
427 	if (!amdtp_stream_running(&tscm->tx_stream)) {
428 		err = amdtp_stream_start(&tscm->tx_stream,
429 				tscm->tx_resources.channel,
430 				fw_parent_device(tscm->unit)->max_speed);
431 		if (err < 0)
432 			goto error;
433 
434 		if (!amdtp_stream_wait_callback(&tscm->tx_stream,
435 						CALLBACK_TIMEOUT)) {
436 			err = -ETIMEDOUT;
437 			goto error;
438 		}
439 	}
440 
441 	return 0;
442 error:
443 	finish_session(tscm);
444 
445 	return err;
446 }
447 
448 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
449 {
450 	if (tscm->substreams_counter == 0) {
451 		finish_session(tscm);
452 
453 		fw_iso_resources_free(&tscm->tx_resources);
454 		fw_iso_resources_free(&tscm->rx_resources);
455 	}
456 }
457 
458 void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
459 {
460 	tscm->dev_lock_changed = true;
461 	wake_up(&tscm->hwdep_wait);
462 }
463 
464 int snd_tscm_stream_lock_try(struct snd_tscm *tscm)
465 {
466 	int err;
467 
468 	spin_lock_irq(&tscm->lock);
469 
470 	/* user land lock this */
471 	if (tscm->dev_lock_count < 0) {
472 		err = -EBUSY;
473 		goto end;
474 	}
475 
476 	/* this is the first time */
477 	if (tscm->dev_lock_count++ == 0)
478 		snd_tscm_stream_lock_changed(tscm);
479 	err = 0;
480 end:
481 	spin_unlock_irq(&tscm->lock);
482 	return err;
483 }
484 
485 void snd_tscm_stream_lock_release(struct snd_tscm *tscm)
486 {
487 	spin_lock_irq(&tscm->lock);
488 
489 	if (WARN_ON(tscm->dev_lock_count <= 0))
490 		goto end;
491 	if (--tscm->dev_lock_count == 0)
492 		snd_tscm_stream_lock_changed(tscm);
493 end:
494 	spin_unlock_irq(&tscm->lock);
495 }
496