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 // 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;
121 ChannelFader::ChannelFader(MotuDevice
&parent
, unsigned int dev_reg
)
122 : MotuDiscreteCtrl(parent
, dev_reg
)
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
)
133 ChannelFader::setValue(int v
)
136 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for channel fader 0x%04x to %d\n", m_register
, v
);
138 if (m_register
== MOTU_CTRL_NONE
) {
139 debugOutput(DEBUG_LEVEL_WARNING
, "use of MOTU_CTRL_NONE in non-matrix control\n");
146 // Bit 30 indicates that the channel fader is being set
148 m_parent
.WriteRegister(m_register
, val
);
154 ChannelFader::getValue()
157 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for channel fader 0x%04x\n", m_register
);
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");
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
);
171 ChannelPan::ChannelPan(MotuDevice
&parent
, unsigned int dev_reg
)
172 : MotuDiscreteCtrl(parent
, dev_reg
)
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
)
183 ChannelPan::setValue(int v
)
186 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for channel pan 0x%04x to %d\n", m_register
, v
);
188 if (m_register
== MOTU_CTRL_NONE
) {
189 debugOutput(DEBUG_LEVEL_WARNING
, "use of MOTU_CTRL_NONE in non-matrix control\n");
193 val
= ((v
<-64?-64:v
)+64) & 0xff;
196 // Bit 31 indicates that pan is being set
197 val
= (val
<< 8) | 0x80000000;
198 m_parent
.WriteRegister(m_register
, val
);
204 ChannelPan::getValue()
207 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for channel pan 0x%04x\n", m_register
);
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");
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;
222 MotuMatrixMixer::MotuMatrixMixer(MotuDevice
&parent
)
223 : Control::MatrixMixer(&parent
, "MatrixMixer")
228 MotuMatrixMixer::MotuMatrixMixer(MotuDevice
&parent
, std::string name
)
229 : Control::MatrixMixer(&parent
, name
)
234 void MotuMatrixMixer::addRowInfo(std::string name
, unsigned int flags
,
235 unsigned int address
)
237 struct sSignalInfo s
;
241 m_RowInfo
.push_back(s
);
244 void MotuMatrixMixer::addColInfo(std::string name
, unsigned int flags
,
245 unsigned int address
)
247 struct sSignalInfo s
;
251 m_ColInfo
.push_back(s
);
254 uint32_t MotuMatrixMixer::getCellRegister(const unsigned int row
, const unsigned int col
)
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
;
262 void MotuMatrixMixer::show()
264 debugOutput(DEBUG_LEVEL_NORMAL
, "MOTU matrix mixer\n");
267 std::string
MotuMatrixMixer::getRowName(const int row
)
269 return m_RowInfo
.at(row
).name
;
272 std::string
MotuMatrixMixer::getColName(const int col
)
274 return m_ColInfo
.at(col
).name
;
277 int MotuMatrixMixer::getRowCount()
279 return m_RowInfo
.size();
282 int MotuMatrixMixer::getColCount()
284 return m_ColInfo
.size();
287 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice
&parent
)
288 : MotuMatrixMixer(parent
, "ChannelFaderMatrixMixer")
292 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice
&parent
, std::string name
)
293 : MotuMatrixMixer(parent
, name
)
297 double ChannelFaderMatrixMixer::setValue(const int row
, const int col
, const double val
)
300 v
= val
<0?0:(uint32_t)val
;
303 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelFader setValue for row %d col %d to %lf (%d)\n",
305 reg
= getCellRegister(row
,col
);
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");
312 // Bit 30 indicates that the channel fader is being set
314 m_parent
.WriteRegister(reg
, v
);
319 double ChannelFaderMatrixMixer::getValue(const int row
, const int col
)
322 reg
= getCellRegister(row
,col
);
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");
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;
333 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelFader getValue for row %d col %d = %u\n",
338 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice
&parent
)
339 : MotuMatrixMixer(parent
, "ChannelPanMatrixMixer")
343 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice
&parent
, std::string name
)
344 : MotuMatrixMixer(parent
, name
)
348 double ChannelPanMatrixMixer::setValue(const int row
, const int col
, const double val
)
351 v
= ((val
<-64?-64:(int32_t)val
)+64) & 0xff;
355 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelPan setValue for row %d col %d to %lf (%d)\n",
357 reg
= getCellRegister(row
,col
);
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");
365 // Bit 31 indicates that pan is being set
366 v
= (v
<< 8) | 0x80000000;
367 m_parent
.WriteRegister(reg
, v
);
372 double ChannelPanMatrixMixer::getValue(const int row
, const int col
)
376 reg
= getCellRegister(row
,col
);
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");
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;
389 debugOutput(DEBUG_LEVEL_VERBOSE
, "ChannelPan getValue for row %d col %d = %u\n",
394 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice
&parent
)
395 : MotuMatrixMixer(parent
, "ChannelPanMatrixMixer")
397 , m_setenable_mask(0)
401 /* If no "write enable" is implemented for a given switch it's safe to
402 * pass zero in to setenable_mask.
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
)
412 double ChannelBinSwMatrixMixer::setValue(const int row
, const int col
, const double val
)
416 debugOutput(DEBUG_LEVEL_VERBOSE
, "BinSw setValue for row %d col %d to %lf (%d)\n",
417 row
, col
, val
, val
==0?0:1);
418 reg
= getCellRegister(row
,col
);
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");
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
;
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
);
441 m_parent
.WriteRegister(reg
, v
);
446 double ChannelBinSwMatrixMixer::getValue(const int row
, const int col
)
449 reg
= getCellRegister(row
,col
);
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");
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;
462 debugOutput(DEBUG_LEVEL_VERBOSE
, "BinSw getValue for row %d col %d = %u\n",
468 MixFader::MixFader(MotuDevice
&parent
, unsigned int dev_reg
)
469 : MotuDiscreteCtrl(parent
, dev_reg
)
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
)
480 MixFader::setValue(int v
)
483 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for mix fader 0x%04x to %d\n", m_register
, v
);
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");
493 // Bit 24 indicates that the mix fader is being set
495 m_parent
.WriteRegister(m_register
, val
);
504 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for mix fader 0x%04x\n", m_register
);
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");
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
);
518 MixMute::MixMute(MotuDevice
&parent
, unsigned int dev_reg
)
519 : MotuDiscreteCtrl(parent
, dev_reg
)
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
)
530 MixMute::setValue(int v
)
532 unsigned int val
, dest
;
533 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for mix mute 0x%04x to %d\n", m_register
, v
);
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");
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
);
558 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for mix mute 0x%04x\n", m_register
);
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");
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;
572 MixDest::MixDest(MotuDevice
&parent
, unsigned int dev_reg
)
573 : MotuDiscreteCtrl(parent
, dev_reg
)
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
)
584 MixDest::setValue(int v
)
586 unsigned int val
, mute
;
587 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for mix destination 0x%04x to %d\n", m_register
, v
);
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");
594 // Need to get current mute status so we can preserve it
595 mute
= m_parent
.ReadRegister(m_register
) & 0x00001000;
597 /* Currently destination values between 0 and 0x0b are accepted.
598 * Ultimately this will be device (and device configuration) dependent.
600 if (val
<0 || val
>0x0b)
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).
605 val
= (val
<< 8) | mute
;
606 // Bit 25 indicates that mute and destination are being set
608 m_parent
.WriteRegister(m_register
, val
);
617 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for mix destination 0x%04x\n", m_register
);
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");
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;
630 PhonesSrc::PhonesSrc(MotuDevice
&parent
)
631 : MotuDiscreteCtrl(parent
, 0)
635 PhonesSrc::PhonesSrc(MotuDevice
&parent
,
636 std::string name
, std::string label
, std::string descr
)
637 : MotuDiscreteCtrl(parent
, 0, name
, label
, descr
)
642 PhonesSrc::setValue(int v
)
645 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for phones destination to %d\n", v
);
647 /* Currently destination values between 0 and 0x0b are accepted.
648 * Ultimately this will be device (and device configuration) dependent.
651 if (val
<0 || val
>0x0b)
653 // Destination is given by bits 3-0.
654 // Bit 24 indicates that the phones source is being set.
656 m_parent
.WriteRegister(MOTU_REG_ROUTE_PORT_CONF
, val
);
662 PhonesSrc::getValue()
665 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for phones destination\n");
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
);
673 OpticalMode::OpticalMode(MotuDevice
&parent
, unsigned int dev_reg
)
674 : MotuDiscreteCtrl(parent
, dev_reg
)
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
)
685 OpticalMode::setValue(int v
)
687 unsigned int val
, dir
;
688 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for optical mode %d to %d\n", m_register
, v
);
690 /* Assume v is 0 for "off", 1 for "ADAT" and 2 for "Toslink" */
692 case 0: val
= MOTU_OPTICAL_MODE_OFF
; break;
693 case 1: val
= MOTU_OPTICAL_MODE_ADAT
; break;
694 case 2: val
= MOTU_OPTICAL_MODE_TOSLINK
; break;
695 default: return true;
697 dir
= (m_register
==MOTU_CTRL_DIR_IN
)?MOTU_DIR_IN
:MOTU_DIR_OUT
;
698 m_parent
.setOpticalMode(dir
, val
, MOTU_OPTICAL_MODE_KEEP
);
703 OpticalMode::getValue()
705 unsigned int dir
, omode_a
;
706 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for optical mode %d\n", m_register
);
708 // FIXME: we could just read the appropriate mixer status field from the
709 // receive stream processor once we work out an efficient way to do this.
710 dir
= (m_register
==MOTU_CTRL_DIR_IN
)?MOTU_DIR_IN
:MOTU_DIR_OUT
;
711 m_parent
.getOpticalMode(dir
, &omode_a
, NULL
);
713 case MOTU_OPTICAL_MODE_OFF
: return 0;
714 case MOTU_OPTICAL_MODE_ADAT
: return 1;
715 case MOTU_OPTICAL_MODE_TOSLINK
: return 2;
721 InputGainPadInv::InputGainPadInv(MotuDevice
&parent
, unsigned int channel
, unsigned int mode
)
722 : MotuDiscreteCtrl(parent
, channel
)
728 InputGainPadInv::InputGainPadInv(MotuDevice
&parent
, unsigned int channel
, unsigned int mode
,
729 std::string name
, std::string label
, std::string descr
)
730 : MotuDiscreteCtrl(parent
, channel
, name
, label
, descr
)
736 void InputGainPadInv::validate(void) {
737 if ((m_mode
==MOTU_CTRL_MODE_PAD
|| m_mode
==MOTU_CTRL_MODE_TRIMGAIN
) &&
738 m_register
>MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL
) {
739 debugOutput(DEBUG_LEVEL_VERBOSE
, "Invalid channel %d: max supported is %d, assuming 0\n",
740 m_register
, MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL
);
743 if ((m_mode
==MOTU_CTRL_MODE_UL_GAIN
|| m_mode
==MOTU_CTRL_MODE_PHASE_INV
) &&
744 m_register
>MOTU_CTRL_GAINPHASEINV_MAX_CHANNEL
) {
745 debugOutput(DEBUG_LEVEL_VERBOSE
, "Invalid ultralite channel %d: max supported is %d, assuming 0\n",
746 m_register
, MOTU_CTRL_GAINPHASEINV_MAX_CHANNEL
);
749 if (m_mode
!=MOTU_CTRL_MODE_PAD
&& m_mode
!=MOTU_CTRL_MODE_TRIMGAIN
&&
750 m_mode
!=MOTU_CTRL_MODE_UL_GAIN
&& m_mode
!=MOTU_CTRL_MODE_PHASE_INV
) {
751 debugOutput(DEBUG_LEVEL_VERBOSE
, "Invalid mode %d, assuming %d\n", m_mode
, MOTU_CTRL_MODE_PAD
);
752 m_mode
= MOTU_CTRL_MODE_PAD
;
756 unsigned int InputGainPadInv::dev_register(void) {
757 /* Work out the device register to use for the associated channel */
758 /* Registers for gain/phase inversion controls on the Ultralite differ from those
761 if (m_mode
==MOTU_CTRL_MODE_PAD
|| m_mode
==MOTU_CTRL_MODE_TRIMGAIN
) {
762 if (m_register
>=0 && m_register
<=3) {
763 return MOTU_REG_INPUT_GAIN_PAD_0
;
765 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported channel %d\n", m_register
);
768 if (m_register
>=0 && m_register
<=3)
769 return MOTU_REG_INPUT_GAIN_PHINV0
;
770 else if (m_register
>=4 && m_register
<=7)
771 return MOTU_REG_INPUT_GAIN_PHINV1
;
772 else if (m_register
>=8 && m_register
<=11)
773 return MOTU_REG_INPUT_GAIN_PHINV2
;
775 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported ultralite channel %d\n", m_register
);
782 InputGainPadInv::setValue(int v
)
785 unsigned int reg
, reg_shift
;
786 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for mode %d input pad/trim %d to %d\n", m_mode
, m_register
, v
);
788 if (m_register
== MOTU_CTRL_NONE
) {
789 debugOutput(DEBUG_LEVEL_WARNING
, "use of MOTU_CTRL_NONE in non-matrix control\n");
793 reg
= dev_register();
796 reg_shift
= (m_register
& 0x03) * 8;
798 // Need to get current gain trim / pad value so we can preserve one
799 // while setting the other. The pad status is in bit 6 of the channel's
800 // respective byte with the trim in bits 0-5. Bit 7 is the write enable
801 // bit for the channel.
802 val
= m_parent
.ReadRegister(reg
) & (0xff << reg_shift
);
805 case MOTU_CTRL_MODE_PAD
:
806 case MOTU_CTRL_MODE_PHASE_INV
:
807 // Set pad/phase inversion bit (bit 6 of relevant channel's byte)
809 val
&= ~(0x40 << reg_shift
);
811 val
|= (0x40 << reg_shift
);
814 case MOTU_CTRL_MODE_TRIMGAIN
:
815 case MOTU_CTRL_MODE_UL_GAIN
:
816 // Set the gain trim (bits 0-5 of the channel's byte). Maximum
817 // gain is 53 dB for trimgain on non-ultralite devices. For
818 // ultralites, mic inputs max out at 0x18, line inputs at 0x12
819 // and spdif inputs at 0x0c. We just clip at 0x18 for now.
820 if (m_mode
==MOTU_CTRL_MODE_TRIMGAIN
) {
827 val
= (val
& ~(0x3f << reg_shift
)) | (v
<< reg_shift
);
830 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported mode %d\n", m_mode
);
834 // Set the channel's write enable bit
835 val
|= (0x80 << reg_shift
);
837 m_parent
.WriteRegister(reg
, val
);
843 InputGainPadInv::getValue()
846 unsigned int reg
, reg_shift
;
847 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for mode %d input pad/trim %d\n", m_mode
, m_register
);
849 if (m_register
== MOTU_CTRL_NONE
) {
850 debugOutput(DEBUG_LEVEL_WARNING
, "use of MOTU_CTRL_NONE in non-matrix control\n");
854 reg
= dev_register();
857 reg_shift
= (m_register
& 0x03) * 8;
859 // The pad/phase inversion status is in bit 6 of the channel's
860 // respective byte with the trim in bits 0-5. Bit 7 is the write enable
861 // bit for the channel.
862 val
= m_parent
.ReadRegister(reg
);
865 case MOTU_CTRL_MODE_PAD
:
866 case MOTU_CTRL_MODE_PHASE_INV
:
867 val
= ((val
>> reg_shift
) & 0x40) != 0;
869 case MOTU_CTRL_MODE_TRIMGAIN
:
870 case MOTU_CTRL_MODE_UL_GAIN
:
871 val
= ((val
>> reg_shift
) & 0x3f);
874 debugOutput(DEBUG_LEVEL_VERBOSE
, "unsupported mode %d\n", m_mode
);
881 MeterControl::MeterControl(MotuDevice
&parent
, unsigned int ctrl_mask
, unsigned int ctrl_shift
)
882 : MotuDiscreteCtrl(parent
, ctrl_mask
)
884 m_shift
= ctrl_shift
;
888 MeterControl::MeterControl(MotuDevice
&parent
, unsigned int ctrl_mask
, unsigned int ctrl_shift
,
889 std::string name
, std::string label
, std::string descr
)
890 : MotuDiscreteCtrl(parent
, ctrl_mask
, name
, label
, descr
)
892 m_shift
= ctrl_shift
;
896 void MeterControl::validate(void) {
897 if ((m_register
& (1<< m_shift
)) == 0) {
898 debugOutput(DEBUG_LEVEL_VERBOSE
, "Inconsistent mask/shift: 0x%08x/%d\n", m_register
, m_shift
);
903 MeterControl::setValue(int v
)
906 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for meter control 0x%08x/%d: %d\n",
907 m_register
, m_shift
, v
);
909 // Need to get current register setting so we can preserve the parts not
910 // being controlled by this object. m_register holds the mask for the
911 // parts we're changing.
912 val
= m_parent
.ReadRegister(MOTU_REG_896HD_METER_CONF
) & ~m_register
;
913 val
|= (v
<< m_shift
) & m_register
;
915 m_parent
.WriteRegister(MOTU_REG_896HD_METER_CONF
, val
);
917 // Drivers under other OSes set MOTU_REG_896HD_METER_REG (0x0b1c) to
918 // 0x0400 whenever MOTU_REG_896HD_METER_CONF (0x0b24) is changed.
919 // There's no obvious reason why they do this, but since it's no hassle
920 // we might as well do the same.
921 m_parent
.WriteRegister(MOTU_REG_896HD_METER_REG
, 0x0400);
927 MeterControl::getValue()
930 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for meter control 0x%08x/%d\n",
931 m_register
, m_shift
);
933 // m_register holds the mask of the part of interest
934 val
= (m_parent
.ReadRegister(MOTU_REG_896HD_METER_CONF
) & m_register
) >> m_shift
;
939 InfoElement::InfoElement(MotuDevice
&parent
, unsigned infotype
)
940 : MotuDiscreteCtrl(parent
, infotype
)
944 InfoElement::InfoElement(MotuDevice
&parent
, unsigned infotype
,
945 std::string name
, std::string label
, std::string descr
)
946 : MotuDiscreteCtrl(parent
, infotype
, name
, label
, descr
)
951 InfoElement::setValue(int v
)
953 /* This is a read-only field, so any call to setValue() is technically
956 debugOutput(DEBUG_LEVEL_VERBOSE
, "InfoElement (%d) is read-only\n", m_register
);
961 InfoElement::getValue()
966 switch (m_register
) {
967 case MOTU_INFO_MODEL
:
968 res
= m_parent
.m_motu_model
;
969 debugOutput(DEBUG_LEVEL_VERBOSE
, "Model: %d\n", res
);
971 case MOTU_INFO_IS_STREAMING
:
972 val
= m_parent
.ReadRegister(MOTU_REG_ISOCTRL
);
973 /* Streaming is active if either bit 22 (Motu->PC streaming
974 * enable) or bit 30 (PC->Motu streaming enable) is set.
976 res
= (val
& 0x40400000) != 0;
977 debugOutput(DEBUG_LEVEL_VERBOSE
, "IsStreaming: %d (reg=%08x)\n", res
, val
);
979 case MOTU_INFO_SAMPLE_RATE
:
980 res
= m_parent
.getSamplingFrequency();
981 debugOutput(DEBUG_LEVEL_VERBOSE
, "SampleRate: %d\n", res
);