[Fireworks] add a workaround for Audiofire12 (and maybe Audiofire8)
[ffado.git] / libffado / src / fireworks / fireworks_device.cpp
blob0308f30038c20b30e3d495b789295c39c45ba129
1 /*
2 * Copyright (C) 2005-2008 by Pieter Palmers
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB.
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.
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.
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/>.
24 // #include "config.h"
25 #include "devicemanager.h"
26 #include "fireworks_device.h"
27 #include "efc/efc_avc_cmd.h"
28 #include "efc/efc_cmd.h"
29 #include "efc/efc_cmds_hardware.h"
30 #include "efc/efc_cmds_hardware_ctrl.h"
31 #include "efc/efc_cmds_flash.h"
33 #include "audiofire/audiofire_device.h"
35 #include "libieee1394/configrom.h"
36 #include "libieee1394/ieee1394service.h"
38 #include "fireworks/fireworks_control.h"
40 #include "libutil/PosixMutex.h"
41 #include "libutil/SystemTimeSource.h"
43 #include "IntelFlashMap.h"
45 #define ECHO_FLASH_ERASE_TIMEOUT_MILLISECS 2000
46 #define FIREWORKS_MIN_FIRMWARE_VERSION 0x04080000
47 #define AVC_MAX_TRIAL 2
48 #define AVC_RETRY_INTERVAL 200000
50 #include <sstream>
51 #include <unistd.h>
52 using namespace std;
54 // FireWorks is the platform used and developed by ECHO AUDIO
55 namespace FireWorks {
57 Device::Device(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
58 : GenericAVC::Device( d, configRom)
59 , m_poll_lock( new Util::PosixMutex("DEVPOLL") )
60 , m_efc_discovery_done ( false )
61 , m_MixerContainer ( NULL )
62 , m_HwInfoContainer ( NULL )
64 debugOutput( DEBUG_LEVEL_VERBOSE, "Created FireWorks::Device (NodeID %d)\n",
65 getConfigRom().getNodeId() );
68 Device::~Device()
70 destroyMixer();
73 void
74 Device::showDevice()
76 debugOutput(DEBUG_LEVEL_VERBOSE, "This is a FireWorks::Device\n");
77 if ( !m_efc_discovery_done) {
78 if (!discoverUsingEFC()) {
79 debugError("EFC discovery failed\n");
82 m_HwInfo.showEfcCmd();
83 GenericAVC::Device::showDevice();
86 bool
87 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
89 if(generic) {
90 // try an EFC command
91 EfcOverAVCCmd cmd( configRom.get1394Service() );
92 cmd.setCommandType( AVC::AVCCommand::eCT_Control );
93 cmd.setNodeId( configRom.getNodeId() );
94 cmd.setSubunitType( AVC::eST_Unit );
95 cmd.setSubunitId( 0xff );
96 cmd.setVerbose( configRom.getVerboseLevel() );
98 EfcHardwareInfoCmd hwInfo;
99 hwInfo.setVerboseLevel(configRom.getVerboseLevel());
100 cmd.m_cmd = &hwInfo;
102 if ( !cmd.fire()) {
103 return false;
106 if ( cmd.getResponse() != AVC::AVCCommand::eR_Accepted) {
107 return false;
109 if ( hwInfo.m_header.retval != EfcCmd::eERV_Ok
110 && hwInfo.m_header.retval != EfcCmd::eERV_FlashBusy) {
111 debugError( "EFC command failed\n" );
112 return false;
114 return true;
115 } else {
116 unsigned int vendorId = configRom.getNodeVendorId();
117 unsigned int modelId = configRom.getModelId();
118 Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
119 return c.isValid(vme) && vme.driver == Util::Configuration::eD_FireWorks;
123 bool
124 Device::discover()
126 unsigned int vendorId = getConfigRom().getNodeVendorId();
127 unsigned int modelId = getConfigRom().getModelId();
129 Util::Configuration &c = getDeviceManager().getConfiguration();
130 Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
132 if (c.isValid(vme) && vme.driver == Util::Configuration::eD_FireWorks) {
133 debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
134 vme.vendor_name.c_str(),
135 vme.model_name.c_str());
136 } else {
137 debugWarning("Using generic ECHO Audio FireWorks support for unsupported device '%s %s'\n",
138 getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
141 // get the info from the EFC
142 if ( !discoverUsingEFC() ) {
143 return false;
146 // discover AVC-wise
147 if ( !GenericAVC::Device::discoverGeneric() ) {
148 debugError( "Could not discover GenericAVC::Device\n" );
149 return false;
152 if(!buildMixer()) {
153 debugWarning("Could not build mixer\n");
156 return true;
159 bool
160 Device::discoverUsingEFC()
162 m_efc_discovery_done = false;
163 m_HwInfo.setVerboseLevel(getDebugLevel());
165 if (!doEfcOverAVC(m_HwInfo)) {
166 debugError("Could not read hardware capabilities\n");
167 return false;
170 // check the firmware version
171 if (m_HwInfo.m_arm_version < FIREWORKS_MIN_FIRMWARE_VERSION) {
172 debugError("Firmware version %u.%u (rev %u) not recent enough. FFADO requires at least version %u.%u (rev %u).\n",
173 (m_HwInfo.m_arm_version >> 24) & 0xFF,
174 (m_HwInfo.m_arm_version >> 16) & 0xFF,
175 (m_HwInfo.m_arm_version >> 0) & 0xFFFF,
176 (FIREWORKS_MIN_FIRMWARE_VERSION >> 24) & 0xFF,
177 (FIREWORKS_MIN_FIRMWARE_VERSION >> 16) & 0xFF,
178 (FIREWORKS_MIN_FIRMWARE_VERSION >> 0) & 0xFFFF
180 return false;
183 // save the EFC version, since some stuff
184 // depends on this
185 m_efc_version = m_HwInfo.m_header.version;
187 if (!updatePolledValues()) {
188 debugError("Could not update polled values\n");
189 return false;
192 m_current_clock = -1;
194 m_efc_discovery_done = true;
195 return true;
198 FFADODevice *
199 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
201 unsigned int vendorId = configRom->getNodeVendorId();
202 // unsigned int modelId = configRom->getModelId();
204 switch(vendorId) {
205 case FW_VENDORID_ECHO: return new ECHO::AudioFire(d, configRom );
206 default: return new Device(d, configRom );
210 bool Device::doEfcOverAVC(EfcCmd &c)
212 int trial;
214 EfcOverAVCCmd cmd( get1394Service() );
215 cmd.setCommandType( AVC::AVCCommand::eCT_Control );
216 cmd.setNodeId( getConfigRom().getNodeId() );
217 cmd.setSubunitType( AVC::eST_Unit );
218 cmd.setSubunitId( 0xff );
220 cmd.setVerbose( getDebugLevel() );
221 cmd.m_cmd = &c;
223 for (trial = 0; trial < AVC_MAX_TRIAL; trial++) {
224 if (cmd.fire())
225 break;
226 Util::SystemTimeSource::SleepUsecRelative(AVC_RETRY_INTERVAL);
229 if (trial == AVC_MAX_TRIAL) {
230 debugError( "EfcOverAVCCmd command failed\n" );
231 c.showEfcCmd();
232 return false;
235 if ( cmd.getResponse() != AVC::AVCCommand::eR_Accepted) {
236 debugError( "EfcOverAVCCmd not accepted\n" );
237 return false;
240 if ( c.m_header.retval != EfcCmd::eERV_Ok
241 && c.m_header.retval != EfcCmd::eERV_FlashBusy) {
242 debugError( "EFC command failed\n" );
243 c.showEfcCmd();
244 return false;
247 return true;
250 bool
251 Device::buildMixer()
253 bool result=true;
254 debugOutput(DEBUG_LEVEL_VERBOSE, "Building a FireWorks mixer...\n");
256 destroyMixer();
258 // create the mixer object container
259 m_MixerContainer = new Control::Container(this, "Mixer");
261 if (!m_MixerContainer) {
262 debugError("Could not create mixer container...\n");
263 return false;
266 // create control objects for the audiofire
268 // matrix mix controls
269 result &= m_MixerContainer->addElement(
270 new MonitorControl(*this, MonitorControl::eMC_Gain, "MonitorGain"));
272 result &= m_MixerContainer->addElement(
273 new MonitorControl(*this, MonitorControl::eMC_Mute, "MonitorMute"));
275 result &= m_MixerContainer->addElement(
276 new MonitorControl(*this, MonitorControl::eMC_Solo, "MonitorSolo"));
278 result &= m_MixerContainer->addElement(
279 new MonitorControl(*this, MonitorControl::eMC_Pan, "MonitorPan"));
281 // Playback mix controls
282 for (unsigned int ch=0;ch<m_HwInfo.m_nb_1394_playback_channels;ch++) {
283 std::ostringstream node_name;
284 node_name << "PC" << ch;
286 result &= m_MixerContainer->addElement(
287 new BinaryControl(*this, eMT_PlaybackMix, eMC_Mute, ch, 0, node_name.str()+"Mute"));
288 result &= m_MixerContainer->addElement(
289 new BinaryControl(*this, eMT_PlaybackMix, eMC_Solo, ch, 0, node_name.str()+"Solo"));
290 result &= m_MixerContainer->addElement(
291 new SimpleControl(*this, eMT_PlaybackMix, eMC_Gain, ch, node_name.str()+"Gain"));
294 // Physical output mix controls
295 for (unsigned int ch=0;ch<m_HwInfo.m_nb_phys_audio_out;ch++) {
296 std::ostringstream node_name;
297 node_name << "OUT" << ch;
299 result &= m_MixerContainer->addElement(
300 new BinaryControl(*this, eMT_PhysicalOutputMix, eMC_Mute, ch, 0, node_name.str()+"Mute"));
301 result &= m_MixerContainer->addElement(
302 new BinaryControl(*this, eMT_PhysicalOutputMix, eMC_Nominal, ch, 1, node_name.str()+"Nominal"));
303 result &= m_MixerContainer->addElement(
304 new SimpleControl(*this, eMT_PhysicalOutputMix, eMC_Gain, ch, node_name.str()+"Gain"));
307 // Physical input mix controls
308 for (unsigned int ch=0;ch<m_HwInfo.m_nb_phys_audio_in;ch++) {
309 std::ostringstream node_name;
310 node_name << "IN" << ch;
312 // result &= m_MixerContainer->addElement(
313 // new BinaryControl(*this, eMT_PhysicalInputMix, eMC_Pad, ch, 0, node_name.str()+"Pad"));
314 result &= m_MixerContainer->addElement(
315 new BinaryControl(*this, eMT_PhysicalInputMix, eMC_Nominal, ch, 1, node_name.str()+"Nominal"));
318 // add hardware information controls
319 m_HwInfoContainer = new Control::Container(this, "HwInfo");
320 result &= m_HwInfoContainer->addElement(
321 new HwInfoControl(*this, HwInfoControl::eHIF_PhysicalAudioOutCount, "PhysicalAudioOutCount"));
322 result &= m_HwInfoContainer->addElement(
323 new HwInfoControl(*this, HwInfoControl::eHIF_PhysicalAudioInCount, "PhysicalAudioInCount"));
324 result &= m_HwInfoContainer->addElement(
325 new HwInfoControl(*this, HwInfoControl::eHIF_1394PlaybackCount, "1394PlaybackCount"));
326 result &= m_HwInfoContainer->addElement(
327 new HwInfoControl(*this, HwInfoControl::eHIF_1394RecordCount, "1394RecordCount"));
328 result &= m_HwInfoContainer->addElement(
329 new HwInfoControl(*this, HwInfoControl::eHIF_GroupOutCount, "GroupOutCount"));
330 result &= m_HwInfoContainer->addElement(
331 new HwInfoControl(*this, HwInfoControl::eHIF_GroupInCount, "GroupInCount"));
332 result &= m_HwInfoContainer->addElement(
333 new HwInfoControl(*this, HwInfoControl::eHIF_PhantomPower, "PhantomPower"));
334 result &= m_HwInfoContainer->addElement(
335 new HwInfoControl(*this, HwInfoControl::eHIF_OpticalInterface, "OpticalInterface"));
336 result &= m_HwInfoContainer->addElement(
337 new HwInfoControl(*this, HwInfoControl::eHIF_PlaybackRouting, "PlaybackRouting"));
339 // add a save settings control
340 result &= this->addElement(
341 new MultiControl(*this, MultiControl::eT_SaveSession, "SaveSettings"));
343 // add an identify control
344 result &= this->addElement(
345 new MultiControl(*this, MultiControl::eT_Identify, "Identify"));
347 // spdif mode control
348 result &= this->addElement(
349 new SpdifModeControl(*this, "SpdifMode"));
351 // check for IO config controls and add them if necessary
352 if(m_HwInfo.hasMirroring()) {
353 result &= this->addElement(
354 new IOConfigControl(*this, eCR_Mirror, "ChannelMirror"));
356 if(m_HwInfo.hasOpticalInterface()) {
357 result &= this->addElement(
358 new IOConfigControl(*this, eCR_DigitalInterface, "DigitalInterface"));
360 if(m_HwInfo.hasSoftwarePhantom()) {
361 result &= this->addElement(
362 new IOConfigControl(*this, eCR_Phantom, "PhantomPower"));
364 if(m_HwInfo.hasPlaybackRouting()) {
365 result &= this->addElement(
366 new PlaybackRoutingControl(*this, "PlaybackRouting"));
369 if (!result) {
370 debugWarning("One or more control elements could not be created.");
371 // clean up those that couldn't be created
372 destroyMixer();
373 return false;
376 if (!addElement(m_MixerContainer)) {
377 debugWarning("Could not register mixer to device\n");
378 // clean up
379 destroyMixer();
380 return false;
383 if (!addElement(m_HwInfoContainer)) {
384 debugWarning("Could not register hwinfo to device\n");
385 // clean up
386 destroyMixer();
387 return false;
390 // load the session block
391 if (!loadSession()) {
392 debugWarning("Could not load session\n");
395 return true;
398 bool
399 Device::destroyMixer()
401 debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
403 if (m_MixerContainer == NULL) {
404 debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
405 } else {
406 if (!deleteElement(m_MixerContainer)) {
407 debugError("Mixer present but not registered to the avdevice\n");
408 return false;
411 // remove and delete (as in free) child control elements
412 m_MixerContainer->clearElements(true);
413 delete m_MixerContainer;
414 m_MixerContainer = NULL;
417 if (m_HwInfoContainer == NULL) {
418 debugOutput(DEBUG_LEVEL_VERBOSE, "no hwinfo to destroy...\n");
419 } else {
420 if (!deleteElement(m_HwInfoContainer)) {
421 debugError("HwInfo present but not registered to the avdevice\n");
422 return false;
425 // remove and delete (as in free) child control elements
426 m_HwInfoContainer->clearElements(true);
427 delete m_HwInfoContainer;
428 m_HwInfoContainer = NULL;
430 return true;
433 bool
434 Device::saveSession()
436 // save the session block
437 // if ( !updateSession() ) {
438 // debugError( "Could not update session\n" );
439 // } else {
440 if ( !m_session.saveToDevice(*this) ) {
441 debugError( "Could not save session block\n" );
443 // }
445 return true;
448 bool
449 Device::loadSession()
451 if ( !m_session.loadFromDevice(*this) ) {
452 debugError( "Could not load session block\n" );
453 return false;
455 return true;
458 bool
459 Device::updatePolledValues() {
460 Util::MutexLockHelper lock(*m_poll_lock);
461 return doEfcOverAVC(m_Polled);
464 #define ECHO_CHECK_AND_ADD_SR(v, x) \
465 { if(x >= m_HwInfo.m_min_sample_rate && x <= m_HwInfo.m_max_sample_rate) \
466 v.push_back(x); }
467 std::vector<int>
468 Device::getSupportedSamplingFrequencies()
470 std::vector<int> frequencies;
471 ECHO_CHECK_AND_ADD_SR(frequencies, 22050);
472 ECHO_CHECK_AND_ADD_SR(frequencies, 24000);
473 ECHO_CHECK_AND_ADD_SR(frequencies, 32000);
474 ECHO_CHECK_AND_ADD_SR(frequencies, 44100);
475 ECHO_CHECK_AND_ADD_SR(frequencies, 48000);
476 ECHO_CHECK_AND_ADD_SR(frequencies, 88200);
477 ECHO_CHECK_AND_ADD_SR(frequencies, 96000);
478 ECHO_CHECK_AND_ADD_SR(frequencies, 176400);
479 ECHO_CHECK_AND_ADD_SR(frequencies, 192000);
480 return frequencies;
483 FFADODevice::ClockSourceVector
484 Device::getSupportedClockSources() {
485 FFADODevice::ClockSourceVector r;
487 if (!m_efc_discovery_done) {
488 debugError("EFC discovery not done yet!\n");
489 return r;
492 uint32_t active_clock=getClock();
494 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_INTERNAL)) {
495 debugOutput(DEBUG_LEVEL_VERBOSE, "Internal clock supported\n");
496 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_INTERNAL);
497 s.active=(active_clock == EFC_CMD_HW_CLOCK_INTERNAL);
498 if (s.type != eCT_Invalid) r.push_back(s);
500 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_SYTMATCH)) {
501 debugOutput(DEBUG_LEVEL_VERBOSE, "Syt Match clock supported\n");
502 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_SYTMATCH);
503 s.active=(active_clock == EFC_CMD_HW_CLOCK_SYTMATCH);
504 if (s.type != eCT_Invalid) r.push_back(s);
506 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_WORDCLOCK)) {
507 debugOutput(DEBUG_LEVEL_VERBOSE, "WordClock supported\n");
508 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_WORDCLOCK);
509 s.active=(active_clock == EFC_CMD_HW_CLOCK_WORDCLOCK);
510 if (s.type != eCT_Invalid) r.push_back(s);
512 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_SPDIF)) {
513 debugOutput(DEBUG_LEVEL_VERBOSE, "SPDIF clock supported\n");
514 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_SPDIF);
515 s.active=(active_clock == EFC_CMD_HW_CLOCK_SPDIF);
516 if (s.type != eCT_Invalid) r.push_back(s);
518 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_ADAT_1)) {
519 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 1 clock supported\n");
520 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_ADAT_1);
521 s.active=(active_clock == EFC_CMD_HW_CLOCK_ADAT_1);
522 if (s.type != eCT_Invalid) r.push_back(s);
524 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_ADAT_2)) {
525 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 2 clock supported\n");
526 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_ADAT_2);
527 s.active=(active_clock == EFC_CMD_HW_CLOCK_ADAT_2);
528 if (s.type != eCT_Invalid) r.push_back(s);
530 return r;
533 bool
534 Device::isClockValid(uint32_t id) {
535 // always valid
536 if (id==EFC_CMD_HW_CLOCK_INTERNAL) return true;
538 // the polled values are used to detect
539 // whether clocks are valid
540 if (!updatePolledValues()) {
541 debugError("Could not update polled values\n");
542 return false;
544 return EFC_CMD_HW_CHECK_FLAG(m_Polled.m_status,id);
547 bool
548 Device::setActiveClockSource(ClockSource s) {
549 bool result;
551 debugOutput(DEBUG_LEVEL_VERBOSE, "setting clock source to id: %d\n",s.id);
553 if(!isClockValid(s.id)) {
554 debugError("Clock not valid\n");
555 return false;
558 result = setClock(s.id);
560 // From the ECHO sources:
561 // "If this is a 1200F and the sample rate is being set via EFC, then
562 // send the "phy reconnect command" so the device will vanish and reappear
563 // with a new descriptor."
565 // EfcPhyReconnectCmd rccmd;
566 // if(!doEfcOverAVC(rccmd)) {
567 // debugError("Phy reconnect failed\n");
568 // } else {
569 // // sleep for one second such that the phy can get reconnected
570 // sleep(1);
571 // }
573 return result;
576 FFADODevice::ClockSource
577 Device::getActiveClockSource() {
578 ClockSource s;
579 uint32_t active_clock=getClock();
580 s=clockIdToClockSource(active_clock);
581 s.active=true;
582 return s;
585 FFADODevice::ClockSource
586 Device::clockIdToClockSource(uint32_t clockid) {
587 ClockSource s;
588 debugOutput(DEBUG_LEVEL_VERBOSE, "clock id: %u\n", clockid);
590 // the polled values are used to detect
591 // whether clocks are valid
592 if (!updatePolledValues()) {
593 debugError("Could not update polled values\n");
594 return s;
597 switch (clockid) {
598 case EFC_CMD_HW_CLOCK_INTERNAL:
599 debugOutput(DEBUG_LEVEL_VERBOSE, "Internal clock\n");
600 s.type=eCT_Internal;
601 s.description="Internal sync";
602 break;
604 case EFC_CMD_HW_CLOCK_SYTMATCH:
605 debugOutput(DEBUG_LEVEL_VERBOSE, "Syt Match\n");
606 s.type=eCT_SytMatch;
607 s.description="SYT Match";
608 break;
610 case EFC_CMD_HW_CLOCK_WORDCLOCK:
611 debugOutput(DEBUG_LEVEL_VERBOSE, "WordClock\n");
612 s.type=eCT_WordClock;
613 s.description="Word Clock";
614 break;
616 case EFC_CMD_HW_CLOCK_SPDIF:
617 debugOutput(DEBUG_LEVEL_VERBOSE, "SPDIF clock\n");
618 s.type=eCT_SPDIF;
619 s.description="SPDIF";
620 break;
622 case EFC_CMD_HW_CLOCK_ADAT_1:
623 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 1 clock\n");
624 s.type=eCT_ADAT;
625 s.description="ADAT 1";
626 break;
628 case EFC_CMD_HW_CLOCK_ADAT_2:
629 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 2 clock\n");
630 s.type=eCT_ADAT;
631 s.description="ADAT 2";
632 break;
634 default:
635 debugError("Invalid clock id: %d\n",clockid);
636 return s; // return an invalid ClockSource
639 s.id=clockid;
640 s.valid=isClockValid(clockid);
642 return s;
645 uint32_t Device::getClock()
647 uint32_t clock;
649 EfcGetClockCmd gccmd;
650 if (!doEfcOverAVC(gccmd)) {
651 debugError("Could not get clock info\n");
652 /* fallback to cache */
653 if (m_current_clock >= 0)
654 clock = m_current_clock;
655 /* fallback to internal */
656 else if (setClock(EFC_CMD_HW_CLOCK_INTERNAL))
657 clock = EFC_CMD_HW_CLOCK_INTERNAL;
658 /* fatal error */
659 else
660 clock = EFC_CMD_HW_CLOCK_UNSPECIFIED;
661 } else
662 clock = gccmd.m_clock;
664 debugOutput(DEBUG_LEVEL_VERBOSE, "Active clock: 0x%08X\n", clock);
665 gccmd.showEfcCmd();
667 return clock;
670 bool Device::setClock(uint32_t id)
672 int sampling_rate = getSamplingFrequency();
673 if (!sampling_rate)
674 return false;
676 debugOutput(DEBUG_LEVEL_VERBOSE, "Set clock: 0x%08X\n", id);
678 EfcSetClockCmd sccmd;
679 sccmd.m_clock=id;
680 sccmd.m_samplerate= sampling_rate;
681 sccmd.m_index=0;
682 if (!doEfcOverAVC(sccmd)) {
683 debugError("Could not set clock info\n");
684 return false;
687 m_current_clock = id;
688 return true;
691 bool
692 Device::lockFlash(bool lock) {
693 // some hardware doesn't need/support flash lock
694 if (m_HwInfo.hasDSP()) {
695 debugOutput(DEBUG_LEVEL_VERBOSE, "flash lock not needed\n");
696 return true;
699 EfcFlashLockCmd cmd;
700 cmd.m_lock = lock;
702 if(!doEfcOverAVC(cmd)) {
703 debugError("Flash lock failed\n");
704 return false;
706 return true;
709 bool
710 Device::writeFlash(uint32_t start, uint32_t len, uint32_t* buffer) {
712 if(len <= 0 || 0xFFFFFFFF - len*4 < start) {
713 debugError("bogus start/len: 0x%08X / %u\n", start, len);
714 return false;
716 if(start & 0x03) {
717 debugError("start address not quadlet aligned: 0x%08X\n", start);
718 return false;
721 uint32_t start_addr = start;
722 uint32_t stop_addr = start + len*4;
723 uint32_t *target_buffer = buffer;
725 EfcFlashWriteCmd cmd;
726 // write EFC_FLASH_SIZE_BYTES at a time
727 for(start_addr = start; start_addr < stop_addr; start_addr += EFC_FLASH_SIZE_BYTES) {
728 cmd.m_address = start_addr;
729 unsigned int quads_to_write = (stop_addr - start_addr)/4;
730 if (quads_to_write > EFC_FLASH_SIZE_QUADS) {
731 quads_to_write = EFC_FLASH_SIZE_QUADS;
733 cmd.m_nb_quadlets = quads_to_write;
734 for(unsigned int i=0; i<quads_to_write; i++) {
735 cmd.m_data[i] = *target_buffer;
736 target_buffer++;
738 if(!doEfcOverAVC(cmd)) {
739 debugError("Flash write failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_write);
740 return false;
743 return true;
746 bool
747 Device::readFlash(uint32_t start, uint32_t len, uint32_t* buffer) {
749 if(len <= 0 || 0xFFFFFFFF - len*4 < start) {
750 debugError("bogus start/len: 0x%08X / %u\n", start, len);
751 return false;
753 if(start & 0x03) {
754 debugError("start address not quadlet aligned: 0x%08X\n", start);
755 return false;
758 uint32_t start_addr = start;
759 uint32_t stop_addr = start + len*4;
760 uint32_t *target_buffer = buffer;
762 EfcFlashReadCmd cmd;
763 // read EFC_FLASH_SIZE_BYTES at a time
764 for(start_addr = start; start_addr < stop_addr; start_addr += EFC_FLASH_SIZE_BYTES) {
765 unsigned int quads_to_read = (stop_addr - start_addr)/4;
766 if (quads_to_read > EFC_FLASH_SIZE_QUADS) {
767 quads_to_read = EFC_FLASH_SIZE_QUADS;
769 uint32_t quadlets_read = 0;
770 int ntries = 10000;
771 do {
772 cmd.m_address = start_addr + quadlets_read*4;
773 unsigned int new_to_read = quads_to_read - quadlets_read;
774 cmd.m_nb_quadlets = new_to_read;
775 if(!doEfcOverAVC(cmd)) {
776 debugError("Flash read failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_read);
777 return false;
779 if(cmd.m_nb_quadlets != new_to_read) {
780 debugOutput(DEBUG_LEVEL_VERBOSE,
781 "Flash read didn't return enough data (%u/%u) \n",
782 cmd.m_nb_quadlets, new_to_read);
783 // continue trying
785 quadlets_read += cmd.m_nb_quadlets;
787 // copy content
788 for(unsigned int i=0; i<cmd.m_nb_quadlets; i++) {
789 *target_buffer = cmd.m_data[i];
790 target_buffer++;
792 } while(quadlets_read < quads_to_read && ntries--);
793 if(ntries==0) {
794 debugError("deadlock while reading flash\n");
795 return false;
798 return true;
801 bool
802 Device::eraseFlash(uint32_t addr) {
803 if(addr & 0x03) {
804 debugError("start address not quadlet aligned: 0x%08X\n", addr);
805 return false;
807 EfcFlashEraseCmd cmd;
808 cmd.m_address = addr;
809 if(!doEfcOverAVC(cmd)) {
810 if (cmd.m_header.retval == EfcCmd::eERV_FlashBusy) {
811 return true;
813 debugError("Flash erase failed for block 0x%08X\n", addr);
814 return false;
816 return true;
819 bool
820 Device::eraseFlashBlocks(uint32_t start_address, unsigned int nb_quads)
822 uint32_t blocksize_bytes;
823 uint32_t blocksize_quads;
824 unsigned int quads_left = nb_quads;
825 bool success = true;
827 const unsigned int max_nb_tries = 10;
828 unsigned int nb_tries = 0;
830 do {
831 // the erase block size is fixed by the HW, and depends
832 // on the flash section we're in
833 if (start_address < MAINBLOCKS_BASE_OFFSET_BYTES)
834 blocksize_bytes = PROGRAMBLOCK_SIZE_BYTES;
835 else
836 blocksize_bytes = MAINBLOCK_SIZE_BYTES;
837 start_address &= ~(blocksize_bytes - 1);
838 blocksize_quads = blocksize_bytes / 4;
840 uint32_t verify[blocksize_quads];
842 // corner case: requested to erase less than one block
843 if (blocksize_quads > quads_left) {
844 blocksize_quads = quads_left;
847 // do the actual erase
848 if (!eraseFlash(start_address)) {
849 debugWarning("Could not erase flash block at 0x%08X\n", start_address);
850 success = false;
851 } else {
852 // wait for the flash to become ready again
853 if (!waitForFlash(ECHO_FLASH_ERASE_TIMEOUT_MILLISECS)) {
854 debugError("Wait for flash timed out at address 0x%08X\n", start_address);
855 return false;
858 // verify that the block is empty as an extra precaution
859 if (!readFlash(start_address, blocksize_quads, verify)) {
860 debugError("Could not read flash block at 0x%08X\n", start_address);
861 return false;
864 // everything should be 0xFFFFFFFF if the erase was successful
865 for (unsigned int i = 0; i < blocksize_quads; i++) {
866 if (0xFFFFFFFF != verify[i]) {
867 debugWarning("Flash erase verification failed.\n");
868 success = false;
869 break;
874 if (success) {
875 start_address += blocksize_bytes;
876 quads_left -= blocksize_quads;
877 nb_tries = 0;
878 } else {
879 nb_tries++;
881 if (nb_tries > max_nb_tries) {
882 debugError("Needed too many tries to erase flash at 0x%08X\n", start_address);
883 return false;
885 } while (quads_left > 0);
887 return true;
890 bool
891 Device::waitForFlash(unsigned int msecs)
893 bool ready;
895 EfcFlashGetStatusCmd statusCmd;
896 const unsigned int time_to_sleep_usecs = 10000;
897 int wait_cycles = msecs * 1000 / time_to_sleep_usecs;
899 do {
900 if (!doEfcOverAVC(statusCmd)) {
901 debugError("Could not read flash status\n");
902 return false;
904 if (statusCmd.m_header.retval == EfcCmd::eERV_FlashBusy) {
905 ready = false;
906 } else {
907 ready = statusCmd.m_ready;
909 usleep(time_to_sleep_usecs);
910 } while (!ready && wait_cycles--);
912 if(wait_cycles == 0) {
913 debugError("Timeout while waiting for flash\n");
914 return false;
917 return ready;
920 uint32_t
921 Device::getSessionBase()
923 EfcFlashGetSessionBaseCmd cmd;
924 if(!doEfcOverAVC(cmd)) {
925 debugError("Could not get session base address\n");
926 return 0; // FIXME: arbitrary
928 return cmd.m_address;
932 Device::getSamplingFrequency()
934 int sampling_rate;
936 EfcGetClockCmd gccmd;
937 if (!doEfcOverAVC(gccmd)) {
938 /* fallback to 'input/output plug signal format' command */
939 sampling_rate = GenericAVC::Device::getSamplingFrequency();
940 if (!sampling_rate) {
941 debugError("Could not get sample rate\n");
942 return false;
944 return sampling_rate;
946 return gccmd.m_samplerate;
948 bool
949 Device::setSamplingFrequency(int s)
951 uint32_t clock = getClock();
952 if (clock == EFC_CMD_HW_CLOCK_UNSPECIFIED)
953 return false;
955 debugOutput(DEBUG_LEVEL_VERBOSE, "Set samplerate: %d\n", s);
957 EfcSetClockCmd sccmd;
958 sccmd.m_clock = clock;
959 sccmd.m_samplerate = s;
960 sccmd.m_index = 0;
961 if (!doEfcOverAVC(sccmd)) {
962 /* fallback to 'input/output plug signal format' command */
963 if (!GenericAVC::Device::setSamplingFrequency(s)) {
964 debugError("Could not set sample rate\n");
965 return false;
968 return true;
972 } // FireWorks