1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family
4 *
5 * Copyright (c) 2014-2015 Takashi Sakamoto
6 */
7
8#include "digi00x.h"
9
10#define READY_TIMEOUT_MS	200
11
12const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = {
13	[SND_DG00X_RATE_44100] = 44100,
14	[SND_DG00X_RATE_48000] = 48000,
15	[SND_DG00X_RATE_88200] = 88200,
16	[SND_DG00X_RATE_96000] = 96000,
17};
18
19/* Multi Bit Linear Audio data channels for each sampling transfer frequency. */
20const unsigned int
21snd_dg00x_stream_pcm_channels[SND_DG00X_RATE_COUNT] = {
22	/* Analog/ADAT/SPDIF */
23	[SND_DG00X_RATE_44100] = (8 + 8 + 2),
24	[SND_DG00X_RATE_48000] = (8 + 8 + 2),
25	/* Analog/SPDIF */
26	[SND_DG00X_RATE_88200] = (8 + 2),
27	[SND_DG00X_RATE_96000] = (8 + 2),
28};
29
30int snd_dg00x_stream_get_local_rate(struct snd_dg00x *dg00x, unsigned int *rate)
31{
32	u32 data;
33	__be32 reg;
34	int err;
35
36	err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
37				 DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
38				 &reg, sizeof(reg), 0);
39	if (err < 0)
40		return err;
41
42	data = be32_to_cpu(reg) & 0x0f;
43	if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
44		*rate = snd_dg00x_stream_rates[data];
45	else
46		err = -EIO;
47
48	return err;
49}
50
51int snd_dg00x_stream_set_local_rate(struct snd_dg00x *dg00x, unsigned int rate)
52{
53	__be32 reg;
54	unsigned int i;
55
56	for (i = 0; i < ARRAY_SIZE(snd_dg00x_stream_rates); i++) {
57		if (rate == snd_dg00x_stream_rates[i])
58			break;
59	}
60	if (i == ARRAY_SIZE(snd_dg00x_stream_rates))
61		return -EINVAL;
62
63	reg = cpu_to_be32(i);
64	return snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
65				  DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
66				  &reg, sizeof(reg), 0);
67}
68
69int snd_dg00x_stream_get_clock(struct snd_dg00x *dg00x,
70			       enum snd_dg00x_clock *clock)
71{
72	__be32 reg;
73	int err;
74
75	err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
76				 DG00X_ADDR_BASE + DG00X_OFFSET_CLOCK_SOURCE,
77				 &reg, sizeof(reg), 0);
78	if (err < 0)
79		return err;
80
81	*clock = be32_to_cpu(reg) & 0x0f;
82	if (*clock >= SND_DG00X_CLOCK_COUNT)
83		err = -EIO;
84
85	return err;
86}
87
88int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x, bool *detect)
89{
90	__be32 reg;
91	int err;
92
93	err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
94				 DG00X_ADDR_BASE + DG00X_OFFSET_DETECT_EXTERNAL,
95				 &reg, sizeof(reg), 0);
96	if (err >= 0)
97		*detect = be32_to_cpu(reg) > 0;
98
99	return err;
100}
101
102int snd_dg00x_stream_get_external_rate(struct snd_dg00x *dg00x,
103				       unsigned int *rate)
104{
105	u32 data;
106	__be32 reg;
107	int err;
108
109	err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
110				 DG00X_ADDR_BASE + DG00X_OFFSET_EXTERNAL_RATE,
111				 &reg, sizeof(reg), 0);
112	if (err < 0)
113		return err;
114
115	data = be32_to_cpu(reg) & 0x0f;
116	if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
117		*rate = snd_dg00x_stream_rates[data];
118	/* This means desync. */
119	else
120		err = -EBUSY;
121
122	return err;
123}
124
125static void finish_session(struct snd_dg00x *dg00x)
126{
127	__be32 data;
128
129	data = cpu_to_be32(0x00000003);
130	snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
131			   DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET,
132			   &data, sizeof(data), 0);
133
134	// Unregister isochronous channels for both direction.
135	data = 0;
136	snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
137			   DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
138			   &data, sizeof(data), 0);
139
140	// Just after finishing the session, the device may lost transmitting
141	// functionality for a short time.
142	msleep(50);
143}
144
145static int begin_session(struct snd_dg00x *dg00x)
146{
147	__be32 data;
148	u32 curr;
149	int err;
150
151	// Register isochronous channels for both direction.
152	data = cpu_to_be32((dg00x->tx_resources.channel << 16) |
153			   dg00x->rx_resources.channel);
154	err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
155				 DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
156				 &data, sizeof(data), 0);
157	if (err < 0)
158		return err;
159
160	err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
161				 DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE,
162				 &data, sizeof(data), 0);
163	if (err < 0)
164		return err;
165	curr = be32_to_cpu(data);
166
167	if (curr == 0)
168		curr = 2;
169
170	curr--;
171	while (curr > 0) {
172		data = cpu_to_be32(curr);
173		err = snd_fw_transaction(dg00x->unit,
174					 TCODE_WRITE_QUADLET_REQUEST,
175					 DG00X_ADDR_BASE +
176					 DG00X_OFFSET_STREAMING_SET,
177					 &data, sizeof(data), 0);
178		if (err < 0)
179			break;
180
181		msleep(20);
182		curr--;
183	}
184
185	return err;
186}
187
188static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream,
189			  unsigned int rate)
190{
191	struct fw_iso_resources *resources;
192	int i;
193	int err;
194
195	// Check sampling rate.
196	for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
197		if (snd_dg00x_stream_rates[i] == rate)
198			break;
199	}
200	if (i == SND_DG00X_RATE_COUNT)
201		return -EINVAL;
202
203	if (stream == &dg00x->tx_stream)
204		resources = &dg00x->tx_resources;
205	else
206		resources = &dg00x->rx_resources;
207
208	err = amdtp_dot_set_parameters(stream, rate,
209				       snd_dg00x_stream_pcm_channels[i]);
210	if (err < 0)
211		return err;
212
213	return fw_iso_resources_allocate(resources,
214				amdtp_stream_get_max_payload(stream),
215				fw_parent_device(dg00x->unit)->max_speed);
216}
217
218static int init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
219{
220	struct fw_iso_resources *resources;
221	enum amdtp_stream_direction dir;
222	int err;
223
224	if (s == &dg00x->tx_stream) {
225		resources = &dg00x->tx_resources;
226		dir = AMDTP_IN_STREAM;
227	} else {
228		resources = &dg00x->rx_resources;
229		dir = AMDTP_OUT_STREAM;
230	}
231
232	err = fw_iso_resources_init(resources, dg00x->unit);
233	if (err < 0)
234		return err;
235
236	err = amdtp_dot_init(s, dg00x->unit, dir);
237	if (err < 0)
238		fw_iso_resources_destroy(resources);
239
240	return err;
241}
242
243static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
244{
245	amdtp_stream_destroy(s);
246
247	if (s == &dg00x->tx_stream)
248		fw_iso_resources_destroy(&dg00x->tx_resources);
249	else
250		fw_iso_resources_destroy(&dg00x->rx_resources);
251}
252
253int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
254{
255	int err;
256
257	err = init_stream(dg00x, &dg00x->rx_stream);
258	if (err < 0)
259		return err;
260
261	err = init_stream(dg00x, &dg00x->tx_stream);
262	if (err < 0) {
263		destroy_stream(dg00x, &dg00x->rx_stream);
264		return err;
265	}
266
267	err = amdtp_domain_init(&dg00x->domain);
268	if (err < 0) {
269		destroy_stream(dg00x, &dg00x->rx_stream);
270		destroy_stream(dg00x, &dg00x->tx_stream);
271	}
272
273	return err;
274}
275
276/*
277 * This function should be called before starting streams or after stopping
278 * streams.
279 */
280void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
281{
282	amdtp_domain_destroy(&dg00x->domain);
283
284	destroy_stream(dg00x, &dg00x->rx_stream);
285	destroy_stream(dg00x, &dg00x->tx_stream);
286}
287
288int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
289				    unsigned int frames_per_period,
290				    unsigned int frames_per_buffer)
291{
292	unsigned int curr_rate;
293	int err;
294
295	err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
296	if (err < 0)
297		return err;
298	if (rate == 0)
299		rate = curr_rate;
300
301	if (dg00x->substreams_counter == 0 || curr_rate != rate) {
302		amdtp_domain_stop(&dg00x->domain);
303
304		finish_session(dg00x);
305
306		fw_iso_resources_free(&dg00x->tx_resources);
307		fw_iso_resources_free(&dg00x->rx_resources);
308
309		err = snd_dg00x_stream_set_local_rate(dg00x, rate);
310		if (err < 0)
311			return err;
312
313		err = keep_resources(dg00x, &dg00x->rx_stream, rate);
314		if (err < 0)
315			return err;
316
317		err = keep_resources(dg00x, &dg00x->tx_stream, rate);
318		if (err < 0) {
319			fw_iso_resources_free(&dg00x->rx_resources);
320			return err;
321		}
322
323		err = amdtp_domain_set_events_per_period(&dg00x->domain,
324					frames_per_period, frames_per_buffer);
325		if (err < 0) {
326			fw_iso_resources_free(&dg00x->rx_resources);
327			fw_iso_resources_free(&dg00x->tx_resources);
328			return err;
329		}
330	}
331
332	return 0;
333}
334
335int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
336{
337	unsigned int generation = dg00x->rx_resources.generation;
338	int err = 0;
339
340	if (dg00x->substreams_counter == 0)
341		return 0;
342
343	if (amdtp_streaming_error(&dg00x->tx_stream) ||
344	    amdtp_streaming_error(&dg00x->rx_stream)) {
345		amdtp_domain_stop(&dg00x->domain);
346		finish_session(dg00x);
347	}
348
349	if (generation != fw_parent_device(dg00x->unit)->card->generation) {
350		err = fw_iso_resources_update(&dg00x->tx_resources);
351		if (err < 0)
352			goto error;
353
354		err = fw_iso_resources_update(&dg00x->rx_resources);
355		if (err < 0)
356			goto error;
357	}
358
359	/*
360	 * No packets are transmitted without receiving packets, reagardless of
361	 * which source of clock is used.
362	 */
363	if (!amdtp_stream_running(&dg00x->rx_stream)) {
364		int spd = fw_parent_device(dg00x->unit)->max_speed;
365
366		err = begin_session(dg00x);
367		if (err < 0)
368			goto error;
369
370		err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
371					      dg00x->rx_resources.channel, spd);
372		if (err < 0)
373			goto error;
374
375		err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
376					      dg00x->tx_resources.channel, spd);
377		if (err < 0)
378			goto error;
379
380		// NOTE: The device doesn't start packet transmission till receiving any packet.
381		// It ignores presentation time expressed by the value of syt field of CIP header
382		// in received packets. The sequence of the number of data blocks per packet is
383		// important for media clock recovery.
384		err = amdtp_domain_start(&dg00x->domain, 0, true, true);
385		if (err < 0)
386			goto error;
387
388		if (!amdtp_domain_wait_ready(&dg00x->domain, READY_TIMEOUT_MS)) {
389			err = -ETIMEDOUT;
390			goto error;
391		}
392	}
393
394	return 0;
395error:
396	amdtp_domain_stop(&dg00x->domain);
397	finish_session(dg00x);
398
399	return err;
400}
401
402void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
403{
404	if (dg00x->substreams_counter == 0) {
405		amdtp_domain_stop(&dg00x->domain);
406		finish_session(dg00x);
407
408		fw_iso_resources_free(&dg00x->tx_resources);
409		fw_iso_resources_free(&dg00x->rx_resources);
410	}
411}
412
413void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)
414{
415	fw_iso_resources_update(&dg00x->tx_resources);
416	fw_iso_resources_update(&dg00x->rx_resources);
417
418	amdtp_stream_update(&dg00x->tx_stream);
419	amdtp_stream_update(&dg00x->rx_stream);
420}
421
422void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x)
423{
424	dg00x->dev_lock_changed = true;
425	wake_up(&dg00x->hwdep_wait);
426}
427
428int snd_dg00x_stream_lock_try(struct snd_dg00x *dg00x)
429{
430	int err;
431
432	spin_lock_irq(&dg00x->lock);
433
434	/* user land lock this */
435	if (dg00x->dev_lock_count < 0) {
436		err = -EBUSY;
437		goto end;
438	}
439
440	/* this is the first time */
441	if (dg00x->dev_lock_count++ == 0)
442		snd_dg00x_stream_lock_changed(dg00x);
443	err = 0;
444end:
445	spin_unlock_irq(&dg00x->lock);
446	return err;
447}
448
449void snd_dg00x_stream_lock_release(struct snd_dg00x *dg00x)
450{
451	spin_lock_irq(&dg00x->lock);
452
453	if (WARN_ON(dg00x->dev_lock_count <= 0))
454		goto end;
455	if (--dg00x->dev_lock_count == 0)
456		snd_dg00x_stream_lock_changed(dg00x);
457end:
458	spin_unlock_irq(&dg00x->lock);
459}
460