Lines Matching refs:s
67 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, in amdtp_stream_init() argument
76 s->protocol = kzalloc(protocol_size, GFP_KERNEL); in amdtp_stream_init()
77 if (!s->protocol) in amdtp_stream_init()
80 s->unit = unit; in amdtp_stream_init()
81 s->direction = dir; in amdtp_stream_init()
82 s->flags = flags; in amdtp_stream_init()
83 s->context = ERR_PTR(-1); in amdtp_stream_init()
84 mutex_init(&s->mutex); in amdtp_stream_init()
85 tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); in amdtp_stream_init()
86 s->packet_index = 0; in amdtp_stream_init()
88 init_waitqueue_head(&s->callback_wait); in amdtp_stream_init()
89 s->callbacked = false; in amdtp_stream_init()
90 s->sync_slave = NULL; in amdtp_stream_init()
92 s->fmt = fmt; in amdtp_stream_init()
93 s->process_data_blocks = process_data_blocks; in amdtp_stream_init()
103 void amdtp_stream_destroy(struct amdtp_stream *s) in amdtp_stream_destroy() argument
105 WARN_ON(amdtp_stream_running(s)); in amdtp_stream_destroy()
106 kfree(s->protocol); in amdtp_stream_destroy()
107 mutex_destroy(&s->mutex); in amdtp_stream_destroy()
138 int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, in amdtp_stream_add_pcm_hw_constraints() argument
160 if (!(s->flags & CIP_BLOCKING)) in amdtp_stream_add_pcm_hw_constraints()
192 int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, in amdtp_stream_set_parameters() argument
204 s->sfc = sfc; in amdtp_stream_set_parameters()
205 s->data_block_quadlets = data_block_quadlets; in amdtp_stream_set_parameters()
206 s->syt_interval = amdtp_syt_intervals[sfc]; in amdtp_stream_set_parameters()
209 s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; in amdtp_stream_set_parameters()
210 if (s->flags & CIP_BLOCKING) in amdtp_stream_set_parameters()
212 s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; in amdtp_stream_set_parameters()
225 unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) in amdtp_stream_get_max_payload() argument
229 if (s->flags & CIP_JUMBO_PAYLOAD) in amdtp_stream_get_max_payload()
232 return 8 + s->syt_interval * s->data_block_quadlets * 4 * multiplier; in amdtp_stream_get_max_payload()
242 void amdtp_stream_pcm_prepare(struct amdtp_stream *s) in amdtp_stream_pcm_prepare() argument
244 tasklet_kill(&s->period_tasklet); in amdtp_stream_pcm_prepare()
245 s->pcm_buffer_pointer = 0; in amdtp_stream_pcm_prepare()
246 s->pcm_period_pointer = 0; in amdtp_stream_pcm_prepare()
247 s->pointer_flush = true; in amdtp_stream_pcm_prepare()
251 static unsigned int calculate_data_blocks(struct amdtp_stream *s, in calculate_data_blocks() argument
257 if (s->flags & CIP_BLOCKING) { in calculate_data_blocks()
262 data_blocks = s->syt_interval; in calculate_data_blocks()
265 if (!cip_sfc_is_base_44100(s->sfc)) { in calculate_data_blocks()
267 data_blocks = s->data_block_state; in calculate_data_blocks()
269 phase = s->data_block_state; in calculate_data_blocks()
279 if (s->sfc == CIP_SFC_44100) in calculate_data_blocks()
285 data_blocks = 11 * (s->sfc >> 1) + (phase == 0); in calculate_data_blocks()
286 if (++phase >= (80 >> (s->sfc >> 1))) in calculate_data_blocks()
288 s->data_block_state = phase; in calculate_data_blocks()
295 static unsigned int calculate_syt(struct amdtp_stream *s, in calculate_syt() argument
300 if (s->last_syt_offset < TICKS_PER_CYCLE) { in calculate_syt()
301 if (!cip_sfc_is_base_44100(s->sfc)) in calculate_syt()
302 syt_offset = s->last_syt_offset + s->syt_offset_state; in calculate_syt()
314 phase = s->syt_offset_state; in calculate_syt()
316 syt_offset = s->last_syt_offset; in calculate_syt()
321 s->syt_offset_state = phase; in calculate_syt()
324 syt_offset = s->last_syt_offset - TICKS_PER_CYCLE; in calculate_syt()
325 s->last_syt_offset = syt_offset; in calculate_syt()
328 syt_offset += s->transfer_delay; in calculate_syt()
338 static void update_pcm_pointers(struct amdtp_stream *s, in update_pcm_pointers() argument
344 ptr = s->pcm_buffer_pointer + frames; in update_pcm_pointers()
347 ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; in update_pcm_pointers()
349 s->pcm_period_pointer += frames; in update_pcm_pointers()
350 if (s->pcm_period_pointer >= pcm->runtime->period_size) { in update_pcm_pointers()
351 s->pcm_period_pointer -= pcm->runtime->period_size; in update_pcm_pointers()
352 s->pointer_flush = false; in update_pcm_pointers()
353 tasklet_hi_schedule(&s->period_tasklet); in update_pcm_pointers()
359 struct amdtp_stream *s = (void *)data; in pcm_period_tasklet() local
360 struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm); in pcm_period_tasklet()
366 static int queue_packet(struct amdtp_stream *s, in queue_packet() argument
373 if (IS_ERR(s->context)) in queue_packet()
376 p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); in queue_packet()
381 err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer, in queue_packet()
382 s->buffer.packets[s->packet_index].offset); in queue_packet()
384 dev_err(&s->unit->device, "queueing error: %d\n", err); in queue_packet()
388 if (++s->packet_index >= QUEUE_LENGTH) in queue_packet()
389 s->packet_index = 0; in queue_packet()
394 static inline int queue_out_packet(struct amdtp_stream *s, in queue_out_packet() argument
397 return queue_packet(s, OUT_PACKET_HEADER_SIZE, in queue_out_packet()
401 static inline int queue_in_packet(struct amdtp_stream *s) in queue_in_packet() argument
403 return queue_packet(s, IN_PACKET_HEADER_SIZE, in queue_in_packet()
404 amdtp_stream_get_max_payload(s), false); in queue_in_packet()
407 static int handle_out_packet(struct amdtp_stream *s, unsigned int data_blocks, in handle_out_packet() argument
415 buffer = s->buffer.packets[s->packet_index].buffer; in handle_out_packet()
416 pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); in handle_out_packet()
418 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | in handle_out_packet()
419 (s->data_block_quadlets << CIP_DBS_SHIFT) | in handle_out_packet()
420 s->data_block_counter); in handle_out_packet()
422 ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | in handle_out_packet()
423 ((s->fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | in handle_out_packet()
426 s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; in handle_out_packet()
428 payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; in handle_out_packet()
429 if (queue_out_packet(s, payload_length, false) < 0) in handle_out_packet()
432 pcm = ACCESS_ONCE(s->pcm); in handle_out_packet()
434 update_pcm_pointers(s, pcm, pcm_frames); in handle_out_packet()
440 static int handle_in_packet(struct amdtp_stream *s, in handle_in_packet() argument
460 dev_info_ratelimited(&s->unit->device, in handle_in_packet()
470 if (fmt != s->fmt) { in handle_in_packet()
471 dev_info_ratelimited(&s->unit->device, in handle_in_packet()
489 dev_err(&s->unit->device, in handle_in_packet()
494 if (s->flags & CIP_WRONG_DBS) in handle_in_packet()
495 data_block_quadlets = s->data_block_quadlets; in handle_in_packet()
502 if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && in handle_in_packet()
503 s->data_block_counter != UINT_MAX) in handle_in_packet()
504 data_block_counter = s->data_block_counter; in handle_in_packet()
506 if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && in handle_in_packet()
507 data_block_counter == s->tx_first_dbc) || in handle_in_packet()
508 s->data_block_counter == UINT_MAX) { in handle_in_packet()
510 } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { in handle_in_packet()
511 lost = data_block_counter != s->data_block_counter; in handle_in_packet()
513 if ((*data_blocks > 0) && (s->tx_dbc_interval > 0)) in handle_in_packet()
514 dbc_interval = s->tx_dbc_interval; in handle_in_packet()
519 ((s->data_block_counter + dbc_interval) & 0xff); in handle_in_packet()
523 dev_err(&s->unit->device, in handle_in_packet()
525 s->data_block_counter, data_block_counter); in handle_in_packet()
529 pcm_frames = s->process_data_blocks(s, buffer + 2, *data_blocks, &syt); in handle_in_packet()
531 if (s->flags & CIP_DBC_IS_END_EVENT) in handle_in_packet()
532 s->data_block_counter = data_block_counter; in handle_in_packet()
534 s->data_block_counter = in handle_in_packet()
537 if (queue_in_packet(s) < 0) in handle_in_packet()
540 pcm = ACCESS_ONCE(s->pcm); in handle_in_packet()
542 update_pcm_pointers(s, pcm, pcm_frames); in handle_in_packet()
551 struct amdtp_stream *s = private_data; in out_stream_callback() local
555 if (s->packet_index < 0) in out_stream_callback()
566 syt = calculate_syt(s, ++cycle); in out_stream_callback()
567 data_blocks = calculate_data_blocks(s, syt); in out_stream_callback()
569 if (handle_out_packet(s, data_blocks, syt) < 0) { in out_stream_callback()
570 s->packet_index = -1; in out_stream_callback()
571 amdtp_stream_pcm_abort(s); in out_stream_callback()
576 fw_iso_context_queue_flush(s->context); in out_stream_callback()
583 struct amdtp_stream *s = private_data; in in_stream_callback() local
589 if (s->packet_index < 0) in in_stream_callback()
596 max_payload_quadlets = amdtp_stream_get_max_payload(s) / 4; in in_stream_callback()
599 buffer = s->buffer.packets[s->packet_index].buffer; in in_stream_callback()
605 dev_err(&s->unit->device, in in_stream_callback()
608 s->packet_index = -1; in in_stream_callback()
613 if (handle_in_packet(s, payload_quadlets, buffer, in in_stream_callback()
615 s->packet_index = -1; in in_stream_callback()
620 if (s->sync_slave && s->sync_slave->callbacked) { in in_stream_callback()
621 if (handle_out_packet(s->sync_slave, in in_stream_callback()
623 s->packet_index = -1; in in_stream_callback()
630 if (s->packet_index < 0) { in in_stream_callback()
631 amdtp_stream_pcm_abort(s); in in_stream_callback()
634 if (s->sync_slave) { in in_stream_callback()
635 s->sync_slave->packet_index = -1; in in_stream_callback()
636 amdtp_stream_pcm_abort(s->sync_slave); in in_stream_callback()
642 if (s->sync_slave && s->sync_slave->callbacked) in in_stream_callback()
643 fw_iso_context_queue_flush(s->sync_slave->context); in in_stream_callback()
645 fw_iso_context_queue_flush(s->context); in in_stream_callback()
661 struct amdtp_stream *s = private_data; in amdtp_stream_first_callback() local
667 s->callbacked = true; in amdtp_stream_first_callback()
668 wake_up(&s->callback_wait); in amdtp_stream_first_callback()
670 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_first_callback()
672 else if (s->flags & CIP_SYNC_TO_DEVICE) in amdtp_stream_first_callback()
677 context->callback.sc(context, cycle, header_length, header, s); in amdtp_stream_first_callback()
690 int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) in amdtp_stream_start() argument
708 mutex_lock(&s->mutex); in amdtp_stream_start()
710 if (WARN_ON(amdtp_stream_running(s) || in amdtp_stream_start()
711 (s->data_block_quadlets < 1))) { in amdtp_stream_start()
716 if (s->direction == AMDTP_IN_STREAM && in amdtp_stream_start()
717 s->flags & CIP_SKIP_INIT_DBC_CHECK) in amdtp_stream_start()
718 s->data_block_counter = UINT_MAX; in amdtp_stream_start()
720 s->data_block_counter = 0; in amdtp_stream_start()
721 s->data_block_state = initial_state[s->sfc].data_block; in amdtp_stream_start()
722 s->syt_offset_state = initial_state[s->sfc].syt_offset; in amdtp_stream_start()
723 s->last_syt_offset = TICKS_PER_CYCLE; in amdtp_stream_start()
726 if (s->direction == AMDTP_IN_STREAM) { in amdtp_stream_start()
735 err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, in amdtp_stream_start()
736 amdtp_stream_get_max_payload(s), dir); in amdtp_stream_start()
740 s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, in amdtp_stream_start()
742 amdtp_stream_first_callback, s); in amdtp_stream_start()
743 if (IS_ERR(s->context)) { in amdtp_stream_start()
744 err = PTR_ERR(s->context); in amdtp_stream_start()
746 dev_err(&s->unit->device, in amdtp_stream_start()
751 amdtp_stream_update(s); in amdtp_stream_start()
753 s->packet_index = 0; in amdtp_stream_start()
755 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_start()
756 err = queue_in_packet(s); in amdtp_stream_start()
758 err = queue_out_packet(s, 0, true); in amdtp_stream_start()
761 } while (s->packet_index > 0); in amdtp_stream_start()
765 if (s->flags & CIP_EMPTY_WITH_TAG0) in amdtp_stream_start()
768 s->callbacked = false; in amdtp_stream_start()
769 err = fw_iso_context_start(s->context, -1, 0, tag); in amdtp_stream_start()
773 mutex_unlock(&s->mutex); in amdtp_stream_start()
778 fw_iso_context_destroy(s->context); in amdtp_stream_start()
779 s->context = ERR_PTR(-1); in amdtp_stream_start()
781 iso_packets_buffer_destroy(&s->buffer, s->unit); in amdtp_stream_start()
783 mutex_unlock(&s->mutex); in amdtp_stream_start()
795 unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s) in amdtp_stream_pcm_pointer() argument
798 if (s->pointer_flush && amdtp_stream_running(s)) in amdtp_stream_pcm_pointer()
799 fw_iso_context_flush_completions(s->context); in amdtp_stream_pcm_pointer()
801 s->pointer_flush = true; in amdtp_stream_pcm_pointer()
803 return ACCESS_ONCE(s->pcm_buffer_pointer); in amdtp_stream_pcm_pointer()
811 void amdtp_stream_update(struct amdtp_stream *s) in amdtp_stream_update() argument
814 ACCESS_ONCE(s->source_node_id_field) = in amdtp_stream_update()
815 (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & in amdtp_stream_update()
827 void amdtp_stream_stop(struct amdtp_stream *s) in amdtp_stream_stop() argument
829 mutex_lock(&s->mutex); in amdtp_stream_stop()
831 if (!amdtp_stream_running(s)) { in amdtp_stream_stop()
832 mutex_unlock(&s->mutex); in amdtp_stream_stop()
836 tasklet_kill(&s->period_tasklet); in amdtp_stream_stop()
837 fw_iso_context_stop(s->context); in amdtp_stream_stop()
838 fw_iso_context_destroy(s->context); in amdtp_stream_stop()
839 s->context = ERR_PTR(-1); in amdtp_stream_stop()
840 iso_packets_buffer_destroy(&s->buffer, s->unit); in amdtp_stream_stop()
842 s->callbacked = false; in amdtp_stream_stop()
844 mutex_unlock(&s->mutex); in amdtp_stream_stop()
855 void amdtp_stream_pcm_abort(struct amdtp_stream *s) in amdtp_stream_pcm_abort() argument
859 pcm = ACCESS_ONCE(s->pcm); in amdtp_stream_pcm_abort()