summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2019-08-04 02:21:31 -0400
committerTakashi Iwai <tiwai@suse.de>2019-08-05 13:57:24 -0400
commitdb40eeb2469fef4efe26789ea2596372ee43ae2f (patch)
treec1e1af9c6038709c4706bf45cdabb2ffbb4e9c5e
parentb0db4d512941455894e7a13f71594b7d4638b94b (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.h2
-rw-r--r--sound/firewire/fireworks/fireworks_stream.c92
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
112int snd_efw_transaction_cmd(struct fw_unit *unit, 114int 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
64static void
65stop_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
75static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, 64static 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;
283error: 280error:
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
289void snd_efw_stream_stop_duplex(struct snd_efw *efw) 289void 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
300void snd_efw_stream_update_duplex(struct snd_efw *efw) 302void 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
309void snd_efw_stream_destroy_duplex(struct snd_efw *efw) 313void 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}