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; 498cccddec4STakashi Sakamoto unsigned int cycles = s->ctx_data.tx.cache.pos; 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 507*cec371ffSTakashi Sakamoto static void cache_seq(struct amdtp_stream *s, const struct pkt_desc *src, 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; 512cccddec4STakashi Sakamoto unsigned int cache_pos = s->ctx_data.tx.cache.pos; 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) { 517cccddec4STakashi Sakamoto struct seq_desc *dst = cache + cache_pos; 518f9e5ecdfSTakashi Sakamoto 519f9e5ecdfSTakashi Sakamoto if (aware_syt && src->syt != CIP_SYT_NO_INFO) 520f9e5ecdfSTakashi Sakamoto dst->syt_offset = compute_syt_offset(src->syt, src->cycle, transfer_delay); 521f9e5ecdfSTakashi Sakamoto else 522f9e5ecdfSTakashi Sakamoto dst->syt_offset = CIP_SYT_NO_INFO; 523f9e5ecdfSTakashi Sakamoto dst->data_blocks = src->data_blocks; 524f9e5ecdfSTakashi Sakamoto 525cccddec4STakashi Sakamoto cache_pos = (cache_pos + 1) % cache_size; 526*cec371ffSTakashi Sakamoto src = amdtp_stream_next_packet_desc(s, src); 527f9e5ecdfSTakashi Sakamoto } 528f9e5ecdfSTakashi Sakamoto 529cccddec4STakashi Sakamoto s->ctx_data.tx.cache.pos = cache_pos; 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; 549c38d8cffSTakashi Sakamoto unsigned int cache_pos = s->ctx_data.rx.cache_pos; 55039c2649cSTakashi Sakamoto int i; 55139c2649cSTakashi Sakamoto 55239c2649cSTakashi Sakamoto for (i = 0; i < count; ++i) { 553c38d8cffSTakashi Sakamoto descs[pos] = cache[cache_pos]; 554c38d8cffSTakashi Sakamoto cache_pos = (cache_pos + 1) % cache_size; 555119c446aSTakashi Sakamoto pos = (pos + 1) % size; 55639c2649cSTakashi Sakamoto } 55739c2649cSTakashi Sakamoto 558c38d8cffSTakashi Sakamoto s->ctx_data.rx.cache_pos = cache_pos; 55939c2649cSTakashi Sakamoto } 56039c2649cSTakashi Sakamoto 561f2bdee85STakashi Sakamoto static void pool_seq_descs(struct amdtp_stream *s, struct seq_desc *descs, unsigned int size, 562f2bdee85STakashi 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; 576c38d8cffSTakashi Sakamoto const unsigned int cache_pos = s->ctx_data.rx.cache_pos; 577c38d8cffSTakashi Sakamoto unsigned int cached_cycles = calculate_cached_cycle_count(tx, cache_pos); 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 884*cec371ffSTakashi Sakamoto static int generate_tx_packet_descs(struct amdtp_stream *s, struct pkt_desc *desc, 885cccddec4STakashi Sakamoto const __be32 *ctx_header, unsigned int packet_count, 88673246fc4STakashi Sakamoto unsigned int *desc_count) 887753e7179STakashi Sakamoto { 888705794c5STakashi Sakamoto unsigned int next_cycle = s->next_cycle; 889753e7179STakashi Sakamoto unsigned int dbc = s->data_block_counter; 890814b4312STakashi Sakamoto unsigned int packet_index = s->packet_index; 891814b4312STakashi Sakamoto unsigned int queue_size = s->queue_size; 892753e7179STakashi Sakamoto int i; 893753e7179STakashi Sakamoto int err; 894753e7179STakashi Sakamoto 89573246fc4STakashi Sakamoto *desc_count = 0; 896cccddec4STakashi Sakamoto for (i = 0; i < packet_count; ++i) { 897753e7179STakashi Sakamoto unsigned int cycle; 898705794c5STakashi Sakamoto bool lost; 899753e7179STakashi Sakamoto unsigned int data_blocks; 900753e7179STakashi Sakamoto unsigned int syt; 901753e7179STakashi Sakamoto 9023e106f4fSTakashi Sakamoto cycle = compute_ohci_cycle_count(ctx_header[1]); 903705794c5STakashi Sakamoto lost = (next_cycle != cycle); 904705794c5STakashi Sakamoto if (lost) { 905705794c5STakashi Sakamoto if (s->flags & CIP_NO_HEADER) { 906705794c5STakashi Sakamoto // Fireface skips transmission just for an isoc cycle corresponding 907705794c5STakashi Sakamoto // to empty packet. 90873246fc4STakashi Sakamoto unsigned int prev_cycle = next_cycle; 90973246fc4STakashi Sakamoto 910705794c5STakashi Sakamoto next_cycle = increment_ohci_cycle_count(next_cycle, 1); 911705794c5STakashi Sakamoto lost = (next_cycle != cycle); 91273246fc4STakashi Sakamoto if (!lost) { 91373246fc4STakashi Sakamoto // Prepare a description for the skipped cycle for 91473246fc4STakashi Sakamoto // sequence replay. 91573246fc4STakashi Sakamoto desc->cycle = prev_cycle; 91673246fc4STakashi Sakamoto desc->syt = 0; 91773246fc4STakashi Sakamoto desc->data_blocks = 0; 91873246fc4STakashi Sakamoto desc->data_block_counter = dbc; 91973246fc4STakashi Sakamoto desc->ctx_payload = NULL; 920*cec371ffSTakashi Sakamoto desc = amdtp_stream_next_packet_desc(s, desc); 92173246fc4STakashi Sakamoto ++(*desc_count); 92273246fc4STakashi Sakamoto } 923705794c5STakashi Sakamoto } else if (s->flags & CIP_JUMBO_PAYLOAD) { 924705794c5STakashi Sakamoto // OXFW970 skips transmission for several isoc cycles during 92573246fc4STakashi Sakamoto // asynchronous transaction. The sequence replay is impossible due 92673246fc4STakashi Sakamoto // to the reason. 927705794c5STakashi Sakamoto unsigned int safe_cycle = increment_ohci_cycle_count(next_cycle, 928705794c5STakashi Sakamoto IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES); 929705794c5STakashi Sakamoto lost = (compare_ohci_cycle_count(safe_cycle, cycle) > 0); 930705794c5STakashi Sakamoto } 931705794c5STakashi Sakamoto if (lost) { 932705794c5STakashi Sakamoto dev_err(&s->unit->device, "Detect discontinuity of cycle: %d %d\n", 933705794c5STakashi Sakamoto next_cycle, cycle); 934705794c5STakashi Sakamoto return -EIO; 935705794c5STakashi Sakamoto } 936705794c5STakashi Sakamoto } 937753e7179STakashi Sakamoto 938ebd2a647STakashi Sakamoto err = parse_ir_ctx_header(s, cycle, ctx_header, &data_blocks, &dbc, &syt, 939ebd2a647STakashi Sakamoto packet_index, i); 940753e7179STakashi Sakamoto if (err < 0) 941753e7179STakashi Sakamoto return err; 942753e7179STakashi Sakamoto 943753e7179STakashi Sakamoto desc->cycle = cycle; 944753e7179STakashi Sakamoto desc->syt = syt; 945753e7179STakashi Sakamoto desc->data_blocks = data_blocks; 946753e7179STakashi Sakamoto desc->data_block_counter = dbc; 947814b4312STakashi Sakamoto desc->ctx_payload = s->buffer.packets[packet_index].buffer; 948753e7179STakashi Sakamoto 949753e7179STakashi Sakamoto if (!(s->flags & CIP_DBC_IS_END_EVENT)) 950753e7179STakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 951753e7179STakashi Sakamoto 952705794c5STakashi Sakamoto next_cycle = increment_ohci_cycle_count(next_cycle, 1); 953*cec371ffSTakashi Sakamoto desc = amdtp_stream_next_packet_desc(s, desc); 95473246fc4STakashi Sakamoto ++(*desc_count); 955705794c5STakashi Sakamoto ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); 956814b4312STakashi Sakamoto packet_index = (packet_index + 1) % queue_size; 957753e7179STakashi Sakamoto } 958753e7179STakashi Sakamoto 959705794c5STakashi Sakamoto s->next_cycle = next_cycle; 960753e7179STakashi Sakamoto s->data_block_counter = dbc; 961753e7179STakashi Sakamoto 962753e7179STakashi Sakamoto return 0; 963753e7179STakashi Sakamoto } 964753e7179STakashi Sakamoto 96583cfb5c5STakashi Sakamoto static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle, 96683cfb5c5STakashi Sakamoto unsigned int transfer_delay) 96783cfb5c5STakashi Sakamoto { 96883cfb5c5STakashi Sakamoto unsigned int syt; 96983cfb5c5STakashi Sakamoto 97083cfb5c5STakashi Sakamoto syt_offset += transfer_delay; 97183cfb5c5STakashi Sakamoto syt = ((cycle + syt_offset / TICKS_PER_CYCLE) << 12) | 97283cfb5c5STakashi Sakamoto (syt_offset % TICKS_PER_CYCLE); 97383cfb5c5STakashi Sakamoto return syt & CIP_SYT_MASK; 97483cfb5c5STakashi Sakamoto } 97583cfb5c5STakashi Sakamoto 976*cec371ffSTakashi Sakamoto static void generate_rx_packet_descs(struct amdtp_stream *s, struct pkt_desc *desc, 977f2bdee85STakashi Sakamoto const __be32 *ctx_header, unsigned int packet_count) 978f4f6ae7bSTakashi Sakamoto { 979f2bdee85STakashi Sakamoto struct seq_desc *seq_descs = s->ctx_data.rx.seq.descs; 980f2bdee85STakashi Sakamoto unsigned int seq_size = s->ctx_data.rx.seq.size; 981f2bdee85STakashi Sakamoto unsigned int seq_pos = s->ctx_data.rx.seq.pos; 982f4f6ae7bSTakashi Sakamoto unsigned int dbc = s->data_block_counter; 9838070d265STakashi Sakamoto bool aware_syt = !(s->flags & CIP_UNAWARE_SYT); 984f4f6ae7bSTakashi Sakamoto int i; 985f4f6ae7bSTakashi Sakamoto 986f2bdee85STakashi Sakamoto pool_seq_descs(s, seq_descs, seq_size, seq_pos, packet_count); 987f2bdee85STakashi Sakamoto 988f2bdee85STakashi Sakamoto for (i = 0; i < packet_count; ++i) { 989a0e02331STakashi Sakamoto unsigned int index = (s->packet_index + i) % s->queue_size; 990f2bdee85STakashi Sakamoto const struct seq_desc *seq = seq_descs + seq_pos; 991f4f6ae7bSTakashi Sakamoto 9923e106f4fSTakashi Sakamoto desc->cycle = compute_ohci_it_cycle(*ctx_header, s->queue_size); 99369efd5c4STakashi Sakamoto 99413d11f14STakashi Sakamoto if (aware_syt && seq->syt_offset != CIP_SYT_NO_INFO) 99513d11f14STakashi Sakamoto desc->syt = compute_syt(seq->syt_offset, desc->cycle, s->transfer_delay); 99613d11f14STakashi Sakamoto else 9978070d265STakashi Sakamoto desc->syt = CIP_SYT_NO_INFO; 9988070d265STakashi Sakamoto 99969efd5c4STakashi Sakamoto desc->data_blocks = seq->data_blocks; 1000f4f6ae7bSTakashi Sakamoto 1001f4f6ae7bSTakashi Sakamoto if (s->flags & CIP_DBC_IS_END_EVENT) 1002f4f6ae7bSTakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 1003f4f6ae7bSTakashi Sakamoto 1004f4f6ae7bSTakashi Sakamoto desc->data_block_counter = dbc; 1005f4f6ae7bSTakashi Sakamoto 1006f4f6ae7bSTakashi Sakamoto if (!(s->flags & CIP_DBC_IS_END_EVENT)) 1007f4f6ae7bSTakashi Sakamoto dbc = (dbc + desc->data_blocks) & 0xff; 1008f4f6ae7bSTakashi Sakamoto 1009f4f6ae7bSTakashi Sakamoto desc->ctx_payload = s->buffer.packets[index].buffer; 1010f4f6ae7bSTakashi Sakamoto 1011f2bdee85STakashi Sakamoto seq_pos = (seq_pos + 1) % seq_size; 1012*cec371ffSTakashi Sakamoto desc = amdtp_stream_next_packet_desc(s, desc); 101369efd5c4STakashi Sakamoto 1014f4f6ae7bSTakashi Sakamoto ++ctx_header; 1015f4f6ae7bSTakashi Sakamoto } 1016f4f6ae7bSTakashi Sakamoto 1017f4f6ae7bSTakashi Sakamoto s->data_block_counter = dbc; 1018f2bdee85STakashi Sakamoto s->ctx_data.rx.seq.pos = seq_pos; 1019f4f6ae7bSTakashi Sakamoto } 1020f4f6ae7bSTakashi Sakamoto 1021fce9b013STakashi Sakamoto static inline void cancel_stream(struct amdtp_stream *s) 1022fce9b013STakashi Sakamoto { 1023fce9b013STakashi Sakamoto s->packet_index = -1; 10243b86ec63STakashi Sakamoto if (in_softirq()) 1025fce9b013STakashi Sakamoto amdtp_stream_pcm_abort(s); 1026fce9b013STakashi Sakamoto WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); 1027fce9b013STakashi Sakamoto } 1028fce9b013STakashi Sakamoto 10290f5cfcb2STakashi Sakamoto static void process_ctx_payloads(struct amdtp_stream *s, 10300f5cfcb2STakashi Sakamoto const struct pkt_desc *descs, 10310f5cfcb2STakashi Sakamoto unsigned int packets) 10320f5cfcb2STakashi Sakamoto { 10339a738ad1STakashi Sakamoto struct snd_pcm_substream *pcm; 10340f5cfcb2STakashi Sakamoto unsigned int pcm_frames; 10350f5cfcb2STakashi Sakamoto 10369a738ad1STakashi Sakamoto pcm = READ_ONCE(s->pcm); 10379a738ad1STakashi Sakamoto pcm_frames = s->process_ctx_payloads(s, descs, packets, pcm); 10389a738ad1STakashi Sakamoto if (pcm) 10390f5cfcb2STakashi Sakamoto update_pcm_pointers(s, pcm, pcm_frames); 10400f5cfcb2STakashi Sakamoto } 10410f5cfcb2STakashi Sakamoto 10429b1fcd9bSTakashi Sakamoto static void process_rx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 10439b1fcd9bSTakashi Sakamoto void *header, void *private_data) 1044d67c46b9STakashi Sakamoto { 1045d67c46b9STakashi Sakamoto struct amdtp_stream *s = private_data; 104669efd5c4STakashi Sakamoto const struct amdtp_domain *d = s->domain; 104726cd1e58STakashi Sakamoto const __be32 *ctx_header = header; 10489b1fcd9bSTakashi Sakamoto const unsigned int events_per_period = d->events_per_period; 104960dd4929STakashi Sakamoto unsigned int event_count = s->ctx_data.rx.event_count; 1050*cec371ffSTakashi Sakamoto struct pkt_desc *desc = s->pkt_descs; 1051233dbbc7STakashi Sakamoto unsigned int pkt_header_length; 1052a0e02331STakashi Sakamoto unsigned int packets; 1053d360870aSTakashi Sakamoto bool need_hw_irq; 10540dcb4efbSTakashi Sakamoto int i; 1055d67c46b9STakashi Sakamoto 1056d67c46b9STakashi Sakamoto if (s->packet_index < 0) 1057d67c46b9STakashi Sakamoto return; 1058d67c46b9STakashi Sakamoto 1059a0e02331STakashi Sakamoto // Calculate the number of packets in buffer and check XRUN. 1060a0e02331STakashi Sakamoto packets = header_length / sizeof(*ctx_header); 1061a0e02331STakashi Sakamoto 1062*cec371ffSTakashi Sakamoto generate_rx_packet_descs(s, desc, ctx_header, packets); 1063f4f6ae7bSTakashi Sakamoto 1064*cec371ffSTakashi Sakamoto process_ctx_payloads(s, desc, packets); 10655e2ece0fSTakashi Sakamoto 1066233dbbc7STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 1067233dbbc7STakashi Sakamoto pkt_header_length = IT_PKT_HEADER_SIZE_CIP; 1068233dbbc7STakashi Sakamoto else 1069233dbbc7STakashi Sakamoto pkt_header_length = 0; 1070233dbbc7STakashi Sakamoto 1071d360870aSTakashi Sakamoto if (s == d->irq_target) { 1072d360870aSTakashi Sakamoto // At NO_PERIOD_WAKEUP mode, the packets for all IT/IR contexts are processed by 1073d360870aSTakashi Sakamoto // the tasks of user process operating ALSA PCM character device by calling ioctl(2) 1074d360870aSTakashi Sakamoto // with some requests, instead of scheduled hardware IRQ of an IT context. 1075d360870aSTakashi Sakamoto struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); 1076d360870aSTakashi Sakamoto need_hw_irq = !pcm || !pcm->runtime->no_period_wakeup; 1077d360870aSTakashi Sakamoto } else { 1078d360870aSTakashi Sakamoto need_hw_irq = false; 1079d360870aSTakashi Sakamoto } 1080d360870aSTakashi Sakamoto 10815e2ece0fSTakashi Sakamoto for (i = 0; i < packets; ++i) { 10826bc1a269STakashi Sakamoto struct { 10836bc1a269STakashi Sakamoto struct fw_iso_packet params; 108467d92ee7STakashi Sakamoto __be32 header[CIP_HEADER_QUADLETS]; 10856bc1a269STakashi Sakamoto } template = { {0}, {0} }; 1086e229853dSTakashi Sakamoto bool sched_irq = false; 1087860d798cSTakashi Sakamoto 1088233dbbc7STakashi Sakamoto build_it_pkt_header(s, desc->cycle, &template.params, pkt_header_length, 1089f4f6ae7bSTakashi Sakamoto desc->data_blocks, desc->data_block_counter, 10908070d265STakashi Sakamoto desc->syt, i); 10916bc1a269STakashi Sakamoto 10922472cfb3STakashi Sakamoto if (s == s->domain->irq_target) { 1093e229853dSTakashi Sakamoto event_count += desc->data_blocks; 1094e229853dSTakashi Sakamoto if (event_count >= events_per_period) { 1095e229853dSTakashi Sakamoto event_count -= events_per_period; 1096d360870aSTakashi Sakamoto sched_irq = need_hw_irq; 1097e229853dSTakashi Sakamoto } 109860dd4929STakashi Sakamoto } 1099e229853dSTakashi Sakamoto 1100e229853dSTakashi Sakamoto if (queue_out_packet(s, &template.params, sched_irq) < 0) { 1101fce9b013STakashi Sakamoto cancel_stream(s); 1102d67c46b9STakashi Sakamoto return; 1103d67c46b9STakashi Sakamoto } 1104*cec371ffSTakashi Sakamoto 1105*cec371ffSTakashi Sakamoto desc = amdtp_stream_next_packet_desc(s, desc); 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 1186c38d8cffSTakashi Sakamoto if (d->replay.enable) 1187c38d8cffSTakashi Sakamoto s->ctx_data.rx.cache_pos = 0; 1188c38d8cffSTakashi Sakamoto 11899b1fcd9bSTakashi Sakamoto process_rx_packets(context, tstamp, header_length, ctx_header, private_data); 11909b1fcd9bSTakashi Sakamoto if (amdtp_streaming_error(s)) 11919b1fcd9bSTakashi Sakamoto return; 11929b1fcd9bSTakashi Sakamoto 11939b1fcd9bSTakashi Sakamoto if (s == d->irq_target) 11949b1fcd9bSTakashi Sakamoto s->context->callback.sc = irq_target_callback; 11959b1fcd9bSTakashi Sakamoto else 11969b1fcd9bSTakashi Sakamoto s->context->callback.sc = process_rx_packets; 11979b1fcd9bSTakashi Sakamoto } 11989b1fcd9bSTakashi Sakamoto } 11999b1fcd9bSTakashi Sakamoto 1200da3623abSTakashi Sakamoto static void process_tx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 1201da3623abSTakashi Sakamoto void *header, void *private_data) 1202d67c46b9STakashi Sakamoto { 1203d67c46b9STakashi Sakamoto struct amdtp_stream *s = private_data; 1204cc4f8e91STakashi Sakamoto __be32 *ctx_header = header; 1205*cec371ffSTakashi Sakamoto struct pkt_desc *desc = s->pkt_descs; 1206cccddec4STakashi Sakamoto unsigned int packet_count; 120773246fc4STakashi Sakamoto unsigned int desc_count; 1208753e7179STakashi Sakamoto int i; 1209753e7179STakashi Sakamoto int err; 1210d67c46b9STakashi Sakamoto 1211d67c46b9STakashi Sakamoto if (s->packet_index < 0) 1212d67c46b9STakashi Sakamoto return; 1213d67c46b9STakashi Sakamoto 1214a0e02331STakashi Sakamoto // Calculate the number of packets in buffer and check XRUN. 1215cccddec4STakashi Sakamoto packet_count = header_length / s->ctx_data.tx.ctx_header_size; 1216f90e2dedSTakashi Sakamoto 121773246fc4STakashi Sakamoto desc_count = 0; 1218*cec371ffSTakashi Sakamoto err = generate_tx_packet_descs(s, desc, ctx_header, packet_count, &desc_count); 1219753e7179STakashi Sakamoto if (err < 0) { 1220753e7179STakashi Sakamoto if (err != -EAGAIN) { 1221753e7179STakashi Sakamoto cancel_stream(s); 1222753e7179STakashi Sakamoto return; 1223753e7179STakashi Sakamoto } 12245e2ece0fSTakashi Sakamoto } else { 1225f9e5ecdfSTakashi Sakamoto struct amdtp_domain *d = s->domain; 1226f9e5ecdfSTakashi Sakamoto 1227*cec371ffSTakashi Sakamoto process_ctx_payloads(s, desc, desc_count); 1228f9e5ecdfSTakashi Sakamoto 1229f9e5ecdfSTakashi Sakamoto if (d->replay.enable) 1230*cec371ffSTakashi Sakamoto cache_seq(s, desc, desc_count); 12315e2ece0fSTakashi Sakamoto } 12325e2ece0fSTakashi Sakamoto 1233cccddec4STakashi Sakamoto for (i = 0; i < packet_count; ++i) { 12345e2ece0fSTakashi Sakamoto struct fw_iso_packet params = {0}; 1235a35463d1STakashi Sakamoto 123660dd4929STakashi Sakamoto if (queue_in_packet(s, ¶ms) < 0) { 1237753e7179STakashi Sakamoto cancel_stream(s); 1238753e7179STakashi Sakamoto return; 1239753e7179STakashi Sakamoto } 1240d67c46b9STakashi Sakamoto } 1241d67c46b9STakashi Sakamoto } 1242d67c46b9STakashi Sakamoto 1243da3623abSTakashi Sakamoto static void drop_tx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, 1244da3623abSTakashi Sakamoto void *header, void *private_data) 1245da3623abSTakashi Sakamoto { 1246da3623abSTakashi Sakamoto struct amdtp_stream *s = private_data; 1247da3623abSTakashi Sakamoto const __be32 *ctx_header = header; 1248da3623abSTakashi Sakamoto unsigned int packets; 1249da3623abSTakashi Sakamoto unsigned int cycle; 1250da3623abSTakashi Sakamoto int i; 1251da3623abSTakashi Sakamoto 1252da3623abSTakashi Sakamoto if (s->packet_index < 0) 1253da3623abSTakashi Sakamoto return; 1254da3623abSTakashi Sakamoto 1255da3623abSTakashi Sakamoto packets = header_length / s->ctx_data.tx.ctx_header_size; 1256da3623abSTakashi Sakamoto 1257da3623abSTakashi Sakamoto ctx_header += (packets - 1) * s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); 1258da3623abSTakashi Sakamoto cycle = compute_ohci_cycle_count(ctx_header[1]); 1259da3623abSTakashi Sakamoto s->next_cycle = increment_ohci_cycle_count(cycle, 1); 1260da3623abSTakashi Sakamoto 1261da3623abSTakashi Sakamoto for (i = 0; i < packets; ++i) { 1262da3623abSTakashi Sakamoto struct fw_iso_packet params = {0}; 1263da3623abSTakashi Sakamoto 1264da3623abSTakashi Sakamoto if (queue_in_packet(s, ¶ms) < 0) { 1265da3623abSTakashi Sakamoto cancel_stream(s); 1266da3623abSTakashi Sakamoto return; 1267da3623abSTakashi Sakamoto } 1268da3623abSTakashi Sakamoto } 1269da3623abSTakashi Sakamoto } 1270da3623abSTakashi Sakamoto 1271da3623abSTakashi Sakamoto static void process_tx_packets_intermediately(struct fw_iso_context *context, u32 tstamp, 1272da3623abSTakashi Sakamoto size_t header_length, void *header, void *private_data) 1273da3623abSTakashi Sakamoto { 1274da3623abSTakashi Sakamoto struct amdtp_stream *s = private_data; 1275da3623abSTakashi Sakamoto struct amdtp_domain *d = s->domain; 1276da3623abSTakashi Sakamoto __be32 *ctx_header; 1277da3623abSTakashi Sakamoto unsigned int packets; 1278da3623abSTakashi Sakamoto unsigned int offset; 1279da3623abSTakashi Sakamoto 1280da3623abSTakashi Sakamoto if (s->packet_index < 0) 1281da3623abSTakashi Sakamoto return; 1282da3623abSTakashi Sakamoto 1283da3623abSTakashi Sakamoto packets = header_length / s->ctx_data.tx.ctx_header_size; 1284da3623abSTakashi Sakamoto 1285da3623abSTakashi Sakamoto offset = 0; 1286da3623abSTakashi Sakamoto ctx_header = header; 1287da3623abSTakashi Sakamoto while (offset < packets) { 1288da3623abSTakashi Sakamoto unsigned int cycle = compute_ohci_cycle_count(ctx_header[1]); 1289da3623abSTakashi Sakamoto 1290da3623abSTakashi Sakamoto if (compare_ohci_cycle_count(cycle, d->processing_cycle.tx_start) >= 0) 1291da3623abSTakashi Sakamoto break; 1292da3623abSTakashi Sakamoto 1293da3623abSTakashi Sakamoto ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(__be32); 1294da3623abSTakashi Sakamoto ++offset; 1295da3623abSTakashi Sakamoto } 1296da3623abSTakashi Sakamoto 1297da3623abSTakashi Sakamoto ctx_header = header; 1298da3623abSTakashi Sakamoto 1299da3623abSTakashi Sakamoto if (offset > 0) { 1300da3623abSTakashi Sakamoto size_t length = s->ctx_data.tx.ctx_header_size * offset; 1301da3623abSTakashi Sakamoto 1302da3623abSTakashi Sakamoto drop_tx_packets(context, tstamp, length, ctx_header, s); 1303da3623abSTakashi Sakamoto if (amdtp_streaming_error(s)) 1304da3623abSTakashi Sakamoto return; 1305da3623abSTakashi Sakamoto 1306da3623abSTakashi Sakamoto ctx_header += length / sizeof(*ctx_header); 1307da3623abSTakashi Sakamoto header_length -= length; 1308da3623abSTakashi Sakamoto } 1309da3623abSTakashi Sakamoto 1310da3623abSTakashi Sakamoto if (offset < packets) { 1311bdaedca7STakashi Sakamoto s->ready_processing = true; 1312bdaedca7STakashi Sakamoto wake_up(&s->ready_wait); 1313bdaedca7STakashi Sakamoto 1314da3623abSTakashi Sakamoto process_tx_packets(context, tstamp, header_length, ctx_header, s); 1315da3623abSTakashi Sakamoto if (amdtp_streaming_error(s)) 1316da3623abSTakashi Sakamoto return; 1317da3623abSTakashi Sakamoto 1318da3623abSTakashi Sakamoto context->callback.sc = process_tx_packets; 1319da3623abSTakashi Sakamoto } 1320da3623abSTakashi Sakamoto } 1321da3623abSTakashi Sakamoto 1322fb25dcc8STakashi Sakamoto static void drop_tx_packets_initially(struct fw_iso_context *context, u32 tstamp, 1323fb25dcc8STakashi Sakamoto size_t header_length, void *header, void *private_data) 1324fb25dcc8STakashi Sakamoto { 1325fb25dcc8STakashi Sakamoto struct amdtp_stream *s = private_data; 1326fb25dcc8STakashi Sakamoto struct amdtp_domain *d = s->domain; 1327fb25dcc8STakashi Sakamoto __be32 *ctx_header; 1328fb25dcc8STakashi Sakamoto unsigned int count; 1329fb25dcc8STakashi Sakamoto unsigned int events; 1330fb25dcc8STakashi Sakamoto int i; 1331fb25dcc8STakashi Sakamoto 1332fb25dcc8STakashi Sakamoto if (s->packet_index < 0) 1333fb25dcc8STakashi Sakamoto return; 1334fb25dcc8STakashi Sakamoto 1335fb25dcc8STakashi Sakamoto count = header_length / s->ctx_data.tx.ctx_header_size; 1336fb25dcc8STakashi Sakamoto 1337fb25dcc8STakashi Sakamoto // Attempt to detect any event in the batch of packets. 1338fb25dcc8STakashi Sakamoto events = 0; 1339fb25dcc8STakashi Sakamoto ctx_header = header; 1340fb25dcc8STakashi Sakamoto for (i = 0; i < count; ++i) { 1341fb25dcc8STakashi Sakamoto unsigned int payload_quads = 1342fb25dcc8STakashi Sakamoto (be32_to_cpu(*ctx_header) >> ISO_DATA_LENGTH_SHIFT) / sizeof(__be32); 1343fb25dcc8STakashi Sakamoto unsigned int data_blocks; 1344fb25dcc8STakashi Sakamoto 1345fb25dcc8STakashi Sakamoto if (s->flags & CIP_NO_HEADER) { 1346fb25dcc8STakashi Sakamoto data_blocks = payload_quads / s->data_block_quadlets; 1347fb25dcc8STakashi Sakamoto } else { 1348fb25dcc8STakashi Sakamoto __be32 *cip_headers = ctx_header + IR_CTX_HEADER_DEFAULT_QUADLETS; 1349fb25dcc8STakashi Sakamoto 1350fb25dcc8STakashi Sakamoto if (payload_quads < CIP_HEADER_QUADLETS) { 1351fb25dcc8STakashi Sakamoto data_blocks = 0; 1352fb25dcc8STakashi Sakamoto } else { 1353fb25dcc8STakashi Sakamoto payload_quads -= CIP_HEADER_QUADLETS; 1354fb25dcc8STakashi Sakamoto 1355fb25dcc8STakashi Sakamoto if (s->flags & CIP_UNAWARE_SYT) { 1356fb25dcc8STakashi Sakamoto data_blocks = payload_quads / s->data_block_quadlets; 1357fb25dcc8STakashi Sakamoto } else { 1358fb25dcc8STakashi Sakamoto u32 cip1 = be32_to_cpu(cip_headers[1]); 1359fb25dcc8STakashi Sakamoto 1360fb25dcc8STakashi Sakamoto // NODATA packet can includes any data blocks but they are 1361fb25dcc8STakashi Sakamoto // not available as event. 1362fb25dcc8STakashi Sakamoto if ((cip1 & CIP_NO_DATA) == CIP_NO_DATA) 1363fb25dcc8STakashi Sakamoto data_blocks = 0; 1364fb25dcc8STakashi Sakamoto else 1365fb25dcc8STakashi Sakamoto data_blocks = payload_quads / s->data_block_quadlets; 1366fb25dcc8STakashi Sakamoto } 1367fb25dcc8STakashi Sakamoto } 1368fb25dcc8STakashi Sakamoto } 1369fb25dcc8STakashi Sakamoto 1370fb25dcc8STakashi Sakamoto events += data_blocks; 1371fb25dcc8STakashi Sakamoto 1372fb25dcc8STakashi Sakamoto ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(__be32); 1373fb25dcc8STakashi Sakamoto } 1374fb25dcc8STakashi Sakamoto 1375fb25dcc8STakashi Sakamoto drop_tx_packets(context, tstamp, header_length, header, s); 1376fb25dcc8STakashi Sakamoto 1377fb25dcc8STakashi Sakamoto if (events > 0) 1378fb25dcc8STakashi Sakamoto s->ctx_data.tx.event_starts = true; 1379fb25dcc8STakashi Sakamoto 1380fb25dcc8STakashi Sakamoto // Decide the cycle count to begin processing content of packet in IR contexts. 1381fb25dcc8STakashi Sakamoto { 1382fb25dcc8STakashi Sakamoto unsigned int stream_count = 0; 1383fb25dcc8STakashi Sakamoto unsigned int event_starts_count = 0; 1384fb25dcc8STakashi Sakamoto unsigned int cycle = UINT_MAX; 1385fb25dcc8STakashi Sakamoto 1386fb25dcc8STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1387fb25dcc8STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1388fb25dcc8STakashi Sakamoto ++stream_count; 1389fb25dcc8STakashi Sakamoto if (s->ctx_data.tx.event_starts) 1390fb25dcc8STakashi Sakamoto ++event_starts_count; 1391fb25dcc8STakashi Sakamoto } 1392fb25dcc8STakashi Sakamoto } 1393fb25dcc8STakashi Sakamoto 1394fb25dcc8STakashi Sakamoto if (stream_count == event_starts_count) { 1395fb25dcc8STakashi Sakamoto unsigned int next_cycle; 1396fb25dcc8STakashi Sakamoto 1397fb25dcc8STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1398fb25dcc8STakashi Sakamoto if (s->direction != AMDTP_IN_STREAM) 1399fb25dcc8STakashi Sakamoto continue; 1400fb25dcc8STakashi Sakamoto 1401fb25dcc8STakashi Sakamoto next_cycle = increment_ohci_cycle_count(s->next_cycle, 1402fb25dcc8STakashi Sakamoto d->processing_cycle.tx_init_skip); 1403fb25dcc8STakashi Sakamoto if (cycle == UINT_MAX || 1404fb25dcc8STakashi Sakamoto compare_ohci_cycle_count(next_cycle, cycle) > 0) 1405fb25dcc8STakashi Sakamoto cycle = next_cycle; 1406fb25dcc8STakashi Sakamoto 1407fb25dcc8STakashi Sakamoto s->context->callback.sc = process_tx_packets_intermediately; 1408fb25dcc8STakashi Sakamoto } 1409fb25dcc8STakashi Sakamoto 1410fb25dcc8STakashi Sakamoto d->processing_cycle.tx_start = cycle; 1411fb25dcc8STakashi Sakamoto } 1412fb25dcc8STakashi Sakamoto } 1413fb25dcc8STakashi Sakamoto } 1414fb25dcc8STakashi Sakamoto 14159b1fcd9bSTakashi Sakamoto static void process_ctxs_in_domain(struct amdtp_domain *d) 141660dd4929STakashi Sakamoto { 141760dd4929STakashi Sakamoto struct amdtp_stream *s; 141860dd4929STakashi Sakamoto 141960dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 14209b1fcd9bSTakashi Sakamoto if (s != d->irq_target && amdtp_stream_running(s)) 142160dd4929STakashi Sakamoto fw_iso_context_flush_completions(s->context); 14229b1fcd9bSTakashi Sakamoto 142360dd4929STakashi Sakamoto if (amdtp_streaming_error(s)) 142460dd4929STakashi Sakamoto goto error; 142560dd4929STakashi Sakamoto } 142660dd4929STakashi Sakamoto 142760dd4929STakashi Sakamoto return; 142860dd4929STakashi Sakamoto error: 14299b1fcd9bSTakashi Sakamoto if (amdtp_stream_running(d->irq_target)) 14309b1fcd9bSTakashi Sakamoto cancel_stream(d->irq_target); 143160dd4929STakashi Sakamoto 143260dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 143360dd4929STakashi Sakamoto if (amdtp_stream_running(s)) 143460dd4929STakashi Sakamoto cancel_stream(s); 143560dd4929STakashi Sakamoto } 143660dd4929STakashi Sakamoto } 143760dd4929STakashi Sakamoto 14389b1fcd9bSTakashi Sakamoto static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, 14399b1fcd9bSTakashi Sakamoto void *header, void *private_data) 14409b1fcd9bSTakashi Sakamoto { 14419b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 14429b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 14439b1fcd9bSTakashi Sakamoto 14449b1fcd9bSTakashi Sakamoto process_rx_packets(context, tstamp, header_length, header, private_data); 14459b1fcd9bSTakashi Sakamoto process_ctxs_in_domain(d); 14469b1fcd9bSTakashi Sakamoto } 14479b1fcd9bSTakashi Sakamoto 14489b1fcd9bSTakashi Sakamoto static void irq_target_callback_intermediately(struct fw_iso_context *context, u32 tstamp, 14499b1fcd9bSTakashi Sakamoto size_t header_length, void *header, void *private_data) 14509b1fcd9bSTakashi Sakamoto { 14519b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 14529b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 14539b1fcd9bSTakashi Sakamoto 14549b1fcd9bSTakashi Sakamoto process_rx_packets_intermediately(context, tstamp, header_length, header, private_data); 14559b1fcd9bSTakashi Sakamoto process_ctxs_in_domain(d); 14569b1fcd9bSTakashi Sakamoto } 14579b1fcd9bSTakashi Sakamoto 14589b1fcd9bSTakashi Sakamoto static void irq_target_callback_skip(struct fw_iso_context *context, u32 tstamp, 14599b1fcd9bSTakashi Sakamoto size_t header_length, void *header, void *private_data) 14609b1fcd9bSTakashi Sakamoto { 14619b1fcd9bSTakashi Sakamoto struct amdtp_stream *s = private_data; 14629b1fcd9bSTakashi Sakamoto struct amdtp_domain *d = s->domain; 146339c2649cSTakashi Sakamoto bool ready_to_start; 14649b1fcd9bSTakashi Sakamoto 14659b1fcd9bSTakashi Sakamoto skip_rx_packets(context, tstamp, header_length, header, private_data); 14669b1fcd9bSTakashi Sakamoto process_ctxs_in_domain(d); 14679b1fcd9bSTakashi Sakamoto 14682f21a177STakashi Sakamoto if (d->replay.enable && !d->replay.on_the_fly) { 146939c2649cSTakashi Sakamoto unsigned int rx_count = 0; 147039c2649cSTakashi Sakamoto unsigned int rx_ready_count = 0; 147139c2649cSTakashi Sakamoto struct amdtp_stream *rx; 147239c2649cSTakashi Sakamoto 147339c2649cSTakashi Sakamoto list_for_each_entry(rx, &d->streams, list) { 147439c2649cSTakashi Sakamoto struct amdtp_stream *tx; 147539c2649cSTakashi Sakamoto unsigned int cached_cycles; 147639c2649cSTakashi Sakamoto 147739c2649cSTakashi Sakamoto if (rx->direction != AMDTP_OUT_STREAM) 147839c2649cSTakashi Sakamoto continue; 147939c2649cSTakashi Sakamoto ++rx_count; 148039c2649cSTakashi Sakamoto 148139c2649cSTakashi Sakamoto tx = rx->ctx_data.rx.replay_target; 148239c2649cSTakashi Sakamoto cached_cycles = calculate_cached_cycle_count(tx, 0); 148339c2649cSTakashi Sakamoto if (cached_cycles > tx->ctx_data.tx.cache.size / 2) 148439c2649cSTakashi Sakamoto ++rx_ready_count; 148539c2649cSTakashi Sakamoto } 148639c2649cSTakashi Sakamoto 148739c2649cSTakashi Sakamoto ready_to_start = (rx_count == rx_ready_count); 148839c2649cSTakashi Sakamoto } else { 148939c2649cSTakashi Sakamoto ready_to_start = true; 149039c2649cSTakashi Sakamoto } 149139c2649cSTakashi Sakamoto 14929b1fcd9bSTakashi Sakamoto // Decide the cycle count to begin processing content of packet in IT contexts. All of IT 14939b1fcd9bSTakashi Sakamoto // contexts are expected to start and get callback when reaching here. 149439c2649cSTakashi Sakamoto if (ready_to_start) { 149539c2649cSTakashi Sakamoto unsigned int cycle = s->next_cycle; 14969b1fcd9bSTakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 14979b1fcd9bSTakashi Sakamoto if (s->direction != AMDTP_OUT_STREAM) 14989b1fcd9bSTakashi Sakamoto continue; 14999b1fcd9bSTakashi Sakamoto 15009b1fcd9bSTakashi Sakamoto if (compare_ohci_cycle_count(s->next_cycle, cycle) > 0) 15019b1fcd9bSTakashi Sakamoto cycle = s->next_cycle; 15029b1fcd9bSTakashi Sakamoto 15039b1fcd9bSTakashi Sakamoto if (s == d->irq_target) 15049b1fcd9bSTakashi Sakamoto s->context->callback.sc = irq_target_callback_intermediately; 15059b1fcd9bSTakashi Sakamoto else 15069b1fcd9bSTakashi Sakamoto s->context->callback.sc = process_rx_packets_intermediately; 15079b1fcd9bSTakashi Sakamoto } 15089b1fcd9bSTakashi Sakamoto 15099b1fcd9bSTakashi Sakamoto d->processing_cycle.rx_start = cycle; 15109b1fcd9bSTakashi Sakamoto } 151139c2649cSTakashi Sakamoto } 15129b1fcd9bSTakashi Sakamoto 1513b7c7699bSTakashi Sakamoto // This is executed one time. For in-stream, first packet has come. For out-stream, prepared to 1514b7c7699bSTakashi Sakamoto // transmit first packet. 1515d67c46b9STakashi Sakamoto static void amdtp_stream_first_callback(struct fw_iso_context *context, 151673fc7f08STakashi Sakamoto u32 tstamp, size_t header_length, 1517d67c46b9STakashi Sakamoto void *header, void *private_data) 1518d67c46b9STakashi Sakamoto { 1519d67c46b9STakashi Sakamoto struct amdtp_stream *s = private_data; 1520da3623abSTakashi Sakamoto struct amdtp_domain *d = s->domain; 1521d67c46b9STakashi Sakamoto 1522cc4f8e91STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1523fb25dcc8STakashi Sakamoto context->callback.sc = drop_tx_packets_initially; 1524a04513f8STakashi Sakamoto } else { 1525da3623abSTakashi Sakamoto if (s == d->irq_target) 15269b1fcd9bSTakashi Sakamoto context->callback.sc = irq_target_callback_skip; 15272472cfb3STakashi Sakamoto else 15289b1fcd9bSTakashi Sakamoto context->callback.sc = skip_rx_packets; 1529a04513f8STakashi Sakamoto } 1530a04513f8STakashi Sakamoto 153173fc7f08STakashi Sakamoto context->callback.sc(context, tstamp, header_length, header, s); 1532d67c46b9STakashi Sakamoto } 1533d67c46b9STakashi Sakamoto 1534d67c46b9STakashi Sakamoto /** 1535d67c46b9STakashi Sakamoto * amdtp_stream_start - start transferring packets 1536d67c46b9STakashi Sakamoto * @s: the AMDTP stream to start 1537d67c46b9STakashi Sakamoto * @channel: the isochronous channel on the bus 1538d67c46b9STakashi Sakamoto * @speed: firewire speed code 1539af86b0b1STakashi Sakamoto * @queue_size: The number of packets in the queue. 1540af86b0b1STakashi Sakamoto * @idle_irq_interval: the interval to queue packet during initial state. 1541d67c46b9STakashi Sakamoto * 1542d67c46b9STakashi Sakamoto * The stream cannot be started until it has been configured with 1543d67c46b9STakashi Sakamoto * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI 1544d67c46b9STakashi Sakamoto * device can be started. 1545d67c46b9STakashi Sakamoto */ 1546a0e02331STakashi Sakamoto static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, 1547bd165079STakashi Sakamoto unsigned int queue_size, unsigned int idle_irq_interval) 1548d67c46b9STakashi Sakamoto { 15492472cfb3STakashi Sakamoto bool is_irq_target = (s == s->domain->irq_target); 1550d3d10a4aSTakashi Sakamoto unsigned int ctx_header_size; 1551f11453c7STakashi Sakamoto unsigned int max_ctx_payload_size; 1552d67c46b9STakashi Sakamoto enum dma_data_direction dir; 1553*cec371ffSTakashi Sakamoto struct pkt_desc *descs; 1554*cec371ffSTakashi Sakamoto int i, type, tag, err; 1555d67c46b9STakashi Sakamoto 1556d67c46b9STakashi Sakamoto mutex_lock(&s->mutex); 1557d67c46b9STakashi Sakamoto 1558d67c46b9STakashi Sakamoto if (WARN_ON(amdtp_stream_running(s) || 1559d67c46b9STakashi Sakamoto (s->data_block_quadlets < 1))) { 1560d67c46b9STakashi Sakamoto err = -EBADFD; 1561d67c46b9STakashi Sakamoto goto err_unlock; 1562d67c46b9STakashi Sakamoto } 1563d67c46b9STakashi Sakamoto 1564d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 156560dd4929STakashi Sakamoto // NOTE: IT context should be used for constant IRQ. 156660dd4929STakashi Sakamoto if (is_irq_target) { 156760dd4929STakashi Sakamoto err = -EINVAL; 156860dd4929STakashi Sakamoto goto err_unlock; 156960dd4929STakashi Sakamoto } 157060dd4929STakashi Sakamoto 1571d67c46b9STakashi Sakamoto s->data_block_counter = UINT_MAX; 1572d3d10a4aSTakashi Sakamoto } else { 1573d67c46b9STakashi Sakamoto s->data_block_counter = 0; 1574d3d10a4aSTakashi Sakamoto } 1575d67c46b9STakashi Sakamoto 15761be4f21dSTakashi Sakamoto // initialize packet buffer. 1577d67c46b9STakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1578d67c46b9STakashi Sakamoto dir = DMA_FROM_DEVICE; 1579d67c46b9STakashi Sakamoto type = FW_ISO_CONTEXT_RECEIVE; 1580c75f3678STakashi Sakamoto if (!(s->flags & CIP_NO_HEADER)) 1581f11453c7STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_CIP; 1582c75f3678STakashi Sakamoto else 1583f11453c7STakashi Sakamoto ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; 1584d67c46b9STakashi Sakamoto } else { 1585d67c46b9STakashi Sakamoto dir = DMA_TO_DEVICE; 1586d67c46b9STakashi Sakamoto type = FW_ISO_CONTEXT_TRANSMIT; 1587df9160b9STakashi Sakamoto ctx_header_size = 0; // No effect for IT context. 1588b18f0cfaSTakashi Sakamoto } 1589c75f3678STakashi Sakamoto max_ctx_payload_size = amdtp_stream_get_max_ctx_payload_size(s); 1590f11453c7STakashi Sakamoto 1591c75f3678STakashi Sakamoto err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size, max_ctx_payload_size, dir); 1592d67c46b9STakashi Sakamoto if (err < 0) 1593d67c46b9STakashi Sakamoto goto err_unlock; 1594af86b0b1STakashi Sakamoto s->queue_size = queue_size; 159560dd4929STakashi Sakamoto 1596d67c46b9STakashi Sakamoto s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, 1597d3d10a4aSTakashi Sakamoto type, channel, speed, ctx_header_size, 15982472cfb3STakashi Sakamoto amdtp_stream_first_callback, s); 1599d67c46b9STakashi Sakamoto if (IS_ERR(s->context)) { 1600d67c46b9STakashi Sakamoto err = PTR_ERR(s->context); 1601d67c46b9STakashi Sakamoto if (err == -EBUSY) 1602d67c46b9STakashi Sakamoto dev_err(&s->unit->device, 1603d67c46b9STakashi Sakamoto "no free stream on this controller\n"); 1604d67c46b9STakashi Sakamoto goto err_buffer; 1605d67c46b9STakashi Sakamoto } 1606d67c46b9STakashi Sakamoto 1607d67c46b9STakashi Sakamoto amdtp_stream_update(s); 1608d67c46b9STakashi Sakamoto 1609d3d10a4aSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 1610f11453c7STakashi Sakamoto s->ctx_data.tx.max_ctx_payload_length = max_ctx_payload_size; 1611d3d10a4aSTakashi Sakamoto s->ctx_data.tx.ctx_header_size = ctx_header_size; 1612fb25dcc8STakashi Sakamoto s->ctx_data.tx.event_starts = false; 1613f9e5ecdfSTakashi Sakamoto 1614f9e5ecdfSTakashi Sakamoto if (s->domain->replay.enable) { 1615f9e5ecdfSTakashi Sakamoto // struct fw_iso_context.drop_overflow_headers is false therefore it's 1616f9e5ecdfSTakashi Sakamoto // possible to cache much unexpectedly. 1617f9e5ecdfSTakashi Sakamoto s->ctx_data.tx.cache.size = max_t(unsigned int, s->syt_interval * 2, 1618f9e5ecdfSTakashi Sakamoto queue_size * 3 / 2); 1619cccddec4STakashi Sakamoto s->ctx_data.tx.cache.pos = 0; 1620f9e5ecdfSTakashi Sakamoto s->ctx_data.tx.cache.descs = kcalloc(s->ctx_data.tx.cache.size, 1621f9e5ecdfSTakashi Sakamoto sizeof(*s->ctx_data.tx.cache.descs), GFP_KERNEL); 16228b6e2193SDan Carpenter if (!s->ctx_data.tx.cache.descs) { 16238b6e2193SDan Carpenter err = -ENOMEM; 1624f9e5ecdfSTakashi Sakamoto goto err_context; 1625f9e5ecdfSTakashi Sakamoto } 16268b6e2193SDan Carpenter } 1627bd165079STakashi Sakamoto } else { 16286f24bb8aSTakashi Sakamoto static const struct { 16296f24bb8aSTakashi Sakamoto unsigned int data_block; 16306f24bb8aSTakashi Sakamoto unsigned int syt_offset; 16316f24bb8aSTakashi Sakamoto } *entry, initial_state[] = { 16326f24bb8aSTakashi Sakamoto [CIP_SFC_32000] = { 4, 3072 }, 16336f24bb8aSTakashi Sakamoto [CIP_SFC_48000] = { 6, 1024 }, 16346f24bb8aSTakashi Sakamoto [CIP_SFC_96000] = { 12, 1024 }, 16356f24bb8aSTakashi Sakamoto [CIP_SFC_192000] = { 24, 1024 }, 16366f24bb8aSTakashi Sakamoto [CIP_SFC_44100] = { 0, 67 }, 16376f24bb8aSTakashi Sakamoto [CIP_SFC_88200] = { 0, 67 }, 16386f24bb8aSTakashi Sakamoto [CIP_SFC_176400] = { 0, 67 }, 16396f24bb8aSTakashi Sakamoto }; 16406f24bb8aSTakashi Sakamoto 16416f24bb8aSTakashi Sakamoto s->ctx_data.rx.seq.descs = kcalloc(queue_size, sizeof(*s->ctx_data.rx.seq.descs), GFP_KERNEL); 16428b6e2193SDan Carpenter if (!s->ctx_data.rx.seq.descs) { 16438b6e2193SDan Carpenter err = -ENOMEM; 16446f24bb8aSTakashi Sakamoto goto err_context; 16458b6e2193SDan Carpenter } 16466f24bb8aSTakashi Sakamoto s->ctx_data.rx.seq.size = queue_size; 1647119c446aSTakashi Sakamoto s->ctx_data.rx.seq.pos = 0; 16486f24bb8aSTakashi Sakamoto 16496f24bb8aSTakashi Sakamoto entry = &initial_state[s->sfc]; 16506f24bb8aSTakashi Sakamoto s->ctx_data.rx.data_block_state = entry->data_block; 16516f24bb8aSTakashi Sakamoto s->ctx_data.rx.syt_offset_state = entry->syt_offset; 16526f24bb8aSTakashi Sakamoto s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE; 16536f24bb8aSTakashi Sakamoto 1654bd165079STakashi Sakamoto s->ctx_data.rx.event_count = 0; 1655d3d10a4aSTakashi Sakamoto } 165652759c09STakashi Sakamoto 16573b196c39STakashi Sakamoto if (s->flags & CIP_NO_HEADER) 16583b196c39STakashi Sakamoto s->tag = TAG_NO_CIP_HEADER; 16593b196c39STakashi Sakamoto else 16603b196c39STakashi Sakamoto s->tag = TAG_CIP; 16613b196c39STakashi Sakamoto 1662*cec371ffSTakashi Sakamoto descs = kcalloc(s->queue_size, sizeof(*descs), GFP_KERNEL); 1663*cec371ffSTakashi Sakamoto if (!descs) { 166404130cf8STakashi Sakamoto err = -ENOMEM; 166504130cf8STakashi Sakamoto goto err_context; 166604130cf8STakashi Sakamoto } 1667*cec371ffSTakashi Sakamoto s->pkt_descs = descs; 1668*cec371ffSTakashi Sakamoto 1669*cec371ffSTakashi Sakamoto INIT_LIST_HEAD(&s->packet_descs_list); 1670*cec371ffSTakashi Sakamoto for (i = 0; i < s->queue_size; ++i) { 1671*cec371ffSTakashi Sakamoto INIT_LIST_HEAD(&descs->link); 1672*cec371ffSTakashi Sakamoto list_add_tail(&descs->link, &s->packet_descs_list); 1673*cec371ffSTakashi Sakamoto ++descs; 1674*cec371ffSTakashi Sakamoto } 167504130cf8STakashi Sakamoto 1676d67c46b9STakashi Sakamoto s->packet_index = 0; 1677d67c46b9STakashi Sakamoto do { 16786007bf54STakashi Sakamoto struct fw_iso_packet params; 1679e229853dSTakashi Sakamoto 1680b18f0cfaSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 168160dd4929STakashi Sakamoto err = queue_in_packet(s, ¶ms); 1682b18f0cfaSTakashi Sakamoto } else { 168360dd4929STakashi Sakamoto bool sched_irq = false; 168460dd4929STakashi Sakamoto 1685b18f0cfaSTakashi Sakamoto params.header_length = 0; 1686b18f0cfaSTakashi Sakamoto params.payload_length = 0; 168760dd4929STakashi Sakamoto 168860dd4929STakashi Sakamoto if (is_irq_target) { 168960dd4929STakashi Sakamoto sched_irq = !((s->packet_index + 1) % 169060dd4929STakashi Sakamoto idle_irq_interval); 169160dd4929STakashi Sakamoto } 169260dd4929STakashi Sakamoto 1693e229853dSTakashi Sakamoto err = queue_out_packet(s, ¶ms, sched_irq); 1694b18f0cfaSTakashi Sakamoto } 1695d67c46b9STakashi Sakamoto if (err < 0) 169604130cf8STakashi Sakamoto goto err_pkt_descs; 1697d67c46b9STakashi Sakamoto } while (s->packet_index > 0); 1698d67c46b9STakashi Sakamoto 1699d67c46b9STakashi Sakamoto /* NOTE: TAG1 matches CIP. This just affects in stream. */ 1700d67c46b9STakashi Sakamoto tag = FW_ISO_CONTEXT_MATCH_TAG1; 17013b196c39STakashi Sakamoto if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER)) 1702d67c46b9STakashi Sakamoto tag |= FW_ISO_CONTEXT_MATCH_TAG0; 1703d67c46b9STakashi Sakamoto 1704bdaedca7STakashi Sakamoto s->ready_processing = false; 1705bd165079STakashi Sakamoto err = fw_iso_context_start(s->context, -1, 0, tag); 1706d67c46b9STakashi Sakamoto if (err < 0) 170704130cf8STakashi Sakamoto goto err_pkt_descs; 1708d67c46b9STakashi Sakamoto 1709d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1710d67c46b9STakashi Sakamoto 1711d67c46b9STakashi Sakamoto return 0; 171204130cf8STakashi Sakamoto err_pkt_descs: 171304130cf8STakashi Sakamoto kfree(s->pkt_descs); 1714*cec371ffSTakashi Sakamoto s->pkt_descs = NULL; 1715d67c46b9STakashi Sakamoto err_context: 1716f9e5ecdfSTakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM) { 17176f24bb8aSTakashi Sakamoto kfree(s->ctx_data.rx.seq.descs); 1718f9e5ecdfSTakashi Sakamoto } else { 1719f9e5ecdfSTakashi Sakamoto if (s->domain->replay.enable) 1720f9e5ecdfSTakashi Sakamoto kfree(s->ctx_data.tx.cache.descs); 1721f9e5ecdfSTakashi Sakamoto } 1722d67c46b9STakashi Sakamoto fw_iso_context_destroy(s->context); 1723d67c46b9STakashi Sakamoto s->context = ERR_PTR(-1); 1724d67c46b9STakashi Sakamoto err_buffer: 1725d67c46b9STakashi Sakamoto iso_packets_buffer_destroy(&s->buffer, s->unit); 1726d67c46b9STakashi Sakamoto err_unlock: 1727d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1728d67c46b9STakashi Sakamoto 1729d67c46b9STakashi Sakamoto return err; 1730d67c46b9STakashi Sakamoto } 1731d67c46b9STakashi Sakamoto 1732d67c46b9STakashi Sakamoto /** 1733f890f9a0STakashi Sakamoto * amdtp_domain_stream_pcm_pointer - get the PCM buffer position 1734f890f9a0STakashi Sakamoto * @d: the AMDTP domain. 1735d67c46b9STakashi Sakamoto * @s: the AMDTP stream that transports the PCM data 1736d67c46b9STakashi Sakamoto * 1737d67c46b9STakashi Sakamoto * Returns the current buffer position, in frames. 1738d67c46b9STakashi Sakamoto */ 1739f890f9a0STakashi Sakamoto unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, 1740f890f9a0STakashi Sakamoto struct amdtp_stream *s) 1741d67c46b9STakashi Sakamoto { 1742f890f9a0STakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 1743f890f9a0STakashi Sakamoto 17447ba5ca32STakashi Sakamoto // Process isochronous packets queued till recent isochronous cycle to handle PCM frames. 1745f890f9a0STakashi Sakamoto if (irq_target && amdtp_stream_running(irq_target)) { 17467ba5ca32STakashi Sakamoto // In software IRQ context, the call causes dead-lock to disable the tasklet 17477ba5ca32STakashi Sakamoto // synchronously. 17483b86ec63STakashi Sakamoto if (!in_softirq()) 1749f890f9a0STakashi Sakamoto fw_iso_context_flush_completions(irq_target->context); 1750f890f9a0STakashi Sakamoto } 1751d67c46b9STakashi Sakamoto 17526aa7de05SMark Rutland return READ_ONCE(s->pcm_buffer_pointer); 1753d67c46b9STakashi Sakamoto } 1754f890f9a0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_pointer); 1755d67c46b9STakashi Sakamoto 1756d67c46b9STakashi Sakamoto /** 1757e6dcc92fSTakashi Sakamoto * amdtp_domain_stream_pcm_ack - acknowledge queued PCM frames 1758e6dcc92fSTakashi Sakamoto * @d: the AMDTP domain. 1759875becf8STakashi Sakamoto * @s: the AMDTP stream that transfers the PCM frames 1760875becf8STakashi Sakamoto * 1761875becf8STakashi Sakamoto * Returns zero always. 1762875becf8STakashi Sakamoto */ 1763e6dcc92fSTakashi Sakamoto int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s) 1764875becf8STakashi Sakamoto { 1765e6dcc92fSTakashi Sakamoto struct amdtp_stream *irq_target = d->irq_target; 1766e6dcc92fSTakashi Sakamoto 1767e6dcc92fSTakashi Sakamoto // Process isochronous packets for recent isochronous cycle to handle 1768e6dcc92fSTakashi Sakamoto // queued PCM frames. 1769987b705bSTakashi Sakamoto if (irq_target && amdtp_stream_running(irq_target)) 1770e6dcc92fSTakashi Sakamoto fw_iso_context_flush_completions(irq_target->context); 1771875becf8STakashi Sakamoto 1772875becf8STakashi Sakamoto return 0; 1773875becf8STakashi Sakamoto } 1774e6dcc92fSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_ack); 1775875becf8STakashi Sakamoto 1776875becf8STakashi Sakamoto /** 1777d67c46b9STakashi Sakamoto * amdtp_stream_update - update the stream after a bus reset 1778d67c46b9STakashi Sakamoto * @s: the AMDTP stream 1779d67c46b9STakashi Sakamoto */ 1780d67c46b9STakashi Sakamoto void amdtp_stream_update(struct amdtp_stream *s) 1781d67c46b9STakashi Sakamoto { 1782d67c46b9STakashi Sakamoto /* Precomputing. */ 17836aa7de05SMark Rutland WRITE_ONCE(s->source_node_id_field, 17846aa7de05SMark Rutland (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & CIP_SID_MASK); 1785d67c46b9STakashi Sakamoto } 1786d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_update); 1787d67c46b9STakashi Sakamoto 1788d67c46b9STakashi Sakamoto /** 1789d67c46b9STakashi Sakamoto * amdtp_stream_stop - stop sending packets 1790d67c46b9STakashi Sakamoto * @s: the AMDTP stream to stop 1791d67c46b9STakashi Sakamoto * 1792d67c46b9STakashi Sakamoto * All PCM and MIDI devices of the stream must be stopped before the stream 1793d67c46b9STakashi Sakamoto * itself can be stopped. 1794d67c46b9STakashi Sakamoto */ 179574f94e41STakashi Sakamoto static void amdtp_stream_stop(struct amdtp_stream *s) 1796d67c46b9STakashi Sakamoto { 1797d67c46b9STakashi Sakamoto mutex_lock(&s->mutex); 1798d67c46b9STakashi Sakamoto 1799d67c46b9STakashi Sakamoto if (!amdtp_stream_running(s)) { 1800d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1801d67c46b9STakashi Sakamoto return; 1802d67c46b9STakashi Sakamoto } 1803d67c46b9STakashi Sakamoto 1804d67c46b9STakashi Sakamoto fw_iso_context_stop(s->context); 1805d67c46b9STakashi Sakamoto fw_iso_context_destroy(s->context); 1806d67c46b9STakashi Sakamoto s->context = ERR_PTR(-1); 1807d67c46b9STakashi Sakamoto iso_packets_buffer_destroy(&s->buffer, s->unit); 180804130cf8STakashi Sakamoto kfree(s->pkt_descs); 1809*cec371ffSTakashi Sakamoto s->pkt_descs = NULL; 1810d67c46b9STakashi Sakamoto 1811f9e5ecdfSTakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM) { 18126f24bb8aSTakashi Sakamoto kfree(s->ctx_data.rx.seq.descs); 1813f9e5ecdfSTakashi Sakamoto } else { 1814f9e5ecdfSTakashi Sakamoto if (s->domain->replay.enable) 1815f9e5ecdfSTakashi Sakamoto kfree(s->ctx_data.tx.cache.descs); 1816f9e5ecdfSTakashi Sakamoto } 1817d67c46b9STakashi Sakamoto 1818d67c46b9STakashi Sakamoto mutex_unlock(&s->mutex); 1819d67c46b9STakashi Sakamoto } 1820d67c46b9STakashi Sakamoto 1821d67c46b9STakashi Sakamoto /** 1822d67c46b9STakashi Sakamoto * amdtp_stream_pcm_abort - abort the running PCM device 1823d67c46b9STakashi Sakamoto * @s: the AMDTP stream about to be stopped 1824d67c46b9STakashi Sakamoto * 1825d67c46b9STakashi Sakamoto * If the isochronous stream needs to be stopped asynchronously, call this 1826d67c46b9STakashi Sakamoto * function first to stop the PCM device. 1827d67c46b9STakashi Sakamoto */ 1828d67c46b9STakashi Sakamoto void amdtp_stream_pcm_abort(struct amdtp_stream *s) 1829d67c46b9STakashi Sakamoto { 1830d67c46b9STakashi Sakamoto struct snd_pcm_substream *pcm; 1831d67c46b9STakashi Sakamoto 18326aa7de05SMark Rutland pcm = READ_ONCE(s->pcm); 1833d67c46b9STakashi Sakamoto if (pcm) 1834d67c46b9STakashi Sakamoto snd_pcm_stop_xrun(pcm); 1835d67c46b9STakashi Sakamoto } 1836d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_abort); 18373ec3d7a3STakashi Sakamoto 18383ec3d7a3STakashi Sakamoto /** 18393ec3d7a3STakashi Sakamoto * amdtp_domain_init - initialize an AMDTP domain structure 18403ec3d7a3STakashi Sakamoto * @d: the AMDTP domain to initialize. 18413ec3d7a3STakashi Sakamoto */ 18423ec3d7a3STakashi Sakamoto int amdtp_domain_init(struct amdtp_domain *d) 18433ec3d7a3STakashi Sakamoto { 18443ec3d7a3STakashi Sakamoto INIT_LIST_HEAD(&d->streams); 18453ec3d7a3STakashi Sakamoto 1846d68c3123STakashi Sakamoto d->events_per_period = 0; 1847d68c3123STakashi Sakamoto 18483ec3d7a3STakashi Sakamoto return 0; 18493ec3d7a3STakashi Sakamoto } 18503ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_init); 18513ec3d7a3STakashi Sakamoto 18523ec3d7a3STakashi Sakamoto /** 18533ec3d7a3STakashi Sakamoto * amdtp_domain_destroy - destroy an AMDTP domain structure 18543ec3d7a3STakashi Sakamoto * @d: the AMDTP domain to destroy. 18553ec3d7a3STakashi Sakamoto */ 18563ec3d7a3STakashi Sakamoto void amdtp_domain_destroy(struct amdtp_domain *d) 18573ec3d7a3STakashi Sakamoto { 18588d0d5c3fSTakashi Sakamoto // At present nothing to do. 18598d0d5c3fSTakashi Sakamoto return; 18603ec3d7a3STakashi Sakamoto } 18613ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_destroy); 18626261f90bSTakashi Sakamoto 18636261f90bSTakashi Sakamoto /** 1864157a53eeSTakashi Sakamoto * amdtp_domain_add_stream - register isoc context into the domain. 1865157a53eeSTakashi Sakamoto * @d: the AMDTP domain. 1866157a53eeSTakashi Sakamoto * @s: the AMDTP stream. 1867157a53eeSTakashi Sakamoto * @channel: the isochronous channel on the bus. 1868157a53eeSTakashi Sakamoto * @speed: firewire speed code. 1869157a53eeSTakashi Sakamoto */ 1870157a53eeSTakashi Sakamoto int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, 1871157a53eeSTakashi Sakamoto int channel, int speed) 1872157a53eeSTakashi Sakamoto { 1873157a53eeSTakashi Sakamoto struct amdtp_stream *tmp; 1874157a53eeSTakashi Sakamoto 1875157a53eeSTakashi Sakamoto list_for_each_entry(tmp, &d->streams, list) { 1876157a53eeSTakashi Sakamoto if (s == tmp) 1877157a53eeSTakashi Sakamoto return -EBUSY; 1878157a53eeSTakashi Sakamoto } 1879157a53eeSTakashi Sakamoto 1880157a53eeSTakashi Sakamoto list_add(&s->list, &d->streams); 1881157a53eeSTakashi Sakamoto 1882157a53eeSTakashi Sakamoto s->channel = channel; 1883157a53eeSTakashi Sakamoto s->speed = speed; 18842472cfb3STakashi Sakamoto s->domain = d; 1885157a53eeSTakashi Sakamoto 1886157a53eeSTakashi Sakamoto return 0; 1887157a53eeSTakashi Sakamoto } 1888157a53eeSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); 1889157a53eeSTakashi Sakamoto 189039c2649cSTakashi Sakamoto // Make the reference from rx stream to tx stream for sequence replay. When the number of tx streams 189139c2649cSTakashi Sakamoto // is less than the number of rx streams, the first tx stream is selected. 189239c2649cSTakashi Sakamoto static int make_association(struct amdtp_domain *d) 189339c2649cSTakashi Sakamoto { 189439c2649cSTakashi Sakamoto unsigned int dst_index = 0; 189539c2649cSTakashi Sakamoto struct amdtp_stream *rx; 189639c2649cSTakashi Sakamoto 189739c2649cSTakashi Sakamoto // Make association to replay target. 189839c2649cSTakashi Sakamoto list_for_each_entry(rx, &d->streams, list) { 189939c2649cSTakashi Sakamoto if (rx->direction == AMDTP_OUT_STREAM) { 190039c2649cSTakashi Sakamoto unsigned int src_index = 0; 190139c2649cSTakashi Sakamoto struct amdtp_stream *tx = NULL; 190239c2649cSTakashi Sakamoto struct amdtp_stream *s; 190339c2649cSTakashi Sakamoto 190439c2649cSTakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 190539c2649cSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 190639c2649cSTakashi Sakamoto if (dst_index == src_index) { 190739c2649cSTakashi Sakamoto tx = s; 190839c2649cSTakashi Sakamoto break; 190939c2649cSTakashi Sakamoto } 191039c2649cSTakashi Sakamoto 191139c2649cSTakashi Sakamoto ++src_index; 191239c2649cSTakashi Sakamoto } 191339c2649cSTakashi Sakamoto } 191439c2649cSTakashi Sakamoto if (!tx) { 191539c2649cSTakashi Sakamoto // Select the first entry. 191639c2649cSTakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 191739c2649cSTakashi Sakamoto if (s->direction == AMDTP_IN_STREAM) { 191839c2649cSTakashi Sakamoto tx = s; 191939c2649cSTakashi Sakamoto break; 192039c2649cSTakashi Sakamoto } 192139c2649cSTakashi Sakamoto } 192239c2649cSTakashi Sakamoto // No target is available to replay sequence. 192339c2649cSTakashi Sakamoto if (!tx) 192439c2649cSTakashi Sakamoto return -EINVAL; 192539c2649cSTakashi Sakamoto } 192639c2649cSTakashi Sakamoto 192739c2649cSTakashi Sakamoto rx->ctx_data.rx.replay_target = tx; 192839c2649cSTakashi Sakamoto 192939c2649cSTakashi Sakamoto ++dst_index; 193039c2649cSTakashi Sakamoto } 193139c2649cSTakashi Sakamoto } 193239c2649cSTakashi Sakamoto 193339c2649cSTakashi Sakamoto return 0; 193439c2649cSTakashi Sakamoto } 193539c2649cSTakashi Sakamoto 1936157a53eeSTakashi Sakamoto /** 19379b4702b0STakashi Sakamoto * amdtp_domain_start - start sending packets for isoc context in the domain. 19389b4702b0STakashi Sakamoto * @d: the AMDTP domain. 193926541cb1STakashi Sakamoto * @tx_init_skip_cycles: the number of cycles to skip processing packets at initial stage of IR 194026541cb1STakashi Sakamoto * contexts. 1941f9e5ecdfSTakashi Sakamoto * @replay_seq: whether to replay the sequence of packet in IR context for the sequence of packet in 1942f9e5ecdfSTakashi Sakamoto * IT context. 19432f21a177STakashi Sakamoto * @replay_on_the_fly: transfer rx packets according to nominal frequency, then begin to replay 19442f21a177STakashi Sakamoto * according to arrival of events in tx packets. 19459b4702b0STakashi Sakamoto */ 19462f21a177STakashi Sakamoto int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq, 19472f21a177STakashi Sakamoto bool replay_on_the_fly) 19489b4702b0STakashi Sakamoto { 1949af86b0b1STakashi Sakamoto unsigned int events_per_buffer = d->events_per_buffer; 1950af86b0b1STakashi Sakamoto unsigned int events_per_period = d->events_per_period; 1951af86b0b1STakashi Sakamoto unsigned int queue_size; 19529b4702b0STakashi Sakamoto struct amdtp_stream *s; 19530cbbeaf3SChristophe JAILLET bool found = false; 1954acfedcbeSTakashi Sakamoto int err; 19559b4702b0STakashi Sakamoto 195639c2649cSTakashi Sakamoto if (replay_seq) { 195739c2649cSTakashi Sakamoto err = make_association(d); 195839c2649cSTakashi Sakamoto if (err < 0) 195939c2649cSTakashi Sakamoto return err; 196039c2649cSTakashi Sakamoto } 1961f9e5ecdfSTakashi Sakamoto d->replay.enable = replay_seq; 19622f21a177STakashi Sakamoto d->replay.on_the_fly = replay_on_the_fly; 1963f9e5ecdfSTakashi Sakamoto 196460dd4929STakashi Sakamoto // Select an IT context as IRQ target. 19659b4702b0STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 19660cbbeaf3SChristophe JAILLET if (s->direction == AMDTP_OUT_STREAM) { 19670cbbeaf3SChristophe JAILLET found = true; 19689b4702b0STakashi Sakamoto break; 19699b4702b0STakashi Sakamoto } 19700cbbeaf3SChristophe JAILLET } 19710cbbeaf3SChristophe JAILLET if (!found) 197260dd4929STakashi Sakamoto return -ENXIO; 197360dd4929STakashi Sakamoto d->irq_target = s; 19749b4702b0STakashi Sakamoto 197526541cb1STakashi Sakamoto d->processing_cycle.tx_init_skip = tx_init_skip_cycles; 197626541cb1STakashi Sakamoto 1977af86b0b1STakashi Sakamoto // This is a case that AMDTP streams in domain run just for MIDI 1978af86b0b1STakashi Sakamoto // substream. Use the number of events equivalent to 10 msec as 1979af86b0b1STakashi Sakamoto // interval of hardware IRQ. 1980af86b0b1STakashi Sakamoto if (events_per_period == 0) 1981af86b0b1STakashi Sakamoto events_per_period = amdtp_rate_table[d->irq_target->sfc] / 100; 1982af86b0b1STakashi Sakamoto if (events_per_buffer == 0) 1983af86b0b1STakashi Sakamoto events_per_buffer = events_per_period * 3; 1984af86b0b1STakashi Sakamoto 1985af86b0b1STakashi Sakamoto queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, 1986af86b0b1STakashi Sakamoto amdtp_rate_table[d->irq_target->sfc]); 1987af86b0b1STakashi Sakamoto 198860dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) { 1989bd165079STakashi Sakamoto unsigned int idle_irq_interval = 0; 1990acfedcbeSTakashi Sakamoto 1991bd165079STakashi Sakamoto if (s->direction == AMDTP_OUT_STREAM && s == d->irq_target) { 1992af86b0b1STakashi Sakamoto idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, 1993af86b0b1STakashi Sakamoto amdtp_rate_table[d->irq_target->sfc]); 1994bd165079STakashi Sakamoto } 1995bd165079STakashi Sakamoto 1996bd165079STakashi Sakamoto // Starts immediately but actually DMA context starts several hundred cycles later. 1997bd165079STakashi Sakamoto err = amdtp_stream_start(s, s->channel, s->speed, queue_size, idle_irq_interval); 199860dd4929STakashi Sakamoto if (err < 0) 199960dd4929STakashi Sakamoto goto error; 2000bd165079STakashi Sakamoto } 200160dd4929STakashi Sakamoto 200260dd4929STakashi Sakamoto return 0; 200360dd4929STakashi Sakamoto error: 200460dd4929STakashi Sakamoto list_for_each_entry(s, &d->streams, list) 200560dd4929STakashi Sakamoto amdtp_stream_stop(s); 20069b4702b0STakashi Sakamoto return err; 20079b4702b0STakashi Sakamoto } 20089b4702b0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_start); 20099b4702b0STakashi Sakamoto 20109b4702b0STakashi Sakamoto /** 20116261f90bSTakashi Sakamoto * amdtp_domain_stop - stop sending packets for isoc context in the same domain. 20126261f90bSTakashi Sakamoto * @d: the AMDTP domain to which the isoc contexts belong. 20136261f90bSTakashi Sakamoto */ 20146261f90bSTakashi Sakamoto void amdtp_domain_stop(struct amdtp_domain *d) 20156261f90bSTakashi Sakamoto { 20166261f90bSTakashi Sakamoto struct amdtp_stream *s, *next; 20176261f90bSTakashi Sakamoto 201860dd4929STakashi Sakamoto if (d->irq_target) 201960dd4929STakashi Sakamoto amdtp_stream_stop(d->irq_target); 202060dd4929STakashi Sakamoto 20216261f90bSTakashi Sakamoto list_for_each_entry_safe(s, next, &d->streams, list) { 20226261f90bSTakashi Sakamoto list_del(&s->list); 20236261f90bSTakashi Sakamoto 202460dd4929STakashi Sakamoto if (s != d->irq_target) 20256261f90bSTakashi Sakamoto amdtp_stream_stop(s); 20266261f90bSTakashi Sakamoto } 2027d68c3123STakashi Sakamoto 2028d68c3123STakashi Sakamoto d->events_per_period = 0; 202960dd4929STakashi Sakamoto d->irq_target = NULL; 20306261f90bSTakashi Sakamoto } 20316261f90bSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stop); 2032