diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2019-08-04 02:21:31 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-08-05 13:57:24 -0400 |
commit | db40eeb2469fef4efe26789ea2596372ee43ae2f (patch) | |
tree | c1e1af9c6038709c4706bf45cdabb2ffbb4e9c5e | |
parent | b0db4d512941455894e7a13f71594b7d4638b94b (diff) |
ALSA: fireworks: support AMDTP domain
This commit adds AMDTP domain support for ALSA fireworks driver.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/firewire/fireworks/fireworks.h | 2 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_stream.c | 92 |
2 files changed, 51 insertions, 43 deletions
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 31efd4b53b4f..4cda297f8438 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h | |||
@@ -107,6 +107,8 @@ struct snd_efw { | |||
107 | u8 *resp_buf; | 107 | u8 *resp_buf; |
108 | u8 *pull_ptr; | 108 | u8 *pull_ptr; |
109 | u8 *push_ptr; | 109 | u8 *push_ptr; |
110 | |||
111 | struct amdtp_domain domain; | ||
110 | }; | 112 | }; |
111 | 113 | ||
112 | int snd_efw_transaction_cmd(struct fw_unit *unit, | 114 | int snd_efw_transaction_cmd(struct fw_unit *unit, |
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index af340491dc43..f2de304d2f26 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c | |||
@@ -61,17 +61,6 @@ static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) | |||
61 | return err; | 61 | return err; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void | ||
65 | stop_stream(struct snd_efw *efw, struct amdtp_stream *stream) | ||
66 | { | ||
67 | amdtp_stream_stop(stream); | ||
68 | |||
69 | if (stream == &efw->tx_stream) | ||
70 | cmp_connection_break(&efw->out_conn); | ||
71 | else | ||
72 | cmp_connection_break(&efw->in_conn); | ||
73 | } | ||
74 | |||
75 | static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, | 64 | static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, |
76 | unsigned int rate) | 65 | unsigned int rate) |
77 | { | 66 | { |
@@ -89,19 +78,13 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, | |||
89 | return err; | 78 | return err; |
90 | 79 | ||
91 | // Start amdtp stream. | 80 | // Start amdtp stream. |
92 | err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); | 81 | err = amdtp_domain_add_stream(&efw->domain, stream, |
82 | conn->resources.channel, conn->speed); | ||
93 | if (err < 0) { | 83 | if (err < 0) { |
94 | cmp_connection_break(conn); | 84 | cmp_connection_break(conn); |
95 | return err; | 85 | return err; |
96 | } | 86 | } |
97 | 87 | ||
98 | // Wait first callback. | ||
99 | if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { | ||
100 | amdtp_stream_stop(stream); | ||
101 | cmp_connection_break(conn); | ||
102 | return -ETIMEDOUT; | ||
103 | } | ||
104 | |||
105 | return 0; | 88 | return 0; |
106 | } | 89 | } |
107 | 90 | ||
@@ -155,6 +138,13 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) | |||
155 | return err; | 138 | return err; |
156 | } | 139 | } |
157 | 140 | ||
141 | err = amdtp_domain_init(&efw->domain); | ||
142 | if (err < 0) { | ||
143 | destroy_stream(efw, &efw->tx_stream); | ||
144 | destroy_stream(efw, &efw->rx_stream); | ||
145 | return err; | ||
146 | } | ||
147 | |||
158 | // set IEC61883 compliant mode (actually not fully compliant...). | 148 | // set IEC61883 compliant mode (actually not fully compliant...). |
159 | err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); | 149 | err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); |
160 | if (err < 0) { | 150 | if (err < 0) { |
@@ -209,8 +199,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) | |||
209 | if (rate == 0) | 199 | if (rate == 0) |
210 | rate = curr_rate; | 200 | rate = curr_rate; |
211 | if (rate != curr_rate) { | 201 | if (rate != curr_rate) { |
212 | stop_stream(efw, &efw->tx_stream); | 202 | amdtp_domain_stop(&efw->domain); |
213 | stop_stream(efw, &efw->rx_stream); | 203 | |
204 | cmp_connection_break(&efw->out_conn); | ||
205 | cmp_connection_break(&efw->in_conn); | ||
214 | 206 | ||
215 | cmp_connection_release(&efw->out_conn); | 207 | cmp_connection_release(&efw->out_conn); |
216 | cmp_connection_release(&efw->in_conn); | 208 | cmp_connection_release(&efw->in_conn); |
@@ -250,47 +242,57 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw) | |||
250 | if (efw->substreams_counter == 0) | 242 | if (efw->substreams_counter == 0) |
251 | return -EIO; | 243 | return -EIO; |
252 | 244 | ||
253 | err = snd_efw_command_get_sampling_rate(efw, &rate); | ||
254 | if (err < 0) | ||
255 | return err; | ||
256 | |||
257 | if (amdtp_streaming_error(&efw->rx_stream) || | 245 | if (amdtp_streaming_error(&efw->rx_stream) || |
258 | amdtp_streaming_error(&efw->tx_stream)) { | 246 | amdtp_streaming_error(&efw->tx_stream)) { |
259 | stop_stream(efw, &efw->rx_stream); | 247 | amdtp_domain_stop(&efw->domain); |
260 | stop_stream(efw, &efw->tx_stream); | 248 | cmp_connection_break(&efw->out_conn); |
249 | cmp_connection_break(&efw->in_conn); | ||
261 | } | 250 | } |
262 | 251 | ||
263 | /* master should be always running */ | 252 | err = snd_efw_command_get_sampling_rate(efw, &rate); |
253 | if (err < 0) | ||
254 | return err; | ||
255 | |||
264 | if (!amdtp_stream_running(&efw->rx_stream)) { | 256 | if (!amdtp_stream_running(&efw->rx_stream)) { |
265 | err = start_stream(efw, &efw->rx_stream, rate); | 257 | err = start_stream(efw, &efw->rx_stream, rate); |
266 | if (err < 0) { | 258 | if (err < 0) |
267 | dev_err(&efw->unit->device, | ||
268 | "fail to start AMDTP master stream:%d\n", err); | ||
269 | goto error; | 259 | goto error; |
270 | } | ||
271 | } | ||
272 | 260 | ||
273 | if (!amdtp_stream_running(&efw->tx_stream)) { | ||
274 | err = start_stream(efw, &efw->tx_stream, rate); | 261 | err = start_stream(efw, &efw->tx_stream, rate); |
275 | if (err < 0) { | 262 | if (err < 0) |
276 | dev_err(&efw->unit->device, | 263 | goto error; |
277 | "fail to start AMDTP slave stream:%d\n", err); | 264 | |
265 | err = amdtp_domain_start(&efw->domain); | ||
266 | if (err < 0) | ||
267 | goto error; | ||
268 | |||
269 | // Wait first callback. | ||
270 | if (!amdtp_stream_wait_callback(&efw->rx_stream, | ||
271 | CALLBACK_TIMEOUT) || | ||
272 | !amdtp_stream_wait_callback(&efw->tx_stream, | ||
273 | CALLBACK_TIMEOUT)) { | ||
274 | err = -ETIMEDOUT; | ||
278 | goto error; | 275 | goto error; |
279 | } | 276 | } |
280 | } | 277 | } |
281 | 278 | ||
282 | return 0; | 279 | return 0; |
283 | error: | 280 | error: |
284 | stop_stream(efw, &efw->rx_stream); | 281 | amdtp_domain_stop(&efw->domain); |
285 | stop_stream(efw, &efw->tx_stream); | 282 | |
283 | cmp_connection_break(&efw->out_conn); | ||
284 | cmp_connection_break(&efw->in_conn); | ||
285 | |||
286 | return err; | 286 | return err; |
287 | } | 287 | } |
288 | 288 | ||
289 | void snd_efw_stream_stop_duplex(struct snd_efw *efw) | 289 | void snd_efw_stream_stop_duplex(struct snd_efw *efw) |
290 | { | 290 | { |
291 | if (efw->substreams_counter == 0) { | 291 | if (efw->substreams_counter == 0) { |
292 | stop_stream(efw, &efw->tx_stream); | 292 | amdtp_domain_stop(&efw->domain); |
293 | stop_stream(efw, &efw->rx_stream); | 293 | |
294 | cmp_connection_break(&efw->out_conn); | ||
295 | cmp_connection_break(&efw->in_conn); | ||
294 | 296 | ||
295 | cmp_connection_release(&efw->out_conn); | 297 | cmp_connection_release(&efw->out_conn); |
296 | cmp_connection_release(&efw->in_conn); | 298 | cmp_connection_release(&efw->in_conn); |
@@ -299,8 +301,10 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) | |||
299 | 301 | ||
300 | void snd_efw_stream_update_duplex(struct snd_efw *efw) | 302 | void snd_efw_stream_update_duplex(struct snd_efw *efw) |
301 | { | 303 | { |
302 | stop_stream(efw, &efw->rx_stream); | 304 | amdtp_domain_stop(&efw->domain); |
303 | stop_stream(efw, &efw->tx_stream); | 305 | |
306 | cmp_connection_break(&efw->out_conn); | ||
307 | cmp_connection_break(&efw->in_conn); | ||
304 | 308 | ||
305 | amdtp_stream_pcm_abort(&efw->rx_stream); | 309 | amdtp_stream_pcm_abort(&efw->rx_stream); |
306 | amdtp_stream_pcm_abort(&efw->tx_stream); | 310 | amdtp_stream_pcm_abort(&efw->tx_stream); |
@@ -308,6 +312,8 @@ void snd_efw_stream_update_duplex(struct snd_efw *efw) | |||
308 | 312 | ||
309 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) | 313 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) |
310 | { | 314 | { |
315 | amdtp_domain_destroy(&efw->domain); | ||
316 | |||
311 | destroy_stream(efw, &efw->rx_stream); | 317 | destroy_stream(efw, &efw->rx_stream); |
312 | destroy_stream(efw, &efw->tx_stream); | 318 | destroy_stream(efw, &efw->tx_stream); |
313 | } | 319 | } |