xref: /openbmc/linux/sound/firewire/dice/dice-stream.c (revision 1a4e39c2e5ca2eb494a53ecd73055562f690bca0)
1 /*
2  * dice_stream.c - a part of driver for DICE based devices
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  *
7  * Licensed under the terms of the GNU General Public License, version 2.
8  */
9 
10 #include "dice.h"
11 
12 const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
13 	/* mode 0 */
14 	[0] =  32000,
15 	[1] =  44100,
16 	[2] =  48000,
17 	/* mode 1 */
18 	[3] =  88200,
19 	[4] =  96000,
20 	/* mode 2 */
21 	[5] = 176400,
22 	[6] = 192000,
23 };
24 
25 int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
26 				  unsigned int *mode)
27 {
28 	int i;
29 
30 	for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
31 		if (!(dice->clock_caps & BIT(i)))
32 			continue;
33 		if (snd_dice_rates[i] != rate)
34 			continue;
35 
36 		*mode = (i - 1) / 2;
37 		return 0;
38 	}
39 	return -EINVAL;
40 }
41 
42 int snd_dice_stream_start_packets(struct snd_dice *dice)
43 {
44 	int err;
45 
46 	if (amdtp_stream_running(&dice->rx_stream))
47 		return 0;
48 
49 	err = amdtp_stream_start(&dice->rx_stream, dice->rx_resources.channel,
50 				 fw_parent_device(dice->unit)->max_speed);
51 	if (err < 0)
52 		return err;
53 
54 	err = snd_dice_transaction_set_enable(dice);
55 	if (err < 0) {
56 		amdtp_stream_stop(&dice->rx_stream);
57 		return err;
58 	}
59 
60 	return 0;
61 }
62 
63 int snd_dice_stream_start(struct snd_dice *dice)
64 {
65 	__be32 channel;
66 	int err;
67 
68 	if (!dice->rx_resources.allocated) {
69 		err = fw_iso_resources_allocate(&dice->rx_resources,
70 				amdtp_stream_get_max_payload(&dice->rx_stream),
71 				fw_parent_device(dice->unit)->max_speed);
72 		if (err < 0)
73 			goto error;
74 
75 		channel = cpu_to_be32(dice->rx_resources.channel);
76 		err = snd_dice_transaction_write_tx(dice, RX_ISOCHRONOUS,
77 						    &channel, 4);
78 		if (err < 0)
79 			goto err_resources;
80 	}
81 
82 	err = snd_dice_stream_start_packets(dice);
83 	if (err < 0)
84 		goto err_rx_channel;
85 
86 	return 0;
87 
88 err_rx_channel:
89 	channel = cpu_to_be32((u32)-1);
90 	snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4);
91 err_resources:
92 	fw_iso_resources_free(&dice->rx_resources);
93 error:
94 	return err;
95 }
96 
97 void snd_dice_stream_stop_packets(struct snd_dice *dice)
98 {
99 	if (!amdtp_stream_running(&dice->rx_stream))
100 		return;
101 
102 	snd_dice_transaction_clear_enable(dice);
103 	amdtp_stream_stop(&dice->rx_stream);
104 }
105 
106 void snd_dice_stream_stop(struct snd_dice *dice)
107 {
108 	__be32 channel;
109 
110 	snd_dice_stream_stop_packets(dice);
111 
112 	if (!dice->rx_resources.allocated)
113 		return;
114 
115 	channel = cpu_to_be32((u32)-1);
116 	snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4);
117 
118 	fw_iso_resources_free(&dice->rx_resources);
119 }
120 
121 int snd_dice_stream_init(struct snd_dice *dice)
122 {
123 	int err;
124 
125 	err = fw_iso_resources_init(&dice->rx_resources, dice->unit);
126 	if (err < 0)
127 		goto end;
128 	dice->rx_resources.channels_mask = 0x00000000ffffffffuLL;
129 
130 	err = amdtp_stream_init(&dice->rx_stream, dice->unit, AMDTP_OUT_STREAM,
131 				CIP_BLOCKING);
132 	if (err < 0)
133 		goto error;
134 
135 	err = snd_dice_transaction_set_clock_source(dice, CLOCK_SOURCE_ARX1);
136 	if (err < 0)
137 		goto error;
138 end:
139 	return err;
140 error:
141 	amdtp_stream_destroy(&dice->rx_stream);
142 	fw_iso_resources_destroy(&dice->rx_resources);
143 	return err;
144 }
145 
146 void snd_dice_stream_destroy(struct snd_dice *dice)
147 {
148 	amdtp_stream_pcm_abort(&dice->rx_stream);
149 	snd_dice_stream_stop(dice);
150 	amdtp_stream_destroy(&dice->rx_stream);
151 	fw_iso_resources_destroy(&dice->rx_resources);
152 }
153 
154 void snd_dice_stream_update(struct snd_dice *dice)
155 {
156 	/*
157 	 * On a bus reset, the DICE firmware disables streaming and then goes
158 	 * off contemplating its own navel for hundreds of milliseconds before
159 	 * it can react to any of our attempts to reenable streaming.  This
160 	 * means that we lose synchronization anyway, so we force our streams
161 	 * to stop so that the application can restart them in an orderly
162 	 * manner.
163 	 */
164 	dice->global_enabled = false;
165 
166 	amdtp_stream_pcm_abort(&dice->rx_stream);
167 	snd_dice_stream_stop_packets(dice);
168 	fw_iso_resources_update(&dice->rx_resources);
169 }
170 
171 static void dice_lock_changed(struct snd_dice *dice)
172 {
173 	dice->dev_lock_changed = true;
174 	wake_up(&dice->hwdep_wait);
175 }
176 
177 int snd_dice_stream_lock_try(struct snd_dice *dice)
178 {
179 	int err;
180 
181 	spin_lock_irq(&dice->lock);
182 
183 	if (dice->dev_lock_count < 0) {
184 		err = -EBUSY;
185 		goto out;
186 	}
187 
188 	if (dice->dev_lock_count++ == 0)
189 		dice_lock_changed(dice);
190 	err = 0;
191 out:
192 	spin_unlock_irq(&dice->lock);
193 	return err;
194 }
195 
196 void snd_dice_stream_lock_release(struct snd_dice *dice)
197 {
198 	spin_lock_irq(&dice->lock);
199 
200 	if (WARN_ON(dice->dev_lock_count <= 0))
201 		goto out;
202 
203 	if (--dice->dev_lock_count == 0)
204 		dice_lock_changed(dice);
205 out:
206 	spin_unlock_irq(&dice->lock);
207 }
208