xref: /linux/sound/firewire/amdtp-stream.c (revision 67d92ee7a50b007b87b113195e73da6ece6b231b)
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 
36*67d92ee7STakashi Sakamoto // Common Isochronous Packet (CIP) header parameters. Use two quadlets CIP header when supported.
37*67d92ee7STakashi 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
52d67c46b9STakashi Sakamoto #define CIP_SYT_MASK		0x0000ffff
53d67c46b9STakashi Sakamoto #define CIP_SYT_NO_INFO		0xffff
54d67c46b9STakashi Sakamoto 
55*67d92ee7STakashi Sakamoto #define CIP_HEADER_SIZE		(sizeof(__be32) * CIP_HEADER_QUADLETS)
56*67d92ee7STakashi Sakamoto 
5751c29fd2STakashi Sakamoto /* Audio and Music transfer protocol specific parameters */
58d67c46b9STakashi Sakamoto #define CIP_FMT_AM		0x10
59d67c46b9STakashi Sakamoto #define AMDTP_FDF_NO_DATA	0xff
60d67c46b9STakashi Sakamoto 
61f11453c7STakashi Sakamoto // For iso header and tstamp.
62*67d92ee7STakashi Sakamoto #define IR_CTX_HEADER_DEFAULT_QUADLETS	2
63*67d92ee7STakashi Sakamoto // Add nothing.
64*67d92ee7STakashi Sakamoto #define IR_CTX_HEADER_SIZE_NO_CIP	(sizeof(__be32) * IR_CTX_HEADER_DEFAULT_QUADLETS)
65*67d92ee7STakashi Sakamoto // Add two quadlets CIP header.
66*67d92ee7STakashi Sakamoto #define IR_CTX_HEADER_SIZE_CIP		(IR_CTX_HEADER_SIZE_NO_CIP + CIP_HEADER_SIZE)
67cc4f8e91STakashi Sakamoto #define HEADER_TSTAMP_MASK	0x0000ffff
68d67c46b9STakashi Sakamoto 
69*67d92ee7STakashi Sakamoto #define IT_PKT_HEADER_SIZE_CIP		CIP_HEADER_SIZE
70b18f0cfaSTakashi Sakamoto #define IT_PKT_HEADER_SIZE_NO_CIP	0 // Nothing.
71b18f0cfaSTakashi Sakamoto 
726a3ce97dSTakashi Sakamoto // The initial firmware of OXFW970 can postpone transmission of packet during finishing
736a3ce97dSTakashi Sakamoto // asynchronous transaction. This module accepts 5 cycles to skip as maximum to avoid buffer
746a3ce97dSTakashi Sakamoto // overrun. Actual device can skip more, then this module stops the packet streaming.
756a3ce97dSTakashi Sakamoto #define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES	5
766a3ce97dSTakashi Sakamoto 
772b3d2987STakashi Iwai static void pcm_period_work(struct work_struct *work);
78d67c46b9STakashi Sakamoto 
79d67c46b9STakashi Sakamoto /**
80d67c46b9STakashi Sakamoto  * amdtp_stream_init - initialize an AMDTP stream structure
81d67c46b9STakashi Sakamoto  * @s: the AMDTP stream to initialize
82d67c46b9STakashi Sakamoto  * @unit: the target of the stream
83d67c46b9STakashi Sakamoto  * @dir: the direction of stream
84ffe66bbeSTakashi Sakamoto  * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants.
855955815eSTakashi Sakamoto  * @fmt: the value of fmt field in CIP header
869a738ad1STakashi Sakamoto  * @process_ctx_payloads: callback handler to process payloads of isoc context
87df075feeSTakashi Sakamoto  * @protocol_size: the size to allocate newly for protocol
88d67c46b9STakashi Sakamoto  */
89d67c46b9STakashi Sakamoto int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
90ffe66bbeSTakashi Sakamoto 		      enum amdtp_stream_direction dir, unsigned int flags,
91df075feeSTakashi Sakamoto 		      unsigned int fmt,
929a738ad1STakashi Sakamoto 		      amdtp_stream_process_ctx_payloads_t process_ctx_payloads,
93df075feeSTakashi Sakamoto 		      unsigned int protocol_size)
94d67c46b9STakashi Sakamoto {
959a738ad1STakashi Sakamoto 	if (process_ctx_payloads == NULL)
96df075feeSTakashi Sakamoto 		return -EINVAL;
97df075feeSTakashi Sakamoto 
98df075feeSTakashi Sakamoto 	s->protocol = kzalloc(protocol_size, GFP_KERNEL);
99df075feeSTakashi Sakamoto 	if (!s->protocol)
100df075feeSTakashi Sakamoto 		return -ENOMEM;
101df075feeSTakashi Sakamoto 
102d67c46b9STakashi Sakamoto 	s->unit = unit;
103d67c46b9STakashi Sakamoto 	s->direction = dir;
104d67c46b9STakashi Sakamoto 	s->flags = flags;
105d67c46b9STakashi Sakamoto 	s->context = ERR_PTR(-1);
106d67c46b9STakashi Sakamoto 	mutex_init(&s->mutex);
1072b3d2987STakashi Iwai 	INIT_WORK(&s->period_work, pcm_period_work);
108d67c46b9STakashi Sakamoto 	s->packet_index = 0;
109d67c46b9STakashi Sakamoto 
110d67c46b9STakashi Sakamoto 	init_waitqueue_head(&s->callback_wait);
111d67c46b9STakashi Sakamoto 	s->callbacked = false;
112d67c46b9STakashi Sakamoto 
1135955815eSTakashi Sakamoto 	s->fmt = fmt;
1149a738ad1STakashi Sakamoto 	s->process_ctx_payloads = process_ctx_payloads;
115d67c46b9STakashi Sakamoto 
1163baf3053STakashi Sakamoto 	if (dir == AMDTP_OUT_STREAM)
1173baf3053STakashi Sakamoto 		s->ctx_data.rx.syt_override = -1;
1183baf3053STakashi Sakamoto 
119d67c46b9STakashi Sakamoto 	return 0;
120d67c46b9STakashi Sakamoto }
121d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_init);
122d67c46b9STakashi Sakamoto 
123d67c46b9STakashi Sakamoto /**
124d67c46b9STakashi Sakamoto  * amdtp_stream_destroy - free stream resources
125d67c46b9STakashi Sakamoto  * @s: the AMDTP stream to destroy
126d67c46b9STakashi Sakamoto  */
127d67c46b9STakashi Sakamoto void amdtp_stream_destroy(struct amdtp_stream *s)
128d67c46b9STakashi Sakamoto {
12944c376b9STakashi Sakamoto 	/* Not initialized. */
13044c376b9STakashi Sakamoto 	if (s->protocol == NULL)
13144c376b9STakashi Sakamoto 		return;
13244c376b9STakashi Sakamoto 
133d67c46b9STakashi Sakamoto 	WARN_ON(amdtp_stream_running(s));
134df075feeSTakashi Sakamoto 	kfree(s->protocol);
135d67c46b9STakashi Sakamoto 	mutex_destroy(&s->mutex);
136d67c46b9STakashi Sakamoto }
137d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_destroy);
138d67c46b9STakashi Sakamoto 
139d67c46b9STakashi Sakamoto const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = {
140d67c46b9STakashi Sakamoto 	[CIP_SFC_32000]  =  8,
141d67c46b9STakashi Sakamoto 	[CIP_SFC_44100]  =  8,
142d67c46b9STakashi Sakamoto 	[CIP_SFC_48000]  =  8,
143d67c46b9STakashi Sakamoto 	[CIP_SFC_88200]  = 16,
144d67c46b9STakashi Sakamoto 	[CIP_SFC_96000]  = 16,
145d67c46b9STakashi Sakamoto 	[CIP_SFC_176400] = 32,
146d67c46b9STakashi Sakamoto 	[CIP_SFC_192000] = 32,
147d67c46b9STakashi Sakamoto };
148d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_syt_intervals);
149d67c46b9STakashi Sakamoto 
150d67c46b9STakashi Sakamoto const unsigned int amdtp_rate_table[CIP_SFC_COUNT] = {
151d67c46b9STakashi Sakamoto 	[CIP_SFC_32000]  =  32000,
152d67c46b9STakashi Sakamoto 	[CIP_SFC_44100]  =  44100,
153d67c46b9STakashi Sakamoto 	[CIP_SFC_48000]  =  48000,
154d67c46b9STakashi Sakamoto 	[CIP_SFC_88200]  =  88200,
155d67c46b9STakashi Sakamoto 	[CIP_SFC_96000]  =  96000,
156d67c46b9STakashi Sakamoto 	[CIP_SFC_176400] = 176400,
157d67c46b9STakashi Sakamoto 	[CIP_SFC_192000] = 192000,
158d67c46b9STakashi Sakamoto };
159d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_rate_table);
160d67c46b9STakashi Sakamoto 
16159502295STakashi Sakamoto static int apply_constraint_to_size(struct snd_pcm_hw_params *params,
16259502295STakashi Sakamoto 				    struct snd_pcm_hw_rule *rule)
16359502295STakashi Sakamoto {
16459502295STakashi Sakamoto 	struct snd_interval *s = hw_param_interval(params, rule->var);
16559502295STakashi Sakamoto 	const struct snd_interval *r =
16659502295STakashi Sakamoto 		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
167826b5de9STakashi Sakamoto 	struct snd_interval t = {0};
168826b5de9STakashi Sakamoto 	unsigned int step = 0;
16959502295STakashi Sakamoto 	int i;
17059502295STakashi Sakamoto 
17159502295STakashi Sakamoto 	for (i = 0; i < CIP_SFC_COUNT; ++i) {
172826b5de9STakashi Sakamoto 		if (snd_interval_test(r, amdtp_rate_table[i]))
173826b5de9STakashi Sakamoto 			step = max(step, amdtp_syt_intervals[i]);
17459502295STakashi Sakamoto 	}
17559502295STakashi Sakamoto 
176826b5de9STakashi Sakamoto 	t.min = roundup(s->min, step);
177826b5de9STakashi Sakamoto 	t.max = rounddown(s->max, step);
178826b5de9STakashi Sakamoto 	t.integer = 1;
17959502295STakashi Sakamoto 
18059502295STakashi Sakamoto 	return snd_interval_refine(s, &t);
18159502295STakashi Sakamoto }
18259502295STakashi Sakamoto 
183d67c46b9STakashi Sakamoto /**
184d67c46b9STakashi Sakamoto  * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream
185d67c46b9STakashi Sakamoto  * @s:		the AMDTP stream, which must be initialized.
186d67c46b9STakashi Sakamoto  * @runtime:	the PCM substream runtime
187d67c46b9STakashi Sakamoto  */
188d67c46b9STakashi Sakamoto int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
189d67c46b9STakashi Sakamoto 					struct snd_pcm_runtime *runtime)
190d67c46b9STakashi Sakamoto {
19155799c5aSTakashi Sakamoto 	struct snd_pcm_hardware *hw = &runtime->hw;
19299921ec6STakashi Sakamoto 	unsigned int ctx_header_size;
19399921ec6STakashi Sakamoto 	unsigned int maximum_usec_per_period;
194d67c46b9STakashi Sakamoto 	int err;
195d67c46b9STakashi Sakamoto 
19655799c5aSTakashi Sakamoto 	hw->info = SNDRV_PCM_INFO_BATCH |
19755799c5aSTakashi Sakamoto 		   SNDRV_PCM_INFO_BLOCK_TRANSFER |
19855799c5aSTakashi Sakamoto 		   SNDRV_PCM_INFO_INTERLEAVED |
19955799c5aSTakashi Sakamoto 		   SNDRV_PCM_INFO_JOINT_DUPLEX |
20055799c5aSTakashi Sakamoto 		   SNDRV_PCM_INFO_MMAP |
20155799c5aSTakashi Sakamoto 		   SNDRV_PCM_INFO_MMAP_VALID;
20255799c5aSTakashi Sakamoto 
20355799c5aSTakashi Sakamoto 	/* SNDRV_PCM_INFO_BATCH */
20455799c5aSTakashi Sakamoto 	hw->periods_min = 2;
20555799c5aSTakashi Sakamoto 	hw->periods_max = UINT_MAX;
20655799c5aSTakashi Sakamoto 
20755799c5aSTakashi Sakamoto 	/* bytes for a frame */
20855799c5aSTakashi Sakamoto 	hw->period_bytes_min = 4 * hw->channels_max;
20955799c5aSTakashi Sakamoto 
21055799c5aSTakashi Sakamoto 	/* Just to prevent from allocating much pages. */
21155799c5aSTakashi Sakamoto 	hw->period_bytes_max = hw->period_bytes_min * 2048;
21255799c5aSTakashi Sakamoto 	hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min;
21355799c5aSTakashi Sakamoto 
21499921ec6STakashi Sakamoto 	// Linux driver for 1394 OHCI controller voluntarily flushes isoc
21599921ec6STakashi Sakamoto 	// context when total size of accumulated context header reaches
2162b3d2987STakashi Iwai 	// PAGE_SIZE. This kicks work for the isoc context and brings
21799921ec6STakashi Sakamoto 	// callback in the middle of scheduled interrupts.
21899921ec6STakashi Sakamoto 	// Although AMDTP streams in the same domain use the same events per
21999921ec6STakashi Sakamoto 	// IRQ, use the largest size of context header between IT/IR contexts.
22099921ec6STakashi Sakamoto 	// Here, use the value of context header in IR context is for both
22199921ec6STakashi Sakamoto 	// contexts.
22299921ec6STakashi Sakamoto 	if (!(s->flags & CIP_NO_HEADER))
22399921ec6STakashi Sakamoto 		ctx_header_size = IR_CTX_HEADER_SIZE_CIP;
22499921ec6STakashi Sakamoto 	else
22599921ec6STakashi Sakamoto 		ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP;
22699921ec6STakashi Sakamoto 	maximum_usec_per_period = USEC_PER_SEC * PAGE_SIZE /
22799921ec6STakashi Sakamoto 				  CYCLES_PER_SECOND / ctx_header_size;
22899921ec6STakashi Sakamoto 
229f706df4fSTakashi Sakamoto 	// In IEC 61883-6, one isoc packet can transfer events up to the value
230f706df4fSTakashi Sakamoto 	// of syt interval. This comes from the interval of isoc cycle. As 1394
231f706df4fSTakashi Sakamoto 	// OHCI controller can generate hardware IRQ per isoc packet, the
232f706df4fSTakashi Sakamoto 	// interval is 125 usec.
233f706df4fSTakashi Sakamoto 	// However, there are two ways of transmission in IEC 61883-6; blocking
234f706df4fSTakashi Sakamoto 	// and non-blocking modes. In blocking mode, the sequence of isoc packet
235f706df4fSTakashi Sakamoto 	// includes 'empty' or 'NODATA' packets which include no event. In
236f706df4fSTakashi Sakamoto 	// non-blocking mode, the number of events per packet is variable up to
237f706df4fSTakashi Sakamoto 	// the syt interval.
238f706df4fSTakashi Sakamoto 	// Due to the above protocol design, the minimum PCM frames per
239f706df4fSTakashi Sakamoto 	// interrupt should be double of the value of syt interval, thus it is
240f706df4fSTakashi Sakamoto 	// 250 usec.
241d67c46b9STakashi Sakamoto 	err = snd_pcm_hw_constraint_minmax(runtime,
242d67c46b9STakashi Sakamoto 					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
243f706df4fSTakashi Sakamoto 					   250, maximum_usec_per_period);
244d67c46b9STakashi Sakamoto 	if (err < 0)
245d67c46b9STakashi Sakamoto 		goto end;
246d67c46b9STakashi Sakamoto 
247d67c46b9STakashi Sakamoto 	/* Non-Blocking stream has no more constraints */
248d67c46b9STakashi Sakamoto 	if (!(s->flags & CIP_BLOCKING))
249d67c46b9STakashi Sakamoto 		goto end;
250d67c46b9STakashi Sakamoto 
251d67c46b9STakashi Sakamoto 	/*
252d67c46b9STakashi Sakamoto 	 * One AMDTP packet can include some frames. In blocking mode, the
253d67c46b9STakashi Sakamoto 	 * number equals to SYT_INTERVAL. So the number is 8, 16 or 32,
254d67c46b9STakashi Sakamoto 	 * depending on its sampling rate. For accurate period interrupt, it's
255d67c46b9STakashi Sakamoto 	 * preferrable to align period/buffer sizes to current SYT_INTERVAL.
256d67c46b9STakashi Sakamoto 	 */
25759502295STakashi Sakamoto 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
25859502295STakashi Sakamoto 				  apply_constraint_to_size, NULL,
259826b5de9STakashi Sakamoto 				  SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
26059502295STakashi Sakamoto 				  SNDRV_PCM_HW_PARAM_RATE, -1);
261d67c46b9STakashi Sakamoto 	if (err < 0)
262d67c46b9STakashi Sakamoto 		goto end;
26359502295STakashi Sakamoto 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
26459502295STakashi Sakamoto 				  apply_constraint_to_size, NULL,
265826b5de9STakashi Sakamoto 				  SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
26659502295STakashi Sakamoto 				  SNDRV_PCM_HW_PARAM_RATE, -1);
26759502295STakashi Sakamoto 	if (err < 0)
26859502295STakashi Sakamoto 		goto end;
269d67c46b9STakashi Sakamoto end:
270d67c46b9STakashi Sakamoto 	return err;
271d67c46b9STakashi Sakamoto }
272d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_add_pcm_hw_constraints);
273d67c46b9STakashi Sakamoto 
274d67c46b9STakashi Sakamoto /**
275d67c46b9STakashi Sakamoto  * amdtp_stream_set_parameters - set stream parameters
276d67c46b9STakashi Sakamoto  * @s: the AMDTP stream to configure
277d67c46b9STakashi Sakamoto  * @rate: the sample rate
278df075feeSTakashi Sakamoto  * @data_block_quadlets: the size of a data block in quadlet unit
279d67c46b9STakashi Sakamoto  *
280d67c46b9STakashi Sakamoto  * The parameters must be set before the stream is started, and must not be
281d67c46b9STakashi Sakamoto  * changed while the stream is running.
282d67c46b9STakashi Sakamoto  */
283df075feeSTakashi Sakamoto int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
284df075feeSTakashi Sakamoto 				unsigned int data_block_quadlets)
285d67c46b9STakashi Sakamoto {
286df075feeSTakashi Sakamoto 	unsigned int sfc;
287d67c46b9STakashi Sakamoto 
288d67c46b9STakashi Sakamoto 	for (sfc = 0; sfc < ARRAY_SIZE(amdtp_rate_table); ++sfc) {
289d67c46b9STakashi Sakamoto 		if (amdtp_rate_table[sfc] == rate)
290d67c46b9STakashi Sakamoto 			break;
291d67c46b9STakashi Sakamoto 	}
292d67c46b9STakashi Sakamoto 	if (sfc == ARRAY_SIZE(amdtp_rate_table))
293d67c46b9STakashi Sakamoto 		return -EINVAL;
294d67c46b9STakashi Sakamoto 
295d67c46b9STakashi Sakamoto 	s->sfc = sfc;
296df075feeSTakashi Sakamoto 	s->data_block_quadlets = data_block_quadlets;
297d67c46b9STakashi Sakamoto 	s->syt_interval = amdtp_syt_intervals[sfc];
298d67c46b9STakashi Sakamoto 
299d3d10a4aSTakashi Sakamoto 	// default buffering in the device.
300d3d10a4aSTakashi Sakamoto 	if (s->direction == AMDTP_OUT_STREAM) {
301d3d10a4aSTakashi Sakamoto 		s->ctx_data.rx.transfer_delay =
302d3d10a4aSTakashi Sakamoto 					TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
303d3d10a4aSTakashi Sakamoto 
304d3d10a4aSTakashi Sakamoto 		if (s->flags & CIP_BLOCKING) {
305d3d10a4aSTakashi Sakamoto 			// additional buffering needed to adjust for no-data
306d3d10a4aSTakashi Sakamoto 			// packets.
307d3d10a4aSTakashi Sakamoto 			s->ctx_data.rx.transfer_delay +=
308d3d10a4aSTakashi Sakamoto 				TICKS_PER_SECOND * s->syt_interval / rate;
309d3d10a4aSTakashi Sakamoto 		}
310d3d10a4aSTakashi Sakamoto 	}
311d67c46b9STakashi Sakamoto 
312d67c46b9STakashi Sakamoto 	return 0;
313d67c46b9STakashi Sakamoto }
314d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_set_parameters);
315d67c46b9STakashi Sakamoto 
316d67c46b9STakashi Sakamoto /**
317d67c46b9STakashi Sakamoto  * amdtp_stream_get_max_payload - get the stream's packet size
318d67c46b9STakashi Sakamoto  * @s: the AMDTP stream
319d67c46b9STakashi Sakamoto  *
320d67c46b9STakashi Sakamoto  * This function must not be called before the stream has been configured
321d67c46b9STakashi Sakamoto  * with amdtp_stream_set_parameters().
322d67c46b9STakashi Sakamoto  */
323d67c46b9STakashi Sakamoto unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s)
324d67c46b9STakashi Sakamoto {
325d67c46b9STakashi Sakamoto 	unsigned int multiplier = 1;
32607ea238cSTakashi Sakamoto 	unsigned int cip_header_size = 0;
327d67c46b9STakashi Sakamoto 
328d67c46b9STakashi Sakamoto 	if (s->flags & CIP_JUMBO_PAYLOAD)
3296a3ce97dSTakashi Sakamoto 		multiplier = IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES;
3303b196c39STakashi Sakamoto 	if (!(s->flags & CIP_NO_HEADER))
331*67d92ee7STakashi Sakamoto 		cip_header_size = CIP_HEADER_SIZE;
332d67c46b9STakashi Sakamoto 
33307ea238cSTakashi Sakamoto 	return cip_header_size +
33407ea238cSTakashi Sakamoto 		s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier;
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 {
3462b3d2987STakashi Iwai 	cancel_work_sync(&s->period_work);
347d67c46b9STakashi Sakamoto 	s->pcm_buffer_pointer = 0;
348d67c46b9STakashi Sakamoto 	s->pcm_period_pointer = 0;
349d67c46b9STakashi Sakamoto }
350d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_prepare);
351d67c46b9STakashi Sakamoto 
352274fc355STakashi Sakamoto static unsigned int calculate_data_blocks(unsigned int *data_block_state,
353274fc355STakashi Sakamoto 				bool is_blocking, bool is_no_info,
354274fc355STakashi Sakamoto 				unsigned int syt_interval, enum cip_sfc sfc)
355d67c46b9STakashi Sakamoto {
356274fc355STakashi Sakamoto 	unsigned int data_blocks;
357d67c46b9STakashi Sakamoto 
358d67c46b9STakashi Sakamoto 	/* Blocking mode. */
359274fc355STakashi Sakamoto 	if (is_blocking) {
360d67c46b9STakashi Sakamoto 		/* This module generate empty packet for 'no data'. */
361274fc355STakashi Sakamoto 		if (is_no_info)
362d67c46b9STakashi Sakamoto 			data_blocks = 0;
363d67c46b9STakashi Sakamoto 		else
364274fc355STakashi Sakamoto 			data_blocks = syt_interval;
365d67c46b9STakashi Sakamoto 	/* Non-blocking mode. */
366d67c46b9STakashi Sakamoto 	} else {
367274fc355STakashi Sakamoto 		if (!cip_sfc_is_base_44100(sfc)) {
368d3d10a4aSTakashi Sakamoto 			// Sample_rate / 8000 is an integer, and precomputed.
369274fc355STakashi Sakamoto 			data_blocks = *data_block_state;
370d67c46b9STakashi Sakamoto 		} else {
371274fc355STakashi Sakamoto 			unsigned int phase = *data_block_state;
372d67c46b9STakashi Sakamoto 
373d67c46b9STakashi Sakamoto 		/*
374d67c46b9STakashi Sakamoto 		 * This calculates the number of data blocks per packet so that
375d67c46b9STakashi Sakamoto 		 * 1) the overall rate is correct and exactly synchronized to
376d67c46b9STakashi Sakamoto 		 *    the bus clock, and
377d67c46b9STakashi Sakamoto 		 * 2) packets with a rounded-up number of blocks occur as early
378d67c46b9STakashi Sakamoto 		 *    as possible in the sequence (to prevent underruns of the
379d67c46b9STakashi Sakamoto 		 *    device's buffer).
380d67c46b9STakashi Sakamoto 		 */
381274fc355STakashi Sakamoto 			if (sfc == CIP_SFC_44100)
382d67c46b9STakashi Sakamoto 				/* 6 6 5 6 5 6 5 ... */
383d67c46b9STakashi Sakamoto 				data_blocks = 5 + ((phase & 1) ^
384d67c46b9STakashi Sakamoto 						   (phase == 0 || phase >= 40));
385d67c46b9STakashi Sakamoto 			else
386d67c46b9STakashi Sakamoto 				/* 12 11 11 11 11 ... or 23 22 22 22 22 ... */
387274fc355STakashi Sakamoto 				data_blocks = 11 * (sfc >> 1) + (phase == 0);
388274fc355STakashi Sakamoto 			if (++phase >= (80 >> (sfc >> 1)))
389d67c46b9STakashi Sakamoto 				phase = 0;
390274fc355STakashi Sakamoto 			*data_block_state = phase;
391d67c46b9STakashi Sakamoto 		}
392d67c46b9STakashi Sakamoto 	}
393d67c46b9STakashi Sakamoto 
394d67c46b9STakashi Sakamoto 	return data_blocks;
395d67c46b9STakashi Sakamoto }
396d67c46b9STakashi Sakamoto 
397816d8482STakashi Sakamoto static unsigned int calculate_syt_offset(unsigned int *last_syt_offset,
398816d8482STakashi Sakamoto 			unsigned int *syt_offset_state, enum cip_sfc sfc)
399d67c46b9STakashi Sakamoto {
400816d8482STakashi Sakamoto 	unsigned int syt_offset;
401d67c46b9STakashi Sakamoto 
402816d8482STakashi Sakamoto 	if (*last_syt_offset < TICKS_PER_CYCLE) {
403816d8482STakashi Sakamoto 		if (!cip_sfc_is_base_44100(sfc))
404816d8482STakashi Sakamoto 			syt_offset = *last_syt_offset + *syt_offset_state;
405d67c46b9STakashi Sakamoto 		else {
406d67c46b9STakashi Sakamoto 		/*
407d67c46b9STakashi Sakamoto 		 * The time, in ticks, of the n'th SYT_INTERVAL sample is:
408d67c46b9STakashi Sakamoto 		 *   n * SYT_INTERVAL * 24576000 / sample_rate
409d67c46b9STakashi Sakamoto 		 * Modulo TICKS_PER_CYCLE, the difference between successive
410d67c46b9STakashi Sakamoto 		 * elements is about 1386.23.  Rounding the results of this
411d67c46b9STakashi Sakamoto 		 * formula to the SYT precision results in a sequence of
412d67c46b9STakashi Sakamoto 		 * differences that begins with:
413d67c46b9STakashi Sakamoto 		 *   1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ...
414d67c46b9STakashi Sakamoto 		 * This code generates _exactly_ the same sequence.
415d67c46b9STakashi Sakamoto 		 */
416816d8482STakashi Sakamoto 			unsigned int phase = *syt_offset_state;
417816d8482STakashi Sakamoto 			unsigned int index = phase % 13;
418816d8482STakashi Sakamoto 
419816d8482STakashi Sakamoto 			syt_offset = *last_syt_offset;
420d67c46b9STakashi Sakamoto 			syt_offset += 1386 + ((index && !(index & 3)) ||
421d67c46b9STakashi Sakamoto 					      phase == 146);
422d67c46b9STakashi Sakamoto 			if (++phase >= 147)
423d67c46b9STakashi Sakamoto 				phase = 0;
424816d8482STakashi Sakamoto 			*syt_offset_state = phase;
425d67c46b9STakashi Sakamoto 		}
426d67c46b9STakashi Sakamoto 	} else
427816d8482STakashi Sakamoto 		syt_offset = *last_syt_offset - TICKS_PER_CYCLE;
428816d8482STakashi Sakamoto 	*last_syt_offset = syt_offset;
429d67c46b9STakashi Sakamoto 
43083cfb5c5STakashi Sakamoto 	if (syt_offset >= TICKS_PER_CYCLE)
43183cfb5c5STakashi Sakamoto 		syt_offset = CIP_SYT_NO_INFO;
432d67c46b9STakashi Sakamoto 
43383cfb5c5STakashi Sakamoto 	return syt_offset;
434d67c46b9STakashi Sakamoto }
435d67c46b9STakashi Sakamoto 
436d67c46b9STakashi Sakamoto static void update_pcm_pointers(struct amdtp_stream *s,
437d67c46b9STakashi Sakamoto 				struct snd_pcm_substream *pcm,
438d67c46b9STakashi Sakamoto 				unsigned int frames)
439d67c46b9STakashi Sakamoto {
440d67c46b9STakashi Sakamoto 	unsigned int ptr;
441d67c46b9STakashi Sakamoto 
442d67c46b9STakashi Sakamoto 	ptr = s->pcm_buffer_pointer + frames;
443d67c46b9STakashi Sakamoto 	if (ptr >= pcm->runtime->buffer_size)
444d67c46b9STakashi Sakamoto 		ptr -= pcm->runtime->buffer_size;
4456aa7de05SMark Rutland 	WRITE_ONCE(s->pcm_buffer_pointer, ptr);
446d67c46b9STakashi Sakamoto 
447d67c46b9STakashi Sakamoto 	s->pcm_period_pointer += frames;
448d67c46b9STakashi Sakamoto 	if (s->pcm_period_pointer >= pcm->runtime->period_size) {
449d67c46b9STakashi Sakamoto 		s->pcm_period_pointer -= pcm->runtime->period_size;
4502b3d2987STakashi Iwai 		queue_work(system_highpri_wq, &s->period_work);
451d67c46b9STakashi Sakamoto 	}
452d67c46b9STakashi Sakamoto }
453d67c46b9STakashi Sakamoto 
4542b3d2987STakashi Iwai static void pcm_period_work(struct work_struct *work)
455d67c46b9STakashi Sakamoto {
4562b3d2987STakashi Iwai 	struct amdtp_stream *s = container_of(work, struct amdtp_stream,
4572b3d2987STakashi Iwai 					      period_work);
4586aa7de05SMark Rutland 	struct snd_pcm_substream *pcm = READ_ONCE(s->pcm);
459d67c46b9STakashi Sakamoto 
460d67c46b9STakashi Sakamoto 	if (pcm)
461d67c46b9STakashi Sakamoto 		snd_pcm_period_elapsed(pcm);
462d67c46b9STakashi Sakamoto }
463d67c46b9STakashi Sakamoto 
464e229853dSTakashi Sakamoto static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params,
465e229853dSTakashi Sakamoto 			bool sched_irq)
466d67c46b9STakashi Sakamoto {
4676007bf54STakashi Sakamoto 	int err;
468d67c46b9STakashi Sakamoto 
469e229853dSTakashi Sakamoto 	params->interrupt = sched_irq;
4706007bf54STakashi Sakamoto 	params->tag = s->tag;
4716007bf54STakashi Sakamoto 	params->sy = 0;
472d67c46b9STakashi Sakamoto 
4736007bf54STakashi Sakamoto 	err = fw_iso_context_queue(s->context, params, &s->buffer.iso_buffer,
474d67c46b9STakashi Sakamoto 				   s->buffer.packets[s->packet_index].offset);
475d67c46b9STakashi Sakamoto 	if (err < 0) {
476d67c46b9STakashi Sakamoto 		dev_err(&s->unit->device, "queueing error: %d\n", err);
477d67c46b9STakashi Sakamoto 		goto end;
478d67c46b9STakashi Sakamoto 	}
479d67c46b9STakashi Sakamoto 
480a0e02331STakashi Sakamoto 	if (++s->packet_index >= s->queue_size)
481d67c46b9STakashi Sakamoto 		s->packet_index = 0;
482d67c46b9STakashi Sakamoto end:
483d67c46b9STakashi Sakamoto 	return err;
484d67c46b9STakashi Sakamoto }
485d67c46b9STakashi Sakamoto 
486d67c46b9STakashi Sakamoto static inline int queue_out_packet(struct amdtp_stream *s,
487e229853dSTakashi Sakamoto 				   struct fw_iso_packet *params, bool sched_irq)
488d67c46b9STakashi Sakamoto {
489b18f0cfaSTakashi Sakamoto 	params->skip =
490b18f0cfaSTakashi Sakamoto 		!!(params->header_length == 0 && params->payload_length == 0);
491e229853dSTakashi Sakamoto 	return queue_packet(s, params, sched_irq);
492d67c46b9STakashi Sakamoto }
493d67c46b9STakashi Sakamoto 
4946007bf54STakashi Sakamoto static inline int queue_in_packet(struct amdtp_stream *s,
49560dd4929STakashi Sakamoto 				  struct fw_iso_packet *params)
496d67c46b9STakashi Sakamoto {
4976007bf54STakashi Sakamoto 	// Queue one packet for IR context.
4986007bf54STakashi Sakamoto 	params->header_length = s->ctx_data.tx.ctx_header_size;
4996007bf54STakashi Sakamoto 	params->payload_length = s->ctx_data.tx.max_ctx_payload_length;
5006007bf54STakashi Sakamoto 	params->skip = false;
50160dd4929STakashi Sakamoto 	return queue_packet(s, params, false);
502d67c46b9STakashi Sakamoto }
503d67c46b9STakashi Sakamoto 
504252219c7STakashi Sakamoto static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2],
505860d798cSTakashi Sakamoto 			unsigned int data_block_counter, unsigned int syt)
506252219c7STakashi Sakamoto {
507252219c7STakashi Sakamoto 	cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) |
508252219c7STakashi Sakamoto 				(s->data_block_quadlets << CIP_DBS_SHIFT) |
509252219c7STakashi Sakamoto 				((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) |
510860d798cSTakashi Sakamoto 				data_block_counter);
511252219c7STakashi Sakamoto 	cip_header[1] = cpu_to_be32(CIP_EOH |
512252219c7STakashi Sakamoto 			((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) |
513252219c7STakashi Sakamoto 			((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) |
514252219c7STakashi Sakamoto 			(syt & CIP_SYT_MASK));
515252219c7STakashi Sakamoto }
516252219c7STakashi Sakamoto 
5176bc1a269STakashi Sakamoto static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle,
5186bc1a269STakashi Sakamoto 				struct fw_iso_packet *params,
519860d798cSTakashi Sakamoto 				unsigned int data_blocks,
520860d798cSTakashi Sakamoto 				unsigned int data_block_counter,
521860d798cSTakashi Sakamoto 				unsigned int syt, unsigned int index)
522d67c46b9STakashi Sakamoto {
5230ebf3cebSTakashi Sakamoto 	unsigned int payload_length;
52416be4589STakashi Sakamoto 	__be32 *cip_header;
525d67c46b9STakashi Sakamoto 
5260ebf3cebSTakashi Sakamoto 	payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets;
5270ebf3cebSTakashi Sakamoto 	params->payload_length = payload_length;
5280ebf3cebSTakashi Sakamoto 
529b18f0cfaSTakashi Sakamoto 	if (!(s->flags & CIP_NO_HEADER)) {
5306bc1a269STakashi Sakamoto 		cip_header = (__be32 *)params->header;
531860d798cSTakashi Sakamoto 		generate_cip_header(s, cip_header, data_block_counter, syt);
5326bc1a269STakashi Sakamoto 		params->header_length = 2 * sizeof(__be32);
5330ebf3cebSTakashi Sakamoto 		payload_length += params->header_length;
534b18f0cfaSTakashi Sakamoto 	} else {
535b18f0cfaSTakashi Sakamoto 		cip_header = NULL;
536b18f0cfaSTakashi Sakamoto 	}
537d67c46b9STakashi Sakamoto 
538213fa989STakashi Sakamoto 	trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks,
539814b4312STakashi Sakamoto 			   data_block_counter, s->packet_index, index);
5403b196c39STakashi Sakamoto }
5413b196c39STakashi Sakamoto 
542e335425bSTakashi Sakamoto static int check_cip_header(struct amdtp_stream *s, const __be32 *buf,
543e335425bSTakashi Sakamoto 			    unsigned int payload_length,
544a35463d1STakashi Sakamoto 			    unsigned int *data_blocks,
545a35463d1STakashi Sakamoto 			    unsigned int *data_block_counter, unsigned int *syt)
546d67c46b9STakashi Sakamoto {
547d67c46b9STakashi Sakamoto 	u32 cip_header[2];
548e335425bSTakashi Sakamoto 	unsigned int sph;
549e335425bSTakashi Sakamoto 	unsigned int fmt;
550e335425bSTakashi Sakamoto 	unsigned int fdf;
551a35463d1STakashi Sakamoto 	unsigned int dbc;
552d67c46b9STakashi Sakamoto 	bool lost;
553d67c46b9STakashi Sakamoto 
554e335425bSTakashi Sakamoto 	cip_header[0] = be32_to_cpu(buf[0]);
555e335425bSTakashi Sakamoto 	cip_header[1] = be32_to_cpu(buf[1]);
556d67c46b9STakashi Sakamoto 
557d67c46b9STakashi Sakamoto 	/*
558d67c46b9STakashi Sakamoto 	 * This module supports 'Two-quadlet CIP header with SYT field'.
559d67c46b9STakashi Sakamoto 	 * For convenience, also check FMT field is AM824 or not.
560d67c46b9STakashi Sakamoto 	 */
5612128f78fSTakashi Sakamoto 	if ((((cip_header[0] & CIP_EOH_MASK) == CIP_EOH) ||
5622128f78fSTakashi Sakamoto 	     ((cip_header[1] & CIP_EOH_MASK) != CIP_EOH)) &&
5632128f78fSTakashi Sakamoto 	    (!(s->flags & CIP_HEADER_WITHOUT_EOH))) {
564d67c46b9STakashi Sakamoto 		dev_info_ratelimited(&s->unit->device,
565d67c46b9STakashi Sakamoto 				"Invalid CIP header for AMDTP: %08X:%08X\n",
566d67c46b9STakashi Sakamoto 				cip_header[0], cip_header[1]);
567e335425bSTakashi Sakamoto 		return -EAGAIN;
568d67c46b9STakashi Sakamoto 	}
569d67c46b9STakashi Sakamoto 
570d67c46b9STakashi Sakamoto 	/* Check valid protocol or not. */
5719863874fSTakashi Sakamoto 	sph = (cip_header[0] & CIP_SPH_MASK) >> CIP_SPH_SHIFT;
572d67c46b9STakashi Sakamoto 	fmt = (cip_header[1] & CIP_FMT_MASK) >> CIP_FMT_SHIFT;
5739863874fSTakashi Sakamoto 	if (sph != s->sph || fmt != s->fmt) {
5742a7e1713STakashi Sakamoto 		dev_info_ratelimited(&s->unit->device,
575d67c46b9STakashi Sakamoto 				     "Detect unexpected protocol: %08x %08x\n",
576d67c46b9STakashi Sakamoto 				     cip_header[0], cip_header[1]);
577e335425bSTakashi Sakamoto 		return -EAGAIN;
578d67c46b9STakashi Sakamoto 	}
579d67c46b9STakashi Sakamoto 
580d67c46b9STakashi Sakamoto 	/* Calculate data blocks */
581d67c46b9STakashi Sakamoto 	fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT;
5824fd18787STakashi Sakamoto 	if (payload_length == 0 || (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) {
583e335425bSTakashi Sakamoto 		*data_blocks = 0;
584d67c46b9STakashi Sakamoto 	} else {
585e335425bSTakashi Sakamoto 		unsigned int data_block_quadlets =
586d67c46b9STakashi Sakamoto 				(cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT;
587d67c46b9STakashi Sakamoto 		/* avoid division by zero */
588d67c46b9STakashi Sakamoto 		if (data_block_quadlets == 0) {
589d67c46b9STakashi Sakamoto 			dev_err(&s->unit->device,
590d67c46b9STakashi Sakamoto 				"Detect invalid value in dbs field: %08X\n",
591d67c46b9STakashi Sakamoto 				cip_header[0]);
592d67c46b9STakashi Sakamoto 			return -EPROTO;
593d67c46b9STakashi Sakamoto 		}
594d67c46b9STakashi Sakamoto 		if (s->flags & CIP_WRONG_DBS)
595d67c46b9STakashi Sakamoto 			data_block_quadlets = s->data_block_quadlets;
596d67c46b9STakashi Sakamoto 
5974fd18787STakashi Sakamoto 		*data_blocks = payload_length / sizeof(__be32) / data_block_quadlets;
598d67c46b9STakashi Sakamoto 	}
599d67c46b9STakashi Sakamoto 
600d67c46b9STakashi Sakamoto 	/* Check data block counter continuity */
601a35463d1STakashi Sakamoto 	dbc = cip_header[0] & CIP_DBC_MASK;
602e335425bSTakashi Sakamoto 	if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) &&
603a35463d1STakashi Sakamoto 	    *data_block_counter != UINT_MAX)
604a35463d1STakashi Sakamoto 		dbc = *data_block_counter;
605d67c46b9STakashi Sakamoto 
606a35463d1STakashi Sakamoto 	if ((dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) ||
607a35463d1STakashi Sakamoto 	    *data_block_counter == UINT_MAX) {
608d67c46b9STakashi Sakamoto 		lost = false;
609d67c46b9STakashi Sakamoto 	} else if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
610a35463d1STakashi Sakamoto 		lost = dbc != *data_block_counter;
611d67c46b9STakashi Sakamoto 	} else {
612e335425bSTakashi Sakamoto 		unsigned int dbc_interval;
613e335425bSTakashi Sakamoto 
614e335425bSTakashi Sakamoto 		if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
615d3d10a4aSTakashi Sakamoto 			dbc_interval = s->ctx_data.tx.dbc_interval;
616d67c46b9STakashi Sakamoto 		else
617e335425bSTakashi Sakamoto 			dbc_interval = *data_blocks;
618d67c46b9STakashi Sakamoto 
619a35463d1STakashi Sakamoto 		lost = dbc != ((*data_block_counter + dbc_interval) & 0xff);
620d67c46b9STakashi Sakamoto 	}
621d67c46b9STakashi Sakamoto 
622d67c46b9STakashi Sakamoto 	if (lost) {
623d67c46b9STakashi Sakamoto 		dev_err(&s->unit->device,
624d67c46b9STakashi Sakamoto 			"Detect discontinuity of CIP: %02X %02X\n",
625a35463d1STakashi Sakamoto 			*data_block_counter, dbc);
626d67c46b9STakashi Sakamoto 		return -EIO;
627d67c46b9STakashi Sakamoto 	}
628d67c46b9STakashi Sakamoto 
629753e7179STakashi Sakamoto 	*data_block_counter = dbc;
630753e7179STakashi Sakamoto 
631e335425bSTakashi Sakamoto 	*syt = cip_header[1] & CIP_SYT_MASK;
632e335425bSTakashi Sakamoto 
633e335425bSTakashi Sakamoto 	return 0;
634e335425bSTakashi Sakamoto }
635e335425bSTakashi Sakamoto 
63698e3e43bSTakashi Sakamoto static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle,
63798e3e43bSTakashi Sakamoto 			       const __be32 *ctx_header,
638a35463d1STakashi Sakamoto 			       unsigned int *data_blocks,
639a35463d1STakashi Sakamoto 			       unsigned int *data_block_counter,
640814b4312STakashi Sakamoto 			       unsigned int *syt, unsigned int packet_index, unsigned int index)
641e335425bSTakashi Sakamoto {
642ebd2a647STakashi Sakamoto 	unsigned int payload_length;
643f11453c7STakashi Sakamoto 	const __be32 *cip_header;
644395f41e2STakashi Sakamoto 	unsigned int cip_header_size;
645e335425bSTakashi Sakamoto 	int err;
646e335425bSTakashi Sakamoto 
647ebd2a647STakashi Sakamoto 	payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT;
648395f41e2STakashi Sakamoto 
649395f41e2STakashi Sakamoto 	if (!(s->flags & CIP_NO_HEADER))
650*67d92ee7STakashi Sakamoto 		cip_header_size = CIP_HEADER_SIZE;
651395f41e2STakashi Sakamoto 	else
652395f41e2STakashi Sakamoto 		cip_header_size = 0;
653395f41e2STakashi Sakamoto 
654ebd2a647STakashi Sakamoto 	if (payload_length > cip_header_size + s->ctx_data.tx.max_ctx_payload_length) {
655e335425bSTakashi Sakamoto 		dev_err(&s->unit->device,
656e335425bSTakashi Sakamoto 			"Detect jumbo payload: %04x %04x\n",
657ebd2a647STakashi Sakamoto 			payload_length, cip_header_size + s->ctx_data.tx.max_ctx_payload_length);
658e335425bSTakashi Sakamoto 		return -EIO;
659e335425bSTakashi Sakamoto 	}
660e335425bSTakashi Sakamoto 
661395f41e2STakashi Sakamoto 	if (cip_header_size > 0) {
662ebd2a647STakashi Sakamoto 		if (payload_length >= cip_header_size) {
663*67d92ee7STakashi Sakamoto 			cip_header = ctx_header + IR_CTX_HEADER_DEFAULT_QUADLETS;
6644fd18787STakashi Sakamoto 			err = check_cip_header(s, cip_header, payload_length - cip_header_size,
6654fd18787STakashi Sakamoto 					       data_blocks, data_block_counter, syt);
666b8b0e24cSTakashi Sakamoto 			if (err < 0)
667e335425bSTakashi Sakamoto 				return err;
668947b437eSTakashi Sakamoto 		} else {
669c09010eeSTakashi Sakamoto 			// Handle the cycle so that empty packet arrives.
670c09010eeSTakashi Sakamoto 			cip_header = NULL;
671c09010eeSTakashi Sakamoto 			*data_blocks = 0;
672c09010eeSTakashi Sakamoto 			*syt = 0;
673c09010eeSTakashi Sakamoto 		}
674c09010eeSTakashi Sakamoto 	} else {
675947b437eSTakashi Sakamoto 		cip_header = NULL;
67676864868STakashi Sakamoto 		err = 0;
677ebd2a647STakashi Sakamoto 		*data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets;
67898e3e43bSTakashi Sakamoto 		*syt = 0;
6797fbf9096STakashi Sakamoto 
680a35463d1STakashi Sakamoto 		if (*data_block_counter == UINT_MAX)
681a35463d1STakashi Sakamoto 			*data_block_counter = 0;
682947b437eSTakashi Sakamoto 	}
683e335425bSTakashi Sakamoto 
684ebd2a647STakashi Sakamoto 	trace_amdtp_packet(s, cycle, cip_header, payload_length, *data_blocks,
685814b4312STakashi Sakamoto 			   *data_block_counter, packet_index, index);
68664d0bf4dSTakashi Sakamoto 
68776864868STakashi Sakamoto 	return err;
688d67c46b9STakashi Sakamoto }
689d67c46b9STakashi Sakamoto 
69026cd1e58STakashi Sakamoto // In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On
69126cd1e58STakashi Sakamoto // the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent
69226cd1e58STakashi Sakamoto // it. Thus, via Linux firewire subsystem, we can get the 3 bits for second.
6933e106f4fSTakashi Sakamoto static inline u32 compute_ohci_cycle_count(__be32 ctx_header_tstamp)
69473fc7f08STakashi Sakamoto {
69526cd1e58STakashi Sakamoto 	u32 tstamp = be32_to_cpu(ctx_header_tstamp) & HEADER_TSTAMP_MASK;
69673fc7f08STakashi Sakamoto 	return (((tstamp >> 13) & 0x07) * 8000) + (tstamp & 0x1fff);
69773fc7f08STakashi Sakamoto }
69873fc7f08STakashi Sakamoto 
6993e106f4fSTakashi Sakamoto static inline u32 increment_ohci_cycle_count(u32 cycle, unsigned int addend)
70073fc7f08STakashi Sakamoto {
70173fc7f08STakashi Sakamoto 	cycle += addend;
7023e106f4fSTakashi Sakamoto 	if (cycle >= OHCI_SECOND_MODULUS * CYCLES_PER_SECOND)
7033e106f4fSTakashi Sakamoto 		cycle -= OHCI_SECOND_MODULUS * CYCLES_PER_SECOND;
70473fc7f08STakashi Sakamoto 	return cycle;
70573fc7f08STakashi Sakamoto }
70673fc7f08STakashi Sakamoto 
707705794c5STakashi Sakamoto static int compare_ohci_cycle_count(u32 lval, u32 rval)
708705794c5STakashi Sakamoto {
709705794c5STakashi Sakamoto 	if (lval == rval)
710705794c5STakashi Sakamoto 		return 0;
711705794c5STakashi Sakamoto 	else if (lval < rval && rval - lval < OHCI_SECOND_MODULUS * CYCLES_PER_SECOND / 2)
712705794c5STakashi Sakamoto 		return -1;
713705794c5STakashi Sakamoto 	else
714705794c5STakashi Sakamoto 		return 1;
715705794c5STakashi Sakamoto }
716705794c5STakashi Sakamoto 
71726cd1e58STakashi Sakamoto // Align to actual cycle count for the packet which is going to be scheduled.
718a0e02331STakashi Sakamoto // This module queued the same number of isochronous cycle as the size of queue
719a0e02331STakashi Sakamoto // to kip isochronous cycle, therefore it's OK to just increment the cycle by
720a0e02331STakashi Sakamoto // the size of queue for scheduled cycle.
7213e106f4fSTakashi Sakamoto static inline u32 compute_ohci_it_cycle(const __be32 ctx_header_tstamp,
722a0e02331STakashi Sakamoto 					unsigned int queue_size)
72326cd1e58STakashi Sakamoto {
7243e106f4fSTakashi Sakamoto 	u32 cycle = compute_ohci_cycle_count(ctx_header_tstamp);
7253e106f4fSTakashi Sakamoto 	return increment_ohci_cycle_count(cycle, queue_size);
72626cd1e58STakashi Sakamoto }
72726cd1e58STakashi Sakamoto 
728753e7179STakashi Sakamoto static int generate_device_pkt_descs(struct amdtp_stream *s,
729753e7179STakashi Sakamoto 				     struct pkt_desc *descs,
730753e7179STakashi Sakamoto 				     const __be32 *ctx_header,
73173246fc4STakashi Sakamoto 				     unsigned int packets,
73273246fc4STakashi Sakamoto 				     unsigned int *desc_count)
733753e7179STakashi Sakamoto {
734705794c5STakashi Sakamoto 	unsigned int next_cycle = s->next_cycle;
735753e7179STakashi Sakamoto 	unsigned int dbc = s->data_block_counter;
736814b4312STakashi Sakamoto 	unsigned int packet_index = s->packet_index;
737814b4312STakashi Sakamoto 	unsigned int queue_size = s->queue_size;
738753e7179STakashi Sakamoto 	int i;
739753e7179STakashi Sakamoto 	int err;
740753e7179STakashi Sakamoto 
74173246fc4STakashi Sakamoto 	*desc_count = 0;
742753e7179STakashi Sakamoto 	for (i = 0; i < packets; ++i) {
74373246fc4STakashi Sakamoto 		struct pkt_desc *desc = descs + *desc_count;
744753e7179STakashi Sakamoto 		unsigned int cycle;
745705794c5STakashi Sakamoto 		bool lost;
746753e7179STakashi Sakamoto 		unsigned int data_blocks;
747753e7179STakashi Sakamoto 		unsigned int syt;
748753e7179STakashi Sakamoto 
7493e106f4fSTakashi Sakamoto 		cycle = compute_ohci_cycle_count(ctx_header[1]);
750705794c5STakashi Sakamoto 		lost = (next_cycle != cycle);
751705794c5STakashi Sakamoto 		if (lost) {
752705794c5STakashi Sakamoto 			if (s->flags & CIP_NO_HEADER) {
753705794c5STakashi Sakamoto 				// Fireface skips transmission just for an isoc cycle corresponding
754705794c5STakashi Sakamoto 				// to empty packet.
75573246fc4STakashi Sakamoto 				unsigned int prev_cycle = next_cycle;
75673246fc4STakashi Sakamoto 
757705794c5STakashi Sakamoto 				next_cycle = increment_ohci_cycle_count(next_cycle, 1);
758705794c5STakashi Sakamoto 				lost = (next_cycle != cycle);
75973246fc4STakashi Sakamoto 				if (!lost) {
76073246fc4STakashi Sakamoto 					// Prepare a description for the skipped cycle for
76173246fc4STakashi Sakamoto 					// sequence replay.
76273246fc4STakashi Sakamoto 					desc->cycle = prev_cycle;
76373246fc4STakashi Sakamoto 					desc->syt = 0;
76473246fc4STakashi Sakamoto 					desc->data_blocks = 0;
76573246fc4STakashi Sakamoto 					desc->data_block_counter = dbc;
76673246fc4STakashi Sakamoto 					desc->ctx_payload = NULL;
76773246fc4STakashi Sakamoto 					++desc;
76873246fc4STakashi Sakamoto 					++(*desc_count);
76973246fc4STakashi Sakamoto 				}
770705794c5STakashi Sakamoto 			} else if (s->flags & CIP_JUMBO_PAYLOAD) {
771705794c5STakashi Sakamoto 				// OXFW970 skips transmission for several isoc cycles during
77273246fc4STakashi Sakamoto 				// asynchronous transaction. The sequence replay is impossible due
77373246fc4STakashi Sakamoto 				// to the reason.
774705794c5STakashi Sakamoto 				unsigned int safe_cycle = increment_ohci_cycle_count(next_cycle,
775705794c5STakashi Sakamoto 								IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES);
776705794c5STakashi Sakamoto 				lost = (compare_ohci_cycle_count(safe_cycle, cycle) > 0);
777705794c5STakashi Sakamoto 			}
778705794c5STakashi Sakamoto 			if (lost) {
779705794c5STakashi Sakamoto 				dev_err(&s->unit->device, "Detect discontinuity of cycle: %d %d\n",
780705794c5STakashi Sakamoto 					next_cycle, cycle);
781705794c5STakashi Sakamoto 				return -EIO;
782705794c5STakashi Sakamoto 			}
783705794c5STakashi Sakamoto 		}
784753e7179STakashi Sakamoto 
785ebd2a647STakashi Sakamoto 		err = parse_ir_ctx_header(s, cycle, ctx_header, &data_blocks, &dbc, &syt,
786ebd2a647STakashi Sakamoto 					  packet_index, i);
787753e7179STakashi Sakamoto 		if (err < 0)
788753e7179STakashi Sakamoto 			return err;
789753e7179STakashi Sakamoto 
790753e7179STakashi Sakamoto 		desc->cycle = cycle;
791753e7179STakashi Sakamoto 		desc->syt = syt;
792753e7179STakashi Sakamoto 		desc->data_blocks = data_blocks;
793753e7179STakashi Sakamoto 		desc->data_block_counter = dbc;
794814b4312STakashi Sakamoto 		desc->ctx_payload = s->buffer.packets[packet_index].buffer;
795753e7179STakashi Sakamoto 
796753e7179STakashi Sakamoto 		if (!(s->flags & CIP_DBC_IS_END_EVENT))
797753e7179STakashi Sakamoto 			dbc = (dbc + desc->data_blocks) & 0xff;
798753e7179STakashi Sakamoto 
799705794c5STakashi Sakamoto 		next_cycle = increment_ohci_cycle_count(next_cycle, 1);
80073246fc4STakashi Sakamoto 		++(*desc_count);
801705794c5STakashi Sakamoto 		ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header);
802814b4312STakashi Sakamoto 		packet_index = (packet_index + 1) % queue_size;
803753e7179STakashi Sakamoto 	}
804753e7179STakashi Sakamoto 
805705794c5STakashi Sakamoto 	s->next_cycle = next_cycle;
806753e7179STakashi Sakamoto 	s->data_block_counter = dbc;
807753e7179STakashi Sakamoto 
808753e7179STakashi Sakamoto 	return 0;
809753e7179STakashi Sakamoto }
810753e7179STakashi Sakamoto 
81183cfb5c5STakashi Sakamoto static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle,
81283cfb5c5STakashi Sakamoto 				unsigned int transfer_delay)
81383cfb5c5STakashi Sakamoto {
81483cfb5c5STakashi Sakamoto 	unsigned int syt;
81583cfb5c5STakashi Sakamoto 
81683cfb5c5STakashi Sakamoto 	syt_offset += transfer_delay;
81783cfb5c5STakashi Sakamoto 	syt = ((cycle + syt_offset / TICKS_PER_CYCLE) << 12) |
81883cfb5c5STakashi Sakamoto 	      (syt_offset % TICKS_PER_CYCLE);
81983cfb5c5STakashi Sakamoto 	return syt & CIP_SYT_MASK;
82083cfb5c5STakashi Sakamoto }
82183cfb5c5STakashi Sakamoto 
82269efd5c4STakashi Sakamoto static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs,
82369efd5c4STakashi Sakamoto 			       const __be32 *ctx_header, unsigned int packets,
82469efd5c4STakashi Sakamoto 			       const struct seq_desc *seq_descs,
82569efd5c4STakashi Sakamoto 			       unsigned int seq_size)
826f4f6ae7bSTakashi Sakamoto {
827f4f6ae7bSTakashi Sakamoto 	unsigned int dbc = s->data_block_counter;
82869efd5c4STakashi Sakamoto 	unsigned int seq_index = s->ctx_data.rx.seq_index;
829f4f6ae7bSTakashi Sakamoto 	int i;
830f4f6ae7bSTakashi Sakamoto 
831f4f6ae7bSTakashi Sakamoto 	for (i = 0; i < packets; ++i) {
832f4f6ae7bSTakashi Sakamoto 		struct pkt_desc *desc = descs + i;
833a0e02331STakashi Sakamoto 		unsigned int index = (s->packet_index + i) % s->queue_size;
83469efd5c4STakashi Sakamoto 		const struct seq_desc *seq = seq_descs + seq_index;
83569efd5c4STakashi Sakamoto 		unsigned int syt;
836f4f6ae7bSTakashi Sakamoto 
8373e106f4fSTakashi Sakamoto 		desc->cycle = compute_ohci_it_cycle(*ctx_header, s->queue_size);
83869efd5c4STakashi Sakamoto 
83969efd5c4STakashi Sakamoto 		syt = seq->syt_offset;
84069efd5c4STakashi Sakamoto 		if (syt != CIP_SYT_NO_INFO) {
84169efd5c4STakashi Sakamoto 			syt = compute_syt(syt, desc->cycle,
84283cfb5c5STakashi Sakamoto 					  s->ctx_data.rx.transfer_delay);
84383cfb5c5STakashi Sakamoto 		}
84469efd5c4STakashi Sakamoto 		desc->syt = syt;
84569efd5c4STakashi Sakamoto 		desc->data_blocks = seq->data_blocks;
846f4f6ae7bSTakashi Sakamoto 
847f4f6ae7bSTakashi Sakamoto 		if (s->flags & CIP_DBC_IS_END_EVENT)
848f4f6ae7bSTakashi Sakamoto 			dbc = (dbc + desc->data_blocks) & 0xff;
849f4f6ae7bSTakashi Sakamoto 
850f4f6ae7bSTakashi Sakamoto 		desc->data_block_counter = dbc;
851f4f6ae7bSTakashi Sakamoto 
852f4f6ae7bSTakashi Sakamoto 		if (!(s->flags & CIP_DBC_IS_END_EVENT))
853f4f6ae7bSTakashi Sakamoto 			dbc = (dbc + desc->data_blocks) & 0xff;
854f4f6ae7bSTakashi Sakamoto 
855f4f6ae7bSTakashi Sakamoto 		desc->ctx_payload = s->buffer.packets[index].buffer;
856f4f6ae7bSTakashi Sakamoto 
85769efd5c4STakashi Sakamoto 		seq_index = (seq_index + 1) % seq_size;
85869efd5c4STakashi Sakamoto 
859f4f6ae7bSTakashi Sakamoto 		++ctx_header;
860f4f6ae7bSTakashi Sakamoto 	}
861f4f6ae7bSTakashi Sakamoto 
862f4f6ae7bSTakashi Sakamoto 	s->data_block_counter = dbc;
86369efd5c4STakashi Sakamoto 	s->ctx_data.rx.seq_index = seq_index;
864f4f6ae7bSTakashi Sakamoto }
865f4f6ae7bSTakashi Sakamoto 
866fce9b013STakashi Sakamoto static inline void cancel_stream(struct amdtp_stream *s)
867fce9b013STakashi Sakamoto {
868fce9b013STakashi Sakamoto 	s->packet_index = -1;
8692b3d2987STakashi Iwai 	if (current_work() == &s->period_work)
870fce9b013STakashi Sakamoto 		amdtp_stream_pcm_abort(s);
871fce9b013STakashi Sakamoto 	WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
872fce9b013STakashi Sakamoto }
873fce9b013STakashi Sakamoto 
8740f5cfcb2STakashi Sakamoto static void process_ctx_payloads(struct amdtp_stream *s,
8750f5cfcb2STakashi Sakamoto 				 const struct pkt_desc *descs,
8760f5cfcb2STakashi Sakamoto 				 unsigned int packets)
8770f5cfcb2STakashi Sakamoto {
8789a738ad1STakashi Sakamoto 	struct snd_pcm_substream *pcm;
8790f5cfcb2STakashi Sakamoto 	unsigned int pcm_frames;
8800f5cfcb2STakashi Sakamoto 
8819a738ad1STakashi Sakamoto 	pcm = READ_ONCE(s->pcm);
8829a738ad1STakashi Sakamoto 	pcm_frames = s->process_ctx_payloads(s, descs, packets, pcm);
8839a738ad1STakashi Sakamoto 	if (pcm)
8840f5cfcb2STakashi Sakamoto 		update_pcm_pointers(s, pcm, pcm_frames);
8850f5cfcb2STakashi Sakamoto }
8860f5cfcb2STakashi Sakamoto 
88773fc7f08STakashi Sakamoto static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
888d67c46b9STakashi Sakamoto 				size_t header_length, void *header,
889d67c46b9STakashi Sakamoto 				void *private_data)
890d67c46b9STakashi Sakamoto {
891d67c46b9STakashi Sakamoto 	struct amdtp_stream *s = private_data;
89269efd5c4STakashi Sakamoto 	const struct amdtp_domain *d = s->domain;
89326cd1e58STakashi Sakamoto 	const __be32 *ctx_header = header;
8946d60b7a3STakashi Sakamoto 	unsigned int events_per_period = d->events_per_period;
89560dd4929STakashi Sakamoto 	unsigned int event_count = s->ctx_data.rx.event_count;
896a0e02331STakashi Sakamoto 	unsigned int packets;
8970dcb4efbSTakashi Sakamoto 	int i;
898d67c46b9STakashi Sakamoto 
899d67c46b9STakashi Sakamoto 	if (s->packet_index < 0)
900d67c46b9STakashi Sakamoto 		return;
901d67c46b9STakashi Sakamoto 
902a0e02331STakashi Sakamoto 	// Calculate the number of packets in buffer and check XRUN.
903a0e02331STakashi Sakamoto 	packets = header_length / sizeof(*ctx_header);
904a0e02331STakashi Sakamoto 
905d32872f3STakashi Sakamoto 	generate_pkt_descs(s, s->pkt_descs, ctx_header, packets, d->seq.descs,
906d32872f3STakashi Sakamoto 			   d->seq.size);
907f4f6ae7bSTakashi Sakamoto 
9080f5cfcb2STakashi Sakamoto 	process_ctx_payloads(s, s->pkt_descs, packets);
9095e2ece0fSTakashi Sakamoto 
9105e2ece0fSTakashi Sakamoto 	for (i = 0; i < packets; ++i) {
9115e2ece0fSTakashi Sakamoto 		const struct pkt_desc *desc = s->pkt_descs + i;
912f4f6ae7bSTakashi Sakamoto 		unsigned int syt;
9136bc1a269STakashi Sakamoto 		struct {
9146bc1a269STakashi Sakamoto 			struct fw_iso_packet params;
915*67d92ee7STakashi Sakamoto 			__be32 header[CIP_HEADER_QUADLETS];
9166bc1a269STakashi Sakamoto 		} template = { {0}, {0} };
917e229853dSTakashi Sakamoto 		bool sched_irq = false;
918860d798cSTakashi Sakamoto 
919f4f6ae7bSTakashi Sakamoto 		if (s->ctx_data.rx.syt_override < 0)
920f4f6ae7bSTakashi Sakamoto 			syt = desc->syt;
921f4f6ae7bSTakashi Sakamoto 		else
9223baf3053STakashi Sakamoto 			syt = s->ctx_data.rx.syt_override;
9233baf3053STakashi Sakamoto 
924f4f6ae7bSTakashi Sakamoto 		build_it_pkt_header(s, desc->cycle, &template.params,
925f4f6ae7bSTakashi Sakamoto 				    desc->data_blocks, desc->data_block_counter,
926f4f6ae7bSTakashi Sakamoto 				    syt, i);
9276bc1a269STakashi Sakamoto 
9282472cfb3STakashi Sakamoto 		if (s == s->domain->irq_target) {
929e229853dSTakashi Sakamoto 			event_count += desc->data_blocks;
930e229853dSTakashi Sakamoto 			if (event_count >= events_per_period) {
931e229853dSTakashi Sakamoto 				event_count -= events_per_period;
932e229853dSTakashi Sakamoto 				sched_irq = true;
933e229853dSTakashi Sakamoto 			}
93460dd4929STakashi Sakamoto 		}
935e229853dSTakashi Sakamoto 
936e229853dSTakashi Sakamoto 		if (queue_out_packet(s, &template.params, sched_irq) < 0) {
937fce9b013STakashi Sakamoto 			cancel_stream(s);
938d67c46b9STakashi Sakamoto 			return;
939d67c46b9STakashi Sakamoto 		}
940d67c46b9STakashi Sakamoto 	}
941d67c46b9STakashi Sakamoto 
94260dd4929STakashi Sakamoto 	s->ctx_data.rx.event_count = event_count;
943d67c46b9STakashi Sakamoto }
944d67c46b9STakashi Sakamoto 
94573fc7f08STakashi Sakamoto static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
946d67c46b9STakashi Sakamoto 			       size_t header_length, void *header,
947d67c46b9STakashi Sakamoto 			       void *private_data)
948d67c46b9STakashi Sakamoto {
949d67c46b9STakashi Sakamoto 	struct amdtp_stream *s = private_data;
950cc4f8e91STakashi Sakamoto 	__be32 *ctx_header = header;
951e229853dSTakashi Sakamoto 	unsigned int packets;
95273246fc4STakashi Sakamoto 	unsigned int desc_count;
953753e7179STakashi Sakamoto 	int i;
954753e7179STakashi Sakamoto 	int err;
955d67c46b9STakashi Sakamoto 
956d67c46b9STakashi Sakamoto 	if (s->packet_index < 0)
957d67c46b9STakashi Sakamoto 		return;
958d67c46b9STakashi Sakamoto 
959a0e02331STakashi Sakamoto 	// Calculate the number of packets in buffer and check XRUN.
960d3d10a4aSTakashi Sakamoto 	packets = header_length / s->ctx_data.tx.ctx_header_size;
961f90e2dedSTakashi Sakamoto 
96273246fc4STakashi Sakamoto 	desc_count = 0;
96373246fc4STakashi Sakamoto 	err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets, &desc_count);
964753e7179STakashi Sakamoto 	if (err < 0) {
965753e7179STakashi Sakamoto 		if (err != -EAGAIN) {
966753e7179STakashi Sakamoto 			cancel_stream(s);
967753e7179STakashi Sakamoto 			return;
968753e7179STakashi Sakamoto 		}
9695e2ece0fSTakashi Sakamoto 	} else {
97073246fc4STakashi Sakamoto 		process_ctx_payloads(s, s->pkt_descs, desc_count);
9715e2ece0fSTakashi Sakamoto 	}
9725e2ece0fSTakashi Sakamoto 
9735e2ece0fSTakashi Sakamoto 	for (i = 0; i < packets; ++i) {
9745e2ece0fSTakashi Sakamoto 		struct fw_iso_packet params = {0};
975a35463d1STakashi Sakamoto 
97660dd4929STakashi Sakamoto 		if (queue_in_packet(s, &params) < 0) {
977753e7179STakashi Sakamoto 			cancel_stream(s);
978753e7179STakashi Sakamoto 			return;
979753e7179STakashi Sakamoto 		}
980d67c46b9STakashi Sakamoto 	}
981d67c46b9STakashi Sakamoto }
982d67c46b9STakashi Sakamoto 
9831a4be183STakashi Sakamoto static void pool_ideal_seq_descs(struct amdtp_domain *d, unsigned int packets)
9841a4be183STakashi Sakamoto {
9851a4be183STakashi Sakamoto 	struct amdtp_stream *irq_target = d->irq_target;
986d32872f3STakashi Sakamoto 	unsigned int seq_tail = d->seq.tail;
987d32872f3STakashi Sakamoto 	unsigned int seq_size = d->seq.size;
9881a4be183STakashi Sakamoto 	unsigned int min_avail;
9891a4be183STakashi Sakamoto 	struct amdtp_stream *s;
9901a4be183STakashi Sakamoto 
991d32872f3STakashi Sakamoto 	min_avail = d->seq.size;
9921a4be183STakashi Sakamoto 	list_for_each_entry(s, &d->streams, list) {
9931a4be183STakashi Sakamoto 		unsigned int seq_index;
9941a4be183STakashi Sakamoto 		unsigned int avail;
9951a4be183STakashi Sakamoto 
9961a4be183STakashi Sakamoto 		if (s->direction == AMDTP_IN_STREAM)
9971a4be183STakashi Sakamoto 			continue;
9981a4be183STakashi Sakamoto 
9991a4be183STakashi Sakamoto 		seq_index = s->ctx_data.rx.seq_index;
1000d32872f3STakashi Sakamoto 		avail = d->seq.tail;
10011a4be183STakashi Sakamoto 		if (seq_index > avail)
1002d32872f3STakashi Sakamoto 			avail += d->seq.size;
10031a4be183STakashi Sakamoto 		avail -= seq_index;
10041a4be183STakashi Sakamoto 
10051a4be183STakashi Sakamoto 		if (avail < min_avail)
10061a4be183STakashi Sakamoto 			min_avail = avail;
10071a4be183STakashi Sakamoto 	}
10081a4be183STakashi Sakamoto 
10091a4be183STakashi Sakamoto 	while (min_avail < packets) {
1010d32872f3STakashi Sakamoto 		struct seq_desc *desc = d->seq.descs + seq_tail;
10111a4be183STakashi Sakamoto 
10121a4be183STakashi Sakamoto 		desc->syt_offset = calculate_syt_offset(&d->last_syt_offset,
10131a4be183STakashi Sakamoto 					&d->syt_offset_state, irq_target->sfc);
10141a4be183STakashi Sakamoto 		desc->data_blocks = calculate_data_blocks(&d->data_block_state,
10151a4be183STakashi Sakamoto 				!!(irq_target->flags & CIP_BLOCKING),
10161a4be183STakashi Sakamoto 				desc->syt_offset == CIP_SYT_NO_INFO,
10171a4be183STakashi Sakamoto 				irq_target->syt_interval, irq_target->sfc);
10181a4be183STakashi Sakamoto 
10191a4be183STakashi Sakamoto 		++seq_tail;
10201a4be183STakashi Sakamoto 		seq_tail %= seq_size;
10211a4be183STakashi Sakamoto 
10221a4be183STakashi Sakamoto 		++min_avail;
10231a4be183STakashi Sakamoto 	}
10241a4be183STakashi Sakamoto 
1025d32872f3STakashi Sakamoto 	d->seq.tail = seq_tail;
10261a4be183STakashi Sakamoto }
10271a4be183STakashi Sakamoto 
10282472cfb3STakashi Sakamoto static void irq_target_callback(struct fw_iso_context *context, u32 tstamp,
10292472cfb3STakashi Sakamoto 				size_t header_length, void *header,
10302472cfb3STakashi Sakamoto 				void *private_data)
103160dd4929STakashi Sakamoto {
10322472cfb3STakashi Sakamoto 	struct amdtp_stream *irq_target = private_data;
10332472cfb3STakashi Sakamoto 	struct amdtp_domain *d = irq_target->domain;
10341a4be183STakashi Sakamoto 	unsigned int packets = header_length / sizeof(__be32);
103560dd4929STakashi Sakamoto 	struct amdtp_stream *s;
103660dd4929STakashi Sakamoto 
10371a4be183STakashi Sakamoto 	// Record enough entries with extra 3 cycles at least.
10381a4be183STakashi Sakamoto 	pool_ideal_seq_descs(d, packets + 3);
10391a4be183STakashi Sakamoto 
104060dd4929STakashi Sakamoto 	out_stream_callback(context, tstamp, header_length, header, irq_target);
104160dd4929STakashi Sakamoto 	if (amdtp_streaming_error(irq_target))
104260dd4929STakashi Sakamoto 		goto error;
104360dd4929STakashi Sakamoto 
104460dd4929STakashi Sakamoto 	list_for_each_entry(s, &d->streams, list) {
104560dd4929STakashi Sakamoto 		if (s != irq_target && amdtp_stream_running(s)) {
104660dd4929STakashi Sakamoto 			fw_iso_context_flush_completions(s->context);
104760dd4929STakashi Sakamoto 			if (amdtp_streaming_error(s))
104860dd4929STakashi Sakamoto 				goto error;
104960dd4929STakashi Sakamoto 		}
105060dd4929STakashi Sakamoto 	}
105160dd4929STakashi Sakamoto 
105260dd4929STakashi Sakamoto 	return;
105360dd4929STakashi Sakamoto error:
105460dd4929STakashi Sakamoto 	if (amdtp_stream_running(irq_target))
105560dd4929STakashi Sakamoto 		cancel_stream(irq_target);
105660dd4929STakashi Sakamoto 
105760dd4929STakashi Sakamoto 	list_for_each_entry(s, &d->streams, list) {
105860dd4929STakashi Sakamoto 		if (amdtp_stream_running(s))
105960dd4929STakashi Sakamoto 			cancel_stream(s);
106060dd4929STakashi Sakamoto 	}
106160dd4929STakashi Sakamoto }
106260dd4929STakashi Sakamoto 
106360dd4929STakashi Sakamoto // this is executed one time.
1064d67c46b9STakashi Sakamoto static void amdtp_stream_first_callback(struct fw_iso_context *context,
106573fc7f08STakashi Sakamoto 					u32 tstamp, size_t header_length,
1066d67c46b9STakashi Sakamoto 					void *header, void *private_data)
1067d67c46b9STakashi Sakamoto {
1068d67c46b9STakashi Sakamoto 	struct amdtp_stream *s = private_data;
106926cd1e58STakashi Sakamoto 	const __be32 *ctx_header = header;
1070a04513f8STakashi Sakamoto 	u32 cycle;
1071d67c46b9STakashi Sakamoto 
1072d67c46b9STakashi Sakamoto 	/*
1073d67c46b9STakashi Sakamoto 	 * For in-stream, first packet has come.
1074d67c46b9STakashi Sakamoto 	 * For out-stream, prepared to transmit first packet
1075d67c46b9STakashi Sakamoto 	 */
1076d67c46b9STakashi Sakamoto 	s->callbacked = true;
1077d67c46b9STakashi Sakamoto 	wake_up(&s->callback_wait);
1078d67c46b9STakashi Sakamoto 
1079cc4f8e91STakashi Sakamoto 	if (s->direction == AMDTP_IN_STREAM) {
10803e106f4fSTakashi Sakamoto 		cycle = compute_ohci_cycle_count(ctx_header[1]);
1081705794c5STakashi Sakamoto 		s->next_cycle = cycle;
1082a04513f8STakashi Sakamoto 
1083d67c46b9STakashi Sakamoto 		context->callback.sc = in_stream_callback;
1084a04513f8STakashi Sakamoto 	} else {
10853e106f4fSTakashi Sakamoto 		cycle = compute_ohci_it_cycle(*ctx_header, s->queue_size);
108626cd1e58STakashi Sakamoto 
10872472cfb3STakashi Sakamoto 		if (s == s->domain->irq_target)
10882472cfb3STakashi Sakamoto 			context->callback.sc = irq_target_callback;
10892472cfb3STakashi Sakamoto 		else
1090d67c46b9STakashi Sakamoto 			context->callback.sc = out_stream_callback;
1091a04513f8STakashi Sakamoto 	}
1092a04513f8STakashi Sakamoto 
1093a04513f8STakashi Sakamoto 	s->start_cycle = cycle;
1094d67c46b9STakashi Sakamoto 
109573fc7f08STakashi Sakamoto 	context->callback.sc(context, tstamp, header_length, header, s);
1096d67c46b9STakashi Sakamoto }
1097d67c46b9STakashi Sakamoto 
1098d67c46b9STakashi Sakamoto /**
1099d67c46b9STakashi Sakamoto  * amdtp_stream_start - start transferring packets
1100d67c46b9STakashi Sakamoto  * @s: the AMDTP stream to start
1101d67c46b9STakashi Sakamoto  * @channel: the isochronous channel on the bus
1102d67c46b9STakashi Sakamoto  * @speed: firewire speed code
1103acfedcbeSTakashi Sakamoto  * @start_cycle: the isochronous cycle to start the context. Start immediately
1104acfedcbeSTakashi Sakamoto  *		 if negative value is given.
1105af86b0b1STakashi Sakamoto  * @queue_size: The number of packets in the queue.
1106af86b0b1STakashi Sakamoto  * @idle_irq_interval: the interval to queue packet during initial state.
1107d67c46b9STakashi Sakamoto  *
1108d67c46b9STakashi Sakamoto  * The stream cannot be started until it has been configured with
1109d67c46b9STakashi Sakamoto  * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI
1110d67c46b9STakashi Sakamoto  * device can be started.
1111d67c46b9STakashi Sakamoto  */
1112a0e02331STakashi Sakamoto static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
1113af86b0b1STakashi Sakamoto 			      int start_cycle, unsigned int queue_size,
1114af86b0b1STakashi Sakamoto 			      unsigned int idle_irq_interval)
1115d67c46b9STakashi Sakamoto {
11162472cfb3STakashi Sakamoto 	bool is_irq_target = (s == s->domain->irq_target);
1117d3d10a4aSTakashi Sakamoto 	unsigned int ctx_header_size;
1118f11453c7STakashi Sakamoto 	unsigned int max_ctx_payload_size;
1119d67c46b9STakashi Sakamoto 	enum dma_data_direction dir;
1120d67c46b9STakashi Sakamoto 	int type, tag, err;
1121d67c46b9STakashi Sakamoto 
1122d67c46b9STakashi Sakamoto 	mutex_lock(&s->mutex);
1123d67c46b9STakashi Sakamoto 
1124d67c46b9STakashi Sakamoto 	if (WARN_ON(amdtp_stream_running(s) ||
1125d67c46b9STakashi Sakamoto 		    (s->data_block_quadlets < 1))) {
1126d67c46b9STakashi Sakamoto 		err = -EBADFD;
1127d67c46b9STakashi Sakamoto 		goto err_unlock;
1128d67c46b9STakashi Sakamoto 	}
1129d67c46b9STakashi Sakamoto 
1130d3d10a4aSTakashi Sakamoto 	if (s->direction == AMDTP_IN_STREAM) {
113160dd4929STakashi Sakamoto 		// NOTE: IT context should be used for constant IRQ.
113260dd4929STakashi Sakamoto 		if (is_irq_target) {
113360dd4929STakashi Sakamoto 			err = -EINVAL;
113460dd4929STakashi Sakamoto 			goto err_unlock;
113560dd4929STakashi Sakamoto 		}
113660dd4929STakashi Sakamoto 
1137d67c46b9STakashi Sakamoto 		s->data_block_counter = UINT_MAX;
1138d3d10a4aSTakashi Sakamoto 	} else {
1139d67c46b9STakashi Sakamoto 		s->data_block_counter = 0;
1140d3d10a4aSTakashi Sakamoto 	}
1141d67c46b9STakashi Sakamoto 
11421be4f21dSTakashi Sakamoto 	// initialize packet buffer.
11431be4f21dSTakashi Sakamoto 	max_ctx_payload_size = amdtp_stream_get_max_payload(s);
1144d67c46b9STakashi Sakamoto 	if (s->direction == AMDTP_IN_STREAM) {
1145d67c46b9STakashi Sakamoto 		dir = DMA_FROM_DEVICE;
1146d67c46b9STakashi Sakamoto 		type = FW_ISO_CONTEXT_RECEIVE;
11471be4f21dSTakashi Sakamoto 		if (!(s->flags & CIP_NO_HEADER)) {
1148*67d92ee7STakashi Sakamoto 			max_ctx_payload_size -= CIP_HEADER_SIZE;
1149f11453c7STakashi Sakamoto 			ctx_header_size = IR_CTX_HEADER_SIZE_CIP;
11501be4f21dSTakashi Sakamoto 		} else {
1151f11453c7STakashi Sakamoto 			ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP;
11521be4f21dSTakashi Sakamoto 		}
1153d67c46b9STakashi Sakamoto 	} else {
1154d67c46b9STakashi Sakamoto 		dir = DMA_TO_DEVICE;
1155d67c46b9STakashi Sakamoto 		type = FW_ISO_CONTEXT_TRANSMIT;
1156df9160b9STakashi Sakamoto 		ctx_header_size = 0;	// No effect for IT context.
1157f11453c7STakashi Sakamoto 
1158b18f0cfaSTakashi Sakamoto 		if (!(s->flags & CIP_NO_HEADER))
1159b18f0cfaSTakashi Sakamoto 			max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP;
1160b18f0cfaSTakashi Sakamoto 	}
1161f11453c7STakashi Sakamoto 
1162af86b0b1STakashi Sakamoto 	err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size,
1163f11453c7STakashi Sakamoto 				      max_ctx_payload_size, dir);
1164d67c46b9STakashi Sakamoto 	if (err < 0)
1165d67c46b9STakashi Sakamoto 		goto err_unlock;
1166af86b0b1STakashi Sakamoto 	s->queue_size = queue_size;
116760dd4929STakashi Sakamoto 
1168d67c46b9STakashi Sakamoto 	s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
1169d3d10a4aSTakashi Sakamoto 					  type, channel, speed, ctx_header_size,
11702472cfb3STakashi Sakamoto 					  amdtp_stream_first_callback, s);
1171d67c46b9STakashi Sakamoto 	if (IS_ERR(s->context)) {
1172d67c46b9STakashi Sakamoto 		err = PTR_ERR(s->context);
1173d67c46b9STakashi Sakamoto 		if (err == -EBUSY)
1174d67c46b9STakashi Sakamoto 			dev_err(&s->unit->device,
1175d67c46b9STakashi Sakamoto 				"no free stream on this controller\n");
1176d67c46b9STakashi Sakamoto 		goto err_buffer;
1177d67c46b9STakashi Sakamoto 	}
1178d67c46b9STakashi Sakamoto 
1179d67c46b9STakashi Sakamoto 	amdtp_stream_update(s);
1180d67c46b9STakashi Sakamoto 
1181d3d10a4aSTakashi Sakamoto 	if (s->direction == AMDTP_IN_STREAM) {
1182f11453c7STakashi Sakamoto 		s->ctx_data.tx.max_ctx_payload_length = max_ctx_payload_size;
1183d3d10a4aSTakashi Sakamoto 		s->ctx_data.tx.ctx_header_size = ctx_header_size;
1184d3d10a4aSTakashi Sakamoto 	}
118552759c09STakashi Sakamoto 
11863b196c39STakashi Sakamoto 	if (s->flags & CIP_NO_HEADER)
11873b196c39STakashi Sakamoto 		s->tag = TAG_NO_CIP_HEADER;
11883b196c39STakashi Sakamoto 	else
11893b196c39STakashi Sakamoto 		s->tag = TAG_CIP;
11903b196c39STakashi Sakamoto 
1191a0e02331STakashi Sakamoto 	s->pkt_descs = kcalloc(s->queue_size, sizeof(*s->pkt_descs),
119204130cf8STakashi Sakamoto 			       GFP_KERNEL);
119304130cf8STakashi Sakamoto 	if (!s->pkt_descs) {
119404130cf8STakashi Sakamoto 		err = -ENOMEM;
119504130cf8STakashi Sakamoto 		goto err_context;
119604130cf8STakashi Sakamoto 	}
119704130cf8STakashi Sakamoto 
1198d67c46b9STakashi Sakamoto 	s->packet_index = 0;
1199d67c46b9STakashi Sakamoto 	do {
12006007bf54STakashi Sakamoto 		struct fw_iso_packet params;
1201e229853dSTakashi Sakamoto 
1202b18f0cfaSTakashi Sakamoto 		if (s->direction == AMDTP_IN_STREAM) {
120360dd4929STakashi Sakamoto 			err = queue_in_packet(s, &params);
1204b18f0cfaSTakashi Sakamoto 		} else {
120560dd4929STakashi Sakamoto 			bool sched_irq = false;
120660dd4929STakashi Sakamoto 
1207b18f0cfaSTakashi Sakamoto 			params.header_length = 0;
1208b18f0cfaSTakashi Sakamoto 			params.payload_length = 0;
120960dd4929STakashi Sakamoto 
121060dd4929STakashi Sakamoto 			if (is_irq_target) {
121160dd4929STakashi Sakamoto 				sched_irq = !((s->packet_index + 1) %
121260dd4929STakashi Sakamoto 					      idle_irq_interval);
121360dd4929STakashi Sakamoto 			}
121460dd4929STakashi Sakamoto 
1215e229853dSTakashi Sakamoto 			err = queue_out_packet(s, &params, sched_irq);
1216b18f0cfaSTakashi Sakamoto 		}
1217d67c46b9STakashi Sakamoto 		if (err < 0)
121804130cf8STakashi Sakamoto 			goto err_pkt_descs;
1219d67c46b9STakashi Sakamoto 	} while (s->packet_index > 0);
1220d67c46b9STakashi Sakamoto 
1221d67c46b9STakashi Sakamoto 	/* NOTE: TAG1 matches CIP. This just affects in stream. */
1222d67c46b9STakashi Sakamoto 	tag = FW_ISO_CONTEXT_MATCH_TAG1;
12233b196c39STakashi Sakamoto 	if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER))
1224d67c46b9STakashi Sakamoto 		tag |= FW_ISO_CONTEXT_MATCH_TAG0;
1225d67c46b9STakashi Sakamoto 
1226d67c46b9STakashi Sakamoto 	s->callbacked = false;
1227acfedcbeSTakashi Sakamoto 	err = fw_iso_context_start(s->context, start_cycle, 0, tag);
1228d67c46b9STakashi Sakamoto 	if (err < 0)
122904130cf8STakashi Sakamoto 		goto err_pkt_descs;
1230d67c46b9STakashi Sakamoto 
1231d67c46b9STakashi Sakamoto 	mutex_unlock(&s->mutex);
1232d67c46b9STakashi Sakamoto 
1233d67c46b9STakashi Sakamoto 	return 0;
123404130cf8STakashi Sakamoto err_pkt_descs:
123504130cf8STakashi Sakamoto 	kfree(s->pkt_descs);
1236d67c46b9STakashi Sakamoto err_context:
1237d67c46b9STakashi Sakamoto 	fw_iso_context_destroy(s->context);
1238d67c46b9STakashi Sakamoto 	s->context = ERR_PTR(-1);
1239d67c46b9STakashi Sakamoto err_buffer:
1240d67c46b9STakashi Sakamoto 	iso_packets_buffer_destroy(&s->buffer, s->unit);
1241d67c46b9STakashi Sakamoto err_unlock:
1242d67c46b9STakashi Sakamoto 	mutex_unlock(&s->mutex);
1243d67c46b9STakashi Sakamoto 
1244d67c46b9STakashi Sakamoto 	return err;
1245d67c46b9STakashi Sakamoto }
1246d67c46b9STakashi Sakamoto 
1247d67c46b9STakashi Sakamoto /**
1248f890f9a0STakashi Sakamoto  * amdtp_domain_stream_pcm_pointer - get the PCM buffer position
1249f890f9a0STakashi Sakamoto  * @d: the AMDTP domain.
1250d67c46b9STakashi Sakamoto  * @s: the AMDTP stream that transports the PCM data
1251d67c46b9STakashi Sakamoto  *
1252d67c46b9STakashi Sakamoto  * Returns the current buffer position, in frames.
1253d67c46b9STakashi Sakamoto  */
1254f890f9a0STakashi Sakamoto unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
1255f890f9a0STakashi Sakamoto 					      struct amdtp_stream *s)
1256d67c46b9STakashi Sakamoto {
1257f890f9a0STakashi Sakamoto 	struct amdtp_stream *irq_target = d->irq_target;
1258f890f9a0STakashi Sakamoto 
1259f890f9a0STakashi Sakamoto 	if (irq_target && amdtp_stream_running(irq_target)) {
1260f890f9a0STakashi Sakamoto 		// This function is called in software IRQ context of
12612b3d2987STakashi Iwai 		// period_work or process context.
1262f890f9a0STakashi Sakamoto 		//
1263f890f9a0STakashi Sakamoto 		// When the software IRQ context was scheduled by software IRQ
1264f890f9a0STakashi Sakamoto 		// context of IT contexts, queued packets were already handled.
1265f890f9a0STakashi Sakamoto 		// Therefore, no need to flush the queue in buffer furthermore.
1266f890f9a0STakashi Sakamoto 		//
1267f890f9a0STakashi Sakamoto 		// When the process context reach here, some packets will be
1268f890f9a0STakashi Sakamoto 		// already queued in the buffer. These packets should be handled
1269f890f9a0STakashi Sakamoto 		// immediately to keep better granularity of PCM pointer.
1270f890f9a0STakashi Sakamoto 		//
1271f890f9a0STakashi Sakamoto 		// Later, the process context will sometimes schedules software
12722b3d2987STakashi Iwai 		// IRQ context of the period_work. Then, no need to flush the
1273f890f9a0STakashi Sakamoto 		// queue by the same reason as described in the above
12742b3d2987STakashi Iwai 		if (current_work() != &s->period_work) {
1275f890f9a0STakashi Sakamoto 			// Queued packet should be processed without any kernel
1276f890f9a0STakashi Sakamoto 			// preemption to keep latency against bus cycle.
1277f890f9a0STakashi Sakamoto 			preempt_disable();
1278f890f9a0STakashi Sakamoto 			fw_iso_context_flush_completions(irq_target->context);
1279f890f9a0STakashi Sakamoto 			preempt_enable();
1280f890f9a0STakashi Sakamoto 		}
1281f890f9a0STakashi Sakamoto 	}
1282d67c46b9STakashi Sakamoto 
12836aa7de05SMark Rutland 	return READ_ONCE(s->pcm_buffer_pointer);
1284d67c46b9STakashi Sakamoto }
1285f890f9a0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_pointer);
1286d67c46b9STakashi Sakamoto 
1287d67c46b9STakashi Sakamoto /**
1288e6dcc92fSTakashi Sakamoto  * amdtp_domain_stream_pcm_ack - acknowledge queued PCM frames
1289e6dcc92fSTakashi Sakamoto  * @d: the AMDTP domain.
1290875becf8STakashi Sakamoto  * @s: the AMDTP stream that transfers the PCM frames
1291875becf8STakashi Sakamoto  *
1292875becf8STakashi Sakamoto  * Returns zero always.
1293875becf8STakashi Sakamoto  */
1294e6dcc92fSTakashi Sakamoto int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s)
1295875becf8STakashi Sakamoto {
1296e6dcc92fSTakashi Sakamoto 	struct amdtp_stream *irq_target = d->irq_target;
1297e6dcc92fSTakashi Sakamoto 
1298e6dcc92fSTakashi Sakamoto 	// Process isochronous packets for recent isochronous cycle to handle
1299e6dcc92fSTakashi Sakamoto 	// queued PCM frames.
1300e6dcc92fSTakashi Sakamoto 	if (irq_target && amdtp_stream_running(irq_target)) {
1301e6dcc92fSTakashi Sakamoto 		// Queued packet should be processed without any kernel
1302e6dcc92fSTakashi Sakamoto 		// preemption to keep latency against bus cycle.
1303e6dcc92fSTakashi Sakamoto 		preempt_disable();
1304e6dcc92fSTakashi Sakamoto 		fw_iso_context_flush_completions(irq_target->context);
1305e6dcc92fSTakashi Sakamoto 		preempt_enable();
1306e6dcc92fSTakashi Sakamoto 	}
1307875becf8STakashi Sakamoto 
1308875becf8STakashi Sakamoto 	return 0;
1309875becf8STakashi Sakamoto }
1310e6dcc92fSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stream_pcm_ack);
1311875becf8STakashi Sakamoto 
1312875becf8STakashi Sakamoto /**
1313d67c46b9STakashi Sakamoto  * amdtp_stream_update - update the stream after a bus reset
1314d67c46b9STakashi Sakamoto  * @s: the AMDTP stream
1315d67c46b9STakashi Sakamoto  */
1316d67c46b9STakashi Sakamoto void amdtp_stream_update(struct amdtp_stream *s)
1317d67c46b9STakashi Sakamoto {
1318d67c46b9STakashi Sakamoto 	/* Precomputing. */
13196aa7de05SMark Rutland 	WRITE_ONCE(s->source_node_id_field,
13206aa7de05SMark Rutland                    (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & CIP_SID_MASK);
1321d67c46b9STakashi Sakamoto }
1322d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_update);
1323d67c46b9STakashi Sakamoto 
1324d67c46b9STakashi Sakamoto /**
1325d67c46b9STakashi Sakamoto  * amdtp_stream_stop - stop sending packets
1326d67c46b9STakashi Sakamoto  * @s: the AMDTP stream to stop
1327d67c46b9STakashi Sakamoto  *
1328d67c46b9STakashi Sakamoto  * All PCM and MIDI devices of the stream must be stopped before the stream
1329d67c46b9STakashi Sakamoto  * itself can be stopped.
1330d67c46b9STakashi Sakamoto  */
133174f94e41STakashi Sakamoto static void amdtp_stream_stop(struct amdtp_stream *s)
1332d67c46b9STakashi Sakamoto {
1333d67c46b9STakashi Sakamoto 	mutex_lock(&s->mutex);
1334d67c46b9STakashi Sakamoto 
1335d67c46b9STakashi Sakamoto 	if (!amdtp_stream_running(s)) {
1336d67c46b9STakashi Sakamoto 		mutex_unlock(&s->mutex);
1337d67c46b9STakashi Sakamoto 		return;
1338d67c46b9STakashi Sakamoto 	}
1339d67c46b9STakashi Sakamoto 
13402b3d2987STakashi Iwai 	cancel_work_sync(&s->period_work);
1341d67c46b9STakashi Sakamoto 	fw_iso_context_stop(s->context);
1342d67c46b9STakashi Sakamoto 	fw_iso_context_destroy(s->context);
1343d67c46b9STakashi Sakamoto 	s->context = ERR_PTR(-1);
1344d67c46b9STakashi Sakamoto 	iso_packets_buffer_destroy(&s->buffer, s->unit);
134504130cf8STakashi Sakamoto 	kfree(s->pkt_descs);
1346d67c46b9STakashi Sakamoto 
1347d67c46b9STakashi Sakamoto 	s->callbacked = false;
1348d67c46b9STakashi Sakamoto 
1349d67c46b9STakashi Sakamoto 	mutex_unlock(&s->mutex);
1350d67c46b9STakashi Sakamoto }
1351d67c46b9STakashi Sakamoto 
1352d67c46b9STakashi Sakamoto /**
1353d67c46b9STakashi Sakamoto  * amdtp_stream_pcm_abort - abort the running PCM device
1354d67c46b9STakashi Sakamoto  * @s: the AMDTP stream about to be stopped
1355d67c46b9STakashi Sakamoto  *
1356d67c46b9STakashi Sakamoto  * If the isochronous stream needs to be stopped asynchronously, call this
1357d67c46b9STakashi Sakamoto  * function first to stop the PCM device.
1358d67c46b9STakashi Sakamoto  */
1359d67c46b9STakashi Sakamoto void amdtp_stream_pcm_abort(struct amdtp_stream *s)
1360d67c46b9STakashi Sakamoto {
1361d67c46b9STakashi Sakamoto 	struct snd_pcm_substream *pcm;
1362d67c46b9STakashi Sakamoto 
13636aa7de05SMark Rutland 	pcm = READ_ONCE(s->pcm);
1364d67c46b9STakashi Sakamoto 	if (pcm)
1365d67c46b9STakashi Sakamoto 		snd_pcm_stop_xrun(pcm);
1366d67c46b9STakashi Sakamoto }
1367d67c46b9STakashi Sakamoto EXPORT_SYMBOL(amdtp_stream_pcm_abort);
13683ec3d7a3STakashi Sakamoto 
13693ec3d7a3STakashi Sakamoto /**
13703ec3d7a3STakashi Sakamoto  * amdtp_domain_init - initialize an AMDTP domain structure
13713ec3d7a3STakashi Sakamoto  * @d: the AMDTP domain to initialize.
13723ec3d7a3STakashi Sakamoto  */
13733ec3d7a3STakashi Sakamoto int amdtp_domain_init(struct amdtp_domain *d)
13743ec3d7a3STakashi Sakamoto {
13753ec3d7a3STakashi Sakamoto 	INIT_LIST_HEAD(&d->streams);
13763ec3d7a3STakashi Sakamoto 
1377d68c3123STakashi Sakamoto 	d->events_per_period = 0;
1378d68c3123STakashi Sakamoto 
1379d32872f3STakashi Sakamoto 	d->seq.descs = NULL;
138025babf29STakashi Sakamoto 
13813ec3d7a3STakashi Sakamoto 	return 0;
13823ec3d7a3STakashi Sakamoto }
13833ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_init);
13843ec3d7a3STakashi Sakamoto 
13853ec3d7a3STakashi Sakamoto /**
13863ec3d7a3STakashi Sakamoto  * amdtp_domain_destroy - destroy an AMDTP domain structure
13873ec3d7a3STakashi Sakamoto  * @d: the AMDTP domain to destroy.
13883ec3d7a3STakashi Sakamoto  */
13893ec3d7a3STakashi Sakamoto void amdtp_domain_destroy(struct amdtp_domain *d)
13903ec3d7a3STakashi Sakamoto {
13918d0d5c3fSTakashi Sakamoto 	// At present nothing to do.
13928d0d5c3fSTakashi Sakamoto 	return;
13933ec3d7a3STakashi Sakamoto }
13943ec3d7a3STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_destroy);
13956261f90bSTakashi Sakamoto 
13966261f90bSTakashi Sakamoto /**
1397157a53eeSTakashi Sakamoto  * amdtp_domain_add_stream - register isoc context into the domain.
1398157a53eeSTakashi Sakamoto  * @d: the AMDTP domain.
1399157a53eeSTakashi Sakamoto  * @s: the AMDTP stream.
1400157a53eeSTakashi Sakamoto  * @channel: the isochronous channel on the bus.
1401157a53eeSTakashi Sakamoto  * @speed: firewire speed code.
1402157a53eeSTakashi Sakamoto  */
1403157a53eeSTakashi Sakamoto int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s,
1404157a53eeSTakashi Sakamoto 			    int channel, int speed)
1405157a53eeSTakashi Sakamoto {
1406157a53eeSTakashi Sakamoto 	struct amdtp_stream *tmp;
1407157a53eeSTakashi Sakamoto 
1408157a53eeSTakashi Sakamoto 	list_for_each_entry(tmp, &d->streams, list) {
1409157a53eeSTakashi Sakamoto 		if (s == tmp)
1410157a53eeSTakashi Sakamoto 			return -EBUSY;
1411157a53eeSTakashi Sakamoto 	}
1412157a53eeSTakashi Sakamoto 
1413157a53eeSTakashi Sakamoto 	list_add(&s->list, &d->streams);
1414157a53eeSTakashi Sakamoto 
1415157a53eeSTakashi Sakamoto 	s->channel = channel;
1416157a53eeSTakashi Sakamoto 	s->speed = speed;
14172472cfb3STakashi Sakamoto 	s->domain = d;
1418157a53eeSTakashi Sakamoto 
1419157a53eeSTakashi Sakamoto 	return 0;
1420157a53eeSTakashi Sakamoto }
1421157a53eeSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_add_stream);
1422157a53eeSTakashi Sakamoto 
1423acfedcbeSTakashi Sakamoto static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle)
1424acfedcbeSTakashi Sakamoto {
1425acfedcbeSTakashi Sakamoto 	int generation;
1426acfedcbeSTakashi Sakamoto 	int rcode;
1427acfedcbeSTakashi Sakamoto 	__be32 reg;
1428acfedcbeSTakashi Sakamoto 	u32 data;
1429acfedcbeSTakashi Sakamoto 
1430acfedcbeSTakashi Sakamoto 	// This is a request to local 1394 OHCI controller and expected to
1431acfedcbeSTakashi Sakamoto 	// complete without any event waiting.
1432acfedcbeSTakashi Sakamoto 	generation = fw_card->generation;
1433acfedcbeSTakashi Sakamoto 	smp_rmb();	// node_id vs. generation.
1434acfedcbeSTakashi Sakamoto 	rcode = fw_run_transaction(fw_card, TCODE_READ_QUADLET_REQUEST,
1435acfedcbeSTakashi Sakamoto 				   fw_card->node_id, generation, SCODE_100,
1436acfedcbeSTakashi Sakamoto 				   CSR_REGISTER_BASE + CSR_CYCLE_TIME,
1437acfedcbeSTakashi Sakamoto 				   &reg, sizeof(reg));
1438acfedcbeSTakashi Sakamoto 	if (rcode != RCODE_COMPLETE)
1439acfedcbeSTakashi Sakamoto 		return -EIO;
1440acfedcbeSTakashi Sakamoto 
1441acfedcbeSTakashi Sakamoto 	data = be32_to_cpu(reg);
1442acfedcbeSTakashi Sakamoto 	*cur_cycle = data >> 12;
1443acfedcbeSTakashi Sakamoto 
1444acfedcbeSTakashi Sakamoto 	return 0;
1445acfedcbeSTakashi Sakamoto }
1446acfedcbeSTakashi Sakamoto 
1447157a53eeSTakashi Sakamoto /**
14489b4702b0STakashi Sakamoto  * amdtp_domain_start - start sending packets for isoc context in the domain.
14499b4702b0STakashi Sakamoto  * @d: the AMDTP domain.
1450acfedcbeSTakashi Sakamoto  * @ir_delay_cycle: the cycle delay to start all IR contexts.
14519b4702b0STakashi Sakamoto  */
1452acfedcbeSTakashi Sakamoto int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
14539b4702b0STakashi Sakamoto {
14541a4be183STakashi Sakamoto 	static const struct {
14551a4be183STakashi Sakamoto 		unsigned int data_block;
14561a4be183STakashi Sakamoto 		unsigned int syt_offset;
14571a4be183STakashi Sakamoto 	} *entry, initial_state[] = {
14581a4be183STakashi Sakamoto 		[CIP_SFC_32000]  = {  4, 3072 },
14591a4be183STakashi Sakamoto 		[CIP_SFC_48000]  = {  6, 1024 },
14601a4be183STakashi Sakamoto 		[CIP_SFC_96000]  = { 12, 1024 },
14611a4be183STakashi Sakamoto 		[CIP_SFC_192000] = { 24, 1024 },
14621a4be183STakashi Sakamoto 		[CIP_SFC_44100]  = {  0,   67 },
14631a4be183STakashi Sakamoto 		[CIP_SFC_88200]  = {  0,   67 },
14641a4be183STakashi Sakamoto 		[CIP_SFC_176400] = {  0,   67 },
14651a4be183STakashi Sakamoto 	};
1466af86b0b1STakashi Sakamoto 	unsigned int events_per_buffer = d->events_per_buffer;
1467af86b0b1STakashi Sakamoto 	unsigned int events_per_period = d->events_per_period;
1468af86b0b1STakashi Sakamoto 	unsigned int idle_irq_interval;
1469af86b0b1STakashi Sakamoto 	unsigned int queue_size;
14709b4702b0STakashi Sakamoto 	struct amdtp_stream *s;
1471acfedcbeSTakashi Sakamoto 	int cycle;
1472acfedcbeSTakashi Sakamoto 	int err;
14739b4702b0STakashi Sakamoto 
147460dd4929STakashi Sakamoto 	// Select an IT context as IRQ target.
14759b4702b0STakashi Sakamoto 	list_for_each_entry(s, &d->streams, list) {
147660dd4929STakashi Sakamoto 		if (s->direction == AMDTP_OUT_STREAM)
14779b4702b0STakashi Sakamoto 			break;
14789b4702b0STakashi Sakamoto 	}
147960dd4929STakashi Sakamoto 	if (!s)
148060dd4929STakashi Sakamoto 		return -ENXIO;
148160dd4929STakashi Sakamoto 	d->irq_target = s;
14829b4702b0STakashi Sakamoto 
1483af86b0b1STakashi Sakamoto 	// This is a case that AMDTP streams in domain run just for MIDI
1484af86b0b1STakashi Sakamoto 	// substream. Use the number of events equivalent to 10 msec as
1485af86b0b1STakashi Sakamoto 	// interval of hardware IRQ.
1486af86b0b1STakashi Sakamoto 	if (events_per_period == 0)
1487af86b0b1STakashi Sakamoto 		events_per_period = amdtp_rate_table[d->irq_target->sfc] / 100;
1488af86b0b1STakashi Sakamoto 	if (events_per_buffer == 0)
1489af86b0b1STakashi Sakamoto 		events_per_buffer = events_per_period * 3;
1490af86b0b1STakashi Sakamoto 
1491af86b0b1STakashi Sakamoto 	queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer,
1492af86b0b1STakashi Sakamoto 				  amdtp_rate_table[d->irq_target->sfc]);
1493af86b0b1STakashi Sakamoto 
1494d32872f3STakashi Sakamoto 	d->seq.descs = kcalloc(queue_size, sizeof(*d->seq.descs), GFP_KERNEL);
1495d32872f3STakashi Sakamoto 	if (!d->seq.descs)
149625babf29STakashi Sakamoto 		return -ENOMEM;
1497d32872f3STakashi Sakamoto 	d->seq.size = queue_size;
1498d32872f3STakashi Sakamoto 	d->seq.tail = 0;
149925babf29STakashi Sakamoto 
15001a4be183STakashi Sakamoto 	entry = &initial_state[s->sfc];
15011a4be183STakashi Sakamoto 	d->data_block_state = entry->data_block;
15021a4be183STakashi Sakamoto 	d->syt_offset_state = entry->syt_offset;
15031a4be183STakashi Sakamoto 	d->last_syt_offset = TICKS_PER_CYCLE;
15041a4be183STakashi Sakamoto 
1505acfedcbeSTakashi Sakamoto 	if (ir_delay_cycle > 0) {
1506acfedcbeSTakashi Sakamoto 		struct fw_card *fw_card = fw_parent_device(s->unit)->card;
1507acfedcbeSTakashi Sakamoto 
1508acfedcbeSTakashi Sakamoto 		err = get_current_cycle_time(fw_card, &cycle);
1509acfedcbeSTakashi Sakamoto 		if (err < 0)
151025babf29STakashi Sakamoto 			goto error;
1511acfedcbeSTakashi Sakamoto 
1512acfedcbeSTakashi Sakamoto 		// No need to care overflow in cycle field because of enough
1513acfedcbeSTakashi Sakamoto 		// width.
1514acfedcbeSTakashi Sakamoto 		cycle += ir_delay_cycle;
1515acfedcbeSTakashi Sakamoto 
1516acfedcbeSTakashi Sakamoto 		// Round up to sec field.
1517acfedcbeSTakashi Sakamoto 		if ((cycle & 0x00001fff) >= CYCLES_PER_SECOND) {
1518acfedcbeSTakashi Sakamoto 			unsigned int sec;
1519acfedcbeSTakashi Sakamoto 
1520acfedcbeSTakashi Sakamoto 			// The sec field can overflow.
1521acfedcbeSTakashi Sakamoto 			sec = (cycle & 0xffffe000) >> 13;
1522acfedcbeSTakashi Sakamoto 			cycle = (++sec << 13) |
1523acfedcbeSTakashi Sakamoto 				((cycle & 0x00001fff) / CYCLES_PER_SECOND);
1524acfedcbeSTakashi Sakamoto 		}
1525acfedcbeSTakashi Sakamoto 
1526acfedcbeSTakashi Sakamoto 		// In OHCI 1394 specification, lower 2 bits are available for
1527acfedcbeSTakashi Sakamoto 		// sec field.
1528acfedcbeSTakashi Sakamoto 		cycle &= 0x00007fff;
1529acfedcbeSTakashi Sakamoto 	} else {
1530acfedcbeSTakashi Sakamoto 		cycle = -1;
1531acfedcbeSTakashi Sakamoto 	}
1532acfedcbeSTakashi Sakamoto 
153360dd4929STakashi Sakamoto 	list_for_each_entry(s, &d->streams, list) {
1534acfedcbeSTakashi Sakamoto 		int cycle_match;
1535acfedcbeSTakashi Sakamoto 
1536acfedcbeSTakashi Sakamoto 		if (s->direction == AMDTP_IN_STREAM) {
1537acfedcbeSTakashi Sakamoto 			cycle_match = cycle;
1538acfedcbeSTakashi Sakamoto 		} else {
1539acfedcbeSTakashi Sakamoto 			// IT context starts immediately.
1540acfedcbeSTakashi Sakamoto 			cycle_match = -1;
15411a4be183STakashi Sakamoto 			s->ctx_data.rx.seq_index = 0;
1542acfedcbeSTakashi Sakamoto 		}
1543acfedcbeSTakashi Sakamoto 
154460dd4929STakashi Sakamoto 		if (s != d->irq_target) {
15452472cfb3STakashi Sakamoto 			err = amdtp_stream_start(s, s->channel, s->speed,
1546af86b0b1STakashi Sakamoto 						 cycle_match, queue_size, 0);
154760dd4929STakashi Sakamoto 			if (err < 0)
154860dd4929STakashi Sakamoto 				goto error;
154960dd4929STakashi Sakamoto 		}
15509b4702b0STakashi Sakamoto 	}
15519b4702b0STakashi Sakamoto 
155260dd4929STakashi Sakamoto 	s = d->irq_target;
1553af86b0b1STakashi Sakamoto 	s->ctx_data.rx.event_count = 0;
15541a4be183STakashi Sakamoto 	s->ctx_data.rx.seq_index = 0;
1555af86b0b1STakashi Sakamoto 
1556af86b0b1STakashi Sakamoto 	idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period,
1557af86b0b1STakashi Sakamoto 					 amdtp_rate_table[d->irq_target->sfc]);
1558af86b0b1STakashi Sakamoto 	err = amdtp_stream_start(s, s->channel, s->speed, -1, queue_size,
1559af86b0b1STakashi Sakamoto 				 idle_irq_interval);
156060dd4929STakashi Sakamoto 	if (err < 0)
156160dd4929STakashi Sakamoto 		goto error;
156260dd4929STakashi Sakamoto 
156360dd4929STakashi Sakamoto 	return 0;
156460dd4929STakashi Sakamoto error:
156560dd4929STakashi Sakamoto 	list_for_each_entry(s, &d->streams, list)
156660dd4929STakashi Sakamoto 		amdtp_stream_stop(s);
1567d32872f3STakashi Sakamoto 	kfree(d->seq.descs);
1568d32872f3STakashi Sakamoto 	d->seq.descs = NULL;
15699b4702b0STakashi Sakamoto 	return err;
15709b4702b0STakashi Sakamoto }
15719b4702b0STakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_start);
15729b4702b0STakashi Sakamoto 
15739b4702b0STakashi Sakamoto /**
15746261f90bSTakashi Sakamoto  * amdtp_domain_stop - stop sending packets for isoc context in the same domain.
15756261f90bSTakashi Sakamoto  * @d: the AMDTP domain to which the isoc contexts belong.
15766261f90bSTakashi Sakamoto  */
15776261f90bSTakashi Sakamoto void amdtp_domain_stop(struct amdtp_domain *d)
15786261f90bSTakashi Sakamoto {
15796261f90bSTakashi Sakamoto 	struct amdtp_stream *s, *next;
15806261f90bSTakashi Sakamoto 
158160dd4929STakashi Sakamoto 	if (d->irq_target)
158260dd4929STakashi Sakamoto 		amdtp_stream_stop(d->irq_target);
158360dd4929STakashi Sakamoto 
15846261f90bSTakashi Sakamoto 	list_for_each_entry_safe(s, next, &d->streams, list) {
15856261f90bSTakashi Sakamoto 		list_del(&s->list);
15866261f90bSTakashi Sakamoto 
158760dd4929STakashi Sakamoto 		if (s != d->irq_target)
15886261f90bSTakashi Sakamoto 			amdtp_stream_stop(s);
15896261f90bSTakashi Sakamoto 	}
1590d68c3123STakashi Sakamoto 
1591d68c3123STakashi Sakamoto 	d->events_per_period = 0;
159260dd4929STakashi Sakamoto 	d->irq_target = NULL;
159325babf29STakashi Sakamoto 
1594d32872f3STakashi Sakamoto 	kfree(d->seq.descs);
1595d32872f3STakashi Sakamoto 	d->seq.descs = NULL;
15966261f90bSTakashi Sakamoto }
15976261f90bSTakashi Sakamoto EXPORT_SYMBOL_GPL(amdtp_domain_stop);
1598