1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * dice_stream.c - a part of driver for DICE based devices
4  *
5  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
6  * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
7  */
8 
9 #include "dice.h"
10 
11 #define	READY_TIMEOUT_MS	200
12 #define NOTIFICATION_TIMEOUT_MS	100
13 
14 struct reg_params {
15 	unsigned int count;
16 	unsigned int size;
17 };
18 
19 const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
20 	/* mode 0 */
21 	[0] =  32000,
22 	[1] =  44100,
23 	[2] =  48000,
24 	/* mode 1 */
25 	[3] =  88200,
26 	[4] =  96000,
27 	/* mode 2 */
28 	[5] = 176400,
29 	[6] = 192000,
30 };
31 
snd_dice_stream_get_rate_mode(struct snd_dice * dice,unsigned int rate,enum snd_dice_rate_mode * mode)32 int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
33 				  enum snd_dice_rate_mode *mode)
34 {
35 	/* Corresponding to each entry in snd_dice_rates. */
36 	static const enum snd_dice_rate_mode modes[] = {
37 		[0] = SND_DICE_RATE_MODE_LOW,
38 		[1] = SND_DICE_RATE_MODE_LOW,
39 		[2] = SND_DICE_RATE_MODE_LOW,
40 		[3] = SND_DICE_RATE_MODE_MIDDLE,
41 		[4] = SND_DICE_RATE_MODE_MIDDLE,
42 		[5] = SND_DICE_RATE_MODE_HIGH,
43 		[6] = SND_DICE_RATE_MODE_HIGH,
44 	};
45 	int i;
46 
47 	for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
48 		if (!(dice->clock_caps & BIT(i)))
49 			continue;
50 		if (snd_dice_rates[i] != rate)
51 			continue;
52 
53 		*mode = modes[i];
54 		return 0;
55 	}
56 
57 	return -EINVAL;
58 }
59 
select_clock(struct snd_dice * dice,unsigned int rate)60 static int select_clock(struct snd_dice *dice, unsigned int rate)
61 {
62 	__be32 reg;
63 	u32 data;
64 	int i;
65 	int err;
66 
67 	err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
68 					       &reg, sizeof(reg));
69 	if (err < 0)
70 		return err;
71 
72 	data = be32_to_cpu(reg);
73 
74 	data &= ~CLOCK_RATE_MASK;
75 	for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
76 		if (snd_dice_rates[i] == rate)
77 			break;
78 	}
79 	if (i == ARRAY_SIZE(snd_dice_rates))
80 		return -EINVAL;
81 	data |= i << CLOCK_RATE_SHIFT;
82 
83 	if (completion_done(&dice->clock_accepted))
84 		reinit_completion(&dice->clock_accepted);
85 
86 	reg = cpu_to_be32(data);
87 	err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
88 						&reg, sizeof(reg));
89 	if (err < 0)
90 		return err;
91 
92 	if (wait_for_completion_timeout(&dice->clock_accepted,
93 			msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0)
94 		return -ETIMEDOUT;
95 
96 	return 0;
97 }
98 
get_register_params(struct snd_dice * dice,struct reg_params * tx_params,struct reg_params * rx_params)99 static int get_register_params(struct snd_dice *dice,
100 			       struct reg_params *tx_params,
101 			       struct reg_params *rx_params)
102 {
103 	__be32 reg[2];
104 	int err;
105 
106 	err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
107 	if (err < 0)
108 		return err;
109 	tx_params->count =
110 			min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
111 	tx_params->size = be32_to_cpu(reg[1]) * 4;
112 
113 	err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
114 	if (err < 0)
115 		return err;
116 	rx_params->count =
117 			min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
118 	rx_params->size = be32_to_cpu(reg[1]) * 4;
119 
120 	return 0;
121 }
122 
release_resources(struct snd_dice * dice)123 static void release_resources(struct snd_dice *dice)
124 {
125 	int i;
126 
127 	for (i = 0; i < MAX_STREAMS; ++i) {
128 		fw_iso_resources_free(&dice->tx_resources[i]);
129 		fw_iso_resources_free(&dice->rx_resources[i]);
130 	}
131 }
132 
stop_streams(struct snd_dice * dice,enum amdtp_stream_direction dir,struct reg_params * params)133 static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
134 			 struct reg_params *params)
135 {
136 	__be32 reg;
137 	unsigned int i;
138 
139 	for (i = 0; i < params->count; i++) {
140 		reg = cpu_to_be32((u32)-1);
141 		if (dir == AMDTP_IN_STREAM) {
142 			snd_dice_transaction_write_tx(dice,
143 					params->size * i + TX_ISOCHRONOUS,
144 					&reg, sizeof(reg));
145 		} else {
146 			snd_dice_transaction_write_rx(dice,
147 					params->size * i + RX_ISOCHRONOUS,
148 					&reg, sizeof(reg));
149 		}
150 	}
151 }
152 
keep_resources(struct snd_dice * dice,struct amdtp_stream * stream,struct fw_iso_resources * resources,unsigned int rate,unsigned int pcm_chs,unsigned int midi_ports)153 static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
154 			  struct fw_iso_resources *resources, unsigned int rate,
155 			  unsigned int pcm_chs, unsigned int midi_ports)
156 {
157 	bool double_pcm_frames;
158 	unsigned int i;
159 	int err;
160 
161 	// At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
162 	// one data block of AMDTP packet. Thus sampling transfer frequency is
163 	// a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
164 	// transferred on AMDTP packets at 96 kHz. Two successive samples of a
165 	// channel are stored consecutively in the packet. This quirk is called
166 	// as 'Dual Wire'.
167 	// For this quirk, blocking mode is required and PCM buffer size should
168 	// be aligned to SYT_INTERVAL.
169 	double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
170 	if (double_pcm_frames) {
171 		rate /= 2;
172 		pcm_chs *= 2;
173 	}
174 
175 	err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
176 					 double_pcm_frames);
177 	if (err < 0)
178 		return err;
179 
180 	if (double_pcm_frames) {
181 		pcm_chs /= 2;
182 
183 		for (i = 0; i < pcm_chs; i++) {
184 			amdtp_am824_set_pcm_position(stream, i, i * 2);
185 			amdtp_am824_set_pcm_position(stream, i + pcm_chs,
186 						     i * 2 + 1);
187 		}
188 	}
189 
190 	return fw_iso_resources_allocate(resources,
191 				amdtp_stream_get_max_payload(stream),
192 				fw_parent_device(dice->unit)->max_speed);
193 }
194 
keep_dual_resources(struct snd_dice * dice,unsigned int rate,enum amdtp_stream_direction dir,struct reg_params * params)195 static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
196 			       enum amdtp_stream_direction dir,
197 			       struct reg_params *params)
198 {
199 	enum snd_dice_rate_mode mode;
200 	int i;
201 	int err;
202 
203 	err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
204 	if (err < 0)
205 		return err;
206 
207 	for (i = 0; i < params->count; ++i) {
208 		__be32 reg[2];
209 		struct amdtp_stream *stream;
210 		struct fw_iso_resources *resources;
211 		unsigned int pcm_cache;
212 		unsigned int pcm_chs;
213 		unsigned int midi_ports;
214 
215 		if (dir == AMDTP_IN_STREAM) {
216 			stream = &dice->tx_stream[i];
217 			resources = &dice->tx_resources[i];
218 
219 			pcm_cache = dice->tx_pcm_chs[i][mode];
220 			err = snd_dice_transaction_read_tx(dice,
221 					params->size * i + TX_NUMBER_AUDIO,
222 					reg, sizeof(reg));
223 		} else {
224 			stream = &dice->rx_stream[i];
225 			resources = &dice->rx_resources[i];
226 
227 			pcm_cache = dice->rx_pcm_chs[i][mode];
228 			err = snd_dice_transaction_read_rx(dice,
229 					params->size * i + RX_NUMBER_AUDIO,
230 					reg, sizeof(reg));
231 		}
232 		if (err < 0)
233 			return err;
234 		pcm_chs = be32_to_cpu(reg[0]);
235 		midi_ports = be32_to_cpu(reg[1]);
236 
237 		// These are important for developer of this driver.
238 		if (pcm_chs != pcm_cache) {
239 			dev_info(&dice->unit->device,
240 				 "cache mismatch: pcm: %u:%u, midi: %u\n",
241 				 pcm_chs, pcm_cache, midi_ports);
242 			return -EPROTO;
243 		}
244 
245 		err = keep_resources(dice, stream, resources, rate, pcm_chs,
246 				     midi_ports);
247 		if (err < 0)
248 			return err;
249 	}
250 
251 	return 0;
252 }
253 
finish_session(struct snd_dice * dice,struct reg_params * tx_params,struct reg_params * rx_params)254 static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
255 			   struct reg_params *rx_params)
256 {
257 	stop_streams(dice, AMDTP_IN_STREAM, tx_params);
258 	stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
259 
260 	snd_dice_transaction_clear_enable(dice);
261 }
262 
snd_dice_stream_reserve_duplex(struct snd_dice * dice,unsigned int rate,unsigned int events_per_period,unsigned int events_per_buffer)263 int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
264 				   unsigned int events_per_period,
265 				   unsigned int events_per_buffer)
266 {
267 	unsigned int curr_rate;
268 	int err;
269 
270 	// Check sampling transmission frequency.
271 	err = snd_dice_transaction_get_rate(dice, &curr_rate);
272 	if (err < 0)
273 		return err;
274 	if (rate == 0)
275 		rate = curr_rate;
276 
277 	if (dice->substreams_counter == 0 || curr_rate != rate) {
278 		struct reg_params tx_params, rx_params;
279 
280 		amdtp_domain_stop(&dice->domain);
281 
282 		err = get_register_params(dice, &tx_params, &rx_params);
283 		if (err < 0)
284 			return err;
285 		finish_session(dice, &tx_params, &rx_params);
286 
287 		release_resources(dice);
288 
289 		// Just after owning the unit (GLOBAL_OWNER), the unit can
290 		// return invalid stream formats. Selecting clock parameters
291 		// have an effect for the unit to refine it.
292 		err = select_clock(dice, rate);
293 		if (err < 0)
294 			return err;
295 
296 		// After changing sampling transfer frequency, the value of
297 		// register can be changed.
298 		err = get_register_params(dice, &tx_params, &rx_params);
299 		if (err < 0)
300 			return err;
301 
302 		err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
303 					  &tx_params);
304 		if (err < 0)
305 			goto error;
306 
307 		err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
308 					  &rx_params);
309 		if (err < 0)
310 			goto error;
311 
312 		err = amdtp_domain_set_events_per_period(&dice->domain,
313 					events_per_period, events_per_buffer);
314 		if (err < 0)
315 			goto error;
316 	}
317 
318 	return 0;
319 error:
320 	release_resources(dice);
321 	return err;
322 }
323 
start_streams(struct snd_dice * dice,enum amdtp_stream_direction dir,unsigned int rate,struct reg_params * params)324 static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
325 			 unsigned int rate, struct reg_params *params)
326 {
327 	unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
328 	int i;
329 	int err;
330 
331 	for (i = 0; i < params->count; i++) {
332 		struct amdtp_stream *stream;
333 		struct fw_iso_resources *resources;
334 		__be32 reg;
335 
336 		if (dir == AMDTP_IN_STREAM) {
337 			stream = dice->tx_stream + i;
338 			resources = dice->tx_resources + i;
339 		} else {
340 			stream = dice->rx_stream + i;
341 			resources = dice->rx_resources + i;
342 		}
343 
344 		reg = cpu_to_be32(resources->channel);
345 		if (dir == AMDTP_IN_STREAM) {
346 			err = snd_dice_transaction_write_tx(dice,
347 					params->size * i + TX_ISOCHRONOUS,
348 					&reg, sizeof(reg));
349 		} else {
350 			err = snd_dice_transaction_write_rx(dice,
351 					params->size * i + RX_ISOCHRONOUS,
352 					&reg, sizeof(reg));
353 		}
354 		if (err < 0)
355 			return err;
356 
357 		if (dir == AMDTP_IN_STREAM) {
358 			reg = cpu_to_be32(max_speed);
359 			err = snd_dice_transaction_write_tx(dice,
360 					params->size * i + TX_SPEED,
361 					&reg, sizeof(reg));
362 			if (err < 0)
363 				return err;
364 		}
365 
366 		err = amdtp_domain_add_stream(&dice->domain, stream,
367 					      resources->channel, max_speed);
368 		if (err < 0)
369 			return err;
370 	}
371 
372 	return 0;
373 }
374 
375 /*
376  * MEMO: After this function, there're two states of streams:
377  *  - None streams are running.
378  *  - All streams are running.
379  */
snd_dice_stream_start_duplex(struct snd_dice * dice)380 int snd_dice_stream_start_duplex(struct snd_dice *dice)
381 {
382 	unsigned int generation = dice->rx_resources[0].generation;
383 	struct reg_params tx_params, rx_params;
384 	unsigned int i;
385 	unsigned int rate;
386 	enum snd_dice_rate_mode mode;
387 	int err;
388 
389 	if (dice->substreams_counter == 0)
390 		return -EIO;
391 
392 	err = get_register_params(dice, &tx_params, &rx_params);
393 	if (err < 0)
394 		return err;
395 
396 	// Check error of packet streaming.
397 	for (i = 0; i < MAX_STREAMS; ++i) {
398 		if (amdtp_streaming_error(&dice->tx_stream[i]) ||
399 		    amdtp_streaming_error(&dice->rx_stream[i])) {
400 			amdtp_domain_stop(&dice->domain);
401 			finish_session(dice, &tx_params, &rx_params);
402 			break;
403 		}
404 	}
405 
406 	if (generation != fw_parent_device(dice->unit)->card->generation) {
407 		for (i = 0; i < MAX_STREAMS; ++i) {
408 			if (i < tx_params.count)
409 				fw_iso_resources_update(dice->tx_resources + i);
410 			if (i < rx_params.count)
411 				fw_iso_resources_update(dice->rx_resources + i);
412 		}
413 	}
414 
415 	// Check required streams are running or not.
416 	err = snd_dice_transaction_get_rate(dice, &rate);
417 	if (err < 0)
418 		return err;
419 	err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
420 	if (err < 0)
421 		return err;
422 	for (i = 0; i < MAX_STREAMS; ++i) {
423 		if (dice->tx_pcm_chs[i][mode] > 0 &&
424 		    !amdtp_stream_running(&dice->tx_stream[i]))
425 			break;
426 		if (dice->rx_pcm_chs[i][mode] > 0 &&
427 		    !amdtp_stream_running(&dice->rx_stream[i]))
428 			break;
429 	}
430 	if (i < MAX_STREAMS) {
431 		// Start both streams.
432 		err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
433 		if (err < 0)
434 			goto error;
435 
436 		err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
437 		if (err < 0)
438 			goto error;
439 
440 		err = snd_dice_transaction_set_enable(dice);
441 		if (err < 0) {
442 			dev_err(&dice->unit->device,
443 				"fail to enable interface\n");
444 			goto error;
445 		}
446 
447 		// MEMO: The device immediately starts packet transmission when enabled. Some
448 		// devices are strictly to generate any discontinuity in the sequence of tx packet
449 		// when they receives invalid sequence of presentation time in CIP header. The
450 		// sequence replay for media clock recovery can suppress the behaviour.
451 		err = amdtp_domain_start(&dice->domain, 0, true, false);
452 		if (err < 0)
453 			goto error;
454 
455 		if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) {
456 			err = -ETIMEDOUT;
457 			goto error;
458 		}
459 	}
460 
461 	return 0;
462 error:
463 	amdtp_domain_stop(&dice->domain);
464 	finish_session(dice, &tx_params, &rx_params);
465 	return err;
466 }
467 
468 /*
469  * MEMO: After this function, there're two states of streams:
470  *  - None streams are running.
471  *  - All streams are running.
472  */
snd_dice_stream_stop_duplex(struct snd_dice * dice)473 void snd_dice_stream_stop_duplex(struct snd_dice *dice)
474 {
475 	struct reg_params tx_params, rx_params;
476 
477 	if (dice->substreams_counter == 0) {
478 		if (get_register_params(dice, &tx_params, &rx_params) >= 0)
479 			finish_session(dice, &tx_params, &rx_params);
480 
481 		amdtp_domain_stop(&dice->domain);
482 		release_resources(dice);
483 	}
484 }
485 
init_stream(struct snd_dice * dice,enum amdtp_stream_direction dir,unsigned int index)486 static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
487 		       unsigned int index)
488 {
489 	struct amdtp_stream *stream;
490 	struct fw_iso_resources *resources;
491 	int err;
492 
493 	if (dir == AMDTP_IN_STREAM) {
494 		stream = &dice->tx_stream[index];
495 		resources = &dice->tx_resources[index];
496 	} else {
497 		stream = &dice->rx_stream[index];
498 		resources = &dice->rx_resources[index];
499 	}
500 
501 	err = fw_iso_resources_init(resources, dice->unit);
502 	if (err < 0)
503 		goto end;
504 	resources->channels_mask = 0x00000000ffffffffuLL;
505 
506 	err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
507 	if (err < 0) {
508 		amdtp_stream_destroy(stream);
509 		fw_iso_resources_destroy(resources);
510 	}
511 end:
512 	return err;
513 }
514 
515 /*
516  * This function should be called before starting streams or after stopping
517  * streams.
518  */
destroy_stream(struct snd_dice * dice,enum amdtp_stream_direction dir,unsigned int index)519 static void destroy_stream(struct snd_dice *dice,
520 			   enum amdtp_stream_direction dir,
521 			   unsigned int index)
522 {
523 	struct amdtp_stream *stream;
524 	struct fw_iso_resources *resources;
525 
526 	if (dir == AMDTP_IN_STREAM) {
527 		stream = &dice->tx_stream[index];
528 		resources = &dice->tx_resources[index];
529 	} else {
530 		stream = &dice->rx_stream[index];
531 		resources = &dice->rx_resources[index];
532 	}
533 
534 	amdtp_stream_destroy(stream);
535 	fw_iso_resources_destroy(resources);
536 }
537 
snd_dice_stream_init_duplex(struct snd_dice * dice)538 int snd_dice_stream_init_duplex(struct snd_dice *dice)
539 {
540 	int i, err;
541 
542 	for (i = 0; i < MAX_STREAMS; i++) {
543 		err = init_stream(dice, AMDTP_IN_STREAM, i);
544 		if (err < 0) {
545 			for (; i >= 0; i--)
546 				destroy_stream(dice, AMDTP_IN_STREAM, i);
547 			goto end;
548 		}
549 	}
550 
551 	for (i = 0; i < MAX_STREAMS; i++) {
552 		err = init_stream(dice, AMDTP_OUT_STREAM, i);
553 		if (err < 0) {
554 			for (; i >= 0; i--)
555 				destroy_stream(dice, AMDTP_OUT_STREAM, i);
556 			for (i = 0; i < MAX_STREAMS; i++)
557 				destroy_stream(dice, AMDTP_IN_STREAM, i);
558 			goto end;
559 		}
560 	}
561 
562 	err = amdtp_domain_init(&dice->domain);
563 	if (err < 0) {
564 		for (i = 0; i < MAX_STREAMS; ++i) {
565 			destroy_stream(dice, AMDTP_OUT_STREAM, i);
566 			destroy_stream(dice, AMDTP_IN_STREAM, i);
567 		}
568 	}
569 end:
570 	return err;
571 }
572 
snd_dice_stream_destroy_duplex(struct snd_dice * dice)573 void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
574 {
575 	unsigned int i;
576 
577 	for (i = 0; i < MAX_STREAMS; i++) {
578 		destroy_stream(dice, AMDTP_IN_STREAM, i);
579 		destroy_stream(dice, AMDTP_OUT_STREAM, i);
580 	}
581 
582 	amdtp_domain_destroy(&dice->domain);
583 }
584 
snd_dice_stream_update_duplex(struct snd_dice * dice)585 void snd_dice_stream_update_duplex(struct snd_dice *dice)
586 {
587 	struct reg_params tx_params, rx_params;
588 
589 	/*
590 	 * On a bus reset, the DICE firmware disables streaming and then goes
591 	 * off contemplating its own navel for hundreds of milliseconds before
592 	 * it can react to any of our attempts to reenable streaming.  This
593 	 * means that we lose synchronization anyway, so we force our streams
594 	 * to stop so that the application can restart them in an orderly
595 	 * manner.
596 	 */
597 	dice->global_enabled = false;
598 
599 	if (get_register_params(dice, &tx_params, &rx_params) == 0) {
600 		amdtp_domain_stop(&dice->domain);
601 
602 		stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
603 		stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
604 	}
605 }
606 
snd_dice_stream_detect_current_formats(struct snd_dice * dice)607 int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
608 {
609 	unsigned int rate;
610 	enum snd_dice_rate_mode mode;
611 	__be32 reg[2];
612 	struct reg_params tx_params, rx_params;
613 	int i;
614 	int err;
615 
616 	/* If extended protocol is available, detect detail spec. */
617 	err = snd_dice_detect_extension_formats(dice);
618 	if (err >= 0)
619 		return err;
620 
621 	/*
622 	 * Available stream format is restricted at current mode of sampling
623 	 * clock.
624 	 */
625 	err = snd_dice_transaction_get_rate(dice, &rate);
626 	if (err < 0)
627 		return err;
628 
629 	err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
630 	if (err < 0)
631 		return err;
632 
633 	/*
634 	 * Just after owning the unit (GLOBAL_OWNER), the unit can return
635 	 * invalid stream formats. Selecting clock parameters have an effect
636 	 * for the unit to refine it.
637 	 */
638 	err = select_clock(dice, rate);
639 	if (err < 0)
640 		return err;
641 
642 	err = get_register_params(dice, &tx_params, &rx_params);
643 	if (err < 0)
644 		return err;
645 
646 	for (i = 0; i < tx_params.count; ++i) {
647 		err = snd_dice_transaction_read_tx(dice,
648 				tx_params.size * i + TX_NUMBER_AUDIO,
649 				reg, sizeof(reg));
650 		if (err < 0)
651 			return err;
652 		dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
653 		dice->tx_midi_ports[i] = max_t(unsigned int,
654 				be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
655 	}
656 	for (i = 0; i < rx_params.count; ++i) {
657 		err = snd_dice_transaction_read_rx(dice,
658 				rx_params.size * i + RX_NUMBER_AUDIO,
659 				reg, sizeof(reg));
660 		if (err < 0)
661 			return err;
662 		dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
663 		dice->rx_midi_ports[i] = max_t(unsigned int,
664 				be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
665 	}
666 
667 	return 0;
668 }
669 
dice_lock_changed(struct snd_dice * dice)670 static void dice_lock_changed(struct snd_dice *dice)
671 {
672 	dice->dev_lock_changed = true;
673 	wake_up(&dice->hwdep_wait);
674 }
675 
snd_dice_stream_lock_try(struct snd_dice * dice)676 int snd_dice_stream_lock_try(struct snd_dice *dice)
677 {
678 	int err;
679 
680 	spin_lock_irq(&dice->lock);
681 
682 	if (dice->dev_lock_count < 0) {
683 		err = -EBUSY;
684 		goto out;
685 	}
686 
687 	if (dice->dev_lock_count++ == 0)
688 		dice_lock_changed(dice);
689 	err = 0;
690 out:
691 	spin_unlock_irq(&dice->lock);
692 	return err;
693 }
694 
snd_dice_stream_lock_release(struct snd_dice * dice)695 void snd_dice_stream_lock_release(struct snd_dice *dice)
696 {
697 	spin_lock_irq(&dice->lock);
698 
699 	if (WARN_ON(dice->dev_lock_count <= 0))
700 		goto out;
701 
702 	if (--dice->dev_lock_count == 0)
703 		dice_lock_changed(dice);
704 out:
705 	spin_unlock_irq(&dice->lock);
706 }
707