From 8789c2d0df069d1efe846e30b40e03ebd0166541 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Wed, 18 Jul 2007 23:45:43 -0300 Subject: [PATCH] --- yaml --- r: 62559 b: refs/heads/master c: 24d3b77467b6aaf59e38dce4aa86d05541858195 h: refs/heads/master i: 62557: 360752a17095795782cb3f707090a515c9c30f87 62555: 64f2cea6a3f36766013e5d62085d493243039450 62551: 4f5bdbbf561a7b6368649bd42769b87b7e5068fd 62543: 2c0d82c6cfacaf6dadd2f2d0dd8fb8315625775f 62527: bfed6b59aa4f1b29843bf5dbefbfc20161d72b86 v: v3 --- [refs] | 2 +- trunk/Documentation/thinkpad-acpi.txt | 6 +++ trunk/drivers/misc/Kconfig | 1 + trunk/drivers/misc/thinkpad_acpi.c | 62 +++++++++++++++++++++++---- trunk/drivers/misc/thinkpad_acpi.h | 7 +++ 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index 88988bc4ed26..42b3f21b9243 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d5a2f2f1d68e2da538ac28540cddd9ccc733b001 +refs/heads/master: 24d3b77467b6aaf59e38dce4aa86d05541858195 diff --git a/trunk/Documentation/thinkpad-acpi.txt b/trunk/Documentation/thinkpad-acpi.txt index c670363cf5a4..c145bcce2339 100644 --- a/trunk/Documentation/thinkpad-acpi.txt +++ b/trunk/Documentation/thinkpad-acpi.txt @@ -860,6 +860,12 @@ cannot be controlled. The backlight control has eight levels, ranging from 0 to 7. Some of the levels may not be distinct. +There are two interfaces to the firmware for brightness control, EC and CMOS. +To select which one should be used, use the brightness_mode module parameter: +brightness_mode=1 selects EC mode, brightness_mode=2 selects CMOS mode, +brightness_mode=3 selects both EC and CMOS. The driver tries to autodetect +which interface to use. + Procfs notes: The available commands are: diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 5197f9b9b65d..aaaa61ea4217 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -150,6 +150,7 @@ config THINKPAD_ACPI depends on X86 && ACPI select BACKLIGHT_CLASS_DEVICE select HWMON + select NVRAM ---help--- This is a driver for the IBM and Lenovo ThinkPad laptops. It adds support for Fn-Fx key combinations, Bluetooth control, video diff --git a/trunk/drivers/misc/thinkpad_acpi.c b/trunk/drivers/misc/thinkpad_acpi.c index 99500af651c1..5318eb272c61 100644 --- a/trunk/drivers/misc/thinkpad_acpi.c +++ b/trunk/drivers/misc/thinkpad_acpi.c @@ -2953,9 +2953,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); + if (!brightness_mode) { + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) + brightness_mode = 2; + else + brightness_mode = 3; + + dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", + brightness_mode); + } + + if (brightness_mode > 3) + return -EINVAL; + b = brightness_get(NULL); if (b < 0) - return b; + return 1; ibm_backlight_device = backlight_device_register( TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, @@ -2991,13 +3004,35 @@ static int brightness_update_status(struct backlight_device *bd) bd->props.brightness : 0); } +/* + * ThinkPads can read brightness from two places: EC 0x31, or + * CMOS NVRAM byte 0x5E, bits 0-3. + */ static int brightness_get(struct backlight_device *bd) { - u8 level; - if (!acpi_ec_read(brightness_offset, &level)) - return -EIO; + u8 lec = 0, lcmos = 0, level = 0; - level &= 0x7; + if (brightness_mode & 1) { + if (!acpi_ec_read(brightness_offset, &lec)) + return -EIO; + lec &= 7; + level = lec; + }; + if (brightness_mode & 2) { + lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) + & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) + >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; + level = lcmos; + } + + if (brightness_mode == 3 && lec != lcmos) { + printk(IBM_ERR + "CMOS NVRAM (%u) and EC (%u) do not agree " + "on display brightness level\n", + (unsigned int) lcmos, + (unsigned int) lec); + return -EIO; + } return level; } @@ -3007,14 +3042,20 @@ static int brightness_set(int value) int cmos_cmd, inc, i; int current_value = brightness_get(NULL); - value &= 7; + if (value > 7) + return -EINVAL; - cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; + cmos_cmd = value > current_value ? + TP_CMOS_BRIGHTNESS_UP : + TP_CMOS_BRIGHTNESS_DOWN; inc = value > current_value ? 1 : -1; + for (i = current_value; i != value; i += inc) { - if (issue_thinkpad_cmos_command(cmos_cmd)) + if ((brightness_mode & 2) && + issue_thinkpad_cmos_command(cmos_cmd)) return -EIO; - if (!acpi_ec_write(brightness_offset, i + inc)) + if ((brightness_mode & 1) && + !acpi_ec_write(brightness_offset, i + inc)) return -EIO; } @@ -4485,6 +4526,9 @@ module_param(force_load, bool, 0); static int fan_control_allowed; module_param_named(fan_control, fan_control_allowed, bool, 0); +static int brightness_mode; +module_param_named(brightness_mode, brightness_mode, int, 0); + #define IBM_PARAM(feature) \ module_param_call(feature, set_ibm_param, NULL, NULL, 0) diff --git a/trunk/drivers/misc/thinkpad_acpi.h b/trunk/drivers/misc/thinkpad_acpi.h index 09b2282fed0b..b7a4a888cc8b 100644 --- a/trunk/drivers/misc/thinkpad_acpi.h +++ b/trunk/drivers/misc/thinkpad_acpi.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -80,6 +81,11 @@ #define TP_CMOS_BRIGHTNESS_UP 4 #define TP_CMOS_BRIGHTNESS_DOWN 5 +/* ThinkPad CMOS NVRAM constants */ +#define TP_NVRAM_ADDR_BRIGHTNESS 0x5e +#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 +#define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 + #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") #define strlencmp(a,b) (strncmp((a), (b), strlen(b))) @@ -323,6 +329,7 @@ static int bluetooth_write(char *buf); static struct backlight_device *ibm_backlight_device; static int brightness_offset = 0x31; +static int brightness_mode; static int brightness_init(struct ibm_init_struct *iibm); static void brightness_exit(void);