Add patches accepted for 2.6.26-rc1
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / releases / upstream / 2.6.26-rc1 / 0006-ACPI-thinkpad-acpi-fix-brightness-dimming-control.patch
blobb358376d128406e573dc323ea5004b7eb9b8b599
1 From e11aecf1379e7c4a0293182096e38e5a336696b2 Mon Sep 17 00:00:00 2001
2 From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
3 Date: Sat, 26 Apr 2008 01:02:21 -0300
4 Subject: ACPI: thinkpad-acpi: fix brightness dimming control bug
6 ibm-acpi and thinkpad-acpi did not know about bit 5 of the EC backlight
7 level control register (EC 0x31), so it was always forced to zero on
8 any writes.
10 This would disable the BIOS option to *not* use a dimmer backlight level
11 scale while on battery, and who knows what else (there are two other
12 control bits of unknown function).
14 Bit 5 controls the "reduce backlight levels when on battery" optional
15 functionality (active low). Bits 6 and 7 are better left alone as well,
16 instead of being forced to zero.
18 Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
19 Signed-off-by: Len Brown <len.brown@intel.com>
20 ---
21 drivers/misc/thinkpad_acpi.c | 64 ++++++++++++++++++++++++++++++++----------
22 1 files changed, 49 insertions(+), 15 deletions(-)
24 diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
25 index 7dc6b73..5e25abc 100644
26 --- a/drivers/misc/thinkpad_acpi.c
27 +++ b/drivers/misc/thinkpad_acpi.c
28 @@ -4295,8 +4295,16 @@ static struct ibm_struct ecdump_driver_data = {
30 #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
32 +enum {
33 + TP_EC_BACKLIGHT = 0x31,
35 + /* TP_EC_BACKLIGHT bitmasks */
36 + TP_EC_BACKLIGHT_LVLMSK = 0x1F,
37 + TP_EC_BACKLIGHT_CMDMSK = 0xE0,
38 + TP_EC_BACKLIGHT_MAPSW = 0x20,
39 +};
41 static struct backlight_device *ibm_backlight_device;
42 -static int brightness_offset = 0x31;
43 static int brightness_mode;
44 static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
46 @@ -4305,16 +4313,24 @@ static struct mutex brightness_mutex;
48 * ThinkPads can read brightness from two places: EC 0x31, or
49 * CMOS NVRAM byte 0x5E, bits 0-3.
50 + *
51 + * EC 0x31 has the following layout
52 + * Bit 7: unknown function
53 + * Bit 6: unknown function
54 + * Bit 5: Z: honour scale changes, NZ: ignore scale changes
55 + * Bit 4: must be set to zero to avoid problems
56 + * Bit 3-0: backlight brightness level
57 + *
58 + * brightness_get_raw returns status data in the EC 0x31 layout
60 -static int brightness_get(struct backlight_device *bd)
61 +static int brightness_get_raw(int *status)
63 u8 lec = 0, lcmos = 0, level = 0;
65 if (brightness_mode & 1) {
66 - if (!acpi_ec_read(brightness_offset, &lec))
67 + if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec))
68 return -EIO;
69 - lec &= (tp_features.bright_16levels)? 0x0f : 0x07;
70 - level = lec;
71 + level = lec & TP_EC_BACKLIGHT_LVLMSK;
73 if (brightness_mode & 2) {
74 lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
75 @@ -4325,6 +4341,8 @@ static int brightness_get(struct backlight_device *bd)
78 if (brightness_mode == 3) {
79 + *status = lec; /* Prefer EC, CMOS is just a backing store */
80 + lec &= TP_EC_BACKLIGHT_LVLMSK;
81 if (lec == lcmos)
82 tp_warned.bright_cmos_ec_unsync = 0;
83 else {
84 @@ -4338,9 +4356,11 @@ static int brightness_get(struct backlight_device *bd)
86 return -EIO;
88 + } else {
89 + *status = level;
92 - return level;
93 + return 0;
96 /* May return EINTR which can always be mapped to ERESTARTSYS */
97 @@ -4348,19 +4368,22 @@ static int brightness_set(int value)
99 int cmos_cmd, inc, i, res;
100 int current_value;
101 + int command_bits;
103 - if (value > ((tp_features.bright_16levels)? 15 : 7))
104 + if (value > ((tp_features.bright_16levels)? 15 : 7) ||
105 + value < 0)
106 return -EINVAL;
108 res = mutex_lock_interruptible(&brightness_mutex);
109 if (res < 0)
110 return res;
112 - current_value = brightness_get(NULL);
113 - if (current_value < 0) {
114 - res = current_value;
115 + res = brightness_get_raw(&current_value);
116 + if (res < 0)
117 goto errout;
120 + command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK;
121 + current_value &= TP_EC_BACKLIGHT_LVLMSK;
123 cmos_cmd = value > current_value ?
124 TP_CMOS_BRIGHTNESS_UP :
125 @@ -4375,7 +4398,8 @@ static int brightness_set(int value)
126 goto errout;
128 if ((brightness_mode & 1) &&
129 - !acpi_ec_write(brightness_offset, i + inc)) {
130 + !acpi_ec_write(TP_EC_BACKLIGHT,
131 + (i + inc) | command_bits)) {
132 res = -EIO;
133 goto errout;;
135 @@ -4398,6 +4422,17 @@ static int brightness_update_status(struct backlight_device *bd)
136 bd->props.brightness : 0);
139 +static int brightness_get(struct backlight_device *bd)
141 + int status, res;
143 + res = brightness_get_raw(&status);
144 + if (res < 0)
145 + return 0; /* FIXME: teach backlight about error handling */
147 + return status & TP_EC_BACKLIGHT_LVLMSK;
150 static struct backlight_ops ibm_backlight_data = {
151 .get_brightness = brightness_get,
152 .update_status = brightness_update_status,
153 @@ -4462,8 +4497,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
154 if (brightness_mode > 3)
155 return -EINVAL;
157 - b = brightness_get(NULL);
158 - if (b < 0)
159 + if (brightness_get_raw(&b) < 0)
160 return 1;
162 if (tp_features.bright_16levels)
163 @@ -4481,7 +4515,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
165 ibm_backlight_device->props.max_brightness =
166 (tp_features.bright_16levels)? 15 : 7;
167 - ibm_backlight_device->props.brightness = b;
168 + ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
169 backlight_update_status(ibm_backlight_device);
171 return 0;
173 1.5.4.4