2 * Copyright (C) 2009 by Pieter Palmers
3 * Copyright (C) 2009 by Arnold Krille
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 #include "saffire_pro24.h"
26 #include "focusrite_eap.h"
31 int SaffirePro24::SaffirePro24EAP::commandToFix(unsigned offset
) {
32 if (offset
<0x14) return 2;
33 if (offset
<0x3C && offset
>=0x14) return 1;
34 if (offset
<0x58 && offset
>=0x50) return 1;
35 if (offset
<0x40 && offset
>=0x3C) return 3;
36 if (offset
<0x60 && offset
>=0x58) return 4;
39 FocusriteEAP::Poti
* SaffirePro24::SaffirePro24EAP::getMonitorPoti(std::string name
) {
40 return new FocusriteEAP::Poti(this, name
, 0x50);
42 FocusriteEAP::Poti
* SaffirePro24::SaffirePro24EAP::getDimPoti(std::string name
) {
43 return new FocusriteEAP::Poti(this, name
, 0x54);
47 void SaffirePro24::SaffirePro24EAP::setupSources() {
48 addSource("SPDIF", 6, 2, eRS_AES);
49 addSource("ADAT", 0, 8, eRS_ADAT);
50 addSource("Analog", 0, 4, eRS_InS0);
51 addSource("Mixer", 0, 16, eRS_Mixer);
52 addSource("1394", 0, 8, eRS_ARX0);
53 addSource("Mute", 0, 1, eRS_Muted);
55 void SaffirePro24::SaffirePro24EAP::setupDestinations() {
56 addDestination("SPDIF", 6, 2, eRD_AES);
57 addDestination("Analog", 0, 6, eRD_InS0);
58 addDestination("Mixer", 0, 16, eRD_Mixer0);
59 addDestination("Mixer", 0, 2, eRD_Mixer1, 16);
60 addDestination("1394", 0, 16, eRD_ATX0);
61 addDestination("Mute", 0, 1, eRD_Muted);
65 void SaffirePro24::SaffirePro24EAP::setupSources_low() {
66 addSource("SPDIF", 6, 2, eRS_AES
, 1);
67 addSource("ADAT", 0, 8, eRS_ADAT
, 1);
68 addSource("Analog", 0, 4, eRS_InS0
, 1);
69 addSource("Mixer", 0, 16, eRS_Mixer
, 1);
70 addSource("1394", 0, 8, eRS_ARX0
, 1);
71 addSource("Mute", 0, 1, eRS_Muted
);
73 void SaffirePro24::SaffirePro24EAP::setupDestinations_low() {
74 addDestination("SPDIF", 6, 2, eRD_AES
, 1);
75 addDestination("Analog", 0, 6, eRD_InS0
, 1);
76 addDestination("Mixer", 0, 16, eRD_Mixer0
, 1);
77 addDestination("Mixer", 0, 2, eRD_Mixer1
, 17);
78 addDestination("1394", 0, 16, eRD_ATX0
, 1);
79 // Is a Mute destination useful ?
80 // addDestination("Mute", 0, 1, eRD_Muted);
83 void SaffirePro24::SaffirePro24EAP::setupSources_mid() {
84 addSource("SPDIF", 6, 2, eRS_AES
, 1);
85 addSource("ADAT", 0, 4, eRS_ADAT
, 1);
86 addSource("Analog", 0, 4, eRS_InS0
, 1);
87 addSource("Mixer", 0, 16, eRS_Mixer
, 1);
88 addSource("1394", 0, 8, eRS_ARX0
, 1);
89 addSource("Mute", 0, 1, eRS_Muted
);
91 void SaffirePro24::SaffirePro24EAP::setupDestinations_mid() {
92 addDestination("SPDIF", 6, 2, eRD_AES
, 1);
93 addDestination("Analog", 0, 6, eRD_InS0
, 1);
94 addDestination("Mixer", 0, 16, eRD_Mixer0
, 1);
95 addDestination("Mixer", 0, 2, eRD_Mixer1
, 17);
96 addDestination("1394", 0, 12, eRD_ATX0
, 1);
97 // Is a Mute destination useful ?
98 // addDestination("Mute", 0, 1, eRD_Muted);
101 void SaffirePro24::SaffirePro24EAP::setupSources_high() {
102 printMessage("High (192 kHz) sample rate not supported by Saffire Pro 24\n");
105 void SaffirePro24::SaffirePro24EAP::setupDestinations_high() {
106 printMessage("High (192 kHz) sample rate not supported by Saffire Pro 24\n");
110 * The default configurations for the Saffire Pro 24 router.
111 * For coherence with hardware, destinations must follow a specific ordering
112 * There must be 44 destinations at low samplerate
113 * Front LEDs are connected to the first four router entries
116 SaffirePro24::SaffirePro24EAP::setupDefaultRouterConfig_low() {
118 // the 1394 stream receivers except the two "loops" one
119 for (i
=0; i
<4; i
++) {
120 addRoute(eRS_InS0
, i
, eRD_ATX0
, i
);
122 for (i
=0; i
<2; i
++) {
123 addRoute(eRS_AES
, i
+6, eRD_ATX0
, i
+4);
125 for (i
=0; i
<8; i
++) {
126 addRoute(eRS_ADAT
, i
, eRD_ATX0
, i
+6);
129 // Ensure that audio port are not muted
130 for (i
=0; i
<6; i
++) {
131 addRoute(eRS_ARX0
, i
%2, eRD_InS0
, i
);
133 // the SPDIF receiver
134 for (i
=0; i
<2; i
++) {
135 addRoute(eRS_Muted
, 0, eRD_AES
, i
+6);
137 // the "loops" 1394 stream receivers
138 for (i
=0; i
<2; i
++) {
139 addRoute(eRS_Muted
, 0, eRD_ATX0
, i
+14);
142 for (i
=0; i
<4; i
++) {
143 addRoute(eRS_InS0
, i
, eRD_Mixer0
, i
);
145 for (i
=0; i
<2; i
++) {
146 addRoute(eRS_AES
, i
+6, eRD_Mixer0
, i
+4);
148 for (i
=0; i
<8; i
++) {
149 addRoute(eRS_ADAT
, i
, eRD_Mixer0
, i
+6);
151 for (i
=0; i
<2; i
++) {
152 addRoute(eRS_ARX0
, i
, eRD_Mixer0
, i
+14);
154 for (i
=0; i
<2; i
++) {
155 addRoute(eRS_Muted
, 0, eRD_Mixer1
, i
);
157 // The two mute destinations
158 for (i
=0; i
<2; i
++) {
159 addRoute(eRS_Mixer
, i
, eRD_Muted
, 0);
164 * There must be 40 (?) destinations at mid samplerate
165 * Front LEDs are connected to the first four router entries
168 SaffirePro24::SaffirePro24EAP::setupDefaultRouterConfig_mid() {
170 // the 1394 stream receivers except the two "loops" one
171 for (i
=0; i
<4; i
++) {
172 addRoute(eRS_InS0
, i
, eRD_ATX0
, i
);
174 for (i
=0; i
<2; i
++) {
175 addRoute(eRS_AES
, i
+6, eRD_ATX0
, i
+4);
177 for (i
=0; i
<4; i
++) {
178 addRoute(eRS_ADAT
, i
, eRD_ATX0
, i
+6);
181 // Ensure that audio port are not muted
182 for (i
=0; i
<6; i
++) {
183 addRoute(eRS_ARX0
, i
%2, eRD_InS0
, i
);
185 // the SPDIF receiver
186 for (i
=0; i
<2; i
++) {
187 addRoute(eRS_Muted
, 0, eRD_AES
, i
+6);
189 // the "loops" 1394 stream receivers
190 for (i
=0; i
<2; i
++) {
191 addRoute(eRS_Muted
, 0, eRD_ATX0
, i
+10);
194 for (i
=0; i
<4; i
++) {
195 addRoute(eRS_InS0
, i
, eRD_Mixer0
, i
);
197 for (i
=0; i
<2; i
++) {
198 addRoute(eRS_AES
, i
+6, eRD_Mixer0
, i
+4);
200 for (i
=0; i
<4; i
++) {
201 addRoute(eRS_ADAT
, i
, eRD_Mixer0
, i
+6);
203 for (i
=0; i
<2; i
++) {
204 addRoute(eRS_ARX0
, i
, eRD_Mixer0
, i
+10);
206 for (i
=0; i
<4; i
++) {
207 addRoute(eRS_Muted
, 0, eRD_Mixer0
, i
+12);
209 for (i
=0; i
<2; i
++) {
210 addRoute(eRS_Muted
, 0, eRD_Mixer1
, i
);
212 // The two mute destinations
213 for (i
=0; i
<2; i
++) {
214 addRoute(eRS_Mixer
, i
, eRD_Muted
, 0);
219 * High rate not supported
222 SaffirePro24::SaffirePro24EAP::setupDefaultRouterConfig_high() {
223 printMessage("High (192 kHz) sample rate not supported by Saffire Pro 40\n");
226 class SaffirePro24::LineInstSwitch
: public Dice::Focusrite::FocusriteEAP::Switch
229 LineInstSwitch(Dice::Focusrite::FocusriteEAP
* eap
, std::string name
, size_t offset
, int activevalue
)
230 : Dice::Focusrite::FocusriteEAP::Switch(eap
, name
, offset
, activevalue
) {}
231 std::string
getBooleanLabel(bool n
) {
232 if ( n
) return "Instrument";
236 class SaffirePro24::LevelSwitch
: public Dice::Focusrite::FocusriteEAP::Switch
239 LevelSwitch(Dice::Focusrite::FocusriteEAP
* eap
, std::string name
, size_t offset
, int activevalue
)
240 : Dice::Focusrite::FocusriteEAP::Switch(eap
, name
, offset
, activevalue
) {}
241 std::string
getBooleanLabel(bool n
) {
242 if ( n
) return "High";
247 SaffirePro24::SaffirePro24( DeviceManager
& d
,
248 std::auto_ptr
<ConfigRom
>( configRom
))
249 : Dice::Device(d
, configRom
)
253 debugOutput(DEBUG_LEVEL_VERBOSE
, "Created Dice::Focusrite::SaffirePro24 (NodeID %d)\n",
254 getConfigRom().getNodeId());
257 SaffirePro24::~SaffirePro24()
259 //debugOutput(DEBUG_LEVEL_VERBOSE, "Deleting the saffirePro24\n");
260 /// I wonder whether we should really save only on clean exits or also each time a setting is
261 // changed. Or should we provide a function (and thus gui-button) to save the state of the
263 getEAP()->storeFlashConfig();
264 getEAP()->deleteElement(m_ch1
);
265 getEAP()->deleteElement(m_ch2
);
266 if (m_ch1
) delete m_ch1
;
267 if (m_ch2
) delete m_ch2
;
270 bool SaffirePro24::discover() {
271 if (Dice::Device::discover()) {
272 fb_quadlet_t
* tmp
= (fb_quadlet_t
*)calloc(2, sizeof(fb_quadlet_t
));
273 getEAP()->readRegBlock(Dice::EAP::eRT_Application
, 0x00, tmp
, 1*sizeof(fb_quadlet_t
));
274 //hexDumpQuadlets(tmp, 2); // DEBUG
275 // 0x00010004 is a pro24, 0x00010008 is the pro24dsp
276 if (tmp
[0] != 0x00010004 && tmp
[0] != 0x00010008) {
277 debugError("This is a Focusrite Saffire Pro24 but not the right firmware. Better stop here before something goes wrong.\n");
278 debugError("This device has firmware 0x%x while we only know about versions 0x%x and 0x%x.\n", tmp
[0], 0x10004, 0x10008);
281 //getEAP()->readRegBlock(Dice::EAP::eRT_Command, 0x00, tmp, 2*sizeof(fb_quadlet_t)); // DEBUG
282 //hexDumpQuadlets(tmp, 2); // DEBUG
284 FocusriteEAP
* eap
= dynamic_cast<FocusriteEAP
*>(getEAP());
285 m_ch1
= new LineInstSwitch(eap
, "Ch1LineInst", 0x58, 2);
286 getEAP()->addElement(m_ch1
);
287 m_ch2
= new LineInstSwitch(eap
, "Ch2LineInst", 0x58, 2<<16);
288 getEAP()->addElement(m_ch2
);
289 m_ch3
= new LevelSwitch(eap
, "Ch3Level", 0x5C, 1);
290 getEAP()->addElement(m_ch3
);
291 m_ch4
= new LevelSwitch(eap
, "Ch4Level", 0x5C, 1<<16);
292 getEAP()->addElement(m_ch4
);
294 m_monitor
= new FocusriteEAP::MonitorSection(eap
, "Monitoring");
295 getEAP()->addElement(m_monitor
);
301 void SaffirePro24::showDevice()
303 debugOutput(DEBUG_LEVEL_VERBOSE
, "This is a Dice::Focusrite::SaffirePro24\n");
304 Dice::Device::showDevice();
306 Dice::EAP
* SaffirePro24::createEAP() {
307 return new SaffirePro24EAP(*this);
310 bool SaffirePro24::setNickname( std::string name
) {
311 return getEAP()->writeRegBlock( Dice::EAP::eRT_Application
, 0x40, (fb_quadlet_t
*)name
.c_str(), name
.size() );
314 std::string
SaffirePro24::getNickname() {
316 getEAP()->readRegBlock( Dice::EAP::eRT_Application
, 0x40, (fb_quadlet_t
*)name
, 16 );
317 return std::string( name
);