[Desire Android Development] theGanymedes:
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.

Solution?

Well, it's something called "Battery Calibration" which more info can be found on this thread (especially check post #3 for the instructions) : http://xdaforums.com/showthread.php?t=765609

(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: http://xdaforums.com/showpost.php?p=23317695&postcount=2112

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:

if ((htc_batt_info.rep.level != 100) &&
(htc_batt_info.rep.guage_status_reg & 0x80) &&
(htc_batt_info.rep.batt_current <= 80) &&
(htc_batt_info.rep.full_acr == 0)) {

acr[0] = 0x0d;
acr[1] = 0x87;
w1_ds2784_write(di->w1_dev, acr, DS2784_REG_ACCUMULATE_CURR_MSB, 2);
htc_batt_info.rep.full_acr = 1;
pr_info("[HTC_BATT] Current Full ACR = %x %x\n", acr[0], acr[1]);
pr_info("[HTC_BATT] Recharging should set ACR to 100 percent\n");
}

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):

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 :) How much a scheduler matters is exemplified really :D

-----

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 )

---------------

Thank you very much for the donations of

Sally Mack

I really appreciate it :) You really save my life with your donations :)