root/trunk/libffado/src/motu/motu_controls.cpp

Revision 1006, 14.3 kB (checked in by jwoithe, 13 years ago)

MOTU: implement "phones source" control.
MOTU: commence work on optical mode control. For various reasons this isn't functional yet.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2008 by Jonathan Woithe
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 // This also includes motu_controls.h
26 #include "motu_avdevice.h"
27
28 namespace Motu {
29
30 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg)
31 : Control::Discrete()
32 , m_parent(parent)
33 , m_register(dev_reg)
34 {
35 }
36
37 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg,
38              std::string name, std::string label, std::string descr)
39 : Control::Discrete()
40 , m_parent(parent)
41 , m_register(dev_reg)
42 {
43     setName(name);
44     setLabel(label);
45     setDescription(descr);
46 }
47
48 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
49   unsigned int val_mask, unsigned int setenable_mask)
50 : MotuDiscreteCtrl(parent, dev_reg)
51 {
52     m_value_mask = val_mask;
53     /* If no "write enable" is implemented for a given switch it's safe to
54      * pass zero in to setenable_mask.
55      */
56     m_setenable_mask = setenable_mask;
57 }
58
59 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
60     unsigned int val_mask, unsigned int setenable_mask,
61     std::string name, std::string label, std::string descr)
62 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
63 {
64     m_value_mask = val_mask;
65     /* If no "write enable" is implemented for a given switch it's safe to
66      * pass zero in to setenable_mask.
67      */
68     m_setenable_mask = setenable_mask;
69 }
70              
71 bool
72 MotuBinarySwitch::setValue(int v)
73 {
74     unsigned int val;
75     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for switch %s (0x%04x) to %d\n",
76       getName().c_str(), m_register, v);
77
78     // Set the value
79     if (m_setenable_mask) {
80       val = (v==0)?0:m_value_mask;
81       // Set the "write enable" bit for the value being set
82       val |= m_setenable_mask;
83     } else {
84       // It would be good to utilise the cached value from the receive
85       // processor (if running) later on.  For now we'll just fetch the
86       // current register value directly when needed.
87       val = m_parent.ReadRegister(m_register);
88       if (v==0)
89         val &= ~m_value_mask;
90       else
91         val |= m_value_mask;
92     }
93     m_parent.WriteRegister(m_register, val);
94
95     return true;
96 }
97
98 int
99 MotuBinarySwitch::getValue()
100 {
101     unsigned int val;
102     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for switch %s (0x%04x)\n",
103       getName().c_str(), m_register);
104
105     // FIXME: we could just read the appropriate mixer status field from the
106     // receive stream processor once we work out an efficient way to do this.
107     val = m_parent.ReadRegister(m_register);
108     return (val & m_value_mask) != 0;
109 }
110
111 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg)
112 : MotuDiscreteCtrl(parent, dev_reg)
113 {
114 }
115
116 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg,
117              std::string name, std::string label, std::string descr)
118 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
119 {
120 }
121              
122 bool
123 ChannelFader::setValue(int v)
124 {
125     unsigned int val;
126     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel fader 0x%04x to %d\n", m_register, v);
127
128     val = v<0?0:v;
129     if (val > 0x80)
130       val = 0x80;
131     // Bit 30 indicates that the channel fader is being set
132     val |= 0x40000000;
133     m_parent.WriteRegister(m_register, val);
134
135     return true;
136 }
137
138 int
139 ChannelFader::getValue()
140 {
141     unsigned int val;
142     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel fader 0x%04x\n", m_register);
143
144     // FIXME: we could just read the appropriate mixer status field from the
145     // receive stream processor once we work out an efficient way to do this.
146     val = m_parent.ReadRegister(m_register);
147     return val & 0xff;
148 }
149
150 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg)
151 : MotuDiscreteCtrl(parent, dev_reg)
152 {
153 }
154
155 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg,
156              std::string name, std::string label, std::string descr)
157 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
158 {
159 }
160              
161 bool
162 ChannelPan::setValue(int v)
163 {
164     unsigned int val;
165     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel pan 0x%04x to %d\n", m_register, v);
166
167     val = ((v<-64?-64:v)+64) & 0xff;
168     if (val > 0x80)
169       val = 0x80;
170     // Bit 31 indicates that pan is being set
171     val = (val << 8) | 0x80000000;
172     m_parent.WriteRegister(m_register, val);
173
174     return true;
175 }
176
177 int
178 ChannelPan::getValue()
179 {
180     unsigned int val;
181     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel pan 0x%04x\n", m_register);
182
183     // FIXME: we could just read the appropriate mixer status field from the
184     // receive stream processor once we work out an efficient way to do this.
185     val = m_parent.ReadRegister(m_register);
186     return ((val >> 8) & 0xff) - 0x40;
187 }
188
189 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg)
190 : MotuDiscreteCtrl(parent, dev_reg)
191 {
192 }
193
194 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg,
195              std::string name, std::string label, std::string descr)
196 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
197 {
198 }
199              
200 bool
201 MixFader::setValue(int v)
202 {
203     unsigned int val;
204     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix fader 0x%04x to %d\n", m_register, v);
205
206     val = v<0?0:v;
207     if (val > 0x80)
208       val = 0x80;
209     // Bit 24 indicates that the mix fader is being set
210     val |= 0x01000000;
211     m_parent.WriteRegister(m_register, val);
212
213     return true;
214 }
215
216 int
217 MixFader::getValue()
218 {
219     unsigned int val;
220     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix fader 0x%04x\n", m_register);
221
222     // FIXME: we could just read the appropriate mixer status field from the
223     // receive stream processor once we work out an efficient way to do this.
224     val = m_parent.ReadRegister(m_register);
225     return val & 0xff;
226 }
227
228 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg)
229 : MotuDiscreteCtrl(parent, dev_reg)
230 {
231 }
232
233 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg,
234              std::string name, std::string label, std::string descr)
235 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
236 {
237 }
238              
239 bool
240 MixMute::setValue(int v)
241 {
242     unsigned int val, dest;
243     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix mute 0x%04x to %d\n", m_register, v);
244
245     // Need to read current destination so we can preserve that when setting
246     // mute status (mute and destination are always set together).
247     dest = m_parent.ReadRegister(m_register) & 0x00000f00;
248     // Mute status is bit 12
249     val = (v==0)?0:0x00001000;
250     // Bit 25 indicates that mute and destination are being set.  Also
251     // preserve the current destination.
252     val |= 0x02000000 | dest;
253     m_parent.WriteRegister(m_register, val);
254
255     return true;
256 }
257
258 int
259 MixMute::getValue()
260 {
261     unsigned int val;
262     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix mute 0x%04x\n", m_register);
263
264     // FIXME: we could just read the appropriate mixer status field from the
265     // receive stream processor once we work out an efficient way to do this.
266     val = m_parent.ReadRegister(m_register);
267     return (val & 0x00001000) != 0;
268 }
269
270 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg)
271 : MotuDiscreteCtrl(parent, dev_reg)
272 {
273 }
274
275 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg,
276              std::string name, std::string label, std::string descr)
277 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
278 {
279 }
280              
281 bool
282 MixDest::setValue(int v)
283 {
284     unsigned int val, mute;
285     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix destination 0x%04x to %d\n", m_register, v);
286
287     // Need to get current mute status so we can preserve it
288     mute = m_parent.ReadRegister(m_register) & 0x00001000;
289     val = v;
290     /* Currently destination values between 0 and 0x0b are accepted.
291      * Ultimately this will be device (and device configuration) dependent.
292      */
293     if (val<0 || val>0x0b)
294       val = 0;
295     /* Destination is given by bits 11-8.  Add in the current mute status so
296      * it can be preserved (it's set concurrently with the destination).
297      */
298     val = (val << 8) | mute;
299     // Bit 25 indicates that mute and destination are being set
300     val |= 0x02000000;
301     m_parent.WriteRegister(m_register, val);
302
303     return true;
304 }
305
306 int
307 MixDest::getValue()
308 {
309     unsigned int val;
310     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix destination 0x%04x\n", m_register);
311
312     // FIXME: we could just read the appropriate mixer status field from the
313     // receive stream processor once we work out an efficient way to do this.
314     val = m_parent.ReadRegister(m_register);
315     return (val >> 8) & 0x0f;
316 }
317
318 PhonesSrc::PhonesSrc(MotuDevice &parent)
319 : MotuDiscreteCtrl(parent, 0)
320 {
321 }
322
323 PhonesSrc::PhonesSrc(MotuDevice &parent,
324              std::string name, std::string label, std::string descr)
325 : MotuDiscreteCtrl(parent, 0, name, label, descr)
326 {
327 }
328              
329 bool
330 PhonesSrc::setValue(int v)
331 {
332     unsigned int val;
333     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for phones destination to %d\n", v);
334
335     /* Currently destination values between 0 and 0x0b are accepted.
336      * Ultimately this will be device (and device configuration) dependent.
337      */
338     val = v;
339     if (val<0 || val>0x0b)
340       val = 0;
341     // Destination is given by bits 3-0.
342     // Bit 24 indicates that the phones source is being set.
343     val |= 0x01000000;
344     m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
345
346     return true;
347 }
348
349 int
350 PhonesSrc::getValue()
351 {
352     unsigned int val;
353     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for phones destination\n");
354
355     // FIXME: we could just read the appropriate mixer status field from the
356     // receive stream processor once we work out an efficient way to do this.
357     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
358     return val & 0x0f;
359 }
360
361 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg)
362 : MotuDiscreteCtrl(parent, dev_reg)
363 {
364 }
365
366 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg,
367              std::string name, std::string label, std::string descr)
368 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
369 {
370 }
371              
372 bool
373 OpticalMode::setValue(int v)
374 {
375     unsigned int val;
376     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for optical mode %d to %d\n", m_register, v);
377
378     // Need to get current optical modes so we can preserve the one we're
379     // not setting.  Input mode is in bits 9-8, output is in bits 11-10.
380     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF) & 0x000000f0;
381
382     // Set mode as requested.  An invalid setting is effectively ignored.
383     if (v>=0 && v>=3) {
384       if (m_register == MOTU_DIR_IN) {
385         val = (val & ~0x0030) | ((v & 0x03) << 8);
386       } else {
387         val = (val & ~0x00c0) | ((v & 0x03) << 10);
388       }
389     }
390     // Bit 25 indicates that optical modes are being set
391     val |= 0x02000000;
392     m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
393
394     return true;
395 }
396
397 int
398 OpticalMode::getValue()
399 {
400     unsigned int val;
401     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for optical mode %d\n", m_register);
402
403     // FIXME: we could just read the appropriate mixer status field from the
404     // receive stream processor once we work out an efficient way to do this.
405     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
406     if (m_register == MOTU_DIR_IN)
407       val = (val >> 8) & 0x03;
408     else
409       val = (val >> 10) & 0x03;
410     return val;
411 }
412
413 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype)
414 : MotuDiscreteCtrl(parent, infotype)
415 {
416 }
417
418 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype,
419              std::string name, std::string label, std::string descr)
420 : MotuDiscreteCtrl(parent, infotype, name, label, descr)
421 {
422 }
423              
424 bool
425 InfoElement::setValue(int v)
426 {
427     /* This is a read-only field, so any call to setValue() is technically
428      * an error.
429      */
430     debugOutput(DEBUG_LEVEL_VERBOSE, "InfoElement (%d) is read-only\n", m_register);
431     return false;
432 }
433
434 int
435 InfoElement::getValue()
436 {
437     unsigned int val;
438     signed int res = 0;
439
440     switch (m_register) {
441         case MOTU_INFO_IS_STREAMING:
442             val = m_parent.ReadRegister(MOTU_REG_ISOCTRL);
443             /* Streaming is active if either bit 22 (Motu->PC streaming
444              * enable) or bit 30 (PC->Motu streaming enable) is set.
445              */
446             res = (val & 0x40400000) != 0;
447             debugOutput(DEBUG_LEVEL_VERBOSE, "IsStreaming: %d (reg=%08x)\n", res, val);
448             break;
449         case MOTU_INFO_SAMPLE_RATE:
450             res = m_parent.getSamplingFrequency();
451             debugOutput(DEBUG_LEVEL_VERBOSE, "SampleRate: %d\n", res);
452             break;
453         case MOTU_INFO_HAS_MIC_INPUTS:
454             /* Only the 828Mk2 has separate mic inputs.  In time this may be
455              * deduced by walking the port info array within the parent.
456              */
457             res = m_parent.m_motu_model == MOTU_MODEL_828mkII ? 1:0;
458             debugOutput(DEBUG_LEVEL_VERBOSE, "Has mic inputs: %d\n", res);
459             break;
460         case MOTU_INFO_HAS_AESEBU_INPUTS:
461             /* AES/EBU inputs are currently present on the Traveler and
462              * 896HD.  In time this may be deduced by walking the port info
463              * array within the parent.
464              */
465             val = m_parent.m_motu_model;
466             res = (val==MOTU_MODEL_TRAVELER || val==MOTU_MODEL_896HD);
467             debugOutput(DEBUG_LEVEL_VERBOSE, "HasAESEBUInputs: %d\n", res);
468             break;
469         case MOTU_INFO_HAS_SPDIF_INPUTS:
470             /* SPDIF inputs are present on all supported models except the
471              * 896HD and the 8pre.  In time this may be deduced by walking
472              * the port info array within the parent.
473              */
474             val = m_parent.m_motu_model;
475             res = (val!=MOTU_MODEL_8PRE && val!=MOTU_MODEL_896HD);
476             debugOutput(DEBUG_LEVEL_VERBOSE, "HasSPDIFInputs: %d\n", res);
477             break;
478     }
479     return res;
480 }
481
482 }
Note: See TracBrowser for help on using the browser.