• Home
  • Raw
  • Download

Lines Matching full:s

66  * @s: the AMDTP stream to initialize
74 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, in amdtp_stream_init() argument
83 s->protocol = kzalloc(protocol_size, GFP_KERNEL); in amdtp_stream_init()
84 if (!s->protocol) in amdtp_stream_init()
87 s->unit = unit; in amdtp_stream_init()
88 s->direction = dir; in amdtp_stream_init()
89 s->flags = flags; in amdtp_stream_init()
90 s->context = ERR_PTR(-1); in amdtp_stream_init()
91 mutex_init(&s->mutex); in amdtp_stream_init()
92 tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); in amdtp_stream_init()
93 s->packet_index = 0; in amdtp_stream_init()
95 init_waitqueue_head(&s->callback_wait); in amdtp_stream_init()
96 s->callbacked = false; in amdtp_stream_init()
98 s->fmt = fmt; in amdtp_stream_init()
99 s->process_data_blocks = process_data_blocks; in amdtp_stream_init()
107 * @s: the AMDTP stream to destroy
109 void amdtp_stream_destroy(struct amdtp_stream *s) in amdtp_stream_destroy() argument
112 if (s->protocol == NULL) in amdtp_stream_destroy()
115 WARN_ON(amdtp_stream_running(s)); in amdtp_stream_destroy()
116 kfree(s->protocol); in amdtp_stream_destroy()
117 mutex_destroy(&s->mutex); in amdtp_stream_destroy()
145 * @s: the AMDTP stream, which must be initialized.
148 int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, in amdtp_stream_add_pcm_hw_constraints() argument
189 if (!(s->flags & CIP_BLOCKING)) in amdtp_stream_add_pcm_hw_constraints()
195 * depending on its sampling rate. For accurate period interrupt, it's in amdtp_stream_add_pcm_hw_constraints()
214 * @s: the AMDTP stream to configure
221 int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, in amdtp_stream_set_parameters() argument
233 s->sfc = sfc; in amdtp_stream_set_parameters()
234 s->data_block_quadlets = data_block_quadlets; in amdtp_stream_set_parameters()
235 s->syt_interval = amdtp_syt_intervals[sfc]; in amdtp_stream_set_parameters()
238 s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; in amdtp_stream_set_parameters()
239 if (s->flags & CIP_BLOCKING) in amdtp_stream_set_parameters()
241 s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; in amdtp_stream_set_parameters()
248 * amdtp_stream_get_max_payload - get the stream's packet size
249 * @s: the AMDTP stream
254 unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) in amdtp_stream_get_max_payload() argument
259 if (s->flags & CIP_JUMBO_PAYLOAD) in amdtp_stream_get_max_payload()
261 if (!(s->flags & CIP_NO_HEADER)) in amdtp_stream_get_max_payload()
265 s->syt_interval * s->data_block_quadlets * 4 * multiplier; in amdtp_stream_get_max_payload()
271 * @s: the AMDTP stream
273 * This function should be called from the PCM device's .prepare callback.
275 void amdtp_stream_pcm_prepare(struct amdtp_stream *s) in amdtp_stream_pcm_prepare() argument
277 tasklet_kill(&s->period_tasklet); in amdtp_stream_pcm_prepare()
278 s->pcm_buffer_pointer = 0; in amdtp_stream_pcm_prepare()
279 s->pcm_period_pointer = 0; in amdtp_stream_pcm_prepare()
283 static unsigned int calculate_data_blocks(struct amdtp_stream *s, in calculate_data_blocks() argument
289 if (s->flags & CIP_BLOCKING) { in calculate_data_blocks()
294 data_blocks = s->syt_interval; in calculate_data_blocks()
297 if (!cip_sfc_is_base_44100(s->sfc)) { in calculate_data_blocks()
299 data_blocks = s->data_block_state; in calculate_data_blocks()
301 phase = s->data_block_state; in calculate_data_blocks()
309 * device's buffer). in calculate_data_blocks()
311 if (s->sfc == CIP_SFC_44100) in calculate_data_blocks()
317 data_blocks = 11 * (s->sfc >> 1) + (phase == 0); in calculate_data_blocks()
318 if (++phase >= (80 >> (s->sfc >> 1))) in calculate_data_blocks()
320 s->data_block_state = phase; in calculate_data_blocks()
327 static unsigned int calculate_syt(struct amdtp_stream *s, in calculate_syt() argument
332 if (s->last_syt_offset < TICKS_PER_CYCLE) { in calculate_syt()
333 if (!cip_sfc_is_base_44100(s->sfc)) in calculate_syt()
334 syt_offset = s->last_syt_offset + s->syt_offset_state; in calculate_syt()
346 phase = s->syt_offset_state; in calculate_syt()
348 syt_offset = s->last_syt_offset; in calculate_syt()
353 s->syt_offset_state = phase; in calculate_syt()
356 syt_offset = s->last_syt_offset - TICKS_PER_CYCLE; in calculate_syt()
357 s->last_syt_offset = syt_offset; in calculate_syt()
360 syt_offset += s->transfer_delay; in calculate_syt()
370 static void update_pcm_pointers(struct amdtp_stream *s, in update_pcm_pointers() argument
376 ptr = s->pcm_buffer_pointer + frames; in update_pcm_pointers()
379 WRITE_ONCE(s->pcm_buffer_pointer, ptr); in update_pcm_pointers()
381 s->pcm_period_pointer += frames; in update_pcm_pointers()
382 if (s->pcm_period_pointer >= pcm->runtime->period_size) { in update_pcm_pointers()
383 s->pcm_period_pointer -= pcm->runtime->period_size; in update_pcm_pointers()
384 tasklet_hi_schedule(&s->period_tasklet); in update_pcm_pointers()
390 struct amdtp_stream *s = (void *)data; in pcm_period_tasklet() local
391 struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); in pcm_period_tasklet()
397 static int queue_packet(struct amdtp_stream *s, unsigned int header_length, in queue_packet() argument
403 if (IS_ERR(s->context)) in queue_packet()
406 p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); in queue_packet()
407 p.tag = s->tag; in queue_packet()
413 err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer, in queue_packet()
414 s->buffer.packets[s->packet_index].offset); in queue_packet()
416 dev_err(&s->unit->device, "queueing error: %d\n", err); in queue_packet()
420 if (++s->packet_index >= QUEUE_LENGTH) in queue_packet()
421 s->packet_index = 0; in queue_packet()
426 static inline int queue_out_packet(struct amdtp_stream *s, in queue_out_packet() argument
429 return queue_packet(s, OUT_PACKET_HEADER_SIZE, payload_length); in queue_out_packet()
432 static inline int queue_in_packet(struct amdtp_stream *s) in queue_in_packet() argument
434 return queue_packet(s, IN_PACKET_HEADER_SIZE, s->max_payload_length); in queue_in_packet()
437 static int handle_out_packet(struct amdtp_stream *s, in handle_out_packet() argument
447 buffer = s->buffer.packets[s->packet_index].buffer; in handle_out_packet()
448 syt = calculate_syt(s, cycle); in handle_out_packet()
449 data_blocks = calculate_data_blocks(s, syt); in handle_out_packet()
450 pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); in handle_out_packet()
452 if (s->flags & CIP_DBC_IS_END_EVENT) in handle_out_packet()
453 s->data_block_counter = in handle_out_packet()
454 (s->data_block_counter + data_blocks) & 0xff; in handle_out_packet()
456 buffer[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | in handle_out_packet()
457 (s->data_block_quadlets << CIP_DBS_SHIFT) | in handle_out_packet()
458 ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | in handle_out_packet()
459 s->data_block_counter); in handle_out_packet()
461 ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | in handle_out_packet()
462 ((s->fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | in handle_out_packet()
465 if (!(s->flags & CIP_DBC_IS_END_EVENT)) in handle_out_packet()
466 s->data_block_counter = in handle_out_packet()
467 (s->data_block_counter + data_blocks) & 0xff; in handle_out_packet()
468 payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; in handle_out_packet()
470 trace_out_packet(s, cycle, buffer, payload_length, index); in handle_out_packet()
472 if (queue_out_packet(s, payload_length) < 0) in handle_out_packet()
475 pcm = READ_ONCE(s->pcm); in handle_out_packet()
477 update_pcm_pointers(s, pcm, pcm_frames); in handle_out_packet()
483 static int handle_out_packet_without_header(struct amdtp_stream *s, in handle_out_packet_without_header() argument
493 buffer = s->buffer.packets[s->packet_index].buffer; in handle_out_packet_without_header()
494 syt = calculate_syt(s, cycle); in handle_out_packet_without_header()
495 data_blocks = calculate_data_blocks(s, syt); in handle_out_packet_without_header()
496 pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt); in handle_out_packet_without_header()
497 s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; in handle_out_packet_without_header()
499 payload_length = data_blocks * 4 * s->data_block_quadlets; in handle_out_packet_without_header()
501 trace_out_packet_without_header(s, cycle, payload_length, data_blocks, in handle_out_packet_without_header()
504 if (queue_out_packet(s, payload_length) < 0) in handle_out_packet_without_header()
507 pcm = READ_ONCE(s->pcm); in handle_out_packet_without_header()
509 update_pcm_pointers(s, pcm, pcm_frames); in handle_out_packet_without_header()
515 static int handle_in_packet(struct amdtp_stream *s, in handle_in_packet() argument
528 buffer = s->buffer.packets[s->packet_index].buffer; in handle_in_packet()
532 trace_in_packet(s, cycle, cip_header, payload_length, index); in handle_in_packet()
540 (!(s->flags & CIP_HEADER_WITHOUT_EOH))) { in handle_in_packet()
541 dev_info_ratelimited(&s->unit->device, in handle_in_packet()
552 if (sph != s->sph || fmt != s->fmt) { in handle_in_packet()
553 dev_info_ratelimited(&s->unit->device, in handle_in_packet()
571 dev_err(&s->unit->device, in handle_in_packet()
576 if (s->flags & CIP_WRONG_DBS) in handle_in_packet()
577 data_block_quadlets = s->data_block_quadlets; in handle_in_packet()
585 if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && in handle_in_packet()
586 s->data_block_counter != UINT_MAX) in handle_in_packet()
587 data_block_counter = s->data_block_counter; in handle_in_packet()
589 if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && in handle_in_packet()
590 data_block_counter == s->tx_first_dbc) || in handle_in_packet()
591 s->data_block_counter == UINT_MAX) { in handle_in_packet()
593 } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { in handle_in_packet()
594 lost = data_block_counter != s->data_block_counter; in handle_in_packet()
596 if (data_blocks > 0 && s->tx_dbc_interval > 0) in handle_in_packet()
597 dbc_interval = s->tx_dbc_interval; in handle_in_packet()
602 ((s->data_block_counter + dbc_interval) & 0xff); in handle_in_packet()
606 dev_err(&s->unit->device, in handle_in_packet()
608 s->data_block_counter, data_block_counter); in handle_in_packet()
613 pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt); in handle_in_packet()
615 if (s->flags & CIP_DBC_IS_END_EVENT) in handle_in_packet()
616 s->data_block_counter = data_block_counter; in handle_in_packet()
618 s->data_block_counter = in handle_in_packet()
621 if (queue_in_packet(s) < 0) in handle_in_packet()
624 pcm = READ_ONCE(s->pcm); in handle_in_packet()
626 update_pcm_pointers(s, pcm, pcm_frames); in handle_in_packet()
631 static int handle_in_packet_without_header(struct amdtp_stream *s, in handle_in_packet_without_header() argument
641 buffer = s->buffer.packets[s->packet_index].buffer; in handle_in_packet_without_header()
643 data_blocks = payload_quadlets / s->data_block_quadlets; in handle_in_packet_without_header()
645 trace_in_packet_without_header(s, cycle, payload_quadlets, data_blocks, in handle_in_packet_without_header()
648 pcm_frames = s->process_data_blocks(s, buffer, data_blocks, NULL); in handle_in_packet_without_header()
649 s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; in handle_in_packet_without_header()
651 if (queue_in_packet(s) < 0) in handle_in_packet_without_header()
654 pcm = READ_ONCE(s->pcm); in handle_in_packet_without_header()
656 update_pcm_pointers(s, pcm, pcm_frames); in handle_in_packet_without_header()
690 struct amdtp_stream *s = private_data; in out_stream_callback() local
694 if (s->packet_index < 0) in out_stream_callback()
704 if (s->handle_packet(s, 0, cycle, i) < 0) { in out_stream_callback()
705 s->packet_index = -1; in out_stream_callback()
707 amdtp_stream_pcm_abort(s); in out_stream_callback()
708 WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); in out_stream_callback()
713 fw_iso_context_queue_flush(s->context); in out_stream_callback()
720 struct amdtp_stream *s = private_data; in in_stream_callback() local
726 if (s->packet_index < 0) in in_stream_callback()
738 max_payload_length = s->max_payload_length; in in_stream_callback()
747 dev_err(&s->unit->device, in in_stream_callback()
753 if (s->handle_packet(s, payload_length, cycle, i) < 0) in in_stream_callback()
759 s->packet_index = -1; in in_stream_callback()
761 amdtp_stream_pcm_abort(s); in in_stream_callback()
762 WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); in in_stream_callback()
766 fw_iso_context_queue_flush(s->context); in in_stream_callback()
774 struct amdtp_stream *s = private_data; in amdtp_stream_first_callback() local
782 s->callbacked = true; in amdtp_stream_first_callback()
783 wake_up(&s->callback_wait); in amdtp_stream_first_callback()
787 if (s->direction == AMDTP_IN_STREAM) { in amdtp_stream_first_callback()
791 if (s->flags & CIP_NO_HEADER) in amdtp_stream_first_callback()
792 s->handle_packet = handle_in_packet_without_header; in amdtp_stream_first_callback()
794 s->handle_packet = handle_in_packet; in amdtp_stream_first_callback()
799 if (s->flags & CIP_NO_HEADER) in amdtp_stream_first_callback()
800 s->handle_packet = handle_out_packet_without_header; in amdtp_stream_first_callback()
802 s->handle_packet = handle_out_packet; in amdtp_stream_first_callback()
805 s->start_cycle = cycle; in amdtp_stream_first_callback()
807 context->callback.sc(context, tstamp, header_length, header, s); in amdtp_stream_first_callback()
812 * @s: the AMDTP stream to start
820 int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) in amdtp_stream_start() argument
838 mutex_lock(&s->mutex); in amdtp_stream_start()
840 if (WARN_ON(amdtp_stream_running(s) || in amdtp_stream_start()
841 (s->data_block_quadlets < 1))) { in amdtp_stream_start()
846 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_start()
847 s->data_block_counter = UINT_MAX; in amdtp_stream_start()
849 s->data_block_counter = 0; in amdtp_stream_start()
850 s->data_block_state = initial_state[s->sfc].data_block; in amdtp_stream_start()
851 s->syt_offset_state = initial_state[s->sfc].syt_offset; in amdtp_stream_start()
852 s->last_syt_offset = TICKS_PER_CYCLE; in amdtp_stream_start()
855 if (s->direction == AMDTP_IN_STREAM) { in amdtp_stream_start()
864 err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, in amdtp_stream_start()
865 amdtp_stream_get_max_payload(s), dir); in amdtp_stream_start()
869 s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, in amdtp_stream_start()
871 amdtp_stream_first_callback, s); in amdtp_stream_start()
872 if (IS_ERR(s->context)) { in amdtp_stream_start()
873 err = PTR_ERR(s->context); in amdtp_stream_start()
875 dev_err(&s->unit->device, in amdtp_stream_start()
880 amdtp_stream_update(s); in amdtp_stream_start()
882 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_start()
883 s->max_payload_length = amdtp_stream_get_max_payload(s); in amdtp_stream_start()
885 if (s->flags & CIP_NO_HEADER) in amdtp_stream_start()
886 s->tag = TAG_NO_CIP_HEADER; in amdtp_stream_start()
888 s->tag = TAG_CIP; in amdtp_stream_start()
890 s->packet_index = 0; in amdtp_stream_start()
892 if (s->direction == AMDTP_IN_STREAM) in amdtp_stream_start()
893 err = queue_in_packet(s); in amdtp_stream_start()
895 err = queue_out_packet(s, 0); in amdtp_stream_start()
898 } while (s->packet_index > 0); in amdtp_stream_start()
902 if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER)) in amdtp_stream_start()
905 s->callbacked = false; in amdtp_stream_start()
906 err = fw_iso_context_start(s->context, -1, 0, tag); in amdtp_stream_start()
910 mutex_unlock(&s->mutex); in amdtp_stream_start()
915 fw_iso_context_destroy(s->context); in amdtp_stream_start()
916 s->context = ERR_PTR(-1); in amdtp_stream_start()
918 iso_packets_buffer_destroy(&s->buffer, s->unit); in amdtp_stream_start()
920 mutex_unlock(&s->mutex); in amdtp_stream_start()
928 * @s: the AMDTP stream that transports the PCM data
932 unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s) in amdtp_stream_pcm_pointer() argument
950 if (!in_interrupt() && amdtp_stream_running(s)) in amdtp_stream_pcm_pointer()
951 fw_iso_context_flush_completions(s->context); in amdtp_stream_pcm_pointer()
953 return READ_ONCE(s->pcm_buffer_pointer); in amdtp_stream_pcm_pointer()
959 * @s: the AMDTP stream that transfers the PCM frames
963 int amdtp_stream_pcm_ack(struct amdtp_stream *s) in amdtp_stream_pcm_ack() argument
969 if (amdtp_stream_running(s)) in amdtp_stream_pcm_ack()
970 fw_iso_context_flush_completions(s->context); in amdtp_stream_pcm_ack()
978 * @s: the AMDTP stream
980 void amdtp_stream_update(struct amdtp_stream *s) in amdtp_stream_update() argument
983 WRITE_ONCE(s->source_node_id_field, in amdtp_stream_update()
984 (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & CIP_SID_MASK); in amdtp_stream_update()
990 * @s: the AMDTP stream to stop
995 void amdtp_stream_stop(struct amdtp_stream *s) in amdtp_stream_stop() argument
997 mutex_lock(&s->mutex); in amdtp_stream_stop()
999 if (!amdtp_stream_running(s)) { in amdtp_stream_stop()
1000 mutex_unlock(&s->mutex); in amdtp_stream_stop()
1004 tasklet_kill(&s->period_tasklet); in amdtp_stream_stop()
1005 fw_iso_context_stop(s->context); in amdtp_stream_stop()
1006 fw_iso_context_destroy(s->context); in amdtp_stream_stop()
1007 s->context = ERR_PTR(-1); in amdtp_stream_stop()
1008 iso_packets_buffer_destroy(&s->buffer, s->unit); in amdtp_stream_stop()
1010 s->callbacked = false; in amdtp_stream_stop()
1012 mutex_unlock(&s->mutex); in amdtp_stream_stop()
1018 * @s: the AMDTP stream about to be stopped
1023 void amdtp_stream_pcm_abort(struct amdtp_stream *s) in amdtp_stream_pcm_abort() argument
1027 pcm = READ_ONCE(s->pcm); in amdtp_stream_pcm_abort()