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

Revision 1531, 29.6 kB (checked in by ppalmers, 13 years ago)

svn merge -r 1506:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2008-2009 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(&parent)
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(&parent)
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     if (m_register == MOTU_CTRL_NONE) {
79         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
80         return true;
81     }
82
83     // Set the value
84     if (m_setenable_mask) {
85       val = (v==0)?0:m_value_mask;
86       // Set the "write enable" bit for the value being set
87       val |= m_setenable_mask;
88     } else {
89       // It would be good to utilise the cached value from the receive
90       // processor (if running) later on.  For now we'll just fetch the
91       // current register value directly when needed.
92       val = m_parent.ReadRegister(m_register);
93       if (v==0)
94         val &= ~m_value_mask;
95       else
96         val |= m_value_mask;
97     }
98     m_parent.WriteRegister(m_register, val);
99
100     return true;
101 }
102
103 int
104 MotuBinarySwitch::getValue()
105 {
106     unsigned int val;
107     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for switch %s (0x%04x)\n",
108       getName().c_str(), m_register);
109
110     if (m_register == MOTU_CTRL_NONE) {
111         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
112         return 0;
113     }
114
115     // FIXME: we could just read the appropriate mixer status field from the
116     // receive stream processor once we work out an efficient way to do this.
117     val = m_parent.ReadRegister(m_register);
118     return (val & m_value_mask) != 0;
119 }
120
121 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg)
122 : MotuDiscreteCtrl(parent, dev_reg)
123 {
124 }
125
126 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg,
127              std::string name, std::string label, std::string descr)
128 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
129 {
130 }
131              
132 bool
133 ChannelFader::setValue(int v)
134 {
135     unsigned int val;
136     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel fader 0x%04x to %d\n", m_register, v);
137
138     if (m_register == MOTU_CTRL_NONE) {
139         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
140         return true;
141     }
142
143     val = v<0?0:v;
144     if (val > 0x80)
145       val = 0x80;
146     // Bit 30 indicates that the channel fader is being set
147     val |= 0x40000000;
148     m_parent.WriteRegister(m_register, val);
149
150     return true;
151 }
152
153 int
154 ChannelFader::getValue()
155 {
156     unsigned int val;
157     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel fader 0x%04x\n", m_register);
158
159     // Silently swallow attempts to read non-existent controls for now
160     if (m_register == MOTU_CTRL_NONE) {
161         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
162         return 0;
163     }
164
165     // FIXME: we could just read the appropriate mixer status field from the
166     // receive stream processor once we work out an efficient way to do this.
167     val = m_parent.ReadRegister(m_register);
168     return val & 0xff;
169 }
170
171 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg)
172 : MotuDiscreteCtrl(parent, dev_reg)
173 {
174 }
175
176 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg,
177              std::string name, std::string label, std::string descr)
178 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
179 {
180 }
181              
182 bool
183 ChannelPan::setValue(int v)
184 {
185     unsigned int val;
186     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel pan 0x%04x to %d\n", m_register, v);
187
188     if (m_register == MOTU_CTRL_NONE) {
189         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
190         return true;
191     }
192
193     val = ((v<-64?-64:v)+64) & 0xff;
194     if (val > 0x80)
195       val = 0x80;
196     // Bit 31 indicates that pan is being set
197     val = (val << 8) | 0x80000000;
198     m_parent.WriteRegister(m_register, val);
199
200     return true;
201 }
202
203 int
204 ChannelPan::getValue()
205 {
206     unsigned int val;
207     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel pan 0x%04x\n", m_register);
208
209     // Silently swallow attempts to read non-existent controls for now
210     if (m_register == MOTU_CTRL_NONE) {
211         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
212         return 0;
213     }
214
215     // FIXME: we could just read the appropriate mixer status field from the
216     // receive stream processor once we work out an efficient way to do this.
217     val = m_parent.ReadRegister(m_register);
218     return ((val >> 8) & 0xff) - 0x40;
219 }
220
221
222 MotuMatrixMixer::MotuMatrixMixer(MotuDevice &parent)
223 : Control::MatrixMixer(&parent, "MatrixMixer")
224 , m_parent(parent)
225 {
226 }
227
228 MotuMatrixMixer::MotuMatrixMixer(MotuDevice &parent, std::string name)
229 : Control::MatrixMixer(&parent, name)
230 , m_parent(parent)
231 {
232 }
233
234 void MotuMatrixMixer::addRowInfo(std::string name, unsigned int flags,
235   unsigned int address)
236 {
237     struct sSignalInfo s;
238     s.name = name;
239     s.flags = flags;
240     s.address = address;
241     m_RowInfo.push_back(s);
242 }
243
244 void MotuMatrixMixer::addColInfo(std::string name, unsigned int flags,
245   unsigned int address)
246 {
247     struct sSignalInfo s;
248     s.name = name;
249     s.flags = flags;
250     s.address = address;
251     m_ColInfo.push_back(s);
252 }
253
254 uint32_t MotuMatrixMixer::getCellRegister(const unsigned int row, const unsigned int col)
255 {
256     if (m_RowInfo.at(row).address==MOTU_CTRL_NONE ||
257         m_ColInfo.at(col).address==MOTU_CTRL_NONE)
258         return MOTU_CTRL_NONE;
259     return m_RowInfo.at(row).address + m_ColInfo.at(col).address;
260 }
261
262 void MotuMatrixMixer::show()
263 {
264     debugOutput(DEBUG_LEVEL_NORMAL, "MOTU matrix mixer\n");
265 }
266
267 std::string MotuMatrixMixer::getRowName(const int row)
268 {
269     return m_RowInfo.at(row).name;
270 }
271
272 std::string MotuMatrixMixer::getColName(const int col)
273 {
274     return m_ColInfo.at(col).name;
275 }
276
277 int MotuMatrixMixer::getRowCount()
278 {
279     return m_RowInfo.size();
280 }
281
282 int MotuMatrixMixer::getColCount()
283 {
284     return m_ColInfo.size();
285 }
286
287 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice &parent)
288 : MotuMatrixMixer(parent, "ChannelFaderMatrixMixer")
289 {
290 }
291
292 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice &parent, std::string name)
293 : MotuMatrixMixer(parent, name)
294 {
295 }
296
297 double ChannelFaderMatrixMixer::setValue(const int row, const int col, const double val)
298 {
299     uint32_t v, reg;
300     v = val<0?0:(uint32_t)val;
301     if (v > 0x80)
302       v = 0x80;
303     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelFader setValue for row %d col %d to %lf (%ld)\n",
304       row, col, val, v);
305     reg = getCellRegister(row,col);
306
307     // Silently swallow attempts to set non-existent controls for now
308     if (reg == MOTU_CTRL_NONE) {
309         debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
310         return true;
311     }
312     // Bit 30 indicates that the channel fader is being set
313     v |= 0x40000000;
314     m_parent.WriteRegister(reg, v);
315
316     return true;
317 }
318
319 double ChannelFaderMatrixMixer::getValue(const int row, const int col)
320 {
321     uint32_t val, reg;
322     reg = getCellRegister(row,col);
323
324     // Silently swallow attempts to read non-existent controls for now
325     if (reg == MOTU_CTRL_NONE) {
326         debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
327         return 0;
328     }
329     // FIXME: we could just read the appropriate mixer status field from the
330     // receive stream processor once we work out an efficient way to do this.
331     val = m_parent.ReadRegister(reg) & 0xff;
332
333     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelFader getValue for row %d col %d = %lu\n",
334       row, col, val);
335     return val;
336 }
337
338 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice &parent)
339 : MotuMatrixMixer(parent, "ChannelPanMatrixMixer")
340 {
341 }
342
343 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice &parent, std::string name)
344 : MotuMatrixMixer(parent, name)
345 {
346 }
347
348 double ChannelPanMatrixMixer::setValue(const int row, const int col, const double val)
349 {
350     uint32_t v, reg;
351     v = ((val<-64?-64:(int32_t)val)+64) & 0xff;
352     if (v > 0x80)
353       v = 0x80;
354
355     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelPan setValue for row %d col %d to %lf (%ld)\n",
356       row, col, val, v);
357     reg = getCellRegister(row,col);
358
359     // Silently swallow attempts to set non-existent controls for now
360     if (reg == MOTU_CTRL_NONE) {
361         debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
362         return true;
363     }
364
365     // Bit 31 indicates that pan is being set
366     v = (v << 8) | 0x80000000;
367     m_parent.WriteRegister(reg, v);
368
369     return true;
370 }
371
372 double ChannelPanMatrixMixer::getValue(const int row, const int col)
373 {
374     int32_t val;
375     uint32_t reg;
376     reg = getCellRegister(row,col);
377
378     // Silently swallow attempts to read non-existent controls for now
379     if (reg == MOTU_CTRL_NONE) {
380         debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
381         return 0;
382     }
383
384     // FIXME: we could just read the appropriate mixer status field from the
385     // receive stream processor once we work out an efficient way to do this.
386     val = m_parent.ReadRegister(reg);
387     val = ((val >> 8) & 0xff) - 0x40;
388
389     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelPan getValue for row %d col %d = %lu\n",
390       row, col, val);
391     return val;
392 }
393
394 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice &parent)
395 : MotuMatrixMixer(parent, "ChannelPanMatrixMixer")
396 , m_value_mask(0)
397 , m_setenable_mask(0)
398 {
399 }
400
401 /* If no "write enable" is implemented for a given switch it's safe to
402  * pass zero in to setenable_mask.
403  */
404 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice &parent, std::string name,
405   unsigned int val_mask, unsigned int setenable_mask)
406 : MotuMatrixMixer(parent, name)
407 , m_value_mask(val_mask)
408 , m_setenable_mask(setenable_mask)
409 {
410 }
411
412 double ChannelBinSwMatrixMixer::setValue(const int row, const int col, const double val)
413 {
414     uint32_t v, reg;
415
416     debugOutput(DEBUG_LEVEL_VERBOSE, "BinSw setValue for row %d col %d to %lf (%ld)\n",
417       row, col, val, val==0?0:1);
418     reg = getCellRegister(row,col);
419
420     // Silently swallow attempts to set non-existent controls for now
421     if (reg == MOTU_CTRL_NONE) {
422         debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
423         return true;
424     }
425
426     // Set the value
427     if (m_setenable_mask) {
428       v = (val==0)?0:m_value_mask;
429       // Set the "write enable" bit for the value being set
430       v |= m_setenable_mask;
431     } else {
432       // It would be good to utilise the cached value from the receive
433       // processor (if running) later on.  For now we'll just fetch the
434       // current register value directly when needed.
435       v = m_parent.ReadRegister(reg);
436       if (v==0)
437         v &= ~m_value_mask;
438       else
439         v |= m_value_mask;
440     }
441     m_parent.WriteRegister(reg, v);
442
443     return true;
444 }
445
446 double ChannelBinSwMatrixMixer::getValue(const int row, const int col)
447 {
448     uint32_t val, reg;
449     reg = getCellRegister(row,col);
450
451     // Silently swallow attempts to read non-existent controls for now
452     if (reg == MOTU_CTRL_NONE) {
453         debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
454         return 0;
455     }
456
457     // FIXME: we could just read the appropriate mixer status field from the
458     // receive stream processor once we work out an efficient way to do this.
459     val = m_parent.ReadRegister(reg);
460     val = (val & m_value_mask) != 0;
461
462     debugOutput(DEBUG_LEVEL_VERBOSE, "BinSw getValue for row %d col %d = %lu\n",
463       row, col, val);
464     return val;
465 }
466
467
468 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg)
469 : MotuDiscreteCtrl(parent, dev_reg)
470 {
471 }
472
473 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg,
474              std::string name, std::string label, std::string descr)
475 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
476 {
477 }
478              
479 bool
480 MixFader::setValue(int v)
481 {
482     unsigned int val;
483     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix fader 0x%04x to %d\n", m_register, v);
484
485     // Silently swallow attempts to set non-existent controls for now
486     if (m_register == MOTU_CTRL_NONE) {
487         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
488         return true;
489     }
490     val = v<0?0:v;
491     if (val > 0x80)
492       val = 0x80;
493     // Bit 24 indicates that the mix fader is being set
494     val |= 0x01000000;
495     m_parent.WriteRegister(m_register, val);
496
497     return true;
498 }
499
500 int
501 MixFader::getValue()
502 {
503     unsigned int val;
504     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix fader 0x%04x\n", m_register);
505
506     // Silently swallow attempts to read non-existent controls for now
507     if (m_register == MOTU_CTRL_NONE) {
508         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
509         return 0;
510     }
511
512     // FIXME: we could just read the appropriate mixer status field from the
513     // receive stream processor once we work out an efficient way to do this.
514     val = m_parent.ReadRegister(m_register);
515     return val & 0xff;
516 }
517
518 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg)
519 : MotuDiscreteCtrl(parent, dev_reg)
520 {
521 }
522
523 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg,
524              std::string name, std::string label, std::string descr)
525 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
526 {
527 }
528              
529 bool
530 MixMute::setValue(int v)
531 {
532     unsigned int val, dest;
533     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix mute 0x%04x to %d\n", m_register, v);
534
535     // Silently swallow attempts to set non-existent controls for now
536     if (m_register == MOTU_CTRL_NONE) {
537         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
538         return true;
539     }
540
541     // Need to read current destination so we can preserve that when setting
542     // mute status (mute and destination are always set together).
543     dest = m_parent.ReadRegister(m_register) & 0x00000f00;
544     // Mute status is bit 12
545     val = (v==0)?0:0x00001000;
546     // Bit 25 indicates that mute and destination are being set.  Also
547     // preserve the current destination.
548     val |= 0x02000000 | dest;
549     m_parent.WriteRegister(m_register, val);
550
551     return true;
552 }
553
554 int
555 MixMute::getValue()
556 {
557     unsigned int val;
558     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix mute 0x%04x\n", m_register);
559
560     // Silently swallow attempts to read non-existent controls for now
561     if (m_register == MOTU_CTRL_NONE) {
562         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
563         return 0;
564     }
565
566     // FIXME: we could just read the appropriate mixer status field from the
567     // receive stream processor once we work out an efficient way to do this.
568     val = m_parent.ReadRegister(m_register);
569     return (val & 0x00001000) != 0;
570 }
571
572 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg)
573 : MotuDiscreteCtrl(parent, dev_reg)
574 {
575 }
576
577 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg,
578              std::string name, std::string label, std::string descr)
579 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
580 {
581 }
582              
583 bool
584 MixDest::setValue(int v)
585 {
586     unsigned int val, mute;
587     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix destination 0x%04x to %d\n", m_register, v);
588
589     // Silently swallow attempts to set non-existent controls for now
590     if (m_register == MOTU_CTRL_NONE) {
591         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
592         return true;
593     }
594     // Need to get current mute status so we can preserve it
595     mute = m_parent.ReadRegister(m_register) & 0x00001000;
596     val = v;
597     /* Currently destination values between 0 and 0x0b are accepted.
598      * Ultimately this will be device (and device configuration) dependent.
599      */
600     if (val<0 || val>0x0b)
601       val = 0;
602     /* Destination is given by bits 11-8.  Add in the current mute status so
603      * it can be preserved (it's set concurrently with the destination).
604      */
605     val = (val << 8) | mute;
606     // Bit 25 indicates that mute and destination are being set
607     val |= 0x02000000;
608     m_parent.WriteRegister(m_register, val);
609
610     return true;
611 }
612
613 int
614 MixDest::getValue()
615 {
616     unsigned int val;
617     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix destination 0x%04x\n", m_register);
618
619     // Silently swallow attempts to read non-existent controls for now
620     if (m_register == MOTU_CTRL_NONE) {
621         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
622         return true;
623     }
624     // FIXME: we could just read the appropriate mixer status field from the
625     // receive stream processor once we work out an efficient way to do this.
626     val = m_parent.ReadRegister(m_register);
627     return (val >> 8) & 0x0f;
628 }
629
630 PhonesSrc::PhonesSrc(MotuDevice &parent)
631 : MotuDiscreteCtrl(parent, 0)
632 {
633 }
634
635 PhonesSrc::PhonesSrc(MotuDevice &parent,
636              std::string name, std::string label, std::string descr)
637 : MotuDiscreteCtrl(parent, 0, name, label, descr)
638 {
639 }
640              
641 bool
642 PhonesSrc::setValue(int v)
643 {
644     unsigned int val;
645     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for phones destination to %d\n", v);
646
647     /* Currently destination values between 0 and 0x0b are accepted.
648      * Ultimately this will be device (and device configuration) dependent.
649      */
650     val = v;
651     if (val<0 || val>0x0b)
652       val = 0;
653     // Destination is given by bits 3-0.
654     // Bit 24 indicates that the phones source is being set.
655     val |= 0x01000000;
656     m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
657
658     return true;
659 }
660
661 int
662 PhonesSrc::getValue()
663 {
664     unsigned int val;
665     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for phones destination\n");
666
667     // FIXME: we could just read the appropriate mixer status field from the
668     // receive stream processor once we work out an efficient way to do this.
669     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
670     return val & 0x0f;
671 }
672
673 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg)
674 : MotuDiscreteCtrl(parent, dev_reg)
675 {
676 }
677
678 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg,
679              std::string name, std::string label, std::string descr)
680 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
681 {
682 }
683              
684 bool
685 OpticalMode::setValue(int v)
686 {
687     unsigned int val;
688     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for optical mode %d to %d\n", m_register, v);
689
690     // Need to get current optical modes so we can preserve the one we're
691     // not setting.  Input mode is in bits 9-8, output is in bits 11-10.
692     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF) & 0x00000f00;
693
694     // Set mode as requested.  An invalid setting is effectively ignored.
695     if (v>=0 && v<=3) {
696       if (m_register == MOTU_CTRL_DIR_IN) {
697         val = (val & ~0x0300) | ((v & 0x03) << 8);
698       } else {
699         val = (val & ~0x0c00) | ((v & 0x03) << 10);
700       }
701     }
702     // Bit 25 indicates that optical modes are being set
703     val |= 0x02000000;
704     m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
705
706     return true;
707 }
708
709 int
710 OpticalMode::getValue()
711 {
712     unsigned int val;
713     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for optical mode %d\n", m_register);
714
715     // FIXME: we could just read the appropriate mixer status field from the
716     // receive stream processor once we work out an efficient way to do this.
717     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
718     if (m_register == MOTU_CTRL_DIR_IN)
719       val = (val >> 8) & 0x03;
720     else
721       val = (val >> 10) & 0x03;
722     return val;
723 }
724
725 InputGainPadInv::InputGainPadInv(MotuDevice &parent, unsigned int channel, unsigned int mode)
726 : MotuDiscreteCtrl(parent, channel)
727 {
728     m_mode = mode;
729     validate();
730 }
731
732 InputGainPadInv::InputGainPadInv(MotuDevice &parent, unsigned int channel, unsigned int mode,
733              std::string name, std::string label, std::string descr)
734 : MotuDiscreteCtrl(parent, channel, name, label, descr)
735 {
736     m_mode = mode;
737     validate();
738 }
739
740 void InputGainPadInv::validate(void) {
741     if ((m_mode==MOTU_CTRL_MODE_PAD || m_mode==MOTU_CTRL_MODE_TRIMGAIN) &&
742         m_register>MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL) {
743         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid channel %d: max supported is %d, assuming 0\n",
744             m_register, MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL);
745         m_register = 0;
746     }
747     if ((m_mode==MOTU_CTRL_MODE_UL_GAIN || m_mode==MOTU_CTRL_MODE_PHASE_INV) &&
748         m_register>MOTU_CTRL_GAINPHASEINV_MAX_CHANNEL) {
749         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid ultralite channel %d: max supported is %d, assuming 0\n",
750             m_register, MOTU_CTRL_GAINPHASEINV_MAX_CHANNEL);
751         m_register = 0;
752     }
753     if (m_mode!=MOTU_CTRL_MODE_PAD && m_mode!=MOTU_CTRL_MODE_TRIMGAIN &&
754         m_mode!=MOTU_CTRL_MODE_UL_GAIN && m_mode!=MOTU_CTRL_MODE_PHASE_INV) {
755         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid mode %d, assuming %d\n", m_mode, MOTU_CTRL_MODE_PAD);
756         m_mode = MOTU_CTRL_MODE_PAD;
757     }
758 }
759
760 unsigned int InputGainPadInv::dev_register(void) {
761     /* Work out the device register to use for the associated channel */
762     /* Registers for gain/phase inversion controls on the Ultralite differ from those
763      * of other devices.
764      */
765     if (m_mode==MOTU_CTRL_MODE_PAD || m_mode==MOTU_CTRL_MODE_TRIMGAIN) {
766        if (m_register>=0 && m_register<=3) {
767           return MOTU_REG_INPUT_GAIN_PAD_0;     
768        } else {
769           debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported channel %d\n", m_register);
770        }
771     } else {
772        if (m_register>=0 && m_register<=3)
773           return MOTU_REG_INPUT_GAIN_PHINV0;
774        else if (m_register>=4 && m_register<=7)
775           return MOTU_REG_INPUT_GAIN_PHINV1;
776        else if (m_register>=8 && m_register<=11)
777           return MOTU_REG_INPUT_GAIN_PHINV2;
778        else {
779           debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported ultralite channel %d\n", m_register);
780        }
781     }
782     return 0;
783 }
784              
785 bool
786 InputGainPadInv::setValue(int v)
787 {
788     unsigned int val;
789     unsigned int reg, reg_shift;
790     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mode %d input pad/trim %d to %d\n", m_mode, m_register, v);
791
792     if (m_register == MOTU_CTRL_NONE) {
793         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
794         return true;
795     }
796
797     reg = dev_register();
798     if (reg == 0)
799         return false;
800     reg_shift = (m_register & 0x03) * 8;
801
802     // Need to get current gain trim / pad value so we can preserve one
803     // while setting the other.  The pad status is in bit 6 of the channel's
804     // respective byte with the trim in bits 0-5.  Bit 7 is the write enable
805     // bit for the channel.
806     val = m_parent.ReadRegister(reg) & (0xff << reg_shift);
807
808     switch (m_mode) {
809         case MOTU_CTRL_MODE_PAD:
810         case MOTU_CTRL_MODE_PHASE_INV:
811             // Set pad/phase inversion bit (bit 6 of relevant channel's byte)
812             if (v == 0) {
813                 val &= ~(0x40 << reg_shift);
814             } else {
815                 val |= (0x40 << reg_shift);
816             }
817             break;
818       case MOTU_CTRL_MODE_TRIMGAIN:
819       case MOTU_CTRL_MODE_UL_GAIN:
820             // Set the gain trim (bits 0-5 of the channel's byte).  Maximum
821             // gain is 53 dB for trimgain on non-ultralite devices.  For
822             // ultralites, mic inputs max out at 0x18, line inputs at 0x12
823             // and spdif inputs at 0x0c.  We just clip at 0x18 for now.
824             if (m_mode==MOTU_CTRL_MODE_TRIMGAIN) {
825                if (v > 0x35)
826                   v = 0x35;
827             } else {
828                if (v > 0x18)
829                   v = 0x18;
830             }
831             val = (val & ~(0x3f << reg_shift)) | (v << reg_shift);
832             break;
833       default:
834         debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
835         return false;
836     }
837
838     // Set the channel's write enable bit
839     val |= (0x80 << reg_shift);
840
841     m_parent.WriteRegister(reg, val);
842
843     return true;
844 }
845
846 int
847 InputGainPadInv::getValue()
848 {
849     unsigned int val;
850     unsigned int reg, reg_shift;
851     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mode %d input pad/trim %d\n", m_mode, m_register);
852
853     if (m_register == MOTU_CTRL_NONE) {
854         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
855         return 0;
856     }
857
858     reg = dev_register();
859     if (reg == 0)
860         return false;
861     reg_shift = (m_register & 0x03) * 8;
862
863     // The pad/phase inversion status is in bit 6 of the channel's
864     // respective byte with the trim in bits 0-5.  Bit 7 is the write enable
865     // bit for the channel.
866     val = m_parent.ReadRegister(reg);
867
868     switch (m_mode) {
869        case MOTU_CTRL_MODE_PAD:
870        case MOTU_CTRL_MODE_PHASE_INV:
871           val = ((val >> reg_shift) & 0x40) != 0;
872           break;
873        case MOTU_CTRL_MODE_TRIMGAIN:
874        case MOTU_CTRL_MODE_UL_GAIN:
875           val = ((val >> reg_shift) & 0x3f);
876           break;
877        default:
878           debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
879           return 0;
880     }
881
882     return val;
883 }
884
885 MeterControl::MeterControl(MotuDevice &parent, unsigned int ctrl_mask, unsigned int ctrl_shift)
886 : MotuDiscreteCtrl(parent, ctrl_mask)
887 {
888     m_shift = ctrl_shift;
889     validate();
890 }
891
892 MeterControl::MeterControl(MotuDevice &parent, unsigned int ctrl_mask, unsigned int ctrl_shift,
893              std::string name, std::string label, std::string descr)
894 : MotuDiscreteCtrl(parent, ctrl_mask, name, label, descr)
895 {
896     m_shift = ctrl_shift;
897     validate();
898 }
899
900 void MeterControl::validate(void) {
901     if ((m_register & (1<< m_shift)) == 0) {
902         debugOutput(DEBUG_LEVEL_VERBOSE, "Inconsistent mask/shift: 0x%08x/%d\n", m_register, m_shift);
903     }
904 }
905
906 bool
907 MeterControl::setValue(int v)
908 {
909     unsigned int val;
910     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for meter control 0x%08x/%d: %d\n",
911         m_register, m_shift, v);
912
913     // Need to get current register setting so we can preserve the parts not
914     // being controlled by this object.  m_register holds the mask for the
915     // parts we're changing.
916     val = m_parent.ReadRegister(MOTU_REG_896HD_METER_CONF) & ~m_register;
917     val |= (v << m_shift) & m_register;
918
919     m_parent.WriteRegister(MOTU_REG_896HD_METER_CONF, val);
920
921     // Drivers under other OSes set MOTU_REG_896HD_METER_REG (0x0b1c) to
922     // 0x0400 whenever MOTU_REG_896HD_METER_CONF (0x0b24) is changed.
923     // There's no obvious reason why they do this, but since it's no hassle
924     // we might as well do the same.
925     m_parent.WriteRegister(MOTU_REG_896HD_METER_REG, 0x0400);
926
927     return true;
928 }
929
930 int
931 MeterControl::getValue()
932 {
933     unsigned int val;
934     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for meter control 0x%08x/%d\n",
935         m_register, m_shift);
936
937     // m_register holds the mask of the part of interest
938     val = (m_parent.ReadRegister(MOTU_REG_896HD_METER_CONF) & m_register) >> m_shift;
939
940     return val;
941 }
942
943 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype)
944 : MotuDiscreteCtrl(parent, infotype)
945 {
946 }
947
948 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype,
949              std::string name, std::string label, std::string descr)
950 : MotuDiscreteCtrl(parent, infotype, name, label, descr)
951 {
952 }
953              
954 bool
955 InfoElement::setValue(int v)
956 {
957     /* This is a read-only field, so any call to setValue() is technically
958      * an error.
959      */
960     debugOutput(DEBUG_LEVEL_VERBOSE, "InfoElement (%d) is read-only\n", m_register);
961     return false;
962 }
963
964 int
965 InfoElement::getValue()
966 {
967     unsigned int val;
968     signed int res = 0;
969
970     switch (m_register) {
971         case MOTU_INFO_MODEL:
972             res = m_parent.m_motu_model;
973             debugOutput(DEBUG_LEVEL_VERBOSE, "Model: %d\n", res);
974             break;
975         case MOTU_INFO_IS_STREAMING:
976             val = m_parent.ReadRegister(MOTU_REG_ISOCTRL);
977             /* Streaming is active if either bit 22 (Motu->PC streaming
978              * enable) or bit 30 (PC->Motu streaming enable) is set.
979              */
980             res = (val & 0x40400000) != 0;
981             debugOutput(DEBUG_LEVEL_VERBOSE, "IsStreaming: %d (reg=%08x)\n", res, val);
982             break;
983         case MOTU_INFO_SAMPLE_RATE:
984             res = m_parent.getSamplingFrequency();
985             debugOutput(DEBUG_LEVEL_VERBOSE, "SampleRate: %d\n", res);
986             break;
987     }
988     return res;
989 }
990
991 }
Note: See TracBrowser for help on using the browser.