1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d67c46b9STakashi Sakamoto /* 3d67c46b9STakashi Sakamoto * Audio and Music Data Transmission Protocol (IEC 61883-6) streams 4d67c46b9STakashi Sakamoto * with Common Isochronous Packet (IEC 61883-1) headers 5d67c46b9STakashi Sakamoto * 6d67c46b9STakashi Sakamoto * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 7d67c46b9STakashi Sakamoto */ 8d67c46b9STakashi Sakamoto 9d67c46b9STakashi Sakamoto #include <linux/device.h> 10d67c46b9STakashi Sakamoto #include <linux/err.h> 11d67c46b9STakashi Sakamoto #include <linux/firewire.h> 12acfedcbeSTakashi Sakamoto #include <linux/firewire-constants.h> 13d67c46b9STakashi Sakamoto #include <linux/module.h> 14d67c46b9STakashi Sakamoto #include <linux/slab.h> 15d67c46b9STakashi Sakamoto #include <sound/pcm.h> 16d67c46b9STakashi Sakamoto #include <sound/pcm_params.h> 17d67c46b9STakashi Sakamoto #include "amdtp-stream.h" 18d67c46b9STakashi Sakamoto 19d67c46b9STakashi Sakamoto #define TICKS_PER_CYCLE 3072 20d67c46b9STakashi Sakamoto #define CYCLES_PER_SECOND 8000 21d67c46b9STakashi Sakamoto #define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) 22d67c46b9STakashi Sakamoto 233e106f4fSTakashi Sakamoto #define OHCI_SECOND_MODULUS 8 2410aa8e4aSTakashi Sakamoto 250c95c1d6STakashi Sakamoto /* Always support Linux tracing subsystem. */ 260c95c1d6STakashi Sakamoto #define CREATE_TRACE_POINTS 270c95c1d6STakashi Sakamoto #include "amdtp-stream-trace.h" 280c95c1d6STakashi Sakamoto 29d67c46b9STakashi Sakamoto #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 microseconds */ 30d67c46b9STakashi Sakamoto 31d67c46b9STakashi Sakamoto /* isochronous header parameters */ 32d67c46b9STakashi Sakamoto #define ISO_DATA_LENGTH_SHIFT 16 333b196c39STakashi Sakamoto #define TAG_NO_CIP_HEADER 0 34d67c46b9STakashi Sakamoto #define TAG_CIP 1 35d67c46b9STakashi Sakamoto 3667d92ee7STakashi Sakamoto // Common Isochronous Packet (CIP) header parameters. Use two quadlets CIP header when supported. 3767d92ee7STakashi Sakamoto #define CIP_HEADER_QUADLETS 2 38d67c46b9STakashi Sakamoto #define CIP_EOH_SHIFT 31 39d67c46b9STakashi Sakamoto #define CIP_EOH (1u << CIP_EOH_SHIFT) 40d67c46b9STakashi Sakamoto #define CIP_EOH_MASK 0x80000000 41d67c46b9STakashi Sakamoto #define CIP_SID_SHIFT 24 42d67c46b9STakashi Sakamoto #define CIP_SID_MASK 0x3f000000 43d67c46b9STakashi Sakamoto #define CIP_DBS_MASK 0x00ff0000 44d67c46b9STakashi Sakamoto #define CIP_DBS_SHIFT 16 459863874fSTakashi Sakamoto #define CIP_SPH_MASK 0x00000400 469863874fSTakashi Sakamoto #define CIP_SPH_SHIFT 10 47d67c46b9STakashi Sakamoto #define CIP_DBC_MASK 0x000000ff 48d67c46b9STakashi Sakamoto #define CIP_FMT_SHIFT 24 49d67c46b9STakashi Sakamoto #define CIP_FMT_MASK 0x3f000000 50d67c46b9STakashi Sakamoto #define CIP_FDF_MASK 0x00ff0000 51d67c46b9STakashi Sakamoto #define CIP_FDF_SHIFT 16 52fb25dcc8STakashi Sakamoto #define CIP_FDF_NO_DATA 0xff 53d67c46b9STakashi Sakamoto #define CIP_SYT_MASK 0x0000ffff 54d67c46b9STakashi Sakamoto #define CIP_SYT_NO_INFO 0xffff 55f9e5ecdfSTakashi Sakamoto #define CIP_SYT_CYCLE_MODULUS 16 56fb25dcc8STakashi Sakamoto #define CIP_NO_DATA ((CIP_FDF_NO_DATA << CIP_FDF_SHIFT) | CIP_SYT_NO_INFO) 57d67c46b9STakashi Sakamoto 5867d92ee7STakashi Sakamoto #define CIP_HEADER_SIZE (sizeof(__be32) * CIP_HEADER_QUADLETS) 5967d92ee7STakashi Sakamoto 6051c29fd2STakashi Sakamoto /* Audio and Music transfer protocol specific parameters */ 61d67c46b9STakashi Sakamoto #define CIP_FMT_AM 0x10 62d67c46b9STakashi Sakamoto #define AMDTP_FDF_NO_DATA 0xff 63d67c46b9STakashi Sakamoto 64f11453c7STakashi Sakamoto // For iso header and tstamp. 6567d92ee7STakashi Sakamoto #define IR_CTX_HEADER_DEFAULT_QUADLETS 2 6667d92ee7STakashi Sakamoto // Add nothing. 6767d92ee7STakashi Sakamoto #define IR_CTX_HEADER_SIZE_NO_CIP (sizeof(__be32) * IR_CTX_HEADER_DEFAULT_QUADLETS) 6867d92ee7STakashi Sakamoto // Add two quadlets CIP header. 6967d92ee7STakashi Sakamoto #define IR_CTX_HEADER_SIZE_CIP (IR_CTX_HEADER_SIZE_NO_CIP + CIP_HEADER_SIZE) 70cc4f8e91STakashi Sakamoto #define HEADER_TSTAMP_MASK 0x0000ffff 71d67c46b9STakashi Sakamoto 7267d92ee7STakashi Sakamoto #define IT_PKT_HEADER_SIZE_CIP CIP_HEADER_SIZE 73b18f0cfaSTakashi Sakamoto #define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing. 74b18f0cfaSTakashi Sakamoto 756a3ce97dSTakashi Sakamoto // The initial firmware of OXFW970 can postpone transmission of packet during finishing 766a3ce97dSTakashi Sakamoto // asynchronous transaction. This module accepts 5 cycles to skip as maximum to avoid buffer 776a3ce97dSTakashi Sakamoto // overrun. Actual device can skip more, then this module stops the packet streaming. 786a3ce97dSTakashi Sakamoto #define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES 5 796a3ce97dSTakashi Sakamoto 80d67c46b9STakashi Sakamoto /** 81d67c46b9STakashi Sakamoto * amdtp_stream_init - initialize an AMDTP stream structure 82d67c46b9STakashi Sakamoto * @s: the AMDTP stream to initialize 83d67c46b9STakashi Sakamoto * @unit: the target of the stream 84d67c46b9STakashi Sakamoto * @dir: the direction of stream 85ffe66bbeSTakashi Sakamoto * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants. 865955815eSTakashi Sakamoto * @fmt: the value of fmt field in CIP header 879a738ad1STakashi Sakamoto * @process_ctx_payloads: callback handler to process payloads of isoc context 88df075feeSTakashi Sakamoto * @protocol_size: the size to allocate newly for protocol 89d67c46b9STakashi Sakamoto */ 90d67c46b9STakashi Sakamoto int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, 91ffe66bbeSTakashi Sakamoto enum amdtp_stream_direction dir, unsigned int flags, 92df075feeSTakashi Sakamoto unsigned int fmt, 939a738ad1STakashi Sakamoto amdtp_stream_process_ctx_payloads_t process_ctx_payloads, 94df075feeSTakashi Sakamoto unsigned int protocol_size) 95d67c46b9STakashi Sakamoto { 969a738ad1STakashi Sakamoto if (process_ctx_payloads == NULL) 97df075feeSTakashi Sakamoto return -EINVAL; 98df075feeSTakashi Sakamoto 99df075feeSTakashi Sakamoto s->protocol = kzalloc(protocol_size, GFP_KERNEL); 100df075feeSTakashi Sakamoto if (!s->protocol) 101df075feeSTakashi Sakamoto return -ENOMEM; 102df075feeSTakashi Sakamoto 103d67c46b9STakashi Sakamoto s->unit = unit; 104d67c46b9STakashi Sakamoto s->direction = dir; 105d67c46b9STakashi Sakamoto s->flags = flags; 106d67c46b9STakashi Sakamoto s->context = ERR_PTR(-1); 107d67c46b9STakashi Sakamoto mutex_init(&s->mutex); 108d67c46b9STakashi Sakamoto s->packet_index = 0; 109d67c46b9STakashi Sakamoto 110bdaedca7STakashi Sakamoto init_waitqueue_head(&s->ready_wait); 111d67c46b9STakashi Sakamoto 1125955815eSTakashi Sakamoto s->fmt = fmt; 1139a738ad1STakashi Sakamoto s->process_ctx_payloads = process_ctx_payloads; 114d67c46b9STakashi Sakamoto 115d67c46b9STakashi Sakamoto return 0; 116d67c46b9STakashi Sakamoto } 117d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_init); 118d67c46b9STakashi Sakamoto 119d67c46b9STakashi Sakamoto /** 120d67c46b9STakashi Sakamoto * amdtp_stream_destroy - free stream resources 121d67c46b9STakashi Sakamoto * @s: the AMDTP stream to destroy 122d67c46b9STakashi Sakamoto */ 123d67c46b9STakashi Sakamoto void amdtp_stream_destroy(struct amdtp_stream *s) 124d67c46b9STakashi Sakamoto { 12544c376b9STakashi Sakamoto /* Not initialized. */ 12644c376b9STakashi Sakamoto if (s->protocol == NULL) 12744c376b9STakashi Sakamoto return; 12844c376b9STakashi Sakamoto 129d67c46b9STakashi Sakamoto WARN_ON(amdtp_stream_running(s)); 130df075feeSTakashi Sakamoto kfree(s->protocol); 131d67c46b9STakashi Sakamoto mutex_destroy(&s->mutex); 132d67c46b9STakashi Sakamoto } 133d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_destroy); 134d67c46b9STakashi Sakamoto 135d67c46b9STakashi Sakamoto const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = { 136d67c46b9STakashi Sakamoto [CIP_SFC_32000] = 8, 137d67c46b9STakashi Sakamoto [CIP_SFC_44100] = 8, 138d67c46b9STakashi Sakamoto [CIP_SFC_48000] = 8, 139d67c46b9STakashi Sakamoto [CIP_SFC_88200] = 16, 140d67c46b9STakashi Sakamoto [CIP_SFC_96000] = 16, 141d67c46b9STakashi Sakamoto [CIP_SFC_176400] = 32, 142d67c46b9STakashi Sakamoto [CIP_SFC_192000] = 32, 143d67c46b9STakashi Sakamoto }; 144d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_syt_intervals); 145d67c46b9STakashi Sakamoto 146d67c46b9STakashi Sakamoto const unsigned int amdtp_rate_table[CIP_SFC_COUNT] = { 147d67c46b9STakashi Sakamoto [CIP_SFC_32000] = 32000, 148d67c46b9STakashi Sakamoto [CIP_SFC_44100] = 44100, 149d67c46b9STakashi Sakamoto [CIP_SFC_48000] = 48000, 150d67c46b9STakashi Sakamoto [CIP_SFC_88200] = 88200, 151d67c46b9STakashi Sakamoto [CIP_SFC_96000] = 96000, 152d67c46b9STakashi Sakamoto [CIP_SFC_176400] = 176400, 153d67c46b9STakashi Sakamoto [CIP_SFC_192000] = 192000, 154d67c46b9STakashi Sakamoto }; 155d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_rate_table); 156d67c46b9STakashi Sakamoto 15759502295STakashi Sakamoto static int apply_constraint_to_size(struct snd_pcm_hw_params *params, 15859502295STakashi Sakamoto struct snd_pcm_hw_rule *rule) 15959502295STakashi Sakamoto { 16059502295STakashi Sakamoto struct snd_interval *s = hw_param_interval(params, rule->var); 16159502295STakashi Sakamoto const struct snd_interval *r = 16259502295STakashi Sakamoto hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); 163826b5de9STakashi Sakamoto struct snd_interval t = {0}; 164826b5de9STakashi Sakamoto unsigned int step = 0; 16559502295STakashi Sakamoto int i; 16659502295STakashi Sakamoto 16759502295STakashi Sakamoto for (i = 0; i < CIP_SFC_COUNT; ++i) { 168826b5de9STakashi Sakamoto if (snd_interval_test(r, amdtp_rate_table[i])) 169826b5de9STakashi Sakamoto step = max(step, amdtp_syt_intervals[i]); 17059502295STakashi Sakamoto } 17159502295STakashi Sakamoto 172826b5de9STakashi Sakamoto t.min = roundup(s->min, step); 173826b5de9STakashi Sakamoto t.max = rounddown(s->max, step); 174826b5de9STakashi Sakamoto t.integer = 1; 17559502295STakashi Sakamoto 17659502295STakashi Sakamoto return snd_interval_refine(s, &t); 17759502295STakashi Sakamoto } 17859502295STakashi Sakamoto 179d67c46b9STakashi Sakamoto /** 180d67c46b9STakashi Sakamoto * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream 181d67c46b9STakashi Sakamoto * @s: the AMDTP stream, which must be initialized. 182d67c46b9STakashi Sakamoto * @runtime: the PCM substream runtime 183d67c46b9STakashi Sakamoto */ 184d67c46b9STakashi Sakamoto int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, 185d67c46b9STakashi Sakamoto struct snd_pcm_runtime *runtime) 186d67c46b9STakashi Sakamoto { 18755799c5aSTakashi Sakamoto struct snd_pcm_hardware *hw = &runtime->hw; 18899921ec6STakashi Sakamoto unsigned int ctx_header_size; 18999921ec6STakashi Sakamoto unsigned int maximum_usec_per_period; 190d67c46b9STakashi Sakamoto int err; 191d67c46b9STakashi Sakamoto 192d360870aSTakashi Sakamoto hw->info = SNDRV_PCM_INFO_BLOCK_TRANSFER | 19355799c5aSTakashi Sakamoto SNDRV_PCM_INFO_INTERLEAVED | 19455799c5aSTakashi Sakamoto SNDRV_PCM_INFO_JOINT_DUPLEX | 19555799c5aSTakashi Sakamoto SNDRV_PCM_INFO_MMAP | 196d360870aSTakashi Sakamoto SNDRV_PCM_INFO_MMAP_VALID | 197d360870aSTakashi Sakamoto SNDRV_PCM_INFO_NO_PERIOD_WAKEUP; 19855799c5aSTakashi Sakamoto 19955799c5aSTakashi Sakamoto hw->periods_min = 2; 20055799c5aSTakashi Sakamoto hw->periods_max = UINT_MAX; 20155799c5aSTakashi Sakamoto 20255799c5aSTakashi Sakamoto /* bytes for a frame */ 20355799c5aSTakashi Sakamoto hw->period_bytes_min = 4 * hw->channels_max; 20455799c5aSTakashi Sakamoto 20555799c5aSTakashi Sakamoto /* Just to prevent from allocating much pages. */ 20655799c5aSTakashi Sakamoto hw->period_bytes_max = hw->period_bytes_min * 2048; 20755799c5aSTakashi Sakamoto hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; 20855799c5aSTakashi Sakamoto 20999921ec6STakashi Sakamoto // Linux driver for 1394 OHCI controller voluntarily flushes isoc 21099921ec6STakashi Sakamoto // context when total size of accumulated context header reaches 2112b3d2987STakashi Iwai // PAGE_SIZE. This kicks work for the isoc context and brings 21299921ec6STakashi Sakamoto // callback in the middle of scheduled interrupts. 21399921ec6STakashi Sakamoto // Although AMDTP streams in the same domain use the same events per 21499921ec6STakashi Sakamoto // IRQ, use the largest size of context header between IT/IR contexts. 21599921ec6STakashi Sakamoto // Here, use the value of context header in IR context is for both 21699921ec6STakashi Sakamoto // contexts. 21799921ec6STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 21899921ec6STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_CIP; 21999921ec6STakashi Sakamoto else 22099921ec6STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; 22199921ec6STakashi Sakamoto maximum_usec_per_period = USEC_PER_SEC * PAGE_SIZE / 22299921ec6STakashi Sakamoto CYCLES_PER_SECOND / ctx_header_size; 22399921ec6STakashi Sakamoto 224f706df4fSTakashi Sakamoto // In IEC 61883-6, one isoc packet can transfer events up to the value 225f706df4fSTakashi Sakamoto // of syt interval. This comes from the interval of isoc cycle. As 1394 226f706df4fSTakashi Sakamoto // OHCI controller can generate hardware IRQ per isoc packet, the 227f706df4fSTakashi Sakamoto // interval is 125 usec. 228f706df4fSTakashi Sakamoto // However, there are two ways of transmission in IEC 61883-6; blocking 229f706df4fSTakashi Sakamoto // and non-blocking modes. In blocking mode, the sequence of isoc packet 230f706df4fSTakashi Sakamoto // includes 'empty' or 'NODATA' packets which include no event. In 231f706df4fSTakashi Sakamoto // non-blocking mode, the number of events per packet is variable up to 232f706df4fSTakashi Sakamoto // the syt interval. 233f706df4fSTakashi Sakamoto // Due to the above protocol design, the minimum PCM frames per 234f706df4fSTakashi Sakamoto // interrupt should be double of the value of syt interval, thus it is 235f706df4fSTakashi Sakamoto // 250 usec. 236d67c46b9STakashi Sakamoto err = snd_pcm_hw_constraint_minmax(runtime, 237d67c46b9STakashi Sakamoto SNDRV_PCM_HW_PARAM_PERIOD_TIME, 238f706df4fSTakashi Sakamoto 250, maximum_usec_per_period); 239d67c46b9STakashi Sakamoto if (err < 0) 240d67c46b9STakashi Sakamoto goto end; 241d67c46b9STakashi Sakamoto 242d67c46b9STakashi Sakamoto /* Non-Blocking stream has no more constraints */ 243d67c46b9STakashi Sakamoto if (!(s->flags & CIP_BLOCKING)) 244d67c46b9STakashi Sakamoto goto end; 245d67c46b9STakashi Sakamoto 246d67c46b9STakashi Sakamoto /* 247d67c46b9STakashi Sakamoto * One AMDTP packet can include some frames. In blocking mode, the 248d67c46b9STakashi Sakamoto * number equals to SYT_INTERVAL. So the number is 8, 16 or 32, 249d67c46b9STakashi Sakamoto * depending on its sampling rate. For accurate period interrupt, it's 250d67c46b9STakashi Sakamoto * preferrable to align period/buffer sizes to current SYT_INTERVAL. 251d67c46b9STakashi Sakamoto */ 25259502295STakashi Sakamoto err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 25359502295STakashi Sakamoto apply_constraint_to_size, NULL, 254826b5de9STakashi Sakamoto SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 25559502295STakashi Sakamoto SNDRV_PCM_HW_PARAM_RATE, -1); 256d67c46b9STakashi Sakamoto if (err < 0) 257d67c46b9STakashi Sakamoto goto end; 25859502295STakashi Sakamoto err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 25959502295STakashi Sakamoto apply_constraint_to_size, NULL, 260826b5de9STakashi Sakamoto SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 26159502295STakashi Sakamoto SNDRV_PCM_HW_PARAM_RATE, -1); 26259502295STakashi Sakamoto if (err < 0) 26359502295STakashi Sakamoto goto end; 264d67c46b9STakashi Sakamoto end: 265d67c46b9STakashi Sakamoto return err; 266d67c46b9STakashi Sakamoto } 267d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_add_pcm_hw_constraints); 268d67c46b9STakashi Sakamoto 269d67c46b9STakashi Sakamoto /** 270d67c46b9STakashi Sakamoto * amdtp_stream_set_parameters - set stream parameters 271d67c46b9STakashi Sakamoto * @s: the AMDTP stream to configure 272d67c46b9STakashi Sakamoto * @rate: the sample rate 273df075feeSTakashi Sakamoto * @data_block_quadlets: the size of a data block in quadlet unit 274d67c46b9STakashi Sakamoto * 275d67c46b9STakashi Sakamoto * The parameters must be set before the stream is started, and must not be 276d67c46b9STakashi Sakamoto * changed while the stream is running. 277d67c46b9STakashi Sakamoto */ 278df075feeSTakashi Sakamoto int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, 279df075feeSTakashi Sakamoto unsigned int data_block_quadlets) 280d67c46b9STakashi Sakamoto { 281df075feeSTakashi Sakamoto unsigned int sfc; 282d67c46b9STakashi Sakamoto 283d67c46b9STakashi Sakamoto for (sfc = 0; sfc < ARRAY_SIZE(amdtp_rate_table); ++sfc) { 284d67c46b9STakashi Sakamoto if (amdtp_rate_table[sfc] == rate) 285d67c46b9STakashi Sakamoto break; 286d67c46b9STakashi Sakamoto } 287d67c46b9STakashi Sakamoto if (sfc == ARRAY_SIZE(amdtp_rate_table)) 288d67c46b9STakashi Sakamoto return -EINVAL; 289d67c46b9STakashi Sakamoto 290d67c46b9STakashi Sakamoto s->sfc = sfc; 291df075feeSTakashi Sakamoto s->data_block_quadlets = data_block_quadlets; 292d67c46b9STakashi Sakamoto s->syt_interval = amdtp_syt_intervals[sfc]; 293d67c46b9STakashi Sakamoto 294d3d10a4aSTakashi Sakamoto // default buffering in the device. 29513d11f14STakashi Sakamoto s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; 296d3d10a4aSTakashi Sakamoto 29713d11f14STakashi Sakamoto // additional buffering needed to adjust for no-data packets. 29813d11f14STakashi Sakamoto if (s->flags & CIP_BLOCKING) 29913d11f14STakashi Sakamoto s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; 300d67c46b9STakashi Sakamoto 301d67c46b9STakashi Sakamoto return 0; 302d67c46b9STakashi Sakamoto } 303d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_set_parameters); 304d67c46b9STakashi Sakamoto 305c75f3678STakashi Sakamoto // The CIP header is processed in context header apart from context payload. 306c75f3678STakashi Sakamoto static int amdtp_stream_get_max_ctx_payload_size(struct amdtp_stream *s) 307c75f3678STakashi Sakamoto { 308c75f3678STakashi Sakamoto unsigned int multiplier; 309c75f3678STakashi Sakamoto 310c75f3678STakashi Sakamoto if (s->flags & CIP_JUMBO_PAYLOAD) 311c75f3678STakashi Sakamoto multiplier = IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES; 312c75f3678STakashi Sakamoto else 313c75f3678STakashi Sakamoto multiplier = 1; 314c75f3678STakashi Sakamoto 315c75f3678STakashi Sakamoto return s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier; 316c75f3678STakashi Sakamoto } 317c75f3678STakashi Sakamoto 318d67c46b9STakashi Sakamoto /** 319d67c46b9STakashi Sakamoto * amdtp_stream_get_max_payload - get the stream's packet size 320d67c46b9STakashi Sakamoto * @s: the AMDTP stream 321d67c46b9STakashi Sakamoto * 322d67c46b9STakashi Sakamoto * This function must not be called before the stream has been configured 323d67c46b9STakashi Sakamoto * with amdtp_stream_set_parameters(). 324d67c46b9STakashi Sakamoto */ 325d67c46b9STakashi Sakamoto unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) 326d67c46b9STakashi Sakamoto { 327c75f3678STakashi Sakamoto unsigned int cip_header_size; 328d67c46b9STakashi Sakamoto 3293b196c39STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 33067d92ee7STakashi Sakamoto cip_header_size = CIP_HEADER_SIZE; 331c75f3678STakashi Sakamoto else 332c75f3678STakashi Sakamoto cip_header_size = 0; 333d67c46b9STakashi Sakamoto 334c75f3678STakashi Sakamoto return cip_header_size + amdtp_stream_get_max_ctx_payload_size(s); 335d67c46b9STakashi Sakamoto } 336d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_get_max_payload); 337d67c46b9STakashi Sakamoto 338d67c46b9STakashi Sakamoto /** 339d67c46b9STakashi Sakamoto * amdtp_stream_pcm_prepare - prepare PCM device for running 340d67c46b9STakashi Sakamoto * @s: the AMDTP stream 341d67c46b9STakashi Sakamoto * 342d67c46b9STakashi Sakamoto * This function should be called from the PCM device's .prepare callback. 343d67c46b9STakashi Sakamoto */ 344d67c46b9STakashi Sakamoto void amdtp_stream_pcm_prepare(struct amdtp_stream *s) 345d67c46b9STakashi Sakamoto { 346d67c46b9STakashi Sakamoto s->pcm_buffer_pointer = 0; 347d67c46b9STakashi Sakamoto s->pcm_period_pointer = 0; 348d67c46b9STakashi Sakamoto } 349d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_prepare); 350d67c46b9STakashi Sakamoto 351c9f3ac2aSTakashi Sakamoto static void pool_blocking_data_blocks(struct amdtp_stream *s, struct seq_desc *descs, 352119c446aSTakashi Sakamoto unsigned int size, unsigned int pos, unsigned int count) 353d67c46b9STakashi Sakamoto { 354c9f3ac2aSTakashi Sakamoto const unsigned int syt_interval = s->syt_interval; 355c9f3ac2aSTakashi Sakamoto int i; 356d67c46b9STakashi Sakamoto 357c9f3ac2aSTakashi Sakamoto for (i = 0; i < count; ++i) { 358119c446aSTakashi Sakamoto struct seq_desc *desc = descs + pos; 359c9f3ac2aSTakashi Sakamoto 360c9f3ac2aSTakashi Sakamoto if (desc->syt_offset != CIP_SYT_NO_INFO) 361c9f3ac2aSTakashi Sakamoto desc->data_blocks = syt_interval; 362d67c46b9STakashi Sakamoto else 363c9f3ac2aSTakashi Sakamoto desc->data_blocks = 0; 364c9f3ac2aSTakashi Sakamoto 365119c446aSTakashi Sakamoto pos = (pos + 1) % size; 366c9f3ac2aSTakashi Sakamoto } 367c9f3ac2aSTakashi Sakamoto } 368c9f3ac2aSTakashi Sakamoto 369c9f3ac2aSTakashi Sakamoto static void pool_ideal_nonblocking_data_blocks(struct amdtp_stream *s, struct seq_desc *descs, 370119c446aSTakashi Sakamoto unsigned int size, unsigned int pos, 371c9f3ac2aSTakashi Sakamoto unsigned int count) 372c9f3ac2aSTakashi Sakamoto { 373c9f3ac2aSTakashi Sakamoto const enum cip_sfc sfc = s->sfc; 374c9f3ac2aSTakashi Sakamoto unsigned int state = s->ctx_data.rx.data_block_state; 375c9f3ac2aSTakashi Sakamoto int i; 376c9f3ac2aSTakashi Sakamoto 377c9f3ac2aSTakashi Sakamoto for (i = 0; i < count; ++i) { 378119c446aSTakashi Sakamoto struct seq_desc *desc = descs + pos; 379c9f3ac2aSTakashi Sakamoto 380274fc355STakashi Sakamoto if (!cip_sfc_is_base_44100(sfc)) { 381d3d10a4aSTakashi Sakamoto // Sample_rate / 8000 is an integer, and precomputed. 382c9f3ac2aSTakashi Sakamoto desc->data_blocks = state; 383d67c46b9STakashi Sakamoto } else { 384c9f3ac2aSTakashi Sakamoto unsigned int phase = state; 385d67c46b9STakashi Sakamoto 386d67c46b9STakashi Sakamoto /* 387d67c46b9STakashi Sakamoto * This calculates the number of data blocks per packet so that 388d67c46b9STakashi Sakamoto * 1) the overall rate is correct and exactly synchronized to 389d67c46b9STakashi Sakamoto * the bus clock, and 390d67c46b9STakashi Sakamoto * 2) packets with a rounded-up number of blocks occur as early 391d67c46b9STakashi Sakamoto * as possible in the sequence (to prevent underruns of the 392d67c46b9STakashi Sakamoto * device's buffer). 393d67c46b9STakashi Sakamoto */ 394274fc355STakashi Sakamoto if (sfc == CIP_SFC_44100) 395d67c46b9STakashi Sakamoto /* 6 6 5 6 5 6 5 ... */ 396c9f3ac2aSTakashi Sakamoto desc->data_blocks = 5 + ((phase & 1) ^ (phase == 0 || phase >= 40)); 397d67c46b9STakashi Sakamoto else 398d67c46b9STakashi Sakamoto /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ 399c9f3ac2aSTakashi Sakamoto desc->data_blocks = 11 * (sfc >> 1) + (phase == 0); 400274fc355STakashi Sakamoto if (++phase >= (80 >> (sfc >> 1))) 401d67c46b9STakashi Sakamoto phase = 0; 402c9f3ac2aSTakashi Sakamoto state = phase; 403d67c46b9STakashi Sakamoto } 404d67c46b9STakashi Sakamoto 405119c446aSTakashi Sakamoto pos = (pos + 1) % size; 406c9f3ac2aSTakashi Sakamoto } 407c9f3ac2aSTakashi Sakamoto 408c9f3ac2aSTakashi Sakamoto s->ctx_data.rx.data_block_state = state; 409d67c46b9STakashi Sakamoto } 410d67c46b9STakashi Sakamoto 411816d8482STakashi Sakamoto static unsigned int calculate_syt_offset(unsigned int *last_syt_offset, 412816d8482STakashi Sakamoto unsigned int *syt_offset_state, enum cip_sfc sfc) 413d67c46b9STakashi Sakamoto { 414816d8482STakashi Sakamoto unsigned int syt_offset; 415d67c46b9STakashi Sakamoto 416816d8482STakashi Sakamoto if (*last_syt_offset < TICKS_PER_CYCLE) { 417816d8482STakashi Sakamoto if (!cip_sfc_is_base_44100(sfc)) 418816d8482STakashi Sakamoto syt_offset = *last_syt_offset + *syt_offset_state; 419d67c46b9STakashi Sakamoto else { 420d67c46b9STakashi Sakamoto /* 421d67c46b9STakashi Sakamoto * The time, in ticks, of the n'th SYT_INTERVAL sample is: 422d67c46b9STakashi Sakamoto * n * SYT_INTERVAL * 24576000 / sample_rate 423d67c46b9STakashi Sakamoto * Modulo TICKS_PER_CYCLE, the difference between successive 424d67c46b9STakashi Sakamoto * elements is about 1386.23. Rounding the results of this 425d67c46b9STakashi Sakamoto * formula to the SYT precision results in a sequence of 426d67c46b9STakashi Sakamoto * differences that begins with: 427d67c46b9STakashi Sakamoto * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ... 428d67c46b9STakashi Sakamoto * This code generates _exactly_ the same sequence. 429d67c46b9STakashi Sakamoto */ 430816d8482STakashi Sakamoto unsigned int phase = *syt_offset_state; 431816d8482STakashi Sakamoto unsigned int index = phase % 13; 432816d8482STakashi Sakamoto 433816d8482STakashi Sakamoto syt_offset = *last_syt_offset; 434d67c46b9STakashi Sakamoto syt_offset += 1386 + ((index && !(index & 3)) || 435d67c46b9STakashi Sakamoto phase == 146); 436d67c46b9STakashi Sakamoto if (++phase >= 147) 437d67c46b9STakashi Sakamoto phase = 0; 438816d8482STakashi Sakamoto *syt_offset_state = phase; 439d67c46b9STakashi Sakamoto } 440d67c46b9STakashi Sakamoto } else 441816d8482STakashi Sakamoto syt_offset = *last_syt_offset - TICKS_PER_CYCLE; 442816d8482STakashi Sakamoto *last_syt_offset = syt_offset; 443d67c46b9STakashi Sakamoto 44483cfb5c5STakashi Sakamoto if (syt_offset >= TICKS_PER_CYCLE) 44583cfb5c5STakashi Sakamoto syt_offset = CIP_SYT_NO_INFO; 446d67c46b9STakashi Sakamoto 44783cfb5c5STakashi Sakamoto return syt_offset; 448d67c46b9STakashi Sakamoto } 449d67c46b9STakashi Sakamoto 450c79b7158STakashi Sakamoto static void pool_ideal_syt_offsets(struct amdtp_stream *s, struct seq_desc *descs, 451119c446aSTakashi Sakamoto unsigned int size, unsigned int pos, unsigned int count) 452c79b7158STakashi Sakamoto { 453c79b7158STakashi Sakamoto const enum cip_sfc sfc = s->sfc; 454c79b7158STakashi Sakamoto unsigned int last = s->ctx_data.rx.last_syt_offset; 455c79b7158STakashi Sakamoto unsigned int state = s->ctx_data.rx.syt_offset_state; 456c79b7158STakashi Sakamoto int i; 457c79b7158STakashi Sakamoto 458c79b7158STakashi Sakamoto for (i = 0; i < count; ++i) { 459119c446aSTakashi Sakamoto struct seq_desc *desc = descs + pos; 460c79b7158STakashi Sakamoto 461c79b7158STakashi Sakamoto desc->syt_offset = calculate_syt_offset(&last, &state, sfc); 462c79b7158STakashi Sakamoto 463119c446aSTakashi Sakamoto pos = (pos + 1) % size; 464c79b7158STakashi Sakamoto } 465c79b7158STakashi Sakamoto 466c79b7158STakashi Sakamoto s->ctx_data.rx.last_syt_offset = last; 467c79b7158STakashi Sakamoto s->ctx_data.rx.syt_offset_state = state; 468c79b7158STakashi Sakamoto } 469c79b7158STakashi Sakamoto 470f9e5ecdfSTakashi Sakamoto static unsigned int compute_syt_offset(unsigned int syt, unsigned int cycle, 471f9e5ecdfSTakashi Sakamoto unsigned int transfer_delay) 472f9e5ecdfSTakashi Sakamoto { 473f9e5ecdfSTakashi Sakamoto unsigned int cycle_lo = (cycle % CYCLES_PER_SECOND) & 0x0f; 474f9e5ecdfSTakashi Sakamoto unsigned int syt_cycle_lo = (syt & 0xf000) >> 12; 475f9e5ecdfSTakashi Sakamoto unsigned int syt_offset; 476f9e5ecdfSTakashi Sakamoto 477f9e5ecdfSTakashi Sakamoto // Round up. 478f9e5ecdfSTakashi Sakamoto if (syt_cycle_lo < cycle_lo) 479f9e5ecdfSTakashi Sakamoto syt_cycle_lo += CIP_SYT_CYCLE_MODULUS; 480f9e5ecdfSTakashi Sakamoto syt_cycle_lo -= cycle_lo; 481f9e5ecdfSTakashi Sakamoto 482f9e5ecdfSTakashi Sakamoto // Subtract transfer delay so that the synchronization offset is not so large 483f9e5ecdfSTakashi Sakamoto // at transmission. 484f9e5ecdfSTakashi Sakamoto syt_offset = syt_cycle_lo * TICKS_PER_CYCLE + (syt & 0x0fff); 485f9e5ecdfSTakashi Sakamoto if (syt_offset < transfer_delay) 486f9e5ecdfSTakashi Sakamoto syt_offset += CIP_SYT_CYCLE_MODULUS * TICKS_PER_CYCLE; 487f9e5ecdfSTakashi Sakamoto 488f9e5ecdfSTakashi Sakamoto return syt_offset - transfer_delay; 489f9e5ecdfSTakashi Sakamoto } 490f9e5ecdfSTakashi Sakamoto 49139c2649cSTakashi Sakamoto // Both of the producer and consumer of the queue runs in the same clock of IEEE 1394 bus. 49239c2649cSTakashi Sakamoto // Additionally, the sequence of tx packets is severely checked against any discontinuity 49339c2649cSTakashi Sakamoto // before filling entries in the queue. The calculation is safe even if it looks fragile by 49439c2649cSTakashi Sakamoto // overrun. 49539c2649cSTakashi Sakamoto static unsigned int calculate_cached_cycle_count(struct amdtp_stream *s, unsigned int head) 49639c2649cSTakashi Sakamoto { 49739c2649cSTakashi Sakamoto const unsigned int cache_size = s->ctx_data.tx.cache.size; 49839c2649cSTakashi Sakamoto unsigned int cycles = s->ctx_data.tx.cache.tail; 49939c2649cSTakashi Sakamoto 50039c2649cSTakashi Sakamoto if (cycles < head) 50139c2649cSTakashi Sakamoto cycles += cache_size; 50239c2649cSTakashi Sakamoto cycles -= head; 50339c2649cSTakashi Sakamoto 50439c2649cSTakashi Sakamoto return cycles; 50539c2649cSTakashi Sakamoto } 50639c2649cSTakashi Sakamoto 507f9e5ecdfSTakashi Sakamoto static void cache_seq(struct amdtp_stream *s, const struct pkt_desc *descs, unsigned int desc_count) 508f9e5ecdfSTakashi Sakamoto { 509f9e5ecdfSTakashi Sakamoto const unsigned int transfer_delay = s->transfer_delay; 510f9e5ecdfSTakashi Sakamoto const unsigned int cache_size = s->ctx_data.tx.cache.size; 511f9e5ecdfSTakashi Sakamoto struct seq_desc *cache = s->ctx_data.tx.cache.descs; 512f9e5ecdfSTakashi Sakamoto unsigned int cache_tail = s->ctx_data.tx.cache.tail; 513f9e5ecdfSTakashi Sakamoto bool aware_syt = !(s->flags & CIP_UNAWARE_SYT); 514f9e5ecdfSTakashi Sakamoto int i; 515f9e5ecdfSTakashi Sakamoto 516f9e5ecdfSTakashi Sakamoto for (i = 0; i < desc_count; ++i) { 517f9e5ecdfSTakashi Sakamoto struct seq_desc *dst = cache + cache_tail; 518f9e5ecdfSTakashi Sakamoto const struct pkt_desc *src = descs + i; 519f9e5ecdfSTakashi Sakamoto 520f9e5ecdfSTakashi Sakamoto if (aware_syt && src->syt != CIP_SYT_NO_INFO) 521f9e5ecdfSTakashi Sakamoto dst->syt_offset = compute_syt_offset(src->syt, src->cycle, transfer_delay); 522f9e5ecdfSTakashi Sakamoto else 523f9e5ecdfSTakashi Sakamoto dst->syt_offset = CIP_SYT_NO_INFO; 524f9e5ecdfSTakashi Sakamoto dst->data_blocks = src->data_blocks; 525f9e5ecdfSTakashi Sakamoto 526f9e5ecdfSTakashi Sakamoto cache_tail = (cache_tail + 1) % cache_size; 527f9e5ecdfSTakashi Sakamoto } 528f9e5ecdfSTakashi Sakamoto 529f9e5ecdfSTakashi Sakamoto s->ctx_data.tx.cache.tail = cache_tail; 530f9e5ecdfSTakashi Sakamoto } 531f9e5ecdfSTakashi Sakamoto 532119c446aSTakashi Sakamoto static void pool_ideal_seq_descs(struct amdtp_stream *s, struct seq_desc *descs, unsigned int size, 533119c446aSTakashi Sakamoto unsigned int pos, unsigned int count) 5346f24bb8aSTakashi Sakamoto { 535119c446aSTakashi Sakamoto pool_ideal_syt_offsets(s, descs, size, pos, count); 536c79b7158STakashi Sakamoto 537c9f3ac2aSTakashi Sakamoto if (s->flags & CIP_BLOCKING) 538119c446aSTakashi Sakamoto pool_blocking_data_blocks(s, descs, size, pos, count); 539c9f3ac2aSTakashi Sakamoto else 540119c446aSTakashi Sakamoto pool_ideal_nonblocking_data_blocks(s, descs, size, pos, count); 5416f24bb8aSTakashi Sakamoto } 5426f24bb8aSTakashi Sakamoto 543119c446aSTakashi Sakamoto static void pool_replayed_seq(struct amdtp_stream *s, struct seq_desc *descs, unsigned int size, 544119c446aSTakashi Sakamoto unsigned int pos, unsigned int count) 54539c2649cSTakashi Sakamoto { 54639c2649cSTakashi Sakamoto struct amdtp_stream *target = s->ctx_data.rx.replay_target; 54739c2649cSTakashi Sakamoto const struct seq_desc *cache = target->ctx_data.tx.cache.descs; 54839c2649cSTakashi Sakamoto const unsigned int cache_size = target->ctx_data.tx.cache.size; 54939c2649cSTakashi Sakamoto unsigned int cache_head = s->ctx_data.rx.cache_head; 55039c2649cSTakashi Sakamoto int i; 55139c2649cSTakashi Sakamoto 55239c2649cSTakashi Sakamoto for (i = 0; i < count; ++i) { 553119c446aSTakashi Sakamoto descs[pos] = cache[cache_head]; 55439c2649cSTakashi Sakamoto cache_head = (cache_head + 1) % cache_size; 555119c446aSTakashi Sakamoto pos = (pos + 1) % size; 55639c2649cSTakashi Sakamoto } 55739c2649cSTakashi Sakamoto 55839c2649cSTakashi Sakamoto s->ctx_data.rx.cache_head = cache_head; 55939c2649cSTakashi Sakamoto } 56039c2649cSTakashi Sakamoto 561*f2bdee85STakashi Sakamoto static void pool_seq_descs(struct amdtp_stream *s, struct seq_desc *descs, unsigned int size, 562*f2bdee85STakashi Sakamoto unsigned int pos, unsigned int count) 56339c2649cSTakashi Sakamoto { 56439c2649cSTakashi Sakamoto struct amdtp_domain *d = s->domain; 565119c446aSTakashi Sakamoto void (*pool_seq_descs)(struct amdtp_stream *s, struct seq_desc *descs, unsigned int size, 566119c446aSTakashi Sakamoto unsigned int pos, unsigned int count); 56739c2649cSTakashi Sakamoto 5682f21a177STakashi Sakamoto if (!d->replay.enable || !s->ctx_data.rx.replay_target) { 569119c446aSTakashi Sakamoto pool_seq_descs = pool_ideal_seq_descs; 5702f21a177STakashi Sakamoto } else { 5712f21a177STakashi Sakamoto if (!d->replay.on_the_fly) { 572119c446aSTakashi Sakamoto pool_seq_descs = pool_replayed_seq; 5732f21a177STakashi Sakamoto } else { 5742f21a177STakashi Sakamoto struct amdtp_stream *tx = s->ctx_data.rx.replay_target; 5752f21a177STakashi Sakamoto const unsigned int cache_size = tx->ctx_data.tx.cache.size; 5762f21a177STakashi Sakamoto const unsigned int cache_head = s->ctx_data.rx.cache_head; 5772f21a177STakashi Sakamoto unsigned int cached_cycles = calculate_cached_cycle_count(tx, cache_head); 5782f21a177STakashi Sakamoto 5792f21a177STakashi Sakamoto if (cached_cycles > count && cached_cycles > cache_size / 2) 580119c446aSTakashi Sakamoto pool_seq_descs = pool_replayed_seq; 5812f21a177STakashi Sakamoto else 582119c446aSTakashi Sakamoto pool_seq_descs = pool_ideal_seq_descs; 5832f21a177STakashi Sakamoto } 5842f21a177STakashi Sakamoto } 585119c446aSTakashi Sakamoto 586119c446aSTakashi Sakamoto pool_seq_descs(s, descs, size, pos, count); 58739c2649cSTakashi Sakamoto } 58839c2649cSTakashi Sakamoto 589d67c46b9STakashi Sakamoto static void update_pcm_pointers(struct amdtp_stream *s, 590d67c46b9STakashi Sakamoto struct snd_pcm_substream *pcm, 591d67c46b9STakashi Sakamoto unsigned int frames) 592d67c46b9STakashi Sakamoto { 593d67c46b9STakashi Sakamoto unsigned int ptr; 594d67c46b9STakashi Sakamoto 595d67c46b9STakashi Sakamoto ptr = s->pcm_buffer_pointer + frames; 596d67c46b9STakashi Sakamoto if (ptr >= pcm->runtime->buffer_size) 597d67c46b9STakashi Sakamoto ptr -= pcm->runtime->buffer_size; 5986aa7de05SMark Rutland WRITE_ONCE(s->pcm_buffer_pointer, ptr); 599d67c46b9STakashi Sakamoto 600d67c46b9STakashi Sakamoto s->pcm_period_pointer += frames; 601d67c46b9STakashi Sakamoto if (s->pcm_period_pointer >= pcm->runtime->period_size) { 602d67c46b9STakashi Sakamoto s->pcm_period_pointer -= pcm->runtime->period_size; 603d360870aSTakashi Sakamoto 604d360870aSTakashi Sakamoto // The program in user process should periodically check the status of intermediate 605d360870aSTakashi Sakamoto // buffer associated to PCM substream to process PCM frames in the buffer, instead 606d360870aSTakashi Sakamoto // of receiving notification of period elapsed by poll wait. 6077ba5ca32STakashi Sakamoto if (!pcm->runtime->no_period_wakeup) { 6083b86ec63STakashi Sakamoto if (in_softirq()) { 6097ba5ca32STakashi Sakamoto // In software IRQ context for 1394 OHCI. 6107ba5ca32STakashi Sakamoto snd_pcm_period_elapsed(pcm); 6117ba5ca32STakashi Sakamoto } else { 6127ba5ca32STakashi Sakamoto // In process context of ALSA PCM application under acquired lock of 6137ba5ca32STakashi Sakamoto // PCM substream. 6147ba5ca32STakashi Sakamoto snd_pcm_period_elapsed_under_stream_lock(pcm); 6157ba5ca32STakashi Sakamoto } 6167ba5ca32STakashi Sakamoto } 617d67c46b9STakashi Sakamoto } 618d67c46b9STakashi Sakamoto } 619d67c46b9STakashi Sakamoto 620e229853dSTakashi Sakamoto static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params, 621e229853dSTakashi Sakamoto bool sched_irq) 622d67c46b9STakashi Sakamoto { 6236007bf54STakashi Sakamoto int err; 624d67c46b9STakashi Sakamoto 625e229853dSTakashi Sakamoto params->interrupt = sched_irq; 6266007bf54STakashi Sakamoto params->tag = s->tag; 6276007bf54STakashi Sakamoto params->sy = 0; 628d67c46b9STakashi Sakamoto 6296007bf54STakashi Sakamoto err = fw_iso_context_queue(s->context, params, &s->buffer.iso_buffer, 630d67c46b9STakashi Sakamoto s->buffer.packets[s->packet_index].offset); 631d67c46b9STakashi Sakamoto if (err < 0) { 632d67c46b9STakashi Sakamoto dev_err(&s->unit->device, "queueing error: %d\n", err); 633d67c46b9STakashi Sakamoto goto end; 634d67c46b9STakashi Sakamoto } 635d67c46b9STakashi Sakamoto 636a0e02331STakashi Sakamoto if (++s->packet_index >= s->queue_size) 637d67c46b9STakashi Sakamoto s->packet_index = 0; 638d67c46b9STakashi Sakamoto end: 639d67c46b9STakashi Sakamoto return err; 640d67c46b9STakashi Sakamoto } 641d67c46b9STakashi Sakamoto 642d67c46b9STakashi Sakamoto static inline int queue_out_packet(struct amdtp_stream *s, 643e229853dSTakashi Sakamoto struct fw_iso_packet *params, bool sched_irq) 644d67c46b9STakashi Sakamoto { 645b18f0cfaSTakashi Sakamoto params->skip = 646b18f0cfaSTakashi Sakamoto !!(params->header_length == 0 && params->payload_length == 0); 647e229853dSTakashi Sakamoto return queue_packet(s, params, sched_irq); 648d67c46b9STakashi Sakamoto } 649d67c46b9STakashi Sakamoto 6506007bf54STakashi Sakamoto static inline int queue_in_packet(struct amdtp_stream *s, 65160dd4929STakashi Sakamoto struct fw_iso_packet *params) 652d67c46b9STakashi Sakamoto { 6536007bf54STakashi Sakamoto // Queue one packet for IR context. 6546007bf54STakashi Sakamoto params->header_length = s->ctx_data.tx.ctx_header_size; 6556007bf54STakashi Sakamoto params->payload_length = s->ctx_data.tx.max_ctx_payload_length; 6566007bf54STakashi Sakamoto params->skip = false; 65760dd4929STakashi Sakamoto return queue_packet(s, params, false); 658d67c46b9STakashi Sakamoto } 659d67c46b9STakashi Sakamoto 660252219c7STakashi Sakamoto static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], 661860d798cSTakashi Sakamoto unsigned int data_block_counter, unsigned int syt) 662252219c7STakashi Sakamoto { 663252219c7STakashi Sakamoto cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | 664252219c7STakashi Sakamoto (s->data_block_quadlets << CIP_DBS_SHIFT) | 665252219c7STakashi Sakamoto ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | 666860d798cSTakashi Sakamoto data_block_counter); 667252219c7STakashi Sakamoto cip_header[1] = cpu_to_be32(CIP_EOH | 668252219c7STakashi Sakamoto ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | 669252219c7STakashi Sakamoto ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | 670252219c7STakashi Sakamoto (syt & CIP_SYT_MASK)); 671252219c7STakashi Sakamoto } 672252219c7STakashi Sakamoto 6736bc1a269STakashi Sakamoto static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, 674233dbbc7STakashi Sakamoto struct fw_iso_packet *params, unsigned int header_length, 675860d798cSTakashi Sakamoto unsigned int data_blocks, 676860d798cSTakashi Sakamoto unsigned int data_block_counter, 677860d798cSTakashi Sakamoto unsigned int syt, unsigned int index) 678d67c46b9STakashi Sakamoto { 6790ebf3cebSTakashi Sakamoto unsigned int payload_length; 68016be4589STakashi Sakamoto __be32 *cip_header; 681d67c46b9STakashi Sakamoto 6820ebf3cebSTakashi Sakamoto payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; 6830ebf3cebSTakashi Sakamoto params->payload_length = payload_length; 6840ebf3cebSTakashi Sakamoto 685233dbbc7STakashi Sakamoto if (header_length > 0) { 6866bc1a269STakashi Sakamoto cip_header = (__be32 *)params->header; 687860d798cSTakashi Sakamoto generate_cip_header(s, cip_header, data_block_counter, syt); 688233dbbc7STakashi Sakamoto params->header_length = header_length; 689b18f0cfaSTakashi Sakamoto } else { 690b18f0cfaSTakashi Sakamoto cip_header = NULL; 691b18f0cfaSTakashi Sakamoto } 692d67c46b9STakashi Sakamoto 693233dbbc7STakashi Sakamoto trace_amdtp_packet(s, cycle, cip_header, payload_length + header_length, data_blocks, 694814b4312STakashi Sakamoto data_block_counter, s->packet_index, index); 6953b196c39STakashi Sakamoto } 6963b196c39STakashi Sakamoto 697e335425bSTakashi Sakamoto static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, 698e335425bSTakashi Sakamoto unsigned int payload_length, 699a35463d1STakashi Sakamoto unsigned int *data_blocks, 700a35463d1STakashi Sakamoto unsigned int *data_block_counter, unsigned int *syt) 701d67c46b9STakashi Sakamoto { 702d67c46b9STakashi Sakamoto u32 cip_header[2]; 703e335425bSTakashi Sakamoto unsigned int sph; 704e335425bSTakashi Sakamoto unsigned int fmt; 705e335425bSTakashi Sakamoto unsigned int fdf; 706a35463d1STakashi Sakamoto unsigned int dbc; 707d67c46b9STakashi Sakamoto bool lost; 708d67c46b9STakashi Sakamoto 709e335425bSTakashi Sakamoto cip_header[0] = be32_to_cpu(buf[0]); 710e335425bSTakashi Sakamoto cip_header[1] = be32_to_cpu(buf[1]); 711d67c46b9STakashi Sakamoto 712d67c46b9STakashi Sakamoto /* 713d67c46b9STakashi Sakamoto * This module supports 'Two-quadlet CIP header with SYT field'. 714d67c46b9STakashi Sakamoto * For convenience, also check FMT field is AM824 or not. 715d67c46b9STakashi Sakamoto */ 7162128f78fSTakashi Sakamoto if ((((cip_header[0] & CIP_EOH_MASK) == CIP_EOH) || 7172128f78fSTakashi Sakamoto ((cip_header[1] & CIP_EOH_MASK) != CIP_EOH)) && 7182128f78fSTakashi Sakamoto (!(s->flags & CIP_HEADER_WITHOUT_EOH))) { 719d67c46b9STakashi Sakamoto dev_info_ratelimited(&s->unit->device, 720d67c46b9STakashi Sakamoto "Invalid CIP header for AMDTP: %08X:%08X\n", 721d67c46b9STakashi Sakamoto cip_header[0], cip_header[1]); 722e335425bSTakashi Sakamoto return -EAGAIN; 723d67c46b9STakashi Sakamoto } 724d67c46b9STakashi Sakamoto 725d67c46b9STakashi Sakamoto /* Check valid protocol or not. */ 7269863874fSTakashi Sakamoto sph = (cip_header[0] & CIP_SPH_MASK) >> CIP_SPH_SHIFT; 727d67c46b9STakashi Sakamoto fmt = (cip_header[1] & CIP_FMT_MASK) >> CIP_FMT_SHIFT; 7289863874fSTakashi Sakamoto if (sph != s->sph || fmt != s->fmt) { 7292a7e1713STakashi Sakamoto dev_info_ratelimited(&s->unit->device, 730d67c46b9STakashi Sakamoto "Detect unexpected protocol: %08x %08x\n", 731d67c46b9STakashi Sakamoto cip_header[0], cip_header[1]); 732e335425bSTakashi Sakamoto return -EAGAIN; 733d67c46b9STakashi Sakamoto } 734d67c46b9STakashi Sakamoto 735d67c46b9STakashi Sakamoto /* Calculate data blocks */ 736d67c46b9STakashi Sakamoto fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT; 7374fd18787STakashi Sakamoto if (payload_length == 0 || (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { 738e335425bSTakashi Sakamoto *data_blocks = 0; 739d67c46b9STakashi Sakamoto } else { 740e335425bSTakashi Sakamoto unsigned int data_block_quadlets = 741d67c46b9STakashi Sakamoto (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; 742d67c46b9STakashi Sakamoto /* avoid division by zero */ 743d67c46b9STakashi Sakamoto if (data_block_quadlets == 0) { 744d67c46b9STakashi Sakamoto dev_err(&s->unit->device, 745d67c46b9STakashi Sakamoto "Detect invalid value in dbs field: %08X\n", 746d67c46b9STakashi Sakamoto cip_header[0]); 747d67c46b9STakashi Sakamoto return -EPROTO; 748d67c46b9STakashi Sakamoto } 749d67c46b9STakashi Sakamoto if (s->flags & CIP_WRONG_DBS) 750d67c46b9STakashi Sakamoto data_block_quadlets = s->data_block_quadlets; 751d67c46b9STakashi Sakamoto 7524fd18787STakashi Sakamoto *data_blocks = payload_length / sizeof(__be32) / data_block_quadlets; 753d67c46b9STakashi Sakamoto } 754d67c46b9STakashi Sakamoto 755d67c46b9STakashi Sakamoto /* Check data block counter continuity */ 756a35463d1STakashi Sakamoto dbc = cip_header[0] & CIP_DBC_MASK; 757e335425bSTakashi Sakamoto if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && 758a35463d1STakashi Sakamoto *data_block_counter != UINT_MAX) 759a35463d1STakashi Sakamoto dbc = *data_block_counter; 760d67c46b9STakashi Sakamoto 761a35463d1STakashi Sakamoto if ((dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) || 762a35463d1STakashi Sakamoto *data_block_counter == UINT_MAX) { 763d67c46b9STakashi Sakamoto lost = false; 764d67c46b9STakashi Sakamoto } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { 765a35463d1STakashi Sakamoto lost = dbc != *data_block_counter; 766d67c46b9STakashi Sakamoto } else { 767e335425bSTakashi Sakamoto unsigned int dbc_interval; 768e335425bSTakashi Sakamoto 769e335425bSTakashi Sakamoto if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0) 770d3d10a4aSTakashi Sakamoto dbc_interval = s->ctx_data.tx.dbc_interval; 771d67c46b9STakashi Sakamoto else 772e335425bSTakashi Sakamoto dbc_interval = *data_blocks; 773d67c46b9STakashi Sakamoto 774a35463d1STakashi Sakamoto lost = dbc != ((*data_block_counter + dbc_interval) & 0xff); 775d67c46b9STakashi Sakamoto } 776d67c46b9STakashi Sakamoto 777d67c46b9STakashi Sakamoto if (lost) { 778d67c46b9STakashi Sakamoto dev_err(&s->unit->device, 779d67c46b9STakashi Sakamoto "Detect discontinuity of CIP: %02X %02X\n", 780a35463d1STakashi Sakamoto *data_block_counter, dbc); 781d67c46b9STakashi Sakamoto return -EIO; 782d67c46b9STakashi Sakamoto } 783d67c46b9STakashi Sakamoto 784753e7179STakashi Sakamoto *data_block_counter = dbc; 785753e7179STakashi Sakamoto 7868070d265STakashi Sakamoto if (!(s->flags & CIP_UNAWARE_SYT)) 787e335425bSTakashi Sakamoto *syt = cip_header[1] & CIP_SYT_MASK; 788e335425bSTakashi Sakamoto 789e335425bSTakashi Sakamoto return 0; 790e335425bSTakashi Sakamoto } 791e335425bSTakashi Sakamoto 79298e3e43bSTakashi Sakamoto static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, 79398e3e43bSTakashi Sakamoto const __be32 *ctx_header, 794a35463d1STakashi Sakamoto unsigned int *data_blocks, 795a35463d1STakashi Sakamoto unsigned int *data_block_counter, 796814b4312STakashi Sakamoto unsigned int *syt, unsigned int packet_index, unsigned int index) 797e335425bSTakashi Sakamoto { 798ebd2a647STakashi Sakamoto unsigned int payload_length; 799f11453c7STakashi Sakamoto const __be32 *cip_header; 800395f41e2STakashi Sakamoto unsigned int cip_header_size; 801e335425bSTakashi Sakamoto 802ebd2a647STakashi Sakamoto payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; 803395f41e2STakashi Sakamoto 804395f41e2STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 80567d92ee7STakashi Sakamoto cip_header_size = CIP_HEADER_SIZE; 806395f41e2STakashi Sakamoto else 807395f41e2STakashi Sakamoto cip_header_size = 0; 808395f41e2STakashi Sakamoto 809ebd2a647STakashi Sakamoto if (payload_length > cip_header_size + s->ctx_data.tx.max_ctx_payload_length) { 810e335425bSTakashi Sakamoto dev_err(&s->unit->device, 811e335425bSTakashi Sakamoto "Detect jumbo payload: %04x %04x\n", 812ebd2a647STakashi Sakamoto payload_length, cip_header_size + s->ctx_data.tx.max_ctx_payload_length); 813e335425bSTakashi Sakamoto return -EIO; 814e335425bSTakashi Sakamoto } 815e335425bSTakashi Sakamoto 816395f41e2STakashi Sakamoto if (cip_header_size > 0) { 817ebd2a647STakashi Sakamoto if (payload_length >= cip_header_size) { 818344f0f82STakashi Sakamoto int err; 819344f0f82STakashi Sakamoto 82067d92ee7STakashi Sakamoto cip_header = ctx_header + IR_CTX_HEADER_DEFAULT_QUADLETS; 8214fd18787STakashi Sakamoto err = check_cip_header(s, cip_header, payload_length - cip_header_size, 8224fd18787STakashi Sakamoto data_blocks, data_block_counter, syt); 823b8b0e24cSTakashi Sakamoto if (err < 0) 824e335425bSTakashi Sakamoto return err; 825947b437eSTakashi Sakamoto } else { 826c09010eeSTakashi Sakamoto // Handle the cycle so that empty packet arrives. 827c09010eeSTakashi Sakamoto cip_header = NULL; 828c09010eeSTakashi Sakamoto *data_blocks = 0; 829c09010eeSTakashi Sakamoto *syt = 0; 830c09010eeSTakashi Sakamoto } 831c09010eeSTakashi Sakamoto } else { 832947b437eSTakashi Sakamoto cip_header = NULL; 833ebd2a647STakashi Sakamoto *data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets; 83498e3e43bSTakashi Sakamoto *syt = 0; 8357fbf9096STakashi Sakamoto 836a35463d1STakashi Sakamoto if (*data_block_counter == UINT_MAX) 837a35463d1STakashi Sakamoto *data_block_counter = 0; 838947b437eSTakashi Sakamoto } 839e335425bSTakashi Sakamoto 840ebd2a647STakashi Sakamoto trace_amdtp_packet(s, cycle, cip_header, payload_length, *data_blocks, 841814b4312STakashi Sakamoto *data_block_counter, packet_index, index); 84264d0bf4dSTakashi Sakamoto 843344f0f82STakashi Sakamoto return 0; 844d67c46b9STakashi Sakamoto } 845d67c46b9STakashi Sakamoto 84626cd1e58STakashi Sakamoto // In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On 84726cd1e58STakashi Sakamoto // the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent 84826cd1e58STakashi Sakamoto // it. Thus, via Linux firewire subsystem, we can get the 3 bits for second. 8493e106f4fSTakashi Sakamoto static inline u32 compute_ohci_cycle_count(__be32 ctx_header_tstamp) 85073fc7f08STakashi Sakamoto { 85126cd1e58STakashi Sakamoto u32 tstamp = be32_to_cpu(ctx_header_tstamp) & HEADER_TSTAMP_MASK; 85273fc7f08STakashi Sakamoto return (((tstamp >> 13) & 0x07) * 8000) + (tstamp & 0x1fff); 85373fc7f08STakashi Sakamoto } 85473fc7f08STakashi Sakamoto 8553e106f4fSTakashi Sakamoto static inline u32 increment_ohci_cycle_count(u32 cycle, unsigned int addend) 85673fc7f08STakashi Sakamoto { 85773fc7f08STakashi Sakamoto cycle += addend; 8583e106f4fSTakashi Sakamoto if (cycle >= OHCI_SECOND_MODULUS * CYCLES_PER_SECOND) 8593e106f4fSTakashi Sakamoto cycle -= OHCI_SECOND_MODULUS * CYCLES_PER_SECOND; 86073fc7f08STakashi Sakamoto return cycle; 86173fc7f08STakashi Sakamoto } 86273fc7f08STakashi Sakamoto 863705794c5STakashi Sakamoto static int compare_ohci_cycle_count(u32 lval, u32 rval) 864705794c5STakashi Sakamoto { 865705794c5STakashi Sakamoto if (lval == rval) 866705794c5STakashi Sakamoto return 0; 867705794c5STakashi Sakamoto else if (lval < rval && rval - lval < OHCI_SECOND_MODULUS * CYCLES_PER_SECOND / 2) 868705794c5STakashi Sakamoto return -1; 869705794c5STakashi Sakamoto else 870705794c5STakashi Sakamoto return 1; 871705794c5STakashi Sakamoto } 872705794c5STakashi Sakamoto 87326cd1e58STakashi Sakamoto // Align to actual cycle count for the packet which is going to be scheduled. 874a0e02331STakashi Sakamoto // This module queued the same number of isochronous cycle as the size of queue 875a0e02331STakashi Sakamoto // to kip isochronous cycle, therefore it's OK to just increment the cycle by 876a0e02331STakashi Sakamoto // the size of queue for scheduled cycle. 8773e106f4fSTakashi Sakamoto static inline u32 compute_ohci_it_cycle(const __be32 ctx_header_tstamp, 878a0e02331STakashi Sakamoto unsigned int queue_size) 87926cd1e58STakashi Sakamoto { 8803e106f4fSTakashi Sakamoto u32 cycle = compute_ohci_cycle_count(ctx_header_tstamp); 8813e106f4fSTakashi Sakamoto return increment_ohci_cycle_count(cycle, queue_size); 88226cd1e58STakashi Sakamoto } 88326cd1e58STakashi Sakamoto 884753e7179STakashi Sakamoto static int generate_device_pkt_descs(struct amdtp_stream *s, 885753e7179STakashi Sakamoto struct pkt_desc *descs, 886753e7179STakashi Sakamoto const __be32 *ctx_header, 88773246fc4STakashi Sakamoto unsigned int packets, 88873246fc4STakashi Sakamoto unsigned int *desc_count) 889753e7179STakashi Sakamoto { 890705794c5STakashi Sakamoto unsigned int next_cycle = s->next_cycle; 891753e7179STakashi Sakamoto unsigned int dbc = s->data_block_counter; 892814b4312STakashi Sakamoto unsigned int packet_index = s->packet_index; 893814b4312STakashi Sakamoto unsigned int queue_size = s->queue_size; 894753e7179STakashi Sakamoto int i; 895753e7179STakashi Sakamoto int err; 896753e7179STakashi Sakamoto 89773246fc4STakashi Sakamoto *desc_count = 0; 898753e7179STakashi Sakamoto for (i = 0; i < packets; ++i) { 89973246fc4STakashi Sakamoto struct pkt_desc *desc = descs + *desc_count; 900753e7179STakashi Sakamoto unsigned int cycle; 901705794c5STakashi Sakamoto bool lost; 902753e7179STakashi Sakamoto unsigned int data_blocks; 903753e7179STakashi Sakamoto unsigned int syt; 904753e7179STakashi Sakamoto 9053e106f4fSTakashi Sakamoto cycle = compute_ohci_cycle_count(ctx_header[1]); 906705794c5STakashi Sakamoto lost = (next_cycle != cycle); 907705794c5STakashi Sakamoto if (lost) { 908705794c5STakashi Sakamoto if (s->flags & CIP_NO_HEADER) { 909705794c5STakashi Sakamoto // Fireface skips transmission just for an isoc cycle corresponding 910705794c5STakashi Sakamoto // to empty packet. 91173246fc4STakashi Sakamoto unsigned int prev_cycle = next_cycle; 91273246fc4STakashi Sakamoto 913705794c5STakashi Sakamoto next_cycle = increment_ohci_cycle_count(next_cycle, 1); 914705794c5STakashi Sakamoto lost = (next_cycle != cycle); 91573246fc4STakashi Sakamoto if (!lost) { 91673246fc4STakashi Sakamoto // Prepare a description for the skipped cycle for 91773246fc4STakashi Sakamoto // sequence replay. 91873246fc4STakashi Sakamoto desc->cycle = prev_cycle; 91973246fc4STakashi Sakamoto desc->syt = 0; 92073246fc4STakashi Sakamoto desc->data_blocks = 0; 92173246fc4STakashi Sakamoto desc->data_block_counter = dbc; 92273246fc4STakashi Sakamoto desc->ctx_payload = NULL; 92373246fc4STakashi Sakamoto ++desc; 92473246fc4STakashi Sakamoto ++(*desc_count); 92573246fc4STakashi Sakamoto } 926705794c5STakashi Sakamoto } else if (s->flags & CIP_JUMBO_PAYLOAD) { 927705794c5STakashi Sakamoto // OXFW970 skips transmission for several isoc cycles during 92873246fc4STakashi Sakamoto // asynchronous transaction. The sequence replay is impossible due 92973246fc4STakashi Sakamoto // to the reason. 930705794c5STakashi Sakamoto unsigned int safe_cycle = increment_ohci_cycle_count(next_cycle, 931705794c5STakashi Sakamoto IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES); 932705794c5STakashi Sakamoto lost = (compare_ohci_cycle_count(safe_cycle, cycle) > 0); 933705794c5STakashi Sakamoto } 934705794c5STakashi Sakamoto if (lost) { 935705794c5STakashi Sakamoto dev_err(&s->unit->device, "Detect discontinuity of cycle: %d %d\n", 936705794c5STakashi Sakamoto next_cycle, cycle); 937705794c5STakashi Sakamoto return -EIO; 938705794c5STakashi Sakamoto } 939705794c5STakashi Sakamoto } 940753e7179STakashi Sakamoto 941ebd2a647STakashi Sakamoto err = parse_ir_ctx_header(s, cycle, ctx_header, &data_blocks, &dbc, &syt, 942ebd2a647STakashi Sakamoto packet_index, i); 943753e7179STakashi Sakamoto if (err < 0) 944753e7179STakashi Sakamoto return err; 945753e7179STakashi Sakamoto 946753e7179STakashi Sakamoto desc->cycle = cycle; 947753e7179STakashi Sakamoto desc->syt = syt; 948753e7179STakashi Sakamoto desc->data_blocks = data_blocks; 949753e7179STakashi Sakamoto desc->data_block_counter = dbc; 950814b4312STakashi Sakamoto desc->ctx_payload = s->buffer.packets[packet_index].buffer; 951753e7179STakashi Sakamoto 952753e7179STakashi Sakamoto if (!(s->flags & CIP_DBC_IS_END_EVENT)) 953753e7179STakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 954753e7179STakashi Sakamoto 955705794c5STakashi Sakamoto next_cycle = increment_ohci_cycle_count(next_cycle, 1); 95673246fc4STakashi Sakamoto ++(*desc_count); 957705794c5STakashi Sakamoto ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); 958814b4312STakashi Sakamoto packet_index = (packet_index + 1) % queue_size; 959753e7179STakashi Sakamoto } 960753e7179STakashi Sakamoto 961705794c5STakashi Sakamoto s->next_cycle = next_cycle; 962753e7179STakashi Sakamoto s->data_block_counter = dbc; 963753e7179STakashi Sakamoto 964753e7179STakashi Sakamoto return 0; 965753e7179STakashi Sakamoto } 966753e7179STakashi Sakamoto 96783cfb5c5STakashi Sakamoto static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle, 96883cfb5c5STakashi Sakamoto unsigned int transfer_delay) 96983cfb5c5STakashi Sakamoto { 97083cfb5c5STakashi Sakamoto unsigned int syt; 97183cfb5c5STakashi Sakamoto 97283cfb5c5STakashi Sakamoto syt_offset += transfer_delay; 97383cfb5c5STakashi Sakamoto syt = ((cycle + syt_offset / TICKS_PER_CYCLE) << 12) | 97483cfb5c5STakashi Sakamoto (syt_offset % TICKS_PER_CYCLE); 97583cfb5c5STakashi Sakamoto return syt & CIP_SYT_MASK; 97683cfb5c5STakashi Sakamoto } 97783cfb5c5STakashi Sakamoto 978*f2bdee85STakashi Sakamoto static void generate_rx_packet_descs(struct amdtp_stream *s, struct pkt_desc *descs, 979*f2bdee85STakashi Sakamoto const __be32 *ctx_header, unsigned int packet_count) 980f4f6ae7bSTakashi Sakamoto { 981*f2bdee85STakashi Sakamoto struct seq_desc *seq_descs = s->ctx_data.rx.seq.descs; 982*f2bdee85STakashi Sakamoto unsigned int seq_size = s->ctx_data.rx.seq.size; 983*f2bdee85STakashi Sakamoto unsigned int seq_pos = s->ctx_data.rx.seq.pos; 984f4f6ae7bSTakashi Sakamoto unsigned int dbc = s->data_block_counter; 9858070d265STakashi Sakamoto bool aware_syt = !(s->flags & CIP_UNAWARE_SYT); 986f4f6ae7bSTakashi Sakamoto int i; 987f4f6ae7bSTakashi Sakamoto 988*f2bdee85STakashi Sakamoto pool_seq_descs(s, seq_descs, seq_size, seq_pos, packet_count); 989*f2bdee85STakashi Sakamoto 990*f2bdee85STakashi Sakamoto for (i = 0; i < packet_count; ++i) { 991f4f6ae7bSTakashi Sakamoto struct pkt_desc *desc = descs + i; 992a0e02331STakashi Sakamoto unsigned int index = (s->packet_index + i) % s->queue_size; 993*f2bdee85STakashi Sakamoto const struct seq_desc *seq = seq_descs + seq_pos; 994f4f6ae7bSTakashi Sakamoto 9953e106f4fSTakashi Sakamoto desc->cycle = compute_ohci_it_cycle(*ctx_header, s->queue_size); 99669efd5c4STakashi Sakamoto 99713d11f14STakashi Sakamoto if (aware_syt && seq->syt_offset != CIP_SYT_NO_INFO) 99813d11f14STakashi Sakamoto desc->syt = compute_syt(seq->syt_offset, desc->cycle, s->transfer_delay); 99913d11f14STakashi Sakamoto else 10008070d265STakashi Sakamoto desc->syt = CIP_SYT_NO_INFO; 10018070d265STakashi Sakamoto 100269efd5c4STakashi Sakamoto desc->data_blocks = seq->data_blocks; 1003f4f6ae7bSTakashi Sakamoto 1004f4f6ae7bSTakashi Sakamoto if (s->flags & CIP_DBC_IS_END_EVENT) 1005f4f6ae7bSTakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 1006f4f6ae7bSTakashi Sakamoto 1007f4f6ae7bSTakashi Sakamoto desc->data_block_counter = dbc; 1008f4f6ae7bSTakashi Sakamoto 1009f4f6ae7bSTakashi Sakamoto if (!(s->flags & CIP_DBC_IS_END_EVENT)) 1010f4f6ae7bSTakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 1011f4f6ae7bSTakashi Sakamoto 1012f4f6ae7bSTakashi Sakamoto desc->ctx_payload = s->buffer.packets[index].buffer; 1013f4f6ae7bSTakashi Sakamoto 1014*f2bdee85STakashi Sakamoto seq_pos = (seq_pos + 1) % seq_size; 101569efd5c4STakashi Sakamoto 1016f4f6ae7bSTakashi Sakamoto ++ctx_header; 1017f4f6ae7bSTakashi Sakamoto } 1018f4f6ae7bSTakashi Sakamoto 1019f4f6ae7bSTakashi Sakamoto s->data_block_counter = dbc; 1020*f2bdee85STakashi Sakamoto s->ctx_data.rx.seq.pos = seq_pos; 1021f4f6ae7bSTakashi Sakamoto } 1022f4f6ae7bSTakashi Sakamoto 1023fce9b013STakashi Sakamoto static inline void cancel_stream(struct amdtp_stream *s) 1024fce9b013STakashi Sakamoto { 1025fce9b013STakashi Sakamoto s->packet_index = -1; 10263b86ec63STakashi Sakamoto if (in_softirq()) 1027fce9b013STakashi Sakamoto amdtp_stream_pcm_abort(s); 1028fce9b013STakashi Sakamoto WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); 1029fce9b013STakashi Sakamoto } 1030fce9b013STakashi Sakamoto 10310f5cfcb2STakashi Sakamoto static void process_ctx_payloads(struct amdtp_stream *s, 10320f5cfcb2STakashi Sakamoto const struct pkt_desc *descs, 10330f5cfcb2STakashi Sakamoto unsigned int packets) 10340f5cfcb2STakashi Sakamoto { 10359a738ad1STakashi Sakamoto struct snd_pcm_substream *pcm; 10360f5cfcb2STakashi Sakamoto unsigned int pcm_frames; 10370f5cfcb2STakashi Sakamoto 10389a738ad1STakashi Sakamoto pcm = READ_ONCE(s->pcm); 10399a738ad1STakashi Sakamoto pcm_frames = s->process_ctx_payloads(s, descs, packets, pcm); 10409a738ad1STakashi Sakamoto if (pcm) 10410f5cfcb2STakashi Sakamoto update_pcm_pointers(s, pcm, pcm_frames); 10420f5cfcb2STakashi Sakamoto } 10430f5cfcb2STakashi Sakamoto 10449b1fcd9bSTakashi Sakamoto static void process_rx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 10459b1fcd9bSTakashi Sakamoto void *header, void *private_data) 1046d67c46b9STakashi Sakamoto { 1047d67c46b9STakashi Sakamoto struct amdtp_stream *s = private_data; 104869efd5c4STakashi Sakamoto const struct amdtp_domain *d = s->domain; 104926cd1e58STakashi Sakamoto const __be32 *ctx_header = header; 10509b1fcd9bSTakashi Sakamoto const unsigned int events_per_period = d->events_per_period; 105160dd4929STakashi Sakamoto unsigned int event_count = s->ctx_data.rx.event_count; 1052233dbbc7STakashi Sakamoto unsigned int pkt_header_length; 1053a0e02331STakashi Sakamoto unsigned int packets; 1054d360870aSTakashi Sakamoto bool need_hw_irq; 10550dcb4efbSTakashi Sakamoto int i; 1056d67c46b9STakashi Sakamoto 1057d67c46b9STakashi Sakamoto if (s->packet_index < 0) 1058d67c46b9STakashi Sakamoto return; 1059d67c46b9STakashi Sakamoto 1060a0e02331STakashi Sakamoto // Calculate the number of packets in buffer and check XRUN. 1061a0e02331STakashi Sakamoto packets = header_length / sizeof(*ctx_header); 1062a0e02331STakashi Sakamoto 1063*f2bdee85STakashi Sakamoto generate_rx_packet_descs(s, s->pkt_descs, ctx_header, packets); 1064f4f6ae7bSTakashi Sakamoto 10650f5cfcb2STakashi Sakamoto process_ctx_payloads(s, s->pkt_descs, packets); 10665e2ece0fSTakashi Sakamoto 1067233dbbc7STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 1068233dbbc7STakashi Sakamoto pkt_header_length = IT_PKT_HEADER_SIZE_CIP; 1069233dbbc7STakashi Sakamoto else 1070233dbbc7STakashi Sakamoto pkt_header_length = 0; 1071233dbbc7STakashi Sakamoto 1072d360870aSTakashi Sakamoto if (s == d->irq_target) { 1073d360870aSTakashi Sakamoto // At NO_PERIOD_WAKEUP mode, the packets for all IT/IR contexts are processed by 1074d360870aSTakashi Sakamoto // the tasks of user process operating ALSA PCM character device by calling ioctl(2) 1075d360870aSTakashi Sakamoto // with some requests, instead of scheduled hardware IRQ of an IT context. 1076d360870aSTakashi Sakamoto struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); 1077d360870aSTakashi Sakamoto need_hw_irq = !pcm || !pcm->runtime->no_period_wakeup; 1078d360870aSTakashi Sakamoto } else { 1079d360870aSTakashi Sakamoto need_hw_irq = false; 1080d360870aSTakashi Sakamoto } 1081d360870aSTakashi Sakamoto 10825e2ece0fSTakashi Sakamoto for (i = 0; i < packets; ++i) { 10835e2ece0fSTakashi Sakamoto const struct pkt_desc *desc = s->pkt_descs + i; 10846bc1a269STakashi Sakamoto struct { 10856bc1a269STakashi Sakamoto struct fw_iso_packet params; 108667d92ee7STakashi Sakamoto __be32 header[CIP_HEADER_QUADLETS]; 10876bc1a269STakashi Sakamoto } template = { {0}, {0} }; 1088e229853dSTakashi Sakamoto bool sched_irq = false; 1089860d798cSTakashi Sakamoto 1090233dbbc7STakashi Sakamoto build_it_pkt_header(s, desc->cycle, &template.params, pkt_header_length, 1091f4f6ae7bSTakashi Sakamoto desc->data_blocks, desc->data_block_counter, 10928070d265STakashi Sakamoto desc->syt, i); 10936bc1a269STakashi Sakamoto 10942472cfb3STakashi Sakamoto if (s == s->domain->irq_target) { 1095e229853dSTakashi Sakamoto event_count += desc->data_blocks; 1096e229853dSTakashi Sakamoto if (event_count >= events_per_period) { 1097e229853dSTakashi Sakamoto event_count -= events_per_period; 1098d360870aSTakashi Sakamoto sched_irq = need_hw_irq; 1099e229853dSTakashi Sakamoto } 110060dd4929STakashi Sakamoto } 1101e229853dSTakashi Sakamoto 1102e229853dSTakashi Sakamoto if (queue_out_packet(s, &template.params, sched_irq) < 0) { 1103fce9b013STakashi Sakamoto cancel_stream(s); 1104d67c46b9STakashi Sakamoto return; 1105d67c46b9STakashi Sakamoto } 1106d67c46b9STakashi Sakamoto } 1107d67c46b9STakashi Sakamoto 110860dd4929STakashi Sakamoto s->ctx_data.rx.event_count = event_count; 1109d67c46b9STakashi Sakamoto } 1110d67c46b9STakashi Sakamoto 11119b1fcd9bSTakashi Sakamoto static void skip_rx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 11129b1fcd9bSTakashi Sakamoto void *header, void *private_data) 11139b1fcd9bSTakashi Sakamoto { 11149b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 11159b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 11169b1fcd9bSTakashi Sakamoto const __be32 *ctx_header = header; 11179b1fcd9bSTakashi Sakamoto unsigned int packets; 11189b1fcd9bSTakashi Sakamoto unsigned int cycle; 11199b1fcd9bSTakashi Sakamoto int i; 11209b1fcd9bSTakashi Sakamoto 11219b1fcd9bSTakashi Sakamoto if (s->packet_index < 0) 11229b1fcd9bSTakashi Sakamoto return; 11239b1fcd9bSTakashi Sakamoto 11249b1fcd9bSTakashi Sakamoto packets = header_length / sizeof(*ctx_header); 11259b1fcd9bSTakashi Sakamoto 11269b1fcd9bSTakashi Sakamoto cycle = compute_ohci_it_cycle(ctx_header[packets - 1], s->queue_size); 11279b1fcd9bSTakashi Sakamoto s->next_cycle = increment_ohci_cycle_count(cycle, 1); 11289b1fcd9bSTakashi Sakamoto 11299b1fcd9bSTakashi Sakamoto for (i = 0; i < packets; ++i) { 11309b1fcd9bSTakashi Sakamoto struct fw_iso_packet params = { 11319b1fcd9bSTakashi Sakamoto .header_length = 0, 11329b1fcd9bSTakashi Sakamoto .payload_length = 0, 11339b1fcd9bSTakashi Sakamoto }; 11349b1fcd9bSTakashi Sakamoto bool sched_irq = (s == d->irq_target && i == packets - 1); 11359b1fcd9bSTakashi Sakamoto 11369b1fcd9bSTakashi Sakamoto if (queue_out_packet(s, ¶ms, sched_irq) < 0) { 11379b1fcd9bSTakashi Sakamoto cancel_stream(s); 11389b1fcd9bSTakashi Sakamoto return; 11399b1fcd9bSTakashi Sakamoto } 11409b1fcd9bSTakashi Sakamoto } 11419b1fcd9bSTakashi Sakamoto } 11429b1fcd9bSTakashi Sakamoto 11439b1fcd9bSTakashi Sakamoto static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, 11449b1fcd9bSTakashi Sakamoto void *header, void *private_data); 11459b1fcd9bSTakashi Sakamoto 11469b1fcd9bSTakashi Sakamoto static void process_rx_packets_intermediately(struct fw_iso_context *context, u32 tstamp, 11479b1fcd9bSTakashi Sakamoto size_t header_length, void *header, void *private_data) 11489b1fcd9bSTakashi Sakamoto { 11499b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 11509b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 11519b1fcd9bSTakashi Sakamoto __be32 *ctx_header = header; 11529b1fcd9bSTakashi Sakamoto const unsigned int queue_size = s->queue_size; 11539b1fcd9bSTakashi Sakamoto unsigned int packets; 11549b1fcd9bSTakashi Sakamoto unsigned int offset; 11559b1fcd9bSTakashi Sakamoto 11569b1fcd9bSTakashi Sakamoto if (s->packet_index < 0) 11579b1fcd9bSTakashi Sakamoto return; 11589b1fcd9bSTakashi Sakamoto 11599b1fcd9bSTakashi Sakamoto packets = header_length / sizeof(*ctx_header); 11609b1fcd9bSTakashi Sakamoto 11619b1fcd9bSTakashi Sakamoto offset = 0; 11629b1fcd9bSTakashi Sakamoto while (offset < packets) { 11639b1fcd9bSTakashi Sakamoto unsigned int cycle = compute_ohci_it_cycle(ctx_header[offset], queue_size); 11649b1fcd9bSTakashi Sakamoto 11659b1fcd9bSTakashi Sakamoto if (compare_ohci_cycle_count(cycle, d->processing_cycle.rx_start) >= 0) 11669b1fcd9bSTakashi Sakamoto break; 11679b1fcd9bSTakashi Sakamoto 11689b1fcd9bSTakashi Sakamoto ++offset; 11699b1fcd9bSTakashi Sakamoto } 11709b1fcd9bSTakashi Sakamoto 11719b1fcd9bSTakashi Sakamoto if (offset > 0) { 11729b1fcd9bSTakashi Sakamoto unsigned int length = sizeof(*ctx_header) * offset; 11739b1fcd9bSTakashi Sakamoto 11749b1fcd9bSTakashi Sakamoto skip_rx_packets(context, tstamp, length, ctx_header, private_data); 11759b1fcd9bSTakashi Sakamoto if (amdtp_streaming_error(s)) 11769b1fcd9bSTakashi Sakamoto return; 11779b1fcd9bSTakashi Sakamoto 11789b1fcd9bSTakashi Sakamoto ctx_header += offset; 11799b1fcd9bSTakashi Sakamoto header_length -= length; 11809b1fcd9bSTakashi Sakamoto } 11819b1fcd9bSTakashi Sakamoto 11829b1fcd9bSTakashi Sakamoto if (offset < packets) { 1183bdaedca7STakashi Sakamoto s->ready_processing = true; 1184bdaedca7STakashi Sakamoto wake_up(&s->ready_wait); 1185bdaedca7STakashi Sakamoto 11869b1fcd9bSTakashi Sakamoto process_rx_packets(context, tstamp, header_length, ctx_header, private_data); 11879b1fcd9bSTakashi Sakamoto if (amdtp_streaming_error(s)) 11889b1fcd9bSTakashi Sakamoto return; 11899b1fcd9bSTakashi Sakamoto 11909b1fcd9bSTakashi Sakamoto if (s == d->irq_target) 11919b1fcd9bSTakashi Sakamoto s->context->callback.sc = irq_target_callback; 11929b1fcd9bSTakashi Sakamoto else 11939b1fcd9bSTakashi Sakamoto s->context->callback.sc = process_rx_packets; 11949b1fcd9bSTakashi Sakamoto } 11959b1fcd9bSTakashi Sakamoto } 11969b1fcd9bSTakashi Sakamoto 1197da3623abSTakashi Sakamoto static void process_tx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 1198da3623abSTakashi Sakamoto void *header, void *private_data) 1199d67c46b9STakashi Sakamoto { 1200d67c46b9STakashi Sakamoto struct amdtp_stream *s = private_data; 1201cc4f8e91STakashi Sakamoto __be32 *ctx_header = header; 1202e229853dSTakashi Sakamoto unsigned int packets; 120373246fc4STakashi Sakamoto unsigned int desc_count; 1204753e7179STakashi Sakamoto int i; 1205753e7179STakashi Sakamoto int err; 1206d67c46b9STakashi Sakamoto 1207d67c46b9STakashi Sakamoto if (s->packet_index < 0) 1208d67c46b9STakashi Sakamoto return; 1209d67c46b9STakashi Sakamoto 1210a0e02331STakashi Sakamoto // Calculate the number of packets in buffer and check XRUN. 1211d3d10a4aSTakashi Sakamoto packets = header_length / s->ctx_data.tx.ctx_header_size; 1212f90e2dedSTakashi Sakamoto 121373246fc4STakashi Sakamoto desc_count = 0; 121473246fc4STakashi Sakamoto err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets, &desc_count); 1215753e7179STakashi Sakamoto if (err < 0) { 1216753e7179STakashi Sakamoto if (err != -EAGAIN) { 1217753e7179STakashi Sakamoto cancel_stream(s); 1218753e7179STakashi Sakamoto return; 1219753e7179STakashi Sakamoto } 12205e2ece0fSTakashi Sakamoto } else { 1221f9e5ecdfSTakashi Sakamoto struct amdtp_domain *d = s->domain; 1222f9e5ecdfSTakashi Sakamoto 122373246fc4STakashi Sakamoto process_ctx_payloads(s, s->pkt_descs, desc_count); 1224f9e5ecdfSTakashi Sakamoto 1225f9e5ecdfSTakashi Sakamoto if (d->replay.enable) 1226f9e5ecdfSTakashi Sakamoto cache_seq(s, s->pkt_descs, desc_count); 12275e2ece0fSTakashi Sakamoto } 12285e2ece0fSTakashi Sakamoto 12295e2ece0fSTakashi Sakamoto for (i = 0; i < packets; ++i) { 12305e2ece0fSTakashi Sakamoto struct fw_iso_packet params = {0}; 1231a35463d1STakashi Sakamoto 123260dd4929STakashi Sakamoto if (queue_in_packet(s, ¶ms) < 0) { 1233753e7179STakashi Sakamoto cancel_stream(s); 1234753e7179STakashi Sakamoto return; 1235753e7179STakashi Sakamoto } 1236d67c46b9STakashi Sakamoto } 1237d67c46b9STakashi Sakamoto } 1238d67c46b9STakashi Sakamoto 1239da3623abSTakashi Sakamoto static void drop_tx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 1240da3623abSTakashi Sakamoto void *header, void *private_data) 1241da3623abSTakashi Sakamoto { 1242da3623abSTakashi Sakamoto struct amdtp_stream *s = private_data; 1243da3623abSTakashi Sakamoto const __be32 *ctx_header = header; 1244da3623abSTakashi Sakamoto unsigned int packets; 1245da3623abSTakashi Sakamoto unsigned int cycle; 1246da3623abSTakashi Sakamoto int i; 1247da3623abSTakashi Sakamoto 1248da3623abSTakashi Sakamoto if (s->packet_index < 0) 1249da3623abSTakashi Sakamoto return; 1250da3623abSTakashi Sakamoto 1251da3623abSTakashi Sakamoto packets = header_length / s->ctx_data.tx.ctx_header_size; 1252da3623abSTakashi Sakamoto 1253da3623abSTakashi Sakamoto ctx_header += (packets - 1) * s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); 1254da3623abSTakashi Sakamoto cycle = compute_ohci_cycle_count(ctx_header[1]); 1255da3623abSTakashi Sakamoto s->next_cycle = increment_ohci_cycle_count(cycle, 1); 1256da3623abSTakashi Sakamoto 1257da3623abSTakashi Sakamoto for (i = 0; i < packets; ++i) { 1258da3623abSTakashi Sakamoto struct fw_iso_packet params = {0}; 1259da3623abSTakashi Sakamoto 1260da3623abSTakashi Sakamoto if (queue_in_packet(s, ¶ms) < 0) { 1261da3623abSTakashi Sakamoto cancel_stream(s); 1262da3623abSTakashi Sakamoto return; 1263da3623abSTakashi Sakamoto } 1264da3623abSTakashi Sakamoto } 1265da3623abSTakashi Sakamoto } 1266da3623abSTakashi Sakamoto 1267da3623abSTakashi Sakamoto static void process_tx_packets_intermediately(struct fw_iso_context *context, u32 tstamp, 1268da3623abSTakashi Sakamoto size_t header_length, void *header, void *private_data) 1269da3623abSTakashi Sakamoto { 1270da3623abSTakashi Sakamoto struct amdtp_stream *s = private_data; 1271da3623abSTakashi Sakamoto struct amdtp_domain *d = s->domain; 1272da3623abSTakashi Sakamoto __be32 *ctx_header; 1273da3623abSTakashi Sakamoto unsigned int packets; 1274da3623abSTakashi Sakamoto unsigned int offset; 1275da3623abSTakashi Sakamoto 1276da3623abSTakashi Sakamoto if (s->packet_index < 0) 1277da3623abSTakashi Sakamoto return; 1278da3623abSTakashi Sakamoto 1279da3623abSTakashi Sakamoto packets = header_length / s->ctx_data.tx.ctx_header_size; 1280da3623abSTakashi Sakamoto 1281da3623abSTakashi Sakamoto offset = 0; 1282da3623abSTakashi Sakamoto ctx_header = header; 1283da3623abSTakashi Sakamoto while (offset < packets) { 1284da3623abSTakashi Sakamoto unsigned int cycle = compute_ohci_cycle_count(ctx_header[1]); 1285da3623abSTakashi Sakamoto 1286da3623abSTakashi Sakamoto if (compare_ohci_cycle_count(cycle, d->processing_cycle.tx_start) >= 0) 1287da3623abSTakashi Sakamoto break; 1288da3623abSTakashi Sakamoto 1289da3623abSTakashi Sakamoto ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(__be32); 1290da3623abSTakashi Sakamoto ++offset; 1291da3623abSTakashi Sakamoto } 1292da3623abSTakashi Sakamoto 1293da3623abSTakashi Sakamoto ctx_header = header; 1294da3623abSTakashi Sakamoto 1295da3623abSTakashi Sakamoto if (offset > 0) { 1296da3623abSTakashi Sakamoto size_t length = s->ctx_data.tx.ctx_header_size * offset; 1297da3623abSTakashi Sakamoto 1298da3623abSTakashi Sakamoto drop_tx_packets(context, tstamp, length, ctx_header, s); 1299da3623abSTakashi Sakamoto if (amdtp_streaming_error(s)) 1300da3623abSTakashi Sakamoto return; 1301da3623abSTakashi Sakamoto 1302da3623abSTakashi Sakamoto ctx_header += length / sizeof(*ctx_header); 1303da3623abSTakashi Sakamoto header_length -= length; 1304da3623abSTakashi Sakamoto } 1305da3623abSTakashi Sakamoto 1306da3623abSTakashi Sakamoto if (offset < packets) { 1307bdaedca7STakashi Sakamoto s->ready_processing = true; 1308bdaedca7STakashi Sakamoto wake_up(&s->ready_wait); 1309bdaedca7STakashi Sakamoto 1310da3623abSTakashi Sakamoto process_tx_packets(context, tstamp, header_length, ctx_header, s); 1311da3623abSTakashi Sakamoto if (amdtp_streaming_error(s)) 1312da3623abSTakashi Sakamoto return; 1313da3623abSTakashi Sakamoto 1314da3623abSTakashi Sakamoto context->callback.sc = process_tx_packets; 1315da3623abSTakashi Sakamoto } 1316da3623abSTakashi Sakamoto } 1317da3623abSTakashi Sakamoto 1318fb25dcc8STakashi Sakamoto static void drop_tx_packets_initially(struct fw_iso_context *context, u32 tstamp, 1319fb25dcc8STakashi Sakamoto size_t header_length, void *header, void *private_data) 1320fb25dcc8STakashi Sakamoto { 1321fb25dcc8STakashi Sakamoto struct amdtp_stream *s = private_data; 1322fb25dcc8STakashi Sakamoto struct amdtp_domain *d = s->domain; 1323fb25dcc8STakashi Sakamoto __be32 *ctx_header; 1324fb25dcc8STakashi Sakamoto unsigned int count; 1325fb25dcc8STakashi Sakamoto unsigned int events; 1326fb25dcc8STakashi Sakamoto int i; 1327fb25dcc8STakashi Sakamoto 1328fb25dcc8STakashi Sakamoto if (s->packet_index < 0) 1329fb25dcc8STakashi Sakamoto return; 1330fb25dcc8STakashi Sakamoto 1331fb25dcc8STakashi Sakamoto count = header_length / s->ctx_data.tx.ctx_header_size; 1332fb25dcc8STakashi Sakamoto 1333fb25dcc8STakashi Sakamoto // Attempt to detect any event in the batch of packets. 1334fb25dcc8STakashi Sakamoto events = 0; 1335fb25dcc8STakashi Sakamoto ctx_header = header; 1336fb25dcc8STakashi Sakamoto for (i = 0; i < count; ++i) { 1337fb25dcc8STakashi Sakamoto unsigned int payload_quads = 1338fb25dcc8STakashi Sakamoto (be32_to_cpu(*ctx_header) >> ISO_DATA_LENGTH_SHIFT) / sizeof(__be32); 1339fb25dcc8STakashi Sakamoto unsigned int data_blocks; 1340fb25dcc8STakashi Sakamoto 1341fb25dcc8STakashi Sakamoto if (s->flags & CIP_NO_HEADER) { 1342fb25dcc8STakashi Sakamoto data_blocks = payload_quads / s->data_block_quadlets; 1343fb25dcc8STakashi Sakamoto } else { 1344fb25dcc8STakashi Sakamoto __be32 *cip_headers = ctx_header + IR_CTX_HEADER_DEFAULT_QUADLETS; 1345fb25dcc8STakashi Sakamoto 1346fb25dcc8STakashi Sakamoto if (payload_quads < CIP_HEADER_QUADLETS) { 1347fb25dcc8STakashi Sakamoto data_blocks = 0; 1348fb25dcc8STakashi Sakamoto } else { 1349fb25dcc8STakashi Sakamoto payload_quads -= CIP_HEADER_QUADLETS; 1350fb25dcc8STakashi Sakamoto 1351fb25dcc8STakashi Sakamoto if (s->flags & CIP_UNAWARE_SYT) { 1352fb25dcc8STakashi Sakamoto data_blocks = payload_quads / s->data_block_quadlets; 1353fb25dcc8STakashi Sakamoto } else { 1354fb25dcc8STakashi Sakamoto u32 cip1 = be32_to_cpu(cip_headers[1]); 1355fb25dcc8STakashi Sakamoto 1356fb25dcc8STakashi Sakamoto // NODATA packet can includes any data blocks but they are 1357fb25dcc8STakashi Sakamoto // not available as event. 1358fb25dcc8STakashi Sakamoto if ((cip1 & CIP_NO_DATA) == CIP_NO_DATA) 1359fb25dcc8STakashi Sakamoto data_blocks = 0; 1360fb25dcc8STakashi Sakamoto else 1361fb25dcc8STakashi Sakamoto data_blocks = payload_quads / s->data_block_quadlets; 1362fb25dcc8STakashi Sakamoto } 1363fb25dcc8STakashi Sakamoto } 1364fb25dcc8STakashi Sakamoto } 1365fb25dcc8STakashi Sakamoto 1366fb25dcc8STakashi Sakamoto events += data_blocks; 1367fb25dcc8STakashi Sakamoto 1368fb25dcc8STakashi Sakamoto ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(__be32); 1369fb25dcc8STakashi Sakamoto } 1370fb25dcc8STakashi Sakamoto 1371fb25dcc8STakashi Sakamoto drop_tx_packets(context, tstamp, header_length, header, s); 1372fb25dcc8STakashi Sakamoto 1373fb25dcc8STakashi Sakamoto if (events > 0) 1374fb25dcc8STakashi Sakamoto s->ctx_data.tx.event_starts = true; 1375fb25dcc8STakashi Sakamoto 1376fb25dcc8STakashi Sakamoto // Decide the cycle count to begin processing content of packet in IR contexts. 1377fb25dcc8STakashi Sakamoto { 1378fb25dcc8STakashi Sakamoto unsigned int stream_count = 0; 1379fb25dcc8STakashi Sakamoto unsigned int event_starts_count = 0; 1380fb25dcc8STakashi Sakamoto unsigned int cycle = UINT_MAX; 1381fb25dcc8STakashi Sakamoto 1382fb25dcc8STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1383fb25dcc8STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1384fb25dcc8STakashi Sakamoto ++stream_count; 1385fb25dcc8STakashi Sakamoto if (s->ctx_data.tx.event_starts) 1386fb25dcc8STakashi Sakamoto ++event_starts_count; 1387fb25dcc8STakashi Sakamoto } 1388fb25dcc8STakashi Sakamoto } 1389fb25dcc8STakashi Sakamoto 1390fb25dcc8STakashi Sakamoto if (stream_count == event_starts_count) { 1391fb25dcc8STakashi Sakamoto unsigned int next_cycle; 1392fb25dcc8STakashi Sakamoto 1393fb25dcc8STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1394fb25dcc8STakashi Sakamoto if (s->direction != AMDTP_IN_STREAM) 1395fb25dcc8STakashi Sakamoto continue; 1396fb25dcc8STakashi Sakamoto 1397fb25dcc8STakashi Sakamoto next_cycle = increment_ohci_cycle_count(s->next_cycle, 1398fb25dcc8STakashi Sakamoto d->processing_cycle.tx_init_skip); 1399fb25dcc8STakashi Sakamoto if (cycle == UINT_MAX || 1400fb25dcc8STakashi Sakamoto compare_ohci_cycle_count(next_cycle, cycle) > 0) 1401fb25dcc8STakashi Sakamoto cycle = next_cycle; 1402fb25dcc8STakashi Sakamoto 1403fb25dcc8STakashi Sakamoto s->context->callback.sc = process_tx_packets_intermediately; 1404fb25dcc8STakashi Sakamoto } 1405fb25dcc8STakashi Sakamoto 1406fb25dcc8STakashi Sakamoto d->processing_cycle.tx_start = cycle; 1407fb25dcc8STakashi Sakamoto } 1408fb25dcc8STakashi Sakamoto } 1409fb25dcc8STakashi Sakamoto } 1410fb25dcc8STakashi Sakamoto 14119b1fcd9bSTakashi Sakamoto static void process_ctxs_in_domain(struct amdtp_domain *d) 141260dd4929STakashi Sakamoto { 141360dd4929STakashi Sakamoto struct amdtp_stream *s; 141460dd4929STakashi Sakamoto 141560dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 14169b1fcd9bSTakashi Sakamoto if (s != d->irq_target && amdtp_stream_running(s)) 141760dd4929STakashi Sakamoto fw_iso_context_flush_completions(s->context); 14189b1fcd9bSTakashi Sakamoto 141960dd4929STakashi Sakamoto if (amdtp_streaming_error(s)) 142060dd4929STakashi Sakamoto goto error; 142160dd4929STakashi Sakamoto } 142260dd4929STakashi Sakamoto 142360dd4929STakashi Sakamoto return; 142460dd4929STakashi Sakamoto error: 14259b1fcd9bSTakashi Sakamoto if (amdtp_stream_running(d->irq_target)) 14269b1fcd9bSTakashi Sakamoto cancel_stream(d->irq_target); 142760dd4929STakashi Sakamoto 142860dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 142960dd4929STakashi Sakamoto if (amdtp_stream_running(s)) 143060dd4929STakashi Sakamoto cancel_stream(s); 143160dd4929STakashi Sakamoto } 143260dd4929STakashi Sakamoto } 143360dd4929STakashi Sakamoto 14349b1fcd9bSTakashi Sakamoto static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, 14359b1fcd9bSTakashi Sakamoto void *header, void *private_data) 14369b1fcd9bSTakashi Sakamoto { 14379b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 14389b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 14399b1fcd9bSTakashi Sakamoto 14409b1fcd9bSTakashi Sakamoto process_rx_packets(context, tstamp, header_length, header, private_data); 14419b1fcd9bSTakashi Sakamoto process_ctxs_in_domain(d); 14429b1fcd9bSTakashi Sakamoto } 14439b1fcd9bSTakashi Sakamoto 14449b1fcd9bSTakashi Sakamoto static void irq_target_callback_intermediately(struct fw_iso_context *context, u32 tstamp, 14459b1fcd9bSTakashi Sakamoto size_t header_length, void *header, void *private_data) 14469b1fcd9bSTakashi Sakamoto { 14479b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 14489b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 14499b1fcd9bSTakashi Sakamoto 14509b1fcd9bSTakashi Sakamoto process_rx_packets_intermediately(context, tstamp, header_length, header, private_data); 14519b1fcd9bSTakashi Sakamoto process_ctxs_in_domain(d); 14529b1fcd9bSTakashi Sakamoto } 14539b1fcd9bSTakashi Sakamoto 14549b1fcd9bSTakashi Sakamoto static void irq_target_callback_skip(struct fw_iso_context *context, u32 tstamp, 14559b1fcd9bSTakashi Sakamoto size_t header_length, void *header, void *private_data) 14569b1fcd9bSTakashi Sakamoto { 14579b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 14589b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 145939c2649cSTakashi Sakamoto bool ready_to_start; 14609b1fcd9bSTakashi Sakamoto 14619b1fcd9bSTakashi Sakamoto skip_rx_packets(context, tstamp, header_length, header, private_data); 14629b1fcd9bSTakashi Sakamoto process_ctxs_in_domain(d); 14639b1fcd9bSTakashi Sakamoto 14642f21a177STakashi Sakamoto if (d->replay.enable && !d->replay.on_the_fly) { 146539c2649cSTakashi Sakamoto unsigned int rx_count = 0; 146639c2649cSTakashi Sakamoto unsigned int rx_ready_count = 0; 146739c2649cSTakashi Sakamoto struct amdtp_stream *rx; 146839c2649cSTakashi Sakamoto 146939c2649cSTakashi Sakamoto list_for_each_entry(rx, &d->streams, list) { 147039c2649cSTakashi Sakamoto struct amdtp_stream *tx; 147139c2649cSTakashi Sakamoto unsigned int cached_cycles; 147239c2649cSTakashi Sakamoto 147339c2649cSTakashi Sakamoto if (rx->direction != AMDTP_OUT_STREAM) 147439c2649cSTakashi Sakamoto continue; 147539c2649cSTakashi Sakamoto ++rx_count; 147639c2649cSTakashi Sakamoto 147739c2649cSTakashi Sakamoto tx = rx->ctx_data.rx.replay_target; 147839c2649cSTakashi Sakamoto cached_cycles = calculate_cached_cycle_count(tx, 0); 147939c2649cSTakashi Sakamoto if (cached_cycles > tx->ctx_data.tx.cache.size / 2) 148039c2649cSTakashi Sakamoto ++rx_ready_count; 148139c2649cSTakashi Sakamoto } 148239c2649cSTakashi Sakamoto 148339c2649cSTakashi Sakamoto ready_to_start = (rx_count == rx_ready_count); 148439c2649cSTakashi Sakamoto } else { 148539c2649cSTakashi Sakamoto ready_to_start = true; 148639c2649cSTakashi Sakamoto } 148739c2649cSTakashi Sakamoto 14889b1fcd9bSTakashi Sakamoto // Decide the cycle count to begin processing content of packet in IT contexts. All of IT 14899b1fcd9bSTakashi Sakamoto // contexts are expected to start and get callback when reaching here. 149039c2649cSTakashi Sakamoto if (ready_to_start) { 149139c2649cSTakashi Sakamoto unsigned int cycle = s->next_cycle; 14929b1fcd9bSTakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 14939b1fcd9bSTakashi Sakamoto if (s->direction != AMDTP_OUT_STREAM) 14949b1fcd9bSTakashi Sakamoto continue; 14959b1fcd9bSTakashi Sakamoto 14969b1fcd9bSTakashi Sakamoto if (compare_ohci_cycle_count(s->next_cycle, cycle) > 0) 14979b1fcd9bSTakashi Sakamoto cycle = s->next_cycle; 14989b1fcd9bSTakashi Sakamoto 14999b1fcd9bSTakashi Sakamoto if (s == d->irq_target) 15009b1fcd9bSTakashi Sakamoto s->context->callback.sc = irq_target_callback_intermediately; 15019b1fcd9bSTakashi Sakamoto else 15029b1fcd9bSTakashi Sakamoto s->context->callback.sc = process_rx_packets_intermediately; 15039b1fcd9bSTakashi Sakamoto } 15049b1fcd9bSTakashi Sakamoto 15059b1fcd9bSTakashi Sakamoto d->processing_cycle.rx_start = cycle; 15069b1fcd9bSTakashi Sakamoto } 150739c2649cSTakashi Sakamoto } 15089b1fcd9bSTakashi Sakamoto 1509b7c7699bSTakashi Sakamoto // This is executed one time. For in-stream, first packet has come. For out-stream, prepared to 1510b7c7699bSTakashi Sakamoto // transmit first packet. 1511d67c46b9STakashi Sakamoto static void amdtp_stream_first_callback(struct fw_iso_context *context, 151273fc7f08STakashi Sakamoto u32 tstamp, size_t header_length, 1513d67c46b9STakashi Sakamoto void *header, void *private_data) 1514d67c46b9STakashi Sakamoto { 1515d67c46b9STakashi Sakamoto struct amdtp_stream *s = private_data; 1516da3623abSTakashi Sakamoto struct amdtp_domain *d = s->domain; 1517d67c46b9STakashi Sakamoto 1518cc4f8e91STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1519fb25dcc8STakashi Sakamoto context->callback.sc = drop_tx_packets_initially; 1520a04513f8STakashi Sakamoto } else { 1521da3623abSTakashi Sakamoto if (s == d->irq_target) 15229b1fcd9bSTakashi Sakamoto context->callback.sc = irq_target_callback_skip; 15232472cfb3STakashi Sakamoto else 15249b1fcd9bSTakashi Sakamoto context->callback.sc = skip_rx_packets; 1525a04513f8STakashi Sakamoto } 1526a04513f8STakashi Sakamoto 152773fc7f08STakashi Sakamoto context->callback.sc(context, tstamp, header_length, header, s); 1528d67c46b9STakashi Sakamoto } 1529d67c46b9STakashi Sakamoto 1530d67c46b9STakashi Sakamoto /** 1531d67c46b9STakashi Sakamoto * amdtp_stream_start - start transferring packets 1532d67c46b9STakashi Sakamoto * @s: the AMDTP stream to start 1533d67c46b9STakashi Sakamoto * @channel: the isochronous channel on the bus 1534d67c46b9STakashi Sakamoto * @speed: firewire speed code 1535af86b0b1STakashi Sakamoto * @queue_size: The number of packets in the queue. 1536af86b0b1STakashi Sakamoto * @idle_irq_interval: the interval to queue packet during initial state. 1537d67c46b9STakashi Sakamoto * 1538d67c46b9STakashi Sakamoto * The stream cannot be started until it has been configured with 1539d67c46b9STakashi Sakamoto * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI 1540d67c46b9STakashi Sakamoto * device can be started. 1541d67c46b9STakashi Sakamoto */ 1542a0e02331STakashi Sakamoto static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, 1543bd165079STakashi Sakamoto unsigned int queue_size, unsigned int idle_irq_interval) 1544d67c46b9STakashi Sakamoto { 15452472cfb3STakashi Sakamoto bool is_irq_target = (s == s->domain->irq_target); 1546d3d10a4aSTakashi Sakamoto unsigned int ctx_header_size; 1547f11453c7STakashi Sakamoto unsigned int max_ctx_payload_size; 1548d67c46b9STakashi Sakamoto enum dma_data_direction dir; 1549d67c46b9STakashi Sakamoto int type, tag, err; 1550d67c46b9STakashi Sakamoto 1551d67c46b9STakashi Sakamoto mutex_lock(&s->mutex); 1552d67c46b9STakashi Sakamoto 1553d67c46b9STakashi Sakamoto if (WARN_ON(amdtp_stream_running(s) || 1554d67c46b9STakashi Sakamoto (s->data_block_quadlets < 1))) { 1555d67c46b9STakashi Sakamoto err = -EBADFD; 1556d67c46b9STakashi Sakamoto goto err_unlock; 1557d67c46b9STakashi Sakamoto } 1558d67c46b9STakashi Sakamoto 1559d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 156060dd4929STakashi Sakamoto // NOTE: IT context should be used for constant IRQ. 156160dd4929STakashi Sakamoto if (is_irq_target) { 156260dd4929STakashi Sakamoto err = -EINVAL; 156360dd4929STakashi Sakamoto goto err_unlock; 156460dd4929STakashi Sakamoto } 156560dd4929STakashi Sakamoto 1566d67c46b9STakashi Sakamoto s->data_block_counter = UINT_MAX; 1567d3d10a4aSTakashi Sakamoto } else { 1568d67c46b9STakashi Sakamoto s->data_block_counter = 0; 1569d3d10a4aSTakashi Sakamoto } 1570d67c46b9STakashi Sakamoto 15711be4f21dSTakashi Sakamoto // initialize packet buffer. 1572d67c46b9STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1573d67c46b9STakashi Sakamoto dir = DMA_FROM_DEVICE; 1574d67c46b9STakashi Sakamoto type = FW_ISO_CONTEXT_RECEIVE; 1575c75f3678STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 1576f11453c7STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_CIP; 1577c75f3678STakashi Sakamoto else 1578f11453c7STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; 1579d67c46b9STakashi Sakamoto } else { 1580d67c46b9STakashi Sakamoto dir = DMA_TO_DEVICE; 1581d67c46b9STakashi Sakamoto type = FW_ISO_CONTEXT_TRANSMIT; 1582df9160b9STakashi Sakamoto ctx_header_size = 0; // No effect for IT context. 1583b18f0cfaSTakashi Sakamoto } 1584c75f3678STakashi Sakamoto max_ctx_payload_size = amdtp_stream_get_max_ctx_payload_size(s); 1585f11453c7STakashi Sakamoto 1586c75f3678STakashi Sakamoto err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size, max_ctx_payload_size, dir); 1587d67c46b9STakashi Sakamoto if (err < 0) 1588d67c46b9STakashi Sakamoto goto err_unlock; 1589af86b0b1STakashi Sakamoto s->queue_size = queue_size; 159060dd4929STakashi Sakamoto 1591d67c46b9STakashi Sakamoto s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, 1592d3d10a4aSTakashi Sakamoto type, channel, speed, ctx_header_size, 15932472cfb3STakashi Sakamoto amdtp_stream_first_callback, s); 1594d67c46b9STakashi Sakamoto if (IS_ERR(s->context)) { 1595d67c46b9STakashi Sakamoto err = PTR_ERR(s->context); 1596d67c46b9STakashi Sakamoto if (err == -EBUSY) 1597d67c46b9STakashi Sakamoto dev_err(&s->unit->device, 1598d67c46b9STakashi Sakamoto "no free stream on this controller\n"); 1599d67c46b9STakashi Sakamoto goto err_buffer; 1600d67c46b9STakashi Sakamoto } 1601d67c46b9STakashi Sakamoto 1602d67c46b9STakashi Sakamoto amdtp_stream_update(s); 1603d67c46b9STakashi Sakamoto 1604d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1605f11453c7STakashi Sakamoto s->ctx_data.tx.max_ctx_payload_length = max_ctx_payload_size; 1606d3d10a4aSTakashi Sakamoto s->ctx_data.tx.ctx_header_size = ctx_header_size; 1607fb25dcc8STakashi Sakamoto s->ctx_data.tx.event_starts = false; 1608f9e5ecdfSTakashi Sakamoto 1609f9e5ecdfSTakashi Sakamoto if (s->domain->replay.enable) { 1610f9e5ecdfSTakashi Sakamoto // struct fw_iso_context.drop_overflow_headers is false therefore it's 1611f9e5ecdfSTakashi Sakamoto // possible to cache much unexpectedly. 1612f9e5ecdfSTakashi Sakamoto s->ctx_data.tx.cache.size = max_t(unsigned int, s->syt_interval * 2, 1613f9e5ecdfSTakashi Sakamoto queue_size * 3 / 2); 1614f9e5ecdfSTakashi Sakamoto s->ctx_data.tx.cache.tail = 0; 1615f9e5ecdfSTakashi Sakamoto s->ctx_data.tx.cache.descs = kcalloc(s->ctx_data.tx.cache.size, 1616f9e5ecdfSTakashi Sakamoto sizeof(*s->ctx_data.tx.cache.descs), GFP_KERNEL); 16178b6e2193SDan Carpenter if (!s->ctx_data.tx.cache.descs) { 16188b6e2193SDan Carpenter err = -ENOMEM; 1619f9e5ecdfSTakashi Sakamoto goto err_context; 1620f9e5ecdfSTakashi Sakamoto } 16218b6e2193SDan Carpenter } 1622bd165079STakashi Sakamoto } else { 16236f24bb8aSTakashi Sakamoto static const struct { 16246f24bb8aSTakashi Sakamoto unsigned int data_block; 16256f24bb8aSTakashi Sakamoto unsigned int syt_offset; 16266f24bb8aSTakashi Sakamoto } *entry, initial_state[] = { 16276f24bb8aSTakashi Sakamoto [CIP_SFC_32000] = { 4, 3072 }, 16286f24bb8aSTakashi Sakamoto [CIP_SFC_48000] = { 6, 1024 }, 16296f24bb8aSTakashi Sakamoto [CIP_SFC_96000] = { 12, 1024 }, 16306f24bb8aSTakashi Sakamoto [CIP_SFC_192000] = { 24, 1024 }, 16316f24bb8aSTakashi Sakamoto [CIP_SFC_44100] = { 0, 67 }, 16326f24bb8aSTakashi Sakamoto [CIP_SFC_88200] = { 0, 67 }, 16336f24bb8aSTakashi Sakamoto [CIP_SFC_176400] = { 0, 67 }, 16346f24bb8aSTakashi Sakamoto }; 16356f24bb8aSTakashi Sakamoto 16366f24bb8aSTakashi Sakamoto s->ctx_data.rx.seq.descs = kcalloc(queue_size, sizeof(*s->ctx_data.rx.seq.descs), GFP_KERNEL); 16378b6e2193SDan Carpenter if (!s->ctx_data.rx.seq.descs) { 16388b6e2193SDan Carpenter err = -ENOMEM; 16396f24bb8aSTakashi Sakamoto goto err_context; 16408b6e2193SDan Carpenter } 16416f24bb8aSTakashi Sakamoto s->ctx_data.rx.seq.size = queue_size; 1642119c446aSTakashi Sakamoto s->ctx_data.rx.seq.pos = 0; 16436f24bb8aSTakashi Sakamoto 16446f24bb8aSTakashi Sakamoto entry = &initial_state[s->sfc]; 16456f24bb8aSTakashi Sakamoto s->ctx_data.rx.data_block_state = entry->data_block; 16466f24bb8aSTakashi Sakamoto s->ctx_data.rx.syt_offset_state = entry->syt_offset; 16476f24bb8aSTakashi Sakamoto s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE; 16486f24bb8aSTakashi Sakamoto 1649bd165079STakashi Sakamoto s->ctx_data.rx.event_count = 0; 1650d3d10a4aSTakashi Sakamoto } 165152759c09STakashi Sakamoto 16523b196c39STakashi Sakamoto if (s->flags & CIP_NO_HEADER) 16533b196c39STakashi Sakamoto s->tag = TAG_NO_CIP_HEADER; 16543b196c39STakashi Sakamoto else 16553b196c39STakashi Sakamoto s->tag = TAG_CIP; 16563b196c39STakashi Sakamoto 1657a0e02331STakashi Sakamoto s->pkt_descs = kcalloc(s->queue_size, sizeof(*s->pkt_descs), 165804130cf8STakashi Sakamoto GFP_KERNEL); 165904130cf8STakashi Sakamoto if (!s->pkt_descs) { 166004130cf8STakashi Sakamoto err = -ENOMEM; 166104130cf8STakashi Sakamoto goto err_context; 166204130cf8STakashi Sakamoto } 166304130cf8STakashi Sakamoto 1664d67c46b9STakashi Sakamoto s->packet_index = 0; 1665d67c46b9STakashi Sakamoto do { 16666007bf54STakashi Sakamoto struct fw_iso_packet params; 1667e229853dSTakashi Sakamoto 1668b18f0cfaSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 166960dd4929STakashi Sakamoto err = queue_in_packet(s, ¶ms); 1670b18f0cfaSTakashi Sakamoto } else { 167160dd4929STakashi Sakamoto bool sched_irq = false; 167260dd4929STakashi Sakamoto 1673b18f0cfaSTakashi Sakamoto params.header_length = 0; 1674b18f0cfaSTakashi Sakamoto params.payload_length = 0; 167560dd4929STakashi Sakamoto 167660dd4929STakashi Sakamoto if (is_irq_target) { 167760dd4929STakashi Sakamoto sched_irq = !((s->packet_index + 1) % 167860dd4929STakashi Sakamoto idle_irq_interval); 167960dd4929STakashi Sakamoto } 168060dd4929STakashi Sakamoto 1681e229853dSTakashi Sakamoto err = queue_out_packet(s, ¶ms, sched_irq); 1682b18f0cfaSTakashi Sakamoto } 1683d67c46b9STakashi Sakamoto if (err < 0) 168404130cf8STakashi Sakamoto goto err_pkt_descs; 1685d67c46b9STakashi Sakamoto } while (s->packet_index > 0); 1686d67c46b9STakashi Sakamoto 1687d67c46b9STakashi Sakamoto /* NOTE: TAG1 matches CIP. This just affects in stream. */ 1688d67c46b9STakashi Sakamoto tag = FW_ISO_CONTEXT_MATCH_TAG1; 16893b196c39STakashi Sakamoto if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER)) 1690d67c46b9STakashi Sakamoto tag |= FW_ISO_CONTEXT_MATCH_TAG0; 1691d67c46b9STakashi Sakamoto 1692bdaedca7STakashi Sakamoto s->ready_processing = false; 1693bd165079STakashi Sakamoto err = fw_iso_context_start(s->context, -1, 0, tag); 1694d67c46b9STakashi Sakamoto if (err < 0) 169504130cf8STakashi Sakamoto goto err_pkt_descs; 1696d67c46b9STakashi Sakamoto 1697d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1698d67c46b9STakashi Sakamoto 1699d67c46b9STakashi Sakamoto return 0; 170004130cf8STakashi Sakamoto err_pkt_descs: 170104130cf8STakashi Sakamoto kfree(s->pkt_descs); 1702d67c46b9STakashi Sakamoto err_context: 1703f9e5ecdfSTakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM) { 17046f24bb8aSTakashi Sakamoto kfree(s->ctx_data.rx.seq.descs); 1705f9e5ecdfSTakashi Sakamoto } else { 1706f9e5ecdfSTakashi Sakamoto if (s->domain->replay.enable) 1707f9e5ecdfSTakashi Sakamoto kfree(s->ctx_data.tx.cache.descs); 1708f9e5ecdfSTakashi Sakamoto } 1709d67c46b9STakashi Sakamoto fw_iso_context_destroy(s->context); 1710d67c46b9STakashi Sakamoto s->context = ERR_PTR(-1); 1711d67c46b9STakashi Sakamoto err_buffer: 1712d67c46b9STakashi Sakamoto iso_packets_buffer_destroy(&s->buffer, s->unit); 1713d67c46b9STakashi Sakamoto err_unlock: 1714d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1715d67c46b9STakashi Sakamoto 1716d67c46b9STakashi Sakamoto return err; 1717d67c46b9STakashi Sakamoto } 1718d67c46b9STakashi Sakamoto 1719d67c46b9STakashi Sakamoto /** 1720f890f9a0STakashi Sakamoto * amdtp_domain_stream_pcm_pointer - get the PCM buffer position 1721f890f9a0STakashi Sakamoto * @d: the AMDTP domain. 1722d67c46b9STakashi Sakamoto * @s: the AMDTP stream that transports the PCM data 1723d67c46b9STakashi Sakamoto * 1724d67c46b9STakashi Sakamoto * Returns the current buffer position, in frames. 1725d67c46b9STakashi Sakamoto */ 1726f890f9a0STakashi Sakamoto unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, 1727f890f9a0STakashi Sakamoto struct amdtp_stream *s) 1728d67c46b9STakashi Sakamoto { 1729f890f9a0STakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 1730f890f9a0STakashi Sakamoto 17317ba5ca32STakashi Sakamoto // Process isochronous packets queued till recent isochronous cycle to handle PCM frames. 1732f890f9a0STakashi Sakamoto if (irq_target && amdtp_stream_running(irq_target)) { 17337ba5ca32STakashi Sakamoto // In software IRQ context, the call causes dead-lock to disable the tasklet 17347ba5ca32STakashi Sakamoto // synchronously. 17353b86ec63STakashi Sakamoto if (!in_softirq()) 1736f890f9a0STakashi Sakamoto fw_iso_context_flush_completions(irq_target->context); 1737f890f9a0STakashi Sakamoto } 1738d67c46b9STakashi Sakamoto 17396aa7de05SMark Rutland return READ_ONCE(s->pcm_buffer_pointer); 1740d67c46b9STakashi Sakamoto } 1741f890f9a0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_pointer); 1742d67c46b9STakashi Sakamoto 1743d67c46b9STakashi Sakamoto /** 1744e6dcc92fSTakashi Sakamoto * amdtp_domain_stream_pcm_ack - acknowledge queued PCM frames 1745e6dcc92fSTakashi Sakamoto * @d: the AMDTP domain. 1746875becf8STakashi Sakamoto * @s: the AMDTP stream that transfers the PCM frames 1747875becf8STakashi Sakamoto * 1748875becf8STakashi Sakamoto * Returns zero always. 1749875becf8STakashi Sakamoto */ 1750e6dcc92fSTakashi Sakamoto int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s) 1751875becf8STakashi Sakamoto { 1752e6dcc92fSTakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 1753e6dcc92fSTakashi Sakamoto 1754e6dcc92fSTakashi Sakamoto // Process isochronous packets for recent isochronous cycle to handle 1755e6dcc92fSTakashi Sakamoto // queued PCM frames. 1756987b705bSTakashi Sakamoto if (irq_target && amdtp_stream_running(irq_target)) 1757e6dcc92fSTakashi Sakamoto fw_iso_context_flush_completions(irq_target->context); 1758875becf8STakashi Sakamoto 1759875becf8STakashi Sakamoto return 0; 1760875becf8STakashi Sakamoto } 1761e6dcc92fSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_ack); 1762875becf8STakashi Sakamoto 1763875becf8STakashi Sakamoto /** 1764d67c46b9STakashi Sakamoto * amdtp_stream_update - update the stream after a bus reset 1765d67c46b9STakashi Sakamoto * @s: the AMDTP stream 1766d67c46b9STakashi Sakamoto */ 1767d67c46b9STakashi Sakamoto void amdtp_stream_update(struct amdtp_stream *s) 1768d67c46b9STakashi Sakamoto { 1769d67c46b9STakashi Sakamoto /* Precomputing. */ 17706aa7de05SMark Rutland WRITE_ONCE(s->source_node_id_field, 17716aa7de05SMark Rutland (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & CIP_SID_MASK); 1772d67c46b9STakashi Sakamoto } 1773d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_update); 1774d67c46b9STakashi Sakamoto 1775d67c46b9STakashi Sakamoto /** 1776d67c46b9STakashi Sakamoto * amdtp_stream_stop - stop sending packets 1777d67c46b9STakashi Sakamoto * @s: the AMDTP stream to stop 1778d67c46b9STakashi Sakamoto * 1779d67c46b9STakashi Sakamoto * All PCM and MIDI devices of the stream must be stopped before the stream 1780d67c46b9STakashi Sakamoto * itself can be stopped. 1781d67c46b9STakashi Sakamoto */ 178274f94e41STakashi Sakamoto static void amdtp_stream_stop(struct amdtp_stream *s) 1783d67c46b9STakashi Sakamoto { 1784d67c46b9STakashi Sakamoto mutex_lock(&s->mutex); 1785d67c46b9STakashi Sakamoto 1786d67c46b9STakashi Sakamoto if (!amdtp_stream_running(s)) { 1787d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1788d67c46b9STakashi Sakamoto return; 1789d67c46b9STakashi Sakamoto } 1790d67c46b9STakashi Sakamoto 1791d67c46b9STakashi Sakamoto fw_iso_context_stop(s->context); 1792d67c46b9STakashi Sakamoto fw_iso_context_destroy(s->context); 1793d67c46b9STakashi Sakamoto s->context = ERR_PTR(-1); 1794d67c46b9STakashi Sakamoto iso_packets_buffer_destroy(&s->buffer, s->unit); 179504130cf8STakashi Sakamoto kfree(s->pkt_descs); 1796d67c46b9STakashi Sakamoto 1797f9e5ecdfSTakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM) { 17986f24bb8aSTakashi Sakamoto kfree(s->ctx_data.rx.seq.descs); 1799f9e5ecdfSTakashi Sakamoto } else { 1800f9e5ecdfSTakashi Sakamoto if (s->domain->replay.enable) 1801f9e5ecdfSTakashi Sakamoto kfree(s->ctx_data.tx.cache.descs); 1802f9e5ecdfSTakashi Sakamoto } 1803d67c46b9STakashi Sakamoto 1804d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1805d67c46b9STakashi Sakamoto } 1806d67c46b9STakashi Sakamoto 1807d67c46b9STakashi Sakamoto /** 1808d67c46b9STakashi Sakamoto * amdtp_stream_pcm_abort - abort the running PCM device 1809d67c46b9STakashi Sakamoto * @s: the AMDTP stream about to be stopped 1810d67c46b9STakashi Sakamoto * 1811d67c46b9STakashi Sakamoto * If the isochronous stream needs to be stopped asynchronously, call this 1812d67c46b9STakashi Sakamoto * function first to stop the PCM device. 1813d67c46b9STakashi Sakamoto */ 1814d67c46b9STakashi Sakamoto void amdtp_stream_pcm_abort(struct amdtp_stream *s) 1815d67c46b9STakashi Sakamoto { 1816d67c46b9STakashi Sakamoto struct snd_pcm_substream *pcm; 1817d67c46b9STakashi Sakamoto 18186aa7de05SMark Rutland pcm = READ_ONCE(s->pcm); 1819d67c46b9STakashi Sakamoto if (pcm) 1820d67c46b9STakashi Sakamoto snd_pcm_stop_xrun(pcm); 1821d67c46b9STakashi Sakamoto } 1822d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_abort); 18233ec3d7a3STakashi Sakamoto 18243ec3d7a3STakashi Sakamoto /** 18253ec3d7a3STakashi Sakamoto * amdtp_domain_init - initialize an AMDTP domain structure 18263ec3d7a3STakashi Sakamoto * @d: the AMDTP domain to initialize. 18273ec3d7a3STakashi Sakamoto */ 18283ec3d7a3STakashi Sakamoto int amdtp_domain_init(struct amdtp_domain *d) 18293ec3d7a3STakashi Sakamoto { 18303ec3d7a3STakashi Sakamoto INIT_LIST_HEAD(&d->streams); 18313ec3d7a3STakashi Sakamoto 1832d68c3123STakashi Sakamoto d->events_per_period = 0; 1833d68c3123STakashi Sakamoto 18343ec3d7a3STakashi Sakamoto return 0; 18353ec3d7a3STakashi Sakamoto } 18363ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_init); 18373ec3d7a3STakashi Sakamoto 18383ec3d7a3STakashi Sakamoto /** 18393ec3d7a3STakashi Sakamoto * amdtp_domain_destroy - destroy an AMDTP domain structure 18403ec3d7a3STakashi Sakamoto * @d: the AMDTP domain to destroy. 18413ec3d7a3STakashi Sakamoto */ 18423ec3d7a3STakashi Sakamoto void amdtp_domain_destroy(struct amdtp_domain *d) 18433ec3d7a3STakashi Sakamoto { 18448d0d5c3fSTakashi Sakamoto // At present nothing to do. 18458d0d5c3fSTakashi Sakamoto return; 18463ec3d7a3STakashi Sakamoto } 18473ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_destroy); 18486261f90bSTakashi Sakamoto 18496261f90bSTakashi Sakamoto /** 1850157a53eeSTakashi Sakamoto * amdtp_domain_add_stream - register isoc context into the domain. 1851157a53eeSTakashi Sakamoto * @d: the AMDTP domain. 1852157a53eeSTakashi Sakamoto * @s: the AMDTP stream. 1853157a53eeSTakashi Sakamoto * @channel: the isochronous channel on the bus. 1854157a53eeSTakashi Sakamoto * @speed: firewire speed code. 1855157a53eeSTakashi Sakamoto */ 1856157a53eeSTakashi Sakamoto int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, 1857157a53eeSTakashi Sakamoto int channel, int speed) 1858157a53eeSTakashi Sakamoto { 1859157a53eeSTakashi Sakamoto struct amdtp_stream *tmp; 1860157a53eeSTakashi Sakamoto 1861157a53eeSTakashi Sakamoto list_for_each_entry(tmp, &d->streams, list) { 1862157a53eeSTakashi Sakamoto if (s == tmp) 1863157a53eeSTakashi Sakamoto return -EBUSY; 1864157a53eeSTakashi Sakamoto } 1865157a53eeSTakashi Sakamoto 1866157a53eeSTakashi Sakamoto list_add(&s->list, &d->streams); 1867157a53eeSTakashi Sakamoto 1868157a53eeSTakashi Sakamoto s->channel = channel; 1869157a53eeSTakashi Sakamoto s->speed = speed; 18702472cfb3STakashi Sakamoto s->domain = d; 1871157a53eeSTakashi Sakamoto 1872157a53eeSTakashi Sakamoto return 0; 1873157a53eeSTakashi Sakamoto } 1874157a53eeSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); 1875157a53eeSTakashi Sakamoto 187639c2649cSTakashi Sakamoto // Make the reference from rx stream to tx stream for sequence replay. When the number of tx streams 187739c2649cSTakashi Sakamoto // is less than the number of rx streams, the first tx stream is selected. 187839c2649cSTakashi Sakamoto static int make_association(struct amdtp_domain *d) 187939c2649cSTakashi Sakamoto { 188039c2649cSTakashi Sakamoto unsigned int dst_index = 0; 188139c2649cSTakashi Sakamoto struct amdtp_stream *rx; 188239c2649cSTakashi Sakamoto 188339c2649cSTakashi Sakamoto // Make association to replay target. 188439c2649cSTakashi Sakamoto list_for_each_entry(rx, &d->streams, list) { 188539c2649cSTakashi Sakamoto if (rx->direction == AMDTP_OUT_STREAM) { 188639c2649cSTakashi Sakamoto unsigned int src_index = 0; 188739c2649cSTakashi Sakamoto struct amdtp_stream *tx = NULL; 188839c2649cSTakashi Sakamoto struct amdtp_stream *s; 188939c2649cSTakashi Sakamoto 189039c2649cSTakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 189139c2649cSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 189239c2649cSTakashi Sakamoto if (dst_index == src_index) { 189339c2649cSTakashi Sakamoto tx = s; 189439c2649cSTakashi Sakamoto break; 189539c2649cSTakashi Sakamoto } 189639c2649cSTakashi Sakamoto 189739c2649cSTakashi Sakamoto ++src_index; 189839c2649cSTakashi Sakamoto } 189939c2649cSTakashi Sakamoto } 190039c2649cSTakashi Sakamoto if (!tx) { 190139c2649cSTakashi Sakamoto // Select the first entry. 190239c2649cSTakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 190339c2649cSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 190439c2649cSTakashi Sakamoto tx = s; 190539c2649cSTakashi Sakamoto break; 190639c2649cSTakashi Sakamoto } 190739c2649cSTakashi Sakamoto } 190839c2649cSTakashi Sakamoto // No target is available to replay sequence. 190939c2649cSTakashi Sakamoto if (!tx) 191039c2649cSTakashi Sakamoto return -EINVAL; 191139c2649cSTakashi Sakamoto } 191239c2649cSTakashi Sakamoto 191339c2649cSTakashi Sakamoto rx->ctx_data.rx.replay_target = tx; 191439c2649cSTakashi Sakamoto rx->ctx_data.rx.cache_head = 0; 191539c2649cSTakashi Sakamoto 191639c2649cSTakashi Sakamoto ++dst_index; 191739c2649cSTakashi Sakamoto } 191839c2649cSTakashi Sakamoto } 191939c2649cSTakashi Sakamoto 192039c2649cSTakashi Sakamoto return 0; 192139c2649cSTakashi Sakamoto } 192239c2649cSTakashi Sakamoto 1923157a53eeSTakashi Sakamoto /** 19249b4702b0STakashi Sakamoto * amdtp_domain_start - start sending packets for isoc context in the domain. 19259b4702b0STakashi Sakamoto * @d: the AMDTP domain. 192626541cb1STakashi Sakamoto * @tx_init_skip_cycles: the number of cycles to skip processing packets at initial stage of IR 192726541cb1STakashi Sakamoto * contexts. 1928f9e5ecdfSTakashi Sakamoto * @replay_seq: whether to replay the sequence of packet in IR context for the sequence of packet in 1929f9e5ecdfSTakashi Sakamoto * IT context. 19302f21a177STakashi Sakamoto * @replay_on_the_fly: transfer rx packets according to nominal frequency, then begin to replay 19312f21a177STakashi Sakamoto * according to arrival of events in tx packets. 19329b4702b0STakashi Sakamoto */ 19332f21a177STakashi Sakamoto int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq, 19342f21a177STakashi Sakamoto bool replay_on_the_fly) 19359b4702b0STakashi Sakamoto { 1936af86b0b1STakashi Sakamoto unsigned int events_per_buffer = d->events_per_buffer; 1937af86b0b1STakashi Sakamoto unsigned int events_per_period = d->events_per_period; 1938af86b0b1STakashi Sakamoto unsigned int queue_size; 19399b4702b0STakashi Sakamoto struct amdtp_stream *s; 19400cbbeaf3SChristophe JAILLET bool found = false; 1941acfedcbeSTakashi Sakamoto int err; 19429b4702b0STakashi Sakamoto 194339c2649cSTakashi Sakamoto if (replay_seq) { 194439c2649cSTakashi Sakamoto err = make_association(d); 194539c2649cSTakashi Sakamoto if (err < 0) 194639c2649cSTakashi Sakamoto return err; 194739c2649cSTakashi Sakamoto } 1948f9e5ecdfSTakashi Sakamoto d->replay.enable = replay_seq; 19492f21a177STakashi Sakamoto d->replay.on_the_fly = replay_on_the_fly; 1950f9e5ecdfSTakashi Sakamoto 195160dd4929STakashi Sakamoto // Select an IT context as IRQ target. 19529b4702b0STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 19530cbbeaf3SChristophe JAILLET if (s->direction == AMDTP_OUT_STREAM) { 19540cbbeaf3SChristophe JAILLET found = true; 19559b4702b0STakashi Sakamoto break; 19569b4702b0STakashi Sakamoto } 19570cbbeaf3SChristophe JAILLET } 19580cbbeaf3SChristophe JAILLET if (!found) 195960dd4929STakashi Sakamoto return -ENXIO; 196060dd4929STakashi Sakamoto d->irq_target = s; 19619b4702b0STakashi Sakamoto 196226541cb1STakashi Sakamoto d->processing_cycle.tx_init_skip = tx_init_skip_cycles; 196326541cb1STakashi Sakamoto 1964af86b0b1STakashi Sakamoto // This is a case that AMDTP streams in domain run just for MIDI 1965af86b0b1STakashi Sakamoto // substream. Use the number of events equivalent to 10 msec as 1966af86b0b1STakashi Sakamoto // interval of hardware IRQ. 1967af86b0b1STakashi Sakamoto if (events_per_period == 0) 1968af86b0b1STakashi Sakamoto events_per_period = amdtp_rate_table[d->irq_target->sfc] / 100; 1969af86b0b1STakashi Sakamoto if (events_per_buffer == 0) 1970af86b0b1STakashi Sakamoto events_per_buffer = events_per_period * 3; 1971af86b0b1STakashi Sakamoto 1972af86b0b1STakashi Sakamoto queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, 1973af86b0b1STakashi Sakamoto amdtp_rate_table[d->irq_target->sfc]); 1974af86b0b1STakashi Sakamoto 197560dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1976bd165079STakashi Sakamoto unsigned int idle_irq_interval = 0; 1977acfedcbeSTakashi Sakamoto 1978bd165079STakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM && s == d->irq_target) { 1979af86b0b1STakashi Sakamoto idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, 1980af86b0b1STakashi Sakamoto amdtp_rate_table[d->irq_target->sfc]); 1981bd165079STakashi Sakamoto } 1982bd165079STakashi Sakamoto 1983bd165079STakashi Sakamoto // Starts immediately but actually DMA context starts several hundred cycles later. 1984bd165079STakashi Sakamoto err = amdtp_stream_start(s, s->channel, s->speed, queue_size, idle_irq_interval); 198560dd4929STakashi Sakamoto if (err < 0) 198660dd4929STakashi Sakamoto goto error; 1987bd165079STakashi Sakamoto } 198860dd4929STakashi Sakamoto 198960dd4929STakashi Sakamoto return 0; 199060dd4929STakashi Sakamoto error: 199160dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) 199260dd4929STakashi Sakamoto amdtp_stream_stop(s); 19939b4702b0STakashi Sakamoto return err; 19949b4702b0STakashi Sakamoto } 19959b4702b0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_start); 19969b4702b0STakashi Sakamoto 19979b4702b0STakashi Sakamoto /** 19986261f90bSTakashi Sakamoto * amdtp_domain_stop - stop sending packets for isoc context in the same domain. 19996261f90bSTakashi Sakamoto * @d: the AMDTP domain to which the isoc contexts belong. 20006261f90bSTakashi Sakamoto */ 20016261f90bSTakashi Sakamoto void amdtp_domain_stop(struct amdtp_domain *d) 20026261f90bSTakashi Sakamoto { 20036261f90bSTakashi Sakamoto struct amdtp_stream *s, *next; 20046261f90bSTakashi Sakamoto 200560dd4929STakashi Sakamoto if (d->irq_target) 200660dd4929STakashi Sakamoto amdtp_stream_stop(d->irq_target); 200760dd4929STakashi Sakamoto 20086261f90bSTakashi Sakamoto list_for_each_entry_safe(s, next, &d->streams, list) { 20096261f90bSTakashi Sakamoto list_del(&s->list); 20106261f90bSTakashi Sakamoto 201160dd4929STakashi Sakamoto if (s != d->irq_target) 20126261f90bSTakashi Sakamoto amdtp_stream_stop(s); 20136261f90bSTakashi Sakamoto } 2014d68c3123STakashi Sakamoto 2015d68c3123STakashi Sakamoto d->events_per_period = 0; 201660dd4929STakashi Sakamoto d->irq_target = NULL; 20176261f90bSTakashi Sakamoto } 20186261f90bSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stop); 2019