root/trunk/libffado/src/fireworks/fireworks_device.cpp

Revision 689, 14.7 kB (checked in by ppalmers, 16 years ago)

more echo firmware work

Line 
1 /*
2  * Copyright (C) 2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "fireworks_device.h"
25 #include "efc/efc_avc_cmd.h"
26 #include "efc/efc_cmd.h"
27 #include "efc/efc_cmds_hardware.h"
28 #include "efc/efc_cmds_hardware_ctrl.h"
29
30 #include "audiofire/audiofire_device.h"
31
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
34
35 #include "config.h"
36
37 #include "fireworks/fireworks_control.h"
38
39 #include <sstream>
40 using namespace std;
41
42 // FireWorks is the platform used and developed by ECHO AUDIO
43 namespace FireWorks {
44
45 Device::Device( Ieee1394Service& ieee1394Service,
46                             std::auto_ptr<ConfigRom>( configRom ))
47     : GenericAVC::AvDevice( ieee1394Service, configRom)
48     , m_efc_discovery_done ( false )
49     , m_MixerContainer ( NULL )
50 {
51     debugOutput( DEBUG_LEVEL_VERBOSE, "Created FireWorks::Device (NodeID %d)\n",
52                  getConfigRom().getNodeId() );
53     pthread_mutex_init( &m_polled_mutex, 0 );
54 }
55
56 Device::~Device()
57 {
58     destroyMixer();
59 }
60
61 void
62 Device::showDevice()
63 {
64     debugOutput(DEBUG_LEVEL_VERBOSE, "This is a FireWorks::Device\n");
65     if ( !m_efc_discovery_done) {
66         if (!discoverUsingEFC()) {
67             debugError("EFC discovery failed\n");
68         }
69     }
70     m_HwInfo.showEfcCmd();
71    
72     GenericAVC::AvDevice::showDevice();
73 }
74
75
76 bool
77 Device::probe( ConfigRom& configRom )
78 {
79     unsigned int vendorId = configRom.getNodeVendorId();
80     unsigned int modelId = configRom.getModelId();
81
82     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_fireworks.txt" );
83     if ( vendorModel.parse() ) {
84         return vendorModel.isPresent( vendorId, modelId );
85     }
86
87     return false;
88 }
89
90 bool
91 Device::discover()
92 {
93     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
94     unsigned int modelId = m_pConfigRom->getModelId();
95
96     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_fireworks.txt" );
97     if ( vendorModel.parse() ) {
98         m_model = vendorModel.find( vendorId, modelId );
99     }
100
101     if (!GenericAVC::VendorModel::isValid(m_model)) {
102         return false;
103     }
104     debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
105             m_model.vendor_name.c_str(), m_model.model_name.c_str());
106
107     // get the info from the EFC
108     if ( !discoverUsingEFC() ) {
109         debugError( "Could not discover using EFC\n" );
110         return false;
111     }
112
113     // discover AVC-wise
114     if ( !GenericAVC::AvDevice::discover() ) {
115         debugError( "Could not discover GenericAVC::AvDevice\n" );
116         return false;
117     }
118
119     if(!buildMixer()) {
120         debugWarning("Could not build mixer\n");
121     }
122
123     return true;
124 }
125
126 bool
127 Device::discoverUsingEFC()
128 {
129     m_efc_discovery_done = false;
130
131     if (!doEfcOverAVC(m_HwInfo)) {
132         debugError("Could not read hardware capabilities\n");
133         return false;
134     }
135
136     // save the EFC version, since some stuff
137     // depends on this
138     m_efc_version = m_HwInfo.m_header.version;
139
140     if (!updatePolledValues()) {
141         debugError("Could not update polled values\n");
142         return false;
143     }
144
145     m_efc_discovery_done = true;
146     return true;
147 }
148
149 FFADODevice *
150 Device::createDevice( Ieee1394Service& ieee1394Service,
151                       std::auto_ptr<ConfigRom>( configRom ))
152 {
153     unsigned int vendorId = configRom->getNodeVendorId();
154 //     unsigned int modelId = configRom->getModelId();
155
156     switch(vendorId) {
157         case FW_VENDORID_ECHO: return new ECHO::AudioFire(ieee1394Service, configRom );
158         default: return new Device(ieee1394Service, configRom );
159     }
160 }
161
162 bool
163 Device::doEfcOverAVC(EfcCmd &c) {
164     EfcOverAVCCmd cmd( get1394Service() );
165     cmd.setCommandType( AVC::AVCCommand::eCT_Control );
166     cmd.setNodeId( getConfigRom().getNodeId() );
167     cmd.setSubunitType( AVC::eST_Unit  );
168     cmd.setSubunitId( 0xff );
169
170     cmd.setVerbose( getDebugLevel() );
171 //     cmd.setVerbose( DEBUG_LEVEL_VERY_VERBOSE );
172
173     cmd.m_cmd = &c;
174
175 //     c.showEfcCmd();
176
177     if ( !cmd.fire()) {
178         debugError( "EfcOverAVCCmd command failed\n" );
179         c.showEfcCmd();
180         return false;
181     }
182 //     c.showEfcCmd();
183
184     if ( cmd.getResponse() != AVC::AVCCommand::eR_Accepted) {
185         debugError( "EfcOverAVCCmd not accepted\n" );
186         return false;
187     }
188
189     if (   c.m_header.retval != EfcCmd::eERV_Ok
190         && c.m_header.retval != EfcCmd::eERV_FlashBusy) {
191         debugError( "EFC command failed\n" );
192         c.showEfcCmd();
193         return false;
194     }
195
196     return true;
197 }
198
199 bool
200 Device::buildMixer()
201 {
202     bool result=true;
203     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a FireWorks mixer...\n");
204    
205     destroyMixer();
206    
207     // create the mixer object container
208     m_MixerContainer = new Control::Container("Mixer");
209
210     if (!m_MixerContainer) {
211         debugError("Could not create mixer container...\n");
212         return false;
213     }
214
215     // create control objects for the audiofire
216
217     // matrix mix controls
218     result &= m_MixerContainer->addElement(
219         new MonitorControl(*this, MonitorControl::eMC_Gain, "MonitorGain"));
220
221     result &= m_MixerContainer->addElement(
222         new MonitorControl(*this, MonitorControl::eMC_Mute, "MonitorMute"));
223
224     result &= m_MixerContainer->addElement(
225         new MonitorControl(*this, MonitorControl::eMC_Solo, "MonitorSolo"));
226
227     result &= m_MixerContainer->addElement(
228         new MonitorControl(*this, MonitorControl::eMC_Pan, "MonitorPan"));
229
230     // Playback mix controls
231     for (unsigned int ch=0;ch<m_HwInfo.m_nb_1394_playback_channels;ch++) {
232         std::ostringstream node_name;
233         node_name << "PC" << ch;
234        
235         result &= m_MixerContainer->addElement(
236             new BinaryControl(*this, eMT_PlaybackMix, eMC_Mute, ch, 0, node_name.str()+"Mute"));
237         result &= m_MixerContainer->addElement(
238             new SimpleControl(*this, eMT_PlaybackMix, eMC_Gain, ch, node_name.str()+"Gain"));
239     }
240    
241     // Physical output mix controls
242     for (unsigned int ch=0;ch<m_HwInfo.m_nb_phys_audio_out;ch++) {
243         std::ostringstream node_name;
244         node_name << "OUT" << ch;
245        
246         result &= m_MixerContainer->addElement(
247             new BinaryControl(*this, eMT_PhysicalOutputMix, eMC_Mute, ch, 0, node_name.str()+"Mute"));
248         result &= m_MixerContainer->addElement(
249             new BinaryControl(*this, eMT_PhysicalOutputMix, eMC_Nominal, ch, 1, node_name.str()+"Nominal"));
250         result &= m_MixerContainer->addElement(
251             new SimpleControl(*this, eMT_PhysicalOutputMix, eMC_Gain, ch, node_name.str()+"Gain"));
252     }
253    
254     // check for IO config controls and add them if necessary
255     if(m_HwInfo.hasMirroring()) {
256         result &= m_MixerContainer->addElement(
257             new IOConfigControl(*this, eCR_Mirror, "ChannelMirror"));
258     }
259     if(m_HwInfo.hasSoftwarePhantom()) {
260         result &= m_MixerContainer->addElement(
261             new IOConfigControl(*this, eCR_Phantom, "PhantomPower"));
262     }
263
264     if (!result) {
265         debugWarning("One or more control elements could not be created.");
266         // clean up those that couldn't be created
267         destroyMixer();
268         return false;
269     }
270
271     if (!addElement(m_MixerContainer)) {
272         debugWarning("Could not register mixer to device\n");
273         // clean up
274         destroyMixer();
275         return false;
276     }
277
278     return true;
279 }
280
281 bool
282 Device::destroyMixer()
283 {
284     debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
285
286     if (m_MixerContainer == NULL) {
287         debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
288         return true;
289     }
290
291     if (!deleteElement(m_MixerContainer)) {
292         debugError("Mixer present but not registered to the avdevice\n");
293         return false;
294     }
295
296     // remove and delete (as in free) child control elements
297     m_MixerContainer->clearElements(true);
298     delete m_MixerContainer;
299     return true;
300 }
301
302
303 bool
304 Device::updatePolledValues() {
305     bool retval;
306
307     pthread_mutex_lock( &m_polled_mutex );
308     retval = doEfcOverAVC(m_Polled);
309     pthread_mutex_unlock( &m_polled_mutex );
310
311     return retval;
312 }
313
314 FFADODevice::ClockSourceVector
315 Device::getSupportedClockSources() {
316     FFADODevice::ClockSourceVector r;
317
318     if (!m_efc_discovery_done) {
319         debugError("EFC discovery not done yet!\n");
320         return r;
321     }
322
323     uint32_t active_clock=getClock();
324
325     if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_INTERNAL)) {
326         debugOutput(DEBUG_LEVEL_VERBOSE, "Internal clock supported\n");
327         ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_INTERNAL);
328         s.active=(active_clock == EFC_CMD_HW_CLOCK_INTERNAL);
329         if (s.type != eCT_Invalid) r.push_back(s);
330     }
331     if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_SYTMATCH)) {
332         debugOutput(DEBUG_LEVEL_VERBOSE, "Syt Match clock supported\n");
333         ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_SYTMATCH);
334         s.active=(active_clock == EFC_CMD_HW_CLOCK_SYTMATCH);
335         if (s.type != eCT_Invalid) r.push_back(s);
336     }
337     if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_WORDCLOCK)) {
338         debugOutput(DEBUG_LEVEL_VERBOSE, "WordClock supported\n");
339         ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_WORDCLOCK);
340         s.active=(active_clock == EFC_CMD_HW_CLOCK_WORDCLOCK);
341         if (s.type != eCT_Invalid) r.push_back(s);
342     }
343     if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_SPDIF)) {
344         debugOutput(DEBUG_LEVEL_VERBOSE, "SPDIF clock supported\n");
345         ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_SPDIF);
346         s.active=(active_clock == EFC_CMD_HW_CLOCK_SPDIF);
347         if (s.type != eCT_Invalid) r.push_back(s);
348     }
349     if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_ADAT_1)) {
350         debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 1 clock supported\n");
351         ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_ADAT_1);
352         s.active=(active_clock == EFC_CMD_HW_CLOCK_ADAT_1);
353         if (s.type != eCT_Invalid) r.push_back(s);
354     }
355     if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_ADAT_2)) {
356         debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 2 clock supported\n");
357         ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_ADAT_2);
358         s.active=(active_clock == EFC_CMD_HW_CLOCK_ADAT_2);
359         if (s.type != eCT_Invalid) r.push_back(s);
360     }
361
362     return r;
363 }
364
365 bool
366 Device::isClockValid(uint32_t id) {
367     // always valid
368     if (id==EFC_CMD_HW_CLOCK_INTERNAL) return true;
369
370     // the polled values are used to detect
371     // whether clocks are valid
372     if (!updatePolledValues()) {
373         debugError("Could not update polled values\n");
374         return false;
375     }
376     return EFC_CMD_HW_CHECK_FLAG(m_Polled.m_status,id);
377 }
378
379 bool
380 Device::setActiveClockSource(ClockSource s) {
381     bool result;
382
383     debugOutput(DEBUG_LEVEL_VERBOSE, "setting clock source to id: %d\n",s.id);
384
385     if(!isClockValid(s.id)) {
386         debugError("Clock not valid\n");
387         return false;
388     }
389
390     result=setClock(s.id);
391
392     // From the ECHO sources:
393     // "If this is a 1200F and the sample rate is being set via EFC, then
394     // send the "phy reconnect command" so the device will vanish and reappear
395     // with a new descriptor."
396
397 //     EfcPhyReconnectCmd rccmd;
398 //     if(!doEfcOverAVC(rccmd)) {
399 //         debugError("Phy reconnect failed");
400 //     } else {
401 //         // sleep for one second such that the phy can get reconnected
402 //         sleep(1);
403 //     }
404
405     return result;
406 }
407
408 FFADODevice::ClockSource
409 Device::getActiveClockSource() {
410     ClockSource s;
411     uint32_t active_clock=getClock();
412     s=clockIdToClockSource(active_clock);
413     s.active=true;
414     return s;
415 }
416
417 FFADODevice::ClockSource
418 Device::clockIdToClockSource(uint32_t clockid) {
419     ClockSource s;
420     debugOutput(DEBUG_LEVEL_VERBOSE, "clock id: %lu\n", clockid);
421
422     // the polled values are used to detect
423     // whether clocks are valid
424     if (!updatePolledValues()) {
425         debugError("Could not update polled values\n");
426         return s;
427     }
428
429     switch (clockid) {
430         case EFC_CMD_HW_CLOCK_INTERNAL:
431             debugOutput(DEBUG_LEVEL_VERBOSE, "Internal clock\n");
432             s.type=eCT_Internal;
433             s.description="Internal sync";
434             break;
435
436         case EFC_CMD_HW_CLOCK_SYTMATCH:
437             debugOutput(DEBUG_LEVEL_VERBOSE, "Syt Match\n");
438             s.type=eCT_SytMatch;
439             s.description="SYT Match";
440             break;
441
442         case EFC_CMD_HW_CLOCK_WORDCLOCK:
443             debugOutput(DEBUG_LEVEL_VERBOSE, "WordClock\n");
444             s.type=eCT_WordClock;
445             s.description="Word Clock";
446             break;
447
448         case EFC_CMD_HW_CLOCK_SPDIF:
449             debugOutput(DEBUG_LEVEL_VERBOSE, "SPDIF clock\n");
450             s.type=eCT_SPDIF;
451             s.description="SPDIF";
452             break;
453
454         case EFC_CMD_HW_CLOCK_ADAT_1:
455             debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 1 clock\n");
456             s.type=eCT_ADAT;
457             s.description="ADAT 1";
458             break;
459
460         case EFC_CMD_HW_CLOCK_ADAT_2:
461             debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 2 clock\n");
462             s.type=eCT_ADAT;
463             s.description="ADAT 2";
464             break;
465
466         default:
467             debugError("Invalid clock id: %d\n",clockid);
468             return s; // return an invalid ClockSource
469     }
470
471     s.id=clockid;
472     s.valid=isClockValid(clockid);
473
474     return s;
475 }
476
477 uint32_t
478 Device::getClock() {
479     EfcGetClockCmd gccmd;
480     if (!doEfcOverAVC(gccmd)) {
481         debugError("Could not get clock info\n");
482         return EFC_CMD_HW_CLOCK_UNSPECIFIED;
483     }
484     debugOutput(DEBUG_LEVEL_VERBOSE, "Active clock: 0x%08lX\n",gccmd.m_clock);
485     gccmd.showEfcCmd();
486
487     return gccmd.m_clock;
488 }
489
490 bool
491 Device::setClock(uint32_t id) {
492     EfcGetClockCmd gccmd;
493     if (!doEfcOverAVC(gccmd)) {
494         debugError("Could not get clock info\n");
495         return false;
496     }
497     debugOutput(DEBUG_LEVEL_VERBOSE, "Set clock: 0x%08lX\n", id);
498
499     EfcSetClockCmd sccmd;
500     sccmd.m_clock=id;
501     sccmd.m_samplerate=gccmd.m_samplerate;
502     sccmd.m_index=0;
503     if (!doEfcOverAVC(sccmd)) {
504         debugError("Could not set clock info\n");
505         return false;
506     }
507     return true;
508 }
509
510 } // FireWorks
Note: See TracBrowser for help on using the browser.