diff options
-rw-r--r-- | sound/firewire/amdtp-stream.c | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 3468419259a0..f1ebb7b468cf 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c | |||
@@ -447,17 +447,18 @@ static int handle_out_packet(struct amdtp_stream *s, unsigned int data_blocks, | |||
447 | } | 447 | } |
448 | 448 | ||
449 | static int handle_in_packet(struct amdtp_stream *s, | 449 | static int handle_in_packet(struct amdtp_stream *s, |
450 | unsigned int payload_quadlets, __be32 *buffer, | 450 | unsigned int payload_quadlets, unsigned int cycle) |
451 | unsigned int *data_blocks, unsigned int cycle, | ||
452 | unsigned int syt) | ||
453 | { | 451 | { |
452 | __be32 *buffer; | ||
454 | u32 cip_header[2]; | 453 | u32 cip_header[2]; |
455 | unsigned int fmt, fdf; | 454 | unsigned int fmt, fdf, syt; |
456 | unsigned int data_block_quadlets, data_block_counter, dbc_interval; | 455 | unsigned int data_block_quadlets, data_block_counter, dbc_interval; |
456 | unsigned int data_blocks; | ||
457 | struct snd_pcm_substream *pcm; | 457 | struct snd_pcm_substream *pcm; |
458 | unsigned int pcm_frames; | 458 | unsigned int pcm_frames; |
459 | bool lost; | 459 | bool lost; |
460 | 460 | ||
461 | buffer = s->buffer.packets[s->packet_index].buffer; | ||
461 | cip_header[0] = be32_to_cpu(buffer[0]); | 462 | cip_header[0] = be32_to_cpu(buffer[0]); |
462 | cip_header[1] = be32_to_cpu(buffer[1]); | 463 | cip_header[1] = be32_to_cpu(buffer[1]); |
463 | 464 | ||
@@ -472,7 +473,7 @@ static int handle_in_packet(struct amdtp_stream *s, | |||
472 | dev_info_ratelimited(&s->unit->device, | 473 | dev_info_ratelimited(&s->unit->device, |
473 | "Invalid CIP header for AMDTP: %08X:%08X\n", | 474 | "Invalid CIP header for AMDTP: %08X:%08X\n", |
474 | cip_header[0], cip_header[1]); | 475 | cip_header[0], cip_header[1]); |
475 | *data_blocks = 0; | 476 | data_blocks = 0; |
476 | pcm_frames = 0; | 477 | pcm_frames = 0; |
477 | goto end; | 478 | goto end; |
478 | } | 479 | } |
@@ -483,7 +484,7 @@ static int handle_in_packet(struct amdtp_stream *s, | |||
483 | dev_info_ratelimited(&s->unit->device, | 484 | dev_info_ratelimited(&s->unit->device, |
484 | "Detect unexpected protocol: %08x %08x\n", | 485 | "Detect unexpected protocol: %08x %08x\n", |
485 | cip_header[0], cip_header[1]); | 486 | cip_header[0], cip_header[1]); |
486 | *data_blocks = 0; | 487 | data_blocks = 0; |
487 | pcm_frames = 0; | 488 | pcm_frames = 0; |
488 | goto end; | 489 | goto end; |
489 | } | 490 | } |
@@ -492,7 +493,7 @@ static int handle_in_packet(struct amdtp_stream *s, | |||
492 | fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT; | 493 | fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT; |
493 | if (payload_quadlets < 3 || | 494 | if (payload_quadlets < 3 || |
494 | (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { | 495 | (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { |
495 | *data_blocks = 0; | 496 | data_blocks = 0; |
496 | } else { | 497 | } else { |
497 | data_block_quadlets = | 498 | data_block_quadlets = |
498 | (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; | 499 | (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; |
@@ -506,12 +507,12 @@ static int handle_in_packet(struct amdtp_stream *s, | |||
506 | if (s->flags & CIP_WRONG_DBS) | 507 | if (s->flags & CIP_WRONG_DBS) |
507 | data_block_quadlets = s->data_block_quadlets; | 508 | data_block_quadlets = s->data_block_quadlets; |
508 | 509 | ||
509 | *data_blocks = (payload_quadlets - 2) / data_block_quadlets; | 510 | data_blocks = (payload_quadlets - 2) / data_block_quadlets; |
510 | } | 511 | } |
511 | 512 | ||
512 | /* Check data block counter continuity */ | 513 | /* Check data block counter continuity */ |
513 | data_block_counter = cip_header[0] & CIP_DBC_MASK; | 514 | data_block_counter = cip_header[0] & CIP_DBC_MASK; |
514 | if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && | 515 | if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && |
515 | s->data_block_counter != UINT_MAX) | 516 | s->data_block_counter != UINT_MAX) |
516 | data_block_counter = s->data_block_counter; | 517 | data_block_counter = s->data_block_counter; |
517 | 518 | ||
@@ -522,10 +523,10 @@ static int handle_in_packet(struct amdtp_stream *s, | |||
522 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { | 523 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { |
523 | lost = data_block_counter != s->data_block_counter; | 524 | lost = data_block_counter != s->data_block_counter; |
524 | } else { | 525 | } else { |
525 | if ((*data_blocks > 0) && (s->tx_dbc_interval > 0)) | 526 | if (data_blocks > 0 && s->tx_dbc_interval > 0) |
526 | dbc_interval = s->tx_dbc_interval; | 527 | dbc_interval = s->tx_dbc_interval; |
527 | else | 528 | else |
528 | dbc_interval = *data_blocks; | 529 | dbc_interval = data_blocks; |
529 | 530 | ||
530 | lost = data_block_counter != | 531 | lost = data_block_counter != |
531 | ((s->data_block_counter + dbc_interval) & 0xff); | 532 | ((s->data_block_counter + dbc_interval) & 0xff); |
@@ -538,13 +539,14 @@ static int handle_in_packet(struct amdtp_stream *s, | |||
538 | return -EIO; | 539 | return -EIO; |
539 | } | 540 | } |
540 | 541 | ||
541 | pcm_frames = s->process_data_blocks(s, buffer + 2, *data_blocks, &syt); | 542 | syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; |
543 | pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); | ||
542 | 544 | ||
543 | if (s->flags & CIP_DBC_IS_END_EVENT) | 545 | if (s->flags & CIP_DBC_IS_END_EVENT) |
544 | s->data_block_counter = data_block_counter; | 546 | s->data_block_counter = data_block_counter; |
545 | else | 547 | else |
546 | s->data_block_counter = | 548 | s->data_block_counter = |
547 | (data_block_counter + *data_blocks) & 0xff; | 549 | (data_block_counter + data_blocks) & 0xff; |
548 | end: | 550 | end: |
549 | if (queue_in_packet(s) < 0) | 551 | if (queue_in_packet(s) < 0) |
550 | return -EIO; | 552 | return -EIO; |
@@ -618,10 +620,9 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
618 | void *private_data) | 620 | void *private_data) |
619 | { | 621 | { |
620 | struct amdtp_stream *s = private_data; | 622 | struct amdtp_stream *s = private_data; |
621 | unsigned int p, syt, packets; | 623 | unsigned int i, packets; |
622 | unsigned int payload_quadlets, max_payload_quadlets; | 624 | unsigned int payload_quadlets, max_payload_quadlets; |
623 | unsigned int data_blocks; | 625 | __be32 *headers = header; |
624 | __be32 *buffer, *headers = header; | ||
625 | u32 cycle; | 626 | u32 cycle; |
626 | 627 | ||
627 | if (s->packet_index < 0) | 628 | if (s->packet_index < 0) |
@@ -638,13 +639,12 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
638 | /* For buffer-over-run prevention. */ | 639 | /* For buffer-over-run prevention. */ |
639 | max_payload_quadlets = amdtp_stream_get_max_payload(s) / 4; | 640 | max_payload_quadlets = amdtp_stream_get_max_payload(s) / 4; |
640 | 641 | ||
641 | for (p = 0; p < packets; p++) { | 642 | for (i = 0; i < packets; i++) { |
642 | cycle = increment_cycle_count(cycle, 1); | 643 | cycle = increment_cycle_count(cycle, 1); |
643 | buffer = s->buffer.packets[s->packet_index].buffer; | ||
644 | 644 | ||
645 | /* The number of quadlets in this packet */ | 645 | /* The number of quadlets in this packet */ |
646 | payload_quadlets = | 646 | payload_quadlets = |
647 | (be32_to_cpu(headers[p]) >> ISO_DATA_LENGTH_SHIFT) / 4; | 647 | (be32_to_cpu(headers[i]) >> ISO_DATA_LENGTH_SHIFT) / 4; |
648 | if (payload_quadlets > max_payload_quadlets) { | 648 | if (payload_quadlets > max_payload_quadlets) { |
649 | dev_err(&s->unit->device, | 649 | dev_err(&s->unit->device, |
650 | "Detect jumbo payload: %02x %02x\n", | 650 | "Detect jumbo payload: %02x %02x\n", |
@@ -652,14 +652,12 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
652 | break; | 652 | break; |
653 | } | 653 | } |
654 | 654 | ||
655 | syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; | 655 | if (handle_in_packet(s, payload_quadlets, cycle) < 0) |
656 | if (handle_in_packet(s, payload_quadlets, buffer, | ||
657 | &data_blocks, cycle, syt) < 0) | ||
658 | break; | 656 | break; |
659 | } | 657 | } |
660 | 658 | ||
661 | /* Queueing error or detecting invalid payload. */ | 659 | /* Queueing error or detecting invalid payload. */ |
662 | if (p < packets) { | 660 | if (i < packets) { |
663 | s->packet_index = -1; | 661 | s->packet_index = -1; |
664 | amdtp_stream_pcm_abort(s); | 662 | amdtp_stream_pcm_abort(s); |
665 | return; | 663 | return; |