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"
30 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice
&parent
, unsigned int dev_reg
)
31 : Control::Discrete(&parent
)
37 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice
&parent
, unsigned int dev_reg
,
38 std::string name
, std::string label
, std::string descr
)
39 : Control::Discrete(&parent
)
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
;
72 MotuBinarySwitch::setValue(int v
)
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");
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
;
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
);
98 m_parent
.WriteRegister(m_register
, val
);
104 MotuBinarySwitch::getValue()
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");
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
)
131 ChannelFader::setValue(int v
)
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");
144 // Bit 30 indicates that the channel fader is being set
146 m_parent
.WriteRegister(m_register
, val
);
152 ChannelFader::getValue()
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");
163 val
= m_parent
.ReadRegister(m_register
);
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
)
179 ChannelPan::setValue(int v
)
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");
189 val
= ((v
<-64?-64:v
)+64) & 0xff;
192 // Bit 31 indicates that pan is being set
193 val
= (val
<< 8) | 0x80000000;
194 m_parent
.WriteRegister(m_register
, val
);
200 ChannelPan::getValue()
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");
211 val
= m_parent
.ReadRegister(m_register
);
212 return ((val
>> 8) & 0xff) - 0x40;
216 MotuMatrixMixer::MotuMatrixMixer(MotuDevice
&parent
)
217 : Control::MatrixMixer(&parent
, "MatrixMixer")
222 MotuMatrixMixer::MotuMatrixMixer(MotuDevice
&parent
, std::string name
)
223 : Control::MatrixMixer(&parent
, name
)
228 void MotuMatrixMixer::addRowInfo(std::string name
, unsigned int flags
,
229 unsigned int address
)
231 struct sSignalInfo s
;
235 m_RowInfo
.push_back(s
);
238 void MotuMatrixMixer::addColInfo(std::string name
, unsigned int flags
,
239 unsigned int address
)
241 struct sSignalInfo s
;
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
)
294 v
= val
<0?0:(uint32_t)val
;
297 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelFader setValue for row %d col %d to %lf (%d)\n",
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");
306 // Bit 30 indicates that the channel fader is being set
308 m_parent
.WriteRegister(reg
, v
);
313 double ChannelFaderMatrixMixer::getValue(const int row
, const int col
)
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");
323 val
= m_parent
.ReadRegister(reg
) & 0xff;
325 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelFader getValue for row %d col %d = %u\n",
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
)
343 v
= ((val
<-64?-64:(int32_t)val
)+64) & 0xff;
347 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelPan setValue for row %d col %d to %lf (%d)\n",
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");
357 // Bit 31 indicates that pan is being set
358 v
= (v
<< 8) | 0x80000000;
359 m_parent
.WriteRegister(reg
, v
);
364 double ChannelPanMatrixMixer::getValue(const int row
, const int col
)
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");
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",
384 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice
&parent
)
385 : MotuMatrixMixer(parent
, "ChannelPanMatrixMixer")
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
)
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");
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
;
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
);
431 m_parent
.WriteRegister(reg
, v
);
436 double ChannelBinSwMatrixMixer::getValue(const int row
, const int col
)
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");
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",
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
)
468 MixFader::setValue(int v
)
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");
481 // Bit 24 indicates that the mix fader is being set
483 m_parent
.WriteRegister(m_register
, 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");
500 val
= m_parent
.ReadRegister(m_register
);
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
)
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");
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
);
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");
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
)
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");
578 // Need to get current mute status so we can preserve it
579 mute
= m_parent
.ReadRegister(m_register
) & 0x00001000;
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)
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
592 m_parent
.WriteRegister(m_register
, 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");
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
)
624 PhonesSrc::setValue(int v
)
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.
633 if (val
<0 || val
>0x0b)
635 // Destination is given by bits 3-0.
636 // Bit 24 indicates that the phones source is being set.
638 m_parent
.WriteRegister(MOTU_REG_ROUTE_PORT_CONF
, val
);
644 PhonesSrc::getValue()
647 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for phones destination\n");
649 val
= m_parent
.ReadRegister(MOTU_REG_ROUTE_PORT_CONF
);
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
)
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" */
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
);
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
);
691 case MOTU_OPTICAL_MODE_OFF
: return 0;
692 case MOTU_OPTICAL_MODE_ADAT
: return 1;
693 case MOTU_OPTICAL_MODE_TOSLINK
: return 2;
699 InputGainPadInv::InputGainPadInv(MotuDevice
&parent
, unsigned int channel
, unsigned int mode
)
700 : MotuDiscreteCtrl(parent
, channel
)
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
)
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
);
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
);
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
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
;
743 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported channel %d\n", m_register
);
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
;
753 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported ultralite channel %d\n", m_register
);
760 InputGainPadInv::setValue(int v
)
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");
771 reg
= dev_register();
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
);
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)
787 val
&= ~(0x40 << reg_shift
);
789 val
|= (0x40 << reg_shift
);
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
) {
805 val
= (val
& ~(0x3f << reg_shift
)) | (v
<< reg_shift
);
808 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported mode %d\n", m_mode
);
812 // Set the channel's write enable bit
813 val
|= (0x80 << reg_shift
);
815 m_parent
.WriteRegister(reg
, val
);
821 InputGainPadInv::getValue()
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");
832 reg
= dev_register();
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
);
843 case MOTU_CTRL_MODE_PAD
:
844 case MOTU_CTRL_MODE_PHASE_INV
:
845 val
= ((val
>> reg_shift
) & 0x40) != 0;
847 case MOTU_CTRL_MODE_TRIMGAIN
:
848 case MOTU_CTRL_MODE_UL_GAIN
:
849 val
= ((val
>> reg_shift
) & 0x3f);
852 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported mode %d\n", m_mode
);
859 MeterControl::MeterControl(MotuDevice
&parent
, unsigned int ctrl_mask
, unsigned int ctrl_shift
)
860 : MotuDiscreteCtrl(parent
, ctrl_mask
)
862 m_shift
= ctrl_shift
;
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
;
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
);
881 MeterControl::setValue(int v
)
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);
905 MeterControl::getValue()
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
;
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
)
929 InfoElement::setValue(int v
)
931 /* This is a read-only field, so any call to setValue() is technically
934 debugOutput(DEBUG_LEVEL_VERBOSE
, "InfoElement (%d) is read-only\n", m_register
);
939 InfoElement::getValue()
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
);
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
);
957 case MOTU_INFO_SAMPLE_RATE
:
958 res
= m_parent
.getSamplingFrequency();
959 debugOutput(DEBUG_LEVEL_VERBOSE
, "SampleRate: %d\n", res
);