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

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

remove device table printout

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