cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

amdtp-stream.h (10212B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED
      3#define SOUND_FIREWIRE_AMDTP_H_INCLUDED
      4
      5#include <linux/err.h>
      6#include <linux/interrupt.h>
      7#include <linux/mutex.h>
      8#include <linux/sched.h>
      9#include <sound/asound.h>
     10#include "packets-buffer.h"
     11
     12/**
     13 * enum cip_flags - describes details of the streaming protocol
     14 * @CIP_NONBLOCKING: In non-blocking mode, each packet contains
     15 *	sample_rate/8000 samples, with rounding up or down to adjust
     16 *	for clock skew and left-over fractional samples.  This should
     17 *	be used if supported by the device.
     18 * @CIP_BLOCKING: In blocking mode, each packet contains either zero or
     19 *	SYT_INTERVAL samples, with these two types alternating so that
     20 *	the overall sample rate comes out right.
     21 * @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0.
     22 * @CIP_DBC_IS_END_EVENT: The value of dbc in an packet corresponds to the end
     23 * of event in the packet. Out of IEC 61883.
     24 * @CIP_WRONG_DBS: Only for in-stream. The value of dbs is wrong in in-packets.
     25 *	The value of data_block_quadlets is used instead of reported value.
     26 * @CIP_SKIP_DBC_ZERO_CHECK: Only for in-stream.  Packets with zero in dbc is
     27 *	skipped for detecting discontinuity.
     28 * @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty
     29 *	packet is wrong but the others are correct.
     30 * @CIP_JUMBO_PAYLOAD: Only for in-stream. The number of data blocks in an
     31 *	packet is larger than IEC 61883-6 defines. Current implementation
     32 *	allows 5 times as large as IEC 61883-6 defines.
     33 * @CIP_HEADER_WITHOUT_EOH: Only for in-stream. CIP Header doesn't include
     34 *	valid EOH.
     35 * @CIP_NO_HEADERS: a lack of headers in packets
     36 * @CIP_UNALIGHED_DBC: Only for in-stream. The value of dbc is not alighed to
     37 *	the value of current SYT_INTERVAL; e.g. initial value is not zero.
     38 * @CIP_UNAWARE_SYT: For outgoing packet, the value in SYT field of CIP is 0xffff.
     39 *	For incoming packet, the value in SYT field of CIP is not handled.
     40 */
     41enum cip_flags {
     42	CIP_NONBLOCKING		= 0x00,
     43	CIP_BLOCKING		= 0x01,
     44	CIP_EMPTY_WITH_TAG0	= 0x02,
     45	CIP_DBC_IS_END_EVENT	= 0x04,
     46	CIP_WRONG_DBS		= 0x08,
     47	CIP_SKIP_DBC_ZERO_CHECK	= 0x10,
     48	CIP_EMPTY_HAS_WRONG_DBC	= 0x20,
     49	CIP_JUMBO_PAYLOAD	= 0x40,
     50	CIP_HEADER_WITHOUT_EOH	= 0x80,
     51	CIP_NO_HEADER		= 0x100,
     52	CIP_UNALIGHED_DBC	= 0x200,
     53	CIP_UNAWARE_SYT		= 0x400,
     54};
     55
     56/**
     57 * enum cip_sfc - supported Sampling Frequency Codes (SFCs)
     58 * @CIP_SFC_32000:   32,000 data blocks
     59 * @CIP_SFC_44100:   44,100 data blocks
     60 * @CIP_SFC_48000:   48,000 data blocks
     61 * @CIP_SFC_88200:   88,200 data blocks
     62 * @CIP_SFC_96000:   96,000 data blocks
     63 * @CIP_SFC_176400: 176,400 data blocks
     64 * @CIP_SFC_192000: 192,000 data blocks
     65 * @CIP_SFC_COUNT: the number of supported SFCs
     66 *
     67 * These values are used to show nominal Sampling Frequency Code in
     68 * Format Dependent Field (FDF) of AMDTP packet header. In IEC 61883-6:2002,
     69 * this code means the number of events per second. Actually the code
     70 * represents the number of data blocks transferred per second in an AMDTP
     71 * stream.
     72 *
     73 * In IEC 61883-6:2005, some extensions were added to support more types of
     74 * data such as 'One Bit LInear Audio', therefore the meaning of SFC became
     75 * different depending on the types.
     76 *
     77 * Currently our implementation is compatible with IEC 61883-6:2002.
     78 */
     79enum cip_sfc {
     80	CIP_SFC_32000  = 0,
     81	CIP_SFC_44100  = 1,
     82	CIP_SFC_48000  = 2,
     83	CIP_SFC_88200  = 3,
     84	CIP_SFC_96000  = 4,
     85	CIP_SFC_176400 = 5,
     86	CIP_SFC_192000 = 6,
     87	CIP_SFC_COUNT
     88};
     89
     90struct fw_unit;
     91struct fw_iso_context;
     92struct snd_pcm_substream;
     93struct snd_pcm_runtime;
     94
     95enum amdtp_stream_direction {
     96	AMDTP_OUT_STREAM = 0,
     97	AMDTP_IN_STREAM
     98};
     99
    100struct pkt_desc {
    101	u32 cycle;
    102	u32 syt;
    103	unsigned int data_blocks;
    104	unsigned int data_block_counter;
    105	__be32 *ctx_payload;
    106};
    107
    108struct amdtp_stream;
    109typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)(
    110						struct amdtp_stream *s,
    111						const struct pkt_desc *desc,
    112						unsigned int packets,
    113						struct snd_pcm_substream *pcm);
    114
    115struct amdtp_domain;
    116struct amdtp_stream {
    117	struct fw_unit *unit;
    118	// The combination of cip_flags enumeration-constants.
    119	unsigned int flags;
    120	enum amdtp_stream_direction direction;
    121	struct mutex mutex;
    122
    123	/* For packet processing. */
    124	struct fw_iso_context *context;
    125	struct iso_packets_buffer buffer;
    126	unsigned int queue_size;
    127	int packet_index;
    128	struct pkt_desc *pkt_descs;
    129	int tag;
    130	union {
    131		struct {
    132			unsigned int ctx_header_size;
    133
    134			// limit for payload of iso packet.
    135			unsigned int max_ctx_payload_length;
    136
    137			// For quirks of CIP headers.
    138			// Fixed interval of dbc between previos/current
    139			// packets.
    140			unsigned int dbc_interval;
    141
    142			// The device starts multiplexing events to the packet.
    143			bool event_starts;
    144
    145			struct {
    146				struct seq_desc *descs;
    147				unsigned int size;
    148				unsigned int tail;
    149			} cache;
    150		} tx;
    151		struct {
    152			// To generate CIP header.
    153			unsigned int fdf;
    154
    155			// To generate constant hardware IRQ.
    156			unsigned int event_count;
    157
    158			// To calculate CIP data blocks and tstamp.
    159			struct {
    160				struct seq_desc *descs;
    161				unsigned int size;
    162				unsigned int tail;
    163				unsigned int head;
    164			} seq;
    165
    166			unsigned int data_block_state;
    167			unsigned int syt_offset_state;
    168			unsigned int last_syt_offset;
    169
    170			struct amdtp_stream *replay_target;
    171			unsigned int cache_head;
    172		} rx;
    173	} ctx_data;
    174
    175	/* For CIP headers. */
    176	unsigned int source_node_id_field;
    177	unsigned int data_block_quadlets;
    178	unsigned int data_block_counter;
    179	unsigned int sph;
    180	unsigned int fmt;
    181
    182	// Internal flags.
    183	unsigned int transfer_delay;
    184	enum cip_sfc sfc;
    185	unsigned int syt_interval;
    186
    187	/* For a PCM substream processing. */
    188	struct snd_pcm_substream *pcm;
    189	snd_pcm_uframes_t pcm_buffer_pointer;
    190	unsigned int pcm_period_pointer;
    191
    192	// To start processing content of packets at the same cycle in several contexts for
    193	// each direction.
    194	bool ready_processing;
    195	wait_queue_head_t ready_wait;
    196	unsigned int next_cycle;
    197
    198	/* For backends to process data blocks. */
    199	void *protocol;
    200	amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
    201
    202	// For domain.
    203	int channel;
    204	int speed;
    205	struct list_head list;
    206	struct amdtp_domain *domain;
    207};
    208
    209int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
    210		      enum amdtp_stream_direction dir, unsigned int flags,
    211		      unsigned int fmt,
    212		      amdtp_stream_process_ctx_payloads_t process_ctx_payloads,
    213		      unsigned int protocol_size);
    214void amdtp_stream_destroy(struct amdtp_stream *s);
    215
    216int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
    217				unsigned int data_block_quadlets);
    218unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s);
    219
    220void amdtp_stream_update(struct amdtp_stream *s);
    221
    222int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
    223					struct snd_pcm_runtime *runtime);
    224
    225void amdtp_stream_pcm_prepare(struct amdtp_stream *s);
    226void amdtp_stream_pcm_abort(struct amdtp_stream *s);
    227
    228extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT];
    229extern const unsigned int amdtp_rate_table[CIP_SFC_COUNT];
    230
    231/**
    232 * amdtp_stream_running - check stream is running or not
    233 * @s: the AMDTP stream
    234 *
    235 * If this function returns true, the stream is running.
    236 */
    237static inline bool amdtp_stream_running(struct amdtp_stream *s)
    238{
    239	return !IS_ERR(s->context);
    240}
    241
    242/**
    243 * amdtp_streaming_error - check for streaming error
    244 * @s: the AMDTP stream
    245 *
    246 * If this function returns true, the stream's packet queue has stopped due to
    247 * an asynchronous error.
    248 */
    249static inline bool amdtp_streaming_error(struct amdtp_stream *s)
    250{
    251	return s->packet_index < 0;
    252}
    253
    254/**
    255 * amdtp_stream_pcm_running - check PCM substream is running or not
    256 * @s: the AMDTP stream
    257 *
    258 * If this function returns true, PCM substream in the AMDTP stream is running.
    259 */
    260static inline bool amdtp_stream_pcm_running(struct amdtp_stream *s)
    261{
    262	return !!s->pcm;
    263}
    264
    265/**
    266 * amdtp_stream_pcm_trigger - start/stop playback from a PCM device
    267 * @s: the AMDTP stream
    268 * @pcm: the PCM device to be started, or %NULL to stop the current device
    269 *
    270 * Call this function on a running isochronous stream to enable the actual
    271 * transmission of PCM data.  This function should be called from the PCM
    272 * device's .trigger callback.
    273 */
    274static inline void amdtp_stream_pcm_trigger(struct amdtp_stream *s,
    275					    struct snd_pcm_substream *pcm)
    276{
    277	WRITE_ONCE(s->pcm, pcm);
    278}
    279
    280static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
    281{
    282	return sfc & 1;
    283}
    284
    285struct seq_desc {
    286	unsigned int syt_offset;
    287	unsigned int data_blocks;
    288};
    289
    290struct amdtp_domain {
    291	struct list_head streams;
    292
    293	unsigned int events_per_period;
    294	unsigned int events_per_buffer;
    295
    296	struct amdtp_stream *irq_target;
    297
    298	struct {
    299		unsigned int tx_init_skip;
    300		unsigned int tx_start;
    301		unsigned int rx_start;
    302	} processing_cycle;
    303
    304	struct {
    305		bool enable:1;
    306		bool on_the_fly:1;
    307	} replay;
    308};
    309
    310int amdtp_domain_init(struct amdtp_domain *d);
    311void amdtp_domain_destroy(struct amdtp_domain *d);
    312
    313int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s,
    314			    int channel, int speed);
    315
    316int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq,
    317		       bool replay_on_the_fly);
    318void amdtp_domain_stop(struct amdtp_domain *d);
    319
    320static inline int amdtp_domain_set_events_per_period(struct amdtp_domain *d,
    321						unsigned int events_per_period,
    322						unsigned int events_per_buffer)
    323{
    324	d->events_per_period = events_per_period;
    325	d->events_per_buffer = events_per_buffer;
    326
    327	return 0;
    328}
    329
    330unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
    331					      struct amdtp_stream *s);
    332int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s);
    333
    334/**
    335 * amdtp_domain_wait_ready - sleep till being ready to process packets or timeout
    336 * @d: the AMDTP domain
    337 * @timeout_ms: msec till timeout
    338 *
    339 * If this function return false, the AMDTP domain should be stopped.
    340 */
    341static inline bool amdtp_domain_wait_ready(struct amdtp_domain *d, unsigned int timeout_ms)
    342{
    343	struct amdtp_stream *s;
    344
    345	list_for_each_entry(s, &d->streams, list) {
    346		unsigned int j = msecs_to_jiffies(timeout_ms);
    347
    348		if (wait_event_interruptible_timeout(s->ready_wait, s->ready_processing, j) <= 0)
    349			return false;
    350	}
    351
    352	return true;
    353}
    354
    355#endif