Lines Matching refs:s
78 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, in amdtp_stream_init() argument
81 s->unit = unit; in amdtp_stream_init()
82 s->direction = dir; in amdtp_stream_init()
83 s->flags = flags; in amdtp_stream_init()
84 s->context = ERR_PTR(-1); in amdtp_stream_init()
85 mutex_init(&s->mutex); in amdtp_stream_init()
86 tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); in amdtp_stream_init()
87 s->packet_index = 0; in amdtp_stream_init()
89 init_waitqueue_head(&s->callback_wait); in amdtp_stream_init()
90 s->callbacked = false; in amdtp_stream_init()
91 s->sync_slave = NULL; in amdtp_stream_init()
101 void amdtp_stream_destroy(struct amdtp_stream *s) in amdtp_stream_destroy() argument
103 WARN_ON(amdtp_stream_running(s)); in amdtp_stream_destroy()
104 mutex_destroy(&s->mutex); in amdtp_stream_destroy()
135 int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, in amdtp_stream_add_pcm_hw_constraints() argument
162 if (!(s->flags & CIP_BLOCKING)) in amdtp_stream_add_pcm_hw_constraints()
196 void amdtp_stream_set_parameters(struct amdtp_stream *s, in amdtp_stream_set_parameters() argument
205 if (WARN_ON(amdtp_stream_running(s)) | in amdtp_stream_set_parameters()
217 s->pcm_channels = pcm_channels; in amdtp_stream_set_parameters()
218 s->sfc = sfc; in amdtp_stream_set_parameters()
219 s->data_block_quadlets = s->pcm_channels + midi_channels; in amdtp_stream_set_parameters()
220 s->midi_ports = midi_ports; in amdtp_stream_set_parameters()
222 s->syt_interval = amdtp_syt_intervals[sfc]; in amdtp_stream_set_parameters()
225 s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; in amdtp_stream_set_parameters()
226 if (s->flags & CIP_BLOCKING) in amdtp_stream_set_parameters()
228 s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; in amdtp_stream_set_parameters()
232 s->pcm_positions[i] = i; in amdtp_stream_set_parameters()
233 s->midi_position = s->pcm_channels; in amdtp_stream_set_parameters()
241 s->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1; in amdtp_stream_set_parameters()
252 unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) in amdtp_stream_get_max_payload() argument
254 return 8 + s->syt_interval * s->data_block_quadlets * 4; in amdtp_stream_get_max_payload()
258 static void amdtp_write_s16(struct amdtp_stream *s,
261 static void amdtp_write_s32(struct amdtp_stream *s,
264 static void amdtp_read_s32(struct amdtp_stream *s,
277 void amdtp_stream_set_pcm_format(struct amdtp_stream *s, in amdtp_stream_set_pcm_format() argument
280 if (WARN_ON(amdtp_stream_pcm_running(s))) in amdtp_stream_set_pcm_format()
288 if (s->direction == AMDTP_OUT_STREAM) { in amdtp_stream_set_pcm_format()
289 s->transfer_samples = amdtp_write_s16; in amdtp_stream_set_pcm_format()
295 if (s->direction == AMDTP_OUT_STREAM) in amdtp_stream_set_pcm_format()
296 s->transfer_samples = amdtp_write_s32; in amdtp_stream_set_pcm_format()
298 s->transfer_samples = amdtp_read_s32; in amdtp_stream_set_pcm_format()
310 void amdtp_stream_pcm_prepare(struct amdtp_stream *s) in amdtp_stream_pcm_prepare() argument
312 tasklet_kill(&s->period_tasklet); in amdtp_stream_pcm_prepare()
313 s->pcm_buffer_pointer = 0; in amdtp_stream_pcm_prepare()
314 s->pcm_period_pointer = 0; in amdtp_stream_pcm_prepare()
315 s->pointer_flush = true; in amdtp_stream_pcm_prepare()
319 static unsigned int calculate_data_blocks(struct amdtp_stream *s) in calculate_data_blocks() argument
323 if (s->flags & CIP_BLOCKING) in calculate_data_blocks()
324 data_blocks = s->syt_interval; in calculate_data_blocks()
325 else if (!cip_sfc_is_base_44100(s->sfc)) { in calculate_data_blocks()
327 data_blocks = s->data_block_state; in calculate_data_blocks()
329 phase = s->data_block_state; in calculate_data_blocks()
339 if (s->sfc == CIP_SFC_44100) in calculate_data_blocks()
345 data_blocks = 11 * (s->sfc >> 1) + (phase == 0); in calculate_data_blocks()
346 if (++phase >= (80 >> (s->sfc >> 1))) in calculate_data_blocks()
348 s->data_block_state = phase; in calculate_data_blocks()
354 static unsigned int calculate_syt(struct amdtp_stream *s, in calculate_syt() argument
359 if (s->last_syt_offset < TICKS_PER_CYCLE) { in calculate_syt()
360 if (!cip_sfc_is_base_44100(s->sfc)) in calculate_syt()
361 syt_offset = s->last_syt_offset + s->syt_offset_state; in calculate_syt()
373 phase = s->syt_offset_state; in calculate_syt()
375 syt_offset = s->last_syt_offset; in calculate_syt()
380 s->syt_offset_state = phase; in calculate_syt()
383 syt_offset = s->last_syt_offset - TICKS_PER_CYCLE; in calculate_syt()
384 s->last_syt_offset = syt_offset; in calculate_syt()
387 syt_offset += s->transfer_delay; in calculate_syt()
397 static void amdtp_write_s32(struct amdtp_stream *s, in amdtp_write_s32() argument
405 channels = s->pcm_channels; in amdtp_write_s32()
407 frames_to_bytes(runtime, s->pcm_buffer_pointer); in amdtp_write_s32()
408 remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; in amdtp_write_s32()
412 buffer[s->pcm_positions[c]] = in amdtp_write_s32()
416 buffer += s->data_block_quadlets; in amdtp_write_s32()
422 static void amdtp_write_s16(struct amdtp_stream *s, in amdtp_write_s16() argument
430 channels = s->pcm_channels; in amdtp_write_s16()
432 frames_to_bytes(runtime, s->pcm_buffer_pointer); in amdtp_write_s16()
433 remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; in amdtp_write_s16()
437 buffer[s->pcm_positions[c]] = in amdtp_write_s16()
441 buffer += s->data_block_quadlets; in amdtp_write_s16()
447 static void amdtp_read_s32(struct amdtp_stream *s, in amdtp_read_s32() argument
455 channels = s->pcm_channels; in amdtp_read_s32()
457 frames_to_bytes(runtime, s->pcm_buffer_pointer); in amdtp_read_s32()
458 remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; in amdtp_read_s32()
462 *dst = be32_to_cpu(buffer[s->pcm_positions[c]]) << 8; in amdtp_read_s32()
465 buffer += s->data_block_quadlets; in amdtp_read_s32()
471 static void amdtp_fill_pcm_silence(struct amdtp_stream *s, in amdtp_fill_pcm_silence() argument
477 for (c = 0; c < s->pcm_channels; ++c) in amdtp_fill_pcm_silence()
478 buffer[s->pcm_positions[c]] = cpu_to_be32(0x40000000); in amdtp_fill_pcm_silence()
479 buffer += s->data_block_quadlets; in amdtp_fill_pcm_silence()
493 static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port) in midi_ratelimit_per_packet() argument
497 used = s->midi_fifo_used[port]; in midi_ratelimit_per_packet()
501 used -= MIDI_BYTES_PER_SECOND * s->syt_interval; in midi_ratelimit_per_packet()
503 s->midi_fifo_used[port] = used; in midi_ratelimit_per_packet()
505 return used < s->midi_fifo_limit; in midi_ratelimit_per_packet()
508 static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port) in midi_rate_use_one_byte() argument
510 s->midi_fifo_used[port] += amdtp_rate_table[s->sfc]; in midi_rate_use_one_byte()
513 static void amdtp_fill_midi(struct amdtp_stream *s, in amdtp_fill_midi() argument
520 b = (u8 *)&buffer[s->midi_position]; in amdtp_fill_midi()
522 port = (s->data_block_counter + f) % 8; in amdtp_fill_midi()
524 midi_ratelimit_per_packet(s, port) && in amdtp_fill_midi()
525 s->midi[port] != NULL && in amdtp_fill_midi()
526 snd_rawmidi_transmit(s->midi[port], &b[1], 1) == 1) { in amdtp_fill_midi()
527 midi_rate_use_one_byte(s, port); in amdtp_fill_midi()
536 buffer += s->data_block_quadlets; in amdtp_fill_midi()
540 static void amdtp_pull_midi(struct amdtp_stream *s, in amdtp_pull_midi() argument
548 port = (s->data_block_counter + f) % 8; in amdtp_pull_midi()
549 b = (u8 *)&buffer[s->midi_position]; in amdtp_pull_midi()
552 if ((1 <= len) && (len <= 3) && (s->midi[port])) in amdtp_pull_midi()
553 snd_rawmidi_receive(s->midi[port], b + 1, len); in amdtp_pull_midi()
555 buffer += s->data_block_quadlets; in amdtp_pull_midi()
559 static void update_pcm_pointers(struct amdtp_stream *s, in update_pcm_pointers() argument
570 if (s->double_pcm_frames) in update_pcm_pointers()
573 ptr = s->pcm_buffer_pointer + frames; in update_pcm_pointers()
576 ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; in update_pcm_pointers()
578 s->pcm_period_pointer += frames; in update_pcm_pointers()
579 if (s->pcm_period_pointer >= pcm->runtime->period_size) { in update_pcm_pointers()
580 s->pcm_period_pointer -= pcm->runtime->period_size; in update_pcm_pointers()
581 s->pointer_flush = false; in update_pcm_pointers()
582 tasklet_hi_schedule(&s->period_tasklet); in update_pcm_pointers()
588 struct amdtp_stream *s = (void *)data; in pcm_period_tasklet() local
589 struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm); in pcm_period_tasklet()
595 static int queue_packet(struct amdtp_stream *s, in queue_packet() argument
602 if (IS_ERR(s->context)) in queue_packet()
605 p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); in queue_packet()
610 err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer, in queue_packet()
611 s->buffer.packets[s->packet_index].offset); in queue_packet()
613 dev_err(&s->unit->device, "queueing error: %d\n", err); in queue_packet()
617 if (++s->packet_index >= QUEUE_LENGTH) in queue_packet()
618 s->packet_index = 0; in queue_packet()
623 static inline int queue_out_packet(struct amdtp_stream *s, in queue_out_packet() argument
626 return queue_packet(s, OUT_PACKET_HEADER_SIZE, in queue_out_packet()
630 static inline int queue_in_packet(struct amdtp_stream *s) in queue_in_packet() argument
632 return queue_packet(s, IN_PACKET_HEADER_SIZE, in queue_in_packet()
633 amdtp_stream_get_max_payload(s), false); in queue_in_packet()
636 static void handle_out_packet(struct amdtp_stream *s, unsigned int syt) in handle_out_packet() argument
642 if (s->packet_index < 0) in handle_out_packet()
646 if (!(s->flags & CIP_BLOCKING) || (syt != CIP_SYT_NO_INFO)) in handle_out_packet()
647 data_blocks = calculate_data_blocks(s); in handle_out_packet()
651 buffer = s->buffer.packets[s->packet_index].buffer; in handle_out_packet()
652 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | in handle_out_packet()
653 (s->data_block_quadlets << AMDTP_DBS_SHIFT) | in handle_out_packet()
654 s->data_block_counter); in handle_out_packet()
656 (s->sfc << CIP_FDF_SFC_SHIFT) | syt); in handle_out_packet()
659 pcm = ACCESS_ONCE(s->pcm); in handle_out_packet()
661 s->transfer_samples(s, pcm, buffer, data_blocks); in handle_out_packet()
663 amdtp_fill_pcm_silence(s, buffer, data_blocks); in handle_out_packet()
664 if (s->midi_ports) in handle_out_packet()
665 amdtp_fill_midi(s, buffer, data_blocks); in handle_out_packet()
667 s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; in handle_out_packet()
669 payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; in handle_out_packet()
670 if (queue_out_packet(s, payload_length, false) < 0) { in handle_out_packet()
671 s->packet_index = -1; in handle_out_packet()
672 amdtp_stream_pcm_abort(s); in handle_out_packet()
677 update_pcm_pointers(s, pcm, data_blocks); in handle_out_packet()
680 static void handle_in_packet(struct amdtp_stream *s, in handle_in_packet() argument
700 dev_info_ratelimited(&s->unit->device, in handle_in_packet()
716 dev_info_ratelimited(&s->unit->device, in handle_in_packet()
721 if (s->flags & CIP_WRONG_DBS) in handle_in_packet()
722 data_block_quadlets = s->data_block_quadlets; in handle_in_packet()
729 if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && in handle_in_packet()
730 s->data_block_counter != UINT_MAX) in handle_in_packet()
731 data_block_counter = s->data_block_counter; in handle_in_packet()
733 if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && in handle_in_packet()
734 data_block_counter == s->tx_first_dbc) || in handle_in_packet()
735 s->data_block_counter == UINT_MAX) { in handle_in_packet()
737 } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { in handle_in_packet()
738 lost = data_block_counter != s->data_block_counter; in handle_in_packet()
740 if ((data_blocks > 0) && (s->tx_dbc_interval > 0)) in handle_in_packet()
741 dbc_interval = s->tx_dbc_interval; in handle_in_packet()
746 ((s->data_block_counter + dbc_interval) & 0xff); in handle_in_packet()
750 dev_info(&s->unit->device, in handle_in_packet()
752 s->data_block_counter, data_block_counter); in handle_in_packet()
759 pcm = ACCESS_ONCE(s->pcm); in handle_in_packet()
761 s->transfer_samples(s, pcm, buffer, data_blocks); in handle_in_packet()
763 if (s->midi_ports) in handle_in_packet()
764 amdtp_pull_midi(s, buffer, data_blocks); in handle_in_packet()
767 if (s->flags & CIP_DBC_IS_END_EVENT) in handle_in_packet()
768 s->data_block_counter = data_block_counter; in handle_in_packet()
770 s->data_block_counter = in handle_in_packet()
773 if (queue_in_packet(s) < 0) in handle_in_packet()
777 update_pcm_pointers(s, pcm, data_blocks); in handle_in_packet()
781 s->packet_index = -1; in handle_in_packet()
782 amdtp_stream_pcm_abort(s); in handle_in_packet()
789 struct amdtp_stream *s = private_data; in out_stream_callback() local
800 syt = calculate_syt(s, ++cycle); in out_stream_callback()
801 handle_out_packet(s, syt); in out_stream_callback()
803 fw_iso_context_queue_flush(s->context); in out_stream_callback()
810 struct amdtp_stream *s = private_data; in in_stream_callback() local
818 if (s->packet_index < 0) in in_stream_callback()
821 buffer = s->buffer.packets[s->packet_index].buffer; in in_stream_callback()
824 if (s->sync_slave && s->sync_slave->callbacked) { in in_stream_callback()
826 handle_out_packet(s->sync_slave, syt); in in_stream_callback()
832 handle_in_packet(s, payload_quadlets, buffer); in in_stream_callback()
836 if (s->packet_index < 0) { in in_stream_callback()
838 if (s->sync_slave) { in in_stream_callback()
839 s->sync_slave->packet_index = -1; in in_stream_callback()
840 amdtp_stream_pcm_abort(s->sync_slave); in in_stream_callback()
846 if (s->sync_slave && s->sync_slave->callbacked) in in_stream_callback()
847 fw_iso_context_queue_flush(s->sync_slave->context); in in_stream_callback()
849 fw_iso_context_queue_flush(s->context); in in_stream_callback()
865 struct amdtp_stream *s = private_data; in amdtp_stream_first_callback() local
871 s->callbacked = true; in amdtp_stream_first_callback()
872 wake_up(&s->callback_wait); in amdtp_stream_first_callback()
874 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_first_callback()
876 else if ((s->flags & CIP_BLOCKING) && (s->flags & CIP_SYNC_TO_DEVICE)) in amdtp_stream_first_callback()
881 context->callback.sc(context, cycle, header_length, header, s); in amdtp_stream_first_callback()
894 int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) in amdtp_stream_start() argument
912 mutex_lock(&s->mutex); in amdtp_stream_start()
914 if (WARN_ON(amdtp_stream_running(s) || in amdtp_stream_start()
915 (s->data_block_quadlets < 1))) { in amdtp_stream_start()
920 if (s->direction == AMDTP_IN_STREAM && in amdtp_stream_start()
921 s->flags & CIP_SKIP_INIT_DBC_CHECK) in amdtp_stream_start()
922 s->data_block_counter = UINT_MAX; in amdtp_stream_start()
924 s->data_block_counter = 0; in amdtp_stream_start()
925 s->data_block_state = initial_state[s->sfc].data_block; in amdtp_stream_start()
926 s->syt_offset_state = initial_state[s->sfc].syt_offset; in amdtp_stream_start()
927 s->last_syt_offset = TICKS_PER_CYCLE; in amdtp_stream_start()
930 if (s->direction == AMDTP_IN_STREAM) { in amdtp_stream_start()
939 err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, in amdtp_stream_start()
940 amdtp_stream_get_max_payload(s), dir); in amdtp_stream_start()
944 s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, in amdtp_stream_start()
946 amdtp_stream_first_callback, s); in amdtp_stream_start()
947 if (IS_ERR(s->context)) { in amdtp_stream_start()
948 err = PTR_ERR(s->context); in amdtp_stream_start()
950 dev_err(&s->unit->device, in amdtp_stream_start()
955 amdtp_stream_update(s); in amdtp_stream_start()
957 s->packet_index = 0; in amdtp_stream_start()
959 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_start()
960 err = queue_in_packet(s); in amdtp_stream_start()
962 err = queue_out_packet(s, 0, true); in amdtp_stream_start()
965 } while (s->packet_index > 0); in amdtp_stream_start()
969 if (s->flags & CIP_EMPTY_WITH_TAG0) in amdtp_stream_start()
972 s->callbacked = false; in amdtp_stream_start()
973 err = fw_iso_context_start(s->context, -1, 0, tag); in amdtp_stream_start()
977 mutex_unlock(&s->mutex); in amdtp_stream_start()
982 fw_iso_context_destroy(s->context); in amdtp_stream_start()
983 s->context = ERR_PTR(-1); in amdtp_stream_start()
985 iso_packets_buffer_destroy(&s->buffer, s->unit); in amdtp_stream_start()
987 mutex_unlock(&s->mutex); in amdtp_stream_start()
999 unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s) in amdtp_stream_pcm_pointer() argument
1002 if (s->pointer_flush && amdtp_stream_running(s)) in amdtp_stream_pcm_pointer()
1003 fw_iso_context_flush_completions(s->context); in amdtp_stream_pcm_pointer()
1005 s->pointer_flush = true; in amdtp_stream_pcm_pointer()
1007 return ACCESS_ONCE(s->pcm_buffer_pointer); in amdtp_stream_pcm_pointer()
1015 void amdtp_stream_update(struct amdtp_stream *s) in amdtp_stream_update() argument
1017 ACCESS_ONCE(s->source_node_id_field) = in amdtp_stream_update()
1018 (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24; in amdtp_stream_update()
1029 void amdtp_stream_stop(struct amdtp_stream *s) in amdtp_stream_stop() argument
1031 mutex_lock(&s->mutex); in amdtp_stream_stop()
1033 if (!amdtp_stream_running(s)) { in amdtp_stream_stop()
1034 mutex_unlock(&s->mutex); in amdtp_stream_stop()
1038 tasklet_kill(&s->period_tasklet); in amdtp_stream_stop()
1039 fw_iso_context_stop(s->context); in amdtp_stream_stop()
1040 fw_iso_context_destroy(s->context); in amdtp_stream_stop()
1041 s->context = ERR_PTR(-1); in amdtp_stream_stop()
1042 iso_packets_buffer_destroy(&s->buffer, s->unit); in amdtp_stream_stop()
1044 s->callbacked = false; in amdtp_stream_stop()
1046 mutex_unlock(&s->mutex); in amdtp_stream_stop()
1057 void amdtp_stream_pcm_abort(struct amdtp_stream *s) in amdtp_stream_pcm_abort() argument
1061 pcm = ACCESS_ONCE(s->pcm); in amdtp_stream_pcm_abort()