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 /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 'sound')
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 4211 |
1 files changed, 3107 insertions, 1104 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index f5eadfc0672a..2db871d9a007 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -8,6 +8,21 @@ | |||
8 | * Modified 2006-06-01 for AES32 support by Remy Bruno | 8 | * Modified 2006-06-01 for AES32 support by Remy Bruno |
9 | * <remy.bruno@trinnov.com> | 9 | * <remy.bruno@trinnov.com> |
10 | * | 10 | * |
11 | * Modified 2009-04-13 for proper metering by Florian Faber | ||
12 | * <faber@faberman.de> | ||
13 | * | ||
14 | * Modified 2009-04-14 for native float support by Florian Faber | ||
15 | * <faber@faberman.de> | ||
16 | * | ||
17 | * Modified 2009-04-26 fixed bug in rms metering by Florian Faber | ||
18 | * <faber@faberman.de> | ||
19 | * | ||
20 | * Modified 2009-04-30 added hw serial number support by Florian Faber | ||
21 | * | ||
22 | * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth | ||
23 | * | ||
24 | * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth | ||
25 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 26 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 27 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 28 | * the Free Software Foundation; either version 2 of the License, or |
@@ -35,6 +50,7 @@ | |||
35 | #include <sound/core.h> | 50 | #include <sound/core.h> |
36 | #include <sound/control.h> | 51 | #include <sound/control.h> |
37 | #include <sound/pcm.h> | 52 | #include <sound/pcm.h> |
53 | #include <sound/pcm_params.h> | ||
38 | #include <sound/info.h> | 54 | #include <sound/info.h> |
39 | #include <sound/asoundef.h> | 55 | #include <sound/asoundef.h> |
40 | #include <sound/rawmidi.h> | 56 | #include <sound/rawmidi.h> |
@@ -47,15 +63,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | |||
47 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 63 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
48 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ | 64 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ |
49 | 65 | ||
50 | /* Disable precise pointer at start */ | ||
51 | static int precise_ptr[SNDRV_CARDS]; | ||
52 | |||
53 | /* Send all playback to line outs */ | ||
54 | static int line_outs_monitor[SNDRV_CARDS]; | ||
55 | |||
56 | /* Enable Analog Outs on Channel 63/64 by default */ | ||
57 | static int enable_monitor[SNDRV_CARDS]; | ||
58 | |||
59 | module_param_array(index, int, NULL, 0444); | 66 | module_param_array(index, int, NULL, 0444); |
60 | MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); | 67 | MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); |
61 | 68 | ||
@@ -65,42 +72,39 @@ MODULE_PARM_DESC(id, "ID string for RME HDSPM interface."); | |||
65 | module_param_array(enable, bool, NULL, 0444); | 72 | module_param_array(enable, bool, NULL, 0444); |
66 | MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); | 73 | MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); |
67 | 74 | ||
68 | module_param_array(precise_ptr, bool, NULL, 0444); | ||
69 | MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer."); | ||
70 | |||
71 | module_param_array(line_outs_monitor, bool, NULL, 0444); | ||
72 | MODULE_PARM_DESC(line_outs_monitor, | ||
73 | "Send playback streams to analog outs by default."); | ||
74 | |||
75 | module_param_array(enable_monitor, bool, NULL, 0444); | ||
76 | MODULE_PARM_DESC(enable_monitor, | ||
77 | "Enable Analog Out on Channel 63/64 by default."); | ||
78 | 75 | ||
79 | MODULE_AUTHOR | 76 | MODULE_AUTHOR |
80 | ("Winfried Ritsch <ritsch_AT_iem.at>, " | 77 | ( |
81 | "Paul Davis <paul@linuxaudiosystems.com>, " | 78 | "Winfried Ritsch <ritsch_AT_iem.at>, " |
82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " | 79 | "Paul Davis <paul@linuxaudiosystems.com>, " |
83 | "Remy Bruno <remy.bruno@trinnov.com>"); | 80 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " |
81 | "Remy Bruno <remy.bruno@trinnov.com>, " | ||
82 | "Florian Faber <faberman@linuxproaudio.org>, " | ||
83 | "Adrian Knoth <adi@drcomp.erfurt.thur.de>" | ||
84 | ); | ||
84 | MODULE_DESCRIPTION("RME HDSPM"); | 85 | MODULE_DESCRIPTION("RME HDSPM"); |
85 | MODULE_LICENSE("GPL"); | 86 | MODULE_LICENSE("GPL"); |
86 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | 87 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); |
87 | 88 | ||
88 | /* --- Write registers. --- | 89 | /* --- Write registers. --- |
89 | These are defined as byte-offsets from the iobase value. */ | 90 | These are defined as byte-offsets from the iobase value. */ |
90 | 91 | ||
92 | #define HDSPM_WR_SETTINGS 0 | ||
93 | #define HDSPM_outputBufferAddress 32 | ||
94 | #define HDSPM_inputBufferAddress 36 | ||
91 | #define HDSPM_controlRegister 64 | 95 | #define HDSPM_controlRegister 64 |
92 | #define HDSPM_interruptConfirmation 96 | 96 | #define HDSPM_interruptConfirmation 96 |
93 | #define HDSPM_control2Reg 256 /* not in specs ???????? */ | 97 | #define HDSPM_control2Reg 256 /* not in specs ???????? */ |
94 | #define HDSPM_freqReg 256 /* for AES32 */ | 98 | #define HDSPM_freqReg 256 /* for AES32 */ |
95 | #define HDSPM_midiDataOut0 352 /* just believe in old code */ | 99 | #define HDSPM_midiDataOut0 352 /* just believe in old code */ |
96 | #define HDSPM_midiDataOut1 356 | 100 | #define HDSPM_midiDataOut1 356 |
97 | #define HDSPM_eeprom_wr 384 /* for AES32 */ | 101 | #define HDSPM_eeprom_wr 384 /* for AES32 */ |
98 | 102 | ||
99 | /* DMA enable for 64 channels, only Bit 0 is relevant */ | 103 | /* DMA enable for 64 channels, only Bit 0 is relevant */ |
100 | #define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ | 104 | #define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ |
101 | #define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ | 105 | #define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ |
102 | 106 | ||
103 | /* 16 page addresses for each of the 64 channels DMA buffer in and out | 107 | /* 16 page addresses for each of the 64 channels DMA buffer in and out |
104 | (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ | 108 | (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ |
105 | #define HDSPM_pageAddressBufferOut 8192 | 109 | #define HDSPM_pageAddressBufferOut 8192 |
106 | #define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) | 110 | #define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) |
@@ -119,22 +123,84 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
119 | #define HDSPM_statusRegister2 192 | 123 | #define HDSPM_statusRegister2 192 |
120 | #define HDSPM_timecodeRegister 128 | 124 | #define HDSPM_timecodeRegister 128 |
121 | 125 | ||
126 | /* AIO, RayDAT */ | ||
127 | #define HDSPM_RD_STATUS_0 0 | ||
128 | #define HDSPM_RD_STATUS_1 64 | ||
129 | #define HDSPM_RD_STATUS_2 128 | ||
130 | #define HDSPM_RD_STATUS_3 192 | ||
131 | |||
132 | #define HDSPM_RD_TCO 256 | ||
133 | #define HDSPM_RD_PLL_FREQ 512 | ||
134 | #define HDSPM_WR_TCO 128 | ||
135 | |||
136 | #define HDSPM_TCO1_TCO_lock 0x00000001 | ||
137 | #define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002 | ||
138 | #define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004 | ||
139 | #define HDSPM_TCO1_LTC_Input_valid 0x00000008 | ||
140 | #define HDSPM_TCO1_WCK_Input_valid 0x00000010 | ||
141 | #define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020 | ||
142 | #define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040 | ||
143 | |||
144 | #define HDSPM_TCO1_set_TC 0x00000100 | ||
145 | #define HDSPM_TCO1_set_drop_frame_flag 0x00000200 | ||
146 | #define HDSPM_TCO1_LTC_Format_LSB 0x00000400 | ||
147 | #define HDSPM_TCO1_LTC_Format_MSB 0x00000800 | ||
148 | |||
149 | #define HDSPM_TCO2_TC_run 0x00010000 | ||
150 | #define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000 | ||
151 | #define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000 | ||
152 | #define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000 | ||
153 | #define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000 | ||
154 | #define HDSPM_TCO2_set_jam_sync 0x00200000 | ||
155 | #define HDSPM_TCO2_set_flywheel 0x00400000 | ||
156 | |||
157 | #define HDSPM_TCO2_set_01_4 0x01000000 | ||
158 | #define HDSPM_TCO2_set_pull_down 0x02000000 | ||
159 | #define HDSPM_TCO2_set_pull_up 0x04000000 | ||
160 | #define HDSPM_TCO2_set_freq 0x08000000 | ||
161 | #define HDSPM_TCO2_set_term_75R 0x10000000 | ||
162 | #define HDSPM_TCO2_set_input_LSB 0x20000000 | ||
163 | #define HDSPM_TCO2_set_input_MSB 0x40000000 | ||
164 | #define HDSPM_TCO2_set_freq_from_app 0x80000000 | ||
165 | |||
166 | |||
167 | #define HDSPM_midiDataOut0 352 | ||
168 | #define HDSPM_midiDataOut1 356 | ||
169 | #define HDSPM_midiDataOut2 368 | ||
170 | |||
122 | #define HDSPM_midiDataIn0 360 | 171 | #define HDSPM_midiDataIn0 360 |
123 | #define HDSPM_midiDataIn1 364 | 172 | #define HDSPM_midiDataIn1 364 |
173 | #define HDSPM_midiDataIn2 372 | ||
174 | #define HDSPM_midiDataIn3 376 | ||
124 | 175 | ||
125 | /* status is data bytes in MIDI-FIFO (0-128) */ | 176 | /* status is data bytes in MIDI-FIFO (0-128) */ |
126 | #define HDSPM_midiStatusOut0 384 | 177 | #define HDSPM_midiStatusOut0 384 |
127 | #define HDSPM_midiStatusOut1 388 | 178 | #define HDSPM_midiStatusOut1 388 |
128 | #define HDSPM_midiStatusIn0 392 | 179 | #define HDSPM_midiStatusOut2 400 |
129 | #define HDSPM_midiStatusIn1 396 | 180 | |
181 | #define HDSPM_midiStatusIn0 392 | ||
182 | #define HDSPM_midiStatusIn1 396 | ||
183 | #define HDSPM_midiStatusIn2 404 | ||
184 | #define HDSPM_midiStatusIn3 408 | ||
130 | 185 | ||
131 | 186 | ||
132 | /* the meters are regular i/o-mapped registers, but offset | 187 | /* the meters are regular i/o-mapped registers, but offset |
133 | considerably from the rest. the peak registers are reset | 188 | considerably from the rest. the peak registers are reset |
134 | when read; the least-significant 4 bits are full-scale counters; | 189 | when read; the least-significant 4 bits are full-scale counters; |
135 | the actual peak value is in the most-significant 24 bits. | 190 | the actual peak value is in the most-significant 24 bits. |
136 | */ | 191 | */ |
137 | #define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */ | 192 | |
193 | #define HDSPM_MADI_INPUT_PEAK 4096 | ||
194 | #define HDSPM_MADI_PLAYBACK_PEAK 4352 | ||
195 | #define HDSPM_MADI_OUTPUT_PEAK 4608 | ||
196 | |||
197 | #define HDSPM_MADI_INPUT_RMS_L 6144 | ||
198 | #define HDSPM_MADI_PLAYBACK_RMS_L 6400 | ||
199 | #define HDSPM_MADI_OUTPUT_RMS_L 6656 | ||
200 | |||
201 | #define HDSPM_MADI_INPUT_RMS_H 7168 | ||
202 | #define HDSPM_MADI_PLAYBACK_RMS_H 7424 | ||
203 | #define HDSPM_MADI_OUTPUT_RMS_H 7680 | ||
138 | 204 | ||
139 | /* --- Control Register bits --------- */ | 205 | /* --- Control Register bits --------- */ |
140 | #define HDSPM_Start (1<<0) /* start engine */ | 206 | #define HDSPM_Start (1<<0) /* start engine */ |
@@ -143,7 +209,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
143 | #define HDSPM_Latency1 (1<<2) /* where n is defined */ | 209 | #define HDSPM_Latency1 (1<<2) /* where n is defined */ |
144 | #define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ | 210 | #define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ |
145 | 211 | ||
146 | #define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */ | 212 | #define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */ |
213 | #define HDSPM_c0Master 0x1 /* Master clock bit in settings | ||
214 | register [RayDAT, AIO] */ | ||
147 | 215 | ||
148 | #define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ | 216 | #define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ |
149 | 217 | ||
@@ -157,7 +225,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
157 | 56channelMODE=0 */ /* MADI ONLY*/ | 225 | 56channelMODE=0 */ /* MADI ONLY*/ |
158 | #define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */ | 226 | #define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */ |
159 | 227 | ||
160 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, | 228 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, |
161 | 0=off, 1=on */ /* MADI ONLY */ | 229 | 0=off, 1=on */ /* MADI ONLY */ |
162 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ | 230 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ |
163 | 231 | ||
@@ -166,22 +234,23 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
166 | */ | 234 | */ |
167 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ | 235 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ |
168 | 236 | ||
169 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ | ||
170 | #define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */ | ||
171 | #define HDSPM_SyncRef2 (1<<13) | 237 | #define HDSPM_SyncRef2 (1<<13) |
172 | #define HDSPM_SyncRef3 (1<<25) | 238 | #define HDSPM_SyncRef3 (1<<25) |
173 | 239 | ||
174 | #define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */ | 240 | #define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */ |
175 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use | 241 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use |
176 | AES additional bits in | 242 | AES additional bits in |
177 | lower 5 Audiodatabits ??? */ | 243 | lower 5 Audiodatabits ??? */ |
178 | #define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */ | 244 | #define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */ |
179 | #define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */ | 245 | #define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */ |
180 | 246 | ||
181 | #define HDSPM_Midi0InterruptEnable (1<<22) | 247 | #define HDSPM_Midi0InterruptEnable 0x0400000 |
182 | #define HDSPM_Midi1InterruptEnable (1<<23) | 248 | #define HDSPM_Midi1InterruptEnable 0x0800000 |
249 | #define HDSPM_Midi2InterruptEnable 0x0200000 | ||
250 | #define HDSPM_Midi3InterruptEnable 0x4000000 | ||
183 | 251 | ||
184 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ | 252 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ |
253 | #define HDSPe_FLOAT_FORMAT 0x2000000 | ||
185 | 254 | ||
186 | #define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */ | 255 | #define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */ |
187 | #define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */ | 256 | #define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */ |
@@ -198,11 +267,18 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
198 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) | 267 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) |
199 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ | 268 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ |
200 | HDSPM_SyncRef2|HDSPM_SyncRef3) | 269 | HDSPM_SyncRef2|HDSPM_SyncRef3) |
201 | #define HDSPM_SyncRef_Word 0 | ||
202 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) | ||
203 | 270 | ||
204 | #define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ | 271 | #define HDSPM_c0_SyncRef0 0x2 |
205 | #define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ | 272 | #define HDSPM_c0_SyncRef1 0x4 |
273 | #define HDSPM_c0_SyncRef2 0x8 | ||
274 | #define HDSPM_c0_SyncRef3 0x10 | ||
275 | #define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\ | ||
276 | HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3) | ||
277 | |||
278 | #define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ | ||
279 | #define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ | ||
280 | #define HDSPM_SYNC_FROM_TCO 2 | ||
281 | #define HDSPM_SYNC_FROM_SYNC_IN 3 | ||
206 | 282 | ||
207 | #define HDSPM_Frequency32KHz HDSPM_Frequency0 | 283 | #define HDSPM_Frequency32KHz HDSPM_Frequency0 |
208 | #define HDSPM_Frequency44_1KHz HDSPM_Frequency1 | 284 | #define HDSPM_Frequency44_1KHz HDSPM_Frequency1 |
@@ -216,17 +292,6 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
216 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ | 292 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ |
217 | HDSPM_Frequency0) | 293 | HDSPM_Frequency0) |
218 | 294 | ||
219 | /* --- for internal discrimination */ | ||
220 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ | ||
221 | #define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1 | ||
222 | #define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2 | ||
223 | #define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3 | ||
224 | #define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4 | ||
225 | #define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5 | ||
226 | #define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6 | ||
227 | #define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7 | ||
228 | #define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8 | ||
229 | #define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9 | ||
230 | 295 | ||
231 | /* Synccheck Status */ | 296 | /* Synccheck Status */ |
232 | #define HDSPM_SYNC_CHECK_NO_LOCK 0 | 297 | #define HDSPM_SYNC_CHECK_NO_LOCK 0 |
@@ -236,14 +301,16 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
236 | /* AutoSync References - used by "autosync_ref" control switch */ | 301 | /* AutoSync References - used by "autosync_ref" control switch */ |
237 | #define HDSPM_AUTOSYNC_FROM_WORD 0 | 302 | #define HDSPM_AUTOSYNC_FROM_WORD 0 |
238 | #define HDSPM_AUTOSYNC_FROM_MADI 1 | 303 | #define HDSPM_AUTOSYNC_FROM_MADI 1 |
239 | #define HDSPM_AUTOSYNC_FROM_NONE 2 | 304 | #define HDSPM_AUTOSYNC_FROM_TCO 2 |
305 | #define HDSPM_AUTOSYNC_FROM_SYNC_IN 3 | ||
306 | #define HDSPM_AUTOSYNC_FROM_NONE 4 | ||
240 | 307 | ||
241 | /* Possible sources of MADI input */ | 308 | /* Possible sources of MADI input */ |
242 | #define HDSPM_OPTICAL 0 /* optical */ | 309 | #define HDSPM_OPTICAL 0 /* optical */ |
243 | #define HDSPM_COAXIAL 1 /* BNC */ | 310 | #define HDSPM_COAXIAL 1 /* BNC */ |
244 | 311 | ||
245 | #define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) | 312 | #define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) |
246 | #define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1) | 313 | #define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1)) |
247 | 314 | ||
248 | #define hdspm_encode_in(x) (((x)&0x3)<<14) | 315 | #define hdspm_encode_in(x) (((x)&0x3)<<14) |
249 | #define hdspm_decode_in(x) (((x)>>14)&0x3) | 316 | #define hdspm_decode_in(x) (((x)>>14)&0x3) |
@@ -270,13 +337,21 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
270 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 | 337 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 |
271 | * (like inp0) | 338 | * (like inp0) |
272 | */ | 339 | */ |
340 | |||
273 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ | 341 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ |
342 | #define HDSPM_madiSync (1<<18) /* MADI is in sync */ | ||
343 | |||
344 | #define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */ | ||
345 | #define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */ | ||
346 | |||
347 | #define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */ | ||
348 | #define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */ | ||
274 | 349 | ||
275 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ | 350 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ |
276 | /* since 64byte accurate last 6 bits | 351 | /* since 64byte accurate, last 6 bits are not used */ |
277 | are not used */ | 352 | |
353 | |||
278 | 354 | ||
279 | #define HDSPM_madiSync (1<<18) /* MADI is in sync */ | ||
280 | #define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ | 355 | #define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ |
281 | 356 | ||
282 | #define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ | 357 | #define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ |
@@ -287,8 +362,19 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
287 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with | 362 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with |
288 | * Interrupt | 363 | * Interrupt |
289 | */ | 364 | */ |
290 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ | 365 | #define HDSPM_tco_detect 0x08000000 |
291 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ | 366 | #define HDSPM_tco_lock 0x20000000 |
367 | |||
368 | #define HDSPM_s2_tco_detect 0x00000040 | ||
369 | #define HDSPM_s2_AEBO_D 0x00000080 | ||
370 | #define HDSPM_s2_AEBI_D 0x00000100 | ||
371 | |||
372 | |||
373 | #define HDSPM_midi0IRQPending 0x40000000 | ||
374 | #define HDSPM_midi1IRQPending 0x80000000 | ||
375 | #define HDSPM_midi2IRQPending 0x20000000 | ||
376 | #define HDSPM_midi2IRQPendingAES 0x00000020 | ||
377 | #define HDSPM_midi3IRQPending 0x00200000 | ||
292 | 378 | ||
293 | /* --- status bit helpers */ | 379 | /* --- status bit helpers */ |
294 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ | 380 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ |
@@ -317,7 +403,10 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
317 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ | 403 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ |
318 | /* missing Bit for 111=128, 1000=176.4, 1001=192 */ | 404 | /* missing Bit for 111=128, 1000=176.4, 1001=192 */ |
319 | 405 | ||
320 | #define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */ | 406 | #define HDSPM_SyncRef0 0x10000 /* Sync Reference */ |
407 | #define HDSPM_SyncRef1 0x20000 | ||
408 | |||
409 | #define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */ | ||
321 | #define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ | 410 | #define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ |
322 | #define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ | 411 | #define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ |
323 | 412 | ||
@@ -331,11 +420,19 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
331 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) | 420 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) |
332 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) | 421 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) |
333 | 422 | ||
423 | #define HDSPM_status1_F_0 0x0400000 | ||
424 | #define HDSPM_status1_F_1 0x0800000 | ||
425 | #define HDSPM_status1_F_2 0x1000000 | ||
426 | #define HDSPM_status1_F_3 0x2000000 | ||
427 | #define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3) | ||
428 | |||
334 | 429 | ||
335 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ | 430 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
336 | HDSPM_SelSyncRef2) | 431 | HDSPM_SelSyncRef2) |
337 | #define HDSPM_SelSyncRef_WORD 0 | 432 | #define HDSPM_SelSyncRef_WORD 0 |
338 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) | 433 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) |
434 | #define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1) | ||
435 | #define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1) | ||
339 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ | 436 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
340 | HDSPM_SelSyncRef2) | 437 | HDSPM_SelSyncRef2) |
341 | 438 | ||
@@ -345,7 +442,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
345 | /* status */ | 442 | /* status */ |
346 | #define HDSPM_AES32_wcLock 0x0200000 | 443 | #define HDSPM_AES32_wcLock 0x0200000 |
347 | #define HDSPM_AES32_wcFreq_bit 22 | 444 | #define HDSPM_AES32_wcFreq_bit 22 |
348 | /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function | 445 | /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function |
349 | HDSPM_bit2freq */ | 446 | HDSPM_bit2freq */ |
350 | #define HDSPM_AES32_syncref_bit 16 | 447 | #define HDSPM_AES32_syncref_bit 16 |
351 | /* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */ | 448 | /* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */ |
@@ -398,28 +495,184 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
398 | #define MADI_DS_CHANNELS 32 | 495 | #define MADI_DS_CHANNELS 32 |
399 | #define MADI_QS_CHANNELS 16 | 496 | #define MADI_QS_CHANNELS 16 |
400 | 497 | ||
498 | #define RAYDAT_SS_CHANNELS 36 | ||
499 | #define RAYDAT_DS_CHANNELS 20 | ||
500 | #define RAYDAT_QS_CHANNELS 12 | ||
501 | |||
502 | #define AIO_IN_SS_CHANNELS 14 | ||
503 | #define AIO_IN_DS_CHANNELS 10 | ||
504 | #define AIO_IN_QS_CHANNELS 8 | ||
505 | #define AIO_OUT_SS_CHANNELS 16 | ||
506 | #define AIO_OUT_DS_CHANNELS 12 | ||
507 | #define AIO_OUT_QS_CHANNELS 10 | ||
508 | |||
401 | /* the size of a substream (1 mono data stream) */ | 509 | /* the size of a substream (1 mono data stream) */ |
402 | #define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) | 510 | #define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) |
403 | #define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) | 511 | #define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) |
404 | 512 | ||
405 | /* the size of the area we need to allocate for DMA transfers. the | 513 | /* the size of the area we need to allocate for DMA transfers. the |
406 | size is the same regardless of the number of channels, and | 514 | size is the same regardless of the number of channels, and |
407 | also the latency to use. | 515 | also the latency to use. |
408 | for one direction !!! | 516 | for one direction !!! |
409 | */ | 517 | */ |
410 | #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) | 518 | #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) |
411 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) | 519 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) |
412 | 520 | ||
413 | /* revisions >= 230 indicate AES32 card */ | 521 | /* revisions >= 230 indicate AES32 card */ |
414 | #define HDSPM_AESREVISION 230 | 522 | #define HDSPM_MADI_REV 210 |
523 | #define HDSPM_RAYDAT_REV 211 | ||
524 | #define HDSPM_AIO_REV 212 | ||
525 | #define HDSPM_MADIFACE_REV 213 | ||
526 | #define HDSPM_AES_REV 240 | ||
415 | 527 | ||
416 | /* speed factor modes */ | 528 | /* speed factor modes */ |
417 | #define HDSPM_SPEED_SINGLE 0 | 529 | #define HDSPM_SPEED_SINGLE 0 |
418 | #define HDSPM_SPEED_DOUBLE 1 | 530 | #define HDSPM_SPEED_DOUBLE 1 |
419 | #define HDSPM_SPEED_QUAD 2 | 531 | #define HDSPM_SPEED_QUAD 2 |
532 | |||
420 | /* names for speed modes */ | 533 | /* names for speed modes */ |
421 | static char *hdspm_speed_names[] = { "single", "double", "quad" }; | 534 | static char *hdspm_speed_names[] = { "single", "double", "quad" }; |
422 | 535 | ||
536 | static char *texts_autosync_aes_tco[] = { "Word Clock", | ||
537 | "AES1", "AES2", "AES3", "AES4", | ||
538 | "AES5", "AES6", "AES7", "AES8", | ||
539 | "TCO" }; | ||
540 | static char *texts_autosync_aes[] = { "Word Clock", | ||
541 | "AES1", "AES2", "AES3", "AES4", | ||
542 | "AES5", "AES6", "AES7", "AES8" }; | ||
543 | static char *texts_autosync_madi_tco[] = { "Word Clock", | ||
544 | "MADI", "TCO", "Sync In" }; | ||
545 | static char *texts_autosync_madi[] = { "Word Clock", | ||
546 | "MADI", "Sync In" }; | ||
547 | |||
548 | static char *texts_autosync_raydat_tco[] = { | ||
549 | "Word Clock", | ||
550 | "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4", | ||
551 | "AES", "SPDIF", "TCO", "Sync In" | ||
552 | }; | ||
553 | static char *texts_autosync_raydat[] = { | ||
554 | "Word Clock", | ||
555 | "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4", | ||
556 | "AES", "SPDIF", "Sync In" | ||
557 | }; | ||
558 | static char *texts_autosync_aio_tco[] = { | ||
559 | "Word Clock", | ||
560 | "ADAT", "AES", "SPDIF", "TCO", "Sync In" | ||
561 | }; | ||
562 | static char *texts_autosync_aio[] = { "Word Clock", | ||
563 | "ADAT", "AES", "SPDIF", "Sync In" }; | ||
564 | |||
565 | static char *texts_freq[] = { | ||
566 | "No Lock", | ||
567 | "32 kHz", | ||
568 | "44.1 kHz", | ||
569 | "48 kHz", | ||
570 | "64 kHz", | ||
571 | "88.2 kHz", | ||
572 | "96 kHz", | ||
573 | "128 kHz", | ||
574 | "176.4 kHz", | ||
575 | "192 kHz" | ||
576 | }; | ||
577 | |||
578 | static char *texts_sync_status[] = { | ||
579 | "no lock", | ||
580 | "lock", | ||
581 | "sync" | ||
582 | }; | ||
583 | |||
584 | static char *texts_ports_madi[] = { | ||
585 | "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6", | ||
586 | "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12", | ||
587 | "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18", | ||
588 | "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24", | ||
589 | "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30", | ||
590 | "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36", | ||
591 | "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42", | ||
592 | "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48", | ||
593 | "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54", | ||
594 | "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60", | ||
595 | "MADI.61", "MADI.62", "MADI.63", "MADI.64", | ||
596 | }; | ||
597 | |||
598 | |||
599 | static char *texts_ports_raydat_ss[] = { | ||
600 | "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6", | ||
601 | "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", | ||
602 | "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2", | ||
603 | "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8", | ||
604 | "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6", | ||
605 | "ADAT4.7", "ADAT4.8", | ||
606 | "AES.L", "AES.R", | ||
607 | "SPDIF.L", "SPDIF.R" | ||
608 | }; | ||
609 | |||
610 | static char *texts_ports_raydat_ds[] = { | ||
611 | "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", | ||
612 | "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", | ||
613 | "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4", | ||
614 | "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", | ||
615 | "AES.L", "AES.R", | ||
616 | "SPDIF.L", "SPDIF.R" | ||
617 | }; | ||
618 | |||
619 | static char *texts_ports_raydat_qs[] = { | ||
620 | "ADAT1.1", "ADAT1.2", | ||
621 | "ADAT2.1", "ADAT2.2", | ||
622 | "ADAT3.1", "ADAT3.2", | ||
623 | "ADAT4.1", "ADAT4.2", | ||
624 | "AES.L", "AES.R", | ||
625 | "SPDIF.L", "SPDIF.R" | ||
626 | }; | ||
627 | |||
628 | |||
629 | static char *texts_ports_aio_in_ss[] = { | ||
630 | "Analogue.L", "Analogue.R", | ||
631 | "AES.L", "AES.R", | ||
632 | "SPDIF.L", "SPDIF.R", | ||
633 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6", | ||
634 | "ADAT.7", "ADAT.8" | ||
635 | }; | ||
636 | |||
637 | static char *texts_ports_aio_out_ss[] = { | ||
638 | "Analogue.L", "Analogue.R", | ||
639 | "AES.L", "AES.R", | ||
640 | "SPDIF.L", "SPDIF.R", | ||
641 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6", | ||
642 | "ADAT.7", "ADAT.8", | ||
643 | "Phone.L", "Phone.R" | ||
644 | }; | ||
645 | |||
646 | static char *texts_ports_aio_in_ds[] = { | ||
647 | "Analogue.L", "Analogue.R", | ||
648 | "AES.L", "AES.R", | ||
649 | "SPDIF.L", "SPDIF.R", | ||
650 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4" | ||
651 | }; | ||
652 | |||
653 | static char *texts_ports_aio_out_ds[] = { | ||
654 | "Analogue.L", "Analogue.R", | ||
655 | "AES.L", "AES.R", | ||
656 | "SPDIF.L", "SPDIF.R", | ||
657 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", | ||
658 | "Phone.L", "Phone.R" | ||
659 | }; | ||
660 | |||
661 | static char *texts_ports_aio_in_qs[] = { | ||
662 | "Analogue.L", "Analogue.R", | ||
663 | "AES.L", "AES.R", | ||
664 | "SPDIF.L", "SPDIF.R", | ||
665 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4" | ||
666 | }; | ||
667 | |||
668 | static char *texts_ports_aio_out_qs[] = { | ||
669 | "Analogue.L", "Analogue.R", | ||
670 | "AES.L", "AES.R", | ||
671 | "SPDIF.L", "SPDIF.R", | ||
672 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", | ||
673 | "Phone.L", "Phone.R" | ||
674 | }; | ||
675 | |||
423 | struct hdspm_midi { | 676 | struct hdspm_midi { |
424 | struct hdspm *hdspm; | 677 | struct hdspm *hdspm; |
425 | int id; | 678 | int id; |
@@ -430,6 +683,21 @@ struct hdspm_midi { | |||
430 | struct timer_list timer; | 683 | struct timer_list timer; |
431 | spinlock_t lock; | 684 | spinlock_t lock; |
432 | int pending; | 685 | int pending; |
686 | int dataIn; | ||
687 | int statusIn; | ||
688 | int dataOut; | ||
689 | int statusOut; | ||
690 | int ie; | ||
691 | int irq; | ||
692 | }; | ||
693 | |||
694 | struct hdspm_tco { | ||
695 | int input; | ||
696 | int framerate; | ||
697 | int wordclock; | ||
698 | int samplerate; | ||
699 | int pull; | ||
700 | int term; /* 0 = off, 1 = on */ | ||
433 | }; | 701 | }; |
434 | 702 | ||
435 | struct hdspm { | 703 | struct hdspm { |
@@ -441,21 +709,39 @@ struct hdspm { | |||
441 | char *card_name; /* for procinfo */ | 709 | char *card_name; /* for procinfo */ |
442 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ | 710 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ |
443 | 711 | ||
444 | unsigned char is_aes32; /* indicates if card is AES32 */ | 712 | uint8_t io_type; |
445 | 713 | ||
446 | int precise_ptr; /* use precise pointers, to be tested */ | ||
447 | int monitor_outs; /* set up monitoring outs init flag */ | 714 | int monitor_outs; /* set up monitoring outs init flag */ |
448 | 715 | ||
449 | u32 control_register; /* cached value */ | 716 | u32 control_register; /* cached value */ |
450 | u32 control2_register; /* cached value */ | 717 | u32 control2_register; /* cached value */ |
718 | u32 settings_register; | ||
451 | 719 | ||
452 | struct hdspm_midi midi[2]; | 720 | struct hdspm_midi midi[4]; |
453 | struct tasklet_struct midi_tasklet; | 721 | struct tasklet_struct midi_tasklet; |
454 | 722 | ||
455 | size_t period_bytes; | 723 | size_t period_bytes; |
456 | unsigned char ss_channels; /* channels of card in single speed */ | 724 | unsigned char ss_in_channels; |
457 | unsigned char ds_channels; /* Double Speed */ | 725 | unsigned char ds_in_channels; |
458 | unsigned char qs_channels; /* Quad Speed */ | 726 | unsigned char qs_in_channels; |
727 | unsigned char ss_out_channels; | ||
728 | unsigned char ds_out_channels; | ||
729 | unsigned char qs_out_channels; | ||
730 | |||
731 | unsigned char max_channels_in; | ||
732 | unsigned char max_channels_out; | ||
733 | |||
734 | char *channel_map_in; | ||
735 | char *channel_map_out; | ||
736 | |||
737 | char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; | ||
738 | char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; | ||
739 | |||
740 | char **port_names_in; | ||
741 | char **port_names_out; | ||
742 | |||
743 | char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs; | ||
744 | char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs; | ||
459 | 745 | ||
460 | unsigned char *playback_buffer; /* suitably aligned address */ | 746 | unsigned char *playback_buffer; /* suitably aligned address */ |
461 | unsigned char *capture_buffer; /* suitably aligned address */ | 747 | unsigned char *capture_buffer; /* suitably aligned address */ |
@@ -468,14 +754,13 @@ struct hdspm { | |||
468 | int last_internal_sample_rate; | 754 | int last_internal_sample_rate; |
469 | int system_sample_rate; | 755 | int system_sample_rate; |
470 | 756 | ||
471 | char *channel_map; /* channel map for DS and Quadspeed */ | ||
472 | |||
473 | int dev; /* Hardware vars... */ | 757 | int dev; /* Hardware vars... */ |
474 | int irq; | 758 | int irq; |
475 | unsigned long port; | 759 | unsigned long port; |
476 | void __iomem *iobase; | 760 | void __iomem *iobase; |
477 | 761 | ||
478 | int irq_count; /* for debug */ | 762 | int irq_count; /* for debug */ |
763 | int midiPorts; | ||
479 | 764 | ||
480 | struct snd_card *card; /* one card */ | 765 | struct snd_card *card; /* one card */ |
481 | struct snd_pcm *pcm; /* has one pcm */ | 766 | struct snd_pcm *pcm; /* has one pcm */ |
@@ -487,28 +772,15 @@ struct hdspm { | |||
487 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; | 772 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; |
488 | /* but input to much, so not used */ | 773 | /* but input to much, so not used */ |
489 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; | 774 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; |
490 | /* full mixer accessible over mixer ioctl or hwdep-device */ | 775 | /* full mixer accessable over mixer ioctl or hwdep-device */ |
491 | struct hdspm_mixer *mixer; | 776 | struct hdspm_mixer *mixer; |
492 | 777 | ||
493 | }; | 778 | struct hdspm_tco *tco; /* NULL if no TCO detected */ |
494 | 779 | ||
495 | /* These tables map the ALSA channels 1..N to the channels that we | 780 | char **texts_autosync; |
496 | need to use in order to find the relevant channel buffer. RME | 781 | int texts_autosync_items; |
497 | refer to this kind of mapping as between "the ADAT channel and | ||
498 | the DMA channel." We index it using the logical audio channel, | ||
499 | and the value is the DMA channel (i.e. channel buffer number) | ||
500 | where the data for that channel can be read/written from/to. | ||
501 | */ | ||
502 | 782 | ||
503 | static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = { | 783 | cycles_t last_interrupt; |
504 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
505 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
506 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
507 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
508 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
509 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
510 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
511 | 56, 57, 58, 59, 60, 61, 62, 63 | ||
512 | }; | 784 | }; |
513 | 785 | ||
514 | 786 | ||
@@ -532,11 +804,11 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
532 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | 804 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, |
533 | struct hdspm * hdspm); | 805 | struct hdspm * hdspm); |
534 | 806 | ||
535 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm); | 807 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); |
536 | static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm); | 808 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); |
537 | static int hdspm_autosync_ref(struct hdspm * hdspm); | 809 | static int hdspm_autosync_ref(struct hdspm *hdspm); |
538 | static int snd_hdspm_set_defaults(struct hdspm * hdspm); | 810 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); |
539 | static void hdspm_set_sgbuf(struct hdspm * hdspm, | 811 | static void hdspm_set_sgbuf(struct hdspm *hdspm, |
540 | struct snd_pcm_substream *substream, | 812 | struct snd_pcm_substream *substream, |
541 | unsigned int reg, int channels); | 813 | unsigned int reg, int channels); |
542 | 814 | ||
@@ -550,7 +822,7 @@ static inline int HDSPM_bit2freq(int n) | |||
550 | return bit2freq_tab[n]; | 822 | return bit2freq_tab[n]; |
551 | } | 823 | } |
552 | 824 | ||
553 | /* Write/read to/from HDSPM with Addresses in Bytes | 825 | /* Write/read to/from HDSPM with Adresses in Bytes |
554 | not words but only 32Bit writes are allowed */ | 826 | not words but only 32Bit writes are allowed */ |
555 | 827 | ||
556 | static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg, | 828 | static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg, |
@@ -564,8 +836,8 @@ static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg) | |||
564 | return readl(hdspm->iobase + reg); | 836 | return readl(hdspm->iobase + reg); |
565 | } | 837 | } |
566 | 838 | ||
567 | /* for each output channel (chan) I have an Input (in) and Playback (pb) Fader | 839 | /* for each output channel (chan) I have an Input (in) and Playback (pb) Fader |
568 | mixer is write only on hardware so we have to cache him for read | 840 | mixer is write only on hardware so we have to cache him for read |
569 | each fader is a u32, but uses only the first 16 bit */ | 841 | each fader is a u32, but uses only the first 16 bit */ |
570 | 842 | ||
571 | static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, | 843 | static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, |
@@ -641,30 +913,67 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) | |||
641 | /* check for external sample rate */ | 913 | /* check for external sample rate */ |
642 | static int hdspm_external_sample_rate(struct hdspm *hdspm) | 914 | static int hdspm_external_sample_rate(struct hdspm *hdspm) |
643 | { | 915 | { |
644 | if (hdspm->is_aes32) { | 916 | unsigned int status, status2, timecode; |
645 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 917 | int syncref, rate = 0, rate_bits; |
646 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 918 | |
647 | unsigned int timecode = | 919 | switch (hdspm->io_type) { |
648 | hdspm_read(hdspm, HDSPM_timecodeRegister); | 920 | case AES32: |
921 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
922 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
923 | timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
649 | 924 | ||
650 | int syncref = hdspm_autosync_ref(hdspm); | 925 | syncref = hdspm_autosync_ref(hdspm); |
651 | 926 | ||
652 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && | 927 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && |
653 | status & HDSPM_AES32_wcLock) | 928 | status & HDSPM_AES32_wcLock) |
654 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) | 929 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF); |
655 | & 0xF); | 930 | |
656 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && | 931 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && |
657 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && | 932 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && |
658 | status2 & (HDSPM_LockAES >> | 933 | status2 & (HDSPM_LockAES >> |
659 | (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))) | 934 | (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))) |
660 | return HDSPM_bit2freq((timecode >> | 935 | return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF); |
661 | (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF); | ||
662 | return 0; | 936 | return 0; |
663 | } else { | 937 | break; |
664 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 938 | |
665 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 939 | case MADIface: |
666 | unsigned int rate_bits; | 940 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
667 | int rate = 0; | 941 | |
942 | if (!(status & HDSPM_madiLock)) { | ||
943 | rate = 0; /* no lock */ | ||
944 | } else { | ||
945 | switch (status & (HDSPM_status1_freqMask)) { | ||
946 | case HDSPM_status1_F_0*1: | ||
947 | rate = 32000; break; | ||
948 | case HDSPM_status1_F_0*2: | ||
949 | rate = 44100; break; | ||
950 | case HDSPM_status1_F_0*3: | ||
951 | rate = 48000; break; | ||
952 | case HDSPM_status1_F_0*4: | ||
953 | rate = 64000; break; | ||
954 | case HDSPM_status1_F_0*5: | ||
955 | rate = 88200; break; | ||
956 | case HDSPM_status1_F_0*6: | ||
957 | rate = 96000; break; | ||
958 | case HDSPM_status1_F_0*7: | ||
959 | rate = 128000; break; | ||
960 | case HDSPM_status1_F_0*8: | ||
961 | rate = 176400; break; | ||
962 | case HDSPM_status1_F_0*9: | ||
963 | rate = 192000; break; | ||
964 | default: | ||
965 | rate = 0; break; | ||
966 | } | ||
967 | } | ||
968 | |||
969 | break; | ||
970 | |||
971 | case MADI: | ||
972 | case AIO: | ||
973 | case RayDAT: | ||
974 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
975 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
976 | rate = 0; | ||
668 | 977 | ||
669 | /* if wordclock has synced freq and wordclock is valid */ | 978 | /* if wordclock has synced freq and wordclock is valid */ |
670 | if ((status2 & HDSPM_wcLock) != 0 && | 979 | if ((status2 & HDSPM_wcLock) != 0 && |
@@ -672,6 +981,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
672 | 981 | ||
673 | rate_bits = status2 & HDSPM_wcFreqMask; | 982 | rate_bits = status2 & HDSPM_wcFreqMask; |
674 | 983 | ||
984 | |||
675 | switch (rate_bits) { | 985 | switch (rate_bits) { |
676 | case HDSPM_wcFreq32: | 986 | case HDSPM_wcFreq32: |
677 | rate = 32000; | 987 | rate = 32000; |
@@ -691,7 +1001,6 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
691 | case HDSPM_wcFreq96: | 1001 | case HDSPM_wcFreq96: |
692 | rate = 96000; | 1002 | rate = 96000; |
693 | break; | 1003 | break; |
694 | /* Quadspeed Bit missing ???? */ | ||
695 | default: | 1004 | default: |
696 | rate = 0; | 1005 | rate = 0; |
697 | break; | 1006 | break; |
@@ -702,10 +1011,10 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
702 | * word has priority to MADI | 1011 | * word has priority to MADI |
703 | */ | 1012 | */ |
704 | if (rate != 0 && | 1013 | if (rate != 0 && |
705 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | 1014 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) |
706 | return rate; | 1015 | return rate; |
707 | 1016 | ||
708 | /* maby a madi input (which is taken if sel sync is madi) */ | 1017 | /* maybe a madi input (which is taken if sel sync is madi) */ |
709 | if (status & HDSPM_madiLock) { | 1018 | if (status & HDSPM_madiLock) { |
710 | rate_bits = status & HDSPM_madiFreqMask; | 1019 | rate_bits = status & HDSPM_madiFreqMask; |
711 | 1020 | ||
@@ -742,36 +1051,26 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
742 | break; | 1051 | break; |
743 | } | 1052 | } |
744 | } | 1053 | } |
745 | return rate; | 1054 | break; |
746 | } | 1055 | } |
1056 | |||
1057 | return rate; | ||
747 | } | 1058 | } |
748 | 1059 | ||
749 | /* Latency function */ | 1060 | /* Latency function */ |
750 | static inline void hdspm_compute_period_size(struct hdspm * hdspm) | 1061 | static inline void hdspm_compute_period_size(struct hdspm *hdspm) |
751 | { | 1062 | { |
752 | hdspm->period_bytes = | 1063 | hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); |
753 | 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); | ||
754 | } | 1064 | } |
755 | 1065 | ||
756 | static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm) | 1066 | |
1067 | static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm) | ||
757 | { | 1068 | { |
758 | int position; | 1069 | int position; |
759 | 1070 | ||
760 | position = hdspm_read(hdspm, HDSPM_statusRegister); | 1071 | position = hdspm_read(hdspm, HDSPM_statusRegister); |
761 | |||
762 | if (!hdspm->precise_ptr) | ||
763 | return (position & HDSPM_BufferID) ? | ||
764 | (hdspm->period_bytes / 4) : 0; | ||
765 | |||
766 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since | ||
767 | PCI Burst) | ||
768 | i have experimented that it is at most 64 Byte to much for playing | ||
769 | so substraction of 64 byte should be ok for ALSA, but use it only | ||
770 | for application where you know what you do since if you come to | ||
771 | near with record pointer it can be a disaster */ | ||
772 | |||
773 | position &= HDSPM_BufferPositionMask; | 1072 | position &= HDSPM_BufferPositionMask; |
774 | position = ((position - 64) % (2 * hdspm->period_bytes)) / 4; | 1073 | position /= 4; /* Bytes per sample */ |
775 | 1074 | ||
776 | return position; | 1075 | return position; |
777 | } | 1076 | } |
@@ -805,7 +1104,7 @@ static void hdspm_silence_playback(struct hdspm *hdspm) | |||
805 | } | 1104 | } |
806 | } | 1105 | } |
807 | 1106 | ||
808 | static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames) | 1107 | static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames) |
809 | { | 1108 | { |
810 | int n; | 1109 | int n; |
811 | 1110 | ||
@@ -829,21 +1128,53 @@ static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames) | |||
829 | return 0; | 1128 | return 0; |
830 | } | 1129 | } |
831 | 1130 | ||
1131 | static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period) | ||
1132 | { | ||
1133 | u64 freq_const; | ||
1134 | |||
1135 | if (period == 0) | ||
1136 | return 0; | ||
1137 | |||
1138 | switch (hdspm->io_type) { | ||
1139 | case MADI: | ||
1140 | case AES32: | ||
1141 | freq_const = 110069313433624ULL; | ||
1142 | break; | ||
1143 | case RayDAT: | ||
1144 | case AIO: | ||
1145 | freq_const = 104857600000000ULL; | ||
1146 | break; | ||
1147 | case MADIface: | ||
1148 | freq_const = 131072000000000ULL; | ||
1149 | } | ||
1150 | |||
1151 | return div_u64(freq_const, period); | ||
1152 | } | ||
1153 | |||
1154 | |||
832 | static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | 1155 | static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) |
833 | { | 1156 | { |
834 | u64 n; | 1157 | u64 n; |
835 | 1158 | ||
836 | if (rate >= 112000) | 1159 | if (rate >= 112000) |
837 | rate /= 4; | 1160 | rate /= 4; |
838 | else if (rate >= 56000) | 1161 | else if (rate >= 56000) |
839 | rate /= 2; | 1162 | rate /= 2; |
840 | 1163 | ||
841 | /* RME says n = 104857600000000, but in the windows MADI driver, I see: | 1164 | switch (hdspm->io_type) { |
842 | // return 104857600000000 / rate; // 100 MHz | 1165 | case MADIface: |
843 | return 110100480000000 / rate; // 105 MHz | 1166 | n = 131072000000000ULL; /* 125 MHz */ |
844 | */ | 1167 | break; |
845 | /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */ | 1168 | case MADI: |
846 | n = 110100480000000ULL; /* Value checked for AES32 and MADI */ | 1169 | case AES32: |
1170 | n = 110069313433624ULL; /* 105 MHz */ | ||
1171 | break; | ||
1172 | case RayDAT: | ||
1173 | case AIO: | ||
1174 | n = 104857600000000ULL; /* 100 MHz */ | ||
1175 | break; | ||
1176 | } | ||
1177 | |||
847 | n = div_u64(n, rate); | 1178 | n = div_u64(n, rate); |
848 | /* n should be less than 2^32 for being written to FREQ register */ | 1179 | /* n should be less than 2^32 for being written to FREQ register */ |
849 | snd_BUG_ON(n >> 32); | 1180 | snd_BUG_ON(n >> 32); |
@@ -864,13 +1195,13 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
864 | 1195 | ||
865 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { | 1196 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { |
866 | 1197 | ||
867 | /* SLAVE --- */ | 1198 | /* SLAVE --- */ |
868 | if (called_internally) { | 1199 | if (called_internally) { |
869 | 1200 | ||
870 | /* request from ctl or card initialization | 1201 | /* request from ctl or card initialization |
871 | just make a warning an remember setting | 1202 | just make a warning an remember setting |
872 | for future master mode switching */ | 1203 | for future master mode switching */ |
873 | 1204 | ||
874 | snd_printk(KERN_WARNING "HDSPM: " | 1205 | snd_printk(KERN_WARNING "HDSPM: " |
875 | "Warning: device is not running " | 1206 | "Warning: device is not running " |
876 | "as a clock master.\n"); | 1207 | "as a clock master.\n"); |
@@ -907,7 +1238,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
907 | 1238 | ||
908 | Note that a similar but essentially insoluble problem exists for | 1239 | Note that a similar but essentially insoluble problem exists for |
909 | externally-driven rate changes. All we can do is to flag rate | 1240 | externally-driven rate changes. All we can do is to flag rate |
910 | changes in the read/write routines. | 1241 | changes in the read/write routines. |
911 | */ | 1242 | */ |
912 | 1243 | ||
913 | if (current_rate <= 48000) | 1244 | if (current_rate <= 48000) |
@@ -975,16 +1306,35 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
975 | /* For AES32, need to set DDS value in FREQ register | 1306 | /* For AES32, need to set DDS value in FREQ register |
976 | For MADI, also apparently */ | 1307 | For MADI, also apparently */ |
977 | hdspm_set_dds_value(hdspm, rate); | 1308 | hdspm_set_dds_value(hdspm, rate); |
978 | 1309 | ||
979 | if (hdspm->is_aes32 && rate != current_rate) | 1310 | if (AES32 == hdspm->io_type && rate != current_rate) |
980 | hdspm_write(hdspm, HDSPM_eeprom_wr, 0); | 1311 | hdspm_write(hdspm, HDSPM_eeprom_wr, 0); |
981 | |||
982 | /* For AES32 and for MADI (at least rev 204), channel_map needs to | ||
983 | * always be channel_map_madi_ss, whatever the sample rate */ | ||
984 | hdspm->channel_map = channel_map_madi_ss; | ||
985 | 1312 | ||
986 | hdspm->system_sample_rate = rate; | 1313 | hdspm->system_sample_rate = rate; |
987 | 1314 | ||
1315 | if (rate <= 48000) { | ||
1316 | hdspm->channel_map_in = hdspm->channel_map_in_ss; | ||
1317 | hdspm->channel_map_out = hdspm->channel_map_out_ss; | ||
1318 | hdspm->max_channels_in = hdspm->ss_in_channels; | ||
1319 | hdspm->max_channels_out = hdspm->ss_out_channels; | ||
1320 | hdspm->port_names_in = hdspm->port_names_in_ss; | ||
1321 | hdspm->port_names_out = hdspm->port_names_out_ss; | ||
1322 | } else if (rate <= 96000) { | ||
1323 | hdspm->channel_map_in = hdspm->channel_map_in_ds; | ||
1324 | hdspm->channel_map_out = hdspm->channel_map_out_ds; | ||
1325 | hdspm->max_channels_in = hdspm->ds_in_channels; | ||
1326 | hdspm->max_channels_out = hdspm->ds_out_channels; | ||
1327 | hdspm->port_names_in = hdspm->port_names_in_ds; | ||
1328 | hdspm->port_names_out = hdspm->port_names_out_ds; | ||
1329 | } else { | ||
1330 | hdspm->channel_map_in = hdspm->channel_map_in_qs; | ||
1331 | hdspm->channel_map_out = hdspm->channel_map_out_qs; | ||
1332 | hdspm->max_channels_in = hdspm->qs_in_channels; | ||
1333 | hdspm->max_channels_out = hdspm->qs_out_channels; | ||
1334 | hdspm->port_names_in = hdspm->port_names_in_qs; | ||
1335 | hdspm->port_names_out = hdspm->port_names_out_qs; | ||
1336 | } | ||
1337 | |||
988 | if (not_set != 0) | 1338 | if (not_set != 0) |
989 | return -1; | 1339 | return -1; |
990 | 1340 | ||
@@ -1019,39 +1369,26 @@ static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, | |||
1019 | int id) | 1369 | int id) |
1020 | { | 1370 | { |
1021 | /* the hardware already does the relevant bit-mask with 0xff */ | 1371 | /* the hardware already does the relevant bit-mask with 0xff */ |
1022 | if (id) | 1372 | return hdspm_read(hdspm, hdspm->midi[id].dataIn); |
1023 | return hdspm_read(hdspm, HDSPM_midiDataIn1); | ||
1024 | else | ||
1025 | return hdspm_read(hdspm, HDSPM_midiDataIn0); | ||
1026 | } | 1373 | } |
1027 | 1374 | ||
1028 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, | 1375 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, |
1029 | int val) | 1376 | int val) |
1030 | { | 1377 | { |
1031 | /* the hardware already does the relevant bit-mask with 0xff */ | 1378 | /* the hardware already does the relevant bit-mask with 0xff */ |
1032 | if (id) | 1379 | return hdspm_write(hdspm, hdspm->midi[id].dataOut, val); |
1033 | hdspm_write(hdspm, HDSPM_midiDataOut1, val); | ||
1034 | else | ||
1035 | hdspm_write(hdspm, HDSPM_midiDataOut0, val); | ||
1036 | } | 1380 | } |
1037 | 1381 | ||
1038 | static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id) | 1382 | static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id) |
1039 | { | 1383 | { |
1040 | if (id) | 1384 | return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF; |
1041 | return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff); | ||
1042 | else | ||
1043 | return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff); | ||
1044 | } | 1385 | } |
1045 | 1386 | ||
1046 | static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) | 1387 | static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) |
1047 | { | 1388 | { |
1048 | int fifo_bytes_used; | 1389 | int fifo_bytes_used; |
1049 | 1390 | ||
1050 | if (id) | 1391 | fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF; |
1051 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1); | ||
1052 | else | ||
1053 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0); | ||
1054 | fifo_bytes_used &= 0xff; | ||
1055 | 1392 | ||
1056 | if (fifo_bytes_used < 128) | 1393 | if (fifo_bytes_used < 128) |
1057 | return 128 - fifo_bytes_used; | 1394 | return 128 - fifo_bytes_used; |
@@ -1074,7 +1411,7 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1074 | unsigned char buf[128]; | 1411 | unsigned char buf[128]; |
1075 | 1412 | ||
1076 | /* Output is not interrupt driven */ | 1413 | /* Output is not interrupt driven */ |
1077 | 1414 | ||
1078 | spin_lock_irqsave (&hmidi->lock, flags); | 1415 | spin_lock_irqsave (&hmidi->lock, flags); |
1079 | if (hmidi->output && | 1416 | if (hmidi->output && |
1080 | !snd_rawmidi_transmit_empty (hmidi->output)) { | 1417 | !snd_rawmidi_transmit_empty (hmidi->output)) { |
@@ -1083,11 +1420,11 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1083 | if (n_pending > 0) { | 1420 | if (n_pending > 0) { |
1084 | if (n_pending > (int)sizeof (buf)) | 1421 | if (n_pending > (int)sizeof (buf)) |
1085 | n_pending = sizeof (buf); | 1422 | n_pending = sizeof (buf); |
1086 | 1423 | ||
1087 | to_write = snd_rawmidi_transmit (hmidi->output, buf, | 1424 | to_write = snd_rawmidi_transmit (hmidi->output, buf, |
1088 | n_pending); | 1425 | n_pending); |
1089 | if (to_write > 0) { | 1426 | if (to_write > 0) { |
1090 | for (i = 0; i < to_write; ++i) | 1427 | for (i = 0; i < to_write; ++i) |
1091 | snd_hdspm_midi_write_byte (hmidi->hdspm, | 1428 | snd_hdspm_midi_write_byte (hmidi->hdspm, |
1092 | hmidi->id, | 1429 | hmidi->id, |
1093 | buf[i]); | 1430 | buf[i]); |
@@ -1127,12 +1464,11 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) | |||
1127 | } | 1464 | } |
1128 | } | 1465 | } |
1129 | hmidi->pending = 0; | 1466 | hmidi->pending = 0; |
1130 | if (hmidi->id) | 1467 | |
1131 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; | 1468 | hmidi->hdspm->control_register |= hmidi->ie; |
1132 | else | ||
1133 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; | ||
1134 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, | 1469 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, |
1135 | hmidi->hdspm->control_register); | 1470 | hmidi->hdspm->control_register); |
1471 | |||
1136 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1472 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1137 | return snd_hdspm_midi_output_write (hmidi); | 1473 | return snd_hdspm_midi_output_write (hmidi); |
1138 | } | 1474 | } |
@@ -1143,20 +1479,18 @@ snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) | |||
1143 | struct hdspm *hdspm; | 1479 | struct hdspm *hdspm; |
1144 | struct hdspm_midi *hmidi; | 1480 | struct hdspm_midi *hmidi; |
1145 | unsigned long flags; | 1481 | unsigned long flags; |
1146 | u32 ie; | ||
1147 | 1482 | ||
1148 | hmidi = substream->rmidi->private_data; | 1483 | hmidi = substream->rmidi->private_data; |
1149 | hdspm = hmidi->hdspm; | 1484 | hdspm = hmidi->hdspm; |
1150 | ie = hmidi->id ? | 1485 | |
1151 | HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | ||
1152 | spin_lock_irqsave (&hdspm->lock, flags); | 1486 | spin_lock_irqsave (&hdspm->lock, flags); |
1153 | if (up) { | 1487 | if (up) { |
1154 | if (!(hdspm->control_register & ie)) { | 1488 | if (!(hdspm->control_register & hmidi->ie)) { |
1155 | snd_hdspm_flush_midi_input (hdspm, hmidi->id); | 1489 | snd_hdspm_flush_midi_input (hdspm, hmidi->id); |
1156 | hdspm->control_register |= ie; | 1490 | hdspm->control_register |= hmidi->ie; |
1157 | } | 1491 | } |
1158 | } else { | 1492 | } else { |
1159 | hdspm->control_register &= ~ie; | 1493 | hdspm->control_register &= ~hmidi->ie; |
1160 | } | 1494 | } |
1161 | 1495 | ||
1162 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 1496 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); |
@@ -1167,14 +1501,14 @@ static void snd_hdspm_midi_output_timer(unsigned long data) | |||
1167 | { | 1501 | { |
1168 | struct hdspm_midi *hmidi = (struct hdspm_midi *) data; | 1502 | struct hdspm_midi *hmidi = (struct hdspm_midi *) data; |
1169 | unsigned long flags; | 1503 | unsigned long flags; |
1170 | 1504 | ||
1171 | snd_hdspm_midi_output_write(hmidi); | 1505 | snd_hdspm_midi_output_write(hmidi); |
1172 | spin_lock_irqsave (&hmidi->lock, flags); | 1506 | spin_lock_irqsave (&hmidi->lock, flags); |
1173 | 1507 | ||
1174 | /* this does not bump hmidi->istimer, because the | 1508 | /* this does not bump hmidi->istimer, because the |
1175 | kernel automatically removed the timer when it | 1509 | kernel automatically removed the timer when it |
1176 | expired, and we are now adding it back, thus | 1510 | expired, and we are now adding it back, thus |
1177 | leaving istimer wherever it was set before. | 1511 | leaving istimer wherever it was set before. |
1178 | */ | 1512 | */ |
1179 | 1513 | ||
1180 | if (hmidi->istimer) { | 1514 | if (hmidi->istimer) { |
@@ -1288,22 +1622,103 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card, | |||
1288 | hdspm->midi[id].hdspm = hdspm; | 1622 | hdspm->midi[id].hdspm = hdspm; |
1289 | spin_lock_init (&hdspm->midi[id].lock); | 1623 | spin_lock_init (&hdspm->midi[id].lock); |
1290 | 1624 | ||
1291 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); | 1625 | if (0 == id) { |
1292 | err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi); | 1626 | if (MADIface == hdspm->io_type) { |
1293 | if (err < 0) | 1627 | /* MIDI-over-MADI on HDSPe MADIface */ |
1294 | return err; | 1628 | hdspm->midi[0].dataIn = HDSPM_midiDataIn2; |
1629 | hdspm->midi[0].statusIn = HDSPM_midiStatusIn2; | ||
1630 | hdspm->midi[0].dataOut = HDSPM_midiDataOut2; | ||
1631 | hdspm->midi[0].statusOut = HDSPM_midiStatusOut2; | ||
1632 | hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable; | ||
1633 | hdspm->midi[0].irq = HDSPM_midi2IRQPending; | ||
1634 | } else { | ||
1635 | hdspm->midi[0].dataIn = HDSPM_midiDataIn0; | ||
1636 | hdspm->midi[0].statusIn = HDSPM_midiStatusIn0; | ||
1637 | hdspm->midi[0].dataOut = HDSPM_midiDataOut0; | ||
1638 | hdspm->midi[0].statusOut = HDSPM_midiStatusOut0; | ||
1639 | hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable; | ||
1640 | hdspm->midi[0].irq = HDSPM_midi0IRQPending; | ||
1641 | } | ||
1642 | } else if (1 == id) { | ||
1643 | hdspm->midi[1].dataIn = HDSPM_midiDataIn1; | ||
1644 | hdspm->midi[1].statusIn = HDSPM_midiStatusIn1; | ||
1645 | hdspm->midi[1].dataOut = HDSPM_midiDataOut1; | ||
1646 | hdspm->midi[1].statusOut = HDSPM_midiStatusOut1; | ||
1647 | hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable; | ||
1648 | hdspm->midi[1].irq = HDSPM_midi1IRQPending; | ||
1649 | } else if ((2 == id) && (MADI == hdspm->io_type)) { | ||
1650 | /* MIDI-over-MADI on HDSPe MADI */ | ||
1651 | hdspm->midi[2].dataIn = HDSPM_midiDataIn2; | ||
1652 | hdspm->midi[2].statusIn = HDSPM_midiStatusIn2; | ||
1653 | hdspm->midi[2].dataOut = HDSPM_midiDataOut2; | ||
1654 | hdspm->midi[2].statusOut = HDSPM_midiStatusOut2; | ||
1655 | hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable; | ||
1656 | hdspm->midi[2].irq = HDSPM_midi2IRQPending; | ||
1657 | } else if (2 == id) { | ||
1658 | /* TCO MTC, read only */ | ||
1659 | hdspm->midi[2].dataIn = HDSPM_midiDataIn2; | ||
1660 | hdspm->midi[2].statusIn = HDSPM_midiStatusIn2; | ||
1661 | hdspm->midi[2].dataOut = -1; | ||
1662 | hdspm->midi[2].statusOut = -1; | ||
1663 | hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable; | ||
1664 | hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES; | ||
1665 | } else if (3 == id) { | ||
1666 | /* TCO MTC on HDSPe MADI */ | ||
1667 | hdspm->midi[3].dataIn = HDSPM_midiDataIn3; | ||
1668 | hdspm->midi[3].statusIn = HDSPM_midiStatusIn3; | ||
1669 | hdspm->midi[3].dataOut = -1; | ||
1670 | hdspm->midi[3].statusOut = -1; | ||
1671 | hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable; | ||
1672 | hdspm->midi[3].irq = HDSPM_midi3IRQPending; | ||
1673 | } | ||
1295 | 1674 | ||
1296 | sprintf(hdspm->midi[id].rmidi->name, "HDSPM MIDI %d", id+1); | 1675 | if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) || |
1297 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; | 1676 | (MADIface == hdspm->io_type)))) { |
1677 | if ((id == 0) && (MADIface == hdspm->io_type)) { | ||
1678 | sprintf(buf, "%s MIDIoverMADI", card->shortname); | ||
1679 | } else if ((id == 2) && (MADI == hdspm->io_type)) { | ||
1680 | sprintf(buf, "%s MIDIoverMADI", card->shortname); | ||
1681 | } else { | ||
1682 | sprintf(buf, "%s MIDI %d", card->shortname, id+1); | ||
1683 | } | ||
1684 | err = snd_rawmidi_new(card, buf, id, 1, 1, | ||
1685 | &hdspm->midi[id].rmidi); | ||
1686 | if (err < 0) | ||
1687 | return err; | ||
1298 | 1688 | ||
1299 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | 1689 | sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d", |
1300 | &snd_hdspm_midi_output); | 1690 | card->id, id+1); |
1301 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | 1691 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; |
1302 | &snd_hdspm_midi_input); | 1692 | |
1693 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, | ||
1694 | SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
1695 | &snd_hdspm_midi_output); | ||
1696 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, | ||
1697 | SNDRV_RAWMIDI_STREAM_INPUT, | ||
1698 | &snd_hdspm_midi_input); | ||
1699 | |||
1700 | hdspm->midi[id].rmidi->info_flags |= | ||
1701 | SNDRV_RAWMIDI_INFO_OUTPUT | | ||
1702 | SNDRV_RAWMIDI_INFO_INPUT | | ||
1703 | SNDRV_RAWMIDI_INFO_DUPLEX; | ||
1704 | } else { | ||
1705 | /* TCO MTC, read only */ | ||
1706 | sprintf(buf, "%s MTC %d", card->shortname, id+1); | ||
1707 | err = snd_rawmidi_new(card, buf, id, 1, 1, | ||
1708 | &hdspm->midi[id].rmidi); | ||
1709 | if (err < 0) | ||
1710 | return err; | ||
1303 | 1711 | ||
1304 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | | 1712 | sprintf(hdspm->midi[id].rmidi->name, |
1305 | SNDRV_RAWMIDI_INFO_INPUT | | 1713 | "%s MTC %d", card->id, id+1); |
1306 | SNDRV_RAWMIDI_INFO_DUPLEX; | 1714 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; |
1715 | |||
1716 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, | ||
1717 | SNDRV_RAWMIDI_STREAM_INPUT, | ||
1718 | &snd_hdspm_midi_input); | ||
1719 | |||
1720 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
1721 | } | ||
1307 | 1722 | ||
1308 | return 0; | 1723 | return 0; |
1309 | } | 1724 | } |
@@ -1312,12 +1727,15 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card, | |||
1312 | static void hdspm_midi_tasklet(unsigned long arg) | 1727 | static void hdspm_midi_tasklet(unsigned long arg) |
1313 | { | 1728 | { |
1314 | struct hdspm *hdspm = (struct hdspm *)arg; | 1729 | struct hdspm *hdspm = (struct hdspm *)arg; |
1315 | 1730 | int i = 0; | |
1316 | if (hdspm->midi[0].pending) | 1731 | |
1317 | snd_hdspm_midi_input_read (&hdspm->midi[0]); | 1732 | while (i < hdspm->midiPorts) { |
1318 | if (hdspm->midi[1].pending) | 1733 | if (hdspm->midi[i].pending) |
1319 | snd_hdspm_midi_input_read (&hdspm->midi[1]); | 1734 | snd_hdspm_midi_input_read(&hdspm->midi[i]); |
1320 | } | 1735 | |
1736 | i++; | ||
1737 | } | ||
1738 | } | ||
1321 | 1739 | ||
1322 | 1740 | ||
1323 | /*----------------------------------------------------------------------------- | 1741 | /*----------------------------------------------------------------------------- |
@@ -1326,6 +1744,22 @@ static void hdspm_midi_tasklet(unsigned long arg) | |||
1326 | 1744 | ||
1327 | /* get the system sample rate which is set */ | 1745 | /* get the system sample rate which is set */ |
1328 | 1746 | ||
1747 | |||
1748 | /** | ||
1749 | * Calculate the real sample rate from the | ||
1750 | * current DDS value. | ||
1751 | **/ | ||
1752 | static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | ||
1753 | { | ||
1754 | unsigned int period, rate; | ||
1755 | |||
1756 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
1757 | rate = hdspm_calc_dds_value(hdspm, period); | ||
1758 | |||
1759 | return rate; | ||
1760 | } | ||
1761 | |||
1762 | |||
1329 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ | 1763 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ |
1330 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1764 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1331 | .name = xname, \ | 1765 | .name = xname, \ |
@@ -1340,112 +1774,251 @@ static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, | |||
1340 | { | 1774 | { |
1341 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1775 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1342 | uinfo->count = 1; | 1776 | uinfo->count = 1; |
1777 | uinfo->value.integer.min = 27000; | ||
1778 | uinfo->value.integer.max = 207000; | ||
1779 | uinfo->value.integer.step = 1; | ||
1343 | return 0; | 1780 | return 0; |
1344 | } | 1781 | } |
1345 | 1782 | ||
1783 | |||
1346 | static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, | 1784 | static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, |
1347 | struct snd_ctl_elem_value * | 1785 | struct snd_ctl_elem_value * |
1348 | ucontrol) | 1786 | ucontrol) |
1349 | { | 1787 | { |
1350 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 1788 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1351 | 1789 | ||
1352 | ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate; | 1790 | ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm); |
1791 | return 0; | ||
1792 | } | ||
1793 | |||
1794 | |||
1795 | /** | ||
1796 | * Returns the WordClock sample rate class for the given card. | ||
1797 | **/ | ||
1798 | static int hdspm_get_wc_sample_rate(struct hdspm *hdspm) | ||
1799 | { | ||
1800 | int status; | ||
1801 | |||
1802 | switch (hdspm->io_type) { | ||
1803 | case RayDAT: | ||
1804 | case AIO: | ||
1805 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
1806 | return (status >> 16) & 0xF; | ||
1807 | break; | ||
1808 | default: | ||
1809 | break; | ||
1810 | } | ||
1811 | |||
1812 | |||
1813 | return 0; | ||
1814 | } | ||
1815 | |||
1816 | |||
1817 | /** | ||
1818 | * Returns the TCO sample rate class for the given card. | ||
1819 | **/ | ||
1820 | static int hdspm_get_tco_sample_rate(struct hdspm *hdspm) | ||
1821 | { | ||
1822 | int status; | ||
1823 | |||
1824 | if (hdspm->tco) { | ||
1825 | switch (hdspm->io_type) { | ||
1826 | case RayDAT: | ||
1827 | case AIO: | ||
1828 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
1829 | return (status >> 20) & 0xF; | ||
1830 | break; | ||
1831 | default: | ||
1832 | break; | ||
1833 | } | ||
1834 | } | ||
1835 | |||
1836 | return 0; | ||
1837 | } | ||
1838 | |||
1839 | |||
1840 | /** | ||
1841 | * Returns the SYNC_IN sample rate class for the given card. | ||
1842 | **/ | ||
1843 | static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm) | ||
1844 | { | ||
1845 | int status; | ||
1846 | |||
1847 | if (hdspm->tco) { | ||
1848 | switch (hdspm->io_type) { | ||
1849 | case RayDAT: | ||
1850 | case AIO: | ||
1851 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); | ||
1852 | return (status >> 12) & 0xF; | ||
1853 | break; | ||
1854 | default: | ||
1855 | break; | ||
1856 | } | ||
1857 | } | ||
1858 | |||
1353 | return 0; | 1859 | return 0; |
1354 | } | 1860 | } |
1355 | 1861 | ||
1862 | |||
1863 | /** | ||
1864 | * Returns the sample rate class for input source <idx> for | ||
1865 | * 'new style' cards like the AIO and RayDAT. | ||
1866 | **/ | ||
1867 | static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) | ||
1868 | { | ||
1869 | int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); | ||
1870 | |||
1871 | return (status >> (idx*4)) & 0xF; | ||
1872 | } | ||
1873 | |||
1874 | |||
1875 | |||
1356 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ | 1876 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ |
1357 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1877 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1358 | .name = xname, \ | 1878 | .name = xname, \ |
1359 | .index = xindex, \ | 1879 | .private_value = xindex, \ |
1360 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | 1880 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ |
1361 | .info = snd_hdspm_info_autosync_sample_rate, \ | 1881 | .info = snd_hdspm_info_autosync_sample_rate, \ |
1362 | .get = snd_hdspm_get_autosync_sample_rate \ | 1882 | .get = snd_hdspm_get_autosync_sample_rate \ |
1363 | } | 1883 | } |
1364 | 1884 | ||
1885 | |||
1365 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, | 1886 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, |
1366 | struct snd_ctl_elem_info *uinfo) | 1887 | struct snd_ctl_elem_info *uinfo) |
1367 | { | 1888 | { |
1368 | static char *texts[] = { "32000", "44100", "48000", | ||
1369 | "64000", "88200", "96000", | ||
1370 | "128000", "176400", "192000", | ||
1371 | "None" | ||
1372 | }; | ||
1373 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1889 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1374 | uinfo->count = 1; | 1890 | uinfo->count = 1; |
1375 | uinfo->value.enumerated.items = 10; | 1891 | uinfo->value.enumerated.items = 10; |
1892 | |||
1376 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1893 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1377 | uinfo->value.enumerated.item = | 1894 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
1378 | uinfo->value.enumerated.items - 1; | ||
1379 | strcpy(uinfo->value.enumerated.name, | 1895 | strcpy(uinfo->value.enumerated.name, |
1380 | texts[uinfo->value.enumerated.item]); | 1896 | texts_freq[uinfo->value.enumerated.item]); |
1381 | return 0; | 1897 | return 0; |
1382 | } | 1898 | } |
1383 | 1899 | ||
1900 | |||
1384 | static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, | 1901 | static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, |
1385 | struct snd_ctl_elem_value * | 1902 | struct snd_ctl_elem_value * |
1386 | ucontrol) | 1903 | ucontrol) |
1387 | { | 1904 | { |
1388 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 1905 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1389 | 1906 | ||
1390 | switch (hdspm_external_sample_rate(hdspm)) { | 1907 | switch (hdspm->io_type) { |
1391 | case 32000: | 1908 | case RayDAT: |
1392 | ucontrol->value.enumerated.item[0] = 0; | 1909 | switch (kcontrol->private_value) { |
1393 | break; | 1910 | case 0: |
1394 | case 44100: | 1911 | ucontrol->value.enumerated.item[0] = |
1395 | ucontrol->value.enumerated.item[0] = 1; | 1912 | hdspm_get_wc_sample_rate(hdspm); |
1396 | break; | 1913 | break; |
1397 | case 48000: | 1914 | case 7: |
1398 | ucontrol->value.enumerated.item[0] = 2; | 1915 | ucontrol->value.enumerated.item[0] = |
1399 | break; | 1916 | hdspm_get_tco_sample_rate(hdspm); |
1400 | case 64000: | 1917 | break; |
1401 | ucontrol->value.enumerated.item[0] = 3; | 1918 | case 8: |
1402 | break; | 1919 | ucontrol->value.enumerated.item[0] = |
1403 | case 88200: | 1920 | hdspm_get_sync_in_sample_rate(hdspm); |
1404 | ucontrol->value.enumerated.item[0] = 4; | 1921 | break; |
1405 | break; | 1922 | default: |
1406 | case 96000: | 1923 | ucontrol->value.enumerated.item[0] = |
1407 | ucontrol->value.enumerated.item[0] = 5; | 1924 | hdspm_get_s1_sample_rate(hdspm, |
1408 | break; | 1925 | kcontrol->private_value-1); |
1409 | case 128000: | 1926 | } |
1410 | ucontrol->value.enumerated.item[0] = 6; | ||
1411 | break; | ||
1412 | case 176400: | ||
1413 | ucontrol->value.enumerated.item[0] = 7; | ||
1414 | break; | ||
1415 | case 192000: | ||
1416 | ucontrol->value.enumerated.item[0] = 8; | ||
1417 | break; | ||
1418 | 1927 | ||
1928 | case AIO: | ||
1929 | switch (kcontrol->private_value) { | ||
1930 | case 0: /* WC */ | ||
1931 | ucontrol->value.enumerated.item[0] = | ||
1932 | hdspm_get_wc_sample_rate(hdspm); | ||
1933 | break; | ||
1934 | case 4: /* TCO */ | ||
1935 | ucontrol->value.enumerated.item[0] = | ||
1936 | hdspm_get_tco_sample_rate(hdspm); | ||
1937 | break; | ||
1938 | case 5: /* SYNC_IN */ | ||
1939 | ucontrol->value.enumerated.item[0] = | ||
1940 | hdspm_get_sync_in_sample_rate(hdspm); | ||
1941 | break; | ||
1942 | default: | ||
1943 | ucontrol->value.enumerated.item[0] = | ||
1944 | hdspm_get_s1_sample_rate(hdspm, | ||
1945 | ucontrol->id.index-1); | ||
1946 | } | ||
1419 | default: | 1947 | default: |
1420 | ucontrol->value.enumerated.item[0] = 9; | 1948 | break; |
1421 | } | 1949 | } |
1950 | |||
1422 | return 0; | 1951 | return 0; |
1423 | } | 1952 | } |
1424 | 1953 | ||
1954 | |||
1425 | #define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ | 1955 | #define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ |
1426 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1956 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1427 | .name = xname, \ | 1957 | .name = xname, \ |
1428 | .index = xindex, \ | 1958 | .index = xindex, \ |
1429 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | 1959 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ |
1430 | .info = snd_hdspm_info_system_clock_mode, \ | 1960 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
1431 | .get = snd_hdspm_get_system_clock_mode, \ | 1961 | .info = snd_hdspm_info_system_clock_mode, \ |
1432 | } | 1962 | .get = snd_hdspm_get_system_clock_mode, \ |
1963 | .put = snd_hdspm_put_system_clock_mode, \ | ||
1964 | } | ||
1965 | |||
1966 | |||
1967 | /** | ||
1968 | * Returns the system clock mode for the given card. | ||
1969 | * @returns 0 - master, 1 - slave | ||
1970 | **/ | ||
1971 | static int hdspm_system_clock_mode(struct hdspm *hdspm) | ||
1972 | { | ||
1973 | switch (hdspm->io_type) { | ||
1974 | case AIO: | ||
1975 | case RayDAT: | ||
1976 | if (hdspm->settings_register & HDSPM_c0Master) | ||
1977 | return 0; | ||
1978 | break; | ||
1979 | |||
1980 | default: | ||
1981 | if (hdspm->control_register & HDSPM_ClockModeMaster) | ||
1982 | return 0; | ||
1983 | } | ||
1433 | 1984 | ||
1985 | return 1; | ||
1986 | } | ||
1434 | 1987 | ||
1435 | 1988 | ||
1436 | static int hdspm_system_clock_mode(struct hdspm * hdspm) | 1989 | /** |
1990 | * Sets the system clock mode. | ||
1991 | * @param mode 0 - master, 1 - slave | ||
1992 | **/ | ||
1993 | static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode) | ||
1437 | { | 1994 | { |
1438 | /* Always reflect the hardware info, rme is never wrong !!!! */ | 1995 | switch (hdspm->io_type) { |
1996 | case AIO: | ||
1997 | case RayDAT: | ||
1998 | if (0 == mode) | ||
1999 | hdspm->settings_register |= HDSPM_c0Master; | ||
2000 | else | ||
2001 | hdspm->settings_register &= ~HDSPM_c0Master; | ||
1439 | 2002 | ||
1440 | if (hdspm->control_register & HDSPM_ClockModeMaster) | 2003 | hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); |
1441 | return 0; | 2004 | break; |
1442 | return 1; | 2005 | |
2006 | default: | ||
2007 | if (0 == mode) | ||
2008 | hdspm->control_register |= HDSPM_ClockModeMaster; | ||
2009 | else | ||
2010 | hdspm->control_register &= ~HDSPM_ClockModeMaster; | ||
2011 | |||
2012 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
2013 | hdspm->control_register); | ||
2014 | } | ||
1443 | } | 2015 | } |
1444 | 2016 | ||
2017 | |||
1445 | static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, | 2018 | static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, |
1446 | struct snd_ctl_elem_info *uinfo) | 2019 | struct snd_ctl_elem_info *uinfo) |
1447 | { | 2020 | { |
1448 | static char *texts[] = { "Master", "Slave" }; | 2021 | static char *texts[] = { "Master", "AutoSync" }; |
1449 | 2022 | ||
1450 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2023 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1451 | uinfo->count = 1; | 2024 | uinfo->count = 1; |
@@ -1463,96 +2036,83 @@ static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol, | |||
1463 | { | 2036 | { |
1464 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2037 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1465 | 2038 | ||
1466 | ucontrol->value.enumerated.item[0] = | 2039 | ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm); |
1467 | hdspm_system_clock_mode(hdspm); | ||
1468 | return 0; | 2040 | return 0; |
1469 | } | 2041 | } |
1470 | 2042 | ||
1471 | #define HDSPM_CLOCK_SOURCE(xname, xindex) \ | 2043 | static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol, |
1472 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2044 | struct snd_ctl_elem_value *ucontrol) |
1473 | .name = xname, \ | 2045 | { |
1474 | .index = xindex, \ | 2046 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1475 | .info = snd_hdspm_info_clock_source, \ | 2047 | int val; |
1476 | .get = snd_hdspm_get_clock_source, \ | 2048 | |
1477 | .put = snd_hdspm_put_clock_source \ | 2049 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
2050 | return -EBUSY; | ||
2051 | |||
2052 | val = ucontrol->value.enumerated.item[0]; | ||
2053 | if (val < 0) | ||
2054 | val = 0; | ||
2055 | else if (val > 1) | ||
2056 | val = 1; | ||
2057 | |||
2058 | hdspm_set_system_clock_mode(hdspm, val); | ||
2059 | |||
2060 | return 0; | ||
2061 | } | ||
2062 | |||
2063 | |||
2064 | #define HDSPM_INTERNAL_CLOCK(xname, xindex) \ | ||
2065 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2066 | .name = xname, \ | ||
2067 | .index = xindex, \ | ||
2068 | .info = snd_hdspm_info_clock_source, \ | ||
2069 | .get = snd_hdspm_get_clock_source, \ | ||
2070 | .put = snd_hdspm_put_clock_source \ | ||
1478 | } | 2071 | } |
1479 | 2072 | ||
2073 | |||
1480 | static int hdspm_clock_source(struct hdspm * hdspm) | 2074 | static int hdspm_clock_source(struct hdspm * hdspm) |
1481 | { | 2075 | { |
1482 | if (hdspm->control_register & HDSPM_ClockModeMaster) { | 2076 | switch (hdspm->system_sample_rate) { |
1483 | switch (hdspm->system_sample_rate) { | 2077 | case 32000: return 0; |
1484 | case 32000: | 2078 | case 44100: return 1; |
1485 | return 1; | 2079 | case 48000: return 2; |
1486 | case 44100: | 2080 | case 64000: return 3; |
1487 | return 2; | 2081 | case 88200: return 4; |
1488 | case 48000: | 2082 | case 96000: return 5; |
1489 | return 3; | 2083 | case 128000: return 6; |
1490 | case 64000: | 2084 | case 176400: return 7; |
1491 | return 4; | 2085 | case 192000: return 8; |
1492 | case 88200: | ||
1493 | return 5; | ||
1494 | case 96000: | ||
1495 | return 6; | ||
1496 | case 128000: | ||
1497 | return 7; | ||
1498 | case 176400: | ||
1499 | return 8; | ||
1500 | case 192000: | ||
1501 | return 9; | ||
1502 | default: | ||
1503 | return 3; | ||
1504 | } | ||
1505 | } else { | ||
1506 | return 0; | ||
1507 | } | 2086 | } |
2087 | |||
2088 | return -1; | ||
1508 | } | 2089 | } |
1509 | 2090 | ||
1510 | static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) | 2091 | static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) |
1511 | { | 2092 | { |
1512 | int rate; | 2093 | int rate; |
1513 | switch (mode) { | 2094 | switch (mode) { |
1514 | 2095 | case 0: | |
1515 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | 2096 | rate = 32000; break; |
1516 | if (hdspm_external_sample_rate(hdspm) != 0) { | 2097 | case 1: |
1517 | hdspm->control_register &= ~HDSPM_ClockModeMaster; | 2098 | rate = 44100; break; |
1518 | hdspm_write(hdspm, HDSPM_controlRegister, | 2099 | case 2: |
1519 | hdspm->control_register); | 2100 | rate = 48000; break; |
1520 | return 0; | 2101 | case 3: |
1521 | } | 2102 | rate = 64000; break; |
1522 | return -1; | 2103 | case 4: |
1523 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | 2104 | rate = 88200; break; |
1524 | rate = 32000; | 2105 | case 5: |
1525 | break; | 2106 | rate = 96000; break; |
1526 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | 2107 | case 6: |
1527 | rate = 44100; | 2108 | rate = 128000; break; |
1528 | break; | 2109 | case 7: |
1529 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | 2110 | rate = 176400; break; |
1530 | rate = 48000; | 2111 | case 8: |
1531 | break; | 2112 | rate = 192000; break; |
1532 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
1533 | rate = 64000; | ||
1534 | break; | ||
1535 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
1536 | rate = 88200; | ||
1537 | break; | ||
1538 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
1539 | rate = 96000; | ||
1540 | break; | ||
1541 | case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: | ||
1542 | rate = 128000; | ||
1543 | break; | ||
1544 | case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: | ||
1545 | rate = 176400; | ||
1546 | break; | ||
1547 | case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: | ||
1548 | rate = 192000; | ||
1549 | break; | ||
1550 | |||
1551 | default: | 2113 | default: |
1552 | rate = 44100; | 2114 | rate = 48000; |
1553 | } | 2115 | } |
1554 | hdspm->control_register |= HDSPM_ClockModeMaster; | ||
1555 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1556 | hdspm_set_rate(hdspm, rate, 1); | 2116 | hdspm_set_rate(hdspm, rate, 1); |
1557 | return 0; | 2117 | return 0; |
1558 | } | 2118 | } |
@@ -1560,25 +2120,16 @@ static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) | |||
1560 | static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol, | 2120 | static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol, |
1561 | struct snd_ctl_elem_info *uinfo) | 2121 | struct snd_ctl_elem_info *uinfo) |
1562 | { | 2122 | { |
1563 | static char *texts[] = { "AutoSync", | ||
1564 | "Internal 32.0 kHz", "Internal 44.1 kHz", | ||
1565 | "Internal 48.0 kHz", | ||
1566 | "Internal 64.0 kHz", "Internal 88.2 kHz", | ||
1567 | "Internal 96.0 kHz", | ||
1568 | "Internal 128.0 kHz", "Internal 176.4 kHz", | ||
1569 | "Internal 192.0 kHz" | ||
1570 | }; | ||
1571 | |||
1572 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2123 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1573 | uinfo->count = 1; | 2124 | uinfo->count = 1; |
1574 | uinfo->value.enumerated.items = 10; | 2125 | uinfo->value.enumerated.items = 9; |
1575 | 2126 | ||
1576 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 2127 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1577 | uinfo->value.enumerated.item = | 2128 | uinfo->value.enumerated.item = |
1578 | uinfo->value.enumerated.items - 1; | 2129 | uinfo->value.enumerated.items - 1; |
1579 | 2130 | ||
1580 | strcpy(uinfo->value.enumerated.name, | 2131 | strcpy(uinfo->value.enumerated.name, |
1581 | texts[uinfo->value.enumerated.item]); | 2132 | texts_freq[uinfo->value.enumerated.item+1]); |
1582 | 2133 | ||
1583 | return 0; | 2134 | return 0; |
1584 | } | 2135 | } |
@@ -1615,134 +2166,301 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, | |||
1615 | return change; | 2166 | return change; |
1616 | } | 2167 | } |
1617 | 2168 | ||
1618 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ | ||
1619 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1620 | .name = xname, \ | ||
1621 | .index = xindex, \ | ||
1622 | .info = snd_hdspm_info_pref_sync_ref, \ | ||
1623 | .get = snd_hdspm_get_pref_sync_ref, \ | ||
1624 | .put = snd_hdspm_put_pref_sync_ref \ | ||
1625 | } | ||
1626 | 2169 | ||
2170 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ | ||
2171 | {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2172 | .name = xname, \ | ||
2173 | .index = xindex, \ | ||
2174 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
2175 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2176 | .info = snd_hdspm_info_pref_sync_ref, \ | ||
2177 | .get = snd_hdspm_get_pref_sync_ref, \ | ||
2178 | .put = snd_hdspm_put_pref_sync_ref \ | ||
2179 | } | ||
2180 | |||
2181 | |||
2182 | /** | ||
2183 | * Returns the current preferred sync reference setting. | ||
2184 | * The semantics of the return value are depending on the | ||
2185 | * card, please see the comments for clarification. | ||
2186 | **/ | ||
1627 | static int hdspm_pref_sync_ref(struct hdspm * hdspm) | 2187 | static int hdspm_pref_sync_ref(struct hdspm * hdspm) |
1628 | { | 2188 | { |
1629 | /* Notice that this looks at the requested sync source, | 2189 | switch (hdspm->io_type) { |
1630 | not the one actually in use. | 2190 | case AES32: |
1631 | */ | ||
1632 | if (hdspm->is_aes32) { | ||
1633 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | 2191 | switch (hdspm->control_register & HDSPM_SyncRefMask) { |
1634 | /* number gives AES index, except for 0 which | 2192 | case 0: return 0; /* WC */ |
1635 | corresponds to WordClock */ | 2193 | case HDSPM_SyncRef0: return 1; /* AES 1 */ |
1636 | case 0: return 0; | 2194 | case HDSPM_SyncRef1: return 2; /* AES 2 */ |
1637 | case HDSPM_SyncRef0: return 1; | 2195 | case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */ |
1638 | case HDSPM_SyncRef1: return 2; | 2196 | case HDSPM_SyncRef2: return 4; /* AES 4 */ |
1639 | case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; | 2197 | case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */ |
1640 | case HDSPM_SyncRef2: return 4; | 2198 | case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */ |
1641 | case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; | 2199 | case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: |
1642 | case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; | 2200 | return 7; /* AES 7 */ |
1643 | case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7; | 2201 | case HDSPM_SyncRef3: return 8; /* AES 8 */ |
1644 | case HDSPM_SyncRef3: return 8; | 2202 | case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */ |
1645 | } | 2203 | } |
1646 | } else { | 2204 | break; |
1647 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | 2205 | |
1648 | case HDSPM_SyncRef_Word: | 2206 | case MADI: |
1649 | return HDSPM_SYNC_FROM_WORD; | 2207 | case MADIface: |
1650 | case HDSPM_SyncRef_MADI: | 2208 | if (hdspm->tco) { |
1651 | return HDSPM_SYNC_FROM_MADI; | 2209 | switch (hdspm->control_register & HDSPM_SyncRefMask) { |
2210 | case 0: return 0; /* WC */ | ||
2211 | case HDSPM_SyncRef0: return 1; /* MADI */ | ||
2212 | case HDSPM_SyncRef1: return 2; /* TCO */ | ||
2213 | case HDSPM_SyncRef1+HDSPM_SyncRef0: | ||
2214 | return 3; /* SYNC_IN */ | ||
2215 | } | ||
2216 | } else { | ||
2217 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
2218 | case 0: return 0; /* WC */ | ||
2219 | case HDSPM_SyncRef0: return 1; /* MADI */ | ||
2220 | case HDSPM_SyncRef1+HDSPM_SyncRef0: | ||
2221 | return 2; /* SYNC_IN */ | ||
2222 | } | ||
2223 | } | ||
2224 | break; | ||
2225 | |||
2226 | case RayDAT: | ||
2227 | if (hdspm->tco) { | ||
2228 | switch ((hdspm->settings_register & | ||
2229 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2230 | case 0: return 0; /* WC */ | ||
2231 | case 3: return 1; /* ADAT 1 */ | ||
2232 | case 4: return 2; /* ADAT 2 */ | ||
2233 | case 5: return 3; /* ADAT 3 */ | ||
2234 | case 6: return 4; /* ADAT 4 */ | ||
2235 | case 1: return 5; /* AES */ | ||
2236 | case 2: return 6; /* SPDIF */ | ||
2237 | case 9: return 7; /* TCO */ | ||
2238 | case 10: return 8; /* SYNC_IN */ | ||
2239 | } | ||
2240 | } else { | ||
2241 | switch ((hdspm->settings_register & | ||
2242 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2243 | case 0: return 0; /* WC */ | ||
2244 | case 3: return 1; /* ADAT 1 */ | ||
2245 | case 4: return 2; /* ADAT 2 */ | ||
2246 | case 5: return 3; /* ADAT 3 */ | ||
2247 | case 6: return 4; /* ADAT 4 */ | ||
2248 | case 1: return 5; /* AES */ | ||
2249 | case 2: return 6; /* SPDIF */ | ||
2250 | case 10: return 7; /* SYNC_IN */ | ||
2251 | } | ||
1652 | } | 2252 | } |
2253 | |||
2254 | break; | ||
2255 | |||
2256 | case AIO: | ||
2257 | if (hdspm->tco) { | ||
2258 | switch ((hdspm->settings_register & | ||
2259 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2260 | case 0: return 0; /* WC */ | ||
2261 | case 3: return 1; /* ADAT */ | ||
2262 | case 1: return 2; /* AES */ | ||
2263 | case 2: return 3; /* SPDIF */ | ||
2264 | case 9: return 4; /* TCO */ | ||
2265 | case 10: return 5; /* SYNC_IN */ | ||
2266 | } | ||
2267 | } else { | ||
2268 | switch ((hdspm->settings_register & | ||
2269 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2270 | case 0: return 0; /* WC */ | ||
2271 | case 3: return 1; /* ADAT */ | ||
2272 | case 1: return 2; /* AES */ | ||
2273 | case 2: return 3; /* SPDIF */ | ||
2274 | case 10: return 4; /* SYNC_IN */ | ||
2275 | } | ||
2276 | } | ||
2277 | |||
2278 | break; | ||
1653 | } | 2279 | } |
1654 | 2280 | ||
1655 | return HDSPM_SYNC_FROM_WORD; | 2281 | return -1; |
1656 | } | 2282 | } |
1657 | 2283 | ||
2284 | |||
2285 | /** | ||
2286 | * Set the preferred sync reference to <pref>. The semantics | ||
2287 | * of <pref> are depending on the card type, see the comments | ||
2288 | * for clarification. | ||
2289 | **/ | ||
1658 | static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) | 2290 | static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) |
1659 | { | 2291 | { |
1660 | hdspm->control_register &= ~HDSPM_SyncRefMask; | 2292 | int p = 0; |
1661 | 2293 | ||
1662 | if (hdspm->is_aes32) { | 2294 | switch (hdspm->io_type) { |
1663 | switch (pref) { | 2295 | case AES32: |
1664 | case 0: | 2296 | hdspm->control_register &= ~HDSPM_SyncRefMask; |
1665 | hdspm->control_register |= 0; | ||
1666 | break; | ||
1667 | case 1: | ||
1668 | hdspm->control_register |= HDSPM_SyncRef0; | ||
1669 | break; | ||
1670 | case 2: | ||
1671 | hdspm->control_register |= HDSPM_SyncRef1; | ||
1672 | break; | ||
1673 | case 3: | ||
1674 | hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1675 | break; | ||
1676 | case 4: | ||
1677 | hdspm->control_register |= HDSPM_SyncRef2; | ||
1678 | break; | ||
1679 | case 5: | ||
1680 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0; | ||
1681 | break; | ||
1682 | case 6: | ||
1683 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; | ||
1684 | break; | ||
1685 | case 7: | ||
1686 | hdspm->control_register |= | ||
1687 | HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1688 | break; | ||
1689 | case 8: | ||
1690 | hdspm->control_register |= HDSPM_SyncRef3; | ||
1691 | break; | ||
1692 | default: | ||
1693 | return -1; | ||
1694 | } | ||
1695 | } else { | ||
1696 | switch (pref) { | 2297 | switch (pref) { |
1697 | case HDSPM_SYNC_FROM_MADI: | 2298 | case 0: /* WC */ |
1698 | hdspm->control_register |= HDSPM_SyncRef_MADI; | 2299 | break; |
2300 | case 1: /* AES 1 */ | ||
2301 | hdspm->control_register |= HDSPM_SyncRef0; | ||
2302 | break; | ||
2303 | case 2: /* AES 2 */ | ||
2304 | hdspm->control_register |= HDSPM_SyncRef1; | ||
2305 | break; | ||
2306 | case 3: /* AES 3 */ | ||
2307 | hdspm->control_register |= | ||
2308 | HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
2309 | break; | ||
2310 | case 4: /* AES 4 */ | ||
2311 | hdspm->control_register |= HDSPM_SyncRef2; | ||
2312 | break; | ||
2313 | case 5: /* AES 5 */ | ||
2314 | hdspm->control_register |= | ||
2315 | HDSPM_SyncRef2+HDSPM_SyncRef0; | ||
1699 | break; | 2316 | break; |
1700 | case HDSPM_SYNC_FROM_WORD: | 2317 | case 6: /* AES 6 */ |
1701 | hdspm->control_register |= HDSPM_SyncRef_Word; | 2318 | hdspm->control_register |= |
2319 | HDSPM_SyncRef2+HDSPM_SyncRef1; | ||
2320 | break; | ||
2321 | case 7: /* AES 7 */ | ||
2322 | hdspm->control_register |= | ||
2323 | HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
2324 | break; | ||
2325 | case 8: /* AES 8 */ | ||
2326 | hdspm->control_register |= HDSPM_SyncRef3; | ||
2327 | break; | ||
2328 | case 9: /* TCO */ | ||
2329 | hdspm->control_register |= | ||
2330 | HDSPM_SyncRef3+HDSPM_SyncRef0; | ||
1702 | break; | 2331 | break; |
1703 | default: | 2332 | default: |
1704 | return -1; | 2333 | return -1; |
1705 | } | 2334 | } |
2335 | |||
2336 | break; | ||
2337 | |||
2338 | case MADI: | ||
2339 | case MADIface: | ||
2340 | hdspm->control_register &= ~HDSPM_SyncRefMask; | ||
2341 | if (hdspm->tco) { | ||
2342 | switch (pref) { | ||
2343 | case 0: /* WC */ | ||
2344 | break; | ||
2345 | case 1: /* MADI */ | ||
2346 | hdspm->control_register |= HDSPM_SyncRef0; | ||
2347 | break; | ||
2348 | case 2: /* TCO */ | ||
2349 | hdspm->control_register |= HDSPM_SyncRef1; | ||
2350 | break; | ||
2351 | case 3: /* SYNC_IN */ | ||
2352 | hdspm->control_register |= | ||
2353 | HDSPM_SyncRef0+HDSPM_SyncRef1; | ||
2354 | break; | ||
2355 | default: | ||
2356 | return -1; | ||
2357 | } | ||
2358 | } else { | ||
2359 | switch (pref) { | ||
2360 | case 0: /* WC */ | ||
2361 | break; | ||
2362 | case 1: /* MADI */ | ||
2363 | hdspm->control_register |= HDSPM_SyncRef0; | ||
2364 | break; | ||
2365 | case 2: /* SYNC_IN */ | ||
2366 | hdspm->control_register |= | ||
2367 | HDSPM_SyncRef0+HDSPM_SyncRef1; | ||
2368 | break; | ||
2369 | default: | ||
2370 | return -1; | ||
2371 | } | ||
2372 | } | ||
2373 | |||
2374 | break; | ||
2375 | |||
2376 | case RayDAT: | ||
2377 | if (hdspm->tco) { | ||
2378 | switch (pref) { | ||
2379 | case 0: p = 0; break; /* WC */ | ||
2380 | case 1: p = 3; break; /* ADAT 1 */ | ||
2381 | case 2: p = 4; break; /* ADAT 2 */ | ||
2382 | case 3: p = 5; break; /* ADAT 3 */ | ||
2383 | case 4: p = 6; break; /* ADAT 4 */ | ||
2384 | case 5: p = 1; break; /* AES */ | ||
2385 | case 6: p = 2; break; /* SPDIF */ | ||
2386 | case 7: p = 9; break; /* TCO */ | ||
2387 | case 8: p = 10; break; /* SYNC_IN */ | ||
2388 | default: return -1; | ||
2389 | } | ||
2390 | } else { | ||
2391 | switch (pref) { | ||
2392 | case 0: p = 0; break; /* WC */ | ||
2393 | case 1: p = 3; break; /* ADAT 1 */ | ||
2394 | case 2: p = 4; break; /* ADAT 2 */ | ||
2395 | case 3: p = 5; break; /* ADAT 3 */ | ||
2396 | case 4: p = 6; break; /* ADAT 4 */ | ||
2397 | case 5: p = 1; break; /* AES */ | ||
2398 | case 6: p = 2; break; /* SPDIF */ | ||
2399 | case 7: p = 10; break; /* SYNC_IN */ | ||
2400 | default: return -1; | ||
2401 | } | ||
2402 | } | ||
2403 | break; | ||
2404 | |||
2405 | case AIO: | ||
2406 | if (hdspm->tco) { | ||
2407 | switch (pref) { | ||
2408 | case 0: p = 0; break; /* WC */ | ||
2409 | case 1: p = 3; break; /* ADAT */ | ||
2410 | case 2: p = 1; break; /* AES */ | ||
2411 | case 3: p = 2; break; /* SPDIF */ | ||
2412 | case 4: p = 9; break; /* TCO */ | ||
2413 | case 5: p = 10; break; /* SYNC_IN */ | ||
2414 | default: return -1; | ||
2415 | } | ||
2416 | } else { | ||
2417 | switch (pref) { | ||
2418 | case 0: p = 0; break; /* WC */ | ||
2419 | case 1: p = 3; break; /* ADAT */ | ||
2420 | case 2: p = 1; break; /* AES */ | ||
2421 | case 3: p = 2; break; /* SPDIF */ | ||
2422 | case 4: p = 10; break; /* SYNC_IN */ | ||
2423 | default: return -1; | ||
2424 | } | ||
2425 | } | ||
2426 | break; | ||
1706 | } | 2427 | } |
1707 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 2428 | |
2429 | switch (hdspm->io_type) { | ||
2430 | case RayDAT: | ||
2431 | case AIO: | ||
2432 | hdspm->settings_register &= ~HDSPM_c0_SyncRefMask; | ||
2433 | hdspm->settings_register |= HDSPM_c0_SyncRef0 * p; | ||
2434 | hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); | ||
2435 | break; | ||
2436 | |||
2437 | case MADI: | ||
2438 | case MADIface: | ||
2439 | case AES32: | ||
2440 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
2441 | hdspm->control_register); | ||
2442 | } | ||
2443 | |||
1708 | return 0; | 2444 | return 0; |
1709 | } | 2445 | } |
1710 | 2446 | ||
2447 | |||
1711 | static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | 2448 | static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, |
1712 | struct snd_ctl_elem_info *uinfo) | 2449 | struct snd_ctl_elem_info *uinfo) |
1713 | { | 2450 | { |
1714 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2451 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1715 | 2452 | ||
1716 | if (hdspm->is_aes32) { | 2453 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1717 | static char *texts[] = { "Word", "AES1", "AES2", "AES3", | 2454 | uinfo->count = 1; |
1718 | "AES4", "AES5", "AES6", "AES7", "AES8" }; | 2455 | uinfo->value.enumerated.items = hdspm->texts_autosync_items; |
1719 | |||
1720 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1721 | uinfo->count = 1; | ||
1722 | |||
1723 | uinfo->value.enumerated.items = 9; | ||
1724 | |||
1725 | if (uinfo->value.enumerated.item >= | ||
1726 | uinfo->value.enumerated.items) | ||
1727 | uinfo->value.enumerated.item = | ||
1728 | uinfo->value.enumerated.items - 1; | ||
1729 | strcpy(uinfo->value.enumerated.name, | ||
1730 | texts[uinfo->value.enumerated.item]); | ||
1731 | } else { | ||
1732 | static char *texts[] = { "Word", "MADI" }; | ||
1733 | 2456 | ||
1734 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2457 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1735 | uinfo->count = 1; | 2458 | uinfo->value.enumerated.item = |
2459 | uinfo->value.enumerated.items - 1; | ||
1736 | 2460 | ||
1737 | uinfo->value.enumerated.items = 2; | 2461 | strcpy(uinfo->value.enumerated.name, |
2462 | hdspm->texts_autosync[uinfo->value.enumerated.item]); | ||
1738 | 2463 | ||
1739 | if (uinfo->value.enumerated.item >= | ||
1740 | uinfo->value.enumerated.items) | ||
1741 | uinfo->value.enumerated.item = | ||
1742 | uinfo->value.enumerated.items - 1; | ||
1743 | strcpy(uinfo->value.enumerated.name, | ||
1744 | texts[uinfo->value.enumerated.item]); | ||
1745 | } | ||
1746 | return 0; | 2464 | return 0; |
1747 | } | 2465 | } |
1748 | 2466 | ||
@@ -1750,32 +2468,41 @@ static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1750 | struct snd_ctl_elem_value *ucontrol) | 2468 | struct snd_ctl_elem_value *ucontrol) |
1751 | { | 2469 | { |
1752 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2470 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2471 | int psf = hdspm_pref_sync_ref(hdspm); | ||
1753 | 2472 | ||
1754 | ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); | 2473 | if (psf >= 0) { |
1755 | return 0; | 2474 | ucontrol->value.enumerated.item[0] = psf; |
2475 | return 0; | ||
2476 | } | ||
2477 | |||
2478 | return -1; | ||
1756 | } | 2479 | } |
1757 | 2480 | ||
1758 | static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | 2481 | static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, |
1759 | struct snd_ctl_elem_value *ucontrol) | 2482 | struct snd_ctl_elem_value *ucontrol) |
1760 | { | 2483 | { |
1761 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2484 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1762 | int change, max; | 2485 | int val, change = 0; |
1763 | unsigned int val; | ||
1764 | |||
1765 | max = hdspm->is_aes32 ? 9 : 2; | ||
1766 | 2486 | ||
1767 | if (!snd_hdspm_use_is_exclusive(hdspm)) | 2487 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
1768 | return -EBUSY; | 2488 | return -EBUSY; |
1769 | 2489 | ||
1770 | val = ucontrol->value.enumerated.item[0] % max; | 2490 | val = ucontrol->value.enumerated.item[0]; |
2491 | |||
2492 | if (val < 0) | ||
2493 | val = 0; | ||
2494 | else if (val >= hdspm->texts_autosync_items) | ||
2495 | val = hdspm->texts_autosync_items-1; | ||
1771 | 2496 | ||
1772 | spin_lock_irq(&hdspm->lock); | 2497 | spin_lock_irq(&hdspm->lock); |
1773 | change = (int) val != hdspm_pref_sync_ref(hdspm); | 2498 | if (val != hdspm_pref_sync_ref(hdspm)) |
1774 | hdspm_set_pref_sync_ref(hdspm, val); | 2499 | change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0; |
2500 | |||
1775 | spin_unlock_irq(&hdspm->lock); | 2501 | spin_unlock_irq(&hdspm->lock); |
1776 | return change; | 2502 | return change; |
1777 | } | 2503 | } |
1778 | 2504 | ||
2505 | |||
1779 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ | 2506 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ |
1780 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2507 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1781 | .name = xname, \ | 2508 | .name = xname, \ |
@@ -1785,18 +2512,18 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1785 | .get = snd_hdspm_get_autosync_ref, \ | 2512 | .get = snd_hdspm_get_autosync_ref, \ |
1786 | } | 2513 | } |
1787 | 2514 | ||
1788 | static int hdspm_autosync_ref(struct hdspm * hdspm) | 2515 | static int hdspm_autosync_ref(struct hdspm *hdspm) |
1789 | { | 2516 | { |
1790 | if (hdspm->is_aes32) { | 2517 | if (AES32 == hdspm->io_type) { |
1791 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 2518 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
1792 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & | 2519 | unsigned int syncref = |
1793 | 0xF; | 2520 | (status >> HDSPM_AES32_syncref_bit) & 0xF; |
1794 | if (syncref == 0) | 2521 | if (syncref == 0) |
1795 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; | 2522 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; |
1796 | if (syncref <= 8) | 2523 | if (syncref <= 8) |
1797 | return syncref; | 2524 | return syncref; |
1798 | return HDSPM_AES32_AUTOSYNC_FROM_NONE; | 2525 | return HDSPM_AES32_AUTOSYNC_FROM_NONE; |
1799 | } else { | 2526 | } else if (MADI == hdspm->io_type) { |
1800 | /* This looks at the autosync selected sync reference */ | 2527 | /* This looks at the autosync selected sync reference */ |
1801 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 2528 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
1802 | 2529 | ||
@@ -1805,22 +2532,27 @@ static int hdspm_autosync_ref(struct hdspm * hdspm) | |||
1805 | return HDSPM_AUTOSYNC_FROM_WORD; | 2532 | return HDSPM_AUTOSYNC_FROM_WORD; |
1806 | case HDSPM_SelSyncRef_MADI: | 2533 | case HDSPM_SelSyncRef_MADI: |
1807 | return HDSPM_AUTOSYNC_FROM_MADI; | 2534 | return HDSPM_AUTOSYNC_FROM_MADI; |
2535 | case HDSPM_SelSyncRef_TCO: | ||
2536 | return HDSPM_AUTOSYNC_FROM_TCO; | ||
2537 | case HDSPM_SelSyncRef_SyncIn: | ||
2538 | return HDSPM_AUTOSYNC_FROM_SYNC_IN; | ||
1808 | case HDSPM_SelSyncRef_NVALID: | 2539 | case HDSPM_SelSyncRef_NVALID: |
1809 | return HDSPM_AUTOSYNC_FROM_NONE; | 2540 | return HDSPM_AUTOSYNC_FROM_NONE; |
1810 | default: | 2541 | default: |
1811 | return 0; | 2542 | return 0; |
1812 | } | 2543 | } |
1813 | 2544 | ||
1814 | return 0; | ||
1815 | } | 2545 | } |
2546 | return 0; | ||
1816 | } | 2547 | } |
1817 | 2548 | ||
2549 | |||
1818 | static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | 2550 | static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, |
1819 | struct snd_ctl_elem_info *uinfo) | 2551 | struct snd_ctl_elem_info *uinfo) |
1820 | { | 2552 | { |
1821 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2553 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1822 | 2554 | ||
1823 | if (hdspm->is_aes32) { | 2555 | if (AES32 == hdspm->io_type) { |
1824 | static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", | 2556 | static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", |
1825 | "AES4", "AES5", "AES6", "AES7", "AES8", "None"}; | 2557 | "AES4", "AES5", "AES6", "AES7", "AES8", "None"}; |
1826 | 2558 | ||
@@ -1833,14 +2565,15 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1833 | uinfo->value.enumerated.items - 1; | 2565 | uinfo->value.enumerated.items - 1; |
1834 | strcpy(uinfo->value.enumerated.name, | 2566 | strcpy(uinfo->value.enumerated.name, |
1835 | texts[uinfo->value.enumerated.item]); | 2567 | texts[uinfo->value.enumerated.item]); |
1836 | } else { | 2568 | } else if (MADI == hdspm->io_type) { |
1837 | static char *texts[] = { "WordClock", "MADI", "None" }; | 2569 | static char *texts[] = {"Word Clock", "MADI", "TCO", |
2570 | "Sync In", "None" }; | ||
1838 | 2571 | ||
1839 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2572 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1840 | uinfo->count = 1; | 2573 | uinfo->count = 1; |
1841 | uinfo->value.enumerated.items = 3; | 2574 | uinfo->value.enumerated.items = 5; |
1842 | if (uinfo->value.enumerated.item >= | 2575 | if (uinfo->value.enumerated.item >= |
1843 | uinfo->value.enumerated.items) | 2576 | uinfo->value.enumerated.items) |
1844 | uinfo->value.enumerated.item = | 2577 | uinfo->value.enumerated.item = |
1845 | uinfo->value.enumerated.items - 1; | 2578 | uinfo->value.enumerated.items - 1; |
1846 | strcpy(uinfo->value.enumerated.name, | 2579 | strcpy(uinfo->value.enumerated.name, |
@@ -1858,6 +2591,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1858 | return 0; | 2591 | return 0; |
1859 | } | 2592 | } |
1860 | 2593 | ||
2594 | |||
1861 | #define HDSPM_LINE_OUT(xname, xindex) \ | 2595 | #define HDSPM_LINE_OUT(xname, xindex) \ |
1862 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2596 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1863 | .name = xname, \ | 2597 | .name = xname, \ |
@@ -1914,6 +2648,7 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol, | |||
1914 | return change; | 2648 | return change; |
1915 | } | 2649 | } |
1916 | 2650 | ||
2651 | |||
1917 | #define HDSPM_TX_64(xname, xindex) \ | 2652 | #define HDSPM_TX_64(xname, xindex) \ |
1918 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2653 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1919 | .name = xname, \ | 2654 | .name = xname, \ |
@@ -1969,6 +2704,7 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol, | |||
1969 | return change; | 2704 | return change; |
1970 | } | 2705 | } |
1971 | 2706 | ||
2707 | |||
1972 | #define HDSPM_C_TMS(xname, xindex) \ | 2708 | #define HDSPM_C_TMS(xname, xindex) \ |
1973 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2709 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1974 | .name = xname, \ | 2710 | .name = xname, \ |
@@ -2024,6 +2760,7 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol, | |||
2024 | return change; | 2760 | return change; |
2025 | } | 2761 | } |
2026 | 2762 | ||
2763 | |||
2027 | #define HDSPM_SAFE_MODE(xname, xindex) \ | 2764 | #define HDSPM_SAFE_MODE(xname, xindex) \ |
2028 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2765 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2029 | .name = xname, \ | 2766 | .name = xname, \ |
@@ -2079,6 +2816,7 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol, | |||
2079 | return change; | 2816 | return change; |
2080 | } | 2817 | } |
2081 | 2818 | ||
2819 | |||
2082 | #define HDSPM_EMPHASIS(xname, xindex) \ | 2820 | #define HDSPM_EMPHASIS(xname, xindex) \ |
2083 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2821 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2084 | .name = xname, \ | 2822 | .name = xname, \ |
@@ -2134,6 +2872,7 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol, | |||
2134 | return change; | 2872 | return change; |
2135 | } | 2873 | } |
2136 | 2874 | ||
2875 | |||
2137 | #define HDSPM_DOLBY(xname, xindex) \ | 2876 | #define HDSPM_DOLBY(xname, xindex) \ |
2138 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2877 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2139 | .name = xname, \ | 2878 | .name = xname, \ |
@@ -2189,6 +2928,7 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol, | |||
2189 | return change; | 2928 | return change; |
2190 | } | 2929 | } |
2191 | 2930 | ||
2931 | |||
2192 | #define HDSPM_PROFESSIONAL(xname, xindex) \ | 2932 | #define HDSPM_PROFESSIONAL(xname, xindex) \ |
2193 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2933 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2194 | .name = xname, \ | 2934 | .name = xname, \ |
@@ -2315,6 +3055,7 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, | |||
2315 | return change; | 3055 | return change; |
2316 | } | 3056 | } |
2317 | 3057 | ||
3058 | |||
2318 | #define HDSPM_DS_WIRE(xname, xindex) \ | 3059 | #define HDSPM_DS_WIRE(xname, xindex) \ |
2319 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3060 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2320 | .name = xname, \ | 3061 | .name = xname, \ |
@@ -2386,6 +3127,7 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, | |||
2386 | return change; | 3127 | return change; |
2387 | } | 3128 | } |
2388 | 3129 | ||
3130 | |||
2389 | #define HDSPM_QS_WIRE(xname, xindex) \ | 3131 | #define HDSPM_QS_WIRE(xname, xindex) \ |
2390 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3132 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2391 | .name = xname, \ | 3133 | .name = xname, \ |
@@ -2472,15 +3214,6 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | |||
2472 | return change; | 3214 | return change; |
2473 | } | 3215 | } |
2474 | 3216 | ||
2475 | /* Simple Mixer | ||
2476 | deprecated since to much faders ??? | ||
2477 | MIXER interface says output (source, destination, value) | ||
2478 | where source > MAX_channels are playback channels | ||
2479 | on MADICARD | ||
2480 | - playback mixer matrix: [channelout+64] [output] [value] | ||
2481 | - input(thru) mixer matrix: [channelin] [output] [value] | ||
2482 | (better do 2 kontrols for separation ?) | ||
2483 | */ | ||
2484 | 3217 | ||
2485 | #define HDSPM_MIXER(xname, xindex) \ | 3218 | #define HDSPM_MIXER(xname, xindex) \ |
2486 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 3219 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
@@ -2586,7 +3319,7 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, | |||
2586 | 3319 | ||
2587 | /* The simple mixer control(s) provide gain control for the | 3320 | /* The simple mixer control(s) provide gain control for the |
2588 | basic 1:1 mappings of playback streams to output | 3321 | basic 1:1 mappings of playback streams to output |
2589 | streams. | 3322 | streams. |
2590 | */ | 3323 | */ |
2591 | 3324 | ||
2592 | #define HDSPM_PLAYBACK_MIXER \ | 3325 | #define HDSPM_PLAYBACK_MIXER \ |
@@ -2604,7 +3337,7 @@ static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2604 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 3337 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2605 | uinfo->count = 1; | 3338 | uinfo->count = 1; |
2606 | uinfo->value.integer.min = 0; | 3339 | uinfo->value.integer.min = 0; |
2607 | uinfo->value.integer.max = 65536; | 3340 | uinfo->value.integer.max = 64; |
2608 | uinfo->value.integer.step = 1; | 3341 | uinfo->value.integer.step = 1; |
2609 | return 0; | 3342 | return 0; |
2610 | } | 3343 | } |
@@ -2614,28 +3347,17 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2614 | { | 3347 | { |
2615 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3348 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2616 | int channel; | 3349 | int channel; |
2617 | int mapped_channel; | ||
2618 | 3350 | ||
2619 | channel = ucontrol->id.index - 1; | 3351 | channel = ucontrol->id.index - 1; |
2620 | 3352 | ||
2621 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) | 3353 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) |
2622 | return -EINVAL; | 3354 | return -EINVAL; |
2623 | 3355 | ||
2624 | mapped_channel = hdspm->channel_map[channel]; | ||
2625 | if (mapped_channel < 0) | ||
2626 | return -EINVAL; | ||
2627 | |||
2628 | spin_lock_irq(&hdspm->lock); | 3356 | spin_lock_irq(&hdspm->lock); |
2629 | ucontrol->value.integer.value[0] = | 3357 | ucontrol->value.integer.value[0] = |
2630 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); | 3358 | (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN; |
2631 | spin_unlock_irq(&hdspm->lock); | 3359 | spin_unlock_irq(&hdspm->lock); |
2632 | 3360 | ||
2633 | /* | ||
2634 | snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, " | ||
2635 | "value %d\n", | ||
2636 | ucontrol->id.index, channel, mapped_channel, | ||
2637 | ucontrol->value.integer.value[0]); | ||
2638 | */ | ||
2639 | return 0; | 3361 | return 0; |
2640 | } | 3362 | } |
2641 | 3363 | ||
@@ -2645,7 +3367,6 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2645 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3367 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2646 | int change; | 3368 | int change; |
2647 | int channel; | 3369 | int channel; |
2648 | int mapped_channel; | ||
2649 | int gain; | 3370 | int gain; |
2650 | 3371 | ||
2651 | if (!snd_hdspm_use_is_exclusive(hdspm)) | 3372 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
@@ -2656,59 +3377,60 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2656 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) | 3377 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) |
2657 | return -EINVAL; | 3378 | return -EINVAL; |
2658 | 3379 | ||
2659 | mapped_channel = hdspm->channel_map[channel]; | 3380 | gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64; |
2660 | if (mapped_channel < 0) | ||
2661 | return -EINVAL; | ||
2662 | |||
2663 | gain = ucontrol->value.integer.value[0]; | ||
2664 | 3381 | ||
2665 | spin_lock_irq(&hdspm->lock); | 3382 | spin_lock_irq(&hdspm->lock); |
2666 | change = | 3383 | change = |
2667 | gain != hdspm_read_pb_gain(hdspm, mapped_channel, | 3384 | gain != hdspm_read_pb_gain(hdspm, channel, |
2668 | mapped_channel); | 3385 | channel); |
2669 | if (change) | 3386 | if (change) |
2670 | hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel, | 3387 | hdspm_write_pb_gain(hdspm, channel, channel, |
2671 | gain); | 3388 | gain); |
2672 | spin_unlock_irq(&hdspm->lock); | 3389 | spin_unlock_irq(&hdspm->lock); |
2673 | return change; | 3390 | return change; |
2674 | } | 3391 | } |
2675 | 3392 | ||
2676 | #define HDSPM_WC_SYNC_CHECK(xname, xindex) \ | 3393 | #define HDSPM_SYNC_CHECK(xname, xindex) \ |
2677 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3394 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2678 | .name = xname, \ | 3395 | .name = xname, \ |
2679 | .index = xindex, \ | 3396 | .private_value = xindex, \ |
2680 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3397 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
2681 | .info = snd_hdspm_info_sync_check, \ | 3398 | .info = snd_hdspm_info_sync_check, \ |
2682 | .get = snd_hdspm_get_wc_sync_check \ | 3399 | .get = snd_hdspm_get_sync_check \ |
2683 | } | 3400 | } |
2684 | 3401 | ||
3402 | |||
2685 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, | 3403 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, |
2686 | struct snd_ctl_elem_info *uinfo) | 3404 | struct snd_ctl_elem_info *uinfo) |
2687 | { | 3405 | { |
2688 | static char *texts[] = { "No Lock", "Lock", "Sync" }; | 3406 | static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; |
2689 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 3407 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2690 | uinfo->count = 1; | 3408 | uinfo->count = 1; |
2691 | uinfo->value.enumerated.items = 3; | 3409 | uinfo->value.enumerated.items = 4; |
2692 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 3410 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
2693 | uinfo->value.enumerated.item = | 3411 | uinfo->value.enumerated.item = |
2694 | uinfo->value.enumerated.items - 1; | 3412 | uinfo->value.enumerated.items - 1; |
2695 | strcpy(uinfo->value.enumerated.name, | 3413 | strcpy(uinfo->value.enumerated.name, |
2696 | texts[uinfo->value.enumerated.item]); | 3414 | texts[uinfo->value.enumerated.item]); |
2697 | return 0; | 3415 | return 0; |
2698 | } | 3416 | } |
2699 | 3417 | ||
2700 | static int hdspm_wc_sync_check(struct hdspm * hdspm) | 3418 | static int hdspm_wc_sync_check(struct hdspm *hdspm) |
2701 | { | 3419 | { |
2702 | if (hdspm->is_aes32) { | 3420 | int status, status2; |
2703 | int status = hdspm_read(hdspm, HDSPM_statusRegister); | 3421 | |
2704 | if (status & HDSPM_AES32_wcLock) { | 3422 | switch (hdspm->io_type) { |
2705 | /* I don't know how to differenciate sync from lock. | 3423 | case AES32: |
2706 | Doing as if sync for now */ | 3424 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
3425 | if (status & HDSPM_wcSync) | ||
2707 | return 2; | 3426 | return 2; |
2708 | } | 3427 | else if (status & HDSPM_wcLock) |
3428 | return 1; | ||
2709 | return 0; | 3429 | return 0; |
2710 | } else { | 3430 | break; |
2711 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 3431 | |
3432 | case MADI: | ||
3433 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
2712 | if (status2 & HDSPM_wcLock) { | 3434 | if (status2 & HDSPM_wcLock) { |
2713 | if (status2 & HDSPM_wcSync) | 3435 | if (status2 & HDSPM_wcSync) |
2714 | return 2; | 3436 | return 2; |
@@ -2716,29 +3438,30 @@ static int hdspm_wc_sync_check(struct hdspm * hdspm) | |||
2716 | return 1; | 3438 | return 1; |
2717 | } | 3439 | } |
2718 | return 0; | 3440 | return 0; |
2719 | } | 3441 | break; |
2720 | } | ||
2721 | 3442 | ||
2722 | static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol, | 3443 | case RayDAT: |
2723 | struct snd_ctl_elem_value *ucontrol) | 3444 | case AIO: |
2724 | { | 3445 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
2725 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2726 | 3446 | ||
2727 | ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm); | 3447 | if (status & 0x2000000) |
2728 | return 0; | 3448 | return 2; |
2729 | } | 3449 | else if (status & 0x1000000) |
3450 | return 1; | ||
3451 | return 0; | ||
3452 | |||
3453 | break; | ||
2730 | 3454 | ||
3455 | case MADIface: | ||
3456 | break; | ||
3457 | } | ||
2731 | 3458 | ||
2732 | #define HDSPM_MADI_SYNC_CHECK(xname, xindex) \ | 3459 | |
2733 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3460 | return 3; |
2734 | .name = xname, \ | ||
2735 | .index = xindex, \ | ||
2736 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2737 | .info = snd_hdspm_info_sync_check, \ | ||
2738 | .get = snd_hdspm_get_madisync_sync_check \ | ||
2739 | } | 3461 | } |
2740 | 3462 | ||
2741 | static int hdspm_madisync_sync_check(struct hdspm * hdspm) | 3463 | |
3464 | static int hdspm_madi_sync_check(struct hdspm *hdspm) | ||
2742 | { | 3465 | { |
2743 | int status = hdspm_read(hdspm, HDSPM_statusRegister); | 3466 | int status = hdspm_read(hdspm, HDSPM_statusRegister); |
2744 | if (status & HDSPM_madiLock) { | 3467 | if (status & HDSPM_madiLock) { |
@@ -2750,89 +3473,727 @@ static int hdspm_madisync_sync_check(struct hdspm * hdspm) | |||
2750 | return 0; | 3473 | return 0; |
2751 | } | 3474 | } |
2752 | 3475 | ||
2753 | static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol, | 3476 | |
2754 | struct snd_ctl_elem_value * | 3477 | static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx) |
2755 | ucontrol) | ||
2756 | { | 3478 | { |
2757 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3479 | int status, lock, sync; |
3480 | |||
3481 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
2758 | 3482 | ||
2759 | ucontrol->value.enumerated.item[0] = | 3483 | lock = (status & (0x1<<idx)) ? 1 : 0; |
2760 | hdspm_madisync_sync_check(hdspm); | 3484 | sync = (status & (0x100<<idx)) ? 1 : 0; |
3485 | |||
3486 | if (lock && sync) | ||
3487 | return 2; | ||
3488 | else if (lock) | ||
3489 | return 1; | ||
2761 | return 0; | 3490 | return 0; |
2762 | } | 3491 | } |
2763 | 3492 | ||
2764 | 3493 | ||
2765 | #define HDSPM_AES_SYNC_CHECK(xname, xindex) \ | 3494 | static int hdspm_sync_in_sync_check(struct hdspm *hdspm) |
2766 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3495 | { |
2767 | .name = xname, \ | 3496 | int status, lock = 0, sync = 0; |
2768 | .index = xindex, \ | 3497 | |
2769 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3498 | switch (hdspm->io_type) { |
2770 | .info = snd_hdspm_info_sync_check, \ | 3499 | case RayDAT: |
2771 | .get = snd_hdspm_get_aes_sync_check \ | 3500 | case AIO: |
3501 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_3); | ||
3502 | lock = (status & 0x400) ? 1 : 0; | ||
3503 | sync = (status & 0x800) ? 1 : 0; | ||
3504 | break; | ||
3505 | |||
3506 | case MADI: | ||
3507 | case AES32: | ||
3508 | status = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
3509 | lock = (status & 0x400000) ? 1 : 0; | ||
3510 | sync = (status & 0x800000) ? 1 : 0; | ||
3511 | break; | ||
3512 | |||
3513 | case MADIface: | ||
3514 | break; | ||
3515 | } | ||
3516 | |||
3517 | if (lock && sync) | ||
3518 | return 2; | ||
3519 | else if (lock) | ||
3520 | return 1; | ||
3521 | |||
3522 | return 0; | ||
2772 | } | 3523 | } |
2773 | 3524 | ||
2774 | static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx) | 3525 | static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx) |
2775 | { | 3526 | { |
2776 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 3527 | int status2, lock, sync; |
2777 | if (status2 & (HDSPM_LockAES >> idx)) { | 3528 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
2778 | /* I don't know how to differenciate sync from lock. | 3529 | |
2779 | Doing as if sync for now */ | 3530 | lock = (status2 & (0x0080 >> idx)) ? 1 : 0; |
3531 | sync = (status2 & (0x8000 >> idx)) ? 1 : 0; | ||
3532 | |||
3533 | if (sync) | ||
2780 | return 2; | 3534 | return 2; |
3535 | else if (lock) | ||
3536 | return 1; | ||
3537 | return 0; | ||
3538 | } | ||
3539 | |||
3540 | |||
3541 | static int hdspm_tco_sync_check(struct hdspm *hdspm) | ||
3542 | { | ||
3543 | int status; | ||
3544 | |||
3545 | if (hdspm->tco) { | ||
3546 | switch (hdspm->io_type) { | ||
3547 | case MADI: | ||
3548 | case AES32: | ||
3549 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
3550 | if (status & HDSPM_tcoLock) { | ||
3551 | if (status & HDSPM_tcoSync) | ||
3552 | return 2; | ||
3553 | else | ||
3554 | return 1; | ||
3555 | } | ||
3556 | return 0; | ||
3557 | |||
3558 | break; | ||
3559 | |||
3560 | case RayDAT: | ||
3561 | case AIO: | ||
3562 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
3563 | |||
3564 | if (status & 0x8000000) | ||
3565 | return 2; /* Sync */ | ||
3566 | if (status & 0x4000000) | ||
3567 | return 1; /* Lock */ | ||
3568 | return 0; /* No signal */ | ||
3569 | break; | ||
3570 | |||
3571 | default: | ||
3572 | break; | ||
3573 | } | ||
3574 | } | ||
3575 | |||
3576 | return 3; /* N/A */ | ||
3577 | } | ||
3578 | |||
3579 | |||
3580 | static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | ||
3581 | struct snd_ctl_elem_value *ucontrol) | ||
3582 | { | ||
3583 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3584 | int val = -1; | ||
3585 | |||
3586 | switch (hdspm->io_type) { | ||
3587 | case RayDAT: | ||
3588 | switch (kcontrol->private_value) { | ||
3589 | case 0: /* WC */ | ||
3590 | val = hdspm_wc_sync_check(hdspm); break; | ||
3591 | case 7: /* TCO */ | ||
3592 | val = hdspm_tco_sync_check(hdspm); break; | ||
3593 | case 8: /* SYNC IN */ | ||
3594 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3595 | default: | ||
3596 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | ||
3597 | } | ||
3598 | |||
3599 | case AIO: | ||
3600 | switch (kcontrol->private_value) { | ||
3601 | case 0: /* WC */ | ||
3602 | val = hdspm_wc_sync_check(hdspm); break; | ||
3603 | case 4: /* TCO */ | ||
3604 | val = hdspm_tco_sync_check(hdspm); break; | ||
3605 | case 5: /* SYNC IN */ | ||
3606 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3607 | default: | ||
3608 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | ||
3609 | } | ||
3610 | |||
3611 | case MADI: | ||
3612 | switch (kcontrol->private_value) { | ||
3613 | case 0: /* WC */ | ||
3614 | val = hdspm_wc_sync_check(hdspm); break; | ||
3615 | case 1: /* MADI */ | ||
3616 | val = hdspm_madi_sync_check(hdspm); break; | ||
3617 | case 2: /* TCO */ | ||
3618 | val = hdspm_tco_sync_check(hdspm); break; | ||
3619 | case 3: /* SYNC_IN */ | ||
3620 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3621 | } | ||
3622 | |||
3623 | case MADIface: | ||
3624 | val = hdspm_madi_sync_check(hdspm); /* MADI */ | ||
3625 | break; | ||
3626 | |||
3627 | case AES32: | ||
3628 | switch (kcontrol->private_value) { | ||
3629 | case 0: /* WC */ | ||
3630 | val = hdspm_wc_sync_check(hdspm); break; | ||
3631 | case 9: /* TCO */ | ||
3632 | val = hdspm_tco_sync_check(hdspm); break; | ||
3633 | case 10 /* SYNC IN */: | ||
3634 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3635 | default: | ||
3636 | val = hdspm_aes_sync_check(hdspm, | ||
3637 | ucontrol->id.index-1); | ||
3638 | } | ||
3639 | |||
3640 | } | ||
3641 | |||
3642 | if (-1 == val) | ||
3643 | val = 3; | ||
3644 | |||
3645 | ucontrol->value.enumerated.item[0] = val; | ||
3646 | return 0; | ||
3647 | } | ||
3648 | |||
3649 | |||
3650 | |||
3651 | /** | ||
3652 | * TCO controls | ||
3653 | **/ | ||
3654 | static void hdspm_tco_write(struct hdspm *hdspm) | ||
3655 | { | ||
3656 | unsigned int tc[4] = { 0, 0, 0, 0}; | ||
3657 | |||
3658 | switch (hdspm->tco->input) { | ||
3659 | case 0: | ||
3660 | tc[2] |= HDSPM_TCO2_set_input_MSB; | ||
3661 | break; | ||
3662 | case 1: | ||
3663 | tc[2] |= HDSPM_TCO2_set_input_LSB; | ||
3664 | break; | ||
3665 | default: | ||
3666 | break; | ||
3667 | } | ||
3668 | |||
3669 | switch (hdspm->tco->framerate) { | ||
3670 | case 1: | ||
3671 | tc[1] |= HDSPM_TCO1_LTC_Format_LSB; | ||
3672 | break; | ||
3673 | case 2: | ||
3674 | tc[1] |= HDSPM_TCO1_LTC_Format_MSB; | ||
3675 | break; | ||
3676 | case 3: | ||
3677 | tc[1] |= HDSPM_TCO1_LTC_Format_MSB + | ||
3678 | HDSPM_TCO1_set_drop_frame_flag; | ||
3679 | break; | ||
3680 | case 4: | ||
3681 | tc[1] |= HDSPM_TCO1_LTC_Format_LSB + | ||
3682 | HDSPM_TCO1_LTC_Format_MSB; | ||
3683 | break; | ||
3684 | case 5: | ||
3685 | tc[1] |= HDSPM_TCO1_LTC_Format_LSB + | ||
3686 | HDSPM_TCO1_LTC_Format_MSB + | ||
3687 | HDSPM_TCO1_set_drop_frame_flag; | ||
3688 | break; | ||
3689 | default: | ||
3690 | break; | ||
3691 | } | ||
3692 | |||
3693 | switch (hdspm->tco->wordclock) { | ||
3694 | case 1: | ||
3695 | tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB; | ||
3696 | break; | ||
3697 | case 2: | ||
3698 | tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB; | ||
3699 | break; | ||
3700 | default: | ||
3701 | break; | ||
3702 | } | ||
3703 | |||
3704 | switch (hdspm->tco->samplerate) { | ||
3705 | case 1: | ||
3706 | tc[2] |= HDSPM_TCO2_set_freq; | ||
3707 | break; | ||
3708 | case 2: | ||
3709 | tc[2] |= HDSPM_TCO2_set_freq_from_app; | ||
3710 | break; | ||
3711 | default: | ||
3712 | break; | ||
3713 | } | ||
3714 | |||
3715 | switch (hdspm->tco->pull) { | ||
3716 | case 1: | ||
3717 | tc[2] |= HDSPM_TCO2_set_pull_up; | ||
3718 | break; | ||
3719 | case 2: | ||
3720 | tc[2] |= HDSPM_TCO2_set_pull_down; | ||
3721 | break; | ||
3722 | case 3: | ||
3723 | tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4; | ||
3724 | break; | ||
3725 | case 4: | ||
3726 | tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4; | ||
3727 | break; | ||
3728 | default: | ||
3729 | break; | ||
3730 | } | ||
3731 | |||
3732 | if (1 == hdspm->tco->term) { | ||
3733 | tc[2] |= HDSPM_TCO2_set_term_75R; | ||
3734 | } | ||
3735 | |||
3736 | hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]); | ||
3737 | hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]); | ||
3738 | hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]); | ||
3739 | hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]); | ||
3740 | } | ||
3741 | |||
3742 | |||
3743 | #define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \ | ||
3744 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3745 | .name = xname, \ | ||
3746 | .index = xindex, \ | ||
3747 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
3748 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3749 | .info = snd_hdspm_info_tco_sample_rate, \ | ||
3750 | .get = snd_hdspm_get_tco_sample_rate, \ | ||
3751 | .put = snd_hdspm_put_tco_sample_rate \ | ||
3752 | } | ||
3753 | |||
3754 | static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol, | ||
3755 | struct snd_ctl_elem_info *uinfo) | ||
3756 | { | ||
3757 | static char *texts[] = { "44.1 kHz", "48 kHz" }; | ||
3758 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3759 | uinfo->count = 1; | ||
3760 | uinfo->value.enumerated.items = 2; | ||
3761 | |||
3762 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3763 | uinfo->value.enumerated.item = | ||
3764 | uinfo->value.enumerated.items - 1; | ||
3765 | |||
3766 | strcpy(uinfo->value.enumerated.name, | ||
3767 | texts[uinfo->value.enumerated.item]); | ||
3768 | |||
3769 | return 0; | ||
3770 | } | ||
3771 | |||
3772 | static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol, | ||
3773 | struct snd_ctl_elem_value *ucontrol) | ||
3774 | { | ||
3775 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3776 | |||
3777 | ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate; | ||
3778 | |||
3779 | return 0; | ||
3780 | } | ||
3781 | |||
3782 | static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol, | ||
3783 | struct snd_ctl_elem_value *ucontrol) | ||
3784 | { | ||
3785 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3786 | |||
3787 | if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) { | ||
3788 | hdspm->tco->samplerate = ucontrol->value.enumerated.item[0]; | ||
3789 | |||
3790 | hdspm_tco_write(hdspm); | ||
3791 | |||
3792 | return 1; | ||
3793 | } | ||
3794 | |||
3795 | return 0; | ||
3796 | } | ||
3797 | |||
3798 | |||
3799 | #define HDSPM_TCO_PULL(xname, xindex) \ | ||
3800 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3801 | .name = xname, \ | ||
3802 | .index = xindex, \ | ||
3803 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
3804 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3805 | .info = snd_hdspm_info_tco_pull, \ | ||
3806 | .get = snd_hdspm_get_tco_pull, \ | ||
3807 | .put = snd_hdspm_put_tco_pull \ | ||
3808 | } | ||
3809 | |||
3810 | static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol, | ||
3811 | struct snd_ctl_elem_info *uinfo) | ||
3812 | { | ||
3813 | static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; | ||
3814 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3815 | uinfo->count = 1; | ||
3816 | uinfo->value.enumerated.items = 5; | ||
3817 | |||
3818 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3819 | uinfo->value.enumerated.item = | ||
3820 | uinfo->value.enumerated.items - 1; | ||
3821 | |||
3822 | strcpy(uinfo->value.enumerated.name, | ||
3823 | texts[uinfo->value.enumerated.item]); | ||
3824 | |||
3825 | return 0; | ||
3826 | } | ||
3827 | |||
3828 | static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol, | ||
3829 | struct snd_ctl_elem_value *ucontrol) | ||
3830 | { | ||
3831 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3832 | |||
3833 | ucontrol->value.enumerated.item[0] = hdspm->tco->pull; | ||
3834 | |||
3835 | return 0; | ||
3836 | } | ||
3837 | |||
3838 | static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol, | ||
3839 | struct snd_ctl_elem_value *ucontrol) | ||
3840 | { | ||
3841 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3842 | |||
3843 | if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) { | ||
3844 | hdspm->tco->pull = ucontrol->value.enumerated.item[0]; | ||
3845 | |||
3846 | hdspm_tco_write(hdspm); | ||
3847 | |||
3848 | return 1; | ||
2781 | } | 3849 | } |
3850 | |||
2782 | return 0; | 3851 | return 0; |
2783 | } | 3852 | } |
2784 | 3853 | ||
2785 | static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol, | 3854 | #define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \ |
3855 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3856 | .name = xname, \ | ||
3857 | .index = xindex, \ | ||
3858 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
3859 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3860 | .info = snd_hdspm_info_tco_wck_conversion, \ | ||
3861 | .get = snd_hdspm_get_tco_wck_conversion, \ | ||
3862 | .put = snd_hdspm_put_tco_wck_conversion \ | ||
3863 | } | ||
3864 | |||
3865 | static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol, | ||
3866 | struct snd_ctl_elem_info *uinfo) | ||
3867 | { | ||
3868 | static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; | ||
3869 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3870 | uinfo->count = 1; | ||
3871 | uinfo->value.enumerated.items = 3; | ||
3872 | |||
3873 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3874 | uinfo->value.enumerated.item = | ||
3875 | uinfo->value.enumerated.items - 1; | ||
3876 | |||
3877 | strcpy(uinfo->value.enumerated.name, | ||
3878 | texts[uinfo->value.enumerated.item]); | ||
3879 | |||
3880 | return 0; | ||
3881 | } | ||
3882 | |||
3883 | static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol, | ||
3884 | struct snd_ctl_elem_value *ucontrol) | ||
3885 | { | ||
3886 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3887 | |||
3888 | ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock; | ||
3889 | |||
3890 | return 0; | ||
3891 | } | ||
3892 | |||
3893 | static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol, | ||
3894 | struct snd_ctl_elem_value *ucontrol) | ||
3895 | { | ||
3896 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3897 | |||
3898 | if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) { | ||
3899 | hdspm->tco->wordclock = ucontrol->value.enumerated.item[0]; | ||
3900 | |||
3901 | hdspm_tco_write(hdspm); | ||
3902 | |||
3903 | return 1; | ||
3904 | } | ||
3905 | |||
3906 | return 0; | ||
3907 | } | ||
3908 | |||
3909 | |||
3910 | #define HDSPM_TCO_FRAME_RATE(xname, xindex) \ | ||
3911 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3912 | .name = xname, \ | ||
3913 | .index = xindex, \ | ||
3914 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
3915 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3916 | .info = snd_hdspm_info_tco_frame_rate, \ | ||
3917 | .get = snd_hdspm_get_tco_frame_rate, \ | ||
3918 | .put = snd_hdspm_put_tco_frame_rate \ | ||
3919 | } | ||
3920 | |||
3921 | static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol, | ||
3922 | struct snd_ctl_elem_info *uinfo) | ||
3923 | { | ||
3924 | static char *texts[] = { "24 fps", "25 fps", "29.97fps", | ||
3925 | "29.97 dfps", "30 fps", "30 dfps" }; | ||
3926 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3927 | uinfo->count = 1; | ||
3928 | uinfo->value.enumerated.items = 6; | ||
3929 | |||
3930 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3931 | uinfo->value.enumerated.item = | ||
3932 | uinfo->value.enumerated.items - 1; | ||
3933 | |||
3934 | strcpy(uinfo->value.enumerated.name, | ||
3935 | texts[uinfo->value.enumerated.item]); | ||
3936 | |||
3937 | return 0; | ||
3938 | } | ||
3939 | |||
3940 | static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol, | ||
2786 | struct snd_ctl_elem_value *ucontrol) | 3941 | struct snd_ctl_elem_value *ucontrol) |
2787 | { | 3942 | { |
2788 | int offset; | ||
2789 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3943 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2790 | 3944 | ||
2791 | offset = ucontrol->id.index - 1; | 3945 | ucontrol->value.enumerated.item[0] = hdspm->tco->framerate; |
2792 | if (offset < 0 || offset >= 8) | ||
2793 | return -EINVAL; | ||
2794 | 3946 | ||
2795 | ucontrol->value.enumerated.item[0] = | ||
2796 | hdspm_aes_sync_check(hdspm, offset); | ||
2797 | return 0; | 3947 | return 0; |
2798 | } | 3948 | } |
2799 | 3949 | ||
3950 | static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol, | ||
3951 | struct snd_ctl_elem_value *ucontrol) | ||
3952 | { | ||
3953 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3954 | |||
3955 | if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) { | ||
3956 | hdspm->tco->framerate = ucontrol->value.enumerated.item[0]; | ||
2800 | 3957 | ||
2801 | static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | 3958 | hdspm_tco_write(hdspm); |
2802 | 3959 | ||
2803 | HDSPM_MIXER("Mixer", 0), | 3960 | return 1; |
2804 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 3961 | } |
2805 | HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), | 3962 | |
3963 | return 0; | ||
3964 | } | ||
3965 | |||
3966 | |||
3967 | #define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \ | ||
3968 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3969 | .name = xname, \ | ||
3970 | .index = xindex, \ | ||
3971 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
3972 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3973 | .info = snd_hdspm_info_tco_sync_source, \ | ||
3974 | .get = snd_hdspm_get_tco_sync_source, \ | ||
3975 | .put = snd_hdspm_put_tco_sync_source \ | ||
3976 | } | ||
3977 | |||
3978 | static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol, | ||
3979 | struct snd_ctl_elem_info *uinfo) | ||
3980 | { | ||
3981 | static char *texts[] = { "LTC", "Video", "WCK" }; | ||
3982 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3983 | uinfo->count = 1; | ||
3984 | uinfo->value.enumerated.items = 3; | ||
3985 | |||
3986 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3987 | uinfo->value.enumerated.item = | ||
3988 | uinfo->value.enumerated.items - 1; | ||
3989 | |||
3990 | strcpy(uinfo->value.enumerated.name, | ||
3991 | texts[uinfo->value.enumerated.item]); | ||
3992 | |||
3993 | return 0; | ||
3994 | } | ||
2806 | 3995 | ||
3996 | static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol, | ||
3997 | struct snd_ctl_elem_value *ucontrol) | ||
3998 | { | ||
3999 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4000 | |||
4001 | ucontrol->value.enumerated.item[0] = hdspm->tco->input; | ||
4002 | |||
4003 | return 0; | ||
4004 | } | ||
4005 | |||
4006 | static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol, | ||
4007 | struct snd_ctl_elem_value *ucontrol) | ||
4008 | { | ||
4009 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4010 | |||
4011 | if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) { | ||
4012 | hdspm->tco->input = ucontrol->value.enumerated.item[0]; | ||
4013 | |||
4014 | hdspm_tco_write(hdspm); | ||
4015 | |||
4016 | return 1; | ||
4017 | } | ||
4018 | |||
4019 | return 0; | ||
4020 | } | ||
4021 | |||
4022 | |||
4023 | #define HDSPM_TCO_WORD_TERM(xname, xindex) \ | ||
4024 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4025 | .name = xname, \ | ||
4026 | .index = xindex, \ | ||
4027 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
4028 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
4029 | .info = snd_hdspm_info_tco_word_term, \ | ||
4030 | .get = snd_hdspm_get_tco_word_term, \ | ||
4031 | .put = snd_hdspm_put_tco_word_term \ | ||
4032 | } | ||
4033 | |||
4034 | static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol, | ||
4035 | struct snd_ctl_elem_info *uinfo) | ||
4036 | { | ||
4037 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
4038 | uinfo->count = 1; | ||
4039 | uinfo->value.integer.min = 0; | ||
4040 | uinfo->value.integer.max = 1; | ||
4041 | |||
4042 | return 0; | ||
4043 | } | ||
4044 | |||
4045 | |||
4046 | static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol, | ||
4047 | struct snd_ctl_elem_value *ucontrol) | ||
4048 | { | ||
4049 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4050 | |||
4051 | ucontrol->value.enumerated.item[0] = hdspm->tco->term; | ||
4052 | |||
4053 | return 0; | ||
4054 | } | ||
4055 | |||
4056 | |||
4057 | static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol, | ||
4058 | struct snd_ctl_elem_value *ucontrol) | ||
4059 | { | ||
4060 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4061 | |||
4062 | if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) { | ||
4063 | hdspm->tco->term = ucontrol->value.enumerated.item[0]; | ||
4064 | |||
4065 | hdspm_tco_write(hdspm); | ||
4066 | |||
4067 | return 1; | ||
4068 | } | ||
4069 | |||
4070 | return 0; | ||
4071 | } | ||
4072 | |||
4073 | |||
4074 | |||
4075 | |||
4076 | static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | ||
4077 | HDSPM_MIXER("Mixer", 0), | ||
4078 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
2807 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | 4079 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
2808 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | 4080 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), |
2809 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | 4081 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), |
2810 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | 4082 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), |
2811 | /* 'External Rate' complies with the alsa control naming scheme */ | 4083 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), |
2812 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | 4084 | HDSPM_SYNC_CHECK("MADI SyncCheck", 1), |
2813 | HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), | 4085 | HDSPM_SYNC_CHECK("TCO SyncCHeck", 2), |
2814 | HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0), | 4086 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), |
2815 | HDSPM_LINE_OUT("Line Out", 0), | 4087 | HDSPM_LINE_OUT("Line Out", 0), |
2816 | HDSPM_TX_64("TX 64 channels mode", 0), | 4088 | HDSPM_TX_64("TX 64 channels mode", 0), |
2817 | HDSPM_C_TMS("Clear Track Marker", 0), | 4089 | HDSPM_C_TMS("Clear Track Marker", 0), |
2818 | HDSPM_SAFE_MODE("Safe Mode", 0), | 4090 | HDSPM_SAFE_MODE("Safe Mode", 0), |
4091 | HDSPM_INPUT_SELECT("Input Select", 0) | ||
4092 | }; | ||
4093 | |||
4094 | |||
4095 | static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { | ||
4096 | HDSPM_MIXER("Mixer", 0), | ||
4097 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
4098 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | ||
4099 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
4100 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
4101 | HDSPM_SYNC_CHECK("MADI SyncCheck", 0), | ||
4102 | HDSPM_TX_64("TX 64 channels mode", 0), | ||
4103 | HDSPM_C_TMS("Clear Track Marker", 0), | ||
4104 | HDSPM_SAFE_MODE("Safe Mode", 0), | ||
2819 | HDSPM_INPUT_SELECT("Input Select", 0), | 4105 | HDSPM_INPUT_SELECT("Input Select", 0), |
2820 | }; | 4106 | }; |
2821 | 4107 | ||
2822 | static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | 4108 | static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { |
4109 | HDSPM_MIXER("Mixer", 0), | ||
4110 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
4111 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | ||
4112 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | ||
4113 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | ||
4114 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
4115 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
4116 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), | ||
4117 | HDSPM_SYNC_CHECK("AES SyncCheck", 1), | ||
4118 | HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2), | ||
4119 | HDSPM_SYNC_CHECK("ADAT SyncCheck", 3), | ||
4120 | HDSPM_SYNC_CHECK("TCO SyncCheck", 4), | ||
4121 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5), | ||
4122 | HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), | ||
4123 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1), | ||
4124 | HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2), | ||
4125 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3), | ||
4126 | HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4), | ||
4127 | HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5) | ||
4128 | |||
4129 | /* | ||
4130 | HDSPM_INPUT_SELECT("Input Select", 0), | ||
4131 | HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0), | ||
4132 | HDSPM_PROFESSIONAL("SPDIF Out Professional", 0); | ||
4133 | HDSPM_SPDIF_IN("SPDIF In", 0); | ||
4134 | HDSPM_BREAKOUT_CABLE("Breakout Cable", 0); | ||
4135 | HDSPM_INPUT_LEVEL("Input Level", 0); | ||
4136 | HDSPM_OUTPUT_LEVEL("Output Level", 0); | ||
4137 | HDSPM_PHONES("Phones", 0); | ||
4138 | */ | ||
4139 | }; | ||
2823 | 4140 | ||
4141 | static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { | ||
2824 | HDSPM_MIXER("Mixer", 0), | 4142 | HDSPM_MIXER("Mixer", 0), |
2825 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 4143 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
2826 | HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), | 4144 | HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0), |
4145 | HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0), | ||
4146 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
4147 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), | ||
4148 | HDSPM_SYNC_CHECK("AES SyncCheck", 1), | ||
4149 | HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2), | ||
4150 | HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3), | ||
4151 | HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4), | ||
4152 | HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5), | ||
4153 | HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6), | ||
4154 | HDSPM_SYNC_CHECK("TCO SyncCheck", 7), | ||
4155 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8), | ||
4156 | HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), | ||
4157 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1), | ||
4158 | HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2), | ||
4159 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3), | ||
4160 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4), | ||
4161 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5), | ||
4162 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6), | ||
4163 | HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7), | ||
4164 | HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8) | ||
4165 | }; | ||
2827 | 4166 | ||
4167 | static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | ||
4168 | HDSPM_MIXER("Mixer", 0), | ||
4169 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
2828 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | 4170 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
2829 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | 4171 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), |
2830 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | 4172 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), |
2831 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | 4173 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), |
2832 | /* 'External Rate' complies with the alsa control naming scheme */ | ||
2833 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | 4174 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), |
2834 | HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), | 4175 | HDSPM_SYNC_CHECK("WC Sync Check", 0), |
2835 | /* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */ | 4176 | HDSPM_SYNC_CHECK("AES1 Sync Check", 1), |
4177 | HDSPM_SYNC_CHECK("AES2 Sync Check", 2), | ||
4178 | HDSPM_SYNC_CHECK("AES3 Sync Check", 3), | ||
4179 | HDSPM_SYNC_CHECK("AES4 Sync Check", 4), | ||
4180 | HDSPM_SYNC_CHECK("AES5 Sync Check", 5), | ||
4181 | HDSPM_SYNC_CHECK("AES6 Sync Check", 6), | ||
4182 | HDSPM_SYNC_CHECK("AES7 Sync Check", 7), | ||
4183 | HDSPM_SYNC_CHECK("AES8 Sync Check", 8), | ||
4184 | HDSPM_SYNC_CHECK("TCO Sync Check", 9), | ||
4185 | HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10), | ||
4186 | HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), | ||
4187 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1), | ||
4188 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2), | ||
4189 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3), | ||
4190 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4), | ||
4191 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5), | ||
4192 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6), | ||
4193 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7), | ||
4194 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8), | ||
4195 | HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9), | ||
4196 | HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10), | ||
2836 | HDSPM_LINE_OUT("Line Out", 0), | 4197 | HDSPM_LINE_OUT("Line Out", 0), |
2837 | HDSPM_EMPHASIS("Emphasis", 0), | 4198 | HDSPM_EMPHASIS("Emphasis", 0), |
2838 | HDSPM_DOLBY("Non Audio", 0), | 4199 | HDSPM_DOLBY("Non Audio", 0), |
@@ -2842,6 +4203,19 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | |||
2842 | HDSPM_QS_WIRE("Quad Speed Wire Mode", 0), | 4203 | HDSPM_QS_WIRE("Quad Speed Wire Mode", 0), |
2843 | }; | 4204 | }; |
2844 | 4205 | ||
4206 | |||
4207 | |||
4208 | /* Control elements for the optional TCO module */ | ||
4209 | static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { | ||
4210 | HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0), | ||
4211 | HDSPM_TCO_PULL("TCO Pull", 0), | ||
4212 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), | ||
4213 | HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), | ||
4214 | HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), | ||
4215 | HDSPM_TCO_WORD_TERM("TCO Word Term", 0) | ||
4216 | }; | ||
4217 | |||
4218 | |||
2845 | static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; | 4219 | static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; |
2846 | 4220 | ||
2847 | 4221 | ||
@@ -2849,78 +4223,76 @@ static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm) | |||
2849 | { | 4223 | { |
2850 | int i; | 4224 | int i; |
2851 | 4225 | ||
2852 | for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) { | 4226 | for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) { |
2853 | if (hdspm->system_sample_rate > 48000) { | 4227 | if (hdspm->system_sample_rate > 48000) { |
2854 | hdspm->playback_mixer_ctls[i]->vd[0].access = | 4228 | hdspm->playback_mixer_ctls[i]->vd[0].access = |
2855 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | | 4229 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | |
2856 | SNDRV_CTL_ELEM_ACCESS_READ | | 4230 | SNDRV_CTL_ELEM_ACCESS_READ | |
2857 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; | 4231 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; |
2858 | } else { | 4232 | } else { |
2859 | hdspm->playback_mixer_ctls[i]->vd[0].access = | 4233 | hdspm->playback_mixer_ctls[i]->vd[0].access = |
2860 | SNDRV_CTL_ELEM_ACCESS_READWRITE | | 4234 | SNDRV_CTL_ELEM_ACCESS_READWRITE | |
2861 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; | 4235 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; |
2862 | } | 4236 | } |
2863 | snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | | 4237 | snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | |
2864 | SNDRV_CTL_EVENT_MASK_INFO, | 4238 | SNDRV_CTL_EVENT_MASK_INFO, |
2865 | &hdspm->playback_mixer_ctls[i]->id); | 4239 | &hdspm->playback_mixer_ctls[i]->id); |
2866 | } | 4240 | } |
2867 | 4241 | ||
2868 | return 0; | 4242 | return 0; |
2869 | } | 4243 | } |
2870 | 4244 | ||
2871 | 4245 | ||
2872 | static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm) | 4246 | static int snd_hdspm_create_controls(struct snd_card *card, |
4247 | struct hdspm *hdspm) | ||
2873 | { | 4248 | { |
2874 | unsigned int idx, limit; | 4249 | unsigned int idx, limit; |
2875 | int err; | 4250 | int err; |
2876 | struct snd_kcontrol *kctl; | 4251 | struct snd_kcontrol *kctl; |
4252 | struct snd_kcontrol_new *list = NULL; | ||
2877 | 4253 | ||
2878 | /* add control list first */ | 4254 | switch (hdspm->io_type) { |
2879 | if (hdspm->is_aes32) { | 4255 | case MADI: |
2880 | struct snd_kcontrol_new aes_sync_ctl = | 4256 | list = snd_hdspm_controls_madi; |
2881 | HDSPM_AES_SYNC_CHECK("AES Lock Status", 0); | 4257 | limit = ARRAY_SIZE(snd_hdspm_controls_madi); |
4258 | break; | ||
4259 | case MADIface: | ||
4260 | list = snd_hdspm_controls_madiface; | ||
4261 | limit = ARRAY_SIZE(snd_hdspm_controls_madiface); | ||
4262 | break; | ||
4263 | case AIO: | ||
4264 | list = snd_hdspm_controls_aio; | ||
4265 | limit = ARRAY_SIZE(snd_hdspm_controls_aio); | ||
4266 | break; | ||
4267 | case RayDAT: | ||
4268 | list = snd_hdspm_controls_raydat; | ||
4269 | limit = ARRAY_SIZE(snd_hdspm_controls_raydat); | ||
4270 | break; | ||
4271 | case AES32: | ||
4272 | list = snd_hdspm_controls_aes32; | ||
4273 | limit = ARRAY_SIZE(snd_hdspm_controls_aes32); | ||
4274 | break; | ||
4275 | } | ||
2882 | 4276 | ||
2883 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32); | 4277 | if (NULL != list) { |
2884 | idx++) { | 4278 | for (idx = 0; idx < limit; idx++) { |
2885 | err = snd_ctl_add(card, | ||
2886 | snd_ctl_new1(&snd_hdspm_controls_aes32[idx], | ||
2887 | hdspm)); | ||
2888 | if (err < 0) | ||
2889 | return err; | ||
2890 | } | ||
2891 | for (idx = 1; idx <= 8; idx++) { | ||
2892 | aes_sync_ctl.index = idx; | ||
2893 | err = snd_ctl_add(card, | ||
2894 | snd_ctl_new1(&aes_sync_ctl, hdspm)); | ||
2895 | if (err < 0) | ||
2896 | return err; | ||
2897 | } | ||
2898 | } else { | ||
2899 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi); | ||
2900 | idx++) { | ||
2901 | err = snd_ctl_add(card, | 4279 | err = snd_ctl_add(card, |
2902 | snd_ctl_new1(&snd_hdspm_controls_madi[idx], | 4280 | snd_ctl_new1(&list[idx], hdspm)); |
2903 | hdspm)); | ||
2904 | if (err < 0) | 4281 | if (err < 0) |
2905 | return err; | 4282 | return err; |
2906 | } | 4283 | } |
2907 | } | 4284 | } |
2908 | 4285 | ||
2909 | /* Channel playback mixer as default control | ||
2910 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, | ||
2911 | thats too * big for any alsamixer they are accessible via special | ||
2912 | IOCTL on hwdep and the mixer 2dimensional mixer control | ||
2913 | */ | ||
2914 | 4286 | ||
4287 | /* create simple 1:1 playback mixer controls */ | ||
2915 | snd_hdspm_playback_mixer.name = "Chn"; | 4288 | snd_hdspm_playback_mixer.name = "Chn"; |
2916 | limit = HDSPM_MAX_CHANNELS; | 4289 | if (hdspm->system_sample_rate >= 128000) { |
2917 | 4290 | limit = hdspm->qs_out_channels; | |
2918 | /* The index values are one greater than the channel ID so that | 4291 | } else if (hdspm->system_sample_rate >= 64000) { |
2919 | * alsamixer will display them correctly. We want to use the index | 4292 | limit = hdspm->ds_out_channels; |
2920 | * for fast lookup of the relevant channel, but if we use it at all, | 4293 | } else { |
2921 | * most ALSA software does the wrong thing with it ... | 4294 | limit = hdspm->ss_out_channels; |
2922 | */ | 4295 | } |
2923 | |||
2924 | for (idx = 0; idx < limit; ++idx) { | 4296 | for (idx = 0; idx < limit; ++idx) { |
2925 | snd_hdspm_playback_mixer.index = idx + 1; | 4297 | snd_hdspm_playback_mixer.index = idx + 1; |
2926 | kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); | 4298 | kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); |
@@ -2930,11 +4302,24 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
2930 | hdspm->playback_mixer_ctls[idx] = kctl; | 4302 | hdspm->playback_mixer_ctls[idx] = kctl; |
2931 | } | 4303 | } |
2932 | 4304 | ||
4305 | |||
4306 | if (hdspm->tco) { | ||
4307 | /* add tco control elements */ | ||
4308 | list = snd_hdspm_controls_tco; | ||
4309 | limit = ARRAY_SIZE(snd_hdspm_controls_tco); | ||
4310 | for (idx = 0; idx < limit; idx++) { | ||
4311 | err = snd_ctl_add(card, | ||
4312 | snd_ctl_new1(&list[idx], hdspm)); | ||
4313 | if (err < 0) | ||
4314 | return err; | ||
4315 | } | ||
4316 | } | ||
4317 | |||
2933 | return 0; | 4318 | return 0; |
2934 | } | 4319 | } |
2935 | 4320 | ||
2936 | /*------------------------------------------------------------ | 4321 | /*------------------------------------------------------------ |
2937 | /proc interface | 4322 | /proc interface |
2938 | ------------------------------------------------------------*/ | 4323 | ------------------------------------------------------------*/ |
2939 | 4324 | ||
2940 | static void | 4325 | static void |
@@ -2942,72 +4327,178 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
2942 | struct snd_info_buffer *buffer) | 4327 | struct snd_info_buffer *buffer) |
2943 | { | 4328 | { |
2944 | struct hdspm *hdspm = entry->private_data; | 4329 | struct hdspm *hdspm = entry->private_data; |
2945 | unsigned int status; | 4330 | unsigned int status, status2, control, freq; |
2946 | unsigned int status2; | 4331 | |
2947 | char *pref_sync_ref; | 4332 | char *pref_sync_ref; |
2948 | char *autosync_ref; | 4333 | char *autosync_ref; |
2949 | char *system_clock_mode; | 4334 | char *system_clock_mode; |
2950 | char *clock_source; | ||
2951 | char *insel; | 4335 | char *insel; |
2952 | char *syncref; | ||
2953 | int x, x2; | 4336 | int x, x2; |
2954 | 4337 | ||
4338 | /* TCO stuff */ | ||
4339 | int a, ltc, frames, seconds, minutes, hours; | ||
4340 | unsigned int period; | ||
4341 | u64 freq_const = 0; | ||
4342 | u32 rate; | ||
4343 | |||
2955 | status = hdspm_read(hdspm, HDSPM_statusRegister); | 4344 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
2956 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 4345 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
4346 | control = hdspm->control_register; | ||
4347 | freq = hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
2957 | 4348 | ||
2958 | snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", | 4349 | snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", |
2959 | hdspm->card_name, hdspm->card->number + 1, | 4350 | hdspm->card_name, hdspm->card->number + 1, |
2960 | hdspm->firmware_rev, | 4351 | hdspm->firmware_rev, |
2961 | (status2 & HDSPM_version0) | | 4352 | (status2 & HDSPM_version0) | |
2962 | (status2 & HDSPM_version1) | (status2 & | 4353 | (status2 & HDSPM_version1) | (status2 & |
2963 | HDSPM_version2)); | 4354 | HDSPM_version2)); |
4355 | |||
4356 | snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n", | ||
4357 | (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF, | ||
4358 | (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF); | ||
2964 | 4359 | ||
2965 | snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", | 4360 | snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", |
2966 | hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); | 4361 | hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); |
2967 | 4362 | ||
2968 | snd_iprintf(buffer, "--- System ---\n"); | 4363 | snd_iprintf(buffer, "--- System ---\n"); |
2969 | 4364 | ||
2970 | snd_iprintf(buffer, | 4365 | snd_iprintf(buffer, |
2971 | "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", | 4366 | "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", |
2972 | status & HDSPM_audioIRQPending, | 4367 | status & HDSPM_audioIRQPending, |
2973 | (status & HDSPM_midi0IRQPending) ? 1 : 0, | 4368 | (status & HDSPM_midi0IRQPending) ? 1 : 0, |
2974 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | 4369 | (status & HDSPM_midi1IRQPending) ? 1 : 0, |
2975 | hdspm->irq_count); | 4370 | hdspm->irq_count); |
2976 | snd_iprintf(buffer, | 4371 | snd_iprintf(buffer, |
2977 | "HW pointer: id = %d, rawptr = %d (%d->%d) " | 4372 | "HW pointer: id = %d, rawptr = %d (%d->%d) " |
2978 | "estimated= %ld (bytes)\n", | 4373 | "estimated= %ld (bytes)\n", |
2979 | ((status & HDSPM_BufferID) ? 1 : 0), | 4374 | ((status & HDSPM_BufferID) ? 1 : 0), |
2980 | (status & HDSPM_BufferPositionMask), | 4375 | (status & HDSPM_BufferPositionMask), |
2981 | (status & HDSPM_BufferPositionMask) % | 4376 | (status & HDSPM_BufferPositionMask) % |
2982 | (2 * (int)hdspm->period_bytes), | 4377 | (2 * (int)hdspm->period_bytes), |
2983 | ((status & HDSPM_BufferPositionMask) - 64) % | 4378 | ((status & HDSPM_BufferPositionMask) - 64) % |
2984 | (2 * (int)hdspm->period_bytes), | 4379 | (2 * (int)hdspm->period_bytes), |
2985 | (long) hdspm_hw_pointer(hdspm) * 4); | 4380 | (long) hdspm_hw_pointer(hdspm) * 4); |
2986 | 4381 | ||
2987 | snd_iprintf(buffer, | 4382 | snd_iprintf(buffer, |
2988 | "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", | 4383 | "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", |
2989 | hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, | 4384 | hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, |
2990 | hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, | 4385 | hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, |
2991 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 4386 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
2992 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 4387 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
2993 | snd_iprintf(buffer, | 4388 | snd_iprintf(buffer, |
2994 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " | 4389 | "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n", |
2995 | "status2=0x%x\n", | 4390 | hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF, |
2996 | hdspm->control_register, hdspm->control2_register, | 4391 | hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF); |
2997 | status, status2); | 4392 | snd_iprintf(buffer, |
4393 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " | ||
4394 | "status2=0x%x\n", | ||
4395 | hdspm->control_register, hdspm->control2_register, | ||
4396 | status, status2); | ||
4397 | if (status & HDSPM_tco_detect) { | ||
4398 | snd_iprintf(buffer, "TCO module detected.\n"); | ||
4399 | a = hdspm_read(hdspm, HDSPM_RD_TCO+4); | ||
4400 | if (a & HDSPM_TCO1_LTC_Input_valid) { | ||
4401 | snd_iprintf(buffer, " LTC valid, "); | ||
4402 | switch (a & (HDSPM_TCO1_LTC_Format_LSB | | ||
4403 | HDSPM_TCO1_LTC_Format_MSB)) { | ||
4404 | case 0: | ||
4405 | snd_iprintf(buffer, "24 fps, "); | ||
4406 | break; | ||
4407 | case HDSPM_TCO1_LTC_Format_LSB: | ||
4408 | snd_iprintf(buffer, "25 fps, "); | ||
4409 | break; | ||
4410 | case HDSPM_TCO1_LTC_Format_MSB: | ||
4411 | snd_iprintf(buffer, "29.97 fps, "); | ||
4412 | break; | ||
4413 | default: | ||
4414 | snd_iprintf(buffer, "30 fps, "); | ||
4415 | break; | ||
4416 | } | ||
4417 | if (a & HDSPM_TCO1_set_drop_frame_flag) { | ||
4418 | snd_iprintf(buffer, "drop frame\n"); | ||
4419 | } else { | ||
4420 | snd_iprintf(buffer, "full frame\n"); | ||
4421 | } | ||
4422 | } else { | ||
4423 | snd_iprintf(buffer, " no LTC\n"); | ||
4424 | } | ||
4425 | if (a & HDSPM_TCO1_Video_Input_Format_NTSC) { | ||
4426 | snd_iprintf(buffer, " Video: NTSC\n"); | ||
4427 | } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) { | ||
4428 | snd_iprintf(buffer, " Video: PAL\n"); | ||
4429 | } else { | ||
4430 | snd_iprintf(buffer, " No video\n"); | ||
4431 | } | ||
4432 | if (a & HDSPM_TCO1_TCO_lock) { | ||
4433 | snd_iprintf(buffer, " Sync: lock\n"); | ||
4434 | } else { | ||
4435 | snd_iprintf(buffer, " Sync: no lock\n"); | ||
4436 | } | ||
4437 | |||
4438 | switch (hdspm->io_type) { | ||
4439 | case MADI: | ||
4440 | case AES32: | ||
4441 | freq_const = 110069313433624ULL; | ||
4442 | break; | ||
4443 | case RayDAT: | ||
4444 | case AIO: | ||
4445 | freq_const = 104857600000000ULL; | ||
4446 | break; | ||
4447 | case MADIface: | ||
4448 | break; /* no TCO possible */ | ||
4449 | } | ||
4450 | |||
4451 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
4452 | snd_iprintf(buffer, " period: %u\n", period); | ||
4453 | |||
4454 | |||
4455 | /* rate = freq_const/period; */ | ||
4456 | rate = div_u64(freq_const, period); | ||
4457 | |||
4458 | if (control & HDSPM_QuadSpeed) { | ||
4459 | rate *= 4; | ||
4460 | } else if (control & HDSPM_DoubleSpeed) { | ||
4461 | rate *= 2; | ||
4462 | } | ||
4463 | |||
4464 | snd_iprintf(buffer, " Frequency: %u Hz\n", | ||
4465 | (unsigned int) rate); | ||
4466 | |||
4467 | ltc = hdspm_read(hdspm, HDSPM_RD_TCO); | ||
4468 | frames = ltc & 0xF; | ||
4469 | ltc >>= 4; | ||
4470 | frames += (ltc & 0x3) * 10; | ||
4471 | ltc >>= 4; | ||
4472 | seconds = ltc & 0xF; | ||
4473 | ltc >>= 4; | ||
4474 | seconds += (ltc & 0x7) * 10; | ||
4475 | ltc >>= 4; | ||
4476 | minutes = ltc & 0xF; | ||
4477 | ltc >>= 4; | ||
4478 | minutes += (ltc & 0x7) * 10; | ||
4479 | ltc >>= 4; | ||
4480 | hours = ltc & 0xF; | ||
4481 | ltc >>= 4; | ||
4482 | hours += (ltc & 0x3) * 10; | ||
4483 | snd_iprintf(buffer, | ||
4484 | " LTC In: %02d:%02d:%02d:%02d\n", | ||
4485 | hours, minutes, seconds, frames); | ||
4486 | |||
4487 | } else { | ||
4488 | snd_iprintf(buffer, "No TCO module detected.\n"); | ||
4489 | } | ||
2998 | 4490 | ||
2999 | snd_iprintf(buffer, "--- Settings ---\n"); | 4491 | snd_iprintf(buffer, "--- Settings ---\n"); |
3000 | 4492 | ||
3001 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & | 4493 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3002 | HDSPM_LatencyMask)); | 4494 | HDSPM_LatencyMask)); |
3003 | 4495 | ||
3004 | snd_iprintf(buffer, | 4496 | snd_iprintf(buffer, |
3005 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 4497 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
3006 | x, (unsigned long) hdspm->period_bytes); | 4498 | x, (unsigned long) hdspm->period_bytes); |
3007 | 4499 | ||
3008 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | 4500 | snd_iprintf(buffer, "Line out: %s\n", |
3009 | (hdspm->control_register & HDSPM_LineOut) ? "on " : "off", | 4501 | (hdspm->control_register & HDSPM_LineOut) ? "on " : "off"); |
3010 | (hdspm->precise_ptr) ? "on" : "off"); | ||
3011 | 4502 | ||
3012 | switch (hdspm->control_register & HDSPM_InputMask) { | 4503 | switch (hdspm->control_register & HDSPM_InputMask) { |
3013 | case HDSPM_InputOptical: | 4504 | case HDSPM_InputOptical: |
@@ -3017,63 +4508,22 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3017 | insel = "Coaxial"; | 4508 | insel = "Coaxial"; |
3018 | break; | 4509 | break; |
3019 | default: | 4510 | default: |
3020 | insel = "Unknown"; | 4511 | insel = "Unkown"; |
3021 | } | 4512 | } |
3022 | 4513 | ||
3023 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
3024 | case HDSPM_SyncRef_Word: | ||
3025 | syncref = "WordClock"; | ||
3026 | break; | ||
3027 | case HDSPM_SyncRef_MADI: | ||
3028 | syncref = "MADI"; | ||
3029 | break; | ||
3030 | default: | ||
3031 | syncref = "Unknown"; | ||
3032 | } | ||
3033 | snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel, | ||
3034 | syncref); | ||
3035 | |||
3036 | snd_iprintf(buffer, | 4514 | snd_iprintf(buffer, |
3037 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, " | 4515 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, " |
3038 | "Auto Input %s\n", | 4516 | "Auto Input %s\n", |
3039 | (hdspm-> | 4517 | (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off", |
3040 | control_register & HDSPM_clr_tms) ? "on" : "off", | 4518 | (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56", |
3041 | (hdspm-> | 4519 | (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off"); |
3042 | control_register & HDSPM_TX_64ch) ? "64" : "56", | 4520 | |
3043 | (hdspm-> | ||
3044 | control_register & HDSPM_AutoInp) ? "on" : "off"); | ||
3045 | 4521 | ||
3046 | switch (hdspm_clock_source(hdspm)) { | ||
3047 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
3048 | clock_source = "AutoSync"; | ||
3049 | break; | ||
3050 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
3051 | clock_source = "Internal 32 kHz"; | ||
3052 | break; | ||
3053 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
3054 | clock_source = "Internal 44.1 kHz"; | ||
3055 | break; | ||
3056 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
3057 | clock_source = "Internal 48 kHz"; | ||
3058 | break; | ||
3059 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
3060 | clock_source = "Internal 64 kHz"; | ||
3061 | break; | ||
3062 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
3063 | clock_source = "Internal 88.2 kHz"; | ||
3064 | break; | ||
3065 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
3066 | clock_source = "Internal 96 kHz"; | ||
3067 | break; | ||
3068 | default: | ||
3069 | clock_source = "Error"; | ||
3070 | } | ||
3071 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | ||
3072 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) | 4522 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) |
3073 | system_clock_mode = "Slave"; | 4523 | system_clock_mode = "AutoSync"; |
3074 | else | 4524 | else |
3075 | system_clock_mode = "Master"; | 4525 | system_clock_mode = "Master"; |
3076 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | 4526 | snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode); |
3077 | 4527 | ||
3078 | switch (hdspm_pref_sync_ref(hdspm)) { | 4528 | switch (hdspm_pref_sync_ref(hdspm)) { |
3079 | case HDSPM_SYNC_FROM_WORD: | 4529 | case HDSPM_SYNC_FROM_WORD: |
@@ -3082,15 +4532,21 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3082 | case HDSPM_SYNC_FROM_MADI: | 4532 | case HDSPM_SYNC_FROM_MADI: |
3083 | pref_sync_ref = "MADI Sync"; | 4533 | pref_sync_ref = "MADI Sync"; |
3084 | break; | 4534 | break; |
4535 | case HDSPM_SYNC_FROM_TCO: | ||
4536 | pref_sync_ref = "TCO"; | ||
4537 | break; | ||
4538 | case HDSPM_SYNC_FROM_SYNC_IN: | ||
4539 | pref_sync_ref = "Sync In"; | ||
4540 | break; | ||
3085 | default: | 4541 | default: |
3086 | pref_sync_ref = "XXXX Clock"; | 4542 | pref_sync_ref = "XXXX Clock"; |
3087 | break; | 4543 | break; |
3088 | } | 4544 | } |
3089 | snd_iprintf(buffer, "Preferred Sync Reference: %s\n", | 4545 | snd_iprintf(buffer, "Preferred Sync Reference: %s\n", |
3090 | pref_sync_ref); | 4546 | pref_sync_ref); |
3091 | 4547 | ||
3092 | snd_iprintf(buffer, "System Clock Frequency: %d\n", | 4548 | snd_iprintf(buffer, "System Clock Frequency: %d\n", |
3093 | hdspm->system_sample_rate); | 4549 | hdspm->system_sample_rate); |
3094 | 4550 | ||
3095 | 4551 | ||
3096 | snd_iprintf(buffer, "--- Status:\n"); | 4552 | snd_iprintf(buffer, "--- Status:\n"); |
@@ -3099,12 +4555,18 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3099 | x2 = status2 & HDSPM_wcSync; | 4555 | x2 = status2 & HDSPM_wcSync; |
3100 | 4556 | ||
3101 | snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", | 4557 | snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", |
3102 | (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : | 4558 | (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : |
3103 | "NoLock", | 4559 | "NoLock", |
3104 | (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : | 4560 | (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : |
3105 | "NoLock"); | 4561 | "NoLock"); |
3106 | 4562 | ||
3107 | switch (hdspm_autosync_ref(hdspm)) { | 4563 | switch (hdspm_autosync_ref(hdspm)) { |
4564 | case HDSPM_AUTOSYNC_FROM_SYNC_IN: | ||
4565 | autosync_ref = "Sync In"; | ||
4566 | break; | ||
4567 | case HDSPM_AUTOSYNC_FROM_TCO: | ||
4568 | autosync_ref = "TCO"; | ||
4569 | break; | ||
3108 | case HDSPM_AUTOSYNC_FROM_WORD: | 4570 | case HDSPM_AUTOSYNC_FROM_WORD: |
3109 | autosync_ref = "Word Clock"; | 4571 | autosync_ref = "Word Clock"; |
3110 | break; | 4572 | break; |
@@ -3119,15 +4581,15 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3119 | break; | 4581 | break; |
3120 | } | 4582 | } |
3121 | snd_iprintf(buffer, | 4583 | snd_iprintf(buffer, |
3122 | "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", | 4584 | "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", |
3123 | autosync_ref, hdspm_external_sample_rate(hdspm), | 4585 | autosync_ref, hdspm_external_sample_rate(hdspm), |
3124 | (status & HDSPM_madiFreqMask) >> 22, | 4586 | (status & HDSPM_madiFreqMask) >> 22, |
3125 | (status2 & HDSPM_wcFreqMask) >> 5); | 4587 | (status2 & HDSPM_wcFreqMask) >> 5); |
3126 | 4588 | ||
3127 | snd_iprintf(buffer, "Input: %s, Mode=%s\n", | 4589 | snd_iprintf(buffer, "Input: %s, Mode=%s\n", |
3128 | (status & HDSPM_AB_int) ? "Coax" : "Optical", | 4590 | (status & HDSPM_AB_int) ? "Coax" : "Optical", |
3129 | (status & HDSPM_RX_64ch) ? "64 channels" : | 4591 | (status & HDSPM_RX_64ch) ? "64 channels" : |
3130 | "56 channels"); | 4592 | "56 channels"); |
3131 | 4593 | ||
3132 | snd_iprintf(buffer, "\n"); | 4594 | snd_iprintf(buffer, "\n"); |
3133 | } | 4595 | } |
@@ -3142,8 +4604,6 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3142 | unsigned int timecode; | 4604 | unsigned int timecode; |
3143 | int pref_syncref; | 4605 | int pref_syncref; |
3144 | char *autosync_ref; | 4606 | char *autosync_ref; |
3145 | char *system_clock_mode; | ||
3146 | char *clock_source; | ||
3147 | int x; | 4607 | int x; |
3148 | 4608 | ||
3149 | status = hdspm_read(hdspm, HDSPM_statusRegister); | 4609 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
@@ -3183,24 +4643,27 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3183 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 4643 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
3184 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 4644 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
3185 | snd_iprintf(buffer, | 4645 | snd_iprintf(buffer, |
3186 | "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, " | 4646 | "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n", |
3187 | "timecode=0x%x\n", | 4647 | hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF, |
3188 | hdspm->control_register, | 4648 | hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF); |
3189 | status, status2, timecode); | 4649 | snd_iprintf(buffer, |
4650 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " | ||
4651 | "status2=0x%x\n", | ||
4652 | hdspm->control_register, hdspm->control2_register, | ||
4653 | status, status2); | ||
3190 | 4654 | ||
3191 | snd_iprintf(buffer, "--- Settings ---\n"); | 4655 | snd_iprintf(buffer, "--- Settings ---\n"); |
3192 | 4656 | ||
3193 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & | 4657 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3194 | HDSPM_LatencyMask)); | 4658 | HDSPM_LatencyMask)); |
3195 | 4659 | ||
3196 | snd_iprintf(buffer, | 4660 | snd_iprintf(buffer, |
3197 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 4661 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
3198 | x, (unsigned long) hdspm->period_bytes); | 4662 | x, (unsigned long) hdspm->period_bytes); |
3199 | 4663 | ||
3200 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | 4664 | snd_iprintf(buffer, "Line out: %s\n", |
3201 | (hdspm-> | 4665 | (hdspm-> |
3202 | control_register & HDSPM_LineOut) ? "on " : "off", | 4666 | control_register & HDSPM_LineOut) ? "on " : "off"); |
3203 | (hdspm->precise_ptr) ? "on" : "off"); | ||
3204 | 4667 | ||
3205 | snd_iprintf(buffer, | 4668 | snd_iprintf(buffer, |
3206 | "ClearTrackMarker %s, Emphasis %s, Dolby %s\n", | 4669 | "ClearTrackMarker %s, Emphasis %s, Dolby %s\n", |
@@ -3211,46 +4674,6 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3211 | (hdspm-> | 4674 | (hdspm-> |
3212 | control_register & HDSPM_Dolby) ? "on" : "off"); | 4675 | control_register & HDSPM_Dolby) ? "on" : "off"); |
3213 | 4676 | ||
3214 | switch (hdspm_clock_source(hdspm)) { | ||
3215 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
3216 | clock_source = "AutoSync"; | ||
3217 | break; | ||
3218 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
3219 | clock_source = "Internal 32 kHz"; | ||
3220 | break; | ||
3221 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
3222 | clock_source = "Internal 44.1 kHz"; | ||
3223 | break; | ||
3224 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
3225 | clock_source = "Internal 48 kHz"; | ||
3226 | break; | ||
3227 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
3228 | clock_source = "Internal 64 kHz"; | ||
3229 | break; | ||
3230 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
3231 | clock_source = "Internal 88.2 kHz"; | ||
3232 | break; | ||
3233 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
3234 | clock_source = "Internal 96 kHz"; | ||
3235 | break; | ||
3236 | case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: | ||
3237 | clock_source = "Internal 128 kHz"; | ||
3238 | break; | ||
3239 | case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: | ||
3240 | clock_source = "Internal 176.4 kHz"; | ||
3241 | break; | ||
3242 | case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: | ||
3243 | clock_source = "Internal 192 kHz"; | ||
3244 | break; | ||
3245 | default: | ||
3246 | clock_source = "Error"; | ||
3247 | } | ||
3248 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | ||
3249 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) | ||
3250 | system_clock_mode = "Slave"; | ||
3251 | else | ||
3252 | system_clock_mode = "Master"; | ||
3253 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | ||
3254 | 4677 | ||
3255 | pref_syncref = hdspm_pref_sync_ref(hdspm); | 4678 | pref_syncref = hdspm_pref_sync_ref(hdspm); |
3256 | if (pref_syncref == 0) | 4679 | if (pref_syncref == 0) |
@@ -3274,38 +4697,108 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3274 | snd_iprintf(buffer, "--- Status:\n"); | 4697 | snd_iprintf(buffer, "--- Status:\n"); |
3275 | 4698 | ||
3276 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", | 4699 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", |
3277 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", | 4700 | (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock", |
3278 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); | 4701 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); |
3279 | 4702 | ||
3280 | for (x = 0; x < 8; x++) { | 4703 | for (x = 0; x < 8; x++) { |
3281 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", | 4704 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", |
3282 | x+1, | 4705 | x+1, |
3283 | (status2 & (HDSPM_LockAES >> x)) ? | 4706 | (status2 & (HDSPM_LockAES >> x)) ? |
3284 | "Sync ": "No Lock", | 4707 | "Sync " : "No Lock", |
3285 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | 4708 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); |
3286 | } | 4709 | } |
3287 | 4710 | ||
3288 | switch (hdspm_autosync_ref(hdspm)) { | 4711 | switch (hdspm_autosync_ref(hdspm)) { |
3289 | case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break; | 4712 | case HDSPM_AES32_AUTOSYNC_FROM_NONE: |
3290 | case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break; | 4713 | autosync_ref = "None"; break; |
3291 | case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break; | 4714 | case HDSPM_AES32_AUTOSYNC_FROM_WORD: |
3292 | case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break; | 4715 | autosync_ref = "Word Clock"; break; |
3293 | case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break; | 4716 | case HDSPM_AES32_AUTOSYNC_FROM_AES1: |
3294 | case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break; | 4717 | autosync_ref = "AES1"; break; |
3295 | case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break; | 4718 | case HDSPM_AES32_AUTOSYNC_FROM_AES2: |
3296 | case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break; | 4719 | autosync_ref = "AES2"; break; |
3297 | case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break; | 4720 | case HDSPM_AES32_AUTOSYNC_FROM_AES3: |
3298 | case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break; | 4721 | autosync_ref = "AES3"; break; |
3299 | default: autosync_ref = "---"; break; | 4722 | case HDSPM_AES32_AUTOSYNC_FROM_AES4: |
4723 | autosync_ref = "AES4"; break; | ||
4724 | case HDSPM_AES32_AUTOSYNC_FROM_AES5: | ||
4725 | autosync_ref = "AES5"; break; | ||
4726 | case HDSPM_AES32_AUTOSYNC_FROM_AES6: | ||
4727 | autosync_ref = "AES6"; break; | ||
4728 | case HDSPM_AES32_AUTOSYNC_FROM_AES7: | ||
4729 | autosync_ref = "AES7"; break; | ||
4730 | case HDSPM_AES32_AUTOSYNC_FROM_AES8: | ||
4731 | autosync_ref = "AES8"; break; | ||
4732 | default: | ||
4733 | autosync_ref = "---"; break; | ||
3300 | } | 4734 | } |
3301 | snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref); | 4735 | snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref); |
3302 | 4736 | ||
3303 | snd_iprintf(buffer, "\n"); | 4737 | snd_iprintf(buffer, "\n"); |
3304 | } | 4738 | } |
3305 | 4739 | ||
4740 | static void | ||
4741 | snd_hdspm_proc_read_raydat(struct snd_info_entry *entry, | ||
4742 | struct snd_info_buffer *buffer) | ||
4743 | { | ||
4744 | struct hdspm *hdspm = entry->private_data; | ||
4745 | unsigned int status1, status2, status3, control, i; | ||
4746 | unsigned int lock, sync; | ||
4747 | |||
4748 | status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */ | ||
4749 | status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */ | ||
4750 | status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */ | ||
4751 | |||
4752 | control = hdspm->control_register; | ||
4753 | |||
4754 | snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1); | ||
4755 | snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2); | ||
4756 | snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3); | ||
4757 | |||
4758 | |||
4759 | snd_iprintf(buffer, "\n*** CLOCK MODE\n\n"); | ||
4760 | |||
4761 | snd_iprintf(buffer, "Clock mode : %s\n", | ||
4762 | (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave"); | ||
4763 | snd_iprintf(buffer, "System frequency: %d Hz\n", | ||
4764 | hdspm_get_system_sample_rate(hdspm)); | ||
4765 | |||
4766 | snd_iprintf(buffer, "\n*** INPUT STATUS\n\n"); | ||
4767 | |||
4768 | lock = 0x1; | ||
4769 | sync = 0x100; | ||
4770 | |||
4771 | for (i = 0; i < 8; i++) { | ||
4772 | snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n", | ||
4773 | i, | ||
4774 | (status1 & lock) ? 1 : 0, | ||
4775 | (status1 & sync) ? 1 : 0, | ||
4776 | texts_freq[(status2 >> (i * 4)) & 0xF]); | ||
4777 | |||
4778 | lock = lock<<1; | ||
4779 | sync = sync<<1; | ||
4780 | } | ||
4781 | |||
4782 | snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n", | ||
4783 | (status1 & 0x1000000) ? 1 : 0, | ||
4784 | (status1 & 0x2000000) ? 1 : 0, | ||
4785 | texts_freq[(status1 >> 16) & 0xF]); | ||
4786 | |||
4787 | snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n", | ||
4788 | (status1 & 0x4000000) ? 1 : 0, | ||
4789 | (status1 & 0x8000000) ? 1 : 0, | ||
4790 | texts_freq[(status1 >> 20) & 0xF]); | ||
4791 | |||
4792 | snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n", | ||
4793 | (status3 & 0x400) ? 1 : 0, | ||
4794 | (status3 & 0x800) ? 1 : 0, | ||
4795 | texts_freq[(status2 >> 12) & 0xF]); | ||
4796 | |||
4797 | } | ||
4798 | |||
3306 | #ifdef CONFIG_SND_DEBUG | 4799 | #ifdef CONFIG_SND_DEBUG |
3307 | static void | 4800 | static void |
3308 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | 4801 | snd_hdspm_proc_read_debug(struct snd_info_entry *entry, |
3309 | struct snd_info_buffer *buffer) | 4802 | struct snd_info_buffer *buffer) |
3310 | { | 4803 | { |
3311 | struct hdspm *hdspm = entry->private_data; | 4804 | struct hdspm *hdspm = entry->private_data; |
@@ -3322,16 +4815,68 @@ snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | |||
3322 | #endif | 4815 | #endif |
3323 | 4816 | ||
3324 | 4817 | ||
4818 | static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry, | ||
4819 | struct snd_info_buffer *buffer) | ||
4820 | { | ||
4821 | struct hdspm *hdspm = entry->private_data; | ||
4822 | int i; | ||
4823 | |||
4824 | snd_iprintf(buffer, "# generated by hdspm\n"); | ||
3325 | 4825 | ||
3326 | static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) | 4826 | for (i = 0; i < hdspm->max_channels_in; i++) { |
4827 | snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]); | ||
4828 | } | ||
4829 | } | ||
4830 | |||
4831 | static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry, | ||
4832 | struct snd_info_buffer *buffer) | ||
4833 | { | ||
4834 | struct hdspm *hdspm = entry->private_data; | ||
4835 | int i; | ||
4836 | |||
4837 | snd_iprintf(buffer, "# generated by hdspm\n"); | ||
4838 | |||
4839 | for (i = 0; i < hdspm->max_channels_out; i++) { | ||
4840 | snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]); | ||
4841 | } | ||
4842 | } | ||
4843 | |||
4844 | |||
4845 | static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm) | ||
3327 | { | 4846 | { |
3328 | struct snd_info_entry *entry; | 4847 | struct snd_info_entry *entry; |
3329 | 4848 | ||
3330 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) | 4849 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) { |
3331 | snd_info_set_text_ops(entry, hdspm, | 4850 | switch (hdspm->io_type) { |
3332 | hdspm->is_aes32 ? | 4851 | case AES32: |
3333 | snd_hdspm_proc_read_aes32 : | 4852 | snd_info_set_text_ops(entry, hdspm, |
3334 | snd_hdspm_proc_read_madi); | 4853 | snd_hdspm_proc_read_aes32); |
4854 | break; | ||
4855 | case MADI: | ||
4856 | snd_info_set_text_ops(entry, hdspm, | ||
4857 | snd_hdspm_proc_read_madi); | ||
4858 | break; | ||
4859 | case MADIface: | ||
4860 | /* snd_info_set_text_ops(entry, hdspm, | ||
4861 | snd_hdspm_proc_read_madiface); */ | ||
4862 | break; | ||
4863 | case RayDAT: | ||
4864 | snd_info_set_text_ops(entry, hdspm, | ||
4865 | snd_hdspm_proc_read_raydat); | ||
4866 | break; | ||
4867 | case AIO: | ||
4868 | break; | ||
4869 | } | ||
4870 | } | ||
4871 | |||
4872 | if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) { | ||
4873 | snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in); | ||
4874 | } | ||
4875 | |||
4876 | if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) { | ||
4877 | snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out); | ||
4878 | } | ||
4879 | |||
3335 | #ifdef CONFIG_SND_DEBUG | 4880 | #ifdef CONFIG_SND_DEBUG |
3336 | /* debug file to read all hdspm registers */ | 4881 | /* debug file to read all hdspm registers */ |
3337 | if (!snd_card_proc_new(hdspm->card, "debug", &entry)) | 4882 | if (!snd_card_proc_new(hdspm->card, "debug", &entry)) |
@@ -3341,47 +4886,48 @@ static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) | |||
3341 | } | 4886 | } |
3342 | 4887 | ||
3343 | /*------------------------------------------------------------ | 4888 | /*------------------------------------------------------------ |
3344 | hdspm intitialize | 4889 | hdspm intitialize |
3345 | ------------------------------------------------------------*/ | 4890 | ------------------------------------------------------------*/ |
3346 | 4891 | ||
3347 | static int snd_hdspm_set_defaults(struct hdspm * hdspm) | 4892 | static int snd_hdspm_set_defaults(struct hdspm * hdspm) |
3348 | { | 4893 | { |
3349 | unsigned int i; | ||
3350 | |||
3351 | /* ASSUMPTION: hdspm->lock is either held, or there is no need to | 4894 | /* ASSUMPTION: hdspm->lock is either held, or there is no need to |
3352 | hold it (e.g. during module initialization). | 4895 | hold it (e.g. during module initialization). |
3353 | */ | 4896 | */ |
3354 | 4897 | ||
3355 | /* set defaults: */ | 4898 | /* set defaults: */ |
3356 | 4899 | ||
3357 | if (hdspm->is_aes32) | 4900 | hdspm->settings_register = 0; |
4901 | |||
4902 | switch (hdspm->io_type) { | ||
4903 | case MADI: | ||
4904 | case MADIface: | ||
4905 | hdspm->control_register = | ||
4906 | 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000; | ||
4907 | break; | ||
4908 | |||
4909 | case RayDAT: | ||
4910 | case AIO: | ||
4911 | hdspm->settings_register = 0x1 + 0x1000; | ||
4912 | /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0, | ||
4913 | * line_out */ | ||
4914 | hdspm->control_register = | ||
4915 | 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000; | ||
4916 | break; | ||
4917 | |||
4918 | case AES32: | ||
3358 | hdspm->control_register = | 4919 | hdspm->control_register = |
3359 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 4920 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
3360 | hdspm_encode_latency(7) | /* latency maximum = | 4921 | hdspm_encode_latency(7) | /* latency max=8192samples */ |
3361 | * 8192 samples | ||
3362 | */ | ||
3363 | HDSPM_SyncRef0 | /* AES1 is syncclock */ | 4922 | HDSPM_SyncRef0 | /* AES1 is syncclock */ |
3364 | HDSPM_LineOut | /* Analog output in */ | 4923 | HDSPM_LineOut | /* Analog output in */ |
3365 | HDSPM_Professional; /* Professional mode */ | 4924 | HDSPM_Professional; /* Professional mode */ |
3366 | else | 4925 | break; |
3367 | hdspm->control_register = | 4926 | } |
3368 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | ||
3369 | hdspm_encode_latency(7) | /* latency maximum = | ||
3370 | * 8192 samples | ||
3371 | */ | ||
3372 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | ||
3373 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | ||
3374 | HDSPM_LineOut | /* Analog output in */ | ||
3375 | HDSPM_TX_64ch | /* transmit in 64ch mode */ | ||
3376 | HDSPM_AutoInp; /* AutoInput chossing (takeover) */ | ||
3377 | |||
3378 | /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ | ||
3379 | /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ | ||
3380 | /* ! HDSPM_clr_tms = do not clear bits in track marks */ | ||
3381 | 4927 | ||
3382 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 4928 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); |
3383 | 4929 | ||
3384 | if (!hdspm->is_aes32) { | 4930 | if (AES32 == hdspm->io_type) { |
3385 | /* No control2 register for AES32 */ | 4931 | /* No control2 register for AES32 */ |
3386 | #ifdef SNDRV_BIG_ENDIAN | 4932 | #ifdef SNDRV_BIG_ENDIAN |
3387 | hdspm->control2_register = HDSPM_BIGENDIAN_MODE; | 4933 | hdspm->control2_register = HDSPM_BIGENDIAN_MODE; |
@@ -3397,57 +4943,59 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
3397 | 4943 | ||
3398 | all_in_all_mixer(hdspm, 0 * UNITY_GAIN); | 4944 | all_in_all_mixer(hdspm, 0 * UNITY_GAIN); |
3399 | 4945 | ||
3400 | if (line_outs_monitor[hdspm->dev]) { | 4946 | if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) { |
3401 | 4947 | hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); | |
3402 | snd_printk(KERN_INFO "HDSPM: " | ||
3403 | "sending all playback streams to line outs.\n"); | ||
3404 | |||
3405 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { | ||
3406 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) | ||
3407 | return -EIO; | ||
3408 | } | ||
3409 | } | 4948 | } |
3410 | 4949 | ||
3411 | /* set a default rate so that the channel map is set up. */ | 4950 | /* set a default rate so that the channel map is set up. */ |
3412 | hdspm->channel_map = channel_map_madi_ss; | 4951 | hdspm_set_rate(hdspm, 48000, 1); |
3413 | hdspm_set_rate(hdspm, 44100, 1); | ||
3414 | 4952 | ||
3415 | return 0; | 4953 | return 0; |
3416 | } | 4954 | } |
3417 | 4955 | ||
3418 | 4956 | ||
3419 | /*------------------------------------------------------------ | 4957 | /*------------------------------------------------------------ |
3420 | interrupt | 4958 | interrupt |
3421 | ------------------------------------------------------------*/ | 4959 | ------------------------------------------------------------*/ |
3422 | 4960 | ||
3423 | static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | 4961 | static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) |
3424 | { | 4962 | { |
3425 | struct hdspm *hdspm = (struct hdspm *) dev_id; | 4963 | struct hdspm *hdspm = (struct hdspm *) dev_id; |
3426 | unsigned int status; | 4964 | unsigned int status; |
3427 | int audio; | 4965 | int i, audio, midi, schedule = 0; |
3428 | int midi0; | 4966 | /* cycles_t now; */ |
3429 | int midi1; | ||
3430 | unsigned int midi0status; | ||
3431 | unsigned int midi1status; | ||
3432 | int schedule = 0; | ||
3433 | 4967 | ||
3434 | status = hdspm_read(hdspm, HDSPM_statusRegister); | 4968 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
3435 | 4969 | ||
3436 | audio = status & HDSPM_audioIRQPending; | 4970 | audio = status & HDSPM_audioIRQPending; |
3437 | midi0 = status & HDSPM_midi0IRQPending; | 4971 | midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending | |
3438 | midi1 = status & HDSPM_midi1IRQPending; | 4972 | HDSPM_midi2IRQPending | HDSPM_midi3IRQPending); |
4973 | |||
4974 | /* now = get_cycles(); */ | ||
4975 | /** | ||
4976 | * LAT_2..LAT_0 period counter (win) counter (mac) | ||
4977 | * 6 4096 ~256053425 ~514672358 | ||
4978 | * 5 2048 ~128024983 ~257373821 | ||
4979 | * 4 1024 ~64023706 ~128718089 | ||
4980 | * 3 512 ~32005945 ~64385999 | ||
4981 | * 2 256 ~16003039 ~32260176 | ||
4982 | * 1 128 ~7998738 ~16194507 | ||
4983 | * 0 64 ~3998231 ~8191558 | ||
4984 | **/ | ||
4985 | /* | ||
4986 | snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n", | ||
4987 | now-hdspm->last_interrupt, status & 0xFFC0); | ||
4988 | hdspm->last_interrupt = now; | ||
4989 | */ | ||
3439 | 4990 | ||
3440 | if (!audio && !midi0 && !midi1) | 4991 | if (!audio && !midi) |
3441 | return IRQ_NONE; | 4992 | return IRQ_NONE; |
3442 | 4993 | ||
3443 | hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); | 4994 | hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); |
3444 | hdspm->irq_count++; | 4995 | hdspm->irq_count++; |
3445 | 4996 | ||
3446 | midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff; | ||
3447 | midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff; | ||
3448 | 4997 | ||
3449 | if (audio) { | 4998 | if (audio) { |
3450 | |||
3451 | if (hdspm->capture_substream) | 4999 | if (hdspm->capture_substream) |
3452 | snd_pcm_period_elapsed(hdspm->capture_substream); | 5000 | snd_pcm_period_elapsed(hdspm->capture_substream); |
3453 | 5001 | ||
@@ -3455,118 +5003,44 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | |||
3455 | snd_pcm_period_elapsed(hdspm->playback_substream); | 5003 | snd_pcm_period_elapsed(hdspm->playback_substream); |
3456 | } | 5004 | } |
3457 | 5005 | ||
3458 | if (midi0 && midi0status) { | 5006 | if (midi) { |
3459 | /* we disable interrupts for this input until processing | 5007 | i = 0; |
3460 | * is done | 5008 | while (i < hdspm->midiPorts) { |
3461 | */ | 5009 | if ((hdspm_read(hdspm, |
3462 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; | 5010 | hdspm->midi[i].statusIn) & 0xff) && |
3463 | hdspm_write(hdspm, HDSPM_controlRegister, | 5011 | (status & hdspm->midi[i].irq)) { |
3464 | hdspm->control_register); | 5012 | /* we disable interrupts for this input until |
3465 | hdspm->midi[0].pending = 1; | 5013 | * processing is done |
3466 | schedule = 1; | 5014 | */ |
3467 | } | 5015 | hdspm->control_register &= ~hdspm->midi[i].ie; |
3468 | if (midi1 && midi1status) { | 5016 | hdspm_write(hdspm, HDSPM_controlRegister, |
3469 | /* we disable interrupts for this input until processing | 5017 | hdspm->control_register); |
3470 | * is done | 5018 | hdspm->midi[i].pending = 1; |
3471 | */ | 5019 | schedule = 1; |
3472 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; | 5020 | } |
3473 | hdspm_write(hdspm, HDSPM_controlRegister, | 5021 | |
3474 | hdspm->control_register); | 5022 | i++; |
3475 | hdspm->midi[1].pending = 1; | 5023 | } |
3476 | schedule = 1; | 5024 | |
5025 | if (schedule) | ||
5026 | tasklet_hi_schedule(&hdspm->midi_tasklet); | ||
3477 | } | 5027 | } |
3478 | if (schedule) | 5028 | |
3479 | tasklet_schedule(&hdspm->midi_tasklet); | ||
3480 | return IRQ_HANDLED; | 5029 | return IRQ_HANDLED; |
3481 | } | 5030 | } |
3482 | 5031 | ||
3483 | /*------------------------------------------------------------ | 5032 | /*------------------------------------------------------------ |
3484 | pcm interface | 5033 | pcm interface |
3485 | ------------------------------------------------------------*/ | 5034 | ------------------------------------------------------------*/ |
3486 | 5035 | ||
3487 | 5036 | ||
3488 | static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream * | 5037 | static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream |
3489 | substream) | 5038 | *substream) |
3490 | { | 5039 | { |
3491 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | 5040 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); |
3492 | return hdspm_hw_pointer(hdspm); | 5041 | return hdspm_hw_pointer(hdspm); |
3493 | } | 5042 | } |
3494 | 5043 | ||
3495 | static char *hdspm_channel_buffer_location(struct hdspm * hdspm, | ||
3496 | int stream, int channel) | ||
3497 | { | ||
3498 | int mapped_channel; | ||
3499 | |||
3500 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) | ||
3501 | return NULL; | ||
3502 | |||
3503 | mapped_channel = hdspm->channel_map[channel]; | ||
3504 | if (mapped_channel < 0) | ||
3505 | return NULL; | ||
3506 | |||
3507 | if (stream == SNDRV_PCM_STREAM_CAPTURE) | ||
3508 | return hdspm->capture_buffer + | ||
3509 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
3510 | else | ||
3511 | return hdspm->playback_buffer + | ||
3512 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
3513 | } | ||
3514 | |||
3515 | |||
3516 | /* dont know why need it ??? */ | ||
3517 | static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream, | ||
3518 | int channel, snd_pcm_uframes_t pos, | ||
3519 | void __user *src, snd_pcm_uframes_t count) | ||
3520 | { | ||
3521 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | ||
3522 | char *channel_buf; | ||
3523 | |||
3524 | if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4)) | ||
3525 | return -EINVAL; | ||
3526 | |||
3527 | channel_buf = | ||
3528 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
3529 | channel); | ||
3530 | |||
3531 | if (snd_BUG_ON(!channel_buf)) | ||
3532 | return -EIO; | ||
3533 | |||
3534 | return copy_from_user(channel_buf + pos * 4, src, count * 4); | ||
3535 | } | ||
3536 | |||
3537 | static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream, | ||
3538 | int channel, snd_pcm_uframes_t pos, | ||
3539 | void __user *dst, snd_pcm_uframes_t count) | ||
3540 | { | ||
3541 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | ||
3542 | char *channel_buf; | ||
3543 | |||
3544 | if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4)) | ||
3545 | return -EINVAL; | ||
3546 | |||
3547 | channel_buf = | ||
3548 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
3549 | channel); | ||
3550 | if (snd_BUG_ON(!channel_buf)) | ||
3551 | return -EIO; | ||
3552 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); | ||
3553 | } | ||
3554 | |||
3555 | static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream, | ||
3556 | int channel, snd_pcm_uframes_t pos, | ||
3557 | snd_pcm_uframes_t count) | ||
3558 | { | ||
3559 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | ||
3560 | char *channel_buf; | ||
3561 | |||
3562 | channel_buf = | ||
3563 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
3564 | channel); | ||
3565 | if (snd_BUG_ON(!channel_buf)) | ||
3566 | return -EIO; | ||
3567 | memset(channel_buf + pos * 4, 0, count * 4); | ||
3568 | return 0; | ||
3569 | } | ||
3570 | 5044 | ||
3571 | static int snd_hdspm_reset(struct snd_pcm_substream *substream) | 5045 | static int snd_hdspm_reset(struct snd_pcm_substream *substream) |
3572 | { | 5046 | { |
@@ -3589,7 +5063,7 @@ static int snd_hdspm_reset(struct snd_pcm_substream *substream) | |||
3589 | snd_pcm_group_for_each_entry(s, substream) { | 5063 | snd_pcm_group_for_each_entry(s, substream) { |
3590 | if (s == other) { | 5064 | if (s == other) { |
3591 | oruntime->status->hw_ptr = | 5065 | oruntime->status->hw_ptr = |
3592 | runtime->status->hw_ptr; | 5066 | runtime->status->hw_ptr; |
3593 | break; | 5067 | break; |
3594 | } | 5068 | } |
3595 | } | 5069 | } |
@@ -3621,19 +5095,19 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3621 | /* The other stream is open, and not by the same | 5095 | /* The other stream is open, and not by the same |
3622 | task as this one. Make sure that the parameters | 5096 | task as this one. Make sure that the parameters |
3623 | that matter are the same. | 5097 | that matter are the same. |
3624 | */ | 5098 | */ |
3625 | 5099 | ||
3626 | if (params_rate(params) != hdspm->system_sample_rate) { | 5100 | if (params_rate(params) != hdspm->system_sample_rate) { |
3627 | spin_unlock_irq(&hdspm->lock); | 5101 | spin_unlock_irq(&hdspm->lock); |
3628 | _snd_pcm_hw_param_setempty(params, | 5102 | _snd_pcm_hw_param_setempty(params, |
3629 | SNDRV_PCM_HW_PARAM_RATE); | 5103 | SNDRV_PCM_HW_PARAM_RATE); |
3630 | return -EBUSY; | 5104 | return -EBUSY; |
3631 | } | 5105 | } |
3632 | 5106 | ||
3633 | if (params_period_size(params) != hdspm->period_bytes / 4) { | 5107 | if (params_period_size(params) != hdspm->period_bytes / 4) { |
3634 | spin_unlock_irq(&hdspm->lock); | 5108 | spin_unlock_irq(&hdspm->lock); |
3635 | _snd_pcm_hw_param_setempty(params, | 5109 | _snd_pcm_hw_param_setempty(params, |
3636 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 5110 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3637 | return -EBUSY; | 5111 | return -EBUSY; |
3638 | } | 5112 | } |
3639 | 5113 | ||
@@ -3646,18 +5120,20 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3646 | spin_lock_irq(&hdspm->lock); | 5120 | spin_lock_irq(&hdspm->lock); |
3647 | err = hdspm_set_rate(hdspm, params_rate(params), 0); | 5121 | err = hdspm_set_rate(hdspm, params_rate(params), 0); |
3648 | if (err < 0) { | 5122 | if (err < 0) { |
5123 | snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err); | ||
3649 | spin_unlock_irq(&hdspm->lock); | 5124 | spin_unlock_irq(&hdspm->lock); |
3650 | _snd_pcm_hw_param_setempty(params, | 5125 | _snd_pcm_hw_param_setempty(params, |
3651 | SNDRV_PCM_HW_PARAM_RATE); | 5126 | SNDRV_PCM_HW_PARAM_RATE); |
3652 | return err; | 5127 | return err; |
3653 | } | 5128 | } |
3654 | spin_unlock_irq(&hdspm->lock); | 5129 | spin_unlock_irq(&hdspm->lock); |
3655 | 5130 | ||
3656 | err = hdspm_set_interrupt_interval(hdspm, | 5131 | err = hdspm_set_interrupt_interval(hdspm, |
3657 | params_period_size(params)); | 5132 | params_period_size(params)); |
3658 | if (err < 0) { | 5133 | if (err < 0) { |
5134 | snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err); | ||
3659 | _snd_pcm_hw_param_setempty(params, | 5135 | _snd_pcm_hw_param_setempty(params, |
3660 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 5136 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3661 | return err; | 5137 | return err; |
3662 | } | 5138 | } |
3663 | 5139 | ||
@@ -3667,10 +5143,13 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3667 | /* malloc all buffer even if not enabled to get sure */ | 5143 | /* malloc all buffer even if not enabled to get sure */ |
3668 | /* Update for MADI rev 204: we need to allocate for all channels, | 5144 | /* Update for MADI rev 204: we need to allocate for all channels, |
3669 | * otherwise it doesn't work at 96kHz */ | 5145 | * otherwise it doesn't work at 96kHz */ |
5146 | |||
3670 | err = | 5147 | err = |
3671 | snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); | 5148 | snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); |
3672 | if (err < 0) | 5149 | if (err < 0) { |
5150 | snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err); | ||
3673 | return err; | 5151 | return err; |
5152 | } | ||
3674 | 5153 | ||
3675 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 5154 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3676 | 5155 | ||
@@ -3681,7 +5160,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3681 | snd_hdspm_enable_out(hdspm, i, 1); | 5160 | snd_hdspm_enable_out(hdspm, i, 1); |
3682 | 5161 | ||
3683 | hdspm->playback_buffer = | 5162 | hdspm->playback_buffer = |
3684 | (unsigned char *) substream->runtime->dma_area; | 5163 | (unsigned char *) substream->runtime->dma_area; |
3685 | snd_printdd("Allocated sample buffer for playback at %p\n", | 5164 | snd_printdd("Allocated sample buffer for playback at %p\n", |
3686 | hdspm->playback_buffer); | 5165 | hdspm->playback_buffer); |
3687 | } else { | 5166 | } else { |
@@ -3692,23 +5171,40 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3692 | snd_hdspm_enable_in(hdspm, i, 1); | 5171 | snd_hdspm_enable_in(hdspm, i, 1); |
3693 | 5172 | ||
3694 | hdspm->capture_buffer = | 5173 | hdspm->capture_buffer = |
3695 | (unsigned char *) substream->runtime->dma_area; | 5174 | (unsigned char *) substream->runtime->dma_area; |
3696 | snd_printdd("Allocated sample buffer for capture at %p\n", | 5175 | snd_printdd("Allocated sample buffer for capture at %p\n", |
3697 | hdspm->capture_buffer); | 5176 | hdspm->capture_buffer); |
3698 | } | 5177 | } |
5178 | |||
3699 | /* | 5179 | /* |
3700 | snd_printdd("Allocated sample buffer for %s at 0x%08X\n", | 5180 | snd_printdd("Allocated sample buffer for %s at 0x%08X\n", |
3701 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 5181 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
3702 | "playback" : "capture", | 5182 | "playback" : "capture", |
3703 | snd_pcm_sgbuf_get_addr(substream, 0)); | 5183 | snd_pcm_sgbuf_get_addr(substream, 0)); |
3704 | */ | 5184 | */ |
3705 | /* | 5185 | /* |
3706 | snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", | 5186 | snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", |
3707 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 5187 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
3708 | "playback" : "capture", | 5188 | "playback" : "capture", |
3709 | params_rate(params), params_channels(params), | 5189 | params_rate(params), params_channels(params), |
3710 | params_buffer_size(params)); | 5190 | params_buffer_size(params)); |
3711 | */ | 5191 | */ |
5192 | |||
5193 | |||
5194 | /* Switch to native float format if requested */ | ||
5195 | if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) { | ||
5196 | if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT)) | ||
5197 | snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n"); | ||
5198 | |||
5199 | hdspm->control_register |= HDSPe_FLOAT_FORMAT; | ||
5200 | } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) { | ||
5201 | if (hdspm->control_register & HDSPe_FLOAT_FORMAT) | ||
5202 | snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n"); | ||
5203 | |||
5204 | hdspm->control_register &= ~HDSPe_FLOAT_FORMAT; | ||
5205 | } | ||
5206 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
5207 | |||
3712 | return 0; | 5208 | return 0; |
3713 | } | 5209 | } |
3714 | 5210 | ||
@@ -3719,14 +5215,14 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) | |||
3719 | 5215 | ||
3720 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 5216 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3721 | 5217 | ||
3722 | /* params_channels(params) should be enough, | 5218 | /* params_channels(params) should be enough, |
3723 | but to get sure in case of error */ | 5219 | but to get sure in case of error */ |
3724 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | 5220 | for (i = 0; i < hdspm->max_channels_out; ++i) |
3725 | snd_hdspm_enable_out(hdspm, i, 0); | 5221 | snd_hdspm_enable_out(hdspm, i, 0); |
3726 | 5222 | ||
3727 | hdspm->playback_buffer = NULL; | 5223 | hdspm->playback_buffer = NULL; |
3728 | } else { | 5224 | } else { |
3729 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | 5225 | for (i = 0; i < hdspm->max_channels_in; ++i) |
3730 | snd_hdspm_enable_in(hdspm, i, 0); | 5226 | snd_hdspm_enable_in(hdspm, i, 0); |
3731 | 5227 | ||
3732 | hdspm->capture_buffer = NULL; | 5228 | hdspm->capture_buffer = NULL; |
@@ -3738,37 +5234,58 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) | |||
3738 | return 0; | 5234 | return 0; |
3739 | } | 5235 | } |
3740 | 5236 | ||
5237 | |||
3741 | static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, | 5238 | static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, |
3742 | struct snd_pcm_channel_info * info) | 5239 | struct snd_pcm_channel_info *info) |
3743 | { | 5240 | { |
3744 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | 5241 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); |
3745 | int mapped_channel; | ||
3746 | 5242 | ||
3747 | if (snd_BUG_ON(info->channel >= HDSPM_MAX_CHANNELS)) | 5243 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3748 | return -EINVAL; | 5244 | if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) { |
5245 | snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel); | ||
5246 | return -EINVAL; | ||
5247 | } | ||
3749 | 5248 | ||
3750 | mapped_channel = hdspm->channel_map[info->channel]; | 5249 | if (hdspm->channel_map_out[info->channel] < 0) { |
3751 | if (mapped_channel < 0) | 5250 | snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel); |
3752 | return -EINVAL; | 5251 | return -EINVAL; |
5252 | } | ||
5253 | |||
5254 | info->offset = hdspm->channel_map_out[info->channel] * | ||
5255 | HDSPM_CHANNEL_BUFFER_BYTES; | ||
5256 | } else { | ||
5257 | if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) { | ||
5258 | snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel); | ||
5259 | return -EINVAL; | ||
5260 | } | ||
5261 | |||
5262 | if (hdspm->channel_map_in[info->channel] < 0) { | ||
5263 | snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel); | ||
5264 | return -EINVAL; | ||
5265 | } | ||
5266 | |||
5267 | info->offset = hdspm->channel_map_in[info->channel] * | ||
5268 | HDSPM_CHANNEL_BUFFER_BYTES; | ||
5269 | } | ||
3753 | 5270 | ||
3754 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
3755 | info->first = 0; | 5271 | info->first = 0; |
3756 | info->step = 32; | 5272 | info->step = 32; |
3757 | return 0; | 5273 | return 0; |
3758 | } | 5274 | } |
3759 | 5275 | ||
5276 | |||
3760 | static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, | 5277 | static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, |
3761 | unsigned int cmd, void *arg) | 5278 | unsigned int cmd, void *arg) |
3762 | { | 5279 | { |
3763 | switch (cmd) { | 5280 | switch (cmd) { |
3764 | case SNDRV_PCM_IOCTL1_RESET: | 5281 | case SNDRV_PCM_IOCTL1_RESET: |
3765 | return snd_hdspm_reset(substream); | 5282 | return snd_hdspm_reset(substream); |
3766 | 5283 | ||
3767 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | 5284 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: |
3768 | { | 5285 | { |
3769 | struct snd_pcm_channel_info *info = arg; | 5286 | struct snd_pcm_channel_info *info = arg; |
3770 | return snd_hdspm_channel_info(substream, info); | 5287 | return snd_hdspm_channel_info(substream, info); |
3771 | } | 5288 | } |
3772 | default: | 5289 | default: |
3773 | break; | 5290 | break; |
3774 | } | 5291 | } |
@@ -3815,19 +5332,19 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
3815 | } | 5332 | } |
3816 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 5333 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
3817 | if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) | 5334 | if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) |
3818 | && substream->stream == | 5335 | && substream->stream == |
3819 | SNDRV_PCM_STREAM_CAPTURE) | 5336 | SNDRV_PCM_STREAM_CAPTURE) |
3820 | hdspm_silence_playback(hdspm); | 5337 | hdspm_silence_playback(hdspm); |
3821 | } else { | 5338 | } else { |
3822 | if (running && | 5339 | if (running && |
3823 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 5340 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
3824 | hdspm_silence_playback(hdspm); | 5341 | hdspm_silence_playback(hdspm); |
3825 | } | 5342 | } |
3826 | } else { | 5343 | } else { |
3827 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 5344 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
3828 | hdspm_silence_playback(hdspm); | 5345 | hdspm_silence_playback(hdspm); |
3829 | } | 5346 | } |
3830 | _ok: | 5347 | _ok: |
3831 | snd_pcm_trigger_done(substream, substream); | 5348 | snd_pcm_trigger_done(substream, substream); |
3832 | if (!hdspm->running && running) | 5349 | if (!hdspm->running && running) |
3833 | hdspm_start_audio(hdspm); | 5350 | hdspm_start_audio(hdspm); |
@@ -3844,8 +5361,18 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream) | |||
3844 | return 0; | 5361 | return 0; |
3845 | } | 5362 | } |
3846 | 5363 | ||
3847 | static unsigned int period_sizes[] = | 5364 | static unsigned int period_sizes_old[] = { |
3848 | { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; | 5365 | 64, 128, 256, 512, 1024, 2048, 4096 |
5366 | }; | ||
5367 | |||
5368 | static unsigned int period_sizes_new[] = { | ||
5369 | 32, 64, 128, 256, 512, 1024, 2048, 4096 | ||
5370 | }; | ||
5371 | |||
5372 | /* RayDAT and AIO always have a buffer of 16384 samples per channel */ | ||
5373 | static unsigned int raydat_aio_buffer_sizes[] = { | ||
5374 | 16384 | ||
5375 | }; | ||
3849 | 5376 | ||
3850 | static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { | 5377 | static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { |
3851 | .info = (SNDRV_PCM_INFO_MMAP | | 5378 | .info = (SNDRV_PCM_INFO_MMAP | |
@@ -3866,9 +5393,9 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { | |||
3866 | .buffer_bytes_max = | 5393 | .buffer_bytes_max = |
3867 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, | 5394 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, |
3868 | .period_bytes_min = (64 * 4), | 5395 | .period_bytes_min = (64 * 4), |
3869 | .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, | 5396 | .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS, |
3870 | .periods_min = 2, | 5397 | .periods_min = 2, |
3871 | .periods_max = 2, | 5398 | .periods_max = 512, |
3872 | .fifo_size = 0 | 5399 | .fifo_size = 0 |
3873 | }; | 5400 | }; |
3874 | 5401 | ||
@@ -3891,20 +5418,66 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { | |||
3891 | .buffer_bytes_max = | 5418 | .buffer_bytes_max = |
3892 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, | 5419 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, |
3893 | .period_bytes_min = (64 * 4), | 5420 | .period_bytes_min = (64 * 4), |
3894 | .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, | 5421 | .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS, |
3895 | .periods_min = 2, | 5422 | .periods_min = 2, |
3896 | .periods_max = 2, | 5423 | .periods_max = 512, |
3897 | .fifo_size = 0 | 5424 | .fifo_size = 0 |
3898 | }; | 5425 | }; |
3899 | 5426 | ||
3900 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { | 5427 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = { |
3901 | .count = ARRAY_SIZE(period_sizes), | 5428 | .count = ARRAY_SIZE(period_sizes_old), |
3902 | .list = period_sizes, | 5429 | .list = period_sizes_old, |
5430 | .mask = 0 | ||
5431 | }; | ||
5432 | |||
5433 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = { | ||
5434 | .count = ARRAY_SIZE(period_sizes_new), | ||
5435 | .list = period_sizes_new, | ||
3903 | .mask = 0 | 5436 | .mask = 0 |
3904 | }; | 5437 | }; |
3905 | 5438 | ||
5439 | static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = { | ||
5440 | .count = ARRAY_SIZE(raydat_aio_buffer_sizes), | ||
5441 | .list = raydat_aio_buffer_sizes, | ||
5442 | .mask = 0 | ||
5443 | }; | ||
5444 | |||
5445 | static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, | ||
5446 | struct snd_pcm_hw_rule *rule) | ||
5447 | { | ||
5448 | struct hdspm *hdspm = rule->private; | ||
5449 | struct snd_interval *c = | ||
5450 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
5451 | struct snd_interval *r = | ||
5452 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
5453 | |||
5454 | if (r->min > 96000 && r->max <= 192000) { | ||
5455 | struct snd_interval t = { | ||
5456 | .min = hdspm->qs_in_channels, | ||
5457 | .max = hdspm->qs_in_channels, | ||
5458 | .integer = 1, | ||
5459 | }; | ||
5460 | return snd_interval_refine(c, &t); | ||
5461 | } else if (r->min > 48000 && r->max <= 96000) { | ||
5462 | struct snd_interval t = { | ||
5463 | .min = hdspm->ds_in_channels, | ||
5464 | .max = hdspm->ds_in_channels, | ||
5465 | .integer = 1, | ||
5466 | }; | ||
5467 | return snd_interval_refine(c, &t); | ||
5468 | } else if (r->max < 64000) { | ||
5469 | struct snd_interval t = { | ||
5470 | .min = hdspm->ss_in_channels, | ||
5471 | .max = hdspm->ss_in_channels, | ||
5472 | .integer = 1, | ||
5473 | }; | ||
5474 | return snd_interval_refine(c, &t); | ||
5475 | } | ||
5476 | |||
5477 | return 0; | ||
5478 | } | ||
3906 | 5479 | ||
3907 | static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params, | 5480 | static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params, |
3908 | struct snd_pcm_hw_rule * rule) | 5481 | struct snd_pcm_hw_rule * rule) |
3909 | { | 5482 | { |
3910 | struct hdspm *hdspm = rule->private; | 5483 | struct hdspm *hdspm = rule->private; |
@@ -3913,25 +5486,33 @@ static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params, | |||
3913 | struct snd_interval *r = | 5486 | struct snd_interval *r = |
3914 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 5487 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
3915 | 5488 | ||
3916 | if (r->min > 48000 && r->max <= 96000) { | 5489 | if (r->min > 96000 && r->max <= 192000) { |
5490 | struct snd_interval t = { | ||
5491 | .min = hdspm->qs_out_channels, | ||
5492 | .max = hdspm->qs_out_channels, | ||
5493 | .integer = 1, | ||
5494 | }; | ||
5495 | return snd_interval_refine(c, &t); | ||
5496 | } else if (r->min > 48000 && r->max <= 96000) { | ||
3917 | struct snd_interval t = { | 5497 | struct snd_interval t = { |
3918 | .min = hdspm->ds_channels, | 5498 | .min = hdspm->ds_out_channels, |
3919 | .max = hdspm->ds_channels, | 5499 | .max = hdspm->ds_out_channels, |
3920 | .integer = 1, | 5500 | .integer = 1, |
3921 | }; | 5501 | }; |
3922 | return snd_interval_refine(c, &t); | 5502 | return snd_interval_refine(c, &t); |
3923 | } else if (r->max < 64000) { | 5503 | } else if (r->max < 64000) { |
3924 | struct snd_interval t = { | 5504 | struct snd_interval t = { |
3925 | .min = hdspm->ss_channels, | 5505 | .min = hdspm->ss_out_channels, |
3926 | .max = hdspm->ss_channels, | 5506 | .max = hdspm->ss_out_channels, |
3927 | .integer = 1, | 5507 | .integer = 1, |
3928 | }; | 5508 | }; |
3929 | return snd_interval_refine(c, &t); | 5509 | return snd_interval_refine(c, &t); |
5510 | } else { | ||
3930 | } | 5511 | } |
3931 | return 0; | 5512 | return 0; |
3932 | } | 5513 | } |
3933 | 5514 | ||
3934 | static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params, | 5515 | static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params, |
3935 | struct snd_pcm_hw_rule * rule) | 5516 | struct snd_pcm_hw_rule * rule) |
3936 | { | 5517 | { |
3937 | struct hdspm *hdspm = rule->private; | 5518 | struct hdspm *hdspm = rule->private; |
@@ -3940,42 +5521,92 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params, | |||
3940 | struct snd_interval *r = | 5521 | struct snd_interval *r = |
3941 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 5522 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
3942 | 5523 | ||
3943 | if (c->min >= hdspm->ss_channels) { | 5524 | if (c->min >= hdspm->ss_in_channels) { |
3944 | struct snd_interval t = { | 5525 | struct snd_interval t = { |
3945 | .min = 32000, | 5526 | .min = 32000, |
3946 | .max = 48000, | 5527 | .max = 48000, |
3947 | .integer = 1, | 5528 | .integer = 1, |
3948 | }; | 5529 | }; |
3949 | return snd_interval_refine(r, &t); | 5530 | return snd_interval_refine(r, &t); |
3950 | } else if (c->max <= hdspm->ds_channels) { | 5531 | } else if (c->max <= hdspm->qs_in_channels) { |
5532 | struct snd_interval t = { | ||
5533 | .min = 128000, | ||
5534 | .max = 192000, | ||
5535 | .integer = 1, | ||
5536 | }; | ||
5537 | return snd_interval_refine(r, &t); | ||
5538 | } else if (c->max <= hdspm->ds_in_channels) { | ||
3951 | struct snd_interval t = { | 5539 | struct snd_interval t = { |
3952 | .min = 64000, | 5540 | .min = 64000, |
3953 | .max = 96000, | 5541 | .max = 96000, |
3954 | .integer = 1, | 5542 | .integer = 1, |
3955 | }; | 5543 | }; |
5544 | return snd_interval_refine(r, &t); | ||
5545 | } | ||
5546 | |||
5547 | return 0; | ||
5548 | } | ||
5549 | static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params, | ||
5550 | struct snd_pcm_hw_rule *rule) | ||
5551 | { | ||
5552 | struct hdspm *hdspm = rule->private; | ||
5553 | struct snd_interval *c = | ||
5554 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
5555 | struct snd_interval *r = | ||
5556 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
3956 | 5557 | ||
5558 | if (c->min >= hdspm->ss_out_channels) { | ||
5559 | struct snd_interval t = { | ||
5560 | .min = 32000, | ||
5561 | .max = 48000, | ||
5562 | .integer = 1, | ||
5563 | }; | ||
5564 | return snd_interval_refine(r, &t); | ||
5565 | } else if (c->max <= hdspm->qs_out_channels) { | ||
5566 | struct snd_interval t = { | ||
5567 | .min = 128000, | ||
5568 | .max = 192000, | ||
5569 | .integer = 1, | ||
5570 | }; | ||
5571 | return snd_interval_refine(r, &t); | ||
5572 | } else if (c->max <= hdspm->ds_out_channels) { | ||
5573 | struct snd_interval t = { | ||
5574 | .min = 64000, | ||
5575 | .max = 96000, | ||
5576 | .integer = 1, | ||
5577 | }; | ||
3957 | return snd_interval_refine(r, &t); | 5578 | return snd_interval_refine(r, &t); |
3958 | } | 5579 | } |
5580 | |||
3959 | return 0; | 5581 | return 0; |
3960 | } | 5582 | } |
3961 | 5583 | ||
3962 | static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params, | 5584 | static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params, |
3963 | struct snd_pcm_hw_rule *rule) | 5585 | struct snd_pcm_hw_rule *rule) |
3964 | { | 5586 | { |
3965 | unsigned int list[3]; | 5587 | unsigned int list[3]; |
3966 | struct hdspm *hdspm = rule->private; | 5588 | struct hdspm *hdspm = rule->private; |
3967 | struct snd_interval *c = hw_param_interval(params, | 5589 | struct snd_interval *c = hw_param_interval(params, |
3968 | SNDRV_PCM_HW_PARAM_CHANNELS); | 5590 | SNDRV_PCM_HW_PARAM_CHANNELS); |
3969 | if (hdspm->is_aes32) { | 5591 | |
3970 | list[0] = hdspm->qs_channels; | 5592 | list[0] = hdspm->qs_in_channels; |
3971 | list[1] = hdspm->ds_channels; | 5593 | list[1] = hdspm->ds_in_channels; |
3972 | list[2] = hdspm->ss_channels; | 5594 | list[2] = hdspm->ss_in_channels; |
3973 | return snd_interval_list(c, 3, list, 0); | 5595 | return snd_interval_list(c, 3, list, 0); |
3974 | } else { | 5596 | } |
3975 | list[0] = hdspm->ds_channels; | 5597 | |
3976 | list[1] = hdspm->ss_channels; | 5598 | static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params, |
3977 | return snd_interval_list(c, 2, list, 0); | 5599 | struct snd_pcm_hw_rule *rule) |
3978 | } | 5600 | { |
5601 | unsigned int list[3]; | ||
5602 | struct hdspm *hdspm = rule->private; | ||
5603 | struct snd_interval *c = hw_param_interval(params, | ||
5604 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
5605 | |||
5606 | list[0] = hdspm->qs_out_channels; | ||
5607 | list[1] = hdspm->ds_out_channels; | ||
5608 | list[2] = hdspm->ss_out_channels; | ||
5609 | return snd_interval_list(c, 3, list, 0); | ||
3979 | } | 5610 | } |
3980 | 5611 | ||
3981 | 5612 | ||
@@ -3999,6 +5630,7 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) | |||
3999 | 5630 | ||
4000 | snd_pcm_set_sync(substream); | 5631 | snd_pcm_set_sync(substream); |
4001 | 5632 | ||
5633 | |||
4002 | runtime->hw = snd_hdspm_playback_subinfo; | 5634 | runtime->hw = snd_hdspm_playback_subinfo; |
4003 | 5635 | ||
4004 | if (hdspm->capture_substream == NULL) | 5636 | if (hdspm->capture_substream == NULL) |
@@ -4011,24 +5643,38 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) | |||
4011 | 5643 | ||
4012 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 5644 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
4013 | 5645 | ||
4014 | snd_pcm_hw_constraint_list(runtime, 0, | 5646 | switch (hdspm->io_type) { |
4015 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 5647 | case AIO: |
4016 | &hw_constraints_period_sizes); | 5648 | case RayDAT: |
5649 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5650 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5651 | &hw_constraints_period_sizes_new); | ||
5652 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5653 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
5654 | &hw_constraints_raydat_io_buffer); | ||
4017 | 5655 | ||
4018 | if (hdspm->is_aes32) { | 5656 | break; |
5657 | |||
5658 | default: | ||
5659 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5660 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5661 | &hw_constraints_period_sizes_old); | ||
5662 | } | ||
5663 | |||
5664 | if (AES32 == hdspm->io_type) { | ||
4019 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5665 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4020 | &hdspm_hw_constraints_aes32_sample_rates); | 5666 | &hdspm_hw_constraints_aes32_sample_rates); |
4021 | } else { | 5667 | } else { |
4022 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 5668 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4023 | snd_hdspm_hw_rule_channels, hdspm, | 5669 | snd_hdspm_hw_rule_out_channels, hdspm, |
4024 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 5670 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
4025 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 5671 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4026 | snd_hdspm_hw_rule_channels_rate, hdspm, | 5672 | snd_hdspm_hw_rule_out_channels_rate, hdspm, |
4027 | SNDRV_PCM_HW_PARAM_RATE, -1); | 5673 | SNDRV_PCM_HW_PARAM_RATE, -1); |
4028 | 5674 | ||
4029 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5675 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4030 | snd_hdspm_hw_rule_rate_channels, hdspm, | 5676 | snd_hdspm_hw_rule_rate_out_channels, hdspm, |
4031 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 5677 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
4032 | } | 5678 | } |
4033 | return 0; | 5679 | return 0; |
4034 | } | 5680 | } |
@@ -4066,22 +5712,36 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) | |||
4066 | spin_unlock_irq(&hdspm->lock); | 5712 | spin_unlock_irq(&hdspm->lock); |
4067 | 5713 | ||
4068 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 5714 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
4069 | snd_pcm_hw_constraint_list(runtime, 0, | 5715 | switch (hdspm->io_type) { |
4070 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 5716 | case AIO: |
4071 | &hw_constraints_period_sizes); | 5717 | case RayDAT: |
4072 | if (hdspm->is_aes32) { | 5718 | snd_pcm_hw_constraint_list(runtime, 0, |
5719 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5720 | &hw_constraints_period_sizes_new); | ||
5721 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5722 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
5723 | &hw_constraints_raydat_io_buffer); | ||
5724 | break; | ||
5725 | |||
5726 | default: | ||
5727 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5728 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5729 | &hw_constraints_period_sizes_old); | ||
5730 | } | ||
5731 | |||
5732 | if (AES32 == hdspm->io_type) { | ||
4073 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5733 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4074 | &hdspm_hw_constraints_aes32_sample_rates); | 5734 | &hdspm_hw_constraints_aes32_sample_rates); |
4075 | } else { | 5735 | } else { |
4076 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 5736 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4077 | snd_hdspm_hw_rule_channels, hdspm, | 5737 | snd_hdspm_hw_rule_in_channels, hdspm, |
4078 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 5738 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
4079 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 5739 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4080 | snd_hdspm_hw_rule_channels_rate, hdspm, | 5740 | snd_hdspm_hw_rule_in_channels_rate, hdspm, |
4081 | SNDRV_PCM_HW_PARAM_RATE, -1); | 5741 | SNDRV_PCM_HW_PARAM_RATE, -1); |
4082 | 5742 | ||
4083 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5743 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4084 | snd_hdspm_hw_rule_rate_channels, hdspm, | 5744 | snd_hdspm_hw_rule_rate_in_channels, hdspm, |
4085 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 5745 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
4086 | } | 5746 | } |
4087 | return 0; | 5747 | return 0; |
@@ -4100,41 +5760,136 @@ static int snd_hdspm_capture_release(struct snd_pcm_substream *substream) | |||
4100 | return 0; | 5760 | return 0; |
4101 | } | 5761 | } |
4102 | 5762 | ||
4103 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | 5763 | static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) |
4104 | unsigned int cmd, unsigned long arg) | 5764 | { |
5765 | /* we have nothing to initialize but the call is required */ | ||
5766 | return 0; | ||
5767 | } | ||
5768 | |||
5769 | static inline int copy_u32_le(void __user *dest, void __iomem *src) | ||
5770 | { | ||
5771 | u32 val = readl(src); | ||
5772 | return copy_to_user(dest, &val, 4); | ||
5773 | } | ||
5774 | |||
5775 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, | ||
5776 | unsigned int cmd, unsigned long __user arg) | ||
4105 | { | 5777 | { |
5778 | void __user *argp = (void __user *)arg; | ||
4106 | struct hdspm *hdspm = hw->private_data; | 5779 | struct hdspm *hdspm = hw->private_data; |
4107 | struct hdspm_mixer_ioctl mixer; | 5780 | struct hdspm_mixer_ioctl mixer; |
4108 | struct hdspm_config_info info; | 5781 | struct hdspm_config info; |
5782 | struct hdspm_status status; | ||
4109 | struct hdspm_version hdspm_version; | 5783 | struct hdspm_version hdspm_version; |
4110 | struct hdspm_peak_rms_ioctl rms; | 5784 | struct hdspm_peak_rms levels; |
5785 | struct hdspm_ltc ltc; | ||
5786 | unsigned int statusregister; | ||
5787 | long unsigned int s; | ||
5788 | int i = 0; | ||
4111 | 5789 | ||
4112 | switch (cmd) { | 5790 | switch (cmd) { |
4113 | 5791 | ||
4114 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: | 5792 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: |
4115 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) | 5793 | for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { |
5794 | levels.input_peaks[i] = | ||
5795 | readl(hdspm->iobase + | ||
5796 | HDSPM_MADI_INPUT_PEAK + i*4); | ||
5797 | levels.playback_peaks[i] = | ||
5798 | readl(hdspm->iobase + | ||
5799 | HDSPM_MADI_PLAYBACK_PEAK + i*4); | ||
5800 | levels.output_peaks[i] = | ||
5801 | readl(hdspm->iobase + | ||
5802 | HDSPM_MADI_OUTPUT_PEAK + i*4); | ||
5803 | |||
5804 | levels.input_rms[i] = | ||
5805 | ((uint64_t) readl(hdspm->iobase + | ||
5806 | HDSPM_MADI_INPUT_RMS_H + i*4) << 32) | | ||
5807 | (uint64_t) readl(hdspm->iobase + | ||
5808 | HDSPM_MADI_INPUT_RMS_L + i*4); | ||
5809 | levels.playback_rms[i] = | ||
5810 | ((uint64_t)readl(hdspm->iobase + | ||
5811 | HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) | | ||
5812 | (uint64_t)readl(hdspm->iobase + | ||
5813 | HDSPM_MADI_PLAYBACK_RMS_L + i*4); | ||
5814 | levels.output_rms[i] = | ||
5815 | ((uint64_t)readl(hdspm->iobase + | ||
5816 | HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) | | ||
5817 | (uint64_t)readl(hdspm->iobase + | ||
5818 | HDSPM_MADI_OUTPUT_RMS_L + i*4); | ||
5819 | } | ||
5820 | |||
5821 | if (hdspm->system_sample_rate > 96000) { | ||
5822 | levels.speed = qs; | ||
5823 | } else if (hdspm->system_sample_rate > 48000) { | ||
5824 | levels.speed = ds; | ||
5825 | } else { | ||
5826 | levels.speed = ss; | ||
5827 | } | ||
5828 | levels.status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
5829 | |||
5830 | s = copy_to_user(argp, &levels, sizeof(struct hdspm_peak_rms)); | ||
5831 | if (0 != s) { | ||
5832 | /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu | ||
5833 | [Levels]\n", sizeof(struct hdspm_peak_rms), s); | ||
5834 | */ | ||
4116 | return -EFAULT; | 5835 | return -EFAULT; |
4117 | /* maybe there is a chance to memorymap in future | 5836 | } |
4118 | * so dont touch just copy | 5837 | break; |
4119 | */ | 5838 | |
4120 | if(copy_to_user_fromio((void __user *)rms.peak, | 5839 | case SNDRV_HDSPM_IOCTL_GET_LTC: |
4121 | hdspm->iobase+HDSPM_MADI_peakrmsbase, | 5840 | ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO); |
4122 | sizeof(struct hdspm_peak_rms)) != 0 ) | 5841 | i = hdspm_read(hdspm, HDSPM_RD_TCO + 4); |
5842 | if (i & HDSPM_TCO1_LTC_Input_valid) { | ||
5843 | switch (i & (HDSPM_TCO1_LTC_Format_LSB | | ||
5844 | HDSPM_TCO1_LTC_Format_MSB)) { | ||
5845 | case 0: | ||
5846 | ltc.format = fps_24; | ||
5847 | break; | ||
5848 | case HDSPM_TCO1_LTC_Format_LSB: | ||
5849 | ltc.format = fps_25; | ||
5850 | break; | ||
5851 | case HDSPM_TCO1_LTC_Format_MSB: | ||
5852 | ltc.format = fps_2997; | ||
5853 | break; | ||
5854 | default: | ||
5855 | ltc.format = 30; | ||
5856 | break; | ||
5857 | } | ||
5858 | if (i & HDSPM_TCO1_set_drop_frame_flag) { | ||
5859 | ltc.frame = drop_frame; | ||
5860 | } else { | ||
5861 | ltc.frame = full_frame; | ||
5862 | } | ||
5863 | } else { | ||
5864 | ltc.format = format_invalid; | ||
5865 | ltc.frame = frame_invalid; | ||
5866 | } | ||
5867 | if (i & HDSPM_TCO1_Video_Input_Format_NTSC) { | ||
5868 | ltc.input_format = ntsc; | ||
5869 | } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) { | ||
5870 | ltc.input_format = pal; | ||
5871 | } else { | ||
5872 | ltc.input_format = no_video; | ||
5873 | } | ||
5874 | |||
5875 | s = copy_to_user(argp, <c, sizeof(struct hdspm_ltc)); | ||
5876 | if (0 != s) { | ||
5877 | /* | ||
5878 | snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */ | ||
4123 | return -EFAULT; | 5879 | return -EFAULT; |
5880 | } | ||
4124 | 5881 | ||
4125 | break; | 5882 | break; |
4126 | |||
4127 | 5883 | ||
4128 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: | 5884 | case SNDRV_HDSPM_IOCTL_GET_CONFIG: |
4129 | 5885 | ||
4130 | memset(&info, 0, sizeof(info)); | ||
4131 | spin_lock_irq(&hdspm->lock); | 5886 | spin_lock_irq(&hdspm->lock); |
4132 | info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); | 5887 | info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); |
4133 | info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); | 5888 | info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); |
4134 | 5889 | ||
4135 | info.system_sample_rate = hdspm->system_sample_rate; | 5890 | info.system_sample_rate = hdspm->system_sample_rate; |
4136 | info.autosync_sample_rate = | 5891 | info.autosync_sample_rate = |
4137 | hdspm_external_sample_rate(hdspm); | 5892 | hdspm_external_sample_rate(hdspm); |
4138 | info.system_clock_mode = hdspm_system_clock_mode(hdspm); | 5893 | info.system_clock_mode = hdspm_system_clock_mode(hdspm); |
4139 | info.clock_source = hdspm_clock_source(hdspm); | 5894 | info.clock_source = hdspm_clock_source(hdspm); |
4140 | info.autosync_ref = hdspm_autosync_ref(hdspm); | 5895 | info.autosync_ref = hdspm_autosync_ref(hdspm); |
@@ -4145,10 +5900,58 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4145 | return -EFAULT; | 5900 | return -EFAULT; |
4146 | break; | 5901 | break; |
4147 | 5902 | ||
5903 | case SNDRV_HDSPM_IOCTL_GET_STATUS: | ||
5904 | status.card_type = hdspm->io_type; | ||
5905 | |||
5906 | status.autosync_source = hdspm_autosync_ref(hdspm); | ||
5907 | |||
5908 | status.card_clock = 110069313433624ULL; | ||
5909 | status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
5910 | |||
5911 | switch (hdspm->io_type) { | ||
5912 | case MADI: | ||
5913 | case MADIface: | ||
5914 | status.card_specific.madi.sync_wc = | ||
5915 | hdspm_wc_sync_check(hdspm); | ||
5916 | status.card_specific.madi.sync_madi = | ||
5917 | hdspm_madi_sync_check(hdspm); | ||
5918 | status.card_specific.madi.sync_tco = | ||
5919 | hdspm_tco_sync_check(hdspm); | ||
5920 | status.card_specific.madi.sync_in = | ||
5921 | hdspm_sync_in_sync_check(hdspm); | ||
5922 | |||
5923 | statusregister = | ||
5924 | hdspm_read(hdspm, HDSPM_statusRegister); | ||
5925 | status.card_specific.madi.madi_input = | ||
5926 | (statusregister & HDSPM_AB_int) ? 1 : 0; | ||
5927 | status.card_specific.madi.channel_format = | ||
5928 | (statusregister & HDSPM_TX_64ch) ? 1 : 0; | ||
5929 | /* TODO: Mac driver sets it when f_s>48kHz */ | ||
5930 | status.card_specific.madi.frame_format = 0; | ||
5931 | |||
5932 | default: | ||
5933 | break; | ||
5934 | } | ||
5935 | |||
5936 | if (copy_to_user((void __user *) arg, &status, sizeof(status))) | ||
5937 | return -EFAULT; | ||
5938 | |||
5939 | |||
5940 | break; | ||
5941 | |||
4148 | case SNDRV_HDSPM_IOCTL_GET_VERSION: | 5942 | case SNDRV_HDSPM_IOCTL_GET_VERSION: |
5943 | hdspm_version.card_type = hdspm->io_type; | ||
5944 | strncpy(hdspm_version.cardname, hdspm->card_name, | ||
5945 | sizeof(hdspm_version.cardname)); | ||
5946 | hdspm_version.serial = (hdspm_read(hdspm, | ||
5947 | HDSPM_midiStatusIn0)>>8) & 0xFFFFFF; | ||
4149 | hdspm_version.firmware_rev = hdspm->firmware_rev; | 5948 | hdspm_version.firmware_rev = hdspm->firmware_rev; |
5949 | hdspm_version.addons = 0; | ||
5950 | if (hdspm->tco) | ||
5951 | hdspm_version.addons |= HDSPM_ADDON_TCO; | ||
5952 | |||
4150 | if (copy_to_user((void __user *) arg, &hdspm_version, | 5953 | if (copy_to_user((void __user *) arg, &hdspm_version, |
4151 | sizeof(hdspm_version))) | 5954 | sizeof(hdspm_version))) |
4152 | return -EFAULT; | 5955 | return -EFAULT; |
4153 | break; | 5956 | break; |
4154 | 5957 | ||
@@ -4156,7 +5959,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4156 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) | 5959 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) |
4157 | return -EFAULT; | 5960 | return -EFAULT; |
4158 | if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, | 5961 | if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, |
4159 | sizeof(struct hdspm_mixer))) | 5962 | sizeof(struct hdspm_mixer))) |
4160 | return -EFAULT; | 5963 | return -EFAULT; |
4161 | break; | 5964 | break; |
4162 | 5965 | ||
@@ -4175,8 +5978,6 @@ static struct snd_pcm_ops snd_hdspm_playback_ops = { | |||
4175 | .prepare = snd_hdspm_prepare, | 5978 | .prepare = snd_hdspm_prepare, |
4176 | .trigger = snd_hdspm_trigger, | 5979 | .trigger = snd_hdspm_trigger, |
4177 | .pointer = snd_hdspm_hw_pointer, | 5980 | .pointer = snd_hdspm_hw_pointer, |
4178 | .copy = snd_hdspm_playback_copy, | ||
4179 | .silence = snd_hdspm_hw_silence, | ||
4180 | .page = snd_pcm_sgbuf_ops_page, | 5981 | .page = snd_pcm_sgbuf_ops_page, |
4181 | }; | 5982 | }; |
4182 | 5983 | ||
@@ -4189,7 +5990,6 @@ static struct snd_pcm_ops snd_hdspm_capture_ops = { | |||
4189 | .prepare = snd_hdspm_prepare, | 5990 | .prepare = snd_hdspm_prepare, |
4190 | .trigger = snd_hdspm_trigger, | 5991 | .trigger = snd_hdspm_trigger, |
4191 | .pointer = snd_hdspm_hw_pointer, | 5992 | .pointer = snd_hdspm_hw_pointer, |
4192 | .copy = snd_hdspm_capture_copy, | ||
4193 | .page = snd_pcm_sgbuf_ops_page, | 5993 | .page = snd_pcm_sgbuf_ops_page, |
4194 | }; | 5994 | }; |
4195 | 5995 | ||
@@ -4207,16 +6007,18 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, | |||
4207 | hw->private_data = hdspm; | 6007 | hw->private_data = hdspm; |
4208 | strcpy(hw->name, "HDSPM hwdep interface"); | 6008 | strcpy(hw->name, "HDSPM hwdep interface"); |
4209 | 6009 | ||
6010 | hw->ops.open = snd_hdspm_hwdep_dummy_op; | ||
4210 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; | 6011 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; |
6012 | hw->ops.release = snd_hdspm_hwdep_dummy_op; | ||
4211 | 6013 | ||
4212 | return 0; | 6014 | return 0; |
4213 | } | 6015 | } |
4214 | 6016 | ||
4215 | 6017 | ||
4216 | /*------------------------------------------------------------ | 6018 | /*------------------------------------------------------------ |
4217 | memory interface | 6019 | memory interface |
4218 | ------------------------------------------------------------*/ | 6020 | ------------------------------------------------------------*/ |
4219 | static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | 6021 | static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm) |
4220 | { | 6022 | { |
4221 | int err; | 6023 | int err; |
4222 | struct snd_pcm *pcm; | 6024 | struct snd_pcm *pcm; |
@@ -4228,7 +6030,7 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
4228 | 6030 | ||
4229 | err = | 6031 | err = |
4230 | snd_pcm_lib_preallocate_pages_for_all(pcm, | 6032 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
4231 | SNDRV_DMA_TYPE_DEV_SG, | 6033 | SNDRV_DMA_TYPE_DEV_SG, |
4232 | snd_dma_pci_data(hdspm->pci), | 6034 | snd_dma_pci_data(hdspm->pci), |
4233 | wanted, | 6035 | wanted, |
4234 | wanted); | 6036 | wanted); |
@@ -4242,19 +6044,23 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
4242 | return 0; | 6044 | return 0; |
4243 | } | 6045 | } |
4244 | 6046 | ||
4245 | static void hdspm_set_sgbuf(struct hdspm * hdspm, | 6047 | |
6048 | static void hdspm_set_sgbuf(struct hdspm *hdspm, | ||
4246 | struct snd_pcm_substream *substream, | 6049 | struct snd_pcm_substream *substream, |
4247 | unsigned int reg, int channels) | 6050 | unsigned int reg, int channels) |
4248 | { | 6051 | { |
4249 | int i; | 6052 | int i; |
6053 | |||
6054 | /* continuous memory segment */ | ||
4250 | for (i = 0; i < (channels * 16); i++) | 6055 | for (i = 0; i < (channels * 16); i++) |
4251 | hdspm_write(hdspm, reg + 4 * i, | 6056 | hdspm_write(hdspm, reg + 4 * i, |
4252 | snd_pcm_sgbuf_get_addr(substream, 4096 * i)); | 6057 | snd_pcm_sgbuf_get_addr(substream, 4096 * i)); |
4253 | } | 6058 | } |
4254 | 6059 | ||
6060 | |||
4255 | /* ------------- ALSA Devices ---------------------------- */ | 6061 | /* ------------- ALSA Devices ---------------------------- */ |
4256 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | 6062 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, |
4257 | struct hdspm * hdspm) | 6063 | struct hdspm *hdspm) |
4258 | { | 6064 | { |
4259 | struct snd_pcm *pcm; | 6065 | struct snd_pcm *pcm; |
4260 | int err; | 6066 | int err; |
@@ -4290,20 +6096,21 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm) | |||
4290 | static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | 6096 | static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, |
4291 | struct hdspm * hdspm) | 6097 | struct hdspm * hdspm) |
4292 | { | 6098 | { |
4293 | int err; | 6099 | int err, i; |
4294 | 6100 | ||
4295 | snd_printdd("Create card...\n"); | 6101 | snd_printdd("Create card...\n"); |
4296 | err = snd_hdspm_create_pcm(card, hdspm); | 6102 | err = snd_hdspm_create_pcm(card, hdspm); |
4297 | if (err < 0) | 6103 | if (err < 0) |
4298 | return err; | 6104 | return err; |
4299 | 6105 | ||
4300 | err = snd_hdspm_create_midi(card, hdspm, 0); | 6106 | i = 0; |
4301 | if (err < 0) | 6107 | while (i < hdspm->midiPorts) { |
4302 | return err; | 6108 | err = snd_hdspm_create_midi(card, hdspm, i); |
4303 | 6109 | if (err < 0) { | |
4304 | err = snd_hdspm_create_midi(card, hdspm, 1); | 6110 | return err; |
4305 | if (err < 0) | 6111 | } |
4306 | return err; | 6112 | i++; |
6113 | } | ||
4307 | 6114 | ||
4308 | err = snd_hdspm_create_controls(card, hdspm); | 6115 | err = snd_hdspm_create_controls(card, hdspm); |
4309 | if (err < 0) | 6116 | if (err < 0) |
@@ -4346,37 +6153,49 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4346 | } | 6153 | } |
4347 | 6154 | ||
4348 | static int __devinit snd_hdspm_create(struct snd_card *card, | 6155 | static int __devinit snd_hdspm_create(struct snd_card *card, |
4349 | struct hdspm *hdspm, | 6156 | struct hdspm *hdspm) { |
4350 | int precise_ptr, int enable_monitor) | 6157 | |
4351 | { | ||
4352 | struct pci_dev *pci = hdspm->pci; | 6158 | struct pci_dev *pci = hdspm->pci; |
4353 | int err; | 6159 | int err; |
4354 | unsigned long io_extent; | 6160 | unsigned long io_extent; |
4355 | 6161 | ||
4356 | hdspm->irq = -1; | 6162 | hdspm->irq = -1; |
4357 | |||
4358 | spin_lock_init(&hdspm->midi[0].lock); | ||
4359 | spin_lock_init(&hdspm->midi[1].lock); | ||
4360 | |||
4361 | hdspm->card = card; | 6163 | hdspm->card = card; |
4362 | 6164 | ||
4363 | spin_lock_init(&hdspm->lock); | 6165 | spin_lock_init(&hdspm->lock); |
4364 | 6166 | ||
4365 | tasklet_init(&hdspm->midi_tasklet, | ||
4366 | hdspm_midi_tasklet, (unsigned long) hdspm); | ||
4367 | |||
4368 | pci_read_config_word(hdspm->pci, | 6167 | pci_read_config_word(hdspm->pci, |
4369 | PCI_CLASS_REVISION, &hdspm->firmware_rev); | 6168 | PCI_CLASS_REVISION, &hdspm->firmware_rev); |
4370 | |||
4371 | hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION); | ||
4372 | 6169 | ||
4373 | strcpy(card->mixername, "Xilinx FPGA"); | 6170 | strcpy(card->mixername, "Xilinx FPGA"); |
4374 | if (hdspm->is_aes32) { | 6171 | strcpy(card->driver, "HDSPM"); |
4375 | strcpy(card->driver, "HDSPAES32"); | 6172 | |
4376 | hdspm->card_name = "RME HDSPM AES32"; | 6173 | switch (hdspm->firmware_rev) { |
4377 | } else { | 6174 | case HDSPM_MADI_REV: |
4378 | strcpy(card->driver, "HDSPM"); | 6175 | hdspm->io_type = MADI; |
4379 | hdspm->card_name = "RME HDSPM MADI"; | 6176 | hdspm->card_name = "RME MADI"; |
6177 | hdspm->midiPorts = 3; | ||
6178 | break; | ||
6179 | case HDSPM_RAYDAT_REV: | ||
6180 | hdspm->io_type = RayDAT; | ||
6181 | hdspm->card_name = "RME RayDAT"; | ||
6182 | hdspm->midiPorts = 2; | ||
6183 | break; | ||
6184 | case HDSPM_AIO_REV: | ||
6185 | hdspm->io_type = AIO; | ||
6186 | hdspm->card_name = "RME AIO"; | ||
6187 | hdspm->midiPorts = 1; | ||
6188 | break; | ||
6189 | case HDSPM_MADIFACE_REV: | ||
6190 | hdspm->io_type = MADIface; | ||
6191 | hdspm->card_name = "RME MADIface"; | ||
6192 | hdspm->midiPorts = 1; | ||
6193 | break; | ||
6194 | case HDSPM_AES_REV: | ||
6195 | hdspm->io_type = AES32; | ||
6196 | hdspm->card_name = "RME AES32"; | ||
6197 | hdspm->midiPorts = 2; | ||
6198 | break; | ||
4380 | } | 6199 | } |
4381 | 6200 | ||
4382 | err = pci_enable_device(pci); | 6201 | err = pci_enable_device(pci); |
@@ -4393,22 +6212,21 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
4393 | io_extent = pci_resource_len(pci, 0); | 6212 | io_extent = pci_resource_len(pci, 0); |
4394 | 6213 | ||
4395 | snd_printdd("grabbed memory region 0x%lx-0x%lx\n", | 6214 | snd_printdd("grabbed memory region 0x%lx-0x%lx\n", |
4396 | hdspm->port, hdspm->port + io_extent - 1); | 6215 | hdspm->port, hdspm->port + io_extent - 1); |
4397 | |||
4398 | 6216 | ||
4399 | hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); | 6217 | hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); |
4400 | if (!hdspm->iobase) { | 6218 | if (!hdspm->iobase) { |
4401 | snd_printk(KERN_ERR "HDSPM: " | 6219 | snd_printk(KERN_ERR "HDSPM: " |
4402 | "unable to remap region 0x%lx-0x%lx\n", | 6220 | "unable to remap region 0x%lx-0x%lx\n", |
4403 | hdspm->port, hdspm->port + io_extent - 1); | 6221 | hdspm->port, hdspm->port + io_extent - 1); |
4404 | return -EBUSY; | 6222 | return -EBUSY; |
4405 | } | 6223 | } |
4406 | snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", | 6224 | snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", |
4407 | (unsigned long)hdspm->iobase, hdspm->port, | 6225 | (unsigned long)hdspm->iobase, hdspm->port, |
4408 | hdspm->port + io_extent - 1); | 6226 | hdspm->port + io_extent - 1); |
4409 | 6227 | ||
4410 | if (request_irq(pci->irq, snd_hdspm_interrupt, | 6228 | if (request_irq(pci->irq, snd_hdspm_interrupt, |
4411 | IRQF_SHARED, "hdspm", hdspm)) { | 6229 | IRQF_SHARED, "hdspm", hdspm)) { |
4412 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); | 6230 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); |
4413 | return -EBUSY; | 6231 | return -EBUSY; |
4414 | } | 6232 | } |
@@ -4416,23 +6234,195 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
4416 | snd_printdd("use IRQ %d\n", pci->irq); | 6234 | snd_printdd("use IRQ %d\n", pci->irq); |
4417 | 6235 | ||
4418 | hdspm->irq = pci->irq; | 6236 | hdspm->irq = pci->irq; |
4419 | hdspm->precise_ptr = precise_ptr; | ||
4420 | |||
4421 | hdspm->monitor_outs = enable_monitor; | ||
4422 | 6237 | ||
4423 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", | 6238 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", |
4424 | sizeof(struct hdspm_mixer)); | 6239 | sizeof(struct hdspm_mixer)); |
4425 | hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); | 6240 | hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); |
4426 | if (!hdspm->mixer) { | 6241 | if (!hdspm->mixer) { |
4427 | snd_printk(KERN_ERR "HDSPM: " | 6242 | snd_printk(KERN_ERR "HDSPM: " |
4428 | "unable to kmalloc Mixer memory of %d Bytes\n", | 6243 | "unable to kmalloc Mixer memory of %d Bytes\n", |
4429 | (int)sizeof(struct hdspm_mixer)); | 6244 | (int)sizeof(struct hdspm_mixer)); |
4430 | return err; | 6245 | return err; |
4431 | } | 6246 | } |
4432 | 6247 | ||
4433 | hdspm->ss_channels = MADI_SS_CHANNELS; | 6248 | hdspm->port_names_in = NULL; |
4434 | hdspm->ds_channels = MADI_DS_CHANNELS; | 6249 | hdspm->port_names_out = NULL; |
4435 | hdspm->qs_channels = MADI_QS_CHANNELS; | 6250 | |
6251 | switch (hdspm->io_type) { | ||
6252 | case AES32: | ||
6253 | break; | ||
6254 | |||
6255 | case MADI: | ||
6256 | case MADIface: | ||
6257 | hdspm->ss_in_channels = hdspm->ss_out_channels = | ||
6258 | MADI_SS_CHANNELS; | ||
6259 | hdspm->ds_in_channels = hdspm->ds_out_channels = | ||
6260 | MADI_DS_CHANNELS; | ||
6261 | hdspm->qs_in_channels = hdspm->qs_out_channels = | ||
6262 | MADI_QS_CHANNELS; | ||
6263 | |||
6264 | hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = | ||
6265 | channel_map_unity_ss; | ||
6266 | hdspm->channel_map_in_ds = hdspm->channel_map_out_ss = | ||
6267 | channel_map_unity_ss; | ||
6268 | hdspm->channel_map_in_qs = hdspm->channel_map_out_ss = | ||
6269 | channel_map_unity_ss; | ||
6270 | |||
6271 | hdspm->port_names_in_ss = hdspm->port_names_out_ss = | ||
6272 | texts_ports_madi; | ||
6273 | hdspm->port_names_in_ds = hdspm->port_names_out_ds = | ||
6274 | texts_ports_madi; | ||
6275 | hdspm->port_names_in_qs = hdspm->port_names_out_qs = | ||
6276 | texts_ports_madi; | ||
6277 | break; | ||
6278 | |||
6279 | case AIO: | ||
6280 | if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) { | ||
6281 | snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n"); | ||
6282 | } | ||
6283 | |||
6284 | hdspm->ss_in_channels = AIO_IN_SS_CHANNELS; | ||
6285 | hdspm->ds_in_channels = AIO_IN_DS_CHANNELS; | ||
6286 | hdspm->qs_in_channels = AIO_IN_QS_CHANNELS; | ||
6287 | hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS; | ||
6288 | hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS; | ||
6289 | hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS; | ||
6290 | |||
6291 | hdspm->channel_map_out_ss = channel_map_aio_out_ss; | ||
6292 | hdspm->channel_map_out_ds = channel_map_aio_out_ds; | ||
6293 | hdspm->channel_map_out_qs = channel_map_aio_out_qs; | ||
6294 | |||
6295 | hdspm->channel_map_in_ss = channel_map_aio_in_ss; | ||
6296 | hdspm->channel_map_in_ds = channel_map_aio_in_ds; | ||
6297 | hdspm->channel_map_in_qs = channel_map_aio_in_qs; | ||
6298 | |||
6299 | hdspm->port_names_in_ss = texts_ports_aio_in_ss; | ||
6300 | hdspm->port_names_out_ss = texts_ports_aio_out_ss; | ||
6301 | hdspm->port_names_in_ds = texts_ports_aio_in_ds; | ||
6302 | hdspm->port_names_out_ds = texts_ports_aio_out_ds; | ||
6303 | hdspm->port_names_in_qs = texts_ports_aio_in_qs; | ||
6304 | hdspm->port_names_out_qs = texts_ports_aio_out_qs; | ||
6305 | |||
6306 | break; | ||
6307 | |||
6308 | case RayDAT: | ||
6309 | hdspm->ss_in_channels = hdspm->ss_out_channels = | ||
6310 | RAYDAT_SS_CHANNELS; | ||
6311 | hdspm->ds_in_channels = hdspm->ds_out_channels = | ||
6312 | RAYDAT_DS_CHANNELS; | ||
6313 | hdspm->qs_in_channels = hdspm->qs_out_channels = | ||
6314 | RAYDAT_QS_CHANNELS; | ||
6315 | |||
6316 | hdspm->max_channels_in = RAYDAT_SS_CHANNELS; | ||
6317 | hdspm->max_channels_out = RAYDAT_SS_CHANNELS; | ||
6318 | |||
6319 | hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = | ||
6320 | channel_map_raydat_ss; | ||
6321 | hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = | ||
6322 | channel_map_raydat_ds; | ||
6323 | hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = | ||
6324 | channel_map_raydat_qs; | ||
6325 | hdspm->channel_map_in = hdspm->channel_map_out = | ||
6326 | channel_map_raydat_ss; | ||
6327 | |||
6328 | hdspm->port_names_in_ss = hdspm->port_names_out_ss = | ||
6329 | texts_ports_raydat_ss; | ||
6330 | hdspm->port_names_in_ds = hdspm->port_names_out_ds = | ||
6331 | texts_ports_raydat_ds; | ||
6332 | hdspm->port_names_in_qs = hdspm->port_names_out_qs = | ||
6333 | texts_ports_raydat_qs; | ||
6334 | |||
6335 | |||
6336 | break; | ||
6337 | |||
6338 | } | ||
6339 | |||
6340 | /* TCO detection */ | ||
6341 | switch (hdspm->io_type) { | ||
6342 | case AIO: | ||
6343 | case RayDAT: | ||
6344 | if (hdspm_read(hdspm, HDSPM_statusRegister2) & | ||
6345 | HDSPM_s2_tco_detect) { | ||
6346 | hdspm->midiPorts++; | ||
6347 | hdspm->tco = kzalloc(sizeof(struct hdspm_tco), | ||
6348 | GFP_KERNEL); | ||
6349 | if (NULL != hdspm->tco) { | ||
6350 | hdspm_tco_write(hdspm); | ||
6351 | } | ||
6352 | snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n"); | ||
6353 | } else { | ||
6354 | hdspm->tco = NULL; | ||
6355 | } | ||
6356 | break; | ||
6357 | |||
6358 | case MADI: | ||
6359 | if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) { | ||
6360 | hdspm->midiPorts++; | ||
6361 | hdspm->tco = kzalloc(sizeof(struct hdspm_tco), | ||
6362 | GFP_KERNEL); | ||
6363 | if (NULL != hdspm->tco) { | ||
6364 | hdspm_tco_write(hdspm); | ||
6365 | } | ||
6366 | snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n"); | ||
6367 | } else { | ||
6368 | hdspm->tco = NULL; | ||
6369 | } | ||
6370 | break; | ||
6371 | |||
6372 | default: | ||
6373 | hdspm->tco = NULL; | ||
6374 | } | ||
6375 | |||
6376 | /* texts */ | ||
6377 | switch (hdspm->io_type) { | ||
6378 | case AES32: | ||
6379 | if (hdspm->tco) { | ||
6380 | hdspm->texts_autosync = texts_autosync_aes_tco; | ||
6381 | hdspm->texts_autosync_items = 10; | ||
6382 | } else { | ||
6383 | hdspm->texts_autosync = texts_autosync_aes; | ||
6384 | hdspm->texts_autosync_items = 9; | ||
6385 | } | ||
6386 | break; | ||
6387 | |||
6388 | case MADI: | ||
6389 | if (hdspm->tco) { | ||
6390 | hdspm->texts_autosync = texts_autosync_madi_tco; | ||
6391 | hdspm->texts_autosync_items = 4; | ||
6392 | } else { | ||
6393 | hdspm->texts_autosync = texts_autosync_madi; | ||
6394 | hdspm->texts_autosync_items = 3; | ||
6395 | } | ||
6396 | break; | ||
6397 | |||
6398 | case MADIface: | ||
6399 | |||
6400 | break; | ||
6401 | |||
6402 | case RayDAT: | ||
6403 | if (hdspm->tco) { | ||
6404 | hdspm->texts_autosync = texts_autosync_raydat_tco; | ||
6405 | hdspm->texts_autosync_items = 9; | ||
6406 | } else { | ||
6407 | hdspm->texts_autosync = texts_autosync_raydat; | ||
6408 | hdspm->texts_autosync_items = 8; | ||
6409 | } | ||
6410 | break; | ||
6411 | |||
6412 | case AIO: | ||
6413 | if (hdspm->tco) { | ||
6414 | hdspm->texts_autosync = texts_autosync_aio_tco; | ||
6415 | hdspm->texts_autosync_items = 6; | ||
6416 | } else { | ||
6417 | hdspm->texts_autosync = texts_autosync_aio; | ||
6418 | hdspm->texts_autosync_items = 5; | ||
6419 | } | ||
6420 | break; | ||
6421 | |||
6422 | } | ||
6423 | |||
6424 | tasklet_init(&hdspm->midi_tasklet, | ||
6425 | hdspm_midi_tasklet, (unsigned long) hdspm); | ||
4436 | 6426 | ||
4437 | snd_printdd("create alsa devices.\n"); | 6427 | snd_printdd("create alsa devices.\n"); |
4438 | err = snd_hdspm_create_alsa_devices(card, hdspm); | 6428 | err = snd_hdspm_create_alsa_devices(card, hdspm); |
@@ -4444,6 +6434,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
4444 | return 0; | 6434 | return 0; |
4445 | } | 6435 | } |
4446 | 6436 | ||
6437 | |||
4447 | static int snd_hdspm_free(struct hdspm * hdspm) | 6438 | static int snd_hdspm_free(struct hdspm * hdspm) |
4448 | { | 6439 | { |
4449 | 6440 | ||
@@ -4452,7 +6443,8 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4452 | /* stop th audio, and cancel all interrupts */ | 6443 | /* stop th audio, and cancel all interrupts */ |
4453 | hdspm->control_register &= | 6444 | hdspm->control_register &= |
4454 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | | 6445 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | |
4455 | HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable); | 6446 | HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable | |
6447 | HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable); | ||
4456 | hdspm_write(hdspm, HDSPM_controlRegister, | 6448 | hdspm_write(hdspm, HDSPM_controlRegister, |
4457 | hdspm->control_register); | 6449 | hdspm->control_register); |
4458 | } | 6450 | } |
@@ -4472,6 +6464,7 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4472 | return 0; | 6464 | return 0; |
4473 | } | 6465 | } |
4474 | 6466 | ||
6467 | |||
4475 | static void snd_hdspm_card_free(struct snd_card *card) | 6468 | static void snd_hdspm_card_free(struct snd_card *card) |
4476 | { | 6469 | { |
4477 | struct hdspm *hdspm = card->private_data; | 6470 | struct hdspm *hdspm = card->private_data; |
@@ -4480,6 +6473,7 @@ static void snd_hdspm_card_free(struct snd_card *card) | |||
4480 | snd_hdspm_free(hdspm); | 6473 | snd_hdspm_free(hdspm); |
4481 | } | 6474 | } |
4482 | 6475 | ||
6476 | |||
4483 | static int __devinit snd_hdspm_probe(struct pci_dev *pci, | 6477 | static int __devinit snd_hdspm_probe(struct pci_dev *pci, |
4484 | const struct pci_device_id *pci_id) | 6478 | const struct pci_device_id *pci_id) |
4485 | { | 6479 | { |
@@ -4496,7 +6490,7 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4496 | } | 6490 | } |
4497 | 6491 | ||
4498 | err = snd_card_create(index[dev], id[dev], | 6492 | err = snd_card_create(index[dev], id[dev], |
4499 | THIS_MODULE, sizeof(struct hdspm), &card); | 6493 | THIS_MODULE, sizeof(struct hdspm), &card); |
4500 | if (err < 0) | 6494 | if (err < 0) |
4501 | return err; | 6495 | return err; |
4502 | 6496 | ||
@@ -4507,16 +6501,25 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4507 | 6501 | ||
4508 | snd_card_set_dev(card, &pci->dev); | 6502 | snd_card_set_dev(card, &pci->dev); |
4509 | 6503 | ||
4510 | err = snd_hdspm_create(card, hdspm, precise_ptr[dev], | 6504 | err = snd_hdspm_create(card, hdspm); |
4511 | enable_monitor[dev]); | ||
4512 | if (err < 0) { | 6505 | if (err < 0) { |
4513 | snd_card_free(card); | 6506 | snd_card_free(card); |
4514 | return err; | 6507 | return err; |
4515 | } | 6508 | } |
4516 | 6509 | ||
4517 | strcpy(card->shortname, "HDSPM MADI"); | 6510 | if (hdspm->io_type != MADIface) { |
4518 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, | 6511 | sprintf(card->shortname, "%s_%x", |
4519 | hdspm->port, hdspm->irq); | 6512 | hdspm->card_name, |
6513 | (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF); | ||
6514 | sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d", | ||
6515 | hdspm->card_name, | ||
6516 | (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF, | ||
6517 | hdspm->port, hdspm->irq); | ||
6518 | } else { | ||
6519 | sprintf(card->shortname, "%s", hdspm->card_name); | ||
6520 | sprintf(card->longname, "%s at 0x%lx, irq %d", | ||
6521 | hdspm->card_name, hdspm->port, hdspm->irq); | ||
6522 | } | ||
4520 | 6523 | ||
4521 | err = snd_card_register(card); | 6524 | err = snd_card_register(card); |
4522 | if (err < 0) { | 6525 | if (err < 0) { |