Esempio n. 1
0
/****************************************************************************
NAME    
    powerManagerGetLBIPM
    
DESCRIPTION
    Returns the Power level to use for Low Battery Intelligent Power 
    Management (LBIPM).
    Note will always return high level if this feature is disabled.
    
RETURNS
    void
*/
power_battery_level powerManagerGetLBIPM( void )                             
{
    PM_DEBUG(("PM: Battery Management %s\n", theSink.lbipmEnable ? "Enabled" : "Disabled"));
    PM_DEBUG(("PM: Using %s Level ", powerManagerIsChargerConnected() ? "Chg" : "Batt"));
    PM_DEBUG(("%d\n", powerManagerIsChargerConnected() ? POWER_BATT_LEVEL3 : theSink.battery_state));

    /* Get current battery level */
    if(theSink.lbipmEnable && !powerManagerIsChargerConnected())
        return theSink.battery_state;
    
    /* LBIPM disabled or charger is connected so use full power level */
    return POWER_BATT_LEVEL3;
}
Esempio n. 2
0
/****************************************************************************
NAME    
    powerManagerHandleVbatLow
    
DESCRIPTION
    Called when the battery voltage is detected to be in Battery Low state
*/
static void powerManagerHandleVbatLow( void )
{
    sinkState lSinkState = stateManagerGetState ();
    bool batt_was_low = powerManagerIsVbatLow();

    PM_DEBUG(("PM: Battery Low\n"));
    if(powerManagerIsChargerConnected() || lSinkState == deviceLimbo)
    {
        theSink.battery_state = POWER_BATT_LEVEL0;
    }
    else
    {
        theSink.battery_state = POWER_BATT_LOW;  
    }

    if(!batt_was_low || !powerManagerIsVbatLow())
    {
        /* update state indication to indicate low batt state change */
#ifndef NO_LED         
        LEDManagerIndicateState( lSinkState );
#endif        
    }
    
    AudioSetPower(powerManagerGetLBIPM());
}
Esempio n. 3
0
/*************************************************************************
NAME    
    InitUserFeatures
    
DESCRIPTION
    This function initialises all of the user features - this will result in a
    poweron message if a user event is configured correctly and the device will 
    complete the power on

RETURNS

*/
void InitUserFeatures ( void ) 
{
    /* Set to a known value*/
    theSink.VoiceRecognitionIsActive = hfp_invalid_link ;
    theSink.buttons_locked           = FALSE;
    theSink.last_outgoing_ag = hfp_primary_link;
    theSink.csr_speech_recognition_is_active = FALSE ;


    if (theSink.VolumeOrientationIsInverted)
    {
        MessageSend ( &theSink.task , EventUsrVolumeOrientationInvert , 0 ) ;
    }
    
    /* set the LED enable disable state which now persists over a reset */
#ifndef NO_LED    
    if (theSink.theLEDTask->gLEDSEnabled)
    {
        LedManagerEnableLEDS () ;
    }
    else
    {
        LedManagerDisableLEDS () ;
    }
#endif
    /* Set inquiry tx power and RSSI inquiry mode */
    ConnectionWriteInquiryTx(theSink.conf2->rssi.tx_power);
    ConnectionWriteInquiryMode(&theSink.task, inquiry_mode_eir);   /* RSSI with EIR data */
    
    /* Check if we're here as result of a watchdog timeout */
    powerManagerCheckPanic();

    /*automatically power on the heasdet as soon as init is complete*/
    if(theSink.panic_reconnect)
    {
        INIT_DEBUG(("INIT: Recover to state 0x%X\n", theSink.rundata->old_state));
        if(theSink.rundata->old_state != deviceLimbo)
            MessageSend( &theSink.task , EventSysPowerOnPanic , NULL ) ;
        else
            theSink.panic_reconnect = FALSE;
    }
    else if((theSink.features.AutoPowerOnAfterInitialisation && !powerManagerIsChargerConnected()))
    {
        INIT_DEBUG(("INIT: Power On\n"));
        MessageSend( &theSink.task , EventUsrPowerOn , NULL ) ;
    }
    
    /* initialise the default volume levels */    
    theSink.volume_levels->a2dp_volume[0].masterVolume = ((theSink.conf1->volume_config.volume_control_config.no_of_steps * theSink.features.DefaultA2dpVolLevel)/ VOLUME_NUM_VOICE_STEPS);
    theSink.volume_levels->a2dp_volume[1].masterVolume = ((theSink.conf1->volume_config.volume_control_config.no_of_steps * theSink.features.DefaultA2dpVolLevel)/ VOLUME_NUM_VOICE_STEPS);

    /* set task to receive system messages */
    MessageSystemTask(&theSink.task);

    INIT_DEBUG(("INIT: complete\n"));
}
Esempio n. 4
0
/****************************************************************************
NAME    
    powerManagerHandleVbat
    
DESCRIPTION
    Called when the battery voltage is detected to be in a Normal state
*/
static void powerManagerHandleVbat(voltage_reading vbat, battery_level_source source)
{
    /* Get the event associated with this battery level */
    sink_battery_setting setting = theSink.conf1->power.bat_events[vbat.level];
    sinkEvents_t event = setting.event;

    PM_DEBUG(("PM: Battery Voltage 0x%02X (%dmV)\n", vbat.level, vbat.voltage));

    displayUpdateBatteryLevel(powerManagerIsChargerConnected());
    
    /* Send indication if not charging, not in limbo state and indication enabled for this source */
    if(!powerManagerIsChargerConnected() && (stateManagerGetState() != deviceLimbo) && (setting.sources & source))
    {
        PM_DEBUG(("PM: Sending Event 0x%X\n", event));
        MessageSend(&theSink.task, event, NULL);
    }
    
    switch(event)
    {
        case EventSysBatteryCritical:
            /* Always indicate critical battery */
            powerManagerHandleVbatCritical();
            usbSetVbatDead(TRUE);
            break;

        case EventSysBatteryLow:
            powerManagerHandleVbatLow();
            usbSetVbatDead(FALSE);
            break;

        case EventSysGasGauge0 :
        case EventSysGasGauge1 :
        case EventSysGasGauge2 :
        case EventSysGasGauge3 :
            powerManagerHandleVbatNormal(event - EventSysGasGauge0);
            usbSetVbatDead(FALSE);
            break;

        default:
            break;
    }
}
Esempio n. 5
0
/****************************************************************************
NAME    
    powerManagerHandleVbatCritical
    
DESCRIPTION
    Called when the battery voltage is detected to be in critical state
*/
static void powerManagerHandleVbatCritical( void )
{
    PM_DEBUG(("PM: Battery Critical\n"));
    /* Reset low batt warning */
    theSink.battery_state = POWER_BATT_CRITICAL;
    /* Power Off */
    if(!powerManagerIsChargerConnected())
    {
        powerManagerPowerOff();
    }
}
Esempio n. 6
0
/*******************************************************************************
NAME
    sinkUpgradePowerEventHandler

DESCRIPTION
    Handle power events and pass relevant ones to the Upgrade library.
    The upgrade library is interested in two kinds of events:
    1. When the library is in the 'normal' state then low battery when
       a charger is not connected triggers transition to
       the 'low battery error' state.
    2. When the library is in the 'low battery error' state, then connecting
       a charger (or when battery level will magically change from low to ok
       without connecting a charger) enables transition back to
       the 'normal' state.

PARAMETERS
    void

RETURNS
    void
*/
void sinkUpgradePowerEventHandler(void)
{
    upgrade_power_state_t power_state = upgrade_battery_ok;

    if(powerManagerIsChargerConnected())
    {
        power_state = upgrade_charger_connected;
    }
    else if(powerManagerIsVbatLow() || powerManagerIsVbatCritical())
    {
        /* Only when charger is not connected and battery level is low notify
         * the upgrade library. This is because purpose the upgrade library's
         * low battery handling is to prevent draining battery to much when
         * charger is not connected.
         */
        power_state = upgrade_battery_low;
    }

    UpgradePowerManagementSetState(power_state);
}
Esempio n. 7
0
/****************************************************************************
NAME    
    batteryNormal
    
DESCRIPTION
    Called when the battery voltage is detected to be in a Normal state
*/
static void powerManagerHandleVbatNormal(uint8 level)
{
#ifndef NO_LED     
    bool low_batt = powerManagerIsVbatLow();
#endif    
    PM_DEBUG(("PM: Battery Normal %d\n", level));
    MessageSend(&theSink.task, EventSysBatteryOk, 0);
    
    /* If charger connected send a charger gas gauge message (these don't have any functional use but can be associated with LEDs/tones) */
    if (powerManagerIsChargerConnected())
        MessageSend(&theSink.task, (EventSysChargerGasGauge0+level), 0);
    
    /* reset any low battery warning that may be in place */
    theSink.battery_state = POWER_BATT_LEVEL0 + level;
    csr2csrHandleAgBatteryRequestRes(level);
#ifndef NO_LED 
    /* when changing from low battery state to a normal state, refresh the led state pattern
       to replace the low battery pattern should it have been shown */
    if(low_batt) LEDManagerIndicateState(stateManagerGetState());
#endif    
    AudioSetPower(powerManagerGetLBIPM());
}
Esempio n. 8
0
/****************************************************************************
NAME 
    usbGetChargeCurrent
    
DESCRIPTION
    Get USB charger limits
    
RETURNS
    void
*/ 
sink_charge_current* usbGetChargeCurrent(void) 
{
    /* USB charging not enabled - no limits */
    if(!USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_BATTERY_CHARGING))
        return NULL;

    USB_DEBUG(("USB: Status "));

    /* Set charge current */
    switch(UsbAttachedStatus())
    {
        case HOST_OR_HUB:
            USB_DEBUG(("Host/Hub "));
            if(theSink.usb.suspended)
            {
                USB_DEBUG(("Suspended (Battery %s)\n", usbDeadBatteryProvision() ? "Dead" : "Okay"));
                if(usbDeadBatteryProvision())
                    return &theSink.usb.config.i_susp_db;
                else
                    return &theSink.usb.config.i_susp;
            }
            else if(powerManagerIsChargerFullCurrent())
            {
                USB_DEBUG(("%sEnumerated (Chg Full)\n", theSink.usb.enumerated ? "" : "Not "));
                if(!theSink.usb.enumerated)
                    return &theSink.usb.config.i_att;
                else
                    return &theSink.usb.config.i_conn;
            }
            else
            {
                USB_DEBUG(("%sEnumerated (Chg Partial)\n", theSink.usb.enumerated ? "" : "Not "));
                if(!theSink.usb.enumerated)
                    return &theSink.usb.config.i_att_trickle;
                else
                    return &theSink.usb.config.i_conn_trickle;
            }
#ifdef HAVE_FULL_USB_CHARGER_DETECTION
        case DEDICATED_CHARGER:
            USB_DEBUG(("Dedicated Charger Port%s\n", theSink.usb.vbus_okay ? "" : " Limited"));
            if(theSink.usb.vbus_okay)
                return &theSink.usb.config.i_dchg;
            else
                return &theSink.usb.config.i_lim;

        case HOST_OR_HUB_CHARGER:
        case CHARGING_PORT:
            USB_DEBUG(("Charger Port%s\n", theSink.usb.vbus_okay ? "" : " Limited"));
            if(theSink.usb.vbus_okay)
                return &theSink.usb.config.i_chg;
            else
                return &theSink.usb.config.i_lim;
#endif
        case DETACHED:
        default:
            USB_DEBUG(("Detached\n"));
            if(powerManagerIsChargerConnected())
                return &theSink.usb.config.i_disc;
            else
                return NULL;
    }
}
Esempio n. 9
0
/****************************************************************************
NAME    
    powerManagerChargerSetup
    
DESCRIPTION
    Update the charger settings based on USB limits and provided temperature
    reading. Updates current, trim, boost charge settings and enables or 
    disables the charger. On BC7 this can also be used to select whether the
    chip draws power from VBAT or VBYP.
    
RETURNS
    bool
*/
bool powerManagerChargerSetup(voltage_reading* vthm)
{
    /* Get temperature limits */
    sink_charge_current* usb_limits = usbGetChargeCurrent();
    sink_charge_setting setting;

    PM_DEBUG(("PM: Set Current\n"));

    if(vthm)
    {
        PM_DEBUG(("PM: Temp 0x%02X %dmV\n", vthm->level, vthm->voltage));
        setting = theSink.conf1->power.chg_settings[vthm->level];
    }
    else
    {
        PM_DEBUG(("PM: No Temp Reading\n"));
        setting = default_charge_setting;
    }
    
    if(usb_limits)
    {
        /* Apply minimum settings from combined limits */
        setting.current.charge = usb_limits->charge & setting.current.charge;
        if(usb_limits->boost < setting.current.boost)
            setting.current.boost = usb_limits->boost;
        setting.current.vsel = usb_limits->vsel | setting.current.vsel;
        setting.current.disable_leds = usb_limits->disable_leds | setting.current.disable_leds;
        if(usb_limits->current < setting.current.current)
            setting.current.current = usb_limits->current;
    }
    
    if(!powerManagerIsChargerConnected())
    {
        /* Must apply these settings when charger removed */
        setting.current.boost  = power_boost_disabled;
        setting.current.charge = FALSE;
#ifdef HAVE_VBAT_SEL
        setting.current.vsel   = vsel_bat;
    }
    else if(setting.current.power_off)
    {
        /* If outside operating temp cannot run from battery */
        setting.current.vsel = vsel_chg;
#endif
    }

    switch(setting.termination.type)
    {
        case vterm_voltage:
            /* BC7 allows us to set absolute termination voltage */
            PM_DEBUG(("PM: Termination Voltage %d\n", setting.termination.voltage * POWER_VSCALE));
            if(!PowerChargerSetVterm(setting.termination.voltage))
            {
                PM_DEBUG(("PM: Failed, disabling charger\n"));
                setting.current.charge = FALSE;
            }
        break;
        case vterm_trim:
            /* BC5 needs to modify trim setting */
            PM_DEBUG(("PM: Trim Termination Voltage -%d\n", setting.termination.trim));
            /* Disable charger if unable to trim */
            if(!PowerChargerReduceTrim(setting.termination.trim))
            {
                PM_DEBUG(("PM: Failed, disabling charger\n"));
                setting.current.charge = FALSE;
            }
        break;
        default:
            /* Use default termination voltage */
            PM_DEBUG(("PM: Termination Voltage Unchanged\n"));
        break;
    }

    /* Disable LEDs if required */
    PM_DEBUG(("PM: %s LEDs\n", setting.current.disable_leds ? "Disable" : "Enable"));
#ifndef NO_LED    
    LedManagerForceDisable(setting.current.disable_leds);
#endif    
    /* With VBAT_SEL we can wait for temp reading before enabling charger. 
       Without we enable charger by default and may need to turn it off. */
    if(vthm)
    {
        PM_DEBUG(("PM: Current %d, Boost 0x%X\n", setting.current.current, setting.current.boost));
        PM_DEBUG(("PM: Charger %s\n", (setting.current.charge ? "Enabled" : "Disabled")));
        
        /* Set charge current */
        PowerChargerSetCurrent(setting.current.current);
        PowerChargerSetBoost(setting.current.boost);

#ifdef HAVE_VBAT_SEL
    }
    /* Flip the switch to draw current from VBAT or VBYP */
    PM_DEBUG(("PM: SEL %s\n", ((setting.current.vsel == vsel_bat) ? "VBAT" : "VBYP") ));
    PsuConfigure(PSU_VBAT_SWITCH, PSU_SMPS_INPUT_SEL_VBAT, ((setting.current.vsel == vsel_bat) ? TRUE : FALSE));

    if(vthm)
    {
#endif
        /* Enable/disable charger */
        PowerChargerEnable(setting.current.charge);

        /* Power off */
        if(setting.current.power_off)
        {
            PM_DEBUG(("PM: Power Off\n"));
            powerManagerPowerOff();
        }
    }
    return((vthm) && (setting.current.charge));
}