Clean up compiler warnings when compiling on 64-bit systems. These are mostly fixing...
[ffado.git] / libffado / src / motu / motu_controls.cpp
blob2bf502cc63b96b77459e6c3c598834e39372fd19
1 /*
2 * Copyright (C) 2005-2008 by Pieter Palmers
3 * Copyright (C) 2008-2009 by Jonathan Woithe
5 * This file is part of FFADO
6 * FFADO = Free Firewire (pro-)audio drivers for linux
8 * FFADO is based upon FreeBoB.
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.
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.
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/>.
25 // This also includes motu_controls.h
26 #include "motu_avdevice.h"
28 namespace Motu {
30 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg)
31 : Control::Discrete(&parent)
32 , m_parent(parent)
33 , m_register(dev_reg)
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)
43 setName(name);
44 setLabel(label);
45 setDescription(descr);
48 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
49 unsigned int val_mask, unsigned int setenable_mask)
50 : MotuDiscreteCtrl(parent, dev_reg)
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.
56 m_setenable_mask = setenable_mask;
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)
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.
68 m_setenable_mask = setenable_mask;
71 bool
72 MotuBinarySwitch::setValue(int v)
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);
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;
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;
98 m_parent.WriteRegister(m_register, val);
100 return true;
104 MotuBinarySwitch::getValue()
106 unsigned int val;
107 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for switch %s (0x%04x)\n",
108 getName().c_str(), m_register);
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;
115 val = m_parent.ReadRegister(m_register);
116 return (val & m_value_mask) != 0;
119 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg)
120 : MotuDiscreteCtrl(parent, dev_reg)
124 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg,
125 std::string name, std::string label, std::string descr)
126 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
130 bool
131 ChannelFader::setValue(int v)
133 unsigned int val;
134 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel fader 0x%04x to %d\n", m_register, v);
136 if (m_register == MOTU_CTRL_NONE) {
137 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
138 return true;
141 val = v<0?0:v;
142 if (val > 0x80)
143 val = 0x80;
144 // Bit 30 indicates that the channel fader is being set
145 val |= 0x40000000;
146 m_parent.WriteRegister(m_register, val);
148 return true;
152 ChannelFader::getValue()
154 unsigned int val;
155 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel fader 0x%04x\n", m_register);
157 // Silently swallow attempts to read non-existent controls for now
158 if (m_register == MOTU_CTRL_NONE) {
159 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
160 return 0;
163 val = m_parent.ReadRegister(m_register);
164 return val & 0xff;
167 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg)
168 : MotuDiscreteCtrl(parent, dev_reg)
172 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg,
173 std::string name, std::string label, std::string descr)
174 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
178 bool
179 ChannelPan::setValue(int v)
181 unsigned int val;
182 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel pan 0x%04x to %d\n", m_register, v);
184 if (m_register == MOTU_CTRL_NONE) {
185 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
186 return true;
189 val = ((v<-64?-64:v)+64) & 0xff;
190 if (val > 0x80)
191 val = 0x80;
192 // Bit 31 indicates that pan is being set
193 val = (val << 8) | 0x80000000;
194 m_parent.WriteRegister(m_register, val);
196 return true;
200 ChannelPan::getValue()
202 unsigned int val;
203 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel pan 0x%04x\n", m_register);
205 // Silently swallow attempts to read non-existent controls for now
206 if (m_register == MOTU_CTRL_NONE) {
207 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
208 return 0;
211 val = m_parent.ReadRegister(m_register);
212 return ((val >> 8) & 0xff) - 0x40;
216 MotuMatrixMixer::MotuMatrixMixer(MotuDevice &parent)
217 : Control::MatrixMixer(&parent, "MatrixMixer")
218 , m_parent(parent)
222 MotuMatrixMixer::MotuMatrixMixer(MotuDevice &parent, std::string name)
223 : Control::MatrixMixer(&parent, name)
224 , m_parent(parent)
228 void MotuMatrixMixer::addRowInfo(std::string name, unsigned int flags,
229 unsigned int address)
231 struct sSignalInfo s;
232 s.name = name;
233 s.flags = flags;
234 s.address = address;
235 m_RowInfo.push_back(s);
238 void MotuMatrixMixer::addColInfo(std::string name, unsigned int flags,
239 unsigned int address)
241 struct sSignalInfo s;
242 s.name = name;
243 s.flags = flags;
244 s.address = address;
245 m_ColInfo.push_back(s);
248 uint32_t MotuMatrixMixer::getCellRegister(const unsigned int row, const unsigned int col)
250 if (m_RowInfo.at(row).address==MOTU_CTRL_NONE ||
251 m_ColInfo.at(col).address==MOTU_CTRL_NONE)
252 return MOTU_CTRL_NONE;
253 return m_RowInfo.at(row).address + m_ColInfo.at(col).address;
256 void MotuMatrixMixer::show()
258 debugOutput(DEBUG_LEVEL_NORMAL, "MOTU matrix mixer\n");
261 std::string MotuMatrixMixer::getRowName(const int row)
263 return m_RowInfo.at(row).name;
266 std::string MotuMatrixMixer::getColName(const int col)
268 return m_ColInfo.at(col).name;
271 int MotuMatrixMixer::getRowCount()
273 return m_RowInfo.size();
276 int MotuMatrixMixer::getColCount()
278 return m_ColInfo.size();
281 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice &parent)
282 : MotuMatrixMixer(parent, "ChannelFaderMatrixMixer")
286 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice &parent, std::string name)
287 : MotuMatrixMixer(parent, name)
291 double ChannelFaderMatrixMixer::setValue(const int row, const int col, const double val)
293 uint32_t v, reg;
294 v = val<0?0:(uint32_t)val;
295 if (v > 0x80)
296 v = 0x80;
297 debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelFader setValue for row %d col %d to %lf (%d)\n",
298 row, col, val, v);
299 reg = getCellRegister(row,col);
301 // Silently swallow attempts to set non-existent controls for now
302 if (reg == MOTU_CTRL_NONE) {
303 debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
304 return true;
306 // Bit 30 indicates that the channel fader is being set
307 v |= 0x40000000;
308 m_parent.WriteRegister(reg, v);
310 return true;
313 double ChannelFaderMatrixMixer::getValue(const int row, const int col)
315 uint32_t val, reg;
316 reg = getCellRegister(row,col);
318 // Silently swallow attempts to read non-existent controls for now
319 if (reg == MOTU_CTRL_NONE) {
320 debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
321 return 0;
323 val = m_parent.ReadRegister(reg) & 0xff;
325 debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelFader getValue for row %d col %d = %u\n",
326 row, col, val);
327 return val;
330 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice &parent)
331 : MotuMatrixMixer(parent, "ChannelPanMatrixMixer")
335 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice &parent, std::string name)
336 : MotuMatrixMixer(parent, name)
340 double ChannelPanMatrixMixer::setValue(const int row, const int col, const double val)
342 uint32_t v, reg;
343 v = ((val<-64?-64:(int32_t)val)+64) & 0xff;
344 if (v > 0x80)
345 v = 0x80;
347 debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelPan setValue for row %d col %d to %lf (%d)\n",
348 row, col, val, v);
349 reg = getCellRegister(row,col);
351 // Silently swallow attempts to set non-existent controls for now
352 if (reg == MOTU_CTRL_NONE) {
353 debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
354 return true;
357 // Bit 31 indicates that pan is being set
358 v = (v << 8) | 0x80000000;
359 m_parent.WriteRegister(reg, v);
361 return true;
364 double ChannelPanMatrixMixer::getValue(const int row, const int col)
366 int32_t val;
367 uint32_t reg;
368 reg = getCellRegister(row,col);
370 // Silently swallow attempts to read non-existent controls for now
371 if (reg == MOTU_CTRL_NONE) {
372 debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
373 return 0;
376 val = m_parent.ReadRegister(reg);
377 val = ((val >> 8) & 0xff) - 0x40;
379 debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelPan getValue for row %d col %d = %u\n",
380 row, col, val);
381 return val;
384 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice &parent)
385 : MotuMatrixMixer(parent, "ChannelPanMatrixMixer")
386 , m_value_mask(0)
387 , m_setenable_mask(0)
391 /* If no "write enable" is implemented for a given switch it's safe to
392 * pass zero in to setenable_mask.
394 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice &parent, std::string name,
395 unsigned int val_mask, unsigned int setenable_mask)
396 : MotuMatrixMixer(parent, name)
397 , m_value_mask(val_mask)
398 , m_setenable_mask(setenable_mask)
402 double ChannelBinSwMatrixMixer::setValue(const int row, const int col, const double val)
404 uint32_t v, reg;
406 debugOutput(DEBUG_LEVEL_VERBOSE, "BinSw setValue for row %d col %d to %lf (%d)\n",
407 row, col, val, val==0?0:1);
408 reg = getCellRegister(row,col);
410 // Silently swallow attempts to set non-existent controls for now
411 if (reg == MOTU_CTRL_NONE) {
412 debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
413 return true;
416 // Set the value
417 if (m_setenable_mask) {
418 v = (val==0)?0:m_value_mask;
419 // Set the "write enable" bit for the value being set
420 v |= m_setenable_mask;
421 } else {
422 // It would be good to utilise the cached value from the receive
423 // processor (if running) later on. For now we'll just fetch the
424 // current register value directly when needed.
425 v = m_parent.ReadRegister(reg);
426 if (v==0)
427 v &= ~m_value_mask;
428 else
429 v |= m_value_mask;
431 m_parent.WriteRegister(reg, v);
433 return true;
436 double ChannelBinSwMatrixMixer::getValue(const int row, const int col)
438 uint32_t val, reg;
439 reg = getCellRegister(row,col);
441 // Silently swallow attempts to read non-existent controls for now
442 if (reg == MOTU_CTRL_NONE) {
443 debugOutput(DEBUG_LEVEL_VERBOSE, "ignoring control marked as non-existent\n");
444 return 0;
447 val = m_parent.ReadRegister(reg);
448 val = (val & m_value_mask) != 0;
450 debugOutput(DEBUG_LEVEL_VERBOSE, "BinSw getValue for row %d col %d = %u\n",
451 row, col, val);
452 return val;
456 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg)
457 : MotuDiscreteCtrl(parent, dev_reg)
461 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg,
462 std::string name, std::string label, std::string descr)
463 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
467 bool
468 MixFader::setValue(int v)
470 unsigned int val;
471 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix fader 0x%04x to %d\n", m_register, v);
473 // Silently swallow attempts to set non-existent controls for now
474 if (m_register == MOTU_CTRL_NONE) {
475 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
476 return true;
478 val = v<0?0:v;
479 if (val > 0x80)
480 val = 0x80;
481 // Bit 24 indicates that the mix fader is being set
482 val |= 0x01000000;
483 m_parent.WriteRegister(m_register, val);
485 return true;
489 MixFader::getValue()
491 unsigned int val;
492 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix fader 0x%04x\n", m_register);
494 // Silently swallow attempts to read non-existent controls for now
495 if (m_register == MOTU_CTRL_NONE) {
496 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
497 return 0;
500 val = m_parent.ReadRegister(m_register);
501 return val & 0xff;
504 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg)
505 : MotuDiscreteCtrl(parent, dev_reg)
509 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg,
510 std::string name, std::string label, std::string descr)
511 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
515 bool
516 MixMute::setValue(int v)
518 unsigned int val, dest;
519 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix mute 0x%04x to %d\n", m_register, v);
521 // Silently swallow attempts to set non-existent controls for now
522 if (m_register == MOTU_CTRL_NONE) {
523 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
524 return true;
527 // Need to read current destination so we can preserve that when setting
528 // mute status (mute and destination are always set together).
529 dest = m_parent.ReadRegister(m_register) & 0x00000f00;
530 // Mute status is bit 12
531 val = (v==0)?0:0x00001000;
532 // Bit 25 indicates that mute and destination are being set. Also
533 // preserve the current destination.
534 val |= 0x02000000 | dest;
535 m_parent.WriteRegister(m_register, val);
537 return true;
541 MixMute::getValue()
543 unsigned int val;
544 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix mute 0x%04x\n", m_register);
546 // Silently swallow attempts to read non-existent controls for now
547 if (m_register == MOTU_CTRL_NONE) {
548 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
549 return 0;
552 val = m_parent.ReadRegister(m_register);
553 return (val & 0x00001000) != 0;
556 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg)
557 : MotuDiscreteCtrl(parent, dev_reg)
561 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg,
562 std::string name, std::string label, std::string descr)
563 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
567 bool
568 MixDest::setValue(int v)
570 unsigned int val, mute;
571 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix destination 0x%04x to %d\n", m_register, v);
573 // Silently swallow attempts to set non-existent controls for now
574 if (m_register == MOTU_CTRL_NONE) {
575 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
576 return true;
578 // Need to get current mute status so we can preserve it
579 mute = m_parent.ReadRegister(m_register) & 0x00001000;
580 val = v;
581 /* Currently destination values between 0 and 0x0b are accepted.
582 * Ultimately this will be device (and device configuration) dependent.
584 if (val<0 || val>0x0b)
585 val = 0;
586 /* Destination is given by bits 11-8. Add in the current mute status so
587 * it can be preserved (it's set concurrently with the destination).
589 val = (val << 8) | mute;
590 // Bit 25 indicates that mute and destination are being set
591 val |= 0x02000000;
592 m_parent.WriteRegister(m_register, val);
594 return true;
598 MixDest::getValue()
600 unsigned int val;
601 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix destination 0x%04x\n", m_register);
603 // Silently swallow attempts to read non-existent controls for now
604 if (m_register == MOTU_CTRL_NONE) {
605 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
606 return true;
608 val = m_parent.ReadRegister(m_register);
609 return (val >> 8) & 0x0f;
612 PhonesSrc::PhonesSrc(MotuDevice &parent)
613 : MotuDiscreteCtrl(parent, 0)
617 PhonesSrc::PhonesSrc(MotuDevice &parent,
618 std::string name, std::string label, std::string descr)
619 : MotuDiscreteCtrl(parent, 0, name, label, descr)
623 bool
624 PhonesSrc::setValue(int v)
626 unsigned int val;
627 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for phones destination to %d\n", v);
629 /* Currently destination values between 0 and 0x0b are accepted.
630 * Ultimately this will be device (and device configuration) dependent.
632 val = v;
633 if (val<0 || val>0x0b)
634 val = 0;
635 // Destination is given by bits 3-0.
636 // Bit 24 indicates that the phones source is being set.
637 val |= 0x01000000;
638 m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
640 return true;
644 PhonesSrc::getValue()
646 unsigned int val;
647 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for phones destination\n");
649 val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
650 return val & 0x0f;
653 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg)
654 : MotuDiscreteCtrl(parent, dev_reg)
658 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg,
659 std::string name, std::string label, std::string descr)
660 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
664 bool
665 OpticalMode::setValue(int v)
667 unsigned int val, dir;
668 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for optical mode %d to %d\n", m_register, v);
670 /* Assume v is 0 for "off", 1 for "ADAT" and 2 for "Toslink" */
671 switch (v) {
672 case 0: val = MOTU_OPTICAL_MODE_OFF; break;
673 case 1: val = MOTU_OPTICAL_MODE_ADAT; break;
674 case 2: val = MOTU_OPTICAL_MODE_TOSLINK; break;
675 default: return true;
677 dir = (m_register==MOTU_CTRL_DIR_IN)?MOTU_DIR_IN:MOTU_DIR_OUT;
678 m_parent.setOpticalMode(dir, val, MOTU_OPTICAL_MODE_KEEP);
679 return true;
683 OpticalMode::getValue()
685 unsigned int dir, omode_a;
686 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for optical mode %d\n", m_register);
688 dir = (m_register==MOTU_CTRL_DIR_IN)?MOTU_DIR_IN:MOTU_DIR_OUT;
689 m_parent.getOpticalMode(dir, &omode_a, NULL);
690 switch (omode_a) {
691 case MOTU_OPTICAL_MODE_OFF: return 0;
692 case MOTU_OPTICAL_MODE_ADAT: return 1;
693 case MOTU_OPTICAL_MODE_TOSLINK: return 2;
694 default: return 0;
696 return 0;
699 InputGainPadInv::InputGainPadInv(MotuDevice &parent, unsigned int channel, unsigned int mode)
700 : MotuDiscreteCtrl(parent, channel)
702 m_mode = mode;
703 validate();
706 InputGainPadInv::InputGainPadInv(MotuDevice &parent, unsigned int channel, unsigned int mode,
707 std::string name, std::string label, std::string descr)
708 : MotuDiscreteCtrl(parent, channel, name, label, descr)
710 m_mode = mode;
711 validate();
714 void InputGainPadInv::validate(void) {
715 if ((m_mode==MOTU_CTRL_MODE_PAD || m_mode==MOTU_CTRL_MODE_TRIMGAIN) &&
716 m_register>MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL) {
717 debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid channel %d: max supported is %d, assuming 0\n",
718 m_register, MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL);
719 m_register = 0;
721 if ((m_mode==MOTU_CTRL_MODE_UL_GAIN || m_mode==MOTU_CTRL_MODE_PHASE_INV) &&
722 m_register>MOTU_CTRL_GAINPHASEINV_MAX_CHANNEL) {
723 debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid ultralite channel %d: max supported is %d, assuming 0\n",
724 m_register, MOTU_CTRL_GAINPHASEINV_MAX_CHANNEL);
725 m_register = 0;
727 if (m_mode!=MOTU_CTRL_MODE_PAD && m_mode!=MOTU_CTRL_MODE_TRIMGAIN &&
728 m_mode!=MOTU_CTRL_MODE_UL_GAIN && m_mode!=MOTU_CTRL_MODE_PHASE_INV) {
729 debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid mode %d, assuming %d\n", m_mode, MOTU_CTRL_MODE_PAD);
730 m_mode = MOTU_CTRL_MODE_PAD;
734 unsigned int InputGainPadInv::dev_register(void) {
735 /* Work out the device register to use for the associated channel */
736 /* Registers for gain/phase inversion controls on the Ultralite differ from those
737 * of other devices.
739 if (m_mode==MOTU_CTRL_MODE_PAD || m_mode==MOTU_CTRL_MODE_TRIMGAIN) {
740 if (m_register>=0 && m_register<=3) {
741 return MOTU_REG_INPUT_GAIN_PAD_0;
742 } else {
743 debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported channel %d\n", m_register);
745 } else {
746 if (m_register>=0 && m_register<=3)
747 return MOTU_REG_INPUT_GAIN_PHINV0;
748 else if (m_register>=4 && m_register<=7)
749 return MOTU_REG_INPUT_GAIN_PHINV1;
750 else if (m_register>=8 && m_register<=11)
751 return MOTU_REG_INPUT_GAIN_PHINV2;
752 else {
753 debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported ultralite channel %d\n", m_register);
756 return 0;
759 bool
760 InputGainPadInv::setValue(int v)
762 unsigned int val;
763 unsigned int reg, reg_shift;
764 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mode %d input pad/trim %d to %d\n", m_mode, m_register, v);
766 if (m_register == MOTU_CTRL_NONE) {
767 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
768 return true;
771 reg = dev_register();
772 if (reg == 0)
773 return false;
774 reg_shift = (m_register & 0x03) * 8;
776 // Need to get current gain trim / pad value so we can preserve one
777 // while setting the other. The pad status is in bit 6 of the channel's
778 // respective byte with the trim in bits 0-5. Bit 7 is the write enable
779 // bit for the channel.
780 val = m_parent.ReadRegister(reg) & (0xff << reg_shift);
782 switch (m_mode) {
783 case MOTU_CTRL_MODE_PAD:
784 case MOTU_CTRL_MODE_PHASE_INV:
785 // Set pad/phase inversion bit (bit 6 of relevant channel's byte)
786 if (v == 0) {
787 val &= ~(0x40 << reg_shift);
788 } else {
789 val |= (0x40 << reg_shift);
791 break;
792 case MOTU_CTRL_MODE_TRIMGAIN:
793 case MOTU_CTRL_MODE_UL_GAIN:
794 // Set the gain trim (bits 0-5 of the channel's byte). Maximum
795 // gain is 53 dB for trimgain on non-ultralite devices. For
796 // ultralites, mic inputs max out at 0x18, line inputs at 0x12
797 // and spdif inputs at 0x0c. We just clip at 0x18 for now.
798 if (m_mode==MOTU_CTRL_MODE_TRIMGAIN) {
799 if (v > 0x35)
800 v = 0x35;
801 } else {
802 if (v > 0x18)
803 v = 0x18;
805 val = (val & ~(0x3f << reg_shift)) | (v << reg_shift);
806 break;
807 default:
808 debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
809 return false;
812 // Set the channel's write enable bit
813 val |= (0x80 << reg_shift);
815 m_parent.WriteRegister(reg, val);
817 return true;
821 InputGainPadInv::getValue()
823 unsigned int val;
824 unsigned int reg, reg_shift;
825 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mode %d input pad/trim %d\n", m_mode, m_register);
827 if (m_register == MOTU_CTRL_NONE) {
828 debugOutput(DEBUG_LEVEL_WARNING, "use of MOTU_CTRL_NONE in non-matrix control\n");
829 return 0;
832 reg = dev_register();
833 if (reg == 0)
834 return false;
835 reg_shift = (m_register & 0x03) * 8;
837 // The pad/phase inversion status is in bit 6 of the channel's
838 // respective byte with the trim in bits 0-5. Bit 7 is the write enable
839 // bit for the channel.
840 val = m_parent.ReadRegister(reg);
842 switch (m_mode) {
843 case MOTU_CTRL_MODE_PAD:
844 case MOTU_CTRL_MODE_PHASE_INV:
845 val = ((val >> reg_shift) & 0x40) != 0;
846 break;
847 case MOTU_CTRL_MODE_TRIMGAIN:
848 case MOTU_CTRL_MODE_UL_GAIN:
849 val = ((val >> reg_shift) & 0x3f);
850 break;
851 default:
852 debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
853 return 0;
856 return val;
859 MeterControl::MeterControl(MotuDevice &parent, unsigned int ctrl_mask, unsigned int ctrl_shift)
860 : MotuDiscreteCtrl(parent, ctrl_mask)
862 m_shift = ctrl_shift;
863 validate();
866 MeterControl::MeterControl(MotuDevice &parent, unsigned int ctrl_mask, unsigned int ctrl_shift,
867 std::string name, std::string label, std::string descr)
868 : MotuDiscreteCtrl(parent, ctrl_mask, name, label, descr)
870 m_shift = ctrl_shift;
871 validate();
874 void MeterControl::validate(void) {
875 if ((m_register & (1<< m_shift)) == 0) {
876 debugOutput(DEBUG_LEVEL_VERBOSE, "Inconsistent mask/shift: 0x%08x/%d\n", m_register, m_shift);
880 bool
881 MeterControl::setValue(int v)
883 unsigned int val;
884 debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for meter control 0x%08x/%d: %d\n",
885 m_register, m_shift, v);
887 // Need to get current register setting so we can preserve the parts not
888 // being controlled by this object. m_register holds the mask for the
889 // parts we're changing.
890 val = m_parent.ReadRegister(MOTU_REG_896HD_METER_CONF) & ~m_register;
891 val |= (v << m_shift) & m_register;
893 m_parent.WriteRegister(MOTU_REG_896HD_METER_CONF, val);
895 // Drivers under other OSes set MOTU_REG_896HD_METER_REG (0x0b1c) to
896 // 0x0400 whenever MOTU_REG_896HD_METER_CONF (0x0b24) is changed.
897 // There's no obvious reason why they do this, but since it's no hassle
898 // we might as well do the same.
899 m_parent.WriteRegister(MOTU_REG_896HD_METER_REG, 0x0400);
901 return true;
905 MeterControl::getValue()
907 unsigned int val;
908 debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for meter control 0x%08x/%d\n",
909 m_register, m_shift);
911 // m_register holds the mask of the part of interest
912 val = (m_parent.ReadRegister(MOTU_REG_896HD_METER_CONF) & m_register) >> m_shift;
914 return val;
917 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype)
918 : MotuDiscreteCtrl(parent, infotype)
922 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype,
923 std::string name, std::string label, std::string descr)
924 : MotuDiscreteCtrl(parent, infotype, name, label, descr)
928 bool
929 InfoElement::setValue(int v)
931 /* This is a read-only field, so any call to setValue() is technically
932 * an error.
934 debugOutput(DEBUG_LEVEL_VERBOSE, "InfoElement (%d) is read-only\n", m_register);
935 return false;
939 InfoElement::getValue()
941 unsigned int val;
942 signed int res = 0;
944 switch (m_register) {
945 case MOTU_INFO_MODEL:
946 res = m_parent.m_motu_model;
947 debugOutput(DEBUG_LEVEL_VERBOSE, "Model: %d\n", res);
948 break;
949 case MOTU_INFO_IS_STREAMING:
950 val = m_parent.ReadRegister(MOTU_REG_ISOCTRL);
951 /* Streaming is active if either bit 22 (Motu->PC streaming
952 * enable) or bit 30 (PC->Motu streaming enable) is set.
954 res = (val & 0x40400000) != 0;
955 debugOutput(DEBUG_LEVEL_VERBOSE, "IsStreaming: %d (reg=%08x)\n", res, val);
956 break;
957 case MOTU_INFO_SAMPLE_RATE:
958 res = m_parent.getSamplingFrequency();
959 debugOutput(DEBUG_LEVEL_VERBOSE, "SampleRate: %d\n", res);
960 break;
962 return res;