2 * ff-stream.c - a part of driver for RME Fireface series
4 * Copyright (c) 2015-2017 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
11 #define CALLBACK_TIMEOUT_MS 200
13 static int get_rate_mode(unsigned int rate
, unsigned int *mode
)
17 for (i
= 0; i
< CIP_SFC_COUNT
; i
++) {
18 if (amdtp_rate_table
[i
] == rate
)
22 if (i
== CIP_SFC_COUNT
)
25 *mode
= ((int)i
- 1) / 2;
31 * Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
32 * we can allocate between 0 and 7 channel.
34 static int keep_resources(struct snd_ff
*ff
, unsigned int rate
)
39 err
= get_rate_mode(rate
, &mode
);
43 /* Keep resources for in-stream. */
44 err
= amdtp_ff_set_parameters(&ff
->tx_stream
, rate
,
45 ff
->spec
->pcm_capture_channels
[mode
]);
48 ff
->tx_resources
.channels_mask
= 0x00000000000000ffuLL
;
49 err
= fw_iso_resources_allocate(&ff
->tx_resources
,
50 amdtp_stream_get_max_payload(&ff
->tx_stream
),
51 fw_parent_device(ff
->unit
)->max_speed
);
55 /* Keep resources for out-stream. */
56 err
= amdtp_ff_set_parameters(&ff
->rx_stream
, rate
,
57 ff
->spec
->pcm_playback_channels
[mode
]);
60 ff
->rx_resources
.channels_mask
= 0x00000000000000ffuLL
;
61 err
= fw_iso_resources_allocate(&ff
->rx_resources
,
62 amdtp_stream_get_max_payload(&ff
->rx_stream
),
63 fw_parent_device(ff
->unit
)->max_speed
);
65 fw_iso_resources_free(&ff
->tx_resources
);
70 static void release_resources(struct snd_ff
*ff
)
72 fw_iso_resources_free(&ff
->tx_resources
);
73 fw_iso_resources_free(&ff
->rx_resources
);
76 static inline void finish_session(struct snd_ff
*ff
)
78 ff
->spec
->protocol
->finish_session(ff
);
79 ff
->spec
->protocol
->switch_fetching_mode(ff
, false);
82 static int init_stream(struct snd_ff
*ff
, enum amdtp_stream_direction dir
)
85 struct fw_iso_resources
*resources
;
86 struct amdtp_stream
*stream
;
88 if (dir
== AMDTP_IN_STREAM
) {
89 resources
= &ff
->tx_resources
;
90 stream
= &ff
->tx_stream
;
92 resources
= &ff
->rx_resources
;
93 stream
= &ff
->rx_stream
;
96 err
= fw_iso_resources_init(resources
, ff
->unit
);
100 err
= amdtp_ff_init(stream
, ff
->unit
, dir
);
102 fw_iso_resources_destroy(resources
);
107 static void destroy_stream(struct snd_ff
*ff
, enum amdtp_stream_direction dir
)
109 if (dir
== AMDTP_IN_STREAM
) {
110 amdtp_stream_destroy(&ff
->tx_stream
);
111 fw_iso_resources_destroy(&ff
->tx_resources
);
113 amdtp_stream_destroy(&ff
->rx_stream
);
114 fw_iso_resources_destroy(&ff
->rx_resources
);
118 int snd_ff_stream_init_duplex(struct snd_ff
*ff
)
122 err
= init_stream(ff
, AMDTP_OUT_STREAM
);
126 err
= init_stream(ff
, AMDTP_IN_STREAM
);
128 destroy_stream(ff
, AMDTP_OUT_STREAM
);
134 * This function should be called before starting streams or after stopping
137 void snd_ff_stream_destroy_duplex(struct snd_ff
*ff
)
139 destroy_stream(ff
, AMDTP_IN_STREAM
);
140 destroy_stream(ff
, AMDTP_OUT_STREAM
);
143 int snd_ff_stream_start_duplex(struct snd_ff
*ff
, unsigned int rate
)
145 unsigned int curr_rate
;
146 enum snd_ff_clock_src src
;
149 if (ff
->substreams_counter
== 0)
152 err
= ff
->spec
->protocol
->get_clock(ff
, &curr_rate
, &src
);
155 if (curr_rate
!= rate
||
156 amdtp_streaming_error(&ff
->tx_stream
) ||
157 amdtp_streaming_error(&ff
->rx_stream
)) {
160 amdtp_stream_stop(&ff
->tx_stream
);
161 amdtp_stream_stop(&ff
->rx_stream
);
163 release_resources(ff
);
167 * Regardless of current source of clock signal, drivers transfer some
168 * packets. Then, the device transfers packets.
170 if (!amdtp_stream_running(&ff
->rx_stream
)) {
171 err
= keep_resources(ff
, rate
);
175 err
= ff
->spec
->protocol
->begin_session(ff
, rate
);
179 err
= amdtp_stream_start(&ff
->rx_stream
,
180 ff
->rx_resources
.channel
,
181 fw_parent_device(ff
->unit
)->max_speed
);
185 if (!amdtp_stream_wait_callback(&ff
->rx_stream
,
186 CALLBACK_TIMEOUT_MS
)) {
191 err
= ff
->spec
->protocol
->switch_fetching_mode(ff
, true);
196 if (!amdtp_stream_running(&ff
->tx_stream
)) {
197 err
= amdtp_stream_start(&ff
->tx_stream
,
198 ff
->tx_resources
.channel
,
199 fw_parent_device(ff
->unit
)->max_speed
);
203 if (!amdtp_stream_wait_callback(&ff
->tx_stream
,
204 CALLBACK_TIMEOUT_MS
)) {
212 amdtp_stream_stop(&ff
->tx_stream
);
213 amdtp_stream_stop(&ff
->rx_stream
);
216 release_resources(ff
);
221 void snd_ff_stream_stop_duplex(struct snd_ff
*ff
)
223 if (ff
->substreams_counter
> 0)
226 amdtp_stream_stop(&ff
->tx_stream
);
227 amdtp_stream_stop(&ff
->rx_stream
);
229 release_resources(ff
);
232 void snd_ff_stream_update_duplex(struct snd_ff
*ff
)
234 /* The device discontinue to transfer packets. */
235 amdtp_stream_pcm_abort(&ff
->tx_stream
);
236 amdtp_stream_stop(&ff
->tx_stream
);
238 amdtp_stream_pcm_abort(&ff
->rx_stream
);
239 amdtp_stream_stop(&ff
->rx_stream
);
241 fw_iso_resources_update(&ff
->tx_resources
);
242 fw_iso_resources_update(&ff
->rx_resources
);
245 void snd_ff_stream_lock_changed(struct snd_ff
*ff
)
247 ff
->dev_lock_changed
= true;
248 wake_up(&ff
->hwdep_wait
);
251 int snd_ff_stream_lock_try(struct snd_ff
*ff
)
255 spin_lock_irq(&ff
->lock
);
257 /* user land lock this */
258 if (ff
->dev_lock_count
< 0) {
263 /* this is the first time */
264 if (ff
->dev_lock_count
++ == 0)
265 snd_ff_stream_lock_changed(ff
);
268 spin_unlock_irq(&ff
->lock
);
272 void snd_ff_stream_lock_release(struct snd_ff
*ff
)
274 spin_lock_irq(&ff
->lock
);
276 if (WARN_ON(ff
->dev_lock_count
<= 0))
278 if (--ff
->dev_lock_count
== 0)
279 snd_ff_stream_lock_changed(ff
);
281 spin_unlock_irq(&ff
->lock
);