xref: /linux/sound/firewire/digi00x/digi00x-stream.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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 
12 const 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. */
20 const unsigned int
21 snd_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 
snd_dg00x_stream_get_local_rate(struct snd_dg00x * dg00x,unsigned int * rate)30 int 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 
snd_dg00x_stream_set_local_rate(struct snd_dg00x * dg00x,unsigned int rate)51 int 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 
snd_dg00x_stream_get_clock(struct snd_dg00x * dg00x,enum snd_dg00x_clock * clock)69 int 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 
snd_dg00x_stream_check_external_clock(struct snd_dg00x * dg00x,bool * detect)88 int 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 
snd_dg00x_stream_get_external_rate(struct snd_dg00x * dg00x,unsigned int * rate)102 int 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 
finish_session(struct snd_dg00x * dg00x)125 static 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 
begin_session(struct snd_dg00x * dg00x)145 static 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 
keep_resources(struct snd_dg00x * dg00x,struct amdtp_stream * stream,unsigned int rate)188 static 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 
init_stream(struct snd_dg00x * dg00x,struct amdtp_stream * s)218 static 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 
destroy_stream(struct snd_dg00x * dg00x,struct amdtp_stream * s)243 static 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 
snd_dg00x_stream_init_duplex(struct snd_dg00x * dg00x)253 int 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  */
snd_dg00x_stream_destroy_duplex(struct snd_dg00x * dg00x)280 void 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 
snd_dg00x_stream_reserve_duplex(struct snd_dg00x * dg00x,unsigned int rate,unsigned int frames_per_period,unsigned int frames_per_buffer)288 int 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 
snd_dg00x_stream_start_duplex(struct snd_dg00x * dg00x)335 int 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;
395 error:
396 	amdtp_domain_stop(&dg00x->domain);
397 	finish_session(dg00x);
398 
399 	return err;
400 }
401 
snd_dg00x_stream_stop_duplex(struct snd_dg00x * dg00x)402 void 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 
snd_dg00x_stream_update_duplex(struct snd_dg00x * dg00x)413 void 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 
snd_dg00x_stream_lock_changed(struct snd_dg00x * dg00x)422 void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x)
423 {
424 	dg00x->dev_lock_changed = true;
425 	wake_up(&dg00x->hwdep_wait);
426 }
427 
snd_dg00x_stream_lock_try(struct snd_dg00x * dg00x)428 int 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;
444 end:
445 	spin_unlock_irq(&dg00x->lock);
446 	return err;
447 }
448 
snd_dg00x_stream_lock_release(struct snd_dg00x * dg00x)449 void 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);
457 end:
458 	spin_unlock_irq(&dg00x->lock);
459 }
460