diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2011-03-15 02:53:21 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-03-15 03:42:22 -0400 |
commit | 31ef9134eb52636d383a7d0626cbbd345cb94f2f (patch) | |
tree | 5d994932a8773e844190cbea43ef31d67f605cf8 /sound/firewire/amdtp.h | |
parent | a5abba989deceb731047425812d268daf7536575 (diff) |
ALSA: add LaCie FireWire Speakers/Griffin FireWave Surround driver
Add a driver for two playback-only FireWire devices based on the OXFW970
chip.
v2: better AMDTP API abstraction; fix fw_unit leak; small fixes
v3: cache the iPCR value
v4: FireWave constraints; fix fw_device reference counting;
fix PCR caching; small changes and fixes
v5: volume/mute support; fix crashing due to pcm stop races
v6: fix build; one-channel volume for LaCie
v7: use signed values to make volume (range checks) work; fix function
block IDs for volume/mute; always use channel 0 for LaCie volume
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Tested-by: Jay Fenlason <fenlason@redhat.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/amdtp.h')
-rw-r--r-- | sound/firewire/amdtp.h | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h new file mode 100644 index 000000000000..02dc1a664b55 --- /dev/null +++ b/sound/firewire/amdtp.h | |||
@@ -0,0 +1,157 @@ | |||
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 | */ | ||
15 | enum cip_out_flags { | ||
16 | CIP_NONBLOCKING = 0, | ||
17 | }; | ||
18 | |||
19 | /** | ||
20 | * enum cip_sfc - a stream's sample rate | ||
21 | */ | ||
22 | enum 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 | |||
35 | struct fw_unit; | ||
36 | struct fw_iso_context; | ||
37 | struct snd_pcm_substream; | ||
38 | |||
39 | struct 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 | unsigned int packet_counter; | ||
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 | |||
71 | int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, | ||
72 | enum cip_out_flags flags); | ||
73 | void amdtp_out_stream_destroy(struct amdtp_out_stream *s); | ||
74 | |||
75 | void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate); | ||
76 | unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s); | ||
77 | |||
78 | int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed); | ||
79 | void amdtp_out_stream_update(struct amdtp_out_stream *s); | ||
80 | void amdtp_out_stream_stop(struct amdtp_out_stream *s); | ||
81 | |||
82 | void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, | ||
83 | snd_pcm_format_t format); | ||
84 | void 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 | */ | ||
94 | static 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 | */ | ||
107 | static 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_stream_pcm_prepare - prepare PCM device for running | ||
115 | * @s: the AMDTP output stream | ||
116 | * | ||
117 | * This function should be called from the PCM device's .prepare callback. | ||
118 | */ | ||
119 | static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s) | ||
120 | { | ||
121 | s->pcm_buffer_pointer = 0; | ||
122 | s->pcm_period_pointer = 0; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device | ||
127 | * @s: the AMDTP output stream | ||
128 | * @pcm: the PCM device to be started, or %NULL to stop the current device | ||
129 | * | ||
130 | * Call this function on a running isochronous stream to enable the actual | ||
131 | * transmission of PCM data. This function should be called from the PCM | ||
132 | * device's .trigger callback. | ||
133 | */ | ||
134 | static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s, | ||
135 | struct snd_pcm_substream *pcm) | ||
136 | { | ||
137 | ACCESS_ONCE(s->pcm) = pcm; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * amdtp_out_stream_pcm_pointer - get the PCM buffer position | ||
142 | * @s: the AMDTP output stream that transports the PCM data | ||
143 | * | ||
144 | * Returns the current buffer position, in frames. | ||
145 | */ | ||
146 | static inline unsigned long | ||
147 | amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s) | ||
148 | { | ||
149 | return ACCESS_ONCE(s->pcm_buffer_pointer); | ||
150 | } | ||
151 | |||
152 | static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) | ||
153 | { | ||
154 | return sfc & 1; | ||
155 | } | ||
156 | |||
157 | #endif | ||