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

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

- Adapt the ffado external API (upgrade to v3)

NEEDS NEW JACK BACKEND

- simplify FFADODevice constructor even more
- implement first framework support for supporting multiple adapters.

currently all firewire adapters are scanned for supported devices unless specified otherwise
however attaching devices to separate adapters is not supported. using multiple adapters at
that are connected together might 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(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.