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