You are on page 1of 4

[BATT Fix][GB SENSE Kernel] Calibration under Sense and solution for 15% shutdowns!

Hi everyone!
As a desire user myself, some of us are already familiar of what I'm talking about: the famous problem of
Desire shutting itself down while it was showing a percentage of 15 (or sometimes even higher) percentages!
This problem is a troublemaker, because it's causing the battery to deplete deeply - which is a bad thing for a
Li-Ion battery - and also causing you unguarded: you think that you have enough battery to make it home, but
hey; your device is dead!
The reason?
The cause of the problem is battery aging. Even though Li-Ion batteries don't have memory effect problems,
they are batteries after all and like every battery they get older and lose their capacity.
Ideally (old or new) the battery shows 3200 mV when empty and 4180 (sometimes 4200) mV when it's full.
This never changes unlike NiMH batteries - it's why Li-Ion batteries are told "never to suffer from memory
effect". The thing is, cells get older in time and even though they always yield the same voltages, they might
not last the same (mAh value gets lower). This is called "aging" in batteries.
In HTC Desire device, there is a Battery Controller chip (it's Maxim DS2784 Chip) that is responsible with the
battery capacity, percentage estimation; as well as aging compensation. However, during my examinations
(since I did have this 15% shut down problem myself) I've noticed something major in the HTC Desire Sense
Kernel sources:
A small code piece in ds2784 battery driver which is written with a false assumption is causing your Desire to
think it has full "brand new" capacity, which is not the case if you're owner of an aged one! Due to this, your
device thinks it has more capacity, when it's actually empty (which occurs at 15-20% depending on the battery)
and shutting down at weird percentages.
Well, it's something called "Battery Calibration" which more info can be found on this thread (especially check
post #3 for the instructions) :
(It's Nexus One dev. forum, but don't mind it - the process is exactly the same for us)
The thing about this calibration is; you have to do it under CM or Oxygen ROM's, because it requires a
modified AOSP kernel. During my checks, I've seen that this is actually simply because the Sense kernel lacks
some sysfs entries - other than that, Sense driver is also capable of doing this calibration - with the help of Jon
Richard's "Battery Calibrator" (available at the Play Store (Market) ).
Also, the calibration data normally (I don't really know why) gets erased when you charge your device while off
- the way to fix this is available in here:
OK.. Is this all?
No. Actually this part is more important.
While I'm including this piece to the Sense Kernel, I've seen the following buggy code piece, which is resetting
your battery capacity to 1392 mA - which is wrong (too much) if your battery is aged one:
Noticed the "acr" part? That's the part where the driver wrongly assigning 1393 mAh to the DS2784 chip.
If you're to read DS2784 battery specification, under "ACR Housekeeping" part, the following is written ;(ACR
- Accumulated Capacity register - the register which shows your current capacity of battery as mAh):

ACR Housekeeping
The ACR value is adjusted occasionally to maintain the coulomb count within the model curve boundaries.
the battery is charged to full (CHGTF set), the ACR is set equal to the age scaled full lookup value at the
It clearly states that the ACR value, by chip itself, is already updated to the Full value available in ROM chip!
The driver doesn't need to do that (and doesn't need to do that WRONG AT ALL!).
This is the problem, because we calibrate our batteries, and then simply because of a buggy assignment of the
driver, we lose all the calibration we made!
Cut the story.. Can you fix this?
Well, already did. Attached to the end of this post, there is a "ds2784_battery.c" file which all the stuff I
mentioned in this post is applied to. In the kernel source, change in the kernel source dir
drivers/power/ds2784_battery.c file with the one I provided and recompile the kernel - voila, you can now
calibrate your battery and it no longer will screw your calibration.
Diff patch?
Available below.
Do I have to compile kernel myself? I'm not a geek like you, man!
Flashable recovery zip for kernel is added to the post (named ahmet-exp4_*.zip)!
And here is what completes the circle: The Battery Calibrator App, modified to work with our kernel!
Can be downloaded here
EDIT: I've added the patch file, and also changed the source file itself - I mistakenly forgot to uncomment the
parts which include the sysfs interface, sorry
ADDENDUM (11.03.12): CFS Version is included to the post. Soon, I shall include the Droidzone's battfix into
it for high capacity batteries as well, but I kinda think that Droidzone's fix is "not complete" so I'll rewrite it
from scratch and thus it does take some time. I guess I can put it next weekend.
ADDENDUM (13.03.12): An improved (?) version of Droidzone's Extended Battery fix has been enabled into
the battery driver. Also, HAVS and SVS versions are added for those who prefer (version string does keep these
info too, if you forget in the future ). Diff patch is updated with the changes.
About extended batt-fix: Please note that I couldn't test the driver with an Extended battery, but I changed the
register parts, so it should run with any battery now since it reads all the data from the Chip's EEPROM instead
of using "hardcoded" values.
I also lowered the RSSI values in iw_wl.h file -> now your wifi should not drop so easily as it was in the past
(it was -91; I made it -110 ). Diff and edited file are added.
NOTE: My kernels do include nearly all I/O schedulers inside, so that you can change them as you like. If you
think your device doesn't perform well with the read/write operations to sd-card or MTD partitions, you can
change your I/O scheduler following way:
first, query the modes. You can google-search them to learn what they mean
--> cat /sys/block/mmcblk0/queue/scheduler (for mmc card)

--> cat /sys/block/mtdblockX/queue/scheduler (for internal memory. X becomes partition number: you can
query it with "cat /proc/mtd")
After this, you can pick one and apply that - for instance, say, you picked BFQ (I like it


--> echo "bfq" > /sys/block/mmcblk0/queue/scheduler (for mmc card - same applies to MTD too, if you need)
WHY BFQ? Because since SD-cards are Solid State Disks, so they don't have a mechanical head thus V(R) or
such schedulers which are optimised for access times are not so optimised for us I think. Instead, we should aim
towards the schedulers which takes "load" into consideration. BFQ is one of such schedulers.
I just checked it with my device, I tell you: the results are really amazing
exemplified really

How much a scheduler matters is

ADDENDUM (15 March 2012): CFS_SVS Version is updated to EXP5; because of some freeze up problems.
This version doesn't add anything else, so the old files still stay at EXP4 version
NOTE: I don't have 2Way Call recording sources, so my kernels don't have that feature (I cannot do everything,
can I :P )
Attached Files
BatteryCalibrator.apk - [Click for QR Code] (420.5 KB, 3505 views)
battery_130312.patch - [Click for QR Code] (13.1 KB, 209 views)
ds2784_battery.c - [Click for QR Code] (52.7 KB, 194 views)
wifi.patch - [Click for QR Code] (648 Bytes, 77 views)
wl_iw.h - [Click for QR Code] (7.5 KB, 42 views) - [Click for QR Code] (2.39 MB, 429 views) - [Click for QR Code] (2.38 MB, 194 views) - [Click for QR Code] (2.38 MB, 170 views) - [Click for QR Code] (2.39 MB, 681 views)

1- I open the app, but all the values look empty!
It's because you are not using a compatible kernel. As far as I know, only mine and Droidzone's latest kernels
do have the necessary patches, so switch to one of them.
2-I cannot drop to 3201 mV!
Some batteries cannot drop into that level, it's true. If your device turns off at higher voltages - like 3400 mV you can use this value for your registers instead. Please read the following pages or DS2784 chip use
your own value here (key registers are 62 and 63)
3- I drop to 3201 mV, it says "plug the charger" and I plugged. Still device turns off!
This is due to Sense kernels using a different power supply drivers than AOSP kernels; and due to Sense kernels
being "less sensitive" to the changes in battery status, thus not sensing the charger plugged it. In order to
overcome this, you must decrease your battery usage to a minimum so that your battery can last a little more just enough for Power Supply driver to sense it. To achive this:
1- At about 3350 mV values, turn on the Airplane mode; decrease the screen brightness to a very low value.
2- Once the program tells you to plug in, plug in right away and then turn your screen off with the power
If your device is not turned off within 2 minutes, your learning phase should have begun.
4- Still the phone turns off at 3201 mV!
It's very much likely those solutions above will work; but in case they don't and you want an "easier"
calibration - try calibration at some AOSP ROM like Cyanogen Mode ROM or Oxygen ROM (i.e. you have to
change your ROM at least temporarily) . AOSP kernels are more "open" to calibration.
5- Do I need "ahmet" kernels for AOSP?
No. All current AOSP Roms come with a modified kernel that's already supporting the calibration - and they are
also free of the Sense kernel bug mentioned above since they're completely written from scratch!
6- Can I change ROMs or Kernels after the calibration?
Changing ROMs are OK as long as you use ahmet or Droidzone's latest kernels (i.e. kernels that support
calibration) with your new ROM. You should flash the ROM prior to booting your device for the first time.
NOTE HERE: If you're to flash AOSP ROM, don't use ahmet-exp kernels with them since ahmet-exp kernels
are Sense kernels. All AOSP ROMs are calibration friendly anyway.
Changing kernels is a tad more tricky: you can change into the kernels that support calibration only: that is
either into ahmet-exp or Droidzone kernels.