diff options
author | Adrian Knoth <adi@drcomp.erfurt.thur.de> | 2011-01-26 13:32:14 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-01-27 06:09:18 -0500 |
commit | 0dca1793063c28dde8f6c49c9c72203fe5cb6efc (patch) | |
tree | 3743c433efe2a8fce31de9a6022d98ae493dabdf /include/sound | |
parent | c6d43ba816d1cf1d125bfbfc938f2a28a87facf9 (diff) |
ALSA: hdspm - Add support for RME RayDAT and AIO
Incorporate changes by Florian Faber into hdspm.c. Code taken from
http://wiki.linuxproaudio.org/index.php/Driver:hdspe
Heavily reworked to mostly comply with the coding standard (whitespace
fixes, line width, C++ style comments)
The code was tested and confirmed to be working on RME RayDAT.
Signed-off-by: Adrian Knoth <adi@drcomp.erfurt.thur.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'include/sound')
-rw-r--r-- | include/sound/hdspm.h | 349 |
1 files changed, 307 insertions, 42 deletions
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h index 81990b2bcc98..c3f18194b08e 100644 --- a/include/sound/hdspm.h +++ b/include/sound/hdspm.h | |||
@@ -3,8 +3,8 @@ | |||
3 | /* | 3 | /* |
4 | * Copyright (C) 2003 Winfried Ritsch (IEM) | 4 | * Copyright (C) 2003 Winfried Ritsch (IEM) |
5 | * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) | 5 | * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) |
6 | * | 6 | * |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
@@ -23,50 +23,41 @@ | |||
23 | /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ | 23 | /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ |
24 | #define HDSPM_MAX_CHANNELS 64 | 24 | #define HDSPM_MAX_CHANNELS 64 |
25 | 25 | ||
26 | /* -------------------- IOCTL Peak/RMS Meters -------------------- */ | 26 | enum hdspm_io_type { |
27 | 27 | MADI, | |
28 | /* peam rms level structure like we get from hardware | 28 | MADIface, |
29 | 29 | AIO, | |
30 | maybe in future we can memory map it so I just copy it | 30 | AES32, |
31 | to user on ioctl call now an dont change anything | 31 | RayDAT |
32 | rms are made out of low and high values | 32 | }; |
33 | where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24) | ||
34 | (i asume so from the code) | ||
35 | */ | ||
36 | |||
37 | struct hdspm_peak_rms { | ||
38 | |||
39 | unsigned int level_offset[1024]; | ||
40 | 33 | ||
41 | unsigned int input_peak[64]; | 34 | enum hdspm_speed { |
42 | unsigned int playback_peak[64]; | 35 | ss, |
43 | unsigned int output_peak[64]; | 36 | ds, |
44 | unsigned int xxx_peak[64]; /* not used */ | 37 | qs |
38 | }; | ||
45 | 39 | ||
46 | unsigned int reserved[256]; /* not used */ | 40 | /* -------------------- IOCTL Peak/RMS Meters -------------------- */ |
47 | 41 | ||
48 | unsigned int input_rms_l[64]; | 42 | struct hdspm_peak_rms { |
49 | unsigned int playback_rms_l[64]; | 43 | uint32_t input_peaks[64]; |
50 | unsigned int output_rms_l[64]; | 44 | uint32_t playback_peaks[64]; |
51 | unsigned int xxx_rms_l[64]; /* not used */ | 45 | uint32_t output_peaks[64]; |
52 | 46 | ||
53 | unsigned int input_rms_h[64]; | 47 | uint64_t input_rms[64]; |
54 | unsigned int playback_rms_h[64]; | 48 | uint64_t playback_rms[64]; |
55 | unsigned int output_rms_h[64]; | 49 | uint64_t output_rms[64]; |
56 | unsigned int xxx_rms_h[64]; /* not used */ | ||
57 | }; | ||
58 | 50 | ||
59 | struct hdspm_peak_rms_ioctl { | 51 | uint8_t speed; /* enum {ss, ds, qs} */ |
60 | struct hdspm_peak_rms *peak; | 52 | int status2; |
61 | }; | 53 | }; |
62 | 54 | ||
63 | /* use indirect access due to the limit of ioctl bit size */ | ||
64 | #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \ | 55 | #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \ |
65 | _IOR('H', 0x40, struct hdspm_peak_rms_ioctl) | 56 | _IOR('H', 0x42, struct hdspm_peak_rms) |
66 | 57 | ||
67 | /* ------------ CONFIG block IOCTL ---------------------- */ | 58 | /* ------------ CONFIG block IOCTL ---------------------- */ |
68 | 59 | ||
69 | struct hdspm_config_info { | 60 | struct hdspm_config { |
70 | unsigned char pref_sync_ref; | 61 | unsigned char pref_sync_ref; |
71 | unsigned char wordclock_sync_check; | 62 | unsigned char wordclock_sync_check; |
72 | unsigned char madi_sync_check; | 63 | unsigned char madi_sync_check; |
@@ -80,18 +71,121 @@ struct hdspm_config_info { | |||
80 | unsigned int analog_out; | 71 | unsigned int analog_out; |
81 | }; | 72 | }; |
82 | 73 | ||
83 | #define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO \ | 74 | #define SNDRV_HDSPM_IOCTL_GET_CONFIG \ |
84 | _IOR('H', 0x41, struct hdspm_config_info) | 75 | _IOR('H', 0x41, struct hdspm_config) |
76 | |||
77 | /** | ||
78 | * If there's a TCO (TimeCode Option) board installed, | ||
79 | * there are further options and status data available. | ||
80 | * The hdspm_ltc structure contains the current SMPTE | ||
81 | * timecode and some status information and can be | ||
82 | * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the | ||
83 | * hdspm_status struct. | ||
84 | **/ | ||
85 | |||
86 | enum hdspm_ltc_format { | ||
87 | format_invalid, | ||
88 | fps_24, | ||
89 | fps_25, | ||
90 | fps_2997, | ||
91 | fps_30 | ||
92 | }; | ||
93 | |||
94 | enum hdspm_ltc_frame { | ||
95 | frame_invalid, | ||
96 | drop_frame, | ||
97 | full_frame | ||
98 | }; | ||
99 | |||
100 | enum hdspm_ltc_input_format { | ||
101 | ntsc, | ||
102 | pal, | ||
103 | no_video | ||
104 | }; | ||
105 | |||
106 | struct hdspm_ltc { | ||
107 | unsigned int ltc; | ||
108 | |||
109 | enum hdspm_ltc_format format; | ||
110 | enum hdspm_ltc_frame frame; | ||
111 | enum hdspm_ltc_input_format input_format; | ||
112 | }; | ||
113 | |||
114 | #define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl) | ||
115 | |||
116 | /** | ||
117 | * The status data reflects the device's current state | ||
118 | * as determined by the card's configuration and | ||
119 | * connection status. | ||
120 | **/ | ||
121 | |||
122 | enum hdspm_sync { | ||
123 | hdspm_sync_no_lock = 0, | ||
124 | hdspm_sync_lock = 1, | ||
125 | hdspm_sync_sync = 2 | ||
126 | }; | ||
127 | |||
128 | enum hdspm_madi_input { | ||
129 | hdspm_input_optical = 0, | ||
130 | hdspm_input_coax = 1 | ||
131 | }; | ||
132 | |||
133 | enum hdspm_madi_channel_format { | ||
134 | hdspm_format_ch_64 = 0, | ||
135 | hdspm_format_ch_56 = 1 | ||
136 | }; | ||
137 | |||
138 | enum hdspm_madi_frame_format { | ||
139 | hdspm_frame_48 = 0, | ||
140 | hdspm_frame_96 = 1 | ||
141 | }; | ||
142 | |||
143 | enum hdspm_syncsource { | ||
144 | syncsource_wc = 0, | ||
145 | syncsource_madi = 1, | ||
146 | syncsource_tco = 2, | ||
147 | syncsource_sync = 3, | ||
148 | syncsource_none = 4 | ||
149 | }; | ||
150 | |||
151 | struct hdspm_status { | ||
152 | uint8_t card_type; /* enum hdspm_io_type */ | ||
153 | enum hdspm_syncsource autosync_source; | ||
85 | 154 | ||
155 | uint64_t card_clock; | ||
156 | uint32_t master_period; | ||
157 | |||
158 | union { | ||
159 | struct { | ||
160 | uint8_t sync_wc; /* enum hdspm_sync */ | ||
161 | uint8_t sync_madi; /* enum hdspm_sync */ | ||
162 | uint8_t sync_tco; /* enum hdspm_sync */ | ||
163 | uint8_t sync_in; /* enum hdspm_sync */ | ||
164 | uint8_t madi_input; /* enum hdspm_madi_input */ | ||
165 | uint8_t channel_format; /* enum hdspm_madi_channel_format */ | ||
166 | uint8_t frame_format; /* enum hdspm_madi_frame_format */ | ||
167 | } madi; | ||
168 | } card_specific; | ||
169 | }; | ||
86 | 170 | ||
87 | /* get Soundcard Version */ | 171 | #define SNDRV_HDSPM_IOCTL_GET_STATUS \ |
172 | _IOR('H', 0x47, struct hdspm_status) | ||
173 | |||
174 | /** | ||
175 | * Get information about the card and its add-ons. | ||
176 | **/ | ||
177 | |||
178 | #define HDSPM_ADDON_TCO 1 | ||
88 | 179 | ||
89 | struct hdspm_version { | 180 | struct hdspm_version { |
181 | uint8_t card_type; /* enum hdspm_io_type */ | ||
182 | char cardname[20]; | ||
183 | unsigned int serial; | ||
90 | unsigned short firmware_rev; | 184 | unsigned short firmware_rev; |
185 | int addons; | ||
91 | }; | 186 | }; |
92 | 187 | ||
93 | #define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdspm_version) | 188 | #define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version) |
94 | |||
95 | 189 | ||
96 | /* ------------- get Matrix Mixer IOCTL --------------- */ | 190 | /* ------------- get Matrix Mixer IOCTL --------------- */ |
97 | 191 | ||
@@ -103,7 +197,7 @@ struct hdspm_version { | |||
103 | /* equivalent to hardware definition, maybe for future feature of mmap of | 197 | /* equivalent to hardware definition, maybe for future feature of mmap of |
104 | * them | 198 | * them |
105 | */ | 199 | */ |
106 | /* each of 64 outputs has 64 infader and 64 outfader: | 200 | /* each of 64 outputs has 64 infader and 64 outfader: |
107 | Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ | 201 | Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ |
108 | 202 | ||
109 | #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS | 203 | #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS |
@@ -131,4 +225,175 @@ typedef struct hdspm_version hdspm_version_t; | |||
131 | typedef struct hdspm_channelfader snd_hdspm_channelfader_t; | 225 | typedef struct hdspm_channelfader snd_hdspm_channelfader_t; |
132 | typedef struct hdspm_mixer hdspm_mixer_t; | 226 | typedef struct hdspm_mixer hdspm_mixer_t; |
133 | 227 | ||
134 | #endif /* __SOUND_HDSPM_H */ | 228 | /* These tables map the ALSA channels 1..N to the channels that we |
229 | need to use in order to find the relevant channel buffer. RME | ||
230 | refers to this kind of mapping as between "the ADAT channel and | ||
231 | the DMA channel." We index it using the logical audio channel, | ||
232 | and the value is the DMA channel (i.e. channel buffer number) | ||
233 | where the data for that channel can be read/written from/to. | ||
234 | */ | ||
235 | |||
236 | char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { | ||
237 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
238 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
239 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
240 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
241 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
242 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
243 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
244 | 56, 57, 58, 59, 60, 61, 62, 63 | ||
245 | }; | ||
246 | |||
247 | char channel_map_unity_ds[HDSPM_MAX_CHANNELS] = { | ||
248 | 0, 2, 4, 6, 8, 10, 12, 14, | ||
249 | 16, 18, 20, 22, 24, 26, 28, 30, | ||
250 | 32, 34, 36, 38, 40, 42, 44, 46, | ||
251 | 48, 50, 52, 54, 56, 58, 60, 62, | ||
252 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
253 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
254 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
255 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
256 | }; | ||
257 | |||
258 | char channel_map_unity_qs[HDSPM_MAX_CHANNELS] = { | ||
259 | 0, 4, 8, 12, 16, 20, 24, 28, | ||
260 | 32, 36, 40, 44, 48, 52, 56, 60, | ||
261 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
262 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
263 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
264 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
265 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
266 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
267 | }; | ||
268 | |||
269 | char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { | ||
270 | 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */ | ||
271 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */ | ||
272 | 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */ | ||
273 | 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */ | ||
274 | 0, 1, /* AES */ | ||
275 | 2, 3, /* SPDIF */ | ||
276 | -1, -1, -1, -1, | ||
277 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
278 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
279 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
280 | }; | ||
281 | |||
282 | char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { | ||
283 | 4, 5, 6, 7, /* ADAT 1 */ | ||
284 | 8, 9, 10, 11, /* ADAT 2 */ | ||
285 | 12, 13, 14, 15, /* ADAT 3 */ | ||
286 | 16, 17, 18, 19, /* ADAT 4 */ | ||
287 | 0, 1, /* AES */ | ||
288 | 2, 3, /* SPDIF */ | ||
289 | -1, -1, -1, -1, | ||
290 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
291 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
292 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
293 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
294 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
295 | }; | ||
296 | |||
297 | char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { | ||
298 | 4, 5, /* ADAT 1 */ | ||
299 | 6, 7, /* ADAT 2 */ | ||
300 | 8, 9, /* ADAT 3 */ | ||
301 | 10, 11, /* ADAT 4 */ | ||
302 | 0, 1, /* AES */ | ||
303 | 2, 3, /* SPDIF */ | ||
304 | -1, -1, -1, -1, | ||
305 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
306 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
307 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
308 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
309 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
310 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
311 | }; | ||
312 | |||
313 | char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { | ||
314 | 0, 1, /* line in */ | ||
315 | 8, 9, /* aes in, */ | ||
316 | 10, 11, /* spdif in */ | ||
317 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */ | ||
318 | -1, -1, | ||
319 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
320 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
321 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
322 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
323 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
324 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
325 | }; | ||
326 | |||
327 | char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { | ||
328 | 0, 1, /* line out */ | ||
329 | 8, 9, /* aes out */ | ||
330 | 10, 11, /* spdif out */ | ||
331 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */ | ||
332 | 6, 7, /* phone out */ | ||
333 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
334 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
335 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
336 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
337 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
338 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
339 | }; | ||
340 | |||
341 | char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { | ||
342 | 0, 1, /* line in */ | ||
343 | 8, 9, /* aes in */ | ||
344 | 10, 11, /* spdif in */ | ||
345 | 12, 14, 16, 18, /* adat in */ | ||
346 | -1, -1, -1, -1, -1, -1, | ||
347 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
348 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
349 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
350 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
351 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
352 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
353 | }; | ||
354 | |||
355 | char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { | ||
356 | 0, 1, /* line out */ | ||
357 | 8, 9, /* aes out */ | ||
358 | 10, 11, /* spdif out */ | ||
359 | 12, 14, 16, 18, /* adat out */ | ||
360 | 6, 7, /* phone out */ | ||
361 | -1, -1, -1, -1, | ||
362 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
363 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
364 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
365 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
366 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
367 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
368 | }; | ||
369 | |||
370 | char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { | ||
371 | 0, 1, /* line in */ | ||
372 | 8, 9, /* aes in */ | ||
373 | 10, 11, /* spdif in */ | ||
374 | 12, 16, /* adat in */ | ||
375 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
376 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
377 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
378 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
379 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
380 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
381 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
382 | }; | ||
383 | |||
384 | char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { | ||
385 | 0, 1, /* line out */ | ||
386 | 8, 9, /* aes out */ | ||
387 | 10, 11, /* spdif out */ | ||
388 | 12, 16, /* adat out */ | ||
389 | 6, 7, /* phone out */ | ||
390 | -1, -1, -1, -1, -1, -1, | ||
391 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
392 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
393 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
394 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
395 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
396 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
397 | }; | ||
398 | |||
399 | #endif | ||