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