1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 231ef9134SClemens Ladisch /* 331ef9134SClemens Ladisch * Audio and Music Data Transmission Protocol (IEC 61883-6) streams 431ef9134SClemens Ladisch * with Common Isochronous Packet (IEC 61883-1) headers 531ef9134SClemens Ladisch * 631ef9134SClemens Ladisch * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 731ef9134SClemens Ladisch */ 831ef9134SClemens Ladisch 931ef9134SClemens Ladisch #include <linux/device.h> 1031ef9134SClemens Ladisch #include <linux/err.h> 1131ef9134SClemens Ladisch #include <linux/firewire.h> 12*acfedcbeSTakashi Sakamoto #include <linux/firewire-constants.h> 1331ef9134SClemens Ladisch #include <linux/module.h> 1431ef9134SClemens Ladisch #include <linux/slab.h> 1531ef9134SClemens Ladisch #include <sound/pcm.h> 167b2d99faSTakashi Sakamoto #include <sound/pcm_params.h> 17d67c46b9STakashi Sakamoto #include "amdtp-stream.h" 1831ef9134SClemens Ladisch 1931ef9134SClemens Ladisch #define TICKS_PER_CYCLE 3072 2031ef9134SClemens Ladisch #define CYCLES_PER_SECOND 8000 2131ef9134SClemens Ladisch #define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) 2231ef9134SClemens Ladisch 230c95c1d6STakashi Sakamoto /* Always support Linux tracing subsystem. */ 240c95c1d6STakashi Sakamoto #define CREATE_TRACE_POINTS 250c95c1d6STakashi Sakamoto #include "amdtp-stream-trace.h" 260c95c1d6STakashi Sakamoto 27ca5b5050STakashi Sakamoto #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 microseconds */ 2831ef9134SClemens Ladisch 29b445db44STakashi Sakamoto /* isochronous header parameters */ 30b445db44STakashi Sakamoto #define ISO_DATA_LENGTH_SHIFT 16 313b196c39STakashi Sakamoto #define TAG_NO_CIP_HEADER 0 3231ef9134SClemens Ladisch #define TAG_CIP 1 3331ef9134SClemens Ladisch 34b445db44STakashi Sakamoto /* common isochronous packet header parameters */ 359a2820c1STakashi Sakamoto #define CIP_EOH_SHIFT 31 369a2820c1STakashi Sakamoto #define CIP_EOH (1u << CIP_EOH_SHIFT) 37b445db44STakashi Sakamoto #define CIP_EOH_MASK 0x80000000 389a2820c1STakashi Sakamoto #define CIP_SID_SHIFT 24 399a2820c1STakashi Sakamoto #define CIP_SID_MASK 0x3f000000 409a2820c1STakashi Sakamoto #define CIP_DBS_MASK 0x00ff0000 419a2820c1STakashi Sakamoto #define CIP_DBS_SHIFT 16 429863874fSTakashi Sakamoto #define CIP_SPH_MASK 0x00000400 439863874fSTakashi Sakamoto #define CIP_SPH_SHIFT 10 449a2820c1STakashi Sakamoto #define CIP_DBC_MASK 0x000000ff 459a2820c1STakashi Sakamoto #define CIP_FMT_SHIFT 24 46b445db44STakashi Sakamoto #define CIP_FMT_MASK 0x3f000000 479a2820c1STakashi Sakamoto #define CIP_FDF_MASK 0x00ff0000 489a2820c1STakashi Sakamoto #define CIP_FDF_SHIFT 16 49b445db44STakashi Sakamoto #define CIP_SYT_MASK 0x0000ffff 50b445db44STakashi Sakamoto #define CIP_SYT_NO_INFO 0xffff 51b445db44STakashi Sakamoto 5251c29fd2STakashi Sakamoto /* Audio and Music transfer protocol specific parameters */ 53414ba022STakashi Sakamoto #define CIP_FMT_AM 0x10 542b3fc456STakashi Sakamoto #define AMDTP_FDF_NO_DATA 0xff 5531ef9134SClemens Ladisch 56f11453c7STakashi Sakamoto // For iso header, tstamp and 2 CIP header. 57f11453c7STakashi Sakamoto #define IR_CTX_HEADER_SIZE_CIP 16 58f11453c7STakashi Sakamoto // For iso header and tstamp. 59f11453c7STakashi Sakamoto #define IR_CTX_HEADER_SIZE_NO_CIP 8 60cc4f8e91STakashi Sakamoto #define HEADER_TSTAMP_MASK 0x0000ffff 614b7da117STakashi Sakamoto 62b18f0cfaSTakashi Sakamoto #define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header. 63b18f0cfaSTakashi Sakamoto #define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing. 64b18f0cfaSTakashi Sakamoto 6576fb8789SClemens Ladisch static void pcm_period_tasklet(unsigned long data); 6676fb8789SClemens Ladisch 6731ef9134SClemens Ladisch /** 68be4a2894STakashi Sakamoto * amdtp_stream_init - initialize an AMDTP stream structure 69be4a2894STakashi Sakamoto * @s: the AMDTP stream to initialize 7031ef9134SClemens Ladisch * @unit: the target of the stream 713ff7e8f0STakashi Sakamoto * @dir: the direction of stream 7231ef9134SClemens Ladisch * @flags: the packet transmission method to use 735955815eSTakashi Sakamoto * @fmt: the value of fmt field in CIP header 749a738ad1STakashi Sakamoto * @process_ctx_payloads: callback handler to process payloads of isoc context 75df075feeSTakashi Sakamoto * @protocol_size: the size to allocate newly for protocol 7631ef9134SClemens Ladisch */ 77be4a2894STakashi Sakamoto int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, 785955815eSTakashi Sakamoto enum amdtp_stream_direction dir, enum cip_flags flags, 79df075feeSTakashi Sakamoto unsigned int fmt, 809a738ad1STakashi Sakamoto amdtp_stream_process_ctx_payloads_t process_ctx_payloads, 81df075feeSTakashi Sakamoto unsigned int protocol_size) 8231ef9134SClemens Ladisch { 839a738ad1STakashi Sakamoto if (process_ctx_payloads == NULL) 84df075feeSTakashi Sakamoto return -EINVAL; 85df075feeSTakashi Sakamoto 86df075feeSTakashi Sakamoto s->protocol = kzalloc(protocol_size, GFP_KERNEL); 87df075feeSTakashi Sakamoto if (!s->protocol) 88df075feeSTakashi Sakamoto return -ENOMEM; 89df075feeSTakashi Sakamoto 90c6f224dcSTakashi Sakamoto s->unit = unit; 913ff7e8f0STakashi Sakamoto s->direction = dir; 9231ef9134SClemens Ladisch s->flags = flags; 9331ef9134SClemens Ladisch s->context = ERR_PTR(-1); 9431ef9134SClemens Ladisch mutex_init(&s->mutex); 9576fb8789SClemens Ladisch tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); 96ec00f5e4SClemens Ladisch s->packet_index = 0; 9731ef9134SClemens Ladisch 987b3b0d85STakashi Sakamoto init_waitqueue_head(&s->callback_wait); 997b3b0d85STakashi Sakamoto s->callbacked = false; 1007b3b0d85STakashi Sakamoto 1015955815eSTakashi Sakamoto s->fmt = fmt; 1029a738ad1STakashi Sakamoto s->process_ctx_payloads = process_ctx_payloads; 103414ba022STakashi Sakamoto 1043baf3053STakashi Sakamoto if (dir == AMDTP_OUT_STREAM) 1053baf3053STakashi Sakamoto s->ctx_data.rx.syt_override = -1; 1063baf3053STakashi Sakamoto 10731ef9134SClemens Ladisch return 0; 10831ef9134SClemens Ladisch } 109be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_init); 11031ef9134SClemens Ladisch 11131ef9134SClemens Ladisch /** 112be4a2894STakashi Sakamoto * amdtp_stream_destroy - free stream resources 113be4a2894STakashi Sakamoto * @s: the AMDTP stream to destroy 11431ef9134SClemens Ladisch */ 115be4a2894STakashi Sakamoto void amdtp_stream_destroy(struct amdtp_stream *s) 11631ef9134SClemens Ladisch { 11744c376b9STakashi Sakamoto /* Not initialized. */ 11844c376b9STakashi Sakamoto if (s->protocol == NULL) 11944c376b9STakashi Sakamoto return; 12044c376b9STakashi Sakamoto 121be4a2894STakashi Sakamoto WARN_ON(amdtp_stream_running(s)); 122df075feeSTakashi Sakamoto kfree(s->protocol); 12331ef9134SClemens Ladisch mutex_destroy(&s->mutex); 12431ef9134SClemens Ladisch } 125be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_destroy); 12631ef9134SClemens Ladisch 127c5280e99SClemens Ladisch const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = { 128a7304e3bSClemens Ladisch [CIP_SFC_32000] = 8, 129a7304e3bSClemens Ladisch [CIP_SFC_44100] = 8, 130a7304e3bSClemens Ladisch [CIP_SFC_48000] = 8, 131a7304e3bSClemens Ladisch [CIP_SFC_88200] = 16, 132a7304e3bSClemens Ladisch [CIP_SFC_96000] = 16, 133a7304e3bSClemens Ladisch [CIP_SFC_176400] = 32, 134a7304e3bSClemens Ladisch [CIP_SFC_192000] = 32, 135a7304e3bSClemens Ladisch }; 136a7304e3bSClemens Ladisch EXPORT_SYMBOL(amdtp_syt_intervals); 137a7304e3bSClemens Ladisch 138f9503a68STakashi Sakamoto const unsigned int amdtp_rate_table[CIP_SFC_COUNT] = { 1391017abedSTakashi Sakamoto [CIP_SFC_32000] = 32000, 1401017abedSTakashi Sakamoto [CIP_SFC_44100] = 44100, 1411017abedSTakashi Sakamoto [CIP_SFC_48000] = 48000, 1421017abedSTakashi Sakamoto [CIP_SFC_88200] = 88200, 1431017abedSTakashi Sakamoto [CIP_SFC_96000] = 96000, 1441017abedSTakashi Sakamoto [CIP_SFC_176400] = 176400, 1451017abedSTakashi Sakamoto [CIP_SFC_192000] = 192000, 1461017abedSTakashi Sakamoto }; 1471017abedSTakashi Sakamoto EXPORT_SYMBOL(amdtp_rate_table); 1481017abedSTakashi Sakamoto 14959502295STakashi Sakamoto static int apply_constraint_to_size(struct snd_pcm_hw_params *params, 15059502295STakashi Sakamoto struct snd_pcm_hw_rule *rule) 15159502295STakashi Sakamoto { 15259502295STakashi Sakamoto struct snd_interval *s = hw_param_interval(params, rule->var); 15359502295STakashi Sakamoto const struct snd_interval *r = 15459502295STakashi Sakamoto hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); 155826b5de9STakashi Sakamoto struct snd_interval t = {0}; 156826b5de9STakashi Sakamoto unsigned int step = 0; 15759502295STakashi Sakamoto int i; 15859502295STakashi Sakamoto 15959502295STakashi Sakamoto for (i = 0; i < CIP_SFC_COUNT; ++i) { 160826b5de9STakashi Sakamoto if (snd_interval_test(r, amdtp_rate_table[i])) 161826b5de9STakashi Sakamoto step = max(step, amdtp_syt_intervals[i]); 16259502295STakashi Sakamoto } 16359502295STakashi Sakamoto 164826b5de9STakashi Sakamoto t.min = roundup(s->min, step); 165826b5de9STakashi Sakamoto t.max = rounddown(s->max, step); 166826b5de9STakashi Sakamoto t.integer = 1; 16759502295STakashi Sakamoto 16859502295STakashi Sakamoto return snd_interval_refine(s, &t); 16959502295STakashi Sakamoto } 17059502295STakashi Sakamoto 17131ef9134SClemens Ladisch /** 1727b2d99faSTakashi Sakamoto * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream 1737b2d99faSTakashi Sakamoto * @s: the AMDTP stream, which must be initialized. 1747b2d99faSTakashi Sakamoto * @runtime: the PCM substream runtime 1757b2d99faSTakashi Sakamoto */ 1767b2d99faSTakashi Sakamoto int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, 1777b2d99faSTakashi Sakamoto struct snd_pcm_runtime *runtime) 1787b2d99faSTakashi Sakamoto { 17955799c5aSTakashi Sakamoto struct snd_pcm_hardware *hw = &runtime->hw; 18099921ec6STakashi Sakamoto unsigned int ctx_header_size; 18199921ec6STakashi Sakamoto unsigned int maximum_usec_per_period; 1827b2d99faSTakashi Sakamoto int err; 1837b2d99faSTakashi Sakamoto 18455799c5aSTakashi Sakamoto hw->info = SNDRV_PCM_INFO_BATCH | 18555799c5aSTakashi Sakamoto SNDRV_PCM_INFO_BLOCK_TRANSFER | 18655799c5aSTakashi Sakamoto SNDRV_PCM_INFO_INTERLEAVED | 18755799c5aSTakashi Sakamoto SNDRV_PCM_INFO_JOINT_DUPLEX | 18855799c5aSTakashi Sakamoto SNDRV_PCM_INFO_MMAP | 18955799c5aSTakashi Sakamoto SNDRV_PCM_INFO_MMAP_VALID; 19055799c5aSTakashi Sakamoto 19155799c5aSTakashi Sakamoto /* SNDRV_PCM_INFO_BATCH */ 19255799c5aSTakashi Sakamoto hw->periods_min = 2; 19355799c5aSTakashi Sakamoto hw->periods_max = UINT_MAX; 19455799c5aSTakashi Sakamoto 19555799c5aSTakashi Sakamoto /* bytes for a frame */ 19655799c5aSTakashi Sakamoto hw->period_bytes_min = 4 * hw->channels_max; 19755799c5aSTakashi Sakamoto 19855799c5aSTakashi Sakamoto /* Just to prevent from allocating much pages. */ 19955799c5aSTakashi Sakamoto hw->period_bytes_max = hw->period_bytes_min * 2048; 20055799c5aSTakashi Sakamoto hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; 20155799c5aSTakashi Sakamoto 20299921ec6STakashi Sakamoto // Linux driver for 1394 OHCI controller voluntarily flushes isoc 20399921ec6STakashi Sakamoto // context when total size of accumulated context header reaches 20499921ec6STakashi Sakamoto // PAGE_SIZE. This kicks tasklet for the isoc context and brings 20599921ec6STakashi Sakamoto // callback in the middle of scheduled interrupts. 20699921ec6STakashi Sakamoto // Although AMDTP streams in the same domain use the same events per 20799921ec6STakashi Sakamoto // IRQ, use the largest size of context header between IT/IR contexts. 20899921ec6STakashi Sakamoto // Here, use the value of context header in IR context is for both 20999921ec6STakashi Sakamoto // contexts. 21099921ec6STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 21199921ec6STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_CIP; 21299921ec6STakashi Sakamoto else 21399921ec6STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; 21499921ec6STakashi Sakamoto maximum_usec_per_period = USEC_PER_SEC * PAGE_SIZE / 21599921ec6STakashi Sakamoto CYCLES_PER_SECOND / ctx_header_size; 21699921ec6STakashi Sakamoto 217f706df4fSTakashi Sakamoto // In IEC 61883-6, one isoc packet can transfer events up to the value 218f706df4fSTakashi Sakamoto // of syt interval. This comes from the interval of isoc cycle. As 1394 219f706df4fSTakashi Sakamoto // OHCI controller can generate hardware IRQ per isoc packet, the 220f706df4fSTakashi Sakamoto // interval is 125 usec. 221f706df4fSTakashi Sakamoto // However, there are two ways of transmission in IEC 61883-6; blocking 222f706df4fSTakashi Sakamoto // and non-blocking modes. In blocking mode, the sequence of isoc packet 223f706df4fSTakashi Sakamoto // includes 'empty' or 'NODATA' packets which include no event. In 224f706df4fSTakashi Sakamoto // non-blocking mode, the number of events per packet is variable up to 225f706df4fSTakashi Sakamoto // the syt interval. 226f706df4fSTakashi Sakamoto // Due to the above protocol design, the minimum PCM frames per 227f706df4fSTakashi Sakamoto // interrupt should be double of the value of syt interval, thus it is 228f706df4fSTakashi Sakamoto // 250 usec. 2297b2d99faSTakashi Sakamoto err = snd_pcm_hw_constraint_minmax(runtime, 2307b2d99faSTakashi Sakamoto SNDRV_PCM_HW_PARAM_PERIOD_TIME, 231f706df4fSTakashi Sakamoto 250, maximum_usec_per_period); 2327b2d99faSTakashi Sakamoto if (err < 0) 2337b2d99faSTakashi Sakamoto goto end; 2347b2d99faSTakashi Sakamoto 2357b2d99faSTakashi Sakamoto /* Non-Blocking stream has no more constraints */ 2367b2d99faSTakashi Sakamoto if (!(s->flags & CIP_BLOCKING)) 2377b2d99faSTakashi Sakamoto goto end; 2387b2d99faSTakashi Sakamoto 2397b2d99faSTakashi Sakamoto /* 2407b2d99faSTakashi Sakamoto * One AMDTP packet can include some frames. In blocking mode, the 2417b2d99faSTakashi Sakamoto * number equals to SYT_INTERVAL. So the number is 8, 16 or 32, 2427b2d99faSTakashi Sakamoto * depending on its sampling rate. For accurate period interrupt, it's 243ce991981SYannick Guerrini * preferrable to align period/buffer sizes to current SYT_INTERVAL. 2447b2d99faSTakashi Sakamoto */ 24559502295STakashi Sakamoto err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 24659502295STakashi Sakamoto apply_constraint_to_size, NULL, 247826b5de9STakashi Sakamoto SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 24859502295STakashi Sakamoto SNDRV_PCM_HW_PARAM_RATE, -1); 2497b2d99faSTakashi Sakamoto if (err < 0) 2507b2d99faSTakashi Sakamoto goto end; 25159502295STakashi Sakamoto err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 25259502295STakashi Sakamoto apply_constraint_to_size, NULL, 253826b5de9STakashi Sakamoto SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 25459502295STakashi Sakamoto SNDRV_PCM_HW_PARAM_RATE, -1); 25559502295STakashi Sakamoto if (err < 0) 25659502295STakashi Sakamoto goto end; 2577b2d99faSTakashi Sakamoto end: 2587b2d99faSTakashi Sakamoto return err; 2597b2d99faSTakashi Sakamoto } 2607b2d99faSTakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_add_pcm_hw_constraints); 2617b2d99faSTakashi Sakamoto 2627b2d99faSTakashi Sakamoto /** 263be4a2894STakashi Sakamoto * amdtp_stream_set_parameters - set stream parameters 264be4a2894STakashi Sakamoto * @s: the AMDTP stream to configure 26531ef9134SClemens Ladisch * @rate: the sample rate 266df075feeSTakashi Sakamoto * @data_block_quadlets: the size of a data block in quadlet unit 26731ef9134SClemens Ladisch * 268a7304e3bSClemens Ladisch * The parameters must be set before the stream is started, and must not be 26931ef9134SClemens Ladisch * changed while the stream is running. 27031ef9134SClemens Ladisch */ 271df075feeSTakashi Sakamoto int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, 272df075feeSTakashi Sakamoto unsigned int data_block_quadlets) 27331ef9134SClemens Ladisch { 274df075feeSTakashi Sakamoto unsigned int sfc; 27531ef9134SClemens Ladisch 276547e631cSTakashi Sakamoto for (sfc = 0; sfc < ARRAY_SIZE(amdtp_rate_table); ++sfc) { 2771017abedSTakashi Sakamoto if (amdtp_rate_table[sfc] == rate) 278547e631cSTakashi Sakamoto break; 279547e631cSTakashi Sakamoto } 280547e631cSTakashi Sakamoto if (sfc == ARRAY_SIZE(amdtp_rate_table)) 281547e631cSTakashi Sakamoto return -EINVAL; 282e84d15f6SClemens Ladisch 28331ef9134SClemens Ladisch s->sfc = sfc; 284df075feeSTakashi Sakamoto s->data_block_quadlets = data_block_quadlets; 285a7304e3bSClemens Ladisch s->syt_interval = amdtp_syt_intervals[sfc]; 286e84d15f6SClemens Ladisch 287d3d10a4aSTakashi Sakamoto // default buffering in the device. 288d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM) { 289d3d10a4aSTakashi Sakamoto s->ctx_data.rx.transfer_delay = 290d3d10a4aSTakashi Sakamoto TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; 291d3d10a4aSTakashi Sakamoto 292d3d10a4aSTakashi Sakamoto if (s->flags & CIP_BLOCKING) { 293d3d10a4aSTakashi Sakamoto // additional buffering needed to adjust for no-data 294d3d10a4aSTakashi Sakamoto // packets. 295d3d10a4aSTakashi Sakamoto s->ctx_data.rx.transfer_delay += 296d3d10a4aSTakashi Sakamoto TICKS_PER_SECOND * s->syt_interval / rate; 297d3d10a4aSTakashi Sakamoto } 298d3d10a4aSTakashi Sakamoto } 29977d2a8a4STakashi Sakamoto 300547e631cSTakashi Sakamoto return 0; 30131ef9134SClemens Ladisch } 302be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_set_parameters); 30331ef9134SClemens Ladisch 30431ef9134SClemens Ladisch /** 305be4a2894STakashi Sakamoto * amdtp_stream_get_max_payload - get the stream's packet size 306be4a2894STakashi Sakamoto * @s: the AMDTP stream 30731ef9134SClemens Ladisch * 30831ef9134SClemens Ladisch * This function must not be called before the stream has been configured 309be4a2894STakashi Sakamoto * with amdtp_stream_set_parameters(). 31031ef9134SClemens Ladisch */ 311be4a2894STakashi Sakamoto unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) 31231ef9134SClemens Ladisch { 313a2064710STakashi Sakamoto unsigned int multiplier = 1; 31407ea238cSTakashi Sakamoto unsigned int cip_header_size = 0; 315a2064710STakashi Sakamoto 316a2064710STakashi Sakamoto if (s->flags & CIP_JUMBO_PAYLOAD) 317a2064710STakashi Sakamoto multiplier = 5; 3183b196c39STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 31907ea238cSTakashi Sakamoto cip_header_size = sizeof(__be32) * 2; 320a2064710STakashi Sakamoto 32107ea238cSTakashi Sakamoto return cip_header_size + 32207ea238cSTakashi Sakamoto s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier; 32331ef9134SClemens Ladisch } 324be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_get_max_payload); 32531ef9134SClemens Ladisch 32676fb8789SClemens Ladisch /** 327be4a2894STakashi Sakamoto * amdtp_stream_pcm_prepare - prepare PCM device for running 328be4a2894STakashi Sakamoto * @s: the AMDTP stream 32976fb8789SClemens Ladisch * 33076fb8789SClemens Ladisch * This function should be called from the PCM device's .prepare callback. 33176fb8789SClemens Ladisch */ 332be4a2894STakashi Sakamoto void amdtp_stream_pcm_prepare(struct amdtp_stream *s) 33376fb8789SClemens Ladisch { 33476fb8789SClemens Ladisch tasklet_kill(&s->period_tasklet); 33576fb8789SClemens Ladisch s->pcm_buffer_pointer = 0; 33676fb8789SClemens Ladisch s->pcm_period_pointer = 0; 33776fb8789SClemens Ladisch } 338be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_prepare); 33976fb8789SClemens Ladisch 340875be091STakashi Sakamoto static unsigned int calculate_data_blocks(struct amdtp_stream *s, 341875be091STakashi Sakamoto unsigned int syt) 34231ef9134SClemens Ladisch { 34331ef9134SClemens Ladisch unsigned int phase, data_blocks; 34431ef9134SClemens Ladisch 345875be091STakashi Sakamoto /* Blocking mode. */ 346875be091STakashi Sakamoto if (s->flags & CIP_BLOCKING) { 347875be091STakashi Sakamoto /* This module generate empty packet for 'no data'. */ 348875be091STakashi Sakamoto if (syt == CIP_SYT_NO_INFO) 349875be091STakashi Sakamoto data_blocks = 0; 350875be091STakashi Sakamoto else 351ccccad86STakashi Sakamoto data_blocks = s->syt_interval; 352875be091STakashi Sakamoto /* Non-blocking mode. */ 353875be091STakashi Sakamoto } else { 354875be091STakashi Sakamoto if (!cip_sfc_is_base_44100(s->sfc)) { 355d3d10a4aSTakashi Sakamoto // Sample_rate / 8000 is an integer, and precomputed. 356d3d10a4aSTakashi Sakamoto data_blocks = s->ctx_data.rx.data_block_state; 35731ef9134SClemens Ladisch } else { 358d3d10a4aSTakashi Sakamoto phase = s->ctx_data.rx.data_block_state; 35931ef9134SClemens Ladisch 36031ef9134SClemens Ladisch /* 36131ef9134SClemens Ladisch * This calculates the number of data blocks per packet so that 36231ef9134SClemens Ladisch * 1) the overall rate is correct and exactly synchronized to 36331ef9134SClemens Ladisch * the bus clock, and 36431ef9134SClemens Ladisch * 2) packets with a rounded-up number of blocks occur as early 36531ef9134SClemens Ladisch * as possible in the sequence (to prevent underruns of the 36631ef9134SClemens Ladisch * device's buffer). 36731ef9134SClemens Ladisch */ 36831ef9134SClemens Ladisch if (s->sfc == CIP_SFC_44100) 36931ef9134SClemens Ladisch /* 6 6 5 6 5 6 5 ... */ 37031ef9134SClemens Ladisch data_blocks = 5 + ((phase & 1) ^ 37131ef9134SClemens Ladisch (phase == 0 || phase >= 40)); 37231ef9134SClemens Ladisch else 37331ef9134SClemens Ladisch /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ 37431ef9134SClemens Ladisch data_blocks = 11 * (s->sfc >> 1) + (phase == 0); 37531ef9134SClemens Ladisch if (++phase >= (80 >> (s->sfc >> 1))) 37631ef9134SClemens Ladisch phase = 0; 377d3d10a4aSTakashi Sakamoto s->ctx_data.rx.data_block_state = phase; 37831ef9134SClemens Ladisch } 379875be091STakashi Sakamoto } 38031ef9134SClemens Ladisch 38131ef9134SClemens Ladisch return data_blocks; 38231ef9134SClemens Ladisch } 38331ef9134SClemens Ladisch 384be4a2894STakashi Sakamoto static unsigned int calculate_syt(struct amdtp_stream *s, 38531ef9134SClemens Ladisch unsigned int cycle) 38631ef9134SClemens Ladisch { 38731ef9134SClemens Ladisch unsigned int syt_offset, phase, index, syt; 38831ef9134SClemens Ladisch 389d3d10a4aSTakashi Sakamoto if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) { 39031ef9134SClemens Ladisch if (!cip_sfc_is_base_44100(s->sfc)) 391d3d10a4aSTakashi Sakamoto syt_offset = s->ctx_data.rx.last_syt_offset + 392d3d10a4aSTakashi Sakamoto s->ctx_data.rx.syt_offset_state; 39331ef9134SClemens Ladisch else { 39431ef9134SClemens Ladisch /* 39531ef9134SClemens Ladisch * The time, in ticks, of the n'th SYT_INTERVAL sample is: 39631ef9134SClemens Ladisch * n * SYT_INTERVAL * 24576000 / sample_rate 39731ef9134SClemens Ladisch * Modulo TICKS_PER_CYCLE, the difference between successive 39831ef9134SClemens Ladisch * elements is about 1386.23. Rounding the results of this 39931ef9134SClemens Ladisch * formula to the SYT precision results in a sequence of 40031ef9134SClemens Ladisch * differences that begins with: 40131ef9134SClemens Ladisch * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ... 40231ef9134SClemens Ladisch * This code generates _exactly_ the same sequence. 40331ef9134SClemens Ladisch */ 404d3d10a4aSTakashi Sakamoto phase = s->ctx_data.rx.syt_offset_state; 40531ef9134SClemens Ladisch index = phase % 13; 406d3d10a4aSTakashi Sakamoto syt_offset = s->ctx_data.rx.last_syt_offset; 40731ef9134SClemens Ladisch syt_offset += 1386 + ((index && !(index & 3)) || 40831ef9134SClemens Ladisch phase == 146); 40931ef9134SClemens Ladisch if (++phase >= 147) 41031ef9134SClemens Ladisch phase = 0; 411d3d10a4aSTakashi Sakamoto s->ctx_data.rx.syt_offset_state = phase; 41231ef9134SClemens Ladisch } 41331ef9134SClemens Ladisch } else 414d3d10a4aSTakashi Sakamoto syt_offset = s->ctx_data.rx.last_syt_offset - TICKS_PER_CYCLE; 415d3d10a4aSTakashi Sakamoto s->ctx_data.rx.last_syt_offset = syt_offset; 41631ef9134SClemens Ladisch 417be454366SClemens Ladisch if (syt_offset < TICKS_PER_CYCLE) { 418d3d10a4aSTakashi Sakamoto syt_offset += s->ctx_data.rx.transfer_delay; 41931ef9134SClemens Ladisch syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; 42031ef9134SClemens Ladisch syt += syt_offset % TICKS_PER_CYCLE; 42131ef9134SClemens Ladisch 422b445db44STakashi Sakamoto return syt & CIP_SYT_MASK; 423be454366SClemens Ladisch } else { 424b445db44STakashi Sakamoto return CIP_SYT_NO_INFO; 425be454366SClemens Ladisch } 42631ef9134SClemens Ladisch } 42731ef9134SClemens Ladisch 4284b7da117STakashi Sakamoto static void update_pcm_pointers(struct amdtp_stream *s, 4294b7da117STakashi Sakamoto struct snd_pcm_substream *pcm, 4304b7da117STakashi Sakamoto unsigned int frames) 43165845f29STakashi Sakamoto { 43265845f29STakashi Sakamoto unsigned int ptr; 43365845f29STakashi Sakamoto 4344b7da117STakashi Sakamoto ptr = s->pcm_buffer_pointer + frames; 4354b7da117STakashi Sakamoto if (ptr >= pcm->runtime->buffer_size) 4364b7da117STakashi Sakamoto ptr -= pcm->runtime->buffer_size; 4376aa7de05SMark Rutland WRITE_ONCE(s->pcm_buffer_pointer, ptr); 4384b7da117STakashi Sakamoto 4394b7da117STakashi Sakamoto s->pcm_period_pointer += frames; 4404b7da117STakashi Sakamoto if (s->pcm_period_pointer >= pcm->runtime->period_size) { 4414b7da117STakashi Sakamoto s->pcm_period_pointer -= pcm->runtime->period_size; 4424b7da117STakashi Sakamoto tasklet_hi_schedule(&s->period_tasklet); 4434b7da117STakashi Sakamoto } 4444b7da117STakashi Sakamoto } 4454b7da117STakashi Sakamoto 4464b7da117STakashi Sakamoto static void pcm_period_tasklet(unsigned long data) 4474b7da117STakashi Sakamoto { 4484b7da117STakashi Sakamoto struct amdtp_stream *s = (void *)data; 4496aa7de05SMark Rutland struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); 4504b7da117STakashi Sakamoto 4514b7da117STakashi Sakamoto if (pcm) 4524b7da117STakashi Sakamoto snd_pcm_period_elapsed(pcm); 4534b7da117STakashi Sakamoto } 4544b7da117STakashi Sakamoto 455e229853dSTakashi Sakamoto static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params, 456e229853dSTakashi Sakamoto bool sched_irq) 4574b7da117STakashi Sakamoto { 4586007bf54STakashi Sakamoto int err; 4597b3b0d85STakashi Sakamoto 460e229853dSTakashi Sakamoto params->interrupt = sched_irq; 4616007bf54STakashi Sakamoto params->tag = s->tag; 4626007bf54STakashi Sakamoto params->sy = 0; 4634b7da117STakashi Sakamoto 4646007bf54STakashi Sakamoto err = fw_iso_context_queue(s->context, params, &s->buffer.iso_buffer, 4654b7da117STakashi Sakamoto s->buffer.packets[s->packet_index].offset); 4664b7da117STakashi Sakamoto if (err < 0) { 4674b7da117STakashi Sakamoto dev_err(&s->unit->device, "queueing error: %d\n", err); 4684b7da117STakashi Sakamoto goto end; 4694b7da117STakashi Sakamoto } 4704b7da117STakashi Sakamoto 471a0e02331STakashi Sakamoto if (++s->packet_index >= s->queue_size) 4724b7da117STakashi Sakamoto s->packet_index = 0; 4734b7da117STakashi Sakamoto end: 4744b7da117STakashi Sakamoto return err; 4754b7da117STakashi Sakamoto } 4764b7da117STakashi Sakamoto 4774b7da117STakashi Sakamoto static inline int queue_out_packet(struct amdtp_stream *s, 478e229853dSTakashi Sakamoto struct fw_iso_packet *params, bool sched_irq) 4794b7da117STakashi Sakamoto { 480b18f0cfaSTakashi Sakamoto params->skip = 481b18f0cfaSTakashi Sakamoto !!(params->header_length == 0 && params->payload_length == 0); 482e229853dSTakashi Sakamoto return queue_packet(s, params, sched_irq); 4834b7da117STakashi Sakamoto } 4844b7da117STakashi Sakamoto 4856007bf54STakashi Sakamoto static inline int queue_in_packet(struct amdtp_stream *s, 48660dd4929STakashi Sakamoto struct fw_iso_packet *params) 4872b3fc456STakashi Sakamoto { 4886007bf54STakashi Sakamoto // Queue one packet for IR context. 4896007bf54STakashi Sakamoto params->header_length = s->ctx_data.tx.ctx_header_size; 4906007bf54STakashi Sakamoto params->payload_length = s->ctx_data.tx.max_ctx_payload_length; 4916007bf54STakashi Sakamoto params->skip = false; 49260dd4929STakashi Sakamoto return queue_packet(s, params, false); 4932b3fc456STakashi Sakamoto } 4942b3fc456STakashi Sakamoto 495252219c7STakashi Sakamoto static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], 496860d798cSTakashi Sakamoto unsigned int data_block_counter, unsigned int syt) 497252219c7STakashi Sakamoto { 498252219c7STakashi Sakamoto cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | 499252219c7STakashi Sakamoto (s->data_block_quadlets << CIP_DBS_SHIFT) | 500252219c7STakashi Sakamoto ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | 501860d798cSTakashi Sakamoto data_block_counter); 502252219c7STakashi Sakamoto cip_header[1] = cpu_to_be32(CIP_EOH | 503252219c7STakashi Sakamoto ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | 504252219c7STakashi Sakamoto ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | 505252219c7STakashi Sakamoto (syt & CIP_SYT_MASK)); 506252219c7STakashi Sakamoto } 507252219c7STakashi Sakamoto 5086bc1a269STakashi Sakamoto static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, 5096bc1a269STakashi Sakamoto struct fw_iso_packet *params, 510860d798cSTakashi Sakamoto unsigned int data_blocks, 511860d798cSTakashi Sakamoto unsigned int data_block_counter, 512860d798cSTakashi Sakamoto unsigned int syt, unsigned int index) 51331ef9134SClemens Ladisch { 5140ebf3cebSTakashi Sakamoto unsigned int payload_length; 51516be4589STakashi Sakamoto __be32 *cip_header; 51631ef9134SClemens Ladisch 5170ebf3cebSTakashi Sakamoto payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; 5180ebf3cebSTakashi Sakamoto params->payload_length = payload_length; 5190ebf3cebSTakashi Sakamoto 520b18f0cfaSTakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) { 5216bc1a269STakashi Sakamoto cip_header = (__be32 *)params->header; 522860d798cSTakashi Sakamoto generate_cip_header(s, cip_header, data_block_counter, syt); 5236bc1a269STakashi Sakamoto params->header_length = 2 * sizeof(__be32); 5240ebf3cebSTakashi Sakamoto payload_length += params->header_length; 525b18f0cfaSTakashi Sakamoto } else { 526b18f0cfaSTakashi Sakamoto cip_header = NULL; 527b18f0cfaSTakashi Sakamoto } 52831ef9134SClemens Ladisch 529213fa989STakashi Sakamoto trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, 530860d798cSTakashi Sakamoto data_block_counter, index); 5313b196c39STakashi Sakamoto } 5323b196c39STakashi Sakamoto 533e335425bSTakashi Sakamoto static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, 534e335425bSTakashi Sakamoto unsigned int payload_length, 535a35463d1STakashi Sakamoto unsigned int *data_blocks, 536a35463d1STakashi Sakamoto unsigned int *data_block_counter, unsigned int *syt) 5372b3fc456STakashi Sakamoto { 5382b3fc456STakashi Sakamoto u32 cip_header[2]; 539e335425bSTakashi Sakamoto unsigned int sph; 540e335425bSTakashi Sakamoto unsigned int fmt; 541e335425bSTakashi Sakamoto unsigned int fdf; 542a35463d1STakashi Sakamoto unsigned int dbc; 543c8bdf49bSTakashi Sakamoto bool lost; 5442b3fc456STakashi Sakamoto 545e335425bSTakashi Sakamoto cip_header[0] = be32_to_cpu(buf[0]); 546e335425bSTakashi Sakamoto cip_header[1] = be32_to_cpu(buf[1]); 5472b3fc456STakashi Sakamoto 5482b3fc456STakashi Sakamoto /* 5492b3fc456STakashi Sakamoto * This module supports 'Two-quadlet CIP header with SYT field'. 55077d2a8a4STakashi Sakamoto * For convenience, also check FMT field is AM824 or not. 5512b3fc456STakashi Sakamoto */ 5522128f78fSTakashi Sakamoto if ((((cip_header[0] & CIP_EOH_MASK) == CIP_EOH) || 5532128f78fSTakashi Sakamoto ((cip_header[1] & CIP_EOH_MASK) != CIP_EOH)) && 5542128f78fSTakashi Sakamoto (!(s->flags & CIP_HEADER_WITHOUT_EOH))) { 5552b3fc456STakashi Sakamoto dev_info_ratelimited(&s->unit->device, 5562b3fc456STakashi Sakamoto "Invalid CIP header for AMDTP: %08X:%08X\n", 5572b3fc456STakashi Sakamoto cip_header[0], cip_header[1]); 558e335425bSTakashi Sakamoto return -EAGAIN; 5592b3fc456STakashi Sakamoto } 5602b3fc456STakashi Sakamoto 561414ba022STakashi Sakamoto /* Check valid protocol or not. */ 5629863874fSTakashi Sakamoto sph = (cip_header[0] & CIP_SPH_MASK) >> CIP_SPH_SHIFT; 563414ba022STakashi Sakamoto fmt = (cip_header[1] & CIP_FMT_MASK) >> CIP_FMT_SHIFT; 5649863874fSTakashi Sakamoto if (sph != s->sph || fmt != s->fmt) { 5652a7e1713STakashi Sakamoto dev_info_ratelimited(&s->unit->device, 566414ba022STakashi Sakamoto "Detect unexpected protocol: %08x %08x\n", 567414ba022STakashi Sakamoto cip_header[0], cip_header[1]); 568e335425bSTakashi Sakamoto return -EAGAIN; 569414ba022STakashi Sakamoto } 570414ba022STakashi Sakamoto 5712b3fc456STakashi Sakamoto /* Calculate data blocks */ 572414ba022STakashi Sakamoto fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT; 573e335425bSTakashi Sakamoto if (payload_length < sizeof(__be32) * 2 || 574414ba022STakashi Sakamoto (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { 575e335425bSTakashi Sakamoto *data_blocks = 0; 5762b3fc456STakashi Sakamoto } else { 577e335425bSTakashi Sakamoto unsigned int data_block_quadlets = 5789a2820c1STakashi Sakamoto (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; 5792b3fc456STakashi Sakamoto /* avoid division by zero */ 5802b3fc456STakashi Sakamoto if (data_block_quadlets == 0) { 58112e0f438STakashi Sakamoto dev_err(&s->unit->device, 5822b3fc456STakashi Sakamoto "Detect invalid value in dbs field: %08X\n", 5832b3fc456STakashi Sakamoto cip_header[0]); 584a9007054STakashi Sakamoto return -EPROTO; 5852b3fc456STakashi Sakamoto } 58669702239STakashi Sakamoto if (s->flags & CIP_WRONG_DBS) 58769702239STakashi Sakamoto data_block_quadlets = s->data_block_quadlets; 5882b3fc456STakashi Sakamoto 589e335425bSTakashi Sakamoto *data_blocks = (payload_length / sizeof(__be32) - 2) / 590ff0fb5aaSTakashi Sakamoto data_block_quadlets; 5912b3fc456STakashi Sakamoto } 5922b3fc456STakashi Sakamoto 5932b3fc456STakashi Sakamoto /* Check data block counter continuity */ 594a35463d1STakashi Sakamoto dbc = cip_header[0] & CIP_DBC_MASK; 595e335425bSTakashi Sakamoto if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && 596a35463d1STakashi Sakamoto *data_block_counter != UINT_MAX) 597a35463d1STakashi Sakamoto dbc = *data_block_counter; 5989d59124cSTakashi Sakamoto 599a35463d1STakashi Sakamoto if ((dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) || 600a35463d1STakashi Sakamoto *data_block_counter == UINT_MAX) { 601b84b1a27STakashi Sakamoto lost = false; 602b84b1a27STakashi Sakamoto } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { 603a35463d1STakashi Sakamoto lost = dbc != *data_block_counter; 604d9cd0065STakashi Sakamoto } else { 605e335425bSTakashi Sakamoto unsigned int dbc_interval; 606e335425bSTakashi Sakamoto 607e335425bSTakashi Sakamoto if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0) 608d3d10a4aSTakashi Sakamoto dbc_interval = s->ctx_data.tx.dbc_interval; 609c8bdf49bSTakashi Sakamoto else 610e335425bSTakashi Sakamoto dbc_interval = *data_blocks; 611d9cd0065STakashi Sakamoto 612a35463d1STakashi Sakamoto lost = dbc != ((*data_block_counter + dbc_interval) & 0xff); 613d9cd0065STakashi Sakamoto } 614c8bdf49bSTakashi Sakamoto 615c8bdf49bSTakashi Sakamoto if (lost) { 61612e0f438STakashi Sakamoto dev_err(&s->unit->device, 6172b3fc456STakashi Sakamoto "Detect discontinuity of CIP: %02X %02X\n", 618a35463d1STakashi Sakamoto *data_block_counter, dbc); 6196fc6b9ceSTakashi Sakamoto return -EIO; 6202b3fc456STakashi Sakamoto } 6212b3fc456STakashi Sakamoto 622753e7179STakashi Sakamoto *data_block_counter = dbc; 623753e7179STakashi Sakamoto 624e335425bSTakashi Sakamoto *syt = cip_header[1] & CIP_SYT_MASK; 625e335425bSTakashi Sakamoto 626e335425bSTakashi Sakamoto return 0; 627e335425bSTakashi Sakamoto } 628e335425bSTakashi Sakamoto 62998e3e43bSTakashi Sakamoto static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, 63098e3e43bSTakashi Sakamoto const __be32 *ctx_header, 63198e3e43bSTakashi Sakamoto unsigned int *payload_length, 632a35463d1STakashi Sakamoto unsigned int *data_blocks, 633a35463d1STakashi Sakamoto unsigned int *data_block_counter, 634a35463d1STakashi Sakamoto unsigned int *syt, unsigned int index) 635e335425bSTakashi Sakamoto { 636f11453c7STakashi Sakamoto const __be32 *cip_header; 637e335425bSTakashi Sakamoto int err; 638e335425bSTakashi Sakamoto 63998e3e43bSTakashi Sakamoto *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; 64098e3e43bSTakashi Sakamoto if (*payload_length > s->ctx_data.tx.ctx_header_size + 641f11453c7STakashi Sakamoto s->ctx_data.tx.max_ctx_payload_length) { 642e335425bSTakashi Sakamoto dev_err(&s->unit->device, 643e335425bSTakashi Sakamoto "Detect jumbo payload: %04x %04x\n", 64498e3e43bSTakashi Sakamoto *payload_length, s->ctx_data.tx.max_ctx_payload_length); 645e335425bSTakashi Sakamoto return -EIO; 646e335425bSTakashi Sakamoto } 647e335425bSTakashi Sakamoto 648947b437eSTakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) { 64998e3e43bSTakashi Sakamoto cip_header = ctx_header + 2; 65098e3e43bSTakashi Sakamoto err = check_cip_header(s, cip_header, *payload_length, 651a35463d1STakashi Sakamoto data_blocks, data_block_counter, syt); 652b8b0e24cSTakashi Sakamoto if (err < 0) 653e335425bSTakashi Sakamoto return err; 654947b437eSTakashi Sakamoto } else { 655947b437eSTakashi Sakamoto cip_header = NULL; 65676864868STakashi Sakamoto err = 0; 65798e3e43bSTakashi Sakamoto *data_blocks = *payload_length / sizeof(__be32) / 65898e3e43bSTakashi Sakamoto s->data_block_quadlets; 65998e3e43bSTakashi Sakamoto *syt = 0; 6607fbf9096STakashi Sakamoto 661a35463d1STakashi Sakamoto if (*data_block_counter == UINT_MAX) 662a35463d1STakashi Sakamoto *data_block_counter = 0; 663947b437eSTakashi Sakamoto } 664e335425bSTakashi Sakamoto 66598e3e43bSTakashi Sakamoto trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, 666a35463d1STakashi Sakamoto *data_block_counter, index); 66764d0bf4dSTakashi Sakamoto 66876864868STakashi Sakamoto return err; 6692b3fc456STakashi Sakamoto } 6702b3fc456STakashi Sakamoto 67126cd1e58STakashi Sakamoto // In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On 67226cd1e58STakashi Sakamoto // the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent 67326cd1e58STakashi Sakamoto // it. Thus, via Linux firewire subsystem, we can get the 3 bits for second. 67426cd1e58STakashi Sakamoto static inline u32 compute_cycle_count(__be32 ctx_header_tstamp) 67573fc7f08STakashi Sakamoto { 67626cd1e58STakashi Sakamoto u32 tstamp = be32_to_cpu(ctx_header_tstamp) & HEADER_TSTAMP_MASK; 67773fc7f08STakashi Sakamoto return (((tstamp >> 13) & 0x07) * 8000) + (tstamp & 0x1fff); 67873fc7f08STakashi Sakamoto } 67973fc7f08STakashi Sakamoto 68073fc7f08STakashi Sakamoto static inline u32 increment_cycle_count(u32 cycle, unsigned int addend) 68173fc7f08STakashi Sakamoto { 68273fc7f08STakashi Sakamoto cycle += addend; 68373fc7f08STakashi Sakamoto if (cycle >= 8 * CYCLES_PER_SECOND) 68473fc7f08STakashi Sakamoto cycle -= 8 * CYCLES_PER_SECOND; 68573fc7f08STakashi Sakamoto return cycle; 68673fc7f08STakashi Sakamoto } 68773fc7f08STakashi Sakamoto 68826cd1e58STakashi Sakamoto // Align to actual cycle count for the packet which is going to be scheduled. 689a0e02331STakashi Sakamoto // This module queued the same number of isochronous cycle as the size of queue 690a0e02331STakashi Sakamoto // to kip isochronous cycle, therefore it's OK to just increment the cycle by 691a0e02331STakashi Sakamoto // the size of queue for scheduled cycle. 692a0e02331STakashi Sakamoto static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp, 693a0e02331STakashi Sakamoto unsigned int queue_size) 69426cd1e58STakashi Sakamoto { 69526cd1e58STakashi Sakamoto u32 cycle = compute_cycle_count(ctx_header_tstamp); 696a0e02331STakashi Sakamoto return increment_cycle_count(cycle, queue_size); 69726cd1e58STakashi Sakamoto } 69826cd1e58STakashi Sakamoto 699753e7179STakashi Sakamoto static int generate_device_pkt_descs(struct amdtp_stream *s, 700753e7179STakashi Sakamoto struct pkt_desc *descs, 701753e7179STakashi Sakamoto const __be32 *ctx_header, 702753e7179STakashi Sakamoto unsigned int packets) 703753e7179STakashi Sakamoto { 704753e7179STakashi Sakamoto unsigned int dbc = s->data_block_counter; 705753e7179STakashi Sakamoto int i; 706753e7179STakashi Sakamoto int err; 707753e7179STakashi Sakamoto 708753e7179STakashi Sakamoto for (i = 0; i < packets; ++i) { 709753e7179STakashi Sakamoto struct pkt_desc *desc = descs + i; 710a0e02331STakashi Sakamoto unsigned int index = (s->packet_index + i) % s->queue_size; 711753e7179STakashi Sakamoto unsigned int cycle; 712753e7179STakashi Sakamoto unsigned int payload_length; 713753e7179STakashi Sakamoto unsigned int data_blocks; 714753e7179STakashi Sakamoto unsigned int syt; 715753e7179STakashi Sakamoto 716753e7179STakashi Sakamoto cycle = compute_cycle_count(ctx_header[1]); 717753e7179STakashi Sakamoto 718753e7179STakashi Sakamoto err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, 719753e7179STakashi Sakamoto &data_blocks, &dbc, &syt, i); 720753e7179STakashi Sakamoto if (err < 0) 721753e7179STakashi Sakamoto return err; 722753e7179STakashi Sakamoto 723753e7179STakashi Sakamoto desc->cycle = cycle; 724753e7179STakashi Sakamoto desc->syt = syt; 725753e7179STakashi Sakamoto desc->data_blocks = data_blocks; 726753e7179STakashi Sakamoto desc->data_block_counter = dbc; 727753e7179STakashi Sakamoto desc->ctx_payload = s->buffer.packets[index].buffer; 728753e7179STakashi Sakamoto 729753e7179STakashi Sakamoto if (!(s->flags & CIP_DBC_IS_END_EVENT)) 730753e7179STakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 731753e7179STakashi Sakamoto 732753e7179STakashi Sakamoto ctx_header += 733753e7179STakashi Sakamoto s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); 734753e7179STakashi Sakamoto } 735753e7179STakashi Sakamoto 736753e7179STakashi Sakamoto s->data_block_counter = dbc; 737753e7179STakashi Sakamoto 738753e7179STakashi Sakamoto return 0; 739753e7179STakashi Sakamoto } 740753e7179STakashi Sakamoto 741f4f6ae7bSTakashi Sakamoto static void generate_ideal_pkt_descs(struct amdtp_stream *s, 742f4f6ae7bSTakashi Sakamoto struct pkt_desc *descs, 743f4f6ae7bSTakashi Sakamoto const __be32 *ctx_header, 744f4f6ae7bSTakashi Sakamoto unsigned int packets) 745f4f6ae7bSTakashi Sakamoto { 746f4f6ae7bSTakashi Sakamoto unsigned int dbc = s->data_block_counter; 747f4f6ae7bSTakashi Sakamoto int i; 748f4f6ae7bSTakashi Sakamoto 749f4f6ae7bSTakashi Sakamoto for (i = 0; i < packets; ++i) { 750f4f6ae7bSTakashi Sakamoto struct pkt_desc *desc = descs + i; 751a0e02331STakashi Sakamoto unsigned int index = (s->packet_index + i) % s->queue_size; 752f4f6ae7bSTakashi Sakamoto 753a0e02331STakashi Sakamoto desc->cycle = compute_it_cycle(*ctx_header, s->queue_size); 754f4f6ae7bSTakashi Sakamoto desc->syt = calculate_syt(s, desc->cycle); 755f4f6ae7bSTakashi Sakamoto desc->data_blocks = calculate_data_blocks(s, desc->syt); 756f4f6ae7bSTakashi Sakamoto 757f4f6ae7bSTakashi Sakamoto if (s->flags & CIP_DBC_IS_END_EVENT) 758f4f6ae7bSTakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 759f4f6ae7bSTakashi Sakamoto 760f4f6ae7bSTakashi Sakamoto desc->data_block_counter = dbc; 761f4f6ae7bSTakashi Sakamoto 762f4f6ae7bSTakashi Sakamoto if (!(s->flags & CIP_DBC_IS_END_EVENT)) 763f4f6ae7bSTakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 764f4f6ae7bSTakashi Sakamoto 765f4f6ae7bSTakashi Sakamoto desc->ctx_payload = s->buffer.packets[index].buffer; 766f4f6ae7bSTakashi Sakamoto 767f4f6ae7bSTakashi Sakamoto ++ctx_header; 768f4f6ae7bSTakashi Sakamoto } 769f4f6ae7bSTakashi Sakamoto 770f4f6ae7bSTakashi Sakamoto s->data_block_counter = dbc; 771f4f6ae7bSTakashi Sakamoto } 772f4f6ae7bSTakashi Sakamoto 773fce9b013STakashi Sakamoto static inline void cancel_stream(struct amdtp_stream *s) 774fce9b013STakashi Sakamoto { 775fce9b013STakashi Sakamoto s->packet_index = -1; 776fce9b013STakashi Sakamoto if (in_interrupt()) 777fce9b013STakashi Sakamoto amdtp_stream_pcm_abort(s); 778fce9b013STakashi Sakamoto WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); 779fce9b013STakashi Sakamoto } 780fce9b013STakashi Sakamoto 7810f5cfcb2STakashi Sakamoto static void process_ctx_payloads(struct amdtp_stream *s, 7820f5cfcb2STakashi Sakamoto const struct pkt_desc *descs, 7830f5cfcb2STakashi Sakamoto unsigned int packets) 7840f5cfcb2STakashi Sakamoto { 7859a738ad1STakashi Sakamoto struct snd_pcm_substream *pcm; 7860f5cfcb2STakashi Sakamoto unsigned int pcm_frames; 7870f5cfcb2STakashi Sakamoto 7889a738ad1STakashi Sakamoto pcm = READ_ONCE(s->pcm); 7899a738ad1STakashi Sakamoto pcm_frames = s->process_ctx_payloads(s, descs, packets, pcm); 7909a738ad1STakashi Sakamoto if (pcm) 7910f5cfcb2STakashi Sakamoto update_pcm_pointers(s, pcm, pcm_frames); 7920f5cfcb2STakashi Sakamoto } 7930f5cfcb2STakashi Sakamoto 79460dd4929STakashi Sakamoto static void amdtp_stream_master_callback(struct fw_iso_context *context, 79560dd4929STakashi Sakamoto u32 tstamp, size_t header_length, 79660dd4929STakashi Sakamoto void *header, void *private_data); 79760dd4929STakashi Sakamoto 79860dd4929STakashi Sakamoto static void amdtp_stream_master_first_callback(struct fw_iso_context *context, 79960dd4929STakashi Sakamoto u32 tstamp, size_t header_length, 80060dd4929STakashi Sakamoto void *header, void *private_data); 80160dd4929STakashi Sakamoto 80273fc7f08STakashi Sakamoto static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, 8034b7da117STakashi Sakamoto size_t header_length, void *header, 8044b7da117STakashi Sakamoto void *private_data) 80531ef9134SClemens Ladisch { 806be4a2894STakashi Sakamoto struct amdtp_stream *s = private_data; 80726cd1e58STakashi Sakamoto const __be32 *ctx_header = header; 80860dd4929STakashi Sakamoto unsigned int events_per_period = s->ctx_data.rx.events_per_period; 80960dd4929STakashi Sakamoto unsigned int event_count = s->ctx_data.rx.event_count; 810a0e02331STakashi Sakamoto unsigned int packets; 81160dd4929STakashi Sakamoto bool is_irq_target; 8120dcb4efbSTakashi Sakamoto int i; 81331ef9134SClemens Ladisch 814a4103bd7STakashi Sakamoto if (s->packet_index < 0) 815a4103bd7STakashi Sakamoto return; 816a4103bd7STakashi Sakamoto 817a0e02331STakashi Sakamoto // Calculate the number of packets in buffer and check XRUN. 818a0e02331STakashi Sakamoto packets = header_length / sizeof(*ctx_header); 819a0e02331STakashi Sakamoto 820f4f6ae7bSTakashi Sakamoto generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); 821f4f6ae7bSTakashi Sakamoto 8220f5cfcb2STakashi Sakamoto process_ctx_payloads(s, s->pkt_descs, packets); 8235e2ece0fSTakashi Sakamoto 82460dd4929STakashi Sakamoto is_irq_target = 82560dd4929STakashi Sakamoto !!(context->callback.sc == amdtp_stream_master_callback || 82660dd4929STakashi Sakamoto context->callback.sc == amdtp_stream_master_first_callback); 82760dd4929STakashi Sakamoto 8285e2ece0fSTakashi Sakamoto for (i = 0; i < packets; ++i) { 8295e2ece0fSTakashi Sakamoto const struct pkt_desc *desc = s->pkt_descs + i; 830f4f6ae7bSTakashi Sakamoto unsigned int syt; 8316bc1a269STakashi Sakamoto struct { 8326bc1a269STakashi Sakamoto struct fw_iso_packet params; 8336bc1a269STakashi Sakamoto __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; 8346bc1a269STakashi Sakamoto } template = { {0}, {0} }; 835e229853dSTakashi Sakamoto bool sched_irq = false; 836860d798cSTakashi Sakamoto 837f4f6ae7bSTakashi Sakamoto if (s->ctx_data.rx.syt_override < 0) 838f4f6ae7bSTakashi Sakamoto syt = desc->syt; 839f4f6ae7bSTakashi Sakamoto else 8403baf3053STakashi Sakamoto syt = s->ctx_data.rx.syt_override; 8413baf3053STakashi Sakamoto 842f4f6ae7bSTakashi Sakamoto build_it_pkt_header(s, desc->cycle, &template.params, 843f4f6ae7bSTakashi Sakamoto desc->data_blocks, desc->data_block_counter, 844f4f6ae7bSTakashi Sakamoto syt, i); 8456bc1a269STakashi Sakamoto 84660dd4929STakashi Sakamoto if (is_irq_target) { 847e229853dSTakashi Sakamoto event_count += desc->data_blocks; 848e229853dSTakashi Sakamoto if (event_count >= events_per_period) { 849e229853dSTakashi Sakamoto event_count -= events_per_period; 850e229853dSTakashi Sakamoto sched_irq = true; 851e229853dSTakashi Sakamoto } 85260dd4929STakashi Sakamoto } 853e229853dSTakashi Sakamoto 854e229853dSTakashi Sakamoto if (queue_out_packet(s, &template.params, sched_irq) < 0) { 855fce9b013STakashi Sakamoto cancel_stream(s); 856a4103bd7STakashi Sakamoto return; 857ccccad86STakashi Sakamoto } 858a4103bd7STakashi Sakamoto } 859a4103bd7STakashi Sakamoto 86060dd4929STakashi Sakamoto s->ctx_data.rx.event_count = event_count; 86131ef9134SClemens Ladisch } 86231ef9134SClemens Ladisch 86373fc7f08STakashi Sakamoto static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, 8642b3fc456STakashi Sakamoto size_t header_length, void *header, 8652b3fc456STakashi Sakamoto void *private_data) 8662b3fc456STakashi Sakamoto { 8672b3fc456STakashi Sakamoto struct amdtp_stream *s = private_data; 868cc4f8e91STakashi Sakamoto __be32 *ctx_header = header; 869e229853dSTakashi Sakamoto unsigned int packets; 870753e7179STakashi Sakamoto int i; 871753e7179STakashi Sakamoto int err; 8722b3fc456STakashi Sakamoto 873a4103bd7STakashi Sakamoto if (s->packet_index < 0) 874a4103bd7STakashi Sakamoto return; 875a4103bd7STakashi Sakamoto 876a0e02331STakashi Sakamoto // Calculate the number of packets in buffer and check XRUN. 877d3d10a4aSTakashi Sakamoto packets = header_length / s->ctx_data.tx.ctx_header_size; 878f90e2dedSTakashi Sakamoto 879753e7179STakashi Sakamoto err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets); 880753e7179STakashi Sakamoto if (err < 0) { 881753e7179STakashi Sakamoto if (err != -EAGAIN) { 882753e7179STakashi Sakamoto cancel_stream(s); 883753e7179STakashi Sakamoto return; 884753e7179STakashi Sakamoto } 8855e2ece0fSTakashi Sakamoto } else { 8860f5cfcb2STakashi Sakamoto process_ctx_payloads(s, s->pkt_descs, packets); 8875e2ece0fSTakashi Sakamoto } 8885e2ece0fSTakashi Sakamoto 8895e2ece0fSTakashi Sakamoto for (i = 0; i < packets; ++i) { 8905e2ece0fSTakashi Sakamoto struct fw_iso_packet params = {0}; 891a35463d1STakashi Sakamoto 89260dd4929STakashi Sakamoto if (queue_in_packet(s, ¶ms) < 0) { 893753e7179STakashi Sakamoto cancel_stream(s); 894753e7179STakashi Sakamoto return; 895753e7179STakashi Sakamoto } 8967b3b0d85STakashi Sakamoto } 8972b3fc456STakashi Sakamoto } 8982b3fc456STakashi Sakamoto 89960dd4929STakashi Sakamoto static void amdtp_stream_master_callback(struct fw_iso_context *context, 90060dd4929STakashi Sakamoto u32 tstamp, size_t header_length, 90160dd4929STakashi Sakamoto void *header, void *private_data) 90260dd4929STakashi Sakamoto { 90360dd4929STakashi Sakamoto struct amdtp_domain *d = private_data; 90460dd4929STakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 90560dd4929STakashi Sakamoto struct amdtp_stream *s; 90660dd4929STakashi Sakamoto 90760dd4929STakashi Sakamoto out_stream_callback(context, tstamp, header_length, header, irq_target); 90860dd4929STakashi Sakamoto if (amdtp_streaming_error(irq_target)) 90960dd4929STakashi Sakamoto goto error; 91060dd4929STakashi Sakamoto 91160dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 91260dd4929STakashi Sakamoto if (s != irq_target && amdtp_stream_running(s)) { 91360dd4929STakashi Sakamoto fw_iso_context_flush_completions(s->context); 91460dd4929STakashi Sakamoto if (amdtp_streaming_error(s)) 91560dd4929STakashi Sakamoto goto error; 91660dd4929STakashi Sakamoto } 91760dd4929STakashi Sakamoto } 91860dd4929STakashi Sakamoto 91960dd4929STakashi Sakamoto return; 92060dd4929STakashi Sakamoto error: 92160dd4929STakashi Sakamoto if (amdtp_stream_running(irq_target)) 92260dd4929STakashi Sakamoto cancel_stream(irq_target); 92360dd4929STakashi Sakamoto 92460dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 92560dd4929STakashi Sakamoto if (amdtp_stream_running(s)) 92660dd4929STakashi Sakamoto cancel_stream(s); 92760dd4929STakashi Sakamoto } 92860dd4929STakashi Sakamoto } 92960dd4929STakashi Sakamoto 93060dd4929STakashi Sakamoto // this is executed one time. 9317b3b0d85STakashi Sakamoto static void amdtp_stream_first_callback(struct fw_iso_context *context, 93273fc7f08STakashi Sakamoto u32 tstamp, size_t header_length, 9337b3b0d85STakashi Sakamoto void *header, void *private_data) 9347b3b0d85STakashi Sakamoto { 9357b3b0d85STakashi Sakamoto struct amdtp_stream *s = private_data; 93626cd1e58STakashi Sakamoto const __be32 *ctx_header = header; 937a04513f8STakashi Sakamoto u32 cycle; 9387b3b0d85STakashi Sakamoto 9397b3b0d85STakashi Sakamoto /* 9407b3b0d85STakashi Sakamoto * For in-stream, first packet has come. 9417b3b0d85STakashi Sakamoto * For out-stream, prepared to transmit first packet 9427b3b0d85STakashi Sakamoto */ 9437b3b0d85STakashi Sakamoto s->callbacked = true; 9447b3b0d85STakashi Sakamoto wake_up(&s->callback_wait); 9457b3b0d85STakashi Sakamoto 946cc4f8e91STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 94726cd1e58STakashi Sakamoto cycle = compute_cycle_count(ctx_header[1]); 948a04513f8STakashi Sakamoto 9497b3b0d85STakashi Sakamoto context->callback.sc = in_stream_callback; 950a04513f8STakashi Sakamoto } else { 951a0e02331STakashi Sakamoto cycle = compute_it_cycle(*ctx_header, s->queue_size); 95226cd1e58STakashi Sakamoto 9537b3b0d85STakashi Sakamoto context->callback.sc = out_stream_callback; 954a04513f8STakashi Sakamoto } 955a04513f8STakashi Sakamoto 956a04513f8STakashi Sakamoto s->start_cycle = cycle; 9577b3b0d85STakashi Sakamoto 95873fc7f08STakashi Sakamoto context->callback.sc(context, tstamp, header_length, header, s); 9597b3b0d85STakashi Sakamoto } 9607b3b0d85STakashi Sakamoto 96160dd4929STakashi Sakamoto static void amdtp_stream_master_first_callback(struct fw_iso_context *context, 96260dd4929STakashi Sakamoto u32 tstamp, size_t header_length, 96360dd4929STakashi Sakamoto void *header, void *private_data) 96460dd4929STakashi Sakamoto { 96560dd4929STakashi Sakamoto struct amdtp_domain *d = private_data; 96660dd4929STakashi Sakamoto struct amdtp_stream *s = d->irq_target; 96760dd4929STakashi Sakamoto const __be32 *ctx_header = header; 96860dd4929STakashi Sakamoto 96960dd4929STakashi Sakamoto s->callbacked = true; 97060dd4929STakashi Sakamoto wake_up(&s->callback_wait); 97160dd4929STakashi Sakamoto 97260dd4929STakashi Sakamoto s->start_cycle = compute_it_cycle(*ctx_header, s->queue_size); 97360dd4929STakashi Sakamoto 97460dd4929STakashi Sakamoto context->callback.sc = amdtp_stream_master_callback; 97560dd4929STakashi Sakamoto 97660dd4929STakashi Sakamoto context->callback.sc(context, tstamp, header_length, header, d); 97760dd4929STakashi Sakamoto } 97860dd4929STakashi Sakamoto 97931ef9134SClemens Ladisch /** 980be4a2894STakashi Sakamoto * amdtp_stream_start - start transferring packets 981be4a2894STakashi Sakamoto * @s: the AMDTP stream to start 98231ef9134SClemens Ladisch * @channel: the isochronous channel on the bus 98331ef9134SClemens Ladisch * @speed: firewire speed code 98460dd4929STakashi Sakamoto * @d: the AMDTP domain to which the AMDTP stream belongs 98560dd4929STakashi Sakamoto * @is_irq_target: whether isoc context for the AMDTP stream is used to generate 98660dd4929STakashi Sakamoto * hardware IRQ. 987*acfedcbeSTakashi Sakamoto * @start_cycle: the isochronous cycle to start the context. Start immediately 988*acfedcbeSTakashi Sakamoto * if negative value is given. 98931ef9134SClemens Ladisch * 99031ef9134SClemens Ladisch * The stream cannot be started until it has been configured with 991be4a2894STakashi Sakamoto * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI 992be4a2894STakashi Sakamoto * device can be started. 99331ef9134SClemens Ladisch */ 994a0e02331STakashi Sakamoto static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, 995*acfedcbeSTakashi Sakamoto struct amdtp_domain *d, bool is_irq_target, 996*acfedcbeSTakashi Sakamoto int start_cycle) 99731ef9134SClemens Ladisch { 99831ef9134SClemens Ladisch static const struct { 99931ef9134SClemens Ladisch unsigned int data_block; 100031ef9134SClemens Ladisch unsigned int syt_offset; 1001d3d10a4aSTakashi Sakamoto } *entry, initial_state[] = { 100231ef9134SClemens Ladisch [CIP_SFC_32000] = { 4, 3072 }, 100331ef9134SClemens Ladisch [CIP_SFC_48000] = { 6, 1024 }, 100431ef9134SClemens Ladisch [CIP_SFC_96000] = { 12, 1024 }, 100531ef9134SClemens Ladisch [CIP_SFC_192000] = { 24, 1024 }, 100631ef9134SClemens Ladisch [CIP_SFC_44100] = { 0, 67 }, 100731ef9134SClemens Ladisch [CIP_SFC_88200] = { 0, 67 }, 100831ef9134SClemens Ladisch [CIP_SFC_176400] = { 0, 67 }, 100931ef9134SClemens Ladisch }; 1010a0e02331STakashi Sakamoto unsigned int events_per_buffer = d->events_per_buffer; 1011e229853dSTakashi Sakamoto unsigned int events_per_period = d->events_per_period; 101260dd4929STakashi Sakamoto unsigned int idle_irq_interval; 1013d3d10a4aSTakashi Sakamoto unsigned int ctx_header_size; 1014f11453c7STakashi Sakamoto unsigned int max_ctx_payload_size; 10152b3fc456STakashi Sakamoto enum dma_data_direction dir; 10167ab56645STakashi Sakamoto int type, tag, err; 101760dd4929STakashi Sakamoto fw_iso_callback_t ctx_cb; 101860dd4929STakashi Sakamoto void *ctx_data; 101931ef9134SClemens Ladisch 102031ef9134SClemens Ladisch mutex_lock(&s->mutex); 102131ef9134SClemens Ladisch 1022be4a2894STakashi Sakamoto if (WARN_ON(amdtp_stream_running(s) || 10234b7da117STakashi Sakamoto (s->data_block_quadlets < 1))) { 102431ef9134SClemens Ladisch err = -EBADFD; 102531ef9134SClemens Ladisch goto err_unlock; 102631ef9134SClemens Ladisch } 102731ef9134SClemens Ladisch 1028d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 102960dd4929STakashi Sakamoto // NOTE: IT context should be used for constant IRQ. 103060dd4929STakashi Sakamoto if (is_irq_target) { 103160dd4929STakashi Sakamoto err = -EINVAL; 103260dd4929STakashi Sakamoto goto err_unlock; 103360dd4929STakashi Sakamoto } 103460dd4929STakashi Sakamoto 1035b6bc8123STakashi Sakamoto s->data_block_counter = UINT_MAX; 1036d3d10a4aSTakashi Sakamoto } else { 1037d3d10a4aSTakashi Sakamoto entry = &initial_state[s->sfc]; 1038d3d10a4aSTakashi Sakamoto 10394b7da117STakashi Sakamoto s->data_block_counter = 0; 1040d3d10a4aSTakashi Sakamoto s->ctx_data.rx.data_block_state = entry->data_block; 1041d3d10a4aSTakashi Sakamoto s->ctx_data.rx.syt_offset_state = entry->syt_offset; 1042d3d10a4aSTakashi Sakamoto s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE; 1043d3d10a4aSTakashi Sakamoto } 104431ef9134SClemens Ladisch 10452b3fc456STakashi Sakamoto /* initialize packet buffer */ 10462b3fc456STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 10472b3fc456STakashi Sakamoto dir = DMA_FROM_DEVICE; 10482b3fc456STakashi Sakamoto type = FW_ISO_CONTEXT_RECEIVE; 1049f11453c7STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 1050f11453c7STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_CIP; 1051f11453c7STakashi Sakamoto else 1052f11453c7STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; 1053b18f0cfaSTakashi Sakamoto 1054b18f0cfaSTakashi Sakamoto max_ctx_payload_size = amdtp_stream_get_max_payload(s) - 1055b18f0cfaSTakashi Sakamoto ctx_header_size; 10562b3fc456STakashi Sakamoto } else { 10572b3fc456STakashi Sakamoto dir = DMA_TO_DEVICE; 10582b3fc456STakashi Sakamoto type = FW_ISO_CONTEXT_TRANSMIT; 1059df9160b9STakashi Sakamoto ctx_header_size = 0; // No effect for IT context. 1060f11453c7STakashi Sakamoto 1061b18f0cfaSTakashi Sakamoto max_ctx_payload_size = amdtp_stream_get_max_payload(s); 1062b18f0cfaSTakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 1063b18f0cfaSTakashi Sakamoto max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP; 1064b18f0cfaSTakashi Sakamoto } 1065f11453c7STakashi Sakamoto 1066e229853dSTakashi Sakamoto // This is a case that AMDTP streams in domain run just for MIDI 1067e229853dSTakashi Sakamoto // substream. Use the number of events equivalent to 10 msec as 1068e229853dSTakashi Sakamoto // interval of hardware IRQ. 1069e229853dSTakashi Sakamoto if (events_per_period == 0) 1070e229853dSTakashi Sakamoto events_per_period = amdtp_rate_table[s->sfc] / 100; 1071a0e02331STakashi Sakamoto if (events_per_buffer == 0) 1072e229853dSTakashi Sakamoto events_per_buffer = events_per_period * 3; 1073a0e02331STakashi Sakamoto 107460dd4929STakashi Sakamoto idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, 1075e229853dSTakashi Sakamoto amdtp_rate_table[s->sfc]); 1076a0e02331STakashi Sakamoto s->queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, 1077a0e02331STakashi Sakamoto amdtp_rate_table[s->sfc]); 1078a0e02331STakashi Sakamoto 1079a0e02331STakashi Sakamoto err = iso_packets_buffer_init(&s->buffer, s->unit, s->queue_size, 1080f11453c7STakashi Sakamoto max_ctx_payload_size, dir); 108131ef9134SClemens Ladisch if (err < 0) 108231ef9134SClemens Ladisch goto err_unlock; 108331ef9134SClemens Ladisch 108460dd4929STakashi Sakamoto if (is_irq_target) { 108560dd4929STakashi Sakamoto s->ctx_data.rx.events_per_period = events_per_period; 108660dd4929STakashi Sakamoto s->ctx_data.rx.event_count = 0; 108760dd4929STakashi Sakamoto ctx_cb = amdtp_stream_master_first_callback; 108860dd4929STakashi Sakamoto ctx_data = d; 108960dd4929STakashi Sakamoto } else { 109060dd4929STakashi Sakamoto ctx_cb = amdtp_stream_first_callback; 109160dd4929STakashi Sakamoto ctx_data = s; 109260dd4929STakashi Sakamoto } 109360dd4929STakashi Sakamoto 109431ef9134SClemens Ladisch s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, 1095d3d10a4aSTakashi Sakamoto type, channel, speed, ctx_header_size, 109660dd4929STakashi Sakamoto ctx_cb, ctx_data); 109731ef9134SClemens Ladisch if (IS_ERR(s->context)) { 109831ef9134SClemens Ladisch err = PTR_ERR(s->context); 109931ef9134SClemens Ladisch if (err == -EBUSY) 110031ef9134SClemens Ladisch dev_err(&s->unit->device, 1101be4a2894STakashi Sakamoto "no free stream on this controller\n"); 110231ef9134SClemens Ladisch goto err_buffer; 110331ef9134SClemens Ladisch } 110431ef9134SClemens Ladisch 1105be4a2894STakashi Sakamoto amdtp_stream_update(s); 110631ef9134SClemens Ladisch 1107d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1108f11453c7STakashi Sakamoto s->ctx_data.tx.max_ctx_payload_length = max_ctx_payload_size; 1109d3d10a4aSTakashi Sakamoto s->ctx_data.tx.ctx_header_size = ctx_header_size; 1110d3d10a4aSTakashi Sakamoto } 111152759c09STakashi Sakamoto 11123b196c39STakashi Sakamoto if (s->flags & CIP_NO_HEADER) 11133b196c39STakashi Sakamoto s->tag = TAG_NO_CIP_HEADER; 11143b196c39STakashi Sakamoto else 11153b196c39STakashi Sakamoto s->tag = TAG_CIP; 11163b196c39STakashi Sakamoto 1117a0e02331STakashi Sakamoto s->pkt_descs = kcalloc(s->queue_size, sizeof(*s->pkt_descs), 111804130cf8STakashi Sakamoto GFP_KERNEL); 111904130cf8STakashi Sakamoto if (!s->pkt_descs) { 112004130cf8STakashi Sakamoto err = -ENOMEM; 112104130cf8STakashi Sakamoto goto err_context; 112204130cf8STakashi Sakamoto } 112304130cf8STakashi Sakamoto 1124ec00f5e4SClemens Ladisch s->packet_index = 0; 11254b7da117STakashi Sakamoto do { 11266007bf54STakashi Sakamoto struct fw_iso_packet params; 1127e229853dSTakashi Sakamoto 1128b18f0cfaSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 112960dd4929STakashi Sakamoto err = queue_in_packet(s, ¶ms); 1130b18f0cfaSTakashi Sakamoto } else { 113160dd4929STakashi Sakamoto bool sched_irq = false; 113260dd4929STakashi Sakamoto 1133b18f0cfaSTakashi Sakamoto params.header_length = 0; 1134b18f0cfaSTakashi Sakamoto params.payload_length = 0; 113560dd4929STakashi Sakamoto 113660dd4929STakashi Sakamoto if (is_irq_target) { 113760dd4929STakashi Sakamoto sched_irq = !((s->packet_index + 1) % 113860dd4929STakashi Sakamoto idle_irq_interval); 113960dd4929STakashi Sakamoto } 114060dd4929STakashi Sakamoto 1141e229853dSTakashi Sakamoto err = queue_out_packet(s, ¶ms, sched_irq); 1142b18f0cfaSTakashi Sakamoto } 114331ef9134SClemens Ladisch if (err < 0) 114404130cf8STakashi Sakamoto goto err_pkt_descs; 11454b7da117STakashi Sakamoto } while (s->packet_index > 0); 114631ef9134SClemens Ladisch 11472b3fc456STakashi Sakamoto /* NOTE: TAG1 matches CIP. This just affects in stream. */ 11487ab56645STakashi Sakamoto tag = FW_ISO_CONTEXT_MATCH_TAG1; 11493b196c39STakashi Sakamoto if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER)) 11507ab56645STakashi Sakamoto tag |= FW_ISO_CONTEXT_MATCH_TAG0; 11517ab56645STakashi Sakamoto 11527b3b0d85STakashi Sakamoto s->callbacked = false; 1153*acfedcbeSTakashi Sakamoto err = fw_iso_context_start(s->context, start_cycle, 0, tag); 115431ef9134SClemens Ladisch if (err < 0) 115504130cf8STakashi Sakamoto goto err_pkt_descs; 115631ef9134SClemens Ladisch 115731ef9134SClemens Ladisch mutex_unlock(&s->mutex); 115831ef9134SClemens Ladisch 115931ef9134SClemens Ladisch return 0; 116004130cf8STakashi Sakamoto err_pkt_descs: 116104130cf8STakashi Sakamoto kfree(s->pkt_descs); 116231ef9134SClemens Ladisch err_context: 116331ef9134SClemens Ladisch fw_iso_context_destroy(s->context); 116431ef9134SClemens Ladisch s->context = ERR_PTR(-1); 116531ef9134SClemens Ladisch err_buffer: 116631ef9134SClemens Ladisch iso_packets_buffer_destroy(&s->buffer, s->unit); 116731ef9134SClemens Ladisch err_unlock: 116831ef9134SClemens Ladisch mutex_unlock(&s->mutex); 116931ef9134SClemens Ladisch 117031ef9134SClemens Ladisch return err; 117131ef9134SClemens Ladisch } 117231ef9134SClemens Ladisch 117331ef9134SClemens Ladisch /** 1174f890f9a0STakashi Sakamoto * amdtp_domain_stream_pcm_pointer - get the PCM buffer position 1175f890f9a0STakashi Sakamoto * @d: the AMDTP domain. 1176be4a2894STakashi Sakamoto * @s: the AMDTP stream that transports the PCM data 1177e9148dddSClemens Ladisch * 1178e9148dddSClemens Ladisch * Returns the current buffer position, in frames. 1179e9148dddSClemens Ladisch */ 1180f890f9a0STakashi Sakamoto unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, 1181f890f9a0STakashi Sakamoto struct amdtp_stream *s) 1182e9148dddSClemens Ladisch { 1183f890f9a0STakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 1184f890f9a0STakashi Sakamoto 1185f890f9a0STakashi Sakamoto if (irq_target && amdtp_stream_running(irq_target)) { 1186f890f9a0STakashi Sakamoto // This function is called in software IRQ context of 1187f890f9a0STakashi Sakamoto // period_tasklet or process context. 1188f890f9a0STakashi Sakamoto // 1189f890f9a0STakashi Sakamoto // When the software IRQ context was scheduled by software IRQ 1190f890f9a0STakashi Sakamoto // context of IT contexts, queued packets were already handled. 1191f890f9a0STakashi Sakamoto // Therefore, no need to flush the queue in buffer furthermore. 1192f890f9a0STakashi Sakamoto // 1193f890f9a0STakashi Sakamoto // When the process context reach here, some packets will be 1194f890f9a0STakashi Sakamoto // already queued in the buffer. These packets should be handled 1195f890f9a0STakashi Sakamoto // immediately to keep better granularity of PCM pointer. 1196f890f9a0STakashi Sakamoto // 1197f890f9a0STakashi Sakamoto // Later, the process context will sometimes schedules software 1198f890f9a0STakashi Sakamoto // IRQ context of the period_tasklet. Then, no need to flush the 1199f890f9a0STakashi Sakamoto // queue by the same reason as described in the above 1200f890f9a0STakashi Sakamoto if (!in_interrupt()) { 1201f890f9a0STakashi Sakamoto // Queued packet should be processed without any kernel 1202f890f9a0STakashi Sakamoto // preemption to keep latency against bus cycle. 1203f890f9a0STakashi Sakamoto preempt_disable(); 1204f890f9a0STakashi Sakamoto fw_iso_context_flush_completions(irq_target->context); 1205f890f9a0STakashi Sakamoto preempt_enable(); 1206f890f9a0STakashi Sakamoto } 1207f890f9a0STakashi Sakamoto } 1208e9148dddSClemens Ladisch 12096aa7de05SMark Rutland return READ_ONCE(s->pcm_buffer_pointer); 1210e9148dddSClemens Ladisch } 1211f890f9a0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_pointer); 1212e9148dddSClemens Ladisch 1213e9148dddSClemens Ladisch /** 1214e6dcc92fSTakashi Sakamoto * amdtp_domain_stream_pcm_ack - acknowledge queued PCM frames 1215e6dcc92fSTakashi Sakamoto * @d: the AMDTP domain. 1216875becf8STakashi Sakamoto * @s: the AMDTP stream that transfers the PCM frames 1217875becf8STakashi Sakamoto * 1218875becf8STakashi Sakamoto * Returns zero always. 1219875becf8STakashi Sakamoto */ 1220e6dcc92fSTakashi Sakamoto int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s) 1221875becf8STakashi Sakamoto { 1222e6dcc92fSTakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 1223e6dcc92fSTakashi Sakamoto 1224e6dcc92fSTakashi Sakamoto // Process isochronous packets for recent isochronous cycle to handle 1225e6dcc92fSTakashi Sakamoto // queued PCM frames. 1226e6dcc92fSTakashi Sakamoto if (irq_target && amdtp_stream_running(irq_target)) { 1227e6dcc92fSTakashi Sakamoto // Queued packet should be processed without any kernel 1228e6dcc92fSTakashi Sakamoto // preemption to keep latency against bus cycle. 1229e6dcc92fSTakashi Sakamoto preempt_disable(); 1230e6dcc92fSTakashi Sakamoto fw_iso_context_flush_completions(irq_target->context); 1231e6dcc92fSTakashi Sakamoto preempt_enable(); 1232e6dcc92fSTakashi Sakamoto } 1233875becf8STakashi Sakamoto 1234875becf8STakashi Sakamoto return 0; 1235875becf8STakashi Sakamoto } 1236e6dcc92fSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_ack); 1237875becf8STakashi Sakamoto 1238875becf8STakashi Sakamoto /** 1239be4a2894STakashi Sakamoto * amdtp_stream_update - update the stream after a bus reset 1240be4a2894STakashi Sakamoto * @s: the AMDTP stream 124131ef9134SClemens Ladisch */ 1242be4a2894STakashi Sakamoto void amdtp_stream_update(struct amdtp_stream *s) 124331ef9134SClemens Ladisch { 12449a2820c1STakashi Sakamoto /* Precomputing. */ 12456aa7de05SMark Rutland WRITE_ONCE(s->source_node_id_field, 12466aa7de05SMark Rutland (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & CIP_SID_MASK); 124731ef9134SClemens Ladisch } 1248be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_update); 124931ef9134SClemens Ladisch 125031ef9134SClemens Ladisch /** 1251be4a2894STakashi Sakamoto * amdtp_stream_stop - stop sending packets 1252be4a2894STakashi Sakamoto * @s: the AMDTP stream to stop 125331ef9134SClemens Ladisch * 125431ef9134SClemens Ladisch * All PCM and MIDI devices of the stream must be stopped before the stream 125531ef9134SClemens Ladisch * itself can be stopped. 125631ef9134SClemens Ladisch */ 125774f94e41STakashi Sakamoto static void amdtp_stream_stop(struct amdtp_stream *s) 125831ef9134SClemens Ladisch { 125931ef9134SClemens Ladisch mutex_lock(&s->mutex); 126031ef9134SClemens Ladisch 1261be4a2894STakashi Sakamoto if (!amdtp_stream_running(s)) { 126231ef9134SClemens Ladisch mutex_unlock(&s->mutex); 126331ef9134SClemens Ladisch return; 126431ef9134SClemens Ladisch } 126531ef9134SClemens Ladisch 126676fb8789SClemens Ladisch tasklet_kill(&s->period_tasklet); 126731ef9134SClemens Ladisch fw_iso_context_stop(s->context); 126831ef9134SClemens Ladisch fw_iso_context_destroy(s->context); 126931ef9134SClemens Ladisch s->context = ERR_PTR(-1); 127031ef9134SClemens Ladisch iso_packets_buffer_destroy(&s->buffer, s->unit); 127104130cf8STakashi Sakamoto kfree(s->pkt_descs); 127231ef9134SClemens Ladisch 12737b3b0d85STakashi Sakamoto s->callbacked = false; 12747b3b0d85STakashi Sakamoto 127531ef9134SClemens Ladisch mutex_unlock(&s->mutex); 127631ef9134SClemens Ladisch } 127731ef9134SClemens Ladisch 127831ef9134SClemens Ladisch /** 1279be4a2894STakashi Sakamoto * amdtp_stream_pcm_abort - abort the running PCM device 128031ef9134SClemens Ladisch * @s: the AMDTP stream about to be stopped 128131ef9134SClemens Ladisch * 128231ef9134SClemens Ladisch * If the isochronous stream needs to be stopped asynchronously, call this 128331ef9134SClemens Ladisch * function first to stop the PCM device. 128431ef9134SClemens Ladisch */ 1285be4a2894STakashi Sakamoto void amdtp_stream_pcm_abort(struct amdtp_stream *s) 128631ef9134SClemens Ladisch { 128731ef9134SClemens Ladisch struct snd_pcm_substream *pcm; 128831ef9134SClemens Ladisch 12896aa7de05SMark Rutland pcm = READ_ONCE(s->pcm); 12901fb8510cSTakashi Iwai if (pcm) 12911fb8510cSTakashi Iwai snd_pcm_stop_xrun(pcm); 129231ef9134SClemens Ladisch } 1293be4a2894STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_abort); 12943ec3d7a3STakashi Sakamoto 12953ec3d7a3STakashi Sakamoto /** 12963ec3d7a3STakashi Sakamoto * amdtp_domain_init - initialize an AMDTP domain structure 12973ec3d7a3STakashi Sakamoto * @d: the AMDTP domain to initialize. 12983ec3d7a3STakashi Sakamoto */ 12993ec3d7a3STakashi Sakamoto int amdtp_domain_init(struct amdtp_domain *d) 13003ec3d7a3STakashi Sakamoto { 13013ec3d7a3STakashi Sakamoto INIT_LIST_HEAD(&d->streams); 13023ec3d7a3STakashi Sakamoto 1303d68c3123STakashi Sakamoto d->events_per_period = 0; 1304d68c3123STakashi Sakamoto 13053ec3d7a3STakashi Sakamoto return 0; 13063ec3d7a3STakashi Sakamoto } 13073ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_init); 13083ec3d7a3STakashi Sakamoto 13093ec3d7a3STakashi Sakamoto /** 13103ec3d7a3STakashi Sakamoto * amdtp_domain_destroy - destroy an AMDTP domain structure 13113ec3d7a3STakashi Sakamoto * @d: the AMDTP domain to destroy. 13123ec3d7a3STakashi Sakamoto */ 13133ec3d7a3STakashi Sakamoto void amdtp_domain_destroy(struct amdtp_domain *d) 13143ec3d7a3STakashi Sakamoto { 13158d0d5c3fSTakashi Sakamoto // At present nothing to do. 13168d0d5c3fSTakashi Sakamoto return; 13173ec3d7a3STakashi Sakamoto } 13183ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_destroy); 13196261f90bSTakashi Sakamoto 13206261f90bSTakashi Sakamoto /** 1321157a53eeSTakashi Sakamoto * amdtp_domain_add_stream - register isoc context into the domain. 1322157a53eeSTakashi Sakamoto * @d: the AMDTP domain. 1323157a53eeSTakashi Sakamoto * @s: the AMDTP stream. 1324157a53eeSTakashi Sakamoto * @channel: the isochronous channel on the bus. 1325157a53eeSTakashi Sakamoto * @speed: firewire speed code. 1326157a53eeSTakashi Sakamoto */ 1327157a53eeSTakashi Sakamoto int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, 1328157a53eeSTakashi Sakamoto int channel, int speed) 1329157a53eeSTakashi Sakamoto { 1330157a53eeSTakashi Sakamoto struct amdtp_stream *tmp; 1331157a53eeSTakashi Sakamoto 1332157a53eeSTakashi Sakamoto list_for_each_entry(tmp, &d->streams, list) { 1333157a53eeSTakashi Sakamoto if (s == tmp) 1334157a53eeSTakashi Sakamoto return -EBUSY; 1335157a53eeSTakashi Sakamoto } 1336157a53eeSTakashi Sakamoto 1337157a53eeSTakashi Sakamoto list_add(&s->list, &d->streams); 1338157a53eeSTakashi Sakamoto 1339157a53eeSTakashi Sakamoto s->channel = channel; 1340157a53eeSTakashi Sakamoto s->speed = speed; 1341157a53eeSTakashi Sakamoto 1342157a53eeSTakashi Sakamoto return 0; 1343157a53eeSTakashi Sakamoto } 1344157a53eeSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); 1345157a53eeSTakashi Sakamoto 1346*acfedcbeSTakashi Sakamoto static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle) 1347*acfedcbeSTakashi Sakamoto { 1348*acfedcbeSTakashi Sakamoto int generation; 1349*acfedcbeSTakashi Sakamoto int rcode; 1350*acfedcbeSTakashi Sakamoto __be32 reg; 1351*acfedcbeSTakashi Sakamoto u32 data; 1352*acfedcbeSTakashi Sakamoto 1353*acfedcbeSTakashi Sakamoto // This is a request to local 1394 OHCI controller and expected to 1354*acfedcbeSTakashi Sakamoto // complete without any event waiting. 1355*acfedcbeSTakashi Sakamoto generation = fw_card->generation; 1356*acfedcbeSTakashi Sakamoto smp_rmb(); // node_id vs. generation. 1357*acfedcbeSTakashi Sakamoto rcode = fw_run_transaction(fw_card, TCODE_READ_QUADLET_REQUEST, 1358*acfedcbeSTakashi Sakamoto fw_card->node_id, generation, SCODE_100, 1359*acfedcbeSTakashi Sakamoto CSR_REGISTER_BASE + CSR_CYCLE_TIME, 1360*acfedcbeSTakashi Sakamoto ®, sizeof(reg)); 1361*acfedcbeSTakashi Sakamoto if (rcode != RCODE_COMPLETE) 1362*acfedcbeSTakashi Sakamoto return -EIO; 1363*acfedcbeSTakashi Sakamoto 1364*acfedcbeSTakashi Sakamoto data = be32_to_cpu(reg); 1365*acfedcbeSTakashi Sakamoto *cur_cycle = data >> 12; 1366*acfedcbeSTakashi Sakamoto 1367*acfedcbeSTakashi Sakamoto return 0; 1368*acfedcbeSTakashi Sakamoto } 1369*acfedcbeSTakashi Sakamoto 1370157a53eeSTakashi Sakamoto /** 13719b4702b0STakashi Sakamoto * amdtp_domain_start - start sending packets for isoc context in the domain. 13729b4702b0STakashi Sakamoto * @d: the AMDTP domain. 1373*acfedcbeSTakashi Sakamoto * @ir_delay_cycle: the cycle delay to start all IR contexts. 13749b4702b0STakashi Sakamoto */ 1375*acfedcbeSTakashi Sakamoto int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) 13769b4702b0STakashi Sakamoto { 13779b4702b0STakashi Sakamoto struct amdtp_stream *s; 1378*acfedcbeSTakashi Sakamoto int cycle; 1379*acfedcbeSTakashi Sakamoto int err; 13809b4702b0STakashi Sakamoto 138160dd4929STakashi Sakamoto // Select an IT context as IRQ target. 13829b4702b0STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 138360dd4929STakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM) 13849b4702b0STakashi Sakamoto break; 13859b4702b0STakashi Sakamoto } 138660dd4929STakashi Sakamoto if (!s) 138760dd4929STakashi Sakamoto return -ENXIO; 138860dd4929STakashi Sakamoto d->irq_target = s; 13899b4702b0STakashi Sakamoto 1390*acfedcbeSTakashi Sakamoto if (ir_delay_cycle > 0) { 1391*acfedcbeSTakashi Sakamoto struct fw_card *fw_card = fw_parent_device(s->unit)->card; 1392*acfedcbeSTakashi Sakamoto 1393*acfedcbeSTakashi Sakamoto err = get_current_cycle_time(fw_card, &cycle); 1394*acfedcbeSTakashi Sakamoto if (err < 0) 1395*acfedcbeSTakashi Sakamoto return err; 1396*acfedcbeSTakashi Sakamoto 1397*acfedcbeSTakashi Sakamoto // No need to care overflow in cycle field because of enough 1398*acfedcbeSTakashi Sakamoto // width. 1399*acfedcbeSTakashi Sakamoto cycle += ir_delay_cycle; 1400*acfedcbeSTakashi Sakamoto 1401*acfedcbeSTakashi Sakamoto // Round up to sec field. 1402*acfedcbeSTakashi Sakamoto if ((cycle & 0x00001fff) >= CYCLES_PER_SECOND) { 1403*acfedcbeSTakashi Sakamoto unsigned int sec; 1404*acfedcbeSTakashi Sakamoto 1405*acfedcbeSTakashi Sakamoto // The sec field can overflow. 1406*acfedcbeSTakashi Sakamoto sec = (cycle & 0xffffe000) >> 13; 1407*acfedcbeSTakashi Sakamoto cycle = (++sec << 13) | 1408*acfedcbeSTakashi Sakamoto ((cycle & 0x00001fff) / CYCLES_PER_SECOND); 1409*acfedcbeSTakashi Sakamoto } 1410*acfedcbeSTakashi Sakamoto 1411*acfedcbeSTakashi Sakamoto // In OHCI 1394 specification, lower 2 bits are available for 1412*acfedcbeSTakashi Sakamoto // sec field. 1413*acfedcbeSTakashi Sakamoto cycle &= 0x00007fff; 1414*acfedcbeSTakashi Sakamoto } else { 1415*acfedcbeSTakashi Sakamoto cycle = -1; 1416*acfedcbeSTakashi Sakamoto } 1417*acfedcbeSTakashi Sakamoto 141860dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1419*acfedcbeSTakashi Sakamoto int cycle_match; 1420*acfedcbeSTakashi Sakamoto 1421*acfedcbeSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1422*acfedcbeSTakashi Sakamoto cycle_match = cycle; 1423*acfedcbeSTakashi Sakamoto } else { 1424*acfedcbeSTakashi Sakamoto // IT context starts immediately. 1425*acfedcbeSTakashi Sakamoto cycle_match = -1; 1426*acfedcbeSTakashi Sakamoto } 1427*acfedcbeSTakashi Sakamoto 142860dd4929STakashi Sakamoto if (s != d->irq_target) { 142960dd4929STakashi Sakamoto err = amdtp_stream_start(s, s->channel, s->speed, d, 1430*acfedcbeSTakashi Sakamoto false, cycle_match); 143160dd4929STakashi Sakamoto if (err < 0) 143260dd4929STakashi Sakamoto goto error; 143360dd4929STakashi Sakamoto } 14349b4702b0STakashi Sakamoto } 14359b4702b0STakashi Sakamoto 143660dd4929STakashi Sakamoto s = d->irq_target; 1437*acfedcbeSTakashi Sakamoto err = amdtp_stream_start(s, s->channel, s->speed, d, true, -1); 143860dd4929STakashi Sakamoto if (err < 0) 143960dd4929STakashi Sakamoto goto error; 144060dd4929STakashi Sakamoto 144160dd4929STakashi Sakamoto return 0; 144260dd4929STakashi Sakamoto error: 144360dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) 144460dd4929STakashi Sakamoto amdtp_stream_stop(s); 14459b4702b0STakashi Sakamoto return err; 14469b4702b0STakashi Sakamoto } 14479b4702b0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_start); 14489b4702b0STakashi Sakamoto 14499b4702b0STakashi Sakamoto /** 14506261f90bSTakashi Sakamoto * amdtp_domain_stop - stop sending packets for isoc context in the same domain. 14516261f90bSTakashi Sakamoto * @d: the AMDTP domain to which the isoc contexts belong. 14526261f90bSTakashi Sakamoto */ 14536261f90bSTakashi Sakamoto void amdtp_domain_stop(struct amdtp_domain *d) 14546261f90bSTakashi Sakamoto { 14556261f90bSTakashi Sakamoto struct amdtp_stream *s, *next; 14566261f90bSTakashi Sakamoto 145760dd4929STakashi Sakamoto if (d->irq_target) 145860dd4929STakashi Sakamoto amdtp_stream_stop(d->irq_target); 145960dd4929STakashi Sakamoto 14606261f90bSTakashi Sakamoto list_for_each_entry_safe(s, next, &d->streams, list) { 14616261f90bSTakashi Sakamoto list_del(&s->list); 14626261f90bSTakashi Sakamoto 146360dd4929STakashi Sakamoto if (s != d->irq_target) 14646261f90bSTakashi Sakamoto amdtp_stream_stop(s); 14656261f90bSTakashi Sakamoto } 1466d68c3123STakashi Sakamoto 1467d68c3123STakashi Sakamoto d->events_per_period = 0; 146860dd4929STakashi Sakamoto d->irq_target = NULL; 14696261f90bSTakashi Sakamoto } 14706261f90bSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stop); 1471