Changeset 2452

Show
Ignore:
Timestamp:
10/27/13 21:12:17 (4 years ago)
Author:
mocchi
Message:

[Fireworks] add a workaround for Audiofire12 (and maybe Audiofire8)

EfcGetClockCmd? over FCP is often failed or return invalid data. This commit add retry for doEfcOverFCP().

When the trials are completely failed, for sampling rate operation, a fallback to 'input/output plug signal format' command is executed. This command seems to be supported by all models.

But the driver can't know current clock source via 'plug signal format' command. This commit add 'm_current_clock' member to keep the id. This member is updated by setClock(). When getClock() is faled even if this member is not set, fallback to internal clock.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/fireworks/fireworks_device.cpp

    r2394 r2452  
    3939 
    4040#include "libutil/PosixMutex.h" 
     41#include "libutil/SystemTimeSource.h" 
    4142 
    4243#include "IntelFlashMap.h" 
     
    4445#define ECHO_FLASH_ERASE_TIMEOUT_MILLISECS 2000 
    4546#define FIREWORKS_MIN_FIRMWARE_VERSION 0x04080000 
     47#define AVC_MAX_TRIAL           2 
     48#define AVC_RETRY_INTERVAL      200000 
    4649 
    4750#include <sstream> 
     
    187190    } 
    188191 
     192    m_current_clock = -1; 
     193 
    189194    m_efc_discovery_done = true; 
    190195    return true; 
     
    203208} 
    204209 
    205 bool  
    206 Device::doEfcOverAVC(EfcCmd &c) { 
     210bool Device::doEfcOverAVC(EfcCmd &c) 
     211
     212    int trial; 
     213 
    207214    EfcOverAVCCmd cmd( get1394Service() ); 
    208215    cmd.setCommandType( AVC::AVCCommand::eCT_Control ); 
     
    214221    cmd.m_cmd = &c; 
    215222 
    216     if ( !cmd.fire()) { 
    217         debugError( "EfcOverAVCCmd command failed\n" ); 
    218         c.showEfcCmd(); 
    219         return false; 
     223    for (trial = 0; trial < AVC_MAX_TRIAL; trial++) { 
     224        if (cmd.fire()) 
     225            break; 
     226        Util::SystemTimeSource::SleepUsecRelative(AVC_RETRY_INTERVAL); 
     227    } 
     228 
     229    if (trial == AVC_MAX_TRIAL) { 
     230            debugError( "EfcOverAVCCmd command failed\n" ); 
     231            c.showEfcCmd(); 
     232            return false; 
    220233    } 
    221234 
     
    543556    } 
    544557 
    545     result=setClock(s.id); 
     558    result = setClock(s.id); 
    546559 
    547560    // From the ECHO sources: 
     
    630643} 
    631644 
    632 uint32_t 
    633 Device::getClock() { 
     645uint32_t Device::getClock() 
     646
     647    uint32_t clock; 
     648 
    634649    EfcGetClockCmd gccmd; 
    635650    if (!doEfcOverAVC(gccmd)) { 
    636651        debugError("Could not get clock info\n"); 
    637         return EFC_CMD_HW_CLOCK_UNSPECIFIED; 
    638     } 
    639     debugOutput(DEBUG_LEVEL_VERBOSE, "Active clock: 0x%08X\n",gccmd.m_clock); 
     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; 
     663 
     664    debugOutput(DEBUG_LEVEL_VERBOSE, "Active clock: 0x%08X\n", clock); 
    640665    gccmd.showEfcCmd(); 
    641666 
    642     return gccmd.m_clock; 
    643 
    644  
    645 bool 
    646 Device::setClock(uint32_t id) { 
    647     EfcGetClockCmd gccmd; 
    648     if (!doEfcOverAVC(gccmd)) { 
    649         debugError("Could not get clock info\n"); 
    650         return false; 
    651     } 
     667    return clock; 
     668
     669 
     670bool Device::setClock(uint32_t id) 
     671
     672    int sampling_rate = getSamplingFrequency(); 
     673    if (!sampling_rate) 
     674        return false; 
     675 
    652676    debugOutput(DEBUG_LEVEL_VERBOSE, "Set clock: 0x%08X\n", id); 
    653677 
    654678    EfcSetClockCmd sccmd; 
    655679    sccmd.m_clock=id; 
    656     sccmd.m_samplerate=gccmd.m_samplerate; 
     680    sccmd.m_samplerate= sampling_rate; 
    657681    sccmd.m_index=0; 
    658682    if (!doEfcOverAVC(sccmd)) { 
     
    660684        return false; 
    661685    } 
     686 
     687    m_current_clock = id; 
    662688    return true; 
    663689} 
     
    904930 
    905931int 
    906 Device::getSamplingFrequency( ) { 
     932Device::getSamplingFrequency() 
     933
     934    int sampling_rate; 
     935 
    907936    EfcGetClockCmd gccmd; 
    908937    if (!doEfcOverAVC(gccmd)) { 
    909         debugError("Could not get clock info\n"); 
    910         return false; 
     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; 
     943        } 
     944        return sampling_rate; 
    911945    } 
    912946    return gccmd.m_samplerate; 
    913947} 
    914948bool 
    915 Device::setSamplingFrequency( int s ) 
    916 
    917     EfcGetClockCmd gccmd; 
    918     if (!doEfcOverAVC(gccmd)) { 
    919         debugError("Could not get clock info\n"); 
    920         return false; 
    921     } 
     949Device::setSamplingFrequency(int s) 
     950
     951    uint32_t clock = getClock(); 
     952    if (clock == EFC_CMD_HW_CLOCK_UNSPECIFIED) 
     953        return false; 
     954 
    922955    debugOutput(DEBUG_LEVEL_VERBOSE, "Set samplerate: %d\n", s); 
    923956 
    924957    EfcSetClockCmd sccmd; 
    925     sccmd.m_clock=gccmd.m_clock; 
    926     sccmd.m_samplerate=s; 
    927     sccmd.m_index=0; 
     958    sccmd.m_clock = clock; 
     959    sccmd.m_samplerate = s; 
     960    sccmd.m_index = 0; 
    928961    if (!doEfcOverAVC(sccmd)) { 
    929         debugError("Could not set sample rate\n"); 
    930         return false; 
     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; 
     966        } 
    931967    } 
    932968    return true; 
  • trunk/libffado/src/fireworks/fireworks_device.h

    r1910 r2452  
    141141    bool setClock(uint32_t); 
    142142 
     143    /* 
     144     * Audiofire12 often return wrong data for clock source. 
     145     * This member is used to cache the latest clock source change. 
     146     */ 
     147    int m_current_clock; 
     148 
    143149    uint32_t            m_efc_version; 
    144150