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

Revision 864, 14.5 kB (checked in by ppalmers, 15 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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