Clean up compiler warnings when compiling on 64-bit systems. These are mostly fixing...
[ffado.git] / libffado / src / fireworks / fireworks_device.cpp
blob6e90d6e95565d883f1045251a3d5bcd06e11715a
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_cmds_flash.h"
30 #include "audiofire/audiofire_device.h"
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
35 #include "fireworks/fireworks_control.h"
37 #include "libutil/PosixMutex.h"
39 #include "IntelFlashMap.h"
41 #define ECHO_FLASH_ERASE_TIMEOUT_MILLISECS 2000
42 #define FIREWORKS_MIN_FIRMWARE_VERSION 0x04080000
44 #include <sstream>
45 #include <unistd.h>
46 using namespace std;
48 // FireWorks is the platform used and developed by ECHO AUDIO
49 namespace FireWorks {
51 Device::Device(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
52 : GenericAVC::Device( d, configRom)
53 , m_poll_lock( new Util::PosixMutex("DEVPOLL") )
54 , m_efc_discovery_done ( false )
55 , m_MixerContainer ( NULL )
56 , m_HwInfoContainer ( NULL )
58 debugOutput( DEBUG_LEVEL_VERBOSE, "Created FireWorks::Device (NodeID %d)\n",
59 getConfigRom().getNodeId() );
62 Device::~Device()
64 destroyMixer();
67 void
68 Device::showDevice()
70 debugOutput(DEBUG_LEVEL_VERBOSE, "This is a FireWorks::Device\n");
71 if ( !m_efc_discovery_done) {
72 if (!discoverUsingEFC()) {
73 debugError("EFC discovery failed\n");
76 m_HwInfo.showEfcCmd();
77 GenericAVC::Device::showDevice();
80 bool
81 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
83 if(generic) {
84 // try an EFC command
85 EfcOverAVCCmd cmd( configRom.get1394Service() );
86 cmd.setCommandType( AVC::AVCCommand::eCT_Control );
87 cmd.setNodeId( configRom.getNodeId() );
88 cmd.setSubunitType( AVC::eST_Unit );
89 cmd.setSubunitId( 0xff );
90 cmd.setVerbose( configRom.getVerboseLevel() );
92 EfcHardwareInfoCmd hwInfo;
93 hwInfo.setVerboseLevel(configRom.getVerboseLevel());
94 cmd.m_cmd = &hwInfo;
96 if ( !cmd.fire()) {
97 return false;
100 if ( cmd.getResponse() != AVC::AVCCommand::eR_Accepted) {
101 return false;
103 if ( hwInfo.m_header.retval != EfcCmd::eERV_Ok
104 && hwInfo.m_header.retval != EfcCmd::eERV_FlashBusy) {
105 debugError( "EFC command failed\n" );
106 return false;
108 return true;
109 } else {
110 unsigned int vendorId = configRom.getNodeVendorId();
111 unsigned int modelId = configRom.getModelId();
112 Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
113 return c.isValid(vme) && vme.driver == Util::Configuration::eD_FireWorks;
117 bool
118 Device::discover()
120 unsigned int vendorId = getConfigRom().getNodeVendorId();
121 unsigned int modelId = getConfigRom().getModelId();
123 Util::Configuration &c = getDeviceManager().getConfiguration();
124 Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
126 if (c.isValid(vme) && vme.driver == Util::Configuration::eD_FireWorks) {
127 debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
128 vme.vendor_name.c_str(),
129 vme.model_name.c_str());
130 } else {
131 debugWarning("Using generic ECHO Audio FireWorks support for unsupported device '%s %s'\n",
132 getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
135 // get the info from the EFC
136 if ( !discoverUsingEFC() ) {
137 return false;
140 // discover AVC-wise
141 if ( !GenericAVC::Device::discoverGeneric() ) {
142 debugError( "Could not discover GenericAVC::Device\n" );
143 return false;
146 if(!buildMixer()) {
147 debugWarning("Could not build mixer\n");
150 return true;
153 bool
154 Device::discoverUsingEFC()
156 m_efc_discovery_done = false;
157 m_HwInfo.setVerboseLevel(getDebugLevel());
159 if (!doEfcOverAVC(m_HwInfo)) {
160 debugError("Could not read hardware capabilities\n");
161 return false;
164 // check the firmware version
165 if (m_HwInfo.m_arm_version < FIREWORKS_MIN_FIRMWARE_VERSION) {
166 debugError("Firmware version %u.%u (rev %u) not recent enough. FFADO requires at least version %u.%u (rev %u).\n",
167 (m_HwInfo.m_arm_version >> 24) & 0xFF,
168 (m_HwInfo.m_arm_version >> 16) & 0xFF,
169 (m_HwInfo.m_arm_version >> 0) & 0xFFFF,
170 (FIREWORKS_MIN_FIRMWARE_VERSION >> 24) & 0xFF,
171 (FIREWORKS_MIN_FIRMWARE_VERSION >> 16) & 0xFF,
172 (FIREWORKS_MIN_FIRMWARE_VERSION >> 0) & 0xFFFF
174 return false;
177 m_current_clock = -1;
179 m_efc_discovery_done = true;
180 return true;
183 FFADODevice *
184 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
186 unsigned int vendorId = configRom->getNodeVendorId();
187 // unsigned int modelId = configRom->getModelId();
189 switch(vendorId) {
190 case FW_VENDORID_ECHO: return new ECHO::AudioFire(d, configRom );
191 default: return new Device(d, configRom );
195 bool Device::doEfcOverAVC(EfcCmd &c)
197 EfcOverAVCCmd cmd( get1394Service() );
198 cmd.setCommandType( AVC::AVCCommand::eCT_Control );
199 cmd.setNodeId( getConfigRom().getNodeId() );
200 cmd.setSubunitType( AVC::eST_Unit );
201 cmd.setSubunitId( 0xff );
203 cmd.setVerbose( getDebugLevel() );
204 cmd.m_cmd = &c;
206 if (!cmd.fire()) {
207 debugError( "EfcOverAVCCmd command failed\n" );
208 c.showEfcCmd();
209 return false;
212 if ( cmd.getResponse() != AVC::AVCCommand::eR_Accepted) {
213 debugError( "EfcOverAVCCmd not accepted\n" );
214 return false;
217 if ( c.m_header.retval != EfcCmd::eERV_Ok
218 && c.m_header.retval != EfcCmd::eERV_FlashBusy) {
219 debugError( "EFC command failed\n" );
220 c.showEfcCmd();
221 return false;
224 return true;
227 bool
228 Device::buildMixer()
230 bool result=true;
231 debugOutput(DEBUG_LEVEL_VERBOSE, "Building a FireWorks mixer...\n");
233 destroyMixer();
235 // create the mixer object container
236 m_MixerContainer = new Control::Container(this, "Mixer");
238 if (!m_MixerContainer) {
239 debugError("Could not create mixer container...\n");
240 return false;
243 // create control objects for the audiofire
245 // matrix mix controls
246 result &= m_MixerContainer->addElement(
247 new MonitorControl(*this, MonitorControl::eMC_Gain, "MonitorGain"));
249 result &= m_MixerContainer->addElement(
250 new MonitorControl(*this, MonitorControl::eMC_Mute, "MonitorMute"));
252 result &= m_MixerContainer->addElement(
253 new MonitorControl(*this, MonitorControl::eMC_Solo, "MonitorSolo"));
255 result &= m_MixerContainer->addElement(
256 new MonitorControl(*this, MonitorControl::eMC_Pan, "MonitorPan"));
258 // Playback mix controls
259 for (unsigned int ch=0;ch<m_HwInfo.m_nb_1394_playback_channels;ch++) {
260 std::ostringstream node_name;
261 node_name << "PC" << ch;
263 result &= m_MixerContainer->addElement(
264 new BinaryControl(*this, eMT_PlaybackMix, eMC_Mute, ch, 0, node_name.str()+"Mute"));
265 result &= m_MixerContainer->addElement(
266 new BinaryControl(*this, eMT_PlaybackMix, eMC_Solo, ch, 0, node_name.str()+"Solo"));
267 result &= m_MixerContainer->addElement(
268 new SimpleControl(*this, eMT_PlaybackMix, eMC_Gain, ch, node_name.str()+"Gain"));
271 // Physical output mix controls
272 for (unsigned int ch=0;ch<m_HwInfo.m_nb_phys_audio_out;ch++) {
273 std::ostringstream node_name;
274 node_name << "OUT" << ch;
276 result &= m_MixerContainer->addElement(
277 new BinaryControl(*this, eMT_PhysicalOutputMix, eMC_Mute, ch, 0, node_name.str()+"Mute"));
278 result &= m_MixerContainer->addElement(
279 new BinaryControl(*this, eMT_PhysicalOutputMix, eMC_Nominal, ch, 1, node_name.str()+"Nominal"));
280 result &= m_MixerContainer->addElement(
281 new SimpleControl(*this, eMT_PhysicalOutputMix, eMC_Gain, ch, node_name.str()+"Gain"));
284 // Physical input mix controls
285 for (unsigned int ch=0;ch<m_HwInfo.m_nb_phys_audio_in;ch++) {
286 std::ostringstream node_name;
287 node_name << "IN" << ch;
289 // result &= m_MixerContainer->addElement(
290 // new BinaryControl(*this, eMT_PhysicalInputMix, eMC_Pad, ch, 0, node_name.str()+"Pad"));
291 result &= m_MixerContainer->addElement(
292 new BinaryControl(*this, eMT_PhysicalInputMix, eMC_Nominal, ch, 1, node_name.str()+"Nominal"));
295 // add hardware information controls
296 m_HwInfoContainer = new Control::Container(this, "HwInfo");
297 result &= m_HwInfoContainer->addElement(
298 new HwInfoControl(*this, HwInfoControl::eHIF_PhysicalAudioOutCount, "PhysicalAudioOutCount"));
299 result &= m_HwInfoContainer->addElement(
300 new HwInfoControl(*this, HwInfoControl::eHIF_PhysicalAudioInCount, "PhysicalAudioInCount"));
301 result &= m_HwInfoContainer->addElement(
302 new HwInfoControl(*this, HwInfoControl::eHIF_1394PlaybackCount, "1394PlaybackCount"));
303 result &= m_HwInfoContainer->addElement(
304 new HwInfoControl(*this, HwInfoControl::eHIF_1394RecordCount, "1394RecordCount"));
305 result &= m_HwInfoContainer->addElement(
306 new HwInfoControl(*this, HwInfoControl::eHIF_GroupOutCount, "GroupOutCount"));
307 result &= m_HwInfoContainer->addElement(
308 new HwInfoControl(*this, HwInfoControl::eHIF_GroupInCount, "GroupInCount"));
309 result &= m_HwInfoContainer->addElement(
310 new HwInfoControl(*this, HwInfoControl::eHIF_PhantomPower, "PhantomPower"));
311 result &= m_HwInfoContainer->addElement(
312 new HwInfoControl(*this, HwInfoControl::eHIF_OpticalInterface, "OpticalInterface"));
313 result &= m_HwInfoContainer->addElement(
314 new HwInfoControl(*this, HwInfoControl::eHIF_PlaybackRouting, "PlaybackRouting"));
316 // add a save settings control
317 result &= this->addElement(
318 new MultiControl(*this, MultiControl::eT_SaveSession, "SaveSettings"));
320 // add an identify control
321 result &= this->addElement(
322 new MultiControl(*this, MultiControl::eT_Identify, "Identify"));
324 // spdif mode control
325 result &= this->addElement(
326 new SpdifModeControl(*this, "SpdifMode"));
328 // check for IO config controls and add them if necessary
329 if(m_HwInfo.hasMirroring()) {
330 result &= this->addElement(
331 new IOConfigControl(*this, eCR_Mirror, "ChannelMirror"));
333 if(m_HwInfo.hasOpticalInterface()) {
334 result &= this->addElement(
335 new IOConfigControl(*this, eCR_DigitalInterface, "DigitalInterface"));
337 if(m_HwInfo.hasSoftwarePhantom()) {
338 result &= this->addElement(
339 new IOConfigControl(*this, eCR_Phantom, "PhantomPower"));
341 if(m_HwInfo.hasPlaybackRouting()) {
342 result &= this->addElement(
343 new PlaybackRoutingControl(*this, "PlaybackRouting"));
346 if (!result) {
347 debugWarning("One or more control elements could not be created.");
348 // clean up those that couldn't be created
349 destroyMixer();
350 return false;
353 if (!addElement(m_MixerContainer)) {
354 debugWarning("Could not register mixer to device\n");
355 // clean up
356 destroyMixer();
357 return false;
360 if (!addElement(m_HwInfoContainer)) {
361 debugWarning("Could not register hwinfo to device\n");
362 // clean up
363 destroyMixer();
364 return false;
367 // load the session block
368 if (!loadSession()) {
369 debugWarning("Could not load session\n");
372 return true;
375 bool
376 Device::destroyMixer()
378 debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
380 if (m_MixerContainer == NULL) {
381 debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
382 } else {
383 if (!deleteElement(m_MixerContainer)) {
384 debugError("Mixer present but not registered to the avdevice\n");
385 return false;
388 // remove and delete (as in free) child control elements
389 m_MixerContainer->clearElements(true);
390 delete m_MixerContainer;
391 m_MixerContainer = NULL;
394 if (m_HwInfoContainer == NULL) {
395 debugOutput(DEBUG_LEVEL_VERBOSE, "no hwinfo to destroy...\n");
396 } else {
397 if (!deleteElement(m_HwInfoContainer)) {
398 debugError("HwInfo present but not registered to the avdevice\n");
399 return false;
402 // remove and delete (as in free) child control elements
403 m_HwInfoContainer->clearElements(true);
404 delete m_HwInfoContainer;
405 m_HwInfoContainer = NULL;
407 return true;
410 bool
411 Device::saveSession()
413 // save the session block
414 // if ( !updateSession() ) {
415 // debugError( "Could not update session\n" );
416 // } else {
417 if ( !m_session.saveToDevice(*this) ) {
418 debugError( "Could not save session block\n" );
420 // }
422 return true;
425 bool
426 Device::loadSession()
428 if ( !m_session.loadFromDevice(*this) ) {
429 debugError( "Could not load session block\n" );
430 return false;
432 return true;
436 * NOTE:
437 * Firmware version 5.0 or later for AudioFire12 returns invalid values to
438 * contents of response against this command.
440 bool
441 Device::updatePolledValues() {
442 Util::MutexLockHelper lock(*m_poll_lock);
443 return doEfcOverAVC(m_Polled);
446 #define ECHO_CHECK_AND_ADD_SR(v, x) \
447 { if(x >= m_HwInfo.m_min_sample_rate && x <= m_HwInfo.m_max_sample_rate) \
448 v.push_back(x); }
449 std::vector<int>
450 Device::getSupportedSamplingFrequencies()
452 std::vector<int> frequencies;
453 ECHO_CHECK_AND_ADD_SR(frequencies, 22050);
454 ECHO_CHECK_AND_ADD_SR(frequencies, 24000);
455 ECHO_CHECK_AND_ADD_SR(frequencies, 32000);
456 ECHO_CHECK_AND_ADD_SR(frequencies, 44100);
457 ECHO_CHECK_AND_ADD_SR(frequencies, 48000);
458 ECHO_CHECK_AND_ADD_SR(frequencies, 88200);
459 ECHO_CHECK_AND_ADD_SR(frequencies, 96000);
460 ECHO_CHECK_AND_ADD_SR(frequencies, 176400);
461 ECHO_CHECK_AND_ADD_SR(frequencies, 192000);
462 return frequencies;
465 FFADODevice::ClockSourceVector
466 Device::getSupportedClockSources() {
467 FFADODevice::ClockSourceVector r;
469 if (!m_efc_discovery_done) {
470 debugError("EFC discovery not done yet!\n");
471 return r;
474 uint32_t active_clock = getClockSrc();
476 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_INTERNAL)) {
477 debugOutput(DEBUG_LEVEL_VERBOSE, "Internal clock supported\n");
478 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_INTERNAL);
479 s.active=(active_clock == EFC_CMD_HW_CLOCK_INTERNAL);
480 if (s.type != eCT_Invalid) r.push_back(s);
482 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_SYTMATCH)) {
483 debugOutput(DEBUG_LEVEL_VERBOSE, "Syt Match clock supported\n");
484 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_SYTMATCH);
485 s.active=(active_clock == EFC_CMD_HW_CLOCK_SYTMATCH);
486 if (s.type != eCT_Invalid) r.push_back(s);
488 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_WORDCLOCK)) {
489 debugOutput(DEBUG_LEVEL_VERBOSE, "WordClock supported\n");
490 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_WORDCLOCK);
491 s.active=(active_clock == EFC_CMD_HW_CLOCK_WORDCLOCK);
492 if (s.type != eCT_Invalid) r.push_back(s);
494 if(EFC_CMD_HW_CHECK_FLAG(m_HwInfo.m_supported_clocks, EFC_CMD_HW_CLOCK_SPDIF)) {
495 debugOutput(DEBUG_LEVEL_VERBOSE, "SPDIF clock supported\n");
496 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_SPDIF);
497 s.active=(active_clock == EFC_CMD_HW_CLOCK_SPDIF);
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_ADAT_1)) {
501 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 1 clock supported\n");
502 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_ADAT_1);
503 s.active=(active_clock == EFC_CMD_HW_CLOCK_ADAT_1);
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_ADAT_2)) {
507 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 2 clock supported\n");
508 ClockSource s=clockIdToClockSource(EFC_CMD_HW_CLOCK_ADAT_2);
509 s.active=(active_clock == EFC_CMD_HW_CLOCK_ADAT_2);
510 if (s.type != eCT_Invalid) r.push_back(s);
512 return r;
515 bool
516 Device::isClockValid(uint32_t id) {
517 // always valid
518 if (id==EFC_CMD_HW_CLOCK_INTERNAL)
519 return true;
521 // the polled values tell whether each clock source is detected or not
522 if (!updatePolledValues()) {
523 debugError("Could not update polled values\n");
524 return false;
526 return EFC_CMD_HW_CHECK_FLAG(m_Polled.m_status,id);
529 bool
530 Device::setActiveClockSource(ClockSource s) {
531 bool result;
533 debugOutput(DEBUG_LEVEL_VERBOSE, "setting clock source to id: %d\n",s.id);
535 if(!isClockValid(s.id)) {
536 debugError("Clock not valid\n");
537 return false;
540 result = setClockSrc(s.id);
542 // From the ECHO sources:
543 // "If this is a 1200F and the sample rate is being set via EFC, then
544 // send the "phy reconnect command" so the device will vanish and reappear
545 // with a new descriptor."
547 // EfcPhyReconnectCmd rccmd;
548 // if(!doEfcOverAVC(rccmd)) {
549 // debugError("Phy reconnect failed\n");
550 // } else {
551 // // sleep for one second such that the phy can get reconnected
552 // sleep(1);
553 // }
555 return result;
558 FFADODevice::ClockSource
559 Device::getActiveClockSource() {
560 ClockSource s;
561 uint32_t active_clock = getClockSrc();
562 s=clockIdToClockSource(active_clock);
563 s.active=true;
564 return s;
567 FFADODevice::ClockSource
568 Device::clockIdToClockSource(uint32_t clockid) {
569 ClockSource s;
570 debugOutput(DEBUG_LEVEL_VERBOSE, "clock id: %u\n", clockid);
572 switch (clockid) {
573 case EFC_CMD_HW_CLOCK_INTERNAL:
574 debugOutput(DEBUG_LEVEL_VERBOSE, "Internal clock\n");
575 s.type=eCT_Internal;
576 s.description="Internal sync";
577 break;
579 case EFC_CMD_HW_CLOCK_SYTMATCH:
580 debugOutput(DEBUG_LEVEL_VERBOSE, "Syt Match\n");
581 s.type=eCT_SytMatch;
582 s.description="SYT Match";
583 break;
585 case EFC_CMD_HW_CLOCK_WORDCLOCK:
586 debugOutput(DEBUG_LEVEL_VERBOSE, "WordClock\n");
587 s.type=eCT_WordClock;
588 s.description="Word Clock";
589 break;
591 case EFC_CMD_HW_CLOCK_SPDIF:
592 debugOutput(DEBUG_LEVEL_VERBOSE, "SPDIF clock\n");
593 s.type=eCT_SPDIF;
594 s.description="SPDIF";
595 break;
597 case EFC_CMD_HW_CLOCK_ADAT_1:
598 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 1 clock\n");
599 s.type=eCT_ADAT;
600 s.description="ADAT 1";
601 break;
603 case EFC_CMD_HW_CLOCK_ADAT_2:
604 debugOutput(DEBUG_LEVEL_VERBOSE, "ADAT 2 clock\n");
605 s.type=eCT_ADAT;
606 s.description="ADAT 2";
607 break;
609 default:
610 debugError("Invalid clock id: %d\n",clockid);
611 return s; // return an invalid ClockSource
614 s.id=clockid;
615 s.valid=isClockValid(clockid);
617 return s;
620 bool Device::getClock(EfcGetClockCmd &gccmd)
622 if (!doEfcOverAVC(gccmd))
623 return false;
626 * NOTE:
627 * Firmware version 5.0 or later for AudioFire12 returns invalid
628 * values in contents of response against this command.
630 if (gccmd.m_samplerate > 192000) {
631 debugOutput(DEBUG_LEVEL_NORMAL,
632 "Could not get sampling rate. Do fallback\n");
633 int sampling_rate;
635 /* fallback to 'input/output plug signal format' command */
636 sampling_rate = GenericAVC::Device::getSamplingFrequency();
637 /* fallback failed */
638 if (!sampling_rate) {
639 debugOutput(DEBUG_LEVEL_NORMAL, "Fallback failed\n");
640 return false;
643 gccmd.m_samplerate = sampling_rate;
646 if (gccmd.m_clock > EFC_CMD_HW_CLOCK_COUNT) {
647 debugOutput(DEBUG_LEVEL_NORMAL,
648 "Could not get clock info. Do fallback\n");
649 if (m_current_clock < 0) {
650 /* fallback to internal clock source */
651 EfcSetClockCmd sccmd;
652 sccmd.m_clock = EFC_CMD_HW_CLOCK_INTERNAL;
653 sccmd.m_samplerate = gccmd.m_samplerate;
654 sccmd.m_index = 0;
656 if (!doEfcOverAVC(sccmd)) {
657 debugOutput(DEBUG_LEVEL_NORMAL, "Fallback failed\n");
658 return false;
661 /* Cache clock source */
662 m_current_clock = sccmd.m_clock;
665 /* Fallback to cache */
666 gccmd.m_clock = m_current_clock;
669 return true;
671 uint32_t Device::getClockSrc()
673 EfcGetClockCmd gccmd;
674 if (!getClock(gccmd))
675 return EFC_CMD_HW_CLOCK_UNSPECIFIED;
677 debugOutput(DEBUG_LEVEL_VERBOSE, "Get current clock source: %d\n",
678 gccmd.m_clock);
680 return gccmd.m_clock;
682 int Device::getSamplingFrequency()
684 EfcGetClockCmd gccmd;
685 if (!getClock(gccmd))
686 return 0;
688 debugOutput(DEBUG_LEVEL_VERBOSE, "Get current sample rate: %d\n",
689 gccmd.m_samplerate);
691 return gccmd.m_samplerate;
694 bool Device::setClock(EfcSetClockCmd sccmd)
696 if (!doEfcOverAVC(sccmd)) {
697 debugError("Could not set clock info\n");
698 return false;
701 /* Cache clock source for fallback. */
702 m_current_clock = sccmd.m_clock;
704 return true;
706 bool Device::setClockSrc(uint32_t id)
708 bool err;
710 EfcGetClockCmd gccmd;
711 err = getClock(gccmd);
712 if (!err)
713 return err;
715 EfcSetClockCmd sccmd;
716 sccmd.m_clock = id;
717 sccmd.m_samplerate = gccmd.m_samplerate;
718 sccmd.m_index = 0;
720 err = setClock(sccmd);
721 if (err)
722 debugOutput(DEBUG_LEVEL_VERBOSE, "Set current clock source: %d\n",
723 sccmd.m_clock);
725 return err;
727 bool Device::setSamplingFrequency(int samplerate)
729 bool err;
731 EfcGetClockCmd gccmd;
732 err = getClock(gccmd);
733 if (!err)
734 return err;
736 EfcSetClockCmd sccmd;
737 sccmd.m_clock = gccmd.m_clock;
738 sccmd.m_samplerate = samplerate;
739 sccmd.m_index = 0;
741 err = setClock(sccmd);
742 if (err)
743 debugOutput(DEBUG_LEVEL_VERBOSE, "Set current sample rate: %d\n",
744 sccmd.m_samplerate);
746 return err;
749 bool
750 Device::lockFlash(bool lock) {
751 // some hardware doesn't need/support flash lock
752 if (m_HwInfo.hasDSP()) {
753 debugOutput(DEBUG_LEVEL_VERBOSE, "flash lock not needed\n");
754 return true;
757 EfcFlashLockCmd cmd;
758 cmd.m_lock = lock;
760 if(!doEfcOverAVC(cmd)) {
761 debugError("Flash lock failed\n");
762 return false;
764 return true;
767 bool
768 Device::writeFlash(uint32_t start, uint32_t len, uint32_t* buffer) {
770 if(len <= 0 || 0xFFFFFFFF - len*4 < start) {
771 debugError("bogus start/len: 0x%08X / %u\n", start, len);
772 return false;
774 if(start & 0x03) {
775 debugError("start address not quadlet aligned: 0x%08X\n", start);
776 return false;
779 uint32_t start_addr = start;
780 uint32_t stop_addr = start + len*4;
781 uint32_t *target_buffer = buffer;
783 EfcFlashWriteCmd cmd;
784 // write EFC_FLASH_SIZE_BYTES at a time
785 for(start_addr = start; start_addr < stop_addr; start_addr += EFC_FLASH_SIZE_BYTES) {
786 cmd.m_address = start_addr;
787 unsigned int quads_to_write = (stop_addr - start_addr)/4;
788 if (quads_to_write > EFC_FLASH_SIZE_QUADS) {
789 quads_to_write = EFC_FLASH_SIZE_QUADS;
791 cmd.m_nb_quadlets = quads_to_write;
792 for(unsigned int i=0; i<quads_to_write; i++) {
793 cmd.m_data[i] = *target_buffer;
794 target_buffer++;
796 if(!doEfcOverAVC(cmd)) {
797 debugError("Flash write failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_write);
798 return false;
801 return true;
804 bool
805 Device::readFlash(uint32_t start, uint32_t len, uint32_t* buffer) {
807 if(len <= 0 || 0xFFFFFFFF - len*4 < start) {
808 debugError("bogus start/len: 0x%08X / %u\n", start, len);
809 return false;
811 if(start & 0x03) {
812 debugError("start address not quadlet aligned: 0x%08X\n", start);
813 return false;
816 uint32_t start_addr = start;
817 uint32_t stop_addr = start + len*4;
818 uint32_t *target_buffer = buffer;
820 EfcFlashReadCmd cmd;
821 // read EFC_FLASH_SIZE_BYTES at a time
822 for(start_addr = start; start_addr < stop_addr; start_addr += EFC_FLASH_SIZE_BYTES) {
823 unsigned int quads_to_read = (stop_addr - start_addr)/4;
824 if (quads_to_read > EFC_FLASH_SIZE_QUADS) {
825 quads_to_read = EFC_FLASH_SIZE_QUADS;
827 uint32_t quadlets_read = 0;
828 int ntries = 10000;
829 do {
830 cmd.m_address = start_addr + quadlets_read*4;
831 unsigned int new_to_read = quads_to_read - quadlets_read;
832 cmd.m_nb_quadlets = new_to_read;
833 if(!doEfcOverAVC(cmd)) {
834 debugError("Flash read failed for block 0x%08X (%d quadlets)\n", start_addr, quads_to_read);
835 return false;
837 if(cmd.m_nb_quadlets != new_to_read) {
838 debugOutput(DEBUG_LEVEL_VERBOSE,
839 "Flash read didn't return enough data (%u/%u) \n",
840 cmd.m_nb_quadlets, new_to_read);
841 // continue trying
843 quadlets_read += cmd.m_nb_quadlets;
845 // copy content
846 for(unsigned int i=0; i<cmd.m_nb_quadlets; i++) {
847 *target_buffer = cmd.m_data[i];
848 target_buffer++;
850 } while(quadlets_read < quads_to_read && ntries--);
851 if(ntries==0) {
852 debugError("deadlock while reading flash\n");
853 return false;
856 return true;
859 bool
860 Device::eraseFlash(uint32_t addr) {
861 if(addr & 0x03) {
862 debugError("start address not quadlet aligned: 0x%08X\n", addr);
863 return false;
865 EfcFlashEraseCmd cmd;
866 cmd.m_address = addr;
867 if(!doEfcOverAVC(cmd)) {
868 if (cmd.m_header.retval == EfcCmd::eERV_FlashBusy) {
869 return true;
871 debugError("Flash erase failed for block 0x%08X\n", addr);
872 return false;
874 return true;
877 bool
878 Device::eraseFlashBlocks(uint32_t start_address, unsigned int nb_quads)
880 uint32_t blocksize_bytes;
881 uint32_t blocksize_quads;
882 unsigned int quads_left = nb_quads;
883 bool success = true;
885 const unsigned int max_nb_tries = 10;
886 unsigned int nb_tries = 0;
888 do {
889 // the erase block size is fixed by the HW, and depends
890 // on the flash section we're in
891 if (start_address < MAINBLOCKS_BASE_OFFSET_BYTES)
892 blocksize_bytes = PROGRAMBLOCK_SIZE_BYTES;
893 else
894 blocksize_bytes = MAINBLOCK_SIZE_BYTES;
895 start_address &= ~(blocksize_bytes - 1);
896 blocksize_quads = blocksize_bytes / 4;
898 uint32_t verify[blocksize_quads];
900 // corner case: requested to erase less than one block
901 if (blocksize_quads > quads_left) {
902 blocksize_quads = quads_left;
905 // do the actual erase
906 if (!eraseFlash(start_address)) {
907 debugWarning("Could not erase flash block at 0x%08X\n", start_address);
908 success = false;
909 } else {
910 // wait for the flash to become ready again
911 if (!waitForFlash(ECHO_FLASH_ERASE_TIMEOUT_MILLISECS)) {
912 debugError("Wait for flash timed out at address 0x%08X\n", start_address);
913 return false;
916 // verify that the block is empty as an extra precaution
917 if (!readFlash(start_address, blocksize_quads, verify)) {
918 debugError("Could not read flash block at 0x%08X\n", start_address);
919 return false;
922 // everything should be 0xFFFFFFFF if the erase was successful
923 for (unsigned int i = 0; i < blocksize_quads; i++) {
924 if (0xFFFFFFFF != verify[i]) {
925 debugWarning("Flash erase verification failed.\n");
926 success = false;
927 break;
932 if (success) {
933 start_address += blocksize_bytes;
934 quads_left -= blocksize_quads;
935 nb_tries = 0;
936 } else {
937 nb_tries++;
939 if (nb_tries > max_nb_tries) {
940 debugError("Needed too many tries to erase flash at 0x%08X\n", start_address);
941 return false;
943 } while (quads_left > 0);
945 return true;
948 bool
949 Device::waitForFlash(unsigned int msecs)
951 bool ready;
953 EfcFlashGetStatusCmd statusCmd;
954 const unsigned int time_to_sleep_usecs = 10000;
955 int wait_cycles = msecs * 1000 / time_to_sleep_usecs;
957 do {
958 if (!doEfcOverAVC(statusCmd)) {
959 debugError("Could not read flash status\n");
960 return false;
962 if (statusCmd.m_header.retval == EfcCmd::eERV_FlashBusy) {
963 ready = false;
964 } else {
965 ready = statusCmd.m_ready;
967 usleep(time_to_sleep_usecs);
968 } while (!ready && wait_cycles--);
970 if(wait_cycles == 0) {
971 debugError("Timeout while waiting for flash\n");
972 return false;
975 return ready;
978 uint32_t
979 Device::getSessionBase()
981 EfcFlashGetSessionBaseCmd cmd;
982 if(!doEfcOverAVC(cmd)) {
983 debugError("Could not get session base address\n");
984 return 0; // FIXME: arbitrary
986 return cmd.m_address;
990 } // FireWorks