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 READY_TIMEOUT_MS	4000
15
16static 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
44static 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
97int 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
125int 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
141static 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
177static 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
193static 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
222static 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
281static 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
301static 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
334static 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
344int 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.
368void 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.
378void 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
386int 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		tscm->need_long_tx_init_skip = (rate != curr_rate);
428	}
429
430	return 0;
431}
432
433int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
434{
435	unsigned int generation = tscm->rx_resources.generation;
436	int err;
437
438	if (tscm->substreams_counter == 0)
439		return 0;
440
441	if (amdtp_streaming_error(&tscm->rx_stream) ||
442	    amdtp_streaming_error(&tscm->tx_stream)) {
443		amdtp_domain_stop(&tscm->domain);
444		finish_session(tscm);
445	}
446
447	if (generation != fw_parent_device(tscm->unit)->card->generation) {
448		err = fw_iso_resources_update(&tscm->tx_resources);
449		if (err < 0)
450			goto error;
451
452		err = fw_iso_resources_update(&tscm->rx_resources);
453		if (err < 0)
454			goto error;
455	}
456
457	if (!amdtp_stream_running(&tscm->rx_stream)) {
458		int spd = fw_parent_device(tscm->unit)->max_speed;
459		unsigned int tx_init_skip_cycles;
460
461		err = set_stream_formats(tscm, rate);
462		if (err < 0)
463			goto error;
464
465		err = begin_session(tscm);
466		if (err < 0)
467			goto error;
468
469		err = amdtp_domain_add_stream(&tscm->domain, &tscm->rx_stream,
470					      tscm->rx_resources.channel, spd);
471		if (err < 0)
472			goto error;
473
474		err = amdtp_domain_add_stream(&tscm->domain, &tscm->tx_stream,
475					      tscm->tx_resources.channel, spd);
476		if (err < 0)
477			goto error;
478
479		if (tscm->need_long_tx_init_skip)
480			tx_init_skip_cycles = 16000;
481		else
482			tx_init_skip_cycles = 0;
483
484		// MEMO: Just after starting packet streaming, it transfers packets without any
485		// event. Enough after receiving the sequence of packets, it multiplexes events into
486		// the packet. However, just after changing sampling transfer frequency, it stops
487		// multiplexing during packet transmission. Enough after, it restarts multiplexing
488		// again. The device ignores presentation time expressed by the value of syt field
489		// of CIP header in received packets. The sequence of the number of data blocks per
490		// packet is important for media clock recovery.
491		err = amdtp_domain_start(&tscm->domain, tx_init_skip_cycles, true, true);
492		if (err < 0)
493			goto error;
494
495		if (!amdtp_domain_wait_ready(&tscm->domain, READY_TIMEOUT_MS)) {
496			err = -ETIMEDOUT;
497			goto error;
498		}
499	}
500
501	return 0;
502error:
503	amdtp_domain_stop(&tscm->domain);
504	finish_session(tscm);
505
506	return err;
507}
508
509void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
510{
511	if (tscm->substreams_counter == 0) {
512		amdtp_domain_stop(&tscm->domain);
513		finish_session(tscm);
514
515		fw_iso_resources_free(&tscm->tx_resources);
516		fw_iso_resources_free(&tscm->rx_resources);
517
518		tscm->need_long_tx_init_skip = false;
519	}
520}
521
522void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
523{
524	tscm->dev_lock_changed = true;
525	wake_up(&tscm->hwdep_wait);
526}
527
528int snd_tscm_stream_lock_try(struct snd_tscm *tscm)
529{
530	int err;
531
532	spin_lock_irq(&tscm->lock);
533
534	/* user land lock this */
535	if (tscm->dev_lock_count < 0) {
536		err = -EBUSY;
537		goto end;
538	}
539
540	/* this is the first time */
541	if (tscm->dev_lock_count++ == 0)
542		snd_tscm_stream_lock_changed(tscm);
543	err = 0;
544end:
545	spin_unlock_irq(&tscm->lock);
546	return err;
547}
548
549void snd_tscm_stream_lock_release(struct snd_tscm *tscm)
550{
551	spin_lock_irq(&tscm->lock);
552
553	if (WARN_ON(tscm->dev_lock_count <= 0))
554		goto end;
555	if (--tscm->dev_lock_count == 0)
556		snd_tscm_stream_lock_changed(tscm);
557end:
558	spin_unlock_irq(&tscm->lock);
559}
560