1#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED 2#define SOUND_FIREWIRE_AMDTP_H_INCLUDED 3 4#include <linux/mutex.h> 5#include <linux/spinlock.h> 6#include "packets-buffer.h" 7 8/** 9 * enum cip_out_flags - describes details of the streaming protocol 10 * @CIP_NONBLOCKING: In non-blocking mode, each packet contains 11 * sample_rate/8000 samples, with rounding up or down to adjust 12 * for clock skew and left-over fractional samples. This should 13 * be used if supported by the device. 14 */ 15enum cip_out_flags { 16 CIP_NONBLOCKING = 0, 17}; 18 19/** 20 * enum cip_sfc - a stream's sample rate 21 */ 22enum cip_sfc { 23 CIP_SFC_32000 = 0, 24 CIP_SFC_44100 = 1, 25 CIP_SFC_48000 = 2, 26 CIP_SFC_88200 = 3, 27 CIP_SFC_96000 = 4, 28 CIP_SFC_176400 = 5, 29 CIP_SFC_192000 = 6, 30}; 31 32#define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ 33 SNDRV_PCM_FMTBIT_S32) 34 35struct fw_unit; 36struct fw_iso_context; 37struct snd_pcm_substream; 38 39struct amdtp_out_stream { 40 struct fw_unit *unit; 41 enum cip_out_flags flags; 42 struct fw_iso_context *context; 43 struct mutex mutex; 44 45 enum cip_sfc sfc; 46 unsigned int data_block_quadlets; 47 unsigned int pcm_channels; 48 unsigned int midi_ports; 49 void (*transfer_samples)(struct amdtp_out_stream *s, 50 struct snd_pcm_substream *pcm, 51 __be32 *buffer, unsigned int frames); 52 53 unsigned int syt_interval; 54 unsigned int source_node_id_field; 55 struct iso_packets_buffer buffer; 56 57 struct snd_pcm_substream *pcm; 58 59 int packet_index; 60 unsigned int data_block_counter; 61 62 unsigned int data_block_state; 63 64 unsigned int last_syt_offset; 65 unsigned int syt_offset_state; 66 67 unsigned int pcm_buffer_pointer; 68 unsigned int pcm_period_pointer; 69}; 70 71int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, 72 enum cip_out_flags flags); 73void amdtp_out_stream_destroy(struct amdtp_out_stream *s); 74 75void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate); 76unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s); 77 78int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed); 79void amdtp_out_stream_update(struct amdtp_out_stream *s); 80void amdtp_out_stream_stop(struct amdtp_out_stream *s); 81 82void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, 83 snd_pcm_format_t format); 84void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s); 85 86/** 87 * amdtp_out_stream_set_pcm - configure format of PCM samples 88 * @s: the AMDTP output stream to be configured 89 * @pcm_channels: the number of PCM samples in each data block, to be encoded 90 * as AM824 multi-bit linear audio 91 * 92 * This function must not be called while the stream is running. 93 */ 94static inline void amdtp_out_stream_set_pcm(struct amdtp_out_stream *s, 95 unsigned int pcm_channels) 96{ 97 s->pcm_channels = pcm_channels; 98} 99 100/** 101 * amdtp_out_stream_set_midi - configure format of MIDI data 102 * @s: the AMDTP output stream to be configured 103 * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels) 104 * 105 * This function must not be called while the stream is running. 106 */ 107static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s, 108 unsigned int midi_ports) 109{ 110 s->midi_ports = midi_ports; 111} 112 113/** 114 * amdtp_out_streaming_error - check for streaming error 115 * @s: the AMDTP output stream 116 * 117 * If this function returns true, the stream's packet queue has stopped due to 118 * an asynchronous error. 119 */ 120static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s) 121{ 122 return s->packet_index < 0; 123} 124 125/** 126 * amdtp_out_stream_pcm_prepare - prepare PCM device for running 127 * @s: the AMDTP output stream 128 * 129 * This function should be called from the PCM device's .prepare callback. 130 */ 131static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s) 132{ 133 s->pcm_buffer_pointer = 0; 134 s->pcm_period_pointer = 0; 135} 136 137/** 138 * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device 139 * @s: the AMDTP output stream 140 * @pcm: the PCM device to be started, or %NULL to stop the current device 141 * 142 * Call this function on a running isochronous stream to enable the actual 143 * transmission of PCM data. This function should be called from the PCM 144 * device's .trigger callback. 145 */ 146static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s, 147 struct snd_pcm_substream *pcm) 148{ 149 ACCESS_ONCE(s->pcm) = pcm; 150} 151 152/** 153 * amdtp_out_stream_pcm_pointer - get the PCM buffer position 154 * @s: the AMDTP output stream that transports the PCM data 155 * 156 * Returns the current buffer position, in frames. 157 */ 158static inline unsigned long 159amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s) 160{ 161 return ACCESS_ONCE(s->pcm_buffer_pointer); 162} 163 164static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) 165{ 166 return sfc & 1; 167} 168 169#endif 170