aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c600
1 files changed, 376 insertions, 224 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 63290b33c879..4bdb13796e24 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -122,8 +122,14 @@ enum {
122 TP_NVRAM_POS_LEVEL_VOLUME = 0, 122 TP_NVRAM_POS_LEVEL_VOLUME = 0,
123}; 123};
124 124
125/* Misc NVRAM-related */
126enum {
127 TP_NVRAM_LEVEL_VOLUME_MAX = 14,
128};
129
125/* ACPI HIDs */ 130/* ACPI HIDs */
126#define TPACPI_ACPI_HKEY_HID "IBM0068" 131#define TPACPI_ACPI_HKEY_HID "IBM0068"
132#define TPACPI_ACPI_EC_HID "PNP0C09"
127 133
128/* Input IDs */ 134/* Input IDs */
129#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ 135#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */
@@ -299,8 +305,8 @@ static struct {
299 u32 hotkey_tablet:1; 305 u32 hotkey_tablet:1;
300 u32 light:1; 306 u32 light:1;
301 u32 light_status:1; 307 u32 light_status:1;
302 u32 bright_16levels:1;
303 u32 bright_acpimode:1; 308 u32 bright_acpimode:1;
309 u32 bright_unkfw:1;
304 u32 wan:1; 310 u32 wan:1;
305 u32 uwb:1; 311 u32 uwb:1;
306 u32 fan_ctrl_status_undef:1; 312 u32 fan_ctrl_status_undef:1;
@@ -363,6 +369,9 @@ struct tpacpi_led_classdev {
363 unsigned int led; 369 unsigned int led;
364}; 370};
365 371
372/* brightness level capabilities */
373static unsigned int bright_maxlvl; /* 0 = unknown */
374
366#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 375#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
367static int dbg_wlswemul; 376static int dbg_wlswemul;
368static int tpacpi_wlsw_emulstate; 377static int tpacpi_wlsw_emulstate;
@@ -480,6 +489,15 @@ static unsigned long __init tpacpi_check_quirks(
480 return 0; 489 return 0;
481} 490}
482 491
492static inline bool __pure __init tpacpi_is_lenovo(void)
493{
494 return thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO;
495}
496
497static inline bool __pure __init tpacpi_is_ibm(void)
498{
499 return thinkpad_id.vendor == PCI_VENDOR_ID_IBM;
500}
483 501
484/**************************************************************************** 502/****************************************************************************
485 **************************************************************************** 503 ****************************************************************************
@@ -494,21 +512,13 @@ static unsigned long __init tpacpi_check_quirks(
494 */ 512 */
495 513
496static acpi_handle root_handle; 514static acpi_handle root_handle;
515static acpi_handle ec_handle;
497 516
498#define TPACPI_HANDLE(object, parent, paths...) \ 517#define TPACPI_HANDLE(object, parent, paths...) \
499 static acpi_handle object##_handle; \ 518 static acpi_handle object##_handle; \
500 static acpi_handle *object##_parent = &parent##_handle; \ 519 static const acpi_handle *object##_parent __initdata = \
501 static char *object##_path; \ 520 &parent##_handle; \
502 static char *object##_paths[] = { paths } 521 static char *object##_paths[] __initdata = { paths }
503
504TPACPI_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
505 "\\_SB.PCI.ISA.EC", /* 570 */
506 "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
507 "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
508 "\\_SB.PCI0.AD4S.EC0", /* i1400, R30 */
509 "\\_SB.PCI0.ICH3.EC0", /* R31 */
510 "\\_SB.PCI0.LPC.EC", /* all others */
511 );
512 522
513TPACPI_HANDLE(ecrd, ec, "ECRD"); /* 570 */ 523TPACPI_HANDLE(ecrd, ec, "ECRD"); /* 570 */
514TPACPI_HANDLE(ecwr, ec, "ECWR"); /* 570 */ 524TPACPI_HANDLE(ecwr, ec, "ECWR"); /* 570 */
@@ -528,6 +538,7 @@ TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
528 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */ 538 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
529 "\\_SB.PCI0.VID0", /* 770e */ 539 "\\_SB.PCI0.VID0", /* 770e */
530 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */ 540 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
541 "\\_SB.PCI0.AGP.VGA", /* X100e and a few others */
531 "\\_SB.PCI0.AGP.VID", /* all others */ 542 "\\_SB.PCI0.AGP.VID", /* all others */
532 ); /* R30, R31 */ 543 ); /* R30, R31 */
533 544
@@ -594,9 +605,10 @@ static int acpi_evalf(acpi_handle handle,
594 605
595 switch (res_type) { 606 switch (res_type) {
596 case 'd': /* int */ 607 case 'd': /* int */
597 if (res) 608 success = (status == AE_OK &&
609 out_obj.type == ACPI_TYPE_INTEGER);
610 if (success && res)
598 *(int *)res = out_obj.integer.value; 611 *(int *)res = out_obj.integer.value;
599 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
600 break; 612 break;
601 case 'v': /* void */ 613 case 'v': /* void */
602 success = status == AE_OK; 614 success = status == AE_OK;
@@ -609,8 +621,8 @@ static int acpi_evalf(acpi_handle handle,
609 } 621 }
610 622
611 if (!success && !quiet) 623 if (!success && !quiet)
612 printk(TPACPI_ERR "acpi_evalf(%s, %s, ...) failed: %d\n", 624 printk(TPACPI_ERR "acpi_evalf(%s, %s, ...) failed: %s\n",
613 method, fmt0, status); 625 method, fmt0, acpi_format_exception(status));
614 626
615 return success; 627 return success;
616} 628}
@@ -661,11 +673,11 @@ static int issue_thinkpad_cmos_command(int cmos_cmd)
661 673
662#define TPACPI_ACPIHANDLE_INIT(object) \ 674#define TPACPI_ACPIHANDLE_INIT(object) \
663 drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \ 675 drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \
664 object##_paths, ARRAY_SIZE(object##_paths), &object##_path) 676 object##_paths, ARRAY_SIZE(object##_paths))
665 677
666static void drv_acpi_handle_init(char *name, 678static void __init drv_acpi_handle_init(const char *name,
667 acpi_handle *handle, acpi_handle parent, 679 acpi_handle *handle, const acpi_handle parent,
668 char **paths, int num_paths, char **path) 680 char **paths, const int num_paths)
669{ 681{
670 int i; 682 int i;
671 acpi_status status; 683 acpi_status status;
@@ -676,10 +688,9 @@ static void drv_acpi_handle_init(char *name,
676 for (i = 0; i < num_paths; i++) { 688 for (i = 0; i < num_paths; i++) {
677 status = acpi_get_handle(parent, paths[i], handle); 689 status = acpi_get_handle(parent, paths[i], handle);
678 if (ACPI_SUCCESS(status)) { 690 if (ACPI_SUCCESS(status)) {
679 *path = paths[i];
680 dbg_printk(TPACPI_DBG_INIT, 691 dbg_printk(TPACPI_DBG_INIT,
681 "Found ACPI handle %s for %s\n", 692 "Found ACPI handle %s for %s\n",
682 *path, name); 693 paths[i], name);
683 return; 694 return;
684 } 695 }
685 } 696 }
@@ -689,6 +700,43 @@ static void drv_acpi_handle_init(char *name,
689 *handle = NULL; 700 *handle = NULL;
690} 701}
691 702
703static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle,
704 u32 level, void *context, void **return_value)
705{
706 *(acpi_handle *)return_value = handle;
707
708 return AE_CTRL_TERMINATE;
709}
710
711static void __init tpacpi_acpi_handle_locate(const char *name,
712 const char *hid,
713 acpi_handle *handle)
714{
715 acpi_status status;
716 acpi_handle device_found;
717
718 BUG_ON(!name || !hid || !handle);
719 vdbg_printk(TPACPI_DBG_INIT,
720 "trying to locate ACPI handle for %s, using HID %s\n",
721 name, hid);
722
723 memset(&device_found, 0, sizeof(device_found));
724 status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback,
725 (void *)name, &device_found);
726
727 *handle = NULL;
728
729 if (ACPI_SUCCESS(status)) {
730 *handle = device_found;
731 dbg_printk(TPACPI_DBG_INIT,
732 "Found ACPI handle for %s\n", name);
733 } else {
734 vdbg_printk(TPACPI_DBG_INIT,
735 "Could not locate an ACPI handle for %s: %s\n",
736 name, acpi_format_exception(status));
737 }
738}
739
692static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data) 740static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
693{ 741{
694 struct ibm_struct *ibm = data; 742 struct ibm_struct *ibm = data;
@@ -736,8 +784,8 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
736 "handling %s events\n", ibm->name); 784 "handling %s events\n", ibm->name);
737 } else { 785 } else {
738 printk(TPACPI_ERR 786 printk(TPACPI_ERR
739 "acpi_install_notify_handler(%s) failed: %d\n", 787 "acpi_install_notify_handler(%s) failed: %s\n",
740 ibm->name, status); 788 ibm->name, acpi_format_exception(status));
741 } 789 }
742 return -ENODEV; 790 return -ENODEV;
743 } 791 }
@@ -1035,80 +1083,6 @@ static void tpacpi_disable_brightness_delay(void)
1035 "ACPI backlight control delay disabled\n"); 1083 "ACPI backlight control delay disabled\n");
1036} 1084}
1037 1085
1038static int __init tpacpi_query_bcl_levels(acpi_handle handle)
1039{
1040 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1041 union acpi_object *obj;
1042 int rc;
1043
1044 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
1045 obj = (union acpi_object *)buffer.pointer;
1046 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
1047 printk(TPACPI_ERR "Unknown _BCL data, "
1048 "please report this to %s\n", TPACPI_MAIL);
1049 rc = 0;
1050 } else {
1051 rc = obj->package.count;
1052 }
1053 } else {
1054 return 0;
1055 }
1056
1057 kfree(buffer.pointer);
1058 return rc;
1059}
1060
1061static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
1062 u32 lvl, void *context, void **rv)
1063{
1064 char name[ACPI_PATH_SEGMENT_LENGTH];
1065 struct acpi_buffer buffer = { sizeof(name), &name };
1066
1067 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
1068 !strncmp("_BCL", name, sizeof(name) - 1)) {
1069 BUG_ON(!rv || !*rv);
1070 **(int **)rv = tpacpi_query_bcl_levels(handle);
1071 return AE_CTRL_TERMINATE;
1072 } else {
1073 return AE_OK;
1074 }
1075}
1076
1077/*
1078 * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
1079 */
1080static int __init tpacpi_check_std_acpi_brightness_support(void)
1081{
1082 int status;
1083 int bcl_levels = 0;
1084 void *bcl_ptr = &bcl_levels;
1085
1086 if (!vid_handle) {
1087 TPACPI_ACPIHANDLE_INIT(vid);
1088 }
1089 if (!vid_handle)
1090 return 0;
1091
1092 /*
1093 * Search for a _BCL method, and execute it. This is safe on all
1094 * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
1095 * BIOS in ACPI backlight control mode. We do NOT have to care
1096 * about calling the _BCL method in an enabled video device, any
1097 * will do for our purposes.
1098 */
1099
1100 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
1101 tpacpi_acpi_walk_find_bcl, NULL, NULL,
1102 &bcl_ptr);
1103
1104 if (ACPI_SUCCESS(status) && bcl_levels > 2) {
1105 tp_features.bright_acpimode = 1;
1106 return (bcl_levels - 2);
1107 }
1108
1109 return 0;
1110}
1111
1112static void printk_deprecated_attribute(const char * const what, 1086static void printk_deprecated_attribute(const char * const what,
1113 const char * const details) 1087 const char * const details)
1114{ 1088{
@@ -1872,34 +1846,9 @@ static bool __init tpacpi_is_fw_known(void)
1872 ****************************************************************************/ 1846 ****************************************************************************/
1873 1847
1874/************************************************************************* 1848/*************************************************************************
1875 * thinkpad-acpi init subdriver 1849 * thinkpad-acpi metadata subdriver
1876 */ 1850 */
1877 1851
1878static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
1879{
1880 printk(TPACPI_INFO "%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
1881 printk(TPACPI_INFO "%s\n", TPACPI_URL);
1882
1883 printk(TPACPI_INFO "ThinkPad BIOS %s, EC %s\n",
1884 (thinkpad_id.bios_version_str) ?
1885 thinkpad_id.bios_version_str : "unknown",
1886 (thinkpad_id.ec_version_str) ?
1887 thinkpad_id.ec_version_str : "unknown");
1888
1889 if (thinkpad_id.vendor && thinkpad_id.model_str)
1890 printk(TPACPI_INFO "%s %s, model %s\n",
1891 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
1892 "IBM" : ((thinkpad_id.vendor ==
1893 PCI_VENDOR_ID_LENOVO) ?
1894 "Lenovo" : "Unknown vendor"),
1895 thinkpad_id.model_str,
1896 (thinkpad_id.nummodel_str) ?
1897 thinkpad_id.nummodel_str : "unknown");
1898
1899 tpacpi_check_outdated_fw();
1900 return 0;
1901}
1902
1903static int thinkpad_acpi_driver_read(struct seq_file *m) 1852static int thinkpad_acpi_driver_read(struct seq_file *m)
1904{ 1853{
1905 seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC); 1854 seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
@@ -2405,6 +2354,36 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
2405 tpacpi_hotkey_send_key(__scancode); \ 2354 tpacpi_hotkey_send_key(__scancode); \
2406 } while (0) 2355 } while (0)
2407 2356
2357 void issue_volchange(const unsigned int oldvol,
2358 const unsigned int newvol)
2359 {
2360 unsigned int i = oldvol;
2361
2362 while (i > newvol) {
2363 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
2364 i--;
2365 }
2366 while (i < newvol) {
2367 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2368 i++;
2369 }
2370 }
2371
2372 void issue_brightnesschange(const unsigned int oldbrt,
2373 const unsigned int newbrt)
2374 {
2375 unsigned int i = oldbrt;
2376
2377 while (i > newbrt) {
2378 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
2379 i--;
2380 }
2381 while (i < newbrt) {
2382 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
2383 i++;
2384 }
2385 }
2386
2408 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle); 2387 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle);
2409 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle); 2388 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle);
2410 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle); 2389 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle);
@@ -2414,41 +2393,61 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
2414 2393
2415 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF8, displayexp_toggle); 2394 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF8, displayexp_toggle);
2416 2395
2417 /* handle volume */ 2396 /*
2418 if (oldn->volume_toggle != newn->volume_toggle) { 2397 * Handle volume
2419 if (oldn->mute != newn->mute) { 2398 *
2399 * This code is supposed to duplicate the IBM firmware behaviour:
2400 * - Pressing MUTE issues mute hotkey message, even when already mute
2401 * - Pressing Volume up/down issues volume up/down hotkey messages,
2402 * even when already at maximum or minumum volume
2403 * - The act of unmuting issues volume up/down notification,
2404 * depending which key was used to unmute
2405 *
2406 * We are constrained to what the NVRAM can tell us, which is not much
2407 * and certainly not enough if more than one volume hotkey was pressed
2408 * since the last poll cycle.
2409 *
2410 * Just to make our life interesting, some newer Lenovo ThinkPads have
2411 * bugs in the BIOS and may fail to update volume_toggle properly.
2412 */
2413 if (newn->mute) {
2414 /* muted */
2415 if (!oldn->mute ||
2416 oldn->volume_toggle != newn->volume_toggle ||
2417 oldn->volume_level != newn->volume_level) {
2418 /* recently muted, or repeated mute keypress, or
2419 * multiple presses ending in mute */
2420 issue_volchange(oldn->volume_level, newn->volume_level);
2420 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); 2421 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE);
2421 } 2422 }
2422 if (oldn->volume_level > newn->volume_level) { 2423 } else {
2423 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); 2424 /* unmute */
2424 } else if (oldn->volume_level < newn->volume_level) { 2425 if (oldn->mute) {
2426 /* recently unmuted, issue 'unmute' keypress */
2425 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); 2427 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2426 } else if (oldn->mute == newn->mute) { 2428 }
2427 /* repeated key presses that didn't change state */ 2429 if (oldn->volume_level != newn->volume_level) {
2428 if (newn->mute) { 2430 issue_volchange(oldn->volume_level, newn->volume_level);
2429 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); 2431 } else if (oldn->volume_toggle != newn->volume_toggle) {
2430 } else if (newn->volume_level != 0) { 2432 /* repeated vol up/down keypress at end of scale ? */
2431 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); 2433 if (newn->volume_level == 0)
2432 } else {
2433 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); 2434 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
2434 } 2435 else if (newn->volume_level >= TP_NVRAM_LEVEL_VOLUME_MAX)
2436 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2435 } 2437 }
2436 } 2438 }
2437 2439
2438 /* handle brightness */ 2440 /* handle brightness */
2439 if (oldn->brightness_toggle != newn->brightness_toggle) { 2441 if (oldn->brightness_level != newn->brightness_level) {
2440 if (oldn->brightness_level < newn->brightness_level) { 2442 issue_brightnesschange(oldn->brightness_level,
2441 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME); 2443 newn->brightness_level);
2442 } else if (oldn->brightness_level > newn->brightness_level) { 2444 } else if (oldn->brightness_toggle != newn->brightness_toggle) {
2445 /* repeated key presses that didn't change state */
2446 if (newn->brightness_level == 0)
2443 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND); 2447 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
2444 } else { 2448 else if (newn->brightness_level >= bright_maxlvl
2445 /* repeated key presses that didn't change state */ 2449 && !tp_features.bright_unkfw)
2446 if (newn->brightness_level != 0) { 2450 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
2447 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
2448 } else {
2449 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
2450 }
2451 }
2452 } 2451 }
2453 2452
2454#undef TPACPI_COMPARE_KEY 2453#undef TPACPI_COMPARE_KEY
@@ -3353,7 +3352,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3353 goto err_exit; 3352 goto err_exit;
3354 } 3353 }
3355 3354
3356 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { 3355 if (tpacpi_is_lenovo()) {
3357 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, 3356 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3358 "using Lenovo default hot key map\n"); 3357 "using Lenovo default hot key map\n");
3359 memcpy(hotkey_keycode_map, &lenovo_keycode_map, 3358 memcpy(hotkey_keycode_map, &lenovo_keycode_map,
@@ -3391,11 +3390,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3391 } 3390 }
3392 3391
3393 /* Do not issue duplicate brightness change events to 3392 /* Do not issue duplicate brightness change events to
3394 * userspace */ 3393 * userspace. tpacpi_detect_brightness_capabilities() must have
3395 if (!tp_features.bright_acpimode) 3394 * been called before this point */
3396 /* update bright_acpimode... */
3397 tpacpi_check_std_acpi_brightness_support();
3398
3399 if (tp_features.bright_acpimode && acpi_video_backlight_support()) { 3395 if (tp_features.bright_acpimode && acpi_video_backlight_support()) {
3400 printk(TPACPI_INFO 3396 printk(TPACPI_INFO
3401 "This ThinkPad has standard ACPI backlight " 3397 "This ThinkPad has standard ACPI backlight "
@@ -4422,7 +4418,8 @@ static int __init video_init(struct ibm_init_struct *iibm)
4422 vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n"); 4418 vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n");
4423 4419
4424 TPACPI_ACPIHANDLE_INIT(vid); 4420 TPACPI_ACPIHANDLE_INIT(vid);
4425 TPACPI_ACPIHANDLE_INIT(vid2); 4421 if (tpacpi_is_ibm())
4422 TPACPI_ACPIHANDLE_INIT(vid2);
4426 4423
4427 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga) 4424 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
4428 /* G41, assume IVGA doesn't change */ 4425 /* G41, assume IVGA doesn't change */
@@ -4431,10 +4428,12 @@ static int __init video_init(struct ibm_init_struct *iibm)
4431 if (!vid_handle) 4428 if (!vid_handle)
4432 /* video switching not supported on R30, R31 */ 4429 /* video switching not supported on R30, R31 */
4433 video_supported = TPACPI_VIDEO_NONE; 4430 video_supported = TPACPI_VIDEO_NONE;
4434 else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd")) 4431 else if (tpacpi_is_ibm() &&
4432 acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
4435 /* 570 */ 4433 /* 570 */
4436 video_supported = TPACPI_VIDEO_570; 4434 video_supported = TPACPI_VIDEO_570;
4437 else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd")) 4435 else if (tpacpi_is_ibm() &&
4436 acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
4438 /* 600e/x, 770e, 770x */ 4437 /* 600e/x, 770e, 770x */
4439 video_supported = TPACPI_VIDEO_770; 4438 video_supported = TPACPI_VIDEO_770;
4440 else 4439 else
@@ -4811,8 +4810,10 @@ static int __init light_init(struct ibm_init_struct *iibm)
4811 4810
4812 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); 4811 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
4813 4812
4814 TPACPI_ACPIHANDLE_INIT(ledb); 4813 if (tpacpi_is_ibm()) {
4815 TPACPI_ACPIHANDLE_INIT(lght); 4814 TPACPI_ACPIHANDLE_INIT(ledb);
4815 TPACPI_ACPIHANDLE_INIT(lght);
4816 }
4816 TPACPI_ACPIHANDLE_INIT(cmos); 4817 TPACPI_ACPIHANDLE_INIT(cmos);
4817 INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker); 4818 INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker);
4818 4819
@@ -5007,11 +5008,7 @@ enum { /* For TPACPI_LED_OLD */
5007 5008
5008static enum led_access_mode led_supported; 5009static enum led_access_mode led_supported;
5009 5010
5010TPACPI_HANDLE(led, ec, "SLED", /* 570 */ 5011static acpi_handle led_handle;
5011 "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, */
5012 /* T20-22, X20-21 */
5013 "LED", /* all others */
5014 ); /* R30, R31 */
5015 5012
5016#define TPACPI_LED_NUMLEDS 16 5013#define TPACPI_LED_NUMLEDS 16
5017static struct tpacpi_led_classdev *tpacpi_leds; 5014static struct tpacpi_led_classdev *tpacpi_leds;
@@ -5271,6 +5268,32 @@ static const struct tpacpi_quirk led_useful_qtable[] __initconst = {
5271#undef TPACPI_LEDQ_IBM 5268#undef TPACPI_LEDQ_IBM
5272#undef TPACPI_LEDQ_LNV 5269#undef TPACPI_LEDQ_LNV
5273 5270
5271static enum led_access_mode __init led_init_detect_mode(void)
5272{
5273 acpi_status status;
5274
5275 if (tpacpi_is_ibm()) {
5276 /* 570 */
5277 status = acpi_get_handle(ec_handle, "SLED", &led_handle);
5278 if (ACPI_SUCCESS(status))
5279 return TPACPI_LED_570;
5280
5281 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
5282 status = acpi_get_handle(ec_handle, "SYSL", &led_handle);
5283 if (ACPI_SUCCESS(status))
5284 return TPACPI_LED_OLD;
5285 }
5286
5287 /* most others */
5288 status = acpi_get_handle(ec_handle, "LED", &led_handle);
5289 if (ACPI_SUCCESS(status))
5290 return TPACPI_LED_NEW;
5291
5292 /* R30, R31, and unknown firmwares */
5293 led_handle = NULL;
5294 return TPACPI_LED_NONE;
5295}
5296
5274static int __init led_init(struct ibm_init_struct *iibm) 5297static int __init led_init(struct ibm_init_struct *iibm)
5275{ 5298{
5276 unsigned int i; 5299 unsigned int i;
@@ -5279,20 +5302,7 @@ static int __init led_init(struct ibm_init_struct *iibm)
5279 5302
5280 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); 5303 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
5281 5304
5282 TPACPI_ACPIHANDLE_INIT(led); 5305 led_supported = led_init_detect_mode();
5283
5284 if (!led_handle)
5285 /* led not supported on R30, R31 */
5286 led_supported = TPACPI_LED_NONE;
5287 else if (strlencmp(led_path, "SLED") == 0)
5288 /* 570 */
5289 led_supported = TPACPI_LED_570;
5290 else if (strlencmp(led_path, "SYSL") == 0)
5291 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
5292 led_supported = TPACPI_LED_OLD;
5293 else
5294 /* all others */
5295 led_supported = TPACPI_LED_NEW;
5296 5306
5297 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", 5307 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
5298 str_supported(led_supported), led_supported); 5308 str_supported(led_supported), led_supported);
@@ -5741,11 +5751,12 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
5741 TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8; 5751 TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
5742 } 5752 }
5743 } else if (acpi_tmp7) { 5753 } else if (acpi_tmp7) {
5744 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) { 5754 if (tpacpi_is_ibm() &&
5755 acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
5745 /* 600e/x, 770e, 770x */ 5756 /* 600e/x, 770e, 770x */
5746 thermal_read_mode = TPACPI_THERMAL_ACPI_UPDT; 5757 thermal_read_mode = TPACPI_THERMAL_ACPI_UPDT;
5747 } else { 5758 } else {
5748 /* Standard ACPI TMPx access, max 8 sensors */ 5759 /* IBM/LENOVO DSDT EC.TMPx access, max 8 sensors */
5749 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07; 5760 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
5750 } 5761 }
5751 } else { 5762 } else {
@@ -5954,7 +5965,7 @@ static unsigned int tpacpi_brightness_nvram_get(void)
5954 lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) 5965 lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
5955 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) 5966 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
5956 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; 5967 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
5957 lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07; 5968 lnvram &= bright_maxlvl;
5958 5969
5959 return lnvram; 5970 return lnvram;
5960} 5971}
@@ -6063,8 +6074,7 @@ static int brightness_set(unsigned int value)
6063{ 6074{
6064 int res; 6075 int res;
6065 6076
6066 if (value > ((tp_features.bright_16levels)? 15 : 7) || 6077 if (value > bright_maxlvl || value < 0)
6067 value < 0)
6068 return -EINVAL; 6078 return -EINVAL;
6069 6079
6070 vdbg_printk(TPACPI_DBG_BRGHT, 6080 vdbg_printk(TPACPI_DBG_BRGHT,
@@ -6139,6 +6149,80 @@ static struct backlight_ops ibm_backlight_data = {
6139 6149
6140/* --------------------------------------------------------------------- */ 6150/* --------------------------------------------------------------------- */
6141 6151
6152static int __init tpacpi_query_bcl_levels(acpi_handle handle)
6153{
6154 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
6155 union acpi_object *obj;
6156 int rc;
6157
6158 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
6159 obj = (union acpi_object *)buffer.pointer;
6160 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
6161 printk(TPACPI_ERR "Unknown _BCL data, "
6162 "please report this to %s\n", TPACPI_MAIL);
6163 rc = 0;
6164 } else {
6165 rc = obj->package.count;
6166 }
6167 } else {
6168 return 0;
6169 }
6170
6171 kfree(buffer.pointer);
6172 return rc;
6173}
6174
6175static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
6176 u32 lvl, void *context, void **rv)
6177{
6178 char name[ACPI_PATH_SEGMENT_LENGTH];
6179 struct acpi_buffer buffer = { sizeof(name), &name };
6180
6181 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
6182 !strncmp("_BCL", name, sizeof(name) - 1)) {
6183 BUG_ON(!rv || !*rv);
6184 **(int **)rv = tpacpi_query_bcl_levels(handle);
6185 return AE_CTRL_TERMINATE;
6186 } else {
6187 return AE_OK;
6188 }
6189}
6190
6191/*
6192 * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
6193 */
6194static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
6195{
6196 int status;
6197 int bcl_levels = 0;
6198 void *bcl_ptr = &bcl_levels;
6199
6200 if (!vid_handle)
6201 TPACPI_ACPIHANDLE_INIT(vid);
6202
6203 if (!vid_handle)
6204 return 0;
6205
6206 /*
6207 * Search for a _BCL method, and execute it. This is safe on all
6208 * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
6209 * BIOS in ACPI backlight control mode. We do NOT have to care
6210 * about calling the _BCL method in an enabled video device, any
6211 * will do for our purposes.
6212 */
6213
6214 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
6215 tpacpi_acpi_walk_find_bcl, NULL, NULL,
6216 &bcl_ptr);
6217
6218 if (ACPI_SUCCESS(status) && bcl_levels > 2) {
6219 tp_features.bright_acpimode = 1;
6220 return bcl_levels - 2;
6221 }
6222
6223 return 0;
6224}
6225
6142/* 6226/*
6143 * These are only useful for models that have only one possibility 6227 * These are only useful for models that have only one possibility
6144 * of GPU. If the BIOS model handles both ATI and Intel, don't use 6228 * of GPU. If the BIOS model handles both ATI and Intel, don't use
@@ -6169,6 +6253,47 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6169 TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */ 6253 TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */
6170}; 6254};
6171 6255
6256/*
6257 * Returns < 0 for error, otherwise sets tp_features.bright_*
6258 * and bright_maxlvl.
6259 */
6260static void __init tpacpi_detect_brightness_capabilities(void)
6261{
6262 unsigned int b;
6263
6264 vdbg_printk(TPACPI_DBG_INIT,
6265 "detecting firmware brightness interface capabilities\n");
6266
6267 /* we could run a quirks check here (same table used by
6268 * brightness_init) if needed */
6269
6270 /*
6271 * We always attempt to detect acpi support, so as to switch
6272 * Lenovo Vista BIOS to ACPI brightness mode even if we are not
6273 * going to publish a backlight interface
6274 */
6275 b = tpacpi_check_std_acpi_brightness_support();
6276 switch (b) {
6277 case 16:
6278 bright_maxlvl = 15;
6279 printk(TPACPI_INFO
6280 "detected a 16-level brightness capable ThinkPad\n");
6281 break;
6282 case 8:
6283 case 0:
6284 bright_maxlvl = 7;
6285 printk(TPACPI_INFO
6286 "detected a 8-level brightness capable ThinkPad\n");
6287 break;
6288 default:
6289 printk(TPACPI_ERR
6290 "Unsupported brightness interface, "
6291 "please contact %s\n", TPACPI_MAIL);
6292 tp_features.bright_unkfw = 1;
6293 bright_maxlvl = b - 1;
6294 }
6295}
6296
6172static int __init brightness_init(struct ibm_init_struct *iibm) 6297static int __init brightness_init(struct ibm_init_struct *iibm)
6173{ 6298{
6174 struct backlight_properties props; 6299 struct backlight_properties props;
@@ -6182,14 +6307,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6182 quirks = tpacpi_check_quirks(brightness_quirk_table, 6307 quirks = tpacpi_check_quirks(brightness_quirk_table,
6183 ARRAY_SIZE(brightness_quirk_table)); 6308 ARRAY_SIZE(brightness_quirk_table));
6184 6309
6185 /* 6310 /* tpacpi_detect_brightness_capabilities() must have run already */
6186 * We always attempt to detect acpi support, so as to switch 6311
6187 * Lenovo Vista BIOS to ACPI brightness mode even if we are not 6312 /* if it is unknown, we don't handle it: it wouldn't be safe */
6188 * going to publish a backlight interface 6313 if (tp_features.bright_unkfw)
6189 */ 6314 return 1;
6190 b = tpacpi_check_std_acpi_brightness_support();
6191 if (b > 0) {
6192 6315
6316 if (tp_features.bright_acpimode) {
6193 if (acpi_video_backlight_support()) { 6317 if (acpi_video_backlight_support()) {
6194 if (brightness_enable > 1) { 6318 if (brightness_enable > 1) {
6195 printk(TPACPI_NOTICE 6319 printk(TPACPI_NOTICE
@@ -6218,15 +6342,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6218 return 1; 6342 return 1;
6219 } 6343 }
6220 6344
6221 if (b > 16) {
6222 printk(TPACPI_ERR
6223 "Unsupported brightness interface, "
6224 "please contact %s\n", TPACPI_MAIL);
6225 return 1;
6226 }
6227 if (b == 16)
6228 tp_features.bright_16levels = 1;
6229
6230 /* 6345 /*
6231 * Check for module parameter bogosity, note that we 6346 * Check for module parameter bogosity, note that we
6232 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be 6347 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
@@ -6249,7 +6364,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6249 } 6364 }
6250 6365
6251 /* Safety */ 6366 /* Safety */
6252 if (thinkpad_id.vendor != PCI_VENDOR_ID_IBM && 6367 if (!tpacpi_is_ibm() &&
6253 (brightness_mode == TPACPI_BRGHT_MODE_ECNVRAM || 6368 (brightness_mode == TPACPI_BRGHT_MODE_ECNVRAM ||
6254 brightness_mode == TPACPI_BRGHT_MODE_EC)) 6369 brightness_mode == TPACPI_BRGHT_MODE_EC))
6255 return -EINVAL; 6370 return -EINVAL;
@@ -6257,12 +6372,9 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6257 if (tpacpi_brightness_get_raw(&b) < 0) 6372 if (tpacpi_brightness_get_raw(&b) < 0)
6258 return 1; 6373 return 1;
6259 6374
6260 if (tp_features.bright_16levels)
6261 printk(TPACPI_INFO
6262 "detected a 16-level brightness capable ThinkPad\n");
6263
6264 memset(&props, 0, sizeof(struct backlight_properties)); 6375 memset(&props, 0, sizeof(struct backlight_properties));
6265 props.max_brightness = (tp_features.bright_16levels) ? 15 : 7; 6376 props.max_brightness = bright_maxlvl;
6377 props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6266 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME, 6378 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
6267 NULL, NULL, 6379 NULL, NULL,
6268 &ibm_backlight_data, 6380 &ibm_backlight_data,
@@ -6285,7 +6397,10 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6285 "or not on your ThinkPad\n", TPACPI_MAIL); 6397 "or not on your ThinkPad\n", TPACPI_MAIL);
6286 } 6398 }
6287 6399
6288 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6400 /* Added by mistake in early 2007. Probably useless, but it could
6401 * be working around some unknown firmware problem where the value
6402 * read at startup doesn't match the real hardware state... so leave
6403 * it in place just in case */
6289 backlight_update_status(ibm_backlight_device); 6404 backlight_update_status(ibm_backlight_device);
6290 6405
6291 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, 6406 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
@@ -6328,9 +6443,8 @@ static int brightness_read(struct seq_file *m)
6328 } else { 6443 } else {
6329 seq_printf(m, "level:\t\t%d\n", level); 6444 seq_printf(m, "level:\t\t%d\n", level);
6330 seq_printf(m, "commands:\tup, down\n"); 6445 seq_printf(m, "commands:\tup, down\n");
6331 seq_printf(m, "commands:\tlevel <level>" 6446 seq_printf(m, "commands:\tlevel <level> (<level> is 0-%d)\n",
6332 " (<level> is 0-%d)\n", 6447 bright_maxlvl);
6333 (tp_features.bright_16levels) ? 15 : 7);
6334 } 6448 }
6335 6449
6336 return 0; 6450 return 0;
@@ -6341,7 +6455,6 @@ static int brightness_write(char *buf)
6341 int level; 6455 int level;
6342 int rc; 6456 int rc;
6343 char *cmd; 6457 char *cmd;
6344 int max_level = (tp_features.bright_16levels) ? 15 : 7;
6345 6458
6346 level = brightness_get(NULL); 6459 level = brightness_get(NULL);
6347 if (level < 0) 6460 if (level < 0)
@@ -6349,13 +6462,13 @@ static int brightness_write(char *buf)
6349 6462
6350 while ((cmd = next_cmd(&buf))) { 6463 while ((cmd = next_cmd(&buf))) {
6351 if (strlencmp(cmd, "up") == 0) { 6464 if (strlencmp(cmd, "up") == 0) {
6352 if (level < max_level) 6465 if (level < bright_maxlvl)
6353 level++; 6466 level++;
6354 } else if (strlencmp(cmd, "down") == 0) { 6467 } else if (strlencmp(cmd, "down") == 0) {
6355 if (level > 0) 6468 if (level > 0)
6356 level--; 6469 level--;
6357 } else if (sscanf(cmd, "level %d", &level) == 1 && 6470 } else if (sscanf(cmd, "level %d", &level) == 1 &&
6358 level >= 0 && level <= max_level) { 6471 level >= 0 && level <= bright_maxlvl) {
6359 /* new level set */ 6472 /* new level set */
6360 } else 6473 } else
6361 return -EINVAL; 6474 return -EINVAL;
@@ -6669,6 +6782,8 @@ static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6669static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol, 6782static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6670 struct snd_ctl_elem_value *ucontrol) 6783 struct snd_ctl_elem_value *ucontrol)
6671{ 6784{
6785 tpacpi_disclose_usertask("ALSA", "set volume to %ld\n",
6786 ucontrol->value.integer.value[0]);
6672 return volume_alsa_set_volume(ucontrol->value.integer.value[0]); 6787 return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
6673} 6788}
6674 6789
@@ -6692,6 +6807,9 @@ static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6692static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, 6807static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6693 struct snd_ctl_elem_value *ucontrol) 6808 struct snd_ctl_elem_value *ucontrol)
6694{ 6809{
6810 tpacpi_disclose_usertask("ALSA", "%smute\n",
6811 ucontrol->value.integer.value[0] ?
6812 "un" : "");
6695 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); 6813 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
6696} 6814}
6697 6815
@@ -7968,9 +8086,11 @@ static int __init fan_init(struct ibm_init_struct *iibm)
7968 tp_features.second_fan = 0; 8086 tp_features.second_fan = 0;
7969 fan_control_desired_level = 7; 8087 fan_control_desired_level = 7;
7970 8088
7971 TPACPI_ACPIHANDLE_INIT(fans); 8089 if (tpacpi_is_ibm()) {
7972 TPACPI_ACPIHANDLE_INIT(gfan); 8090 TPACPI_ACPIHANDLE_INIT(fans);
7973 TPACPI_ACPIHANDLE_INIT(sfan); 8091 TPACPI_ACPIHANDLE_INIT(gfan);
8092 TPACPI_ACPIHANDLE_INIT(sfan);
8093 }
7974 8094
7975 quirks = tpacpi_check_quirks(fan_quirk_table, 8095 quirks = tpacpi_check_quirks(fan_quirk_table,
7976 ARRAY_SIZE(fan_quirk_table)); 8096 ARRAY_SIZE(fan_quirk_table));
@@ -8662,6 +8782,10 @@ static int __init probe_for_thinkpad(void)
8662 if (acpi_disabled) 8782 if (acpi_disabled)
8663 return -ENODEV; 8783 return -ENODEV;
8664 8784
8785 /* It would be dangerous to run the driver in this case */
8786 if (!tpacpi_is_ibm() && !tpacpi_is_lenovo())
8787 return -ENODEV;
8788
8665 /* 8789 /*
8666 * Non-ancient models have better DMI tagging, but very old models 8790 * Non-ancient models have better DMI tagging, but very old models
8667 * don't. tpacpi_is_fw_known() is a cheat to help in that case. 8791 * don't. tpacpi_is_fw_known() is a cheat to help in that case.
@@ -8670,8 +8794,8 @@ static int __init probe_for_thinkpad(void)
8670 (thinkpad_id.ec_model != 0) || 8794 (thinkpad_id.ec_model != 0) ||
8671 tpacpi_is_fw_known(); 8795 tpacpi_is_fw_known();
8672 8796
8673 /* ec is required because many other handles are relative to it */ 8797 /* The EC handler is required */
8674 TPACPI_ACPIHANDLE_INIT(ec); 8798 tpacpi_acpi_handle_locate("ec", TPACPI_ACPI_EC_HID, &ec_handle);
8675 if (!ec_handle) { 8799 if (!ec_handle) {
8676 if (is_thinkpad) 8800 if (is_thinkpad)
8677 printk(TPACPI_ERR 8801 printk(TPACPI_ERR
@@ -8685,12 +8809,34 @@ static int __init probe_for_thinkpad(void)
8685 return 0; 8809 return 0;
8686} 8810}
8687 8811
8812static void __init thinkpad_acpi_init_banner(void)
8813{
8814 printk(TPACPI_INFO "%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
8815 printk(TPACPI_INFO "%s\n", TPACPI_URL);
8816
8817 printk(TPACPI_INFO "ThinkPad BIOS %s, EC %s\n",
8818 (thinkpad_id.bios_version_str) ?
8819 thinkpad_id.bios_version_str : "unknown",
8820 (thinkpad_id.ec_version_str) ?
8821 thinkpad_id.ec_version_str : "unknown");
8822
8823 BUG_ON(!thinkpad_id.vendor);
8824
8825 if (thinkpad_id.model_str)
8826 printk(TPACPI_INFO "%s %s, model %s\n",
8827 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
8828 "IBM" : ((thinkpad_id.vendor ==
8829 PCI_VENDOR_ID_LENOVO) ?
8830 "Lenovo" : "Unknown vendor"),
8831 thinkpad_id.model_str,
8832 (thinkpad_id.nummodel_str) ?
8833 thinkpad_id.nummodel_str : "unknown");
8834}
8688 8835
8689/* Module init, exit, parameters */ 8836/* Module init, exit, parameters */
8690 8837
8691static struct ibm_init_struct ibms_init[] __initdata = { 8838static struct ibm_init_struct ibms_init[] __initdata = {
8692 { 8839 {
8693 .init = thinkpad_acpi_driver_init,
8694 .data = &thinkpad_acpi_driver_data, 8840 .data = &thinkpad_acpi_driver_data,
8695 }, 8841 },
8696 { 8842 {
@@ -8960,6 +9106,9 @@ static int __init thinkpad_acpi_module_init(void)
8960 9106
8961 /* Driver initialization */ 9107 /* Driver initialization */
8962 9108
9109 thinkpad_acpi_init_banner();
9110 tpacpi_check_outdated_fw();
9111
8963 TPACPI_ACPIHANDLE_INIT(ecrd); 9112 TPACPI_ACPIHANDLE_INIT(ecrd);
8964 TPACPI_ACPIHANDLE_INIT(ecwr); 9113 TPACPI_ACPIHANDLE_INIT(ecwr);
8965 9114
@@ -9059,13 +9208,16 @@ static int __init thinkpad_acpi_module_init(void)
9059 tpacpi_inputdev->name = "ThinkPad Extra Buttons"; 9208 tpacpi_inputdev->name = "ThinkPad Extra Buttons";
9060 tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0"; 9209 tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0";
9061 tpacpi_inputdev->id.bustype = BUS_HOST; 9210 tpacpi_inputdev->id.bustype = BUS_HOST;
9062 tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ? 9211 tpacpi_inputdev->id.vendor = thinkpad_id.vendor;
9063 thinkpad_id.vendor :
9064 PCI_VENDOR_ID_IBM;
9065 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 9212 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
9066 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 9213 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
9067 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; 9214 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
9068 } 9215 }
9216
9217 /* Init subdriver dependencies */
9218 tpacpi_detect_brightness_capabilities();
9219
9220 /* Init subdrivers */
9069 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 9221 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
9070 ret = ibm_init(&ibms_init[i]); 9222 ret = ibm_init(&ibms_init[i]);
9071 if (ret >= 0 && *ibms_init[i].param) 9223 if (ret >= 0 && *ibms_init[i].param)