root/branches/libffado-2.0/src/motu/motu_controls.cpp

Revision 1418, 29.6 kB (checked in by jwoithe, 15 years ago)

MOTU: tidy up internal port management code. There should be no user-visible changes as a result of this - please report any regressions.

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(&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 InputGainPad::InputGainPad(MotuDevice &parent, unsigned int channel, unsigned int mode)
726 : MotuDiscreteCtrl(parent, channel)
727 {
728     m_mode = mode;
729     validate();
730 }
731
732 InputGainPad::InputGainPad(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 InputGainPad::validate(void) {
741     if (m_register > MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL) {
742         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid channel %d: max supported is %d, assuming 0\n",
743             m_register, MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL);
744         m_register = 0;
745     }
746     if (m_mode!=MOTU_CTRL_MODE_PAD && m_mode!=MOTU_CTRL_MODE_TRIMGAIN) {
747         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid mode %d, assuming %d\n", m_mode, MOTU_CTRL_MODE_PAD);
748         m_mode = MOTU_CTRL_MODE_PAD;
749     }
750 }
751
752 unsigned int InputGainPad::dev_register(void) {
753     /* Work out the device register to use for the associated channel */
754     if (m_register>=0 && m_register<=3) {
755       return MOTU_REG_INPUT_GAIN_PAD_0;     
756     } else {
757       debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported channel %d\n", m_register);
758     }
759     return 0;
760 }
761              
762 bool
763 InputGainPad::setValue(int v)
764 {
765     unsigned int val;
766     unsigned int reg, reg_shift;
767     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mode %d input pad/trim %d to %d\n", m_mode, m_register, v);
768
769     if (m_register == MOTU_CTRL_NONE) {
770         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
771         return true;
772     }
773
774     reg = dev_register();
775     if (reg == 0)
776         return false;
777     reg_shift = (m_register & 0x03) * 8;
778
779     // Need to get current gain trim / pad value so we can preserve one
780     // while setting the other.  The pad status is in bit 6 of the channel's
781     // respective byte with the trim in bits 0-5.  Bit 7 is the write enable
782     // bit for the channel.
783     val = m_parent.ReadRegister(reg) & (0xff << reg_shift);
784
785     switch (m_mode) {
786         case MOTU_CTRL_MODE_PAD:
787             // Set pad bit (bit 6 of relevant channel's byte)
788             if (v == 0) {
789                 val &= ~(0x40 << reg_shift);
790             } else {
791                 val |= (0x40 << reg_shift);
792             }
793             break;
794       case MOTU_CTRL_MODE_TRIMGAIN:
795             // Set the gain trim (bits 0-5 of the channel's byte).  Maximum
796             // gain is 53 dB.
797             if (v > 0x35)
798                 v = 0x35;
799             val = (val & ~(0x3f << reg_shift)) | (v << reg_shift);
800             break;
801       default:
802         debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
803         return false;
804     }
805
806     // Set the channel's write enable bit
807     val |= (0x80 << reg_shift);
808
809     m_parent.WriteRegister(reg, val);
810
811     return true;
812 }
813
814 int
815 InputGainPad::getValue()
816 {
817     unsigned int val;
818     unsigned int reg, reg_shift;
819     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mode %d input pad/trim %d\n", m_mode, m_register);
820
821     if (m_register == MOTU_CTRL_NONE) {
822         debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
823         return 0;
824     }
825
826     reg = dev_register();
827     if (reg == 0)
828         return false;
829     reg_shift = (m_register & 0x03) * 8;
830
831     // The pad status is in bit 6 of the channel's respective byte with the
832     // trim in bits 0-5.  Bit 7 is the write enable bit for the channel.
833     val = m_parent.ReadRegister(reg);
834
835     switch (m_mode) {
836         case MOTU_CTRL_MODE_PAD:
837             val = ((val >> reg_shift) & 0x40) != 0;
838             break;
839       case MOTU_CTRL_MODE_TRIMGAIN:
840             val = ((val >> reg_shift) & 0x3f);
841             break;
842       default:
843         debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
844         return 0;
845     }
846
847     return val;
848 }
849
850 MeterControl::MeterControl(MotuDevice &parent, unsigned int ctrl_mask, unsigned int ctrl_shift)
851 : MotuDiscreteCtrl(parent, ctrl_mask)
852 {
853     m_shift = ctrl_shift;
854     validate();
855 }
856
857 MeterControl::MeterControl(MotuDevice &parent, unsigned int ctrl_mask, unsigned int ctrl_shift,
858              std::string name, std::string label, std::string descr)
859 : MotuDiscreteCtrl(parent, ctrl_mask, name, label, descr)
860 {
861     m_shift = ctrl_shift;
862     validate();
863 }
864
865 void MeterControl::validate(void) {
866     if (m_register & (1<< m_shift) == 0) {
867         debugOutput(DEBUG_LEVEL_VERBOSE, "Inconsistent mask/shift: 0x%08x/%d\n", m_register, m_shift);
868     }
869 }
870
871 bool
872 MeterControl::setValue(int v)
873 {
874     unsigned int val;
875     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for meter control 0x%08x/%d: %d\n",
876         m_register, m_shift, v);
877
878     // Need to get current register setting so we can preserve the parts not
879     // being controlled by this object.  m_register holds the mask for the
880     // parts we're changing.
881     val = m_parent.ReadRegister(MOTU_REG_896HD_METER_CONF) & ~m_register;
882     val |= (v << m_shift) & m_register;
883
884     m_parent.WriteRegister(MOTU_REG_896HD_METER_CONF, val);
885
886     // Drivers under other OSes set MOTU_REG_896HD_METER_REG (0x0b1c) to
887     // 0x0400 whenever MOTU_REG_896HD_METER_CONF (0x0b24) is changed.
888     // There's no obvious reason why they do this, but since it's no hassle
889     // we might as well do the same.
890     m_parent.WriteRegister(MOTU_REG_896HD_METER_REG, 0x0400);
891
892     return true;
893 }
894
895 int
896 MeterControl::getValue()
897 {
898     unsigned int val;
899     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for meter control 0x%08x/%d\n",
900         m_register, m_shift);
901
902     // m_register holds the mask of the part of interest
903     val = (m_parent.ReadRegister(MOTU_REG_896HD_METER_CONF) & m_register) >> m_shift;
904
905     return val;
906 }
907
908 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype)
909 : MotuDiscreteCtrl(parent, infotype)
910 {
911 }
912
913 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype,
914              std::string name, std::string label, std::string descr)
915 : MotuDiscreteCtrl(parent, infotype, name, label, descr)
916 {
917 }
918              
919 bool
920 InfoElement::setValue(int v)
921 {
922     /* This is a read-only field, so any call to setValue() is technically
923      * an error.
924      */
925     debugOutput(DEBUG_LEVEL_VERBOSE, "InfoElement (%d) is read-only\n", m_register);
926     return false;
927 }
928
929 int
930 InfoElement::getValue()
931 {
932     unsigned int val;
933     signed int res = 0;
934
935     switch (m_register) {
936         case MOTU_INFO_MODEL:
937             res = m_parent.m_motu_model;
938             debugOutput(DEBUG_LEVEL_VERBOSE, "Model: %d\n", res);
939             break;
940         case MOTU_INFO_IS_STREAMING:
941             val = m_parent.ReadRegister(MOTU_REG_ISOCTRL);
942             /* Streaming is active if either bit 22 (Motu->PC streaming
943              * enable) or bit 30 (PC->Motu streaming enable) is set.
944              */
945             res = (val & 0x40400000) != 0;
946             debugOutput(DEBUG_LEVEL_VERBOSE, "IsStreaming: %d (reg=%08x)\n", res, val);
947             break;
948         case MOTU_INFO_SAMPLE_RATE:
949             res = m_parent.getSamplingFrequency();
950             debugOutput(DEBUG_LEVEL_VERBOSE, "SampleRate: %d\n", res);
951             break;
952         case MOTU_INFO_HAS_MIC_INPUTS:
953             /* Only the 828Mk2 has separate mic inputs.  In time this may be
954              * deduced by walking the port info array within the parent.
955              */
956             res = m_parent.m_motu_model == MOTU_MODEL_828mkII ? 1:0;
957             debugOutput(DEBUG_LEVEL_VERBOSE, "Has mic inputs: %d\n", res);
958             break;
959         case MOTU_INFO_HAS_AESEBU_INPUTS:
960             /* AES/EBU inputs are currently present on the Traveler and
961              * 896HD.  In time this may be deduced by walking the port info
962              * array within the parent.
963              */
964             val = m_parent.m_motu_model;
965             res = (val==MOTU_MODEL_TRAVELER || val==MOTU_MODEL_896HD);
966             debugOutput(DEBUG_LEVEL_VERBOSE, "HasAESEBUInputs: %d\n", res);
967             break;
968         case MOTU_INFO_HAS_SPDIF_INPUTS:
969             /* SPDIF inputs are present on all supported models except the
970              * 896HD and the 8pre.  In time this may be deduced by walking
971              * the port info array within the parent.
972              */
973             val = m_parent.m_motu_model;
974             res = (val!=MOTU_MODEL_8PRE && val!=MOTU_MODEL_896HD);
975             debugOutput(DEBUG_LEVEL_VERBOSE, "HasSPDIFInputs: %d\n", res);
976             break;
977         case MOTU_INFO_HAS_OPTICAL_SPDIF:
978             /* THe 896HD doesn't have optical SPDIF capability */
979             val = m_parent.m_motu_model;
980             res = (val != MOTU_MODEL_896HD);
981             debugOutput(DEBUG_LEVEL_VERBOSE, "HasOpticalSPDIF: %d\n", res);
982             break;
983     }
984     return res;
985 }
986
987 }
Note: See TracBrowser for help on using the browser.