//***************************************************************************** // // Copyright (c) 2012 - 2015, Hefei LCFC Information Technology Co.Ltd. // And/or its affiliates. All rights reserved. // Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL. // Use is subject to license terms. // //****************************************************************************** /*++ Abstract: LCFC Battery common asl code definition, it's for all Hefei LBG projects. History: Date Name Version Change Notes 2014.07.29 Steven Wang V1.00 Initial Release. 2015.07.21 Steven Wang V1.01 Add OEM battery low and warning level policy value, low = 4%, warning = %10. 2015.08.19 Steven Wang V1.02 Fixed the battery icon show empty issue in Lenovo setting. 2015.08.27 Steven Wang V1.03 Add ECAV for EC opregion access safely. 2015.10.23 Steven Wang V1.04 Add AMD support 2016.01.20 Steven Wang V1.05 Optimized battery information reading way from ACPI 62&66 to 68&6c, due to there is possibility that OS get the incorrect value from EC by 62&66 when adding heavy loading, and cause unexpected behavior. 2016.07.07 Steven Wang V1.06 When charging with battery capcity no full, average currency is 0, this is not normal status need modify this value for Remaining Battery Life calculation from ACPI spec 2016.08.12 Steven Wang V1.07 Optimize the battery access method, due to 68 6C will conflict with some tool, change to 62 66 command method. 2018.04.01 Steven Wang V1.08 Fix the system battery charging to full time show 1 or 2 minutes issue when adding heavy loading w/ battery capability not high Module Name: Battery.asl Note: You must take care about the prompt string "LCFCTODO:" and customize your project. --*/ Device(BAT0) { Name(_HID,EISAID("PNP0C0A")) Name(_UID,0x01) Name(_PCL,Package(0x01){ \_SB }) Name(PBIF, Package() { 0x00000000, // Power Unit DWORD 0xFFFFFFFF, // Design Capacity DWORD, unknow capacity 0xFFFFFFFF, // Last Full Charge Capacity DWORD, unknow last full charged capacity 0x00000001, // Battery Technology DWORD 0xFFFFFFFF, // Design Voltage DWORD 0x00000000, // Design Capacity of Warning DWORD 0x00000000, // Design Capacity of Low DWORD 0x00000064, // Battery Capacity Granularity 1 DWORD 0x00000000, // Battery Capacity Granularity 2 DWORD "LCFC", // Model Number ASCIIZ "BAT20101001", // Serial Number ASCIIZ "LiP", // Battery Type ASCIIZ "LENOVO"}) // OEM Information ASCIIZ} Name(XBIF, Package() { 0x00000001, // Revision Integer 0x00000000, // Power Unit DWORD 0xFFFFFFFF, // Design Capacity DWORD, unknow capacity 0xFFFFFFFF, // Last Full Charge Capacity DWORD, unknow last full charged capacity 0x00000001, // Battery Technology DWORD 0xFFFFFFFF, // Design Voltage DWORD 0x00000000, // Design Capacity of Warning DWORD 0x00000000, // Design Capacity of Low DWORD 0x00000000, // Cycle Count DWORD 95000, // Measurement Accuracy DWORD 0xFFFFFFFF, // Max Sampling Time DWORD (Unavailable) 0xFFFFFFFF, // Min Sampling Time DWORD (Unavailable) 1000, // Max Averaging Interval DWORD (MSFT No specific requirement. 1sec ) 1000, // Min Averaging Interval DWORD (MSFT No specific requirement. 1sec ) 0x00000064, // Battery Capacity Granularity 1 DWORD 0x00000000, // Battery Capacity Granularity 2 DWORD "LCFC", // Model Number ASCIIZ "BAT20101001", // Serial Number ASCIIZ "LiP", // Battery Type ASCIIZ "LENOVO", // OEM Information ASCIIZ 0x00000001}) // Battery Swapping Capability DWORD Name(PBST,Package(0x04){ 0x01, 0x0A90, 0x1000, 0x2A30 }) Method(_STA,0,NotSerialized) { If(LEqual(ECON,1)) { If(EC0_SCOPE.EC0.ECAV){ If(LEqual(Acquire(EC0_SCOPE.EC0.LfcM, 0xA000),0x0)){ Store(EC0_SCOPE.EC0.BA1P,Local0) Release(EC0_SCOPE.EC0.LfcM) } } If(And(Local0,0x01)) { Return(0x1F) } Else { Return(0x0F) } } Else { Return(0x00) } } Method(_BIF,0,NotSerialized) { If(LEqual(EC0_SCOPE.EC0.ECAV,1)) { If(LEqual(Acquire(EC0_SCOPE.EC0.LfcM, 0xA000),0x0)){ Store(EC0_SCOPE.EC0.B1DC,Local0) Multiply(Local0,10,Local0) // mWh(Units:10mWh) Store(Local0,Index(PBIF,0x01)) Store(EC0_SCOPE.EC0.B1FC,Local0) Multiply(Local0,10,Local0) // mWh(Units:10mWh) Store(Local0,Index(PBIF,0x02)) Store(EC0_SCOPE.EC0.B1DV,Index(PBIF,0x04)) If(EC0_SCOPE.EC0.B1FC) { Store(Divide(Multiply(EC0_SCOPE.EC0.B1FC, 10),10), Index(PBIF,5)) Store(Divide(Multiply(EC0_SCOPE.EC0.B1DC, 10),100), Index(PBIF,7)) } Store("", Index(PBIF, 0x09)) // Device Name or Model number Store("", Index(PBIF, 0x0A)) // Serial Number Store("", Index(PBIF, 0x0B)) // Device Chemistry Store("", Index(PBIF, 0x0C)) // Manufaturer name Name (BDNT, Buffer(9) {0x00}) Store(EC0_SCOPE.EC0.BDN0, BDNT) Store(ToString(BDNT), Index(PBIF, 0x09)) // Device Name or Model number // // Serial Number // Store(EC0_SCOPE.EC0.B1SN, Local0) // // Prepare Buffer for Serial Number. Since it should be 0-0xFFFF, // assume 5 bytes length // Name( SERN, Buffer(){0x20,0x20,0x20,0x20,0x20,0x00}) Store(4, Local2) While(Local0) { Divide(Local0, 10, Local1,Local0) Add(Local1,0x30, Index(SERN,Local2)) Decrement(Local2) } Store(SERN, Index(PBIF, 0x0A)) // Serial Number // Device chemistry Name (DCH0, Buffer(10) {0x00}) Name (DCH1, "LION") Name (DCH2, "LiP") If (LEqual(EC0_SCOPE.EC0.B1TY, 1)) { Store(DCH1, DCH0) Store(ToString(DCH0), Index(PBIF, 0x0B)) } Else { Store(DCH2, DCH0) Store(ToString(DCH0), Index(PBIF, 0x0B)) } Name (BMNT, Buffer(10) {0x00}) Store(EC0_SCOPE.EC0.BMN0, BMNT) Store(ToString(BMNT), Index(PBIF, 0x0C)) // Manufaturer name Release(EC0_SCOPE.EC0.LfcM) } } Return(PBIF) } Method(_BIX,0,NotSerialized) { If(LEqual(EC0_SCOPE.EC0.ECAV,1)) { If(LEqual(Acquire(EC0_SCOPE.EC0.LfcM, 0xA000),0x0)){ Store(EC0_SCOPE.EC0.B1DC,Local0) Multiply(Local0,10,Local0) // mWh(Units:10mWh) Store(Local0,Index(XBIF,0x02)) Store(EC0_SCOPE.EC0.B1FC,Local0) Multiply(Local0,10,Local0) // mWh(Units:10mWh) Store(Local0,Index(XBIF,0x03)) Store(EC0_SCOPE.EC0.B1DV,Index(XBIF,0x05)) If(EC0_SCOPE.EC0.B1FC) { Store(Divide(Multiply(EC0_SCOPE.EC0.B1FC, 10),10), Index(XBIF,6)) Store(Divide(Multiply(EC0_SCOPE.EC0.B1DC, 10),100), Index(XBIF,0x0E)) } Store(EC0_SCOPE.EC0.B1CT,Index(XBIF,0x08)) //Cycle Count Store("", Index(XBIF, 0x10)) // Device Name or Model number Store("", Index(XBIF, 0x11)) // Serial Number Store("", Index(XBIF, 0x12)) // Device Chemistry Store("", Index(XBIF, 0x13)) // Manufaturer name Name (BDNT, Buffer(9) {0x00}) Store(EC0_SCOPE.EC0.BDN0, BDNT) Store(ToString(BDNT), Index(XBIF, 0x10)) // Device Name or Model number // // Serial Number // Store(EC0_SCOPE.EC0.B1SN, Local0) // // Prepare Buffer for Serial Number. Since it should be 0-0xFFFF, // assume 5 bytes length // Name( SERN, Buffer(){0x20,0x20,0x20,0x20,0x20,0x00}) Store(4, Local2) While(Local0) { Divide(Local0, 10, Local1,Local0) Add(Local1,0x30, Index(SERN,Local2)) Decrement(Local2) } Store(SERN, Index(XBIF, 0x11)) // Serial Number // Device chemistry Name (DCH0, Buffer(10) {0x00}) Name (DCH1, "LION") Name (DCH2, "LiP") If (LEqual(EC0_SCOPE.EC0.B1TY, 1)) { Store(DCH1, DCH0) Store(ToString(DCH0), Index(XBIF, 0x12)) } Else { Store(DCH2, DCH0) Store(ToString(DCH0), Index(XBIF, 0x12)) } Name (BMNT, Buffer(10) {0x00}) Store(EC0_SCOPE.EC0.BMN0, BMNT) Store(ToString(BMNT), Index(XBIF, 0x13)) // Manufaturer name Release(EC0_SCOPE.EC0.LfcM) } } Return(XBIF) } Name (OBST, 0) // Battery Status Name (OBAC, 0) // Battery Average Current Name (OBPR, 0) // Battery Present Rate Name (OBRC, 0) // Battery Remaining Capacity Name (OBPV, 0) // Battery Present Voltage Method(_BST,0,NotSerialized) { If(LEqual(EC0_SCOPE.EC0.ECAV,1)) { If(LEqual(Acquire(EC0_SCOPE.EC0.LfcM, 0xA000),0x0)){ Sleep(16) Store(EC0_SCOPE.EC0.B1ST, Local0) Store(DeRefOf(Index(PBST,0x00)), Local1) switch(And(Local0,0x07)) { case(0) { Store(And(Local1,0xF8),OBST) } case(1) { Store(Or(0x01,And(Local1,0xF8)),OBST) } case(2) { Store(Or(0x02,And(Local1,0xF8)),OBST) } case(4) { Store(Or(0x04,And(Local1,0xF8)),OBST) } } Sleep(16) Store(EC0_SCOPE.EC0.B1AC, OBAC) If(And(OBST,0x01)) // Check discharging status { If(LNotEqual(OBAC,Zero)) { Store(And(Not(OBAC),0x7FFF),OBAC) } } Else { // Charging status If(LNotEqual(EC0_SCOPE.EC0.FBFG,1)) { If(And(OBAC,0x8000)) { // When charging with battery capacity no full w/heavy loading, the total system required power may be over the // adapter output power,cause battery discharge to prevent the power overloading shutdown, // the average currency is negative, need modify this value for Remaining Battery Life calculation from ACPI spec // and the battery charging to full time calculation. Store(0,OBAC) } } } Sleep(16) Store(EC0_SCOPE.EC0.B1RC, OBRC) Sleep(16) Store(EC0_SCOPE.EC0.B1FV, OBPV) Multiply(OBRC,10,OBRC) // mWh(Units:10mWh) Store(Divide(Multiply(OBAC,OBPV),1000),OBPR) // Convert mAh and mV to mWh Store(OBST,Index(PBST,0x00)) Store(OBPR,Index(PBST,0x01)) Store(OBRC,Index(PBST,0x02)) Store(OBPV,Index(PBST,0x03)) Release(EC0_SCOPE.EC0.LfcM) } } Return(PBST) } }