root/trunk/libffado/src/rme/rme_avdevice_settings.cpp

Revision 2033, 10.6 kB (checked in by jwoithe, 9 years ago)

rme: implement SPDIF output option control via ffado-mixer. Again, I haven't the means to confirm whether these settings have the desired effect on the SPDIF bitstream yet.

Line 
1 /*
2  * Copyright (C) 2005-2009 by Jonathan Woithe
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "rme/rme_avdevice.h"
24 #include "rme/fireface_def.h"
25
26 #include "debugmodule/debugmodule.h"
27
28 namespace Rme {
29
30 signed int
31 Device::getPhantom(unsigned int channel) {
32
33     if (channel > 3) {
34         debugOutput(DEBUG_LEVEL_WARNING, "Channel %d phantom power not supported\n", channel);
35         return -1;
36     }
37
38     return settings->mic_phantom[channel] != 0;
39 }
40
41 signed int
42 Device::setPhantom(unsigned int channel, unsigned int status) {
43
44     if (channel > 3) {
45         debugOutput(DEBUG_LEVEL_WARNING, "Channel %d phantom power not supported\n", channel);
46         return -1;
47     }
48
49     settings->mic_phantom[channel] = (status != 0);
50     set_hardware_params();
51
52     return 0;
53 }
54
55 signed int
56 Device::getInputLevel(void) {
57     return settings->input_level;
58 }
59
60 signed int
61 Device::setInputLevel(unsigned int level) {
62
63     if (level<FF_SWPARAM_ILEVEL_LOGAIN || level>FF_SWPARAM_ILEVEL_m10dBV) {
64         debugOutput(DEBUG_LEVEL_WARNING, "Invalid input level ID %d\n", level);
65         return -1;
66     }
67     settings->input_level = level;
68     set_hardware_params();
69
70     return 0;
71 }
72
73 signed int
74 Device::getOutputLevel(void) {
75     return settings->output_level;
76 }
77
78 signed int
79 Device::setOutputLevel(unsigned int level) {
80
81     if (level<FF_SWPARAM_OLEVEL_HIGAIN || level>FF_SWPARAM_OLEVEL_m10dBV) {
82         debugOutput(DEBUG_LEVEL_WARNING, "Invalid output level ID %d\n", level);
83         return -1;
84     }
85     settings->output_level = level;
86     set_hardware_params();
87
88     return 0;
89 }
90
91 signed int
92 Device::getPhonesLevel(void) {
93     return settings->phones_level;
94 }
95
96 signed int
97 Device::setPhonesLevel(unsigned int level) {
98
99     if (level<FF_SWPARAM_PHONESLEVEL_HIGAIN || level>FF_SWPARAM_PHONESLEVEL_m10dBV) {
100         debugOutput(DEBUG_LEVEL_WARNING, "Invalid phones level ID %d\n", level);
101         return -1;
102     }
103     settings->phones_level = level;
104     set_hardware_params();
105
106     return 0;
107 }
108
109 signed int
110 Device::getInputPadOpt(unsigned int channel) {
111     if (m_rme_model!=RME_MODEL_FIREFACE400 || channel<3 || channel>4) {
112         debugOutput(DEBUG_LEVEL_WARNING, "Channel %d input pad option not supported for model %d\n", channel, m_rme_model);
113         return -1;
114     }
115     return settings->ff400_input_pad[channel-3] != 0;
116 }
117
118 signed int
119 Device::setInputPadOpt(unsigned int channel, unsigned int status) {
120     if (m_rme_model!=RME_MODEL_FIREFACE400 || channel<3 || channel>4) {
121         debugOutput(DEBUG_LEVEL_WARNING, "Channel %d input pad option not supported for model %d\n", channel, m_rme_model);
122         return -1;
123     }
124     settings->ff400_input_pad[channel-3] = (status != 0);
125     set_hardware_params();
126     return 0;
127 }
128
129 signed int
130 Device::getInputInstrOpt(unsigned int channel) {
131     if (m_rme_model!=RME_MODEL_FIREFACE400 || channel<3 || channel>4) {
132         debugOutput(DEBUG_LEVEL_WARNING, "Channel %d input instrument option not supported for model %d\n", channel, m_rme_model);
133         return -1;
134     }
135     return settings->ff400_instr_input[channel-3] != 0;
136 }
137
138 signed int
139 Device::setInputInstrOpt(unsigned int channel, unsigned int status) {
140     if (m_rme_model!=RME_MODEL_FIREFACE400 || channel<3 || channel>4) {
141         debugOutput(DEBUG_LEVEL_WARNING, "Channel %d input instrument option not supported for model %d\n", channel, m_rme_model);
142         return -1;
143     }
144     settings->ff400_instr_input[channel-3] = (status != 0);
145     set_hardware_params();
146     return 0;
147 }
148
149 signed int
150 Device::getSpdifInputMode(void) {
151     return settings->spdif_input_mode;
152 }
153
154 signed int
155 Device::setSpdifInputMode(signed int mode) {
156     settings->spdif_input_mode = mode;
157     set_hardware_params();
158     return 0;
159 }
160
161 signed int
162 Device::getSpdifOutputIsOptical(void) {
163     return settings->spdif_output_mode == FF_SWPARAM_SPDIF_OUTPUT_OPTICAL;
164 }
165 signed int
166 Device::setSpdifOutputIsOptical(signed int enable) {
167   settings->spdif_output_mode = enable==1?FF_SWPARAM_SPDIF_OUTPUT_OPTICAL:FF_SWPARAM_SPDIF_OUTPUT_COAX;
168   set_hardware_params();
169   return 0;
170 }
171 signed int
172 Device::getSpdifOutputEmphasisOn(void) {
173     return settings->spdif_output_emphasis == FF_SWPARAM_SPDIF_OUTPUT_EMPHASIS_ON;
174 }
175 signed int
176 Device::setSpdifOutputEmphasisOn(signed int enable) {
177   settings->spdif_output_emphasis = enable==1?FF_SWPARAM_SPDIF_OUTPUT_EMPHASIS_ON:0;
178   set_hardware_params();
179   return 0;
180 }
181 signed int
182 Device::getSpdifOutputNonAudioOn(void) {
183     return settings->spdif_output_nonaudio == FF_SWPARAM_SPDIF_OUTPUT_NONAUDIO_ON;
184 }
185 signed int
186 Device::setSpdifOutputNonAudioOn(signed int enable) {
187   settings->spdif_output_nonaudio = enable==1?FF_SWPARAM_SPDIF_OUTPUT_NONAUDIO_ON:0;
188   set_hardware_params();
189   return 0;
190 }
191 signed int
192 Device::getSpdifOutputProOn(void) {
193     return settings->spdif_output_pro == FF_SWPARAM_SPDIF_OUTPUT_PRO_ON;
194 }
195 signed int
196 Device::setSpdifOutputProOn(signed int enable) {
197   settings->spdif_output_pro = enable==1?FF_SWPARAM_SPDIF_OUTPUT_PRO_ON:0;
198   set_hardware_params();
199   return 0;
200 }
201
202 signed int
203 Device::getAmpGain(unsigned int index) {
204     if (m_rme_model != RME_MODEL_FIREFACE400) {
205         debugOutput(DEBUG_LEVEL_WARNING, "Amp gains only supported on FF400\n");
206         return -1;
207     }
208     if (index > 21) {
209         debugOutput(DEBUG_LEVEL_WARNING, "Amp gain index %d invalid\n", index);
210          return -1;
211     }
212     return settings->amp_gains[index];
213 }
214
215 signed int
216 Device::setAmpGain(unsigned int index, signed int val) {
217
218     if (m_rme_model != RME_MODEL_FIREFACE400) {
219         debugOutput(DEBUG_LEVEL_WARNING, "Amp gains only supported on FF400\n");
220         return -1;
221     }
222     if (index > 21) {
223         debugOutput(DEBUG_LEVEL_WARNING, "Amp gain index %d invalid\n", index);
224          return -1;
225     }
226     settings->amp_gains[index] = val & 0xff;
227     return set_hardware_ampgain(index, val);
228 }
229
230 signed int
231 Device::getMixerGainIndex(unsigned int src_channel, unsigned int dest_channel) {
232     return dest_channel*RME_FF800_MAX_CHANNELS + src_channel;
233 }
234
235 signed int
236 Device::getMixerGain(unsigned int ctype,
237     unsigned int src_channel, unsigned int dest_channel) {
238
239     signed int idx = getMixerGainIndex(src_channel, dest_channel);
240     switch (ctype) {
241         case RME_FF_MM_INPUT:
242             return settings->input_faders[idx];
243             break;
244         case RME_FF_MM_PLAYBACK:
245             return settings->playback_faders[idx];
246             break;
247         case RME_FF_MM_OUTPUT:
248             return settings->output_faders[src_channel];
249             break;
250     }
251     return 0;
252 }
253
254 signed int
255 Device::setMixerGain(unsigned int ctype,
256     unsigned int src_channel, unsigned int dest_channel, signed int val) {
257
258     unsigned char *mixerflags = NULL;
259     signed int idx = getMixerGainIndex(src_channel, dest_channel);
260
261     switch (ctype) {
262         case RME_FF_MM_INPUT:
263             settings->input_faders[idx] = val;
264             mixerflags = settings->input_mixerflags;
265             break;
266         case RME_FF_MM_PLAYBACK:
267             settings->playback_faders[idx] = val;
268             mixerflags = settings->playback_mixerflags;
269             break;
270         case RME_FF_MM_OUTPUT:
271             settings->output_faders[src_channel] = val;
272             mixerflags = settings->output_mixerflags;
273             break;
274     }
275
276     // If the matrix channel is muted, override the fader value and
277     // set it to zero.  Note that this is different to the hardware
278     // mute control dealt with by set_hardware_channel_mute(); the
279     // latter deals with a muting separate from the mixer.
280     if (mixerflags!=NULL && (mixerflags[idx] & FF_SWPARAM_MF_MUTED)!=0) {
281         val = 0;
282     }
283
284     // Phase inversion is effected by sending a negative volume to the
285     // hardware.  However, when transitioning from 0 (-inf dB) to -1 (-90
286     // dB), the hardware seems to first send the volume up to a much higher
287     // level before it drops down to the set point after about a tenth of a
288     // second (this also seems to be the case when switching between
289     // inversion modes).  To work around this for the moment (at least until
290     // it's understood, silently map a value of 0 to -1 when phase inversion
291     // is active.
292     if (mixerflags!=NULL && (mixerflags[idx] & FF_SWPARAM_MF_INVERTED)!=0) {
293         if (val == 0)
294             val = 1;
295         val = -val;
296     }
297
298     return set_hardware_mixergain(ctype, src_channel, dest_channel, val);
299 }
300
301 signed int
302 Device::getMixerFlags(unsigned int ctype,
303     unsigned int src_channel, unsigned int dest_channel, unsigned int flagmask) {
304
305     unsigned char *mixerflags = NULL;
306     signed int idx = getMixerGainIndex(src_channel, dest_channel);
307     if (ctype == RME_FF_MM_OUTPUT) {
308         mixerflags = settings->output_mixerflags;
309         idx = src_channel;
310     } else
311     if (ctype == RME_FF_MM_INPUT)
312         mixerflags = settings->input_mixerflags;
313     else
314         mixerflags = settings->playback_mixerflags;
315
316     return mixerflags[idx] & flagmask;
317 }
318
319 signed int
320 Device::setMixerFlags(unsigned int ctype,
321     unsigned int src_channel, unsigned int dest_channel,
322     unsigned int flagmask, signed int val) {
323
324     unsigned char *mixerflags = NULL;
325     signed int idx = getMixerGainIndex(src_channel, dest_channel);
326     if (ctype == RME_FF_MM_OUTPUT) {
327         mixerflags = settings->output_mixerflags;
328         idx = src_channel;
329     } else
330     if (ctype == RME_FF_MM_INPUT)
331         mixerflags = settings->input_mixerflags;
332     else
333         mixerflags = settings->playback_mixerflags;
334
335 // FIXME: When switching inversion modes, the hardware seems to a channel to
336 // full volume for about 1/10 sec.  Attempt to avoid this by temporarily
337 // muting the channel.  This doesn't seem to work though.
338 //    if (flagmask & FF_SWPARAM_MF_INVERTED)
339 //        set_hardware_mixergain(ctype, src_channel, dest_channel, 0);
340
341     if (val == 0)
342         mixerflags[idx] &= ~flagmask;
343     else
344         mixerflags[idx] |= flagmask;
345
346     if (flagmask & (FF_SWPARAM_MF_MUTED|FF_SWPARAM_MF_INVERTED)) {
347         // Mixer channel muting/inversion is handled via the gain control
348         return setMixerGain(ctype, src_channel, dest_channel,
349             getMixerGain(ctype, src_channel, dest_channel));
350     }
351     return 0;
352 }
353
354 }
Note: See TracBrowser for help on using the browser.