diff options
Diffstat (limited to 'sound/firewire/dice/dice-stream.c')
-rw-r--r-- | sound/firewire/dice/dice-stream.c | 283 |
1 files changed, 215 insertions, 68 deletions
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index 928a255bfc35..c3c892c5c7ff 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c | |||
@@ -30,13 +30,43 @@ const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = { | |||
30 | [6] = 192000, | 30 | [6] = 192000, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate, | ||
34 | enum snd_dice_rate_mode *mode) | ||
35 | { | ||
36 | /* Corresponding to each entry in snd_dice_rates. */ | ||
37 | static const enum snd_dice_rate_mode modes[] = { | ||
38 | [0] = SND_DICE_RATE_MODE_LOW, | ||
39 | [1] = SND_DICE_RATE_MODE_LOW, | ||
40 | [2] = SND_DICE_RATE_MODE_LOW, | ||
41 | [3] = SND_DICE_RATE_MODE_MIDDLE, | ||
42 | [4] = SND_DICE_RATE_MODE_MIDDLE, | ||
43 | [5] = SND_DICE_RATE_MODE_HIGH, | ||
44 | [6] = SND_DICE_RATE_MODE_HIGH, | ||
45 | }; | ||
46 | int i; | ||
47 | |||
48 | for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) { | ||
49 | if (!(dice->clock_caps & BIT(i))) | ||
50 | continue; | ||
51 | if (snd_dice_rates[i] != rate) | ||
52 | continue; | ||
53 | |||
54 | *mode = modes[i]; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | return -EINVAL; | ||
59 | } | ||
60 | |||
33 | /* | 61 | /* |
34 | * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE | 62 | * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE |
35 | * to GLOBAL_STATUS. Especially, just after powering on, these are different. | 63 | * to GLOBAL_STATUS. Especially, just after powering on, these are different. |
36 | */ | 64 | */ |
37 | static int ensure_phase_lock(struct snd_dice *dice) | 65 | static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate) |
38 | { | 66 | { |
39 | __be32 reg, nominal; | 67 | __be32 reg, nominal; |
68 | u32 data; | ||
69 | int i; | ||
40 | int err; | 70 | int err; |
41 | 71 | ||
42 | err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT, | 72 | err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT, |
@@ -44,9 +74,21 @@ static int ensure_phase_lock(struct snd_dice *dice) | |||
44 | if (err < 0) | 74 | if (err < 0) |
45 | return err; | 75 | return err; |
46 | 76 | ||
77 | data = be32_to_cpu(reg); | ||
78 | |||
79 | data &= ~CLOCK_RATE_MASK; | ||
80 | for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { | ||
81 | if (snd_dice_rates[i] == rate) | ||
82 | break; | ||
83 | } | ||
84 | if (i == ARRAY_SIZE(snd_dice_rates)) | ||
85 | return -EINVAL; | ||
86 | data |= i << CLOCK_RATE_SHIFT; | ||
87 | |||
47 | if (completion_done(&dice->clock_accepted)) | 88 | if (completion_done(&dice->clock_accepted)) |
48 | reinit_completion(&dice->clock_accepted); | 89 | reinit_completion(&dice->clock_accepted); |
49 | 90 | ||
91 | reg = cpu_to_be32(data); | ||
50 | err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT, | 92 | err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT, |
51 | ®, sizeof(reg)); | 93 | ®, sizeof(reg)); |
52 | if (err < 0) | 94 | if (err < 0) |
@@ -192,6 +234,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, | |||
192 | unsigned int rate, struct reg_params *params) | 234 | unsigned int rate, struct reg_params *params) |
193 | { | 235 | { |
194 | __be32 reg[2]; | 236 | __be32 reg[2]; |
237 | enum snd_dice_rate_mode mode; | ||
195 | unsigned int i, pcm_chs, midi_ports; | 238 | unsigned int i, pcm_chs, midi_ports; |
196 | struct amdtp_stream *streams; | 239 | struct amdtp_stream *streams; |
197 | struct fw_iso_resources *resources; | 240 | struct fw_iso_resources *resources; |
@@ -206,12 +249,23 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, | |||
206 | resources = dice->rx_resources; | 249 | resources = dice->rx_resources; |
207 | } | 250 | } |
208 | 251 | ||
252 | err = snd_dice_stream_get_rate_mode(dice, rate, &mode); | ||
253 | if (err < 0) | ||
254 | return err; | ||
255 | |||
209 | for (i = 0; i < params->count; i++) { | 256 | for (i = 0; i < params->count; i++) { |
257 | unsigned int pcm_cache; | ||
258 | unsigned int midi_cache; | ||
259 | |||
210 | if (dir == AMDTP_IN_STREAM) { | 260 | if (dir == AMDTP_IN_STREAM) { |
261 | pcm_cache = dice->tx_pcm_chs[i][mode]; | ||
262 | midi_cache = dice->tx_midi_ports[i]; | ||
211 | err = snd_dice_transaction_read_tx(dice, | 263 | err = snd_dice_transaction_read_tx(dice, |
212 | params->size * i + TX_NUMBER_AUDIO, | 264 | params->size * i + TX_NUMBER_AUDIO, |
213 | reg, sizeof(reg)); | 265 | reg, sizeof(reg)); |
214 | } else { | 266 | } else { |
267 | pcm_cache = dice->rx_pcm_chs[i][mode]; | ||
268 | midi_cache = dice->rx_midi_ports[i]; | ||
215 | err = snd_dice_transaction_read_rx(dice, | 269 | err = snd_dice_transaction_read_rx(dice, |
216 | params->size * i + RX_NUMBER_AUDIO, | 270 | params->size * i + RX_NUMBER_AUDIO, |
217 | reg, sizeof(reg)); | 271 | reg, sizeof(reg)); |
@@ -221,6 +275,14 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, | |||
221 | pcm_chs = be32_to_cpu(reg[0]); | 275 | pcm_chs = be32_to_cpu(reg[0]); |
222 | midi_ports = be32_to_cpu(reg[1]); | 276 | midi_ports = be32_to_cpu(reg[1]); |
223 | 277 | ||
278 | /* These are important for developer of this driver. */ | ||
279 | if (pcm_chs != pcm_cache || midi_ports != midi_cache) { | ||
280 | dev_info(&dice->unit->device, | ||
281 | "cache mismatch: pcm: %u:%u, midi: %u:%u\n", | ||
282 | pcm_chs, pcm_cache, midi_ports, midi_cache); | ||
283 | return -EPROTO; | ||
284 | } | ||
285 | |||
224 | err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports); | 286 | err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports); |
225 | if (err < 0) | 287 | if (err < 0) |
226 | return err; | 288 | return err; |
@@ -256,6 +318,68 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, | |||
256 | return err; | 318 | return err; |
257 | } | 319 | } |
258 | 320 | ||
321 | static int start_duplex_streams(struct snd_dice *dice, unsigned int rate) | ||
322 | { | ||
323 | struct reg_params tx_params, rx_params; | ||
324 | int i; | ||
325 | int err; | ||
326 | |||
327 | err = get_register_params(dice, &tx_params, &rx_params); | ||
328 | if (err < 0) | ||
329 | return err; | ||
330 | |||
331 | /* Stop transmission. */ | ||
332 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); | ||
333 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); | ||
334 | snd_dice_transaction_clear_enable(dice); | ||
335 | release_resources(dice); | ||
336 | |||
337 | err = ensure_phase_lock(dice, rate); | ||
338 | if (err < 0) { | ||
339 | dev_err(&dice->unit->device, "fail to ensure phase lock\n"); | ||
340 | return err; | ||
341 | } | ||
342 | |||
343 | /* Likely to have changed stream formats. */ | ||
344 | err = get_register_params(dice, &tx_params, &rx_params); | ||
345 | if (err < 0) | ||
346 | return err; | ||
347 | |||
348 | /* Start both streams. */ | ||
349 | err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params); | ||
350 | if (err < 0) | ||
351 | goto error; | ||
352 | err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params); | ||
353 | if (err < 0) | ||
354 | goto error; | ||
355 | |||
356 | err = snd_dice_transaction_set_enable(dice); | ||
357 | if (err < 0) { | ||
358 | dev_err(&dice->unit->device, "fail to enable interface\n"); | ||
359 | goto error; | ||
360 | } | ||
361 | |||
362 | for (i = 0; i < MAX_STREAMS; i++) { | ||
363 | if ((i < tx_params.count && | ||
364 | !amdtp_stream_wait_callback(&dice->tx_stream[i], | ||
365 | CALLBACK_TIMEOUT)) || | ||
366 | (i < rx_params.count && | ||
367 | !amdtp_stream_wait_callback(&dice->rx_stream[i], | ||
368 | CALLBACK_TIMEOUT))) { | ||
369 | err = -ETIMEDOUT; | ||
370 | goto error; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | return 0; | ||
375 | error: | ||
376 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); | ||
377 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); | ||
378 | snd_dice_transaction_clear_enable(dice); | ||
379 | release_resources(dice); | ||
380 | return err; | ||
381 | } | ||
382 | |||
259 | /* | 383 | /* |
260 | * MEMO: After this function, there're two states of streams: | 384 | * MEMO: After this function, there're two states of streams: |
261 | * - None streams are running. | 385 | * - None streams are running. |
@@ -265,17 +389,13 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate) | |||
265 | { | 389 | { |
266 | unsigned int curr_rate; | 390 | unsigned int curr_rate; |
267 | unsigned int i; | 391 | unsigned int i; |
268 | struct reg_params tx_params, rx_params; | 392 | enum snd_dice_rate_mode mode; |
269 | bool need_to_start; | ||
270 | int err; | 393 | int err; |
271 | 394 | ||
272 | if (dice->substreams_counter == 0) | 395 | if (dice->substreams_counter == 0) |
273 | return -EIO; | 396 | return -EIO; |
274 | 397 | ||
275 | err = get_register_params(dice, &tx_params, &rx_params); | 398 | /* Check sampling transmission frequency. */ |
276 | if (err < 0) | ||
277 | return err; | ||
278 | |||
279 | err = snd_dice_transaction_get_rate(dice, &curr_rate); | 399 | err = snd_dice_transaction_get_rate(dice, &curr_rate); |
280 | if (err < 0) { | 400 | if (err < 0) { |
281 | dev_err(&dice->unit->device, | 401 | dev_err(&dice->unit->device, |
@@ -285,72 +405,36 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate) | |||
285 | if (rate == 0) | 405 | if (rate == 0) |
286 | rate = curr_rate; | 406 | rate = curr_rate; |
287 | if (rate != curr_rate) | 407 | if (rate != curr_rate) |
288 | return -EINVAL; | 408 | goto restart; |
289 | 409 | ||
290 | /* Judge to need to restart streams. */ | 410 | /* Check error of packet streaming. */ |
291 | for (i = 0; i < MAX_STREAMS; i++) { | 411 | for (i = 0; i < MAX_STREAMS; ++i) { |
292 | if (i < tx_params.count) { | 412 | if (amdtp_streaming_error(&dice->tx_stream[i])) |
293 | if (amdtp_streaming_error(&dice->tx_stream[i]) || | 413 | break; |
294 | !amdtp_stream_running(&dice->tx_stream[i])) | 414 | if (amdtp_streaming_error(&dice->rx_stream[i])) |
295 | break; | 415 | break; |
296 | } | ||
297 | if (i < rx_params.count) { | ||
298 | if (amdtp_streaming_error(&dice->rx_stream[i]) || | ||
299 | !amdtp_stream_running(&dice->rx_stream[i])) | ||
300 | break; | ||
301 | } | ||
302 | } | 416 | } |
303 | need_to_start = (i < MAX_STREAMS); | 417 | if (i < MAX_STREAMS) |
304 | 418 | goto restart; | |
305 | if (need_to_start) { | ||
306 | /* Stop transmission. */ | ||
307 | snd_dice_transaction_clear_enable(dice); | ||
308 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); | ||
309 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); | ||
310 | release_resources(dice); | ||
311 | |||
312 | err = ensure_phase_lock(dice); | ||
313 | if (err < 0) { | ||
314 | dev_err(&dice->unit->device, | ||
315 | "fail to ensure phase lock\n"); | ||
316 | return err; | ||
317 | } | ||
318 | 419 | ||
319 | /* Start both streams. */ | 420 | /* Check required streams are running or not. */ |
320 | err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params); | 421 | err = snd_dice_stream_get_rate_mode(dice, rate, &mode); |
321 | if (err < 0) | 422 | if (err < 0) |
322 | goto error; | 423 | return err; |
323 | err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params); | 424 | for (i = 0; i < MAX_STREAMS; ++i) { |
324 | if (err < 0) | 425 | if (dice->tx_pcm_chs[i][mode] > 0 && |
325 | goto error; | 426 | !amdtp_stream_running(&dice->tx_stream[i])) |
326 | 427 | break; | |
327 | err = snd_dice_transaction_set_enable(dice); | 428 | if (dice->rx_pcm_chs[i][mode] > 0 && |
328 | if (err < 0) { | 429 | !amdtp_stream_running(&dice->rx_stream[i])) |
329 | dev_err(&dice->unit->device, | 430 | break; |
330 | "fail to enable interface\n"); | ||
331 | goto error; | ||
332 | } | ||
333 | |||
334 | for (i = 0; i < MAX_STREAMS; i++) { | ||
335 | if ((i < tx_params.count && | ||
336 | !amdtp_stream_wait_callback(&dice->tx_stream[i], | ||
337 | CALLBACK_TIMEOUT)) || | ||
338 | (i < rx_params.count && | ||
339 | !amdtp_stream_wait_callback(&dice->rx_stream[i], | ||
340 | CALLBACK_TIMEOUT))) { | ||
341 | err = -ETIMEDOUT; | ||
342 | goto error; | ||
343 | } | ||
344 | } | ||
345 | } | 431 | } |
432 | if (i < MAX_STREAMS) | ||
433 | goto restart; | ||
346 | 434 | ||
347 | return err; | 435 | return 0; |
348 | error: | 436 | restart: |
349 | snd_dice_transaction_clear_enable(dice); | 437 | return start_duplex_streams(dice, rate); |
350 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); | ||
351 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); | ||
352 | release_resources(dice); | ||
353 | return err; | ||
354 | } | 438 | } |
355 | 439 | ||
356 | /* | 440 | /* |
@@ -484,6 +568,69 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice) | |||
484 | } | 568 | } |
485 | } | 569 | } |
486 | 570 | ||
571 | int snd_dice_stream_detect_current_formats(struct snd_dice *dice) | ||
572 | { | ||
573 | unsigned int rate; | ||
574 | enum snd_dice_rate_mode mode; | ||
575 | __be32 reg[2]; | ||
576 | struct reg_params tx_params, rx_params; | ||
577 | int i; | ||
578 | int err; | ||
579 | |||
580 | /* If extended protocol is available, detect detail spec. */ | ||
581 | err = snd_dice_detect_extension_formats(dice); | ||
582 | if (err >= 0) | ||
583 | return err; | ||
584 | |||
585 | /* | ||
586 | * Available stream format is restricted at current mode of sampling | ||
587 | * clock. | ||
588 | */ | ||
589 | err = snd_dice_transaction_get_rate(dice, &rate); | ||
590 | if (err < 0) | ||
591 | return err; | ||
592 | |||
593 | err = snd_dice_stream_get_rate_mode(dice, rate, &mode); | ||
594 | if (err < 0) | ||
595 | return err; | ||
596 | |||
597 | /* | ||
598 | * Just after owning the unit (GLOBAL_OWNER), the unit can return | ||
599 | * invalid stream formats. Selecting clock parameters have an effect | ||
600 | * for the unit to refine it. | ||
601 | */ | ||
602 | err = ensure_phase_lock(dice, rate); | ||
603 | if (err < 0) | ||
604 | return err; | ||
605 | |||
606 | err = get_register_params(dice, &tx_params, &rx_params); | ||
607 | if (err < 0) | ||
608 | return err; | ||
609 | |||
610 | for (i = 0; i < tx_params.count; ++i) { | ||
611 | err = snd_dice_transaction_read_tx(dice, | ||
612 | tx_params.size * i + TX_NUMBER_AUDIO, | ||
613 | reg, sizeof(reg)); | ||
614 | if (err < 0) | ||
615 | return err; | ||
616 | dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]); | ||
617 | dice->tx_midi_ports[i] = max_t(unsigned int, | ||
618 | be32_to_cpu(reg[1]), dice->tx_midi_ports[i]); | ||
619 | } | ||
620 | for (i = 0; i < rx_params.count; ++i) { | ||
621 | err = snd_dice_transaction_read_rx(dice, | ||
622 | rx_params.size * i + RX_NUMBER_AUDIO, | ||
623 | reg, sizeof(reg)); | ||
624 | if (err < 0) | ||
625 | return err; | ||
626 | dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]); | ||
627 | dice->rx_midi_ports[i] = max_t(unsigned int, | ||
628 | be32_to_cpu(reg[1]), dice->rx_midi_ports[i]); | ||
629 | } | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
487 | static void dice_lock_changed(struct snd_dice *dice) | 634 | static void dice_lock_changed(struct snd_dice *dice) |
488 | { | 635 | { |
489 | dice->dev_lock_changed = true; | 636 | dice->dev_lock_changed = true; |