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

Revision 742, 14.4 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

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