1 /*
2  * motu-stream.c - a part of driver for MOTU FireWire series
3  *
4  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8 
9 #include "motu.h"
10 
11 #define	CALLBACK_TIMEOUT	200
12 
13 #define ISOC_COMM_CONTROL_OFFSET		0x0b00
14 #define  ISOC_COMM_CONTROL_MASK			0xffff0000
15 #define  CHANGE_RX_ISOC_COMM_STATE		0x80000000
16 #define  RX_ISOC_COMM_IS_ACTIVATED		0x40000000
17 #define  RX_ISOC_COMM_CHANNEL_MASK		0x3f000000
18 #define  RX_ISOC_COMM_CHANNEL_SHIFT		24
19 #define  CHANGE_TX_ISOC_COMM_STATE		0x00800000
20 #define  TX_ISOC_COMM_IS_ACTIVATED		0x00400000
21 #define  TX_ISOC_COMM_CHANNEL_MASK		0x003f0000
22 #define  TX_ISOC_COMM_CHANNEL_SHIFT		16
23 
24 #define PACKET_FORMAT_OFFSET			0x0b10
25 #define  TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS	0x00000080
26 #define  RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS	0x00000040
27 #define  TX_PACKET_TRANSMISSION_SPEED_MASK	0x0000000f
28 
29 static int start_both_streams(struct snd_motu *motu, unsigned int rate)
30 {
31 	unsigned int midi_ports = 0;
32 	__be32 reg;
33 	u32 data;
34 	int err;
35 
36 	if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
37 	    (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
38 		midi_ports = 1;
39 
40 	/* Set packet formation to our packet streaming engine. */
41 	err = amdtp_motu_set_parameters(&motu->rx_stream, rate, midi_ports,
42 					&motu->rx_packet_formats);
43 	if (err < 0)
44 		return err;
45 
46 	if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
47 	    (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
48 		midi_ports = 1;
49 	else
50 		midi_ports = 0;
51 
52 	err = amdtp_motu_set_parameters(&motu->tx_stream, rate, midi_ports,
53 					&motu->tx_packet_formats);
54 	if (err < 0)
55 		return err;
56 
57 	/* Get isochronous resources on the bus. */
58 	err = fw_iso_resources_allocate(&motu->rx_resources,
59 				amdtp_stream_get_max_payload(&motu->rx_stream),
60 				fw_parent_device(motu->unit)->max_speed);
61 	if (err < 0)
62 		return err;
63 
64 	err = fw_iso_resources_allocate(&motu->tx_resources,
65 				amdtp_stream_get_max_payload(&motu->tx_stream),
66 				fw_parent_device(motu->unit)->max_speed);
67 	if (err < 0)
68 		return err;
69 
70 	/* Configure the unit to start isochronous communication. */
71 	err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
72 					sizeof(reg));
73 	if (err < 0)
74 		return err;
75 	data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
76 
77 	data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
78 		(motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
79 		CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
80 		(motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
81 
82 	reg = cpu_to_be32(data);
83 	return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
84 					  sizeof(reg));
85 }
86 
87 static void stop_both_streams(struct snd_motu *motu)
88 {
89 	__be32 reg;
90 	u32 data;
91 	int err;
92 
93 	err = motu->spec->protocol->switch_fetching_mode(motu, false);
94 	if (err < 0)
95 		return;
96 
97 	err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
98 					sizeof(reg));
99 	if (err < 0)
100 		return;
101 	data = be32_to_cpu(reg);
102 
103 	data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
104 	data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
105 
106 	reg = cpu_to_be32(data);
107 	snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
108 				   sizeof(reg));
109 
110 	fw_iso_resources_free(&motu->tx_resources);
111 	fw_iso_resources_free(&motu->rx_resources);
112 }
113 
114 static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
115 {
116 	struct fw_iso_resources *resources;
117 	int err;
118 
119 	if (stream == &motu->rx_stream)
120 		resources = &motu->rx_resources;
121 	else
122 		resources = &motu->tx_resources;
123 
124 	err = amdtp_stream_start(stream, resources->channel,
125 				 fw_parent_device(motu->unit)->max_speed);
126 	if (err < 0)
127 		return err;
128 
129 	if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) {
130 		amdtp_stream_stop(stream);
131 		fw_iso_resources_free(resources);
132 		return -ETIMEDOUT;
133 	}
134 
135 	return 0;
136 }
137 
138 static void stop_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
139 {
140 	struct fw_iso_resources *resources;
141 
142 	if (stream == &motu->rx_stream)
143 		resources = &motu->rx_resources;
144 	else
145 		resources = &motu->tx_resources;
146 
147 	amdtp_stream_stop(stream);
148 	fw_iso_resources_free(resources);
149 }
150 
151 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
152 {
153 	int err;
154 
155 	err = motu->spec->protocol->cache_packet_formats(motu);
156 	if (err < 0)
157 		return err;
158 
159 	if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
160 		motu->tx_packet_formats.midi_flag_offset = 4;
161 		motu->tx_packet_formats.midi_byte_offset = 6;
162 	} else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
163 		motu->tx_packet_formats.midi_flag_offset = 8;
164 		motu->tx_packet_formats.midi_byte_offset = 7;
165 	}
166 
167 	if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
168 		motu->rx_packet_formats.midi_flag_offset = 4;
169 		motu->rx_packet_formats.midi_byte_offset = 6;
170 	} else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
171 		motu->rx_packet_formats.midi_flag_offset = 8;
172 		motu->rx_packet_formats.midi_byte_offset = 7;
173 	}
174 
175 	return 0;
176 }
177 
178 static int ensure_packet_formats(struct snd_motu *motu)
179 {
180 	__be32 reg;
181 	u32 data;
182 	int err;
183 
184 	err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
185 					sizeof(reg));
186 	if (err < 0)
187 		return err;
188 	data = be32_to_cpu(reg);
189 
190 	data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
191 		  RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
192 		  TX_PACKET_TRANSMISSION_SPEED_MASK);
193 	if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0)
194 		data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
195 	if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0)
196 		data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
197 	data |= fw_parent_device(motu->unit)->max_speed;
198 
199 	reg = cpu_to_be32(data);
200 	return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
201 					  sizeof(reg));
202 }
203 
204 int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate)
205 {
206 	const struct snd_motu_protocol *protocol = motu->spec->protocol;
207 	unsigned int curr_rate;
208 	int err = 0;
209 
210 	if (motu->capture_substreams == 0 && motu->playback_substreams == 0)
211 		return 0;
212 
213 	/* Some packet queueing errors. */
214 	if (amdtp_streaming_error(&motu->rx_stream) ||
215 	    amdtp_streaming_error(&motu->tx_stream)) {
216 		amdtp_stream_stop(&motu->rx_stream);
217 		amdtp_stream_stop(&motu->tx_stream);
218 		stop_both_streams(motu);
219 	}
220 
221 	err = snd_motu_stream_cache_packet_formats(motu);
222 	if (err < 0)
223 		return err;
224 
225 	/* Stop stream if rate is different. */
226 	err = protocol->get_clock_rate(motu, &curr_rate);
227 	if (err < 0) {
228 		dev_err(&motu->unit->device,
229 			"fail to get sampling rate: %d\n", err);
230 		return err;
231 	}
232 	if (rate == 0)
233 		rate = curr_rate;
234 	if (rate != curr_rate) {
235 		amdtp_stream_stop(&motu->rx_stream);
236 		amdtp_stream_stop(&motu->tx_stream);
237 		stop_both_streams(motu);
238 	}
239 
240 	if (!amdtp_stream_running(&motu->rx_stream)) {
241 		err = protocol->set_clock_rate(motu, rate);
242 		if (err < 0) {
243 			dev_err(&motu->unit->device,
244 				"fail to set sampling rate: %d\n", err);
245 			return err;
246 		}
247 
248 		err = ensure_packet_formats(motu);
249 		if (err < 0)
250 			return err;
251 
252 		err = start_both_streams(motu, rate);
253 		if (err < 0) {
254 			dev_err(&motu->unit->device,
255 				"fail to start isochronous comm: %d\n", err);
256 			goto stop_streams;
257 		}
258 
259 		err = start_isoc_ctx(motu, &motu->rx_stream);
260 		if (err < 0) {
261 			dev_err(&motu->unit->device,
262 				"fail to start IT context: %d\n", err);
263 			goto stop_streams;
264 		}
265 
266 		err = protocol->switch_fetching_mode(motu, true);
267 		if (err < 0) {
268 			dev_err(&motu->unit->device,
269 				"fail to enable frame fetching: %d\n", err);
270 			goto stop_streams;
271 		}
272 	}
273 
274 	if (!amdtp_stream_running(&motu->tx_stream) &&
275 	    motu->capture_substreams > 0) {
276 		err = start_isoc_ctx(motu, &motu->tx_stream);
277 		if (err < 0) {
278 			dev_err(&motu->unit->device,
279 				"fail to start IR context: %d", err);
280 			amdtp_stream_stop(&motu->rx_stream);
281 			goto stop_streams;
282 		}
283 	}
284 
285 	return 0;
286 
287 stop_streams:
288 	stop_both_streams(motu);
289 	return err;
290 }
291 
292 void snd_motu_stream_stop_duplex(struct snd_motu *motu)
293 {
294 	if (motu->capture_substreams == 0) {
295 		if (amdtp_stream_running(&motu->tx_stream))
296 			stop_isoc_ctx(motu, &motu->tx_stream);
297 
298 		if (motu->playback_substreams == 0) {
299 			if (amdtp_stream_running(&motu->rx_stream))
300 				stop_isoc_ctx(motu, &motu->rx_stream);
301 			stop_both_streams(motu);
302 		}
303 	}
304 }
305 
306 static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir)
307 {
308 	int err;
309 	struct amdtp_stream *stream;
310 	struct fw_iso_resources *resources;
311 
312 	if (dir == AMDTP_IN_STREAM) {
313 		stream = &motu->tx_stream;
314 		resources = &motu->tx_resources;
315 	} else {
316 		stream = &motu->rx_stream;
317 		resources = &motu->rx_resources;
318 	}
319 
320 	err = fw_iso_resources_init(resources, motu->unit);
321 	if (err < 0)
322 		return err;
323 
324 	err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol);
325 	if (err < 0) {
326 		amdtp_stream_destroy(stream);
327 		fw_iso_resources_destroy(resources);
328 	}
329 
330 	return err;
331 }
332 
333 static void destroy_stream(struct snd_motu *motu,
334 			   enum amdtp_stream_direction dir)
335 {
336 	struct amdtp_stream *stream;
337 	struct fw_iso_resources *resources;
338 
339 	if (dir == AMDTP_IN_STREAM) {
340 		stream = &motu->tx_stream;
341 		resources = &motu->tx_resources;
342 	} else {
343 		stream = &motu->rx_stream;
344 		resources = &motu->rx_resources;
345 	}
346 
347 	amdtp_stream_destroy(stream);
348 	fw_iso_resources_free(resources);
349 }
350 
351 int snd_motu_stream_init_duplex(struct snd_motu *motu)
352 {
353 	int err;
354 
355 	err = init_stream(motu, AMDTP_IN_STREAM);
356 	if (err < 0)
357 		return err;
358 
359 	err = init_stream(motu, AMDTP_OUT_STREAM);
360 	if (err < 0)
361 		destroy_stream(motu, AMDTP_IN_STREAM);
362 
363 	return err;
364 }
365 
366 /*
367  * This function should be called before starting streams or after stopping
368  * streams.
369  */
370 void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
371 {
372 	destroy_stream(motu, AMDTP_IN_STREAM);
373 	destroy_stream(motu, AMDTP_OUT_STREAM);
374 
375 	motu->playback_substreams = 0;
376 	motu->capture_substreams = 0;
377 }
378 
379 static void motu_lock_changed(struct snd_motu *motu)
380 {
381 	motu->dev_lock_changed = true;
382 	wake_up(&motu->hwdep_wait);
383 }
384 
385 int snd_motu_stream_lock_try(struct snd_motu *motu)
386 {
387 	int err;
388 
389 	spin_lock_irq(&motu->lock);
390 
391 	if (motu->dev_lock_count < 0) {
392 		err = -EBUSY;
393 		goto out;
394 	}
395 
396 	if (motu->dev_lock_count++ == 0)
397 		motu_lock_changed(motu);
398 	err = 0;
399 out:
400 	spin_unlock_irq(&motu->lock);
401 	return err;
402 }
403 
404 void snd_motu_stream_lock_release(struct snd_motu *motu)
405 {
406 	spin_lock_irq(&motu->lock);
407 
408 	if (WARN_ON(motu->dev_lock_count <= 0))
409 		goto out;
410 
411 	if (--motu->dev_lock_count == 0)
412 		motu_lock_changed(motu);
413 out:
414 	spin_unlock_irq(&motu->lock);
415 }
416