[Atrix 4G Android Development] RogerPodacter:
This project started becaues at night the Atrix display is far too bright. I've successfully compiled the kernel (faux's) and made some changes to the display driver, and from there I found a world of useful info and hacks which enhance our display.

Kernel Update

I have compiled faux's kernel and attached it to this thread. please note, this is NOT the cyanogen version of the kernel, only standard ROM's that use faux123's kernel. i can compile the cyan kernel next. this kernel change is simple, it defaults both the display and buttons to the lowest 5mA display mode. this way a reboot puts you right into the lowest mode, and you can manually set reg 17 to higher as-needed. reg 17 will stay set until the next next reboot.

NOTE: THIS RAMDISK WAS MINE PULLED FROM THE STOCK ROM "WITH EXTRAS", SO PLEASE IF YOU TRY A DIFFERENT ROM HAVE A NAND BACKUP READY TO RESTORE JUST IN CASE!!! I HAVENT TRIED THE OTHER ROMS.

it is the zImage and Ramdisk, so it is flashed like:

boot into fastboot (volume down and power on, then vol down till fastboot shows, then vol up to select).

moto-fastboot flash:raw boot zImage ramdisk.gz

sorry it's not a flashable zip. i purposely uses RAR so nobody tries to flash it with CWM.

Update - The brightness limit of 30 has now been removed:

The autobrightness can now go all the way down to 00 even with your stock kernel and ROM. The limit was coming from the frameworks. I've re-compiled the frameworks for the stock ROM and also for Cyan pre-beta 3. There are 2 frameworks attached to this post, stock and cyanogen. download from this post and unzip your correct file for your ROM, and ADB push the files to your phone:

- boot to recovery
- mount system

adb push framework-res.apk /system/framework/framework-res.apk
adb reboot

Update - Cyanogen Pre Beta 4 frameworks added

unzup and flash with adb shown above.

Here is what is found in the frameworks, under res/values/arrays.xml:

10
50
100
150
200
700
1300
2000
3000
4000
5000
6000
7000
8000
9000

20
20
34
46
62
81
100
119
137
138
153
170
187
206
221
255

255
255
255
192
128
0
0
0
0
0
0
0
0
0
0
0

I changed the first value in config_autoBrightnessLcdBacklightValues from a 20 to a 2, and now in auto brightness mode the screen goes all the way down to 2.

Update:

We now have the proper official data sheet (link below) thanks to Saltinbas.

Documentation - Data Sheet

Our backlight chip is the lm3532, which is basically same as lm3530 which is used in the moto droid. i've read the entire data sheet twice and still trying to grasp everything. the data sheet can be found here:

http://www.national.com/ds/LM/LM3532.pdf

Not all registers are exactly the same, so some reverse engineering is needed.

Source Code (Kernel)

The relevant kernel source code:

leds-lm3532.c - Driver

leds-lm3532.h - Headers

board-mot-lights.c - Initialization

What I've Tried So Far

The first change I made was in board-mot-lights.c.

struct lm3532_platform_data lm3532_pdata = {
.flags = LM3532_CONFIG_BUTTON_BL | LM3532_HAS_WEBTOP,
.init = disp_backlight_init,
.power_on = disp_backlight_power_on,
.power_off = disp_backlight_power_off,

.ramp_time = 0, /* Ramp time in milliseconds */
.ctrl_a_fs_current = LM3532_26p6mA_FS_CURRENT,
.ctrl_b_fs_current = LM3532_8p2mA_FS_CURRENT,
.ctrl_a_mapping_mode = LM3532_LINEAR_MAPPING,
.ctrl_b_mapping_mode = LM3532_LINEAR_MAPPING,
.ctrl_a_pwm = 0x82,
};

I changed lines 99 and 100 to this:

.ctrl_a_fs_current = LM3532_5mA_FS_CURRENT,
.ctrl_b_fs_current = LM3532_5mA_FS_CURRENT,

Success

And bingo, display brightness reduced significantly lower than stock. the display has many different "modes" and I went right to the lowest on the list. Here are the brightness modes which can be found in the header file leds-lm3532.h:

Brightness Config Values (Header File)

#define LM3532_5mA_FS_CURRENT 0x00
#define LM3532_5p8mA_FS_CURRENT 0x01
#define LM3532_6p6mA_FS_CURRENT 0x02
#define LM3532_7p4mA_FS_CURRENT 0x03
#define LM3532_8p2mA_FS_CURRENT 0x04
#define LM3532_9mA_FS_CURRENT 0x05
#define LM3532_9p8mA_FS_CURRENT 0x06
#define LM3532_10p6mA_FS_CURRENT 0x07
#define LM3532_11p4mA_FS_CURRENT 0x08
#define LM3532_12p2mA_FS_CURRENT 0x09
#define LM3532_13mA_FS_CURRENT 0x0A
#define LM3532_13p8mA_FS_CURRENT 0x0B
#define LM3532_14p6mA_FS_CURRENT 0x0C
#define LM3532_15p4mA_FS_CURRENT 0x0D
#define LM3532_16p2mA_FS_CURRENT 0x0E
#define LM3532_17mA_FS_CURRENT 0x0F
#define LM3532_17p8mA_FS_CURRENT 0x10
#define LM3532_18p6mA_FS_CURRENT 0x11
#define LM3532_19p4mA_FS_CURRENT 0x12
#define LM3532_20p2mA_FS_CURRENT 0x13
#define LM3532_21mA_FS_CURRENT 0x14
#define LM3532_21p8mA_FS_CURRENT 0x15
#define LM3532_22p6mA_FS_CURRENT 0x16
#define LM3532_23p4mA_FS_CURRENT 0x17
#define LM3532_24p2mA_FS_CURRENT 0x18
#define LM3532_25mA_FS_CURRENT 0x19
#define LM3532_25p8mA_FS_CURRENT 0x1A
#define LM3532_26p6mA_FS_CURRENT 0x1B
#define LM3532_27p4mA_FS_CURRENT 0x1C
#define LM3532_28p2mA_FS_CURRENT 0x1D
#define LM3532_29mA_FS_CURRENT 0x1E
#define LM3532_29p8mA_FS_CURRENT 0x1F

Then i discovered that we don't even need to compile a new kernel to access this chip. We have the proper sysfs files already given to us by motorola engineers. here are some useful commands:

Terminal Commands

Use terminal app and navigate to:

su
cd sys/bus/i2c/drivers/lm3532/0-0038/leds/lcd-backlight

you can set any of the above modes you want. as an example let's say I want to set to maximum brightness mode, use the corresponding hex value in the header file from earlier, and type:

echo 17 1F > registers

that sets register 0x17 (the brightness register) with value 0x1F (the maximum brightness value from the list).

To set the minimum brightness:

echo 17 00 > registers

now for those of you who would like to help out with this and test other registers, you can see all register values by typing:

cat registers

that brings up this:

OUTPUT_CFG_REG (0x10) = 0xD4
START_UP_RAMP_REG (0x11) = 0xC0
RUN_TIME_RAMP_REG (0x12) = 0xC0
CTRL_A_PWM_REG (0x13) = 0x86
CTRL_B_PWM_REG (0x14) = 0x82
CTRL_C_PWM_REG (0x15) = 0x82
CTRL_A_BR_CFG_REG (0x16) = 0xE3
CTRL_A_FS_CURR_REG (0x17) = 0xFF
CTRL_B_BR_CFG_REG (0x18) = 0xE3
CTRL_B_FS_CURR_REG (0x19) = 0xE4
CTRL_C_BR_CFG_REG (0x1a) = 0xF1
CTRL_C_FS_CURR_REG (0x1b) = 0xF3
ENABLE_REG (0x1d) = 0xFF
FEEDBACK_ENABLE_REG (0x1c) = 0xF9
ALS1_RES_SEL_REG (0x20) = 0xE0
ALS2_RES_SEL_REG (0x21) = 0xE0
ALS_CFG_REG (0x23) = 0x44
ALS_ZONE_REG (0x24) = 0xF0
ALS_BR_ZONE_REG (0x25) = 0xF8
ALS_UP_ZONE_REG (0x26) = 0xF8
ZB1_REG (0x60) = 0x35
ZB2_REG (0x61) = 0x33
ZB3_REG (0x62) = 0x6A
ZB4_REG (0x63) = 0x66
CTRL_A_ZT1_REG (0x70) = 0x51
CTRL_A_ZT2_REG (0x71) = 0x66
CTRL_A_ZT3_REG (0x72) = 0x99
CTRL_A_ZT4_REG (0x73) = 0xCC
CTRL_A_ZT5_REG (0x74) = 0xFF
CTRL_B_ZT1_REG (0x75) = 0x00
CTRL_B_ZT2_REG (0x76) = 0x66
CTRL_B_ZT3_REG (0x77) = 0x99
CTRL_B_ZT4_REG (0x78) = 0xCC
CTRL_B_ZT5_REG (0x79) = 0xFF
CTRL_C_ZT1_REG (0x7a) = 0x33
CTRL_C_ZT2_REG (0x7b) = 0x66
CTRL_C_ZT3_REG (0x7c) = 0x99
CTRL_C_ZT4_REG (0x7d) = 0xCC
CTRL_C_ZT5_REG (0x7e) = 0xFF
VERSION_REG (0xcc) = 0xE4

You can set any register XX with any value YY as follows:

echo XX YY > registers

additional knowledge i've learned so far. Ctrl A is the main display. Ctrl B is the bottom buttons. Ctrl C is webtop. So all we really care about are Ctrl A registers for now.

Additional Info

The display is set to linear mapping mode by default. but changing to exponential mapping mode gives a huge range from minimum to maximum brightness. but it's still not ready for primetime. to try out exponential, type:

echo 16 01 > registers

now go to your main phone settings, display, brightness, and drag the slider from min to max and see the enormous full range now available. dont worry, to reset exponential mode just lock the screen with power button then unlock, exponential mode gets cleared. that can be fixed later in the kernel when we get it working better.

just setting to minimum brightness alone gives a huge increase in battery life for display-on time, specifically at night. there's more potential to get out of this chip so hopefully you guys can dig up more stuff that i'm missing.

at some point I can compile the kernel with any changes discovered from this thread, and perhaps we can merge the code changes back into the kernel repo if faux doesn't mind.

Problem 1

I don't fully understand the meaning of the header file brightness values. The names list current mA values, that is clear. but there are also other info in the name which I don't understand yet.

similarly, in the data sheet, they give detailed examples of how to calculate the current draw of each brightness mode, and walk thru setting up the general configuration register. i've been reverse engineering the registers by looking at the data sheet, seeing each 8 bits and what they are assigned, then using appropriate hex value to turn off and on each of those bits in the output config reg. i echo a value, and see the result. most of the time it matches the data sheet, but not always.

Problem 2

There are also 4 boundary zones which trigger the backlight to adjust it's brightness. i've attempted to set these boundaries to different values, but so far i've not had any success with this.

Problem 3

Before this all started, no matter what the display brightness only goes down to 30 from a range of 0-255. even changing all the modes i've listed above, in every one it stops at 30. you can check brightness level by:

cat brightness

I'm stumped on where the 30 limit is coming from.

Ultimately, we can permanently change the following code in board-mot-lights.c to whatever desired values we want to be in the kernel permanently:

struct lm3532_platform_data lm3532_pdata = {
.flags = LM3532_CONFIG_BUTTON_BL | LM3532_HAS_WEBTOP,
.init = disp_backlight_init,
.power_on = disp_backlight_power_on,
.power_off = disp_backlight_power_off,

.ramp_time = 0, /* Ramp time in milliseconds */
.ctrl_a_fs_current = LM3532_26p6mA_FS_CURRENT,
.ctrl_b_fs_current = LM3532_8p2mA_FS_CURRENT,
.ctrl_a_mapping_mode = LM3532_LINEAR_MAPPING,
.ctrl_b_mapping_mode = LM3532_LINEAR_MAPPING,
.ctrl_a_pwm = 0x82,
};

And a companion app could also be made to automate the setting of these registers and such.

last thing, above notice the PWM value being set to 0x82. this is pulse width modulation mode, and is a significant power saving method in electronics. fortunately this is turned on by default, which is what the value 0x82 is doing. i've experimented turning it off and on for the hell of it.

hope some experts can join in this thread and see how far it goes. any questions feel free to ask.