aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/thinkpad_acpi.c
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2010-05-16 18:45:33 -0400
committerHenrique de Moraes Holschuh <hmh@hmh.eng.br>2010-05-16 18:45:33 -0400
commit77775838bb76173d7a1ed28f75dfe388962aceca (patch)
treef0d35d884b68ab56929a06ca7782c073d80119c5 /drivers/platform/x86/thinkpad_acpi.c
parent7a43f788988ac47b21ce258197c5014b5249c9f5 (diff)
thinkpad-acpi: let other subdrivers know backlight level range
Extract the backlight level range size detection from the brightness subdriver, and allow the other subdrivers access to that information. This also allows us to relocate some code to a more convenient place. The moved code was largerly unmodified, except for the return type of tpacpi_check_std_acpi_brightness_support(), which now is correctly marked as returning "unsigned int", and and two cosmetic fixes to make checkpatch.pl happy. Fixes for the NVRAM polling mode for the brightness hotkeys will need this. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Diffstat (limited to 'drivers/platform/x86/thinkpad_acpi.c')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c251
1 files changed, 140 insertions, 111 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index a768a69d58d2..b03bf5153b0f 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -304,8 +304,8 @@ static struct {
304 u32 hotkey_tablet:1; 304 u32 hotkey_tablet:1;
305 u32 light:1; 305 u32 light:1;
306 u32 light_status:1; 306 u32 light_status:1;
307 u32 bright_16levels:1;
308 u32 bright_acpimode:1; 307 u32 bright_acpimode:1;
308 u32 bright_unkfw:1;
309 u32 wan:1; 309 u32 wan:1;
310 u32 uwb:1; 310 u32 uwb:1;
311 u32 fan_ctrl_status_undef:1; 311 u32 fan_ctrl_status_undef:1;
@@ -368,6 +368,9 @@ struct tpacpi_led_classdev {
368 unsigned int led; 368 unsigned int led;
369}; 369};
370 370
371/* brightness level capabilities */
372static unsigned int bright_maxlvl; /* 0 = unknown */
373
371#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 374#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
372static int dbg_wlswemul; 375static int dbg_wlswemul;
373static int tpacpi_wlsw_emulstate; 376static int tpacpi_wlsw_emulstate;
@@ -1051,80 +1054,6 @@ static void tpacpi_disable_brightness_delay(void)
1051 "ACPI backlight control delay disabled\n"); 1054 "ACPI backlight control delay disabled\n");
1052} 1055}
1053 1056
1054static int __init tpacpi_query_bcl_levels(acpi_handle handle)
1055{
1056 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1057 union acpi_object *obj;
1058 int rc;
1059
1060 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
1061 obj = (union acpi_object *)buffer.pointer;
1062 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
1063 printk(TPACPI_ERR "Unknown _BCL data, "
1064 "please report this to %s\n", TPACPI_MAIL);
1065 rc = 0;
1066 } else {
1067 rc = obj->package.count;
1068 }
1069 } else {
1070 return 0;
1071 }
1072
1073 kfree(buffer.pointer);
1074 return rc;
1075}
1076
1077static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
1078 u32 lvl, void *context, void **rv)
1079{
1080 char name[ACPI_PATH_SEGMENT_LENGTH];
1081 struct acpi_buffer buffer = { sizeof(name), &name };
1082
1083 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
1084 !strncmp("_BCL", name, sizeof(name) - 1)) {
1085 BUG_ON(!rv || !*rv);
1086 **(int **)rv = tpacpi_query_bcl_levels(handle);
1087 return AE_CTRL_TERMINATE;
1088 } else {
1089 return AE_OK;
1090 }
1091}
1092
1093/*
1094 * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
1095 */
1096static int __init tpacpi_check_std_acpi_brightness_support(void)
1097{
1098 int status;
1099 int bcl_levels = 0;
1100 void *bcl_ptr = &bcl_levels;
1101
1102 if (!vid_handle) {
1103 TPACPI_ACPIHANDLE_INIT(vid);
1104 }
1105 if (!vid_handle)
1106 return 0;
1107
1108 /*
1109 * Search for a _BCL method, and execute it. This is safe on all
1110 * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
1111 * BIOS in ACPI backlight control mode. We do NOT have to care
1112 * about calling the _BCL method in an enabled video device, any
1113 * will do for our purposes.
1114 */
1115
1116 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
1117 tpacpi_acpi_walk_find_bcl, NULL, NULL,
1118 &bcl_ptr);
1119
1120 if (ACPI_SUCCESS(status) && bcl_levels > 2) {
1121 tp_features.bright_acpimode = 1;
1122 return (bcl_levels - 2);
1123 }
1124
1125 return 0;
1126}
1127
1128static void printk_deprecated_attribute(const char * const what, 1057static void printk_deprecated_attribute(const char * const what,
1129 const char * const details) 1058 const char * const details)
1130{ 1059{
@@ -3420,11 +3349,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3420 } 3349 }
3421 3350
3422 /* Do not issue duplicate brightness change events to 3351 /* Do not issue duplicate brightness change events to
3423 * userspace */ 3352 * userspace. tpacpi_detect_brightness_capabilities() must have
3424 if (!tp_features.bright_acpimode) 3353 * been called before this point */
3425 /* update bright_acpimode... */
3426 tpacpi_check_std_acpi_brightness_support();
3427
3428 if (tp_features.bright_acpimode && acpi_video_backlight_support()) { 3354 if (tp_features.bright_acpimode && acpi_video_backlight_support()) {
3429 printk(TPACPI_INFO 3355 printk(TPACPI_INFO
3430 "This ThinkPad has standard ACPI backlight " 3356 "This ThinkPad has standard ACPI backlight "
@@ -5989,7 +5915,7 @@ static unsigned int tpacpi_brightness_nvram_get(void)
5989 lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) 5915 lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
5990 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) 5916 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
5991 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; 5917 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
5992 lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07; 5918 lnvram &= bright_maxlvl;
5993 5919
5994 return lnvram; 5920 return lnvram;
5995} 5921}
@@ -6098,8 +6024,7 @@ static int brightness_set(unsigned int value)
6098{ 6024{
6099 int res; 6025 int res;
6100 6026
6101 if (value > ((tp_features.bright_16levels)? 15 : 7) || 6027 if (value > bright_maxlvl || value < 0)
6102 value < 0)
6103 return -EINVAL; 6028 return -EINVAL;
6104 6029
6105 vdbg_printk(TPACPI_DBG_BRGHT, 6030 vdbg_printk(TPACPI_DBG_BRGHT,
@@ -6174,6 +6099,80 @@ static struct backlight_ops ibm_backlight_data = {
6174 6099
6175/* --------------------------------------------------------------------- */ 6100/* --------------------------------------------------------------------- */
6176 6101
6102static int __init tpacpi_query_bcl_levels(acpi_handle handle)
6103{
6104 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
6105 union acpi_object *obj;
6106 int rc;
6107
6108 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
6109 obj = (union acpi_object *)buffer.pointer;
6110 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
6111 printk(TPACPI_ERR "Unknown _BCL data, "
6112 "please report this to %s\n", TPACPI_MAIL);
6113 rc = 0;
6114 } else {
6115 rc = obj->package.count;
6116 }
6117 } else {
6118 return 0;
6119 }
6120
6121 kfree(buffer.pointer);
6122 return rc;
6123}
6124
6125static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
6126 u32 lvl, void *context, void **rv)
6127{
6128 char name[ACPI_PATH_SEGMENT_LENGTH];
6129 struct acpi_buffer buffer = { sizeof(name), &name };
6130
6131 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
6132 !strncmp("_BCL", name, sizeof(name) - 1)) {
6133 BUG_ON(!rv || !*rv);
6134 **(int **)rv = tpacpi_query_bcl_levels(handle);
6135 return AE_CTRL_TERMINATE;
6136 } else {
6137 return AE_OK;
6138 }
6139}
6140
6141/*
6142 * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
6143 */
6144static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
6145{
6146 int status;
6147 int bcl_levels = 0;
6148 void *bcl_ptr = &bcl_levels;
6149
6150 if (!vid_handle)
6151 TPACPI_ACPIHANDLE_INIT(vid);
6152
6153 if (!vid_handle)
6154 return 0;
6155
6156 /*
6157 * Search for a _BCL method, and execute it. This is safe on all
6158 * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
6159 * BIOS in ACPI backlight control mode. We do NOT have to care
6160 * about calling the _BCL method in an enabled video device, any
6161 * will do for our purposes.
6162 */
6163
6164 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
6165 tpacpi_acpi_walk_find_bcl, NULL, NULL,
6166 &bcl_ptr);
6167
6168 if (ACPI_SUCCESS(status) && bcl_levels > 2) {
6169 tp_features.bright_acpimode = 1;
6170 return bcl_levels - 2;
6171 }
6172
6173 return 0;
6174}
6175
6177/* 6176/*
6178 * These are only useful for models that have only one possibility 6177 * These are only useful for models that have only one possibility
6179 * of GPU. If the BIOS model handles both ATI and Intel, don't use 6178 * of GPU. If the BIOS model handles both ATI and Intel, don't use
@@ -6204,6 +6203,47 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6204 TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */ 6203 TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */
6205}; 6204};
6206 6205
6206/*
6207 * Returns < 0 for error, otherwise sets tp_features.bright_*
6208 * and bright_maxlvl.
6209 */
6210static void __init tpacpi_detect_brightness_capabilities(void)
6211{
6212 unsigned int b;
6213
6214 vdbg_printk(TPACPI_DBG_INIT,
6215 "detecting firmware brightness interface capabilities\n");
6216
6217 /* we could run a quirks check here (same table used by
6218 * brightness_init) if needed */
6219
6220 /*
6221 * We always attempt to detect acpi support, so as to switch
6222 * Lenovo Vista BIOS to ACPI brightness mode even if we are not
6223 * going to publish a backlight interface
6224 */
6225 b = tpacpi_check_std_acpi_brightness_support();
6226 switch (b) {
6227 case 16:
6228 bright_maxlvl = 15;
6229 printk(TPACPI_INFO
6230 "detected a 16-level brightness capable ThinkPad\n");
6231 break;
6232 case 8:
6233 case 0:
6234 bright_maxlvl = 7;
6235 printk(TPACPI_INFO
6236 "detected a 8-level brightness capable ThinkPad\n");
6237 break;
6238 default:
6239 printk(TPACPI_ERR
6240 "Unsupported brightness interface, "
6241 "please contact %s\n", TPACPI_MAIL);
6242 tp_features.bright_unkfw = 1;
6243 bright_maxlvl = b - 1;
6244 }
6245}
6246
6207static int __init brightness_init(struct ibm_init_struct *iibm) 6247static int __init brightness_init(struct ibm_init_struct *iibm)
6208{ 6248{
6209 struct backlight_properties props; 6249 struct backlight_properties props;
@@ -6217,14 +6257,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6217 quirks = tpacpi_check_quirks(brightness_quirk_table, 6257 quirks = tpacpi_check_quirks(brightness_quirk_table,
6218 ARRAY_SIZE(brightness_quirk_table)); 6258 ARRAY_SIZE(brightness_quirk_table));
6219 6259
6220 /* 6260 /* tpacpi_detect_brightness_capabilities() must have run already */
6221 * We always attempt to detect acpi support, so as to switch 6261
6222 * Lenovo Vista BIOS to ACPI brightness mode even if we are not 6262 /* if it is unknown, we don't handle it: it wouldn't be safe */
6223 * going to publish a backlight interface 6263 if (tp_features.bright_unkfw)
6224 */ 6264 return 1;
6225 b = tpacpi_check_std_acpi_brightness_support();
6226 if (b > 0) {
6227 6265
6266 if (tp_features.bright_acpimode) {
6228 if (acpi_video_backlight_support()) { 6267 if (acpi_video_backlight_support()) {
6229 if (brightness_enable > 1) { 6268 if (brightness_enable > 1) {
6230 printk(TPACPI_NOTICE 6269 printk(TPACPI_NOTICE
@@ -6253,15 +6292,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6253 return 1; 6292 return 1;
6254 } 6293 }
6255 6294
6256 if (b > 16) {
6257 printk(TPACPI_ERR
6258 "Unsupported brightness interface, "
6259 "please contact %s\n", TPACPI_MAIL);
6260 return 1;
6261 }
6262 if (b == 16)
6263 tp_features.bright_16levels = 1;
6264
6265 /* 6295 /*
6266 * Check for module parameter bogosity, note that we 6296 * Check for module parameter bogosity, note that we
6267 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be 6297 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
@@ -6292,12 +6322,9 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6292 if (tpacpi_brightness_get_raw(&b) < 0) 6322 if (tpacpi_brightness_get_raw(&b) < 0)
6293 return 1; 6323 return 1;
6294 6324
6295 if (tp_features.bright_16levels)
6296 printk(TPACPI_INFO
6297 "detected a 16-level brightness capable ThinkPad\n");
6298
6299 memset(&props, 0, sizeof(struct backlight_properties)); 6325 memset(&props, 0, sizeof(struct backlight_properties));
6300 props.max_brightness = (tp_features.bright_16levels) ? 15 : 7; 6326 props.max_brightness = bright_maxlvl;
6327 props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6301 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME, 6328 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
6302 NULL, NULL, 6329 NULL, NULL,
6303 &ibm_backlight_data, 6330 &ibm_backlight_data,
@@ -6320,7 +6347,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6320 "or not on your ThinkPad\n", TPACPI_MAIL); 6347 "or not on your ThinkPad\n", TPACPI_MAIL);
6321 } 6348 }
6322 6349
6323 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6324 backlight_update_status(ibm_backlight_device); 6350 backlight_update_status(ibm_backlight_device);
6325 6351
6326 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, 6352 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
@@ -6363,9 +6389,8 @@ static int brightness_read(struct seq_file *m)
6363 } else { 6389 } else {
6364 seq_printf(m, "level:\t\t%d\n", level); 6390 seq_printf(m, "level:\t\t%d\n", level);
6365 seq_printf(m, "commands:\tup, down\n"); 6391 seq_printf(m, "commands:\tup, down\n");
6366 seq_printf(m, "commands:\tlevel <level>" 6392 seq_printf(m, "commands:\tlevel <level> (<level> is 0-%d)\n",
6367 " (<level> is 0-%d)\n", 6393 bright_maxlvl);
6368 (tp_features.bright_16levels) ? 15 : 7);
6369 } 6394 }
6370 6395
6371 return 0; 6396 return 0;
@@ -6376,7 +6401,6 @@ static int brightness_write(char *buf)
6376 int level; 6401 int level;
6377 int rc; 6402 int rc;
6378 char *cmd; 6403 char *cmd;
6379 int max_level = (tp_features.bright_16levels) ? 15 : 7;
6380 6404
6381 level = brightness_get(NULL); 6405 level = brightness_get(NULL);
6382 if (level < 0) 6406 if (level < 0)
@@ -6384,13 +6408,13 @@ static int brightness_write(char *buf)
6384 6408
6385 while ((cmd = next_cmd(&buf))) { 6409 while ((cmd = next_cmd(&buf))) {
6386 if (strlencmp(cmd, "up") == 0) { 6410 if (strlencmp(cmd, "up") == 0) {
6387 if (level < max_level) 6411 if (level < bright_maxlvl)
6388 level++; 6412 level++;
6389 } else if (strlencmp(cmd, "down") == 0) { 6413 } else if (strlencmp(cmd, "down") == 0) {
6390 if (level > 0) 6414 if (level > 0)
6391 level--; 6415 level--;
6392 } else if (sscanf(cmd, "level %d", &level) == 1 && 6416 } else if (sscanf(cmd, "level %d", &level) == 1 &&
6393 level >= 0 && level <= max_level) { 6417 level >= 0 && level <= bright_maxlvl) {
6394 /* new level set */ 6418 /* new level set */
6395 } else 6419 } else
6396 return -EINVAL; 6420 return -EINVAL;
@@ -9130,6 +9154,11 @@ static int __init thinkpad_acpi_module_init(void)
9130 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 9154 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
9131 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; 9155 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
9132 } 9156 }
9157
9158 /* Init subdriver dependencies */
9159 tpacpi_detect_brightness_capabilities();
9160
9161 /* Init subdrivers */
9133 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 9162 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
9134 ret = ibm_init(&ibms_init[i]); 9163 ret = ibm_init(&ibms_init[i]);
9135 if (ret >= 0 && *ibms_init[i].param) 9164 if (ret >= 0 && *ibms_init[i].param)