diff options
| -rw-r--r-- | Documentation/laptops/thinkpad-acpi.txt | 127 | ||||
| -rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 34 | ||||
| -rw-r--r-- | drivers/acpi/acpica/acobject.h | 1 | ||||
| -rw-r--r-- | drivers/acpi/acpica/dsopcode.c | 24 | ||||
| -rw-r--r-- | drivers/acpi/acpica/exfldio.c | 6 | ||||
| -rw-r--r-- | drivers/acpi/osl.c | 25 | ||||
| -rw-r--r-- | drivers/acpi/system.c | 2 | ||||
| -rw-r--r-- | drivers/platform/x86/Kconfig | 25 | ||||
| -rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 9 | ||||
| -rw-r--r-- | drivers/platform/x86/hp-wmi.c | 12 | ||||
| -rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 390 | ||||
| -rw-r--r-- | include/acpi/acpiosxf.h | 4 |
12 files changed, 148 insertions, 511 deletions
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index f2296ecedb89..e2ddcdeb61b6 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
| @@ -36,8 +36,6 @@ detailed description): | |||
| 36 | - Bluetooth enable and disable | 36 | - Bluetooth enable and disable |
| 37 | - video output switching, expansion control | 37 | - video output switching, expansion control |
| 38 | - ThinkLight on and off | 38 | - ThinkLight on and off |
| 39 | - limited docking and undocking | ||
| 40 | - UltraBay eject | ||
| 41 | - CMOS/UCMS control | 39 | - CMOS/UCMS control |
| 42 | - LED control | 40 | - LED control |
| 43 | - ACPI sounds | 41 | - ACPI sounds |
| @@ -729,131 +727,6 @@ cannot be read or if it is unknown, thinkpad-acpi will report it as "off". | |||
| 729 | It is impossible to know if the status returned through sysfs is valid. | 727 | It is impossible to know if the status returned through sysfs is valid. |
| 730 | 728 | ||
| 731 | 729 | ||
| 732 | Docking / undocking -- /proc/acpi/ibm/dock | ||
| 733 | ------------------------------------------ | ||
| 734 | |||
| 735 | Docking and undocking (e.g. with the X4 UltraBase) requires some | ||
| 736 | actions to be taken by the operating system to safely make or break | ||
| 737 | the electrical connections with the dock. | ||
| 738 | |||
| 739 | The docking feature of this driver generates the following ACPI events: | ||
| 740 | |||
| 741 | ibm/dock GDCK 00000003 00000001 -- eject request | ||
| 742 | ibm/dock GDCK 00000003 00000002 -- undocked | ||
| 743 | ibm/dock GDCK 00000000 00000003 -- docked | ||
| 744 | |||
| 745 | NOTE: These events will only be generated if the laptop was docked | ||
| 746 | when originally booted. This is due to the current lack of support for | ||
| 747 | hot plugging of devices in the Linux ACPI framework. If the laptop was | ||
| 748 | booted while not in the dock, the following message is shown in the | ||
| 749 | logs: | ||
| 750 | |||
| 751 | Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present | ||
| 752 | |||
| 753 | In this case, no dock-related events are generated but the dock and | ||
| 754 | undock commands described below still work. They can be executed | ||
| 755 | manually or triggered by Fn key combinations (see the example acpid | ||
| 756 | configuration files included in the driver tarball package available | ||
| 757 | on the web site). | ||
| 758 | |||
| 759 | When the eject request button on the dock is pressed, the first event | ||
| 760 | above is generated. The handler for this event should issue the | ||
| 761 | following command: | ||
| 762 | |||
| 763 | echo undock > /proc/acpi/ibm/dock | ||
| 764 | |||
| 765 | After the LED on the dock goes off, it is safe to eject the laptop. | ||
| 766 | Note: if you pressed this key by mistake, go ahead and eject the | ||
| 767 | laptop, then dock it back in. Otherwise, the dock may not function as | ||
| 768 | expected. | ||
| 769 | |||
| 770 | When the laptop is docked, the third event above is generated. The | ||
| 771 | handler for this event should issue the following command to fully | ||
| 772 | enable the dock: | ||
| 773 | |||
| 774 | echo dock > /proc/acpi/ibm/dock | ||
| 775 | |||
| 776 | The contents of the /proc/acpi/ibm/dock file shows the current status | ||
| 777 | of the dock, as provided by the ACPI framework. | ||
| 778 | |||
| 779 | The docking support in this driver does not take care of enabling or | ||
| 780 | disabling any other devices you may have attached to the dock. For | ||
| 781 | example, a CD drive plugged into the UltraBase needs to be disabled or | ||
| 782 | enabled separately. See the provided example acpid configuration files | ||
| 783 | for how this can be accomplished. | ||
| 784 | |||
| 785 | There is no support yet for PCI devices that may be attached to a | ||
| 786 | docking station, e.g. in the ThinkPad Dock II. The driver currently | ||
| 787 | does not recognize, enable or disable such devices. This means that | ||
| 788 | the only docking stations currently supported are the X-series | ||
| 789 | UltraBase docks and "dumb" port replicators like the Mini Dock (the | ||
| 790 | latter don't need any ACPI support, actually). | ||
| 791 | |||
| 792 | |||
| 793 | UltraBay eject -- /proc/acpi/ibm/bay | ||
| 794 | ------------------------------------ | ||
| 795 | |||
| 796 | Inserting or ejecting an UltraBay device requires some actions to be | ||
| 797 | taken by the operating system to safely make or break the electrical | ||
| 798 | connections with the device. | ||
| 799 | |||
| 800 | This feature generates the following ACPI events: | ||
| 801 | |||
| 802 | ibm/bay MSTR 00000003 00000000 -- eject request | ||
| 803 | ibm/bay MSTR 00000001 00000000 -- eject lever inserted | ||
| 804 | |||
| 805 | NOTE: These events will only be generated if the UltraBay was present | ||
| 806 | when the laptop was originally booted (on the X series, the UltraBay | ||
| 807 | is in the dock, so it may not be present if the laptop was undocked). | ||
| 808 | This is due to the current lack of support for hot plugging of devices | ||
| 809 | in the Linux ACPI framework. If the laptop was booted without the | ||
| 810 | UltraBay, the following message is shown in the logs: | ||
| 811 | |||
| 812 | Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present | ||
| 813 | |||
| 814 | In this case, no bay-related events are generated but the eject | ||
| 815 | command described below still works. It can be executed manually or | ||
| 816 | triggered by a hot key combination. | ||
| 817 | |||
| 818 | Sliding the eject lever generates the first event shown above. The | ||
| 819 | handler for this event should take whatever actions are necessary to | ||
| 820 | shut down the device in the UltraBay (e.g. call idectl), then issue | ||
| 821 | the following command: | ||
| 822 | |||
| 823 | echo eject > /proc/acpi/ibm/bay | ||
| 824 | |||
| 825 | After the LED on the UltraBay goes off, it is safe to pull out the | ||
| 826 | device. | ||
| 827 | |||
| 828 | When the eject lever is inserted, the second event above is | ||
| 829 | generated. The handler for this event should take whatever actions are | ||
| 830 | necessary to enable the UltraBay device (e.g. call idectl). | ||
| 831 | |||
| 832 | The contents of the /proc/acpi/ibm/bay file shows the current status | ||
| 833 | of the UltraBay, as provided by the ACPI framework. | ||
| 834 | |||
| 835 | EXPERIMENTAL warm eject support on the 600e/x, A22p and A3x (To use | ||
| 836 | this feature, you need to supply the experimental=1 parameter when | ||
| 837 | loading the module): | ||
| 838 | |||
| 839 | These models do not have a button near the UltraBay device to request | ||
| 840 | a hot eject but rather require the laptop to be put to sleep | ||
| 841 | (suspend-to-ram) before the bay device is ejected or inserted). | ||
| 842 | The sequence of steps to eject the device is as follows: | ||
| 843 | |||
| 844 | echo eject > /proc/acpi/ibm/bay | ||
| 845 | put the ThinkPad to sleep | ||
| 846 | remove the drive | ||
| 847 | resume from sleep | ||
| 848 | cat /proc/acpi/ibm/bay should show that the drive was removed | ||
| 849 | |||
| 850 | On the A3x, both the UltraBay 2000 and UltraBay Plus devices are | ||
| 851 | supported. Use "eject2" instead of "eject" for the second bay. | ||
| 852 | |||
| 853 | Note: the UltraBay eject support on the 600e/x, A22p and A3x is | ||
| 854 | EXPERIMENTAL and may not work as expected. USE WITH CAUTION! | ||
| 855 | |||
| 856 | |||
| 857 | CMOS/UCMS control | 730 | CMOS/UCMS control |
| 858 | ----------------- | 731 | ----------------- |
| 859 | 732 | ||
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 7a0f4aa4fa1e..9a62224cc278 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
| @@ -38,6 +38,9 @@ | |||
| 38 | 38 | ||
| 39 | #define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT | 39 | #define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT |
| 40 | 40 | ||
| 41 | #undef PREFIX | ||
| 42 | #define PREFIX "ACPI:memory_hp:" | ||
| 43 | |||
| 41 | ACPI_MODULE_NAME("acpi_memhotplug"); | 44 | ACPI_MODULE_NAME("acpi_memhotplug"); |
| 42 | MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); | 45 | MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); |
| 43 | MODULE_DESCRIPTION("Hotplug Mem Driver"); | 46 | MODULE_DESCRIPTION("Hotplug Mem Driver"); |
| @@ -153,6 +156,7 @@ acpi_memory_get_device(acpi_handle handle, | |||
| 153 | acpi_handle phandle; | 156 | acpi_handle phandle; |
| 154 | struct acpi_device *device = NULL; | 157 | struct acpi_device *device = NULL; |
| 155 | struct acpi_device *pdevice = NULL; | 158 | struct acpi_device *pdevice = NULL; |
| 159 | int result; | ||
| 156 | 160 | ||
| 157 | 161 | ||
| 158 | if (!acpi_bus_get_device(handle, &device) && device) | 162 | if (!acpi_bus_get_device(handle, &device) && device) |
| @@ -165,9 +169,9 @@ acpi_memory_get_device(acpi_handle handle, | |||
| 165 | } | 169 | } |
| 166 | 170 | ||
| 167 | /* Get the parent device */ | 171 | /* Get the parent device */ |
| 168 | status = acpi_bus_get_device(phandle, &pdevice); | 172 | result = acpi_bus_get_device(phandle, &pdevice); |
| 169 | if (ACPI_FAILURE(status)) { | 173 | if (result) { |
| 170 | ACPI_EXCEPTION((AE_INFO, status, "Cannot get acpi bus device")); | 174 | printk(KERN_WARNING PREFIX "Cannot get acpi bus device"); |
| 171 | return -EINVAL; | 175 | return -EINVAL; |
| 172 | } | 176 | } |
| 173 | 177 | ||
| @@ -175,9 +179,9 @@ acpi_memory_get_device(acpi_handle handle, | |||
| 175 | * Now add the notified device. This creates the acpi_device | 179 | * Now add the notified device. This creates the acpi_device |
| 176 | * and invokes .add function | 180 | * and invokes .add function |
| 177 | */ | 181 | */ |
| 178 | status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); | 182 | result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); |
| 179 | if (ACPI_FAILURE(status)) { | 183 | if (result) { |
| 180 | ACPI_EXCEPTION((AE_INFO, status, "Cannot add acpi bus")); | 184 | printk(KERN_WARNING PREFIX "Cannot add acpi bus"); |
| 181 | return -EINVAL; | 185 | return -EINVAL; |
| 182 | } | 186 | } |
| 183 | 187 | ||
| @@ -238,7 +242,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) | |||
| 238 | num_enabled++; | 242 | num_enabled++; |
| 239 | continue; | 243 | continue; |
| 240 | } | 244 | } |
| 241 | 245 | /* | |
| 246 | * If the memory block size is zero, please ignore it. | ||
| 247 | * Don't try to do the following memory hotplug flowchart. | ||
| 248 | */ | ||
| 249 | if (!info->length) | ||
| 250 | continue; | ||
| 242 | if (node < 0) | 251 | if (node < 0) |
| 243 | node = memory_add_physaddr_to_nid(info->start_addr); | 252 | node = memory_add_physaddr_to_nid(info->start_addr); |
| 244 | 253 | ||
| @@ -253,8 +262,15 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) | |||
| 253 | mem_device->state = MEMORY_INVALID_STATE; | 262 | mem_device->state = MEMORY_INVALID_STATE; |
| 254 | return -EINVAL; | 263 | return -EINVAL; |
| 255 | } | 264 | } |
| 256 | 265 | /* | |
| 257 | return result; | 266 | * Sometimes the memory device will contain several memory blocks. |
| 267 | * When one memory block is hot-added to the system memory, it will | ||
| 268 | * be regarded as a success. | ||
| 269 | * Otherwise if the last memory block can't be hot-added to the system | ||
| 270 | * memory, it will be failure and the memory device can't be bound with | ||
| 271 | * driver. | ||
| 272 | */ | ||
| 273 | return 0; | ||
| 258 | } | 274 | } |
| 259 | 275 | ||
| 260 | static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) | 276 | static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 544dcf834922..eb6f038b03d9 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
| @@ -97,6 +97,7 @@ | |||
| 97 | #define AOPOBJ_OBJECT_INITIALIZED 0x08 | 97 | #define AOPOBJ_OBJECT_INITIALIZED 0x08 |
| 98 | #define AOPOBJ_SETUP_COMPLETE 0x10 | 98 | #define AOPOBJ_SETUP_COMPLETE 0x10 |
| 99 | #define AOPOBJ_SINGLE_DATUM 0x20 | 99 | #define AOPOBJ_SINGLE_DATUM 0x20 |
| 100 | #define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ | ||
| 100 | 101 | ||
| 101 | /****************************************************************************** | 102 | /****************************************************************************** |
| 102 | * | 103 | * |
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 584d766e6f12..b79978f7bc71 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c | |||
| @@ -397,6 +397,30 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) | |||
| 397 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | 397 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), |
| 398 | extra_desc->extra.aml_length, | 398 | extra_desc->extra.aml_length, |
| 399 | extra_desc->extra.aml_start); | 399 | extra_desc->extra.aml_start); |
| 400 | if (ACPI_FAILURE(status)) { | ||
| 401 | return_ACPI_STATUS(status); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* Validate the region address/length via the host OS */ | ||
| 405 | |||
| 406 | status = acpi_os_validate_address(obj_desc->region.space_id, | ||
| 407 | obj_desc->region.address, | ||
| 408 | (acpi_size) obj_desc->region.length, | ||
| 409 | acpi_ut_get_node_name(node)); | ||
| 410 | |||
| 411 | if (ACPI_FAILURE(status)) { | ||
| 412 | /* | ||
| 413 | * Invalid address/length. We will emit an error message and mark | ||
| 414 | * the region as invalid, so that it will cause an additional error if | ||
| 415 | * it is ever used. Then return AE_OK. | ||
| 416 | */ | ||
| 417 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 418 | "During address validation of OpRegion [%4.4s]", | ||
| 419 | node->name.ascii)); | ||
| 420 | obj_desc->common.flags |= AOPOBJ_INVALID; | ||
| 421 | status = AE_OK; | ||
| 422 | } | ||
| 423 | |||
| 400 | return_ACPI_STATUS(status); | 424 | return_ACPI_STATUS(status); |
| 401 | } | 425 | } |
| 402 | 426 | ||
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index d4075b821021..6687be167f5f 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c | |||
| @@ -113,6 +113,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
| 113 | } | 113 | } |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | /* Exit if Address/Length have been disallowed by the host OS */ | ||
| 117 | |||
| 118 | if (rgn_desc->common.flags & AOPOBJ_INVALID) { | ||
| 119 | return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); | ||
| 120 | } | ||
| 121 | |||
| 116 | /* | 122 | /* |
| 117 | * Exit now for SMBus address space, it has a non-linear address space | 123 | * Exit now for SMBus address space, it has a non-linear address space |
| 118 | * and the request cannot be directly validated | 124 | * and the request cannot be directly validated |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 71670719d61a..5691f165a952 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -189,11 +189,36 @@ acpi_status __init acpi_os_initialize(void) | |||
| 189 | return AE_OK; | 189 | return AE_OK; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | static void bind_to_cpu0(struct work_struct *work) | ||
| 193 | { | ||
| 194 | set_cpus_allowed(current, cpumask_of_cpu(0)); | ||
| 195 | kfree(work); | ||
| 196 | } | ||
| 197 | |||
| 198 | static void bind_workqueue(struct workqueue_struct *wq) | ||
| 199 | { | ||
| 200 | struct work_struct *work; | ||
| 201 | |||
| 202 | work = kzalloc(sizeof(struct work_struct), GFP_KERNEL); | ||
| 203 | INIT_WORK(work, bind_to_cpu0); | ||
| 204 | queue_work(wq, work); | ||
| 205 | } | ||
| 206 | |||
| 192 | acpi_status acpi_os_initialize1(void) | 207 | acpi_status acpi_os_initialize1(void) |
| 193 | { | 208 | { |
| 209 | /* | ||
| 210 | * On some machines, a software-initiated SMI causes corruption unless | ||
| 211 | * the SMI runs on CPU 0. An SMI can be initiated by any AML, but | ||
| 212 | * typically it's done in GPE-related methods that are run via | ||
| 213 | * workqueues, so we can avoid the known corruption cases by binding | ||
| 214 | * the workqueues to CPU 0. | ||
| 215 | */ | ||
| 194 | kacpid_wq = create_singlethread_workqueue("kacpid"); | 216 | kacpid_wq = create_singlethread_workqueue("kacpid"); |
| 217 | bind_workqueue(kacpid_wq); | ||
| 195 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); | 218 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); |
| 219 | bind_workqueue(kacpi_notify_wq); | ||
| 196 | kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); | 220 | kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); |
| 221 | bind_workqueue(kacpi_hotplug_wq); | ||
| 197 | BUG_ON(!kacpid_wq); | 222 | BUG_ON(!kacpid_wq); |
| 198 | BUG_ON(!kacpi_notify_wq); | 223 | BUG_ON(!kacpi_notify_wq); |
| 199 | BUG_ON(!kacpi_hotplug_wq); | 224 | BUG_ON(!kacpi_hotplug_wq); |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 0944daec064f..9c61ab2177cf 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
| @@ -121,7 +121,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
| 121 | table_attr->attr.size = 0; | 121 | table_attr->attr.size = 0; |
| 122 | table_attr->attr.read = acpi_table_show; | 122 | table_attr->attr.read = acpi_table_show; |
| 123 | table_attr->attr.attr.name = table_attr->name; | 123 | table_attr->attr.attr.name = table_attr->name; |
| 124 | table_attr->attr.attr.mode = 0444; | 124 | table_attr->attr.attr.mode = 0400; |
| 125 | 125 | ||
| 126 | return; | 126 | return; |
| 127 | } | 127 | } |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 46dad12f952f..77c6097ced80 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -277,31 +277,6 @@ config THINKPAD_ACPI_UNSAFE_LEDS | |||
| 277 | Say N here, unless you are building a kernel for your own | 277 | Say N here, unless you are building a kernel for your own |
| 278 | use, and need to control the important firmware LEDs. | 278 | use, and need to control the important firmware LEDs. |
| 279 | 279 | ||
| 280 | config THINKPAD_ACPI_DOCK | ||
| 281 | bool "Legacy Docking Station Support" | ||
| 282 | depends on THINKPAD_ACPI | ||
| 283 | depends on ACPI_DOCK=n | ||
| 284 | default n | ||
| 285 | ---help--- | ||
| 286 | Allows the thinkpad_acpi driver to handle docking station events. | ||
| 287 | This support was made obsolete by the generic ACPI docking station | ||
| 288 | support (CONFIG_ACPI_DOCK). It will allow locking and removing the | ||
| 289 | laptop from the docking station, but will not properly connect PCI | ||
| 290 | devices. | ||
| 291 | |||
| 292 | If you are not sure, say N here. | ||
| 293 | |||
| 294 | config THINKPAD_ACPI_BAY | ||
| 295 | bool "Legacy Removable Bay Support" | ||
| 296 | depends on THINKPAD_ACPI | ||
| 297 | default y | ||
| 298 | ---help--- | ||
| 299 | Allows the thinkpad_acpi driver to handle removable bays. It will | ||
| 300 | electrically disable the device in the bay, and also generate | ||
| 301 | notifications when the bay lever is ejected or inserted. | ||
| 302 | |||
| 303 | If you are not sure, say Y here. | ||
| 304 | |||
| 305 | config THINKPAD_ACPI_VIDEO | 280 | config THINKPAD_ACPI_VIDEO |
| 306 | bool "Video output control support" | 281 | bool "Video output control support" |
| 307 | depends on THINKPAD_ACPI | 282 | depends on THINKPAD_ACPI |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index ec560f16d720..222ffb892f22 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -143,6 +143,7 @@ struct eeepc_hotk { | |||
| 143 | struct rfkill *bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
| 144 | struct rfkill *wwan3g_rfkill; | 144 | struct rfkill *wwan3g_rfkill; |
| 145 | struct hotplug_slot *hotplug_slot; | 145 | struct hotplug_slot *hotplug_slot; |
| 146 | struct work_struct hotplug_work; | ||
| 146 | }; | 147 | }; |
| 147 | 148 | ||
| 148 | /* The actual device the driver binds to */ | 149 | /* The actual device the driver binds to */ |
| @@ -660,7 +661,7 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | |||
| 660 | return 0; | 661 | return 0; |
| 661 | } | 662 | } |
| 662 | 663 | ||
| 663 | static void eeepc_rfkill_hotplug(void) | 664 | static void eeepc_hotplug_work(struct work_struct *work) |
| 664 | { | 665 | { |
| 665 | struct pci_dev *dev; | 666 | struct pci_dev *dev; |
| 666 | struct pci_bus *bus = pci_find_bus(0, 1); | 667 | struct pci_bus *bus = pci_find_bus(0, 1); |
| @@ -701,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
| 701 | if (event != ACPI_NOTIFY_BUS_CHECK) | 702 | if (event != ACPI_NOTIFY_BUS_CHECK) |
| 702 | return; | 703 | return; |
| 703 | 704 | ||
| 704 | eeepc_rfkill_hotplug(); | 705 | schedule_work(&ehotk->hotplug_work); |
| 705 | } | 706 | } |
| 706 | 707 | ||
| 707 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) | 708 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) |
| @@ -892,7 +893,7 @@ static int eeepc_hotk_resume(struct acpi_device *device) | |||
| 892 | 893 | ||
| 893 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); | 894 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); |
| 894 | 895 | ||
| 895 | eeepc_rfkill_hotplug(); | 896 | schedule_work(&ehotk->hotplug_work); |
| 896 | } | 897 | } |
| 897 | 898 | ||
| 898 | if (ehotk->bluetooth_rfkill) | 899 | if (ehotk->bluetooth_rfkill) |
| @@ -1093,6 +1094,8 @@ static int eeepc_rfkill_init(struct device *dev) | |||
| 1093 | { | 1094 | { |
| 1094 | int result = 0; | 1095 | int result = 0; |
| 1095 | 1096 | ||
| 1097 | INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work); | ||
| 1098 | |||
| 1096 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | 1099 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); |
| 1097 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | 1100 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); |
| 1098 | 1101 | ||
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index ca508564a181..a2ad53e15874 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -520,11 +520,13 @@ static int hp_wmi_resume_handler(struct platform_device *device) | |||
| 520 | * the input layer will only actually pass it on if the state | 520 | * the input layer will only actually pass it on if the state |
| 521 | * changed. | 521 | * changed. |
| 522 | */ | 522 | */ |
| 523 | 523 | if (hp_wmi_input_dev) { | |
| 524 | input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); | 524 | input_report_switch(hp_wmi_input_dev, SW_DOCK, |
| 525 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | 525 | hp_wmi_dock_state()); |
| 526 | hp_wmi_tablet_state()); | 526 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, |
| 527 | input_sync(hp_wmi_input_dev); | 527 | hp_wmi_tablet_state()); |
| 528 | input_sync(hp_wmi_input_dev); | ||
| 529 | } | ||
| 528 | 530 | ||
| 529 | return 0; | 531 | return 0; |
| 530 | } | 532 | } |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a463fd72c495..e85600852502 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -239,12 +239,6 @@ struct ibm_init_struct { | |||
| 239 | }; | 239 | }; |
| 240 | 240 | ||
| 241 | static struct { | 241 | static struct { |
| 242 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
| 243 | u32 bay_status:1; | ||
| 244 | u32 bay_eject:1; | ||
| 245 | u32 bay_status2:1; | ||
| 246 | u32 bay_eject2:1; | ||
| 247 | #endif | ||
| 248 | u32 bluetooth:1; | 242 | u32 bluetooth:1; |
| 249 | u32 hotkey:1; | 243 | u32 hotkey:1; |
| 250 | u32 hotkey_mask:1; | 244 | u32 hotkey_mask:1; |
| @@ -589,18 +583,6 @@ static int acpi_ec_write(int i, u8 v) | |||
| 589 | return 1; | 583 | return 1; |
| 590 | } | 584 | } |
| 591 | 585 | ||
| 592 | #if defined(CONFIG_THINKPAD_ACPI_DOCK) || defined(CONFIG_THINKPAD_ACPI_BAY) | ||
| 593 | static int _sta(acpi_handle handle) | ||
| 594 | { | ||
| 595 | int status; | ||
| 596 | |||
| 597 | if (!handle || !acpi_evalf(handle, &status, "_STA", "d")) | ||
| 598 | status = 0; | ||
| 599 | |||
| 600 | return status; | ||
| 601 | } | ||
| 602 | #endif | ||
| 603 | |||
| 604 | static int issue_thinkpad_cmos_command(int cmos_cmd) | 586 | static int issue_thinkpad_cmos_command(int cmos_cmd) |
| 605 | { | 587 | { |
| 606 | if (!cmos_handle) | 588 | if (!cmos_handle) |
| @@ -784,6 +766,8 @@ static int dispatch_procfs_write(struct file *file, | |||
| 784 | 766 | ||
| 785 | if (!ibm || !ibm->write) | 767 | if (!ibm || !ibm->write) |
| 786 | return -EINVAL; | 768 | return -EINVAL; |
| 769 | if (count > PAGE_SIZE - 2) | ||
| 770 | return -EINVAL; | ||
| 787 | 771 | ||
| 788 | kernbuf = kmalloc(count + 2, GFP_KERNEL); | 772 | kernbuf = kmalloc(count + 2, GFP_KERNEL); |
| 789 | if (!kernbuf) | 773 | if (!kernbuf) |
| @@ -4442,293 +4426,6 @@ static struct ibm_struct light_driver_data = { | |||
| 4442 | }; | 4426 | }; |
| 4443 | 4427 | ||
| 4444 | /************************************************************************* | 4428 | /************************************************************************* |
| 4445 | * Dock subdriver | ||
| 4446 | */ | ||
| 4447 | |||
| 4448 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
| 4449 | |||
| 4450 | static void dock_notify(struct ibm_struct *ibm, u32 event); | ||
| 4451 | static int dock_read(char *p); | ||
| 4452 | static int dock_write(char *buf); | ||
| 4453 | |||
| 4454 | TPACPI_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ | ||
| 4455 | "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ | ||
| 4456 | "\\_SB.PCI0.PCI1.DOCK", /* all others */ | ||
| 4457 | "\\_SB.PCI.ISA.SLCE", /* 570 */ | ||
| 4458 | ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ | ||
| 4459 | |||
| 4460 | /* don't list other alternatives as we install a notify handler on the 570 */ | ||
| 4461 | TPACPI_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ | ||
| 4462 | |||
| 4463 | static const struct acpi_device_id ibm_pci_device_ids[] = { | ||
| 4464 | {PCI_ROOT_HID_STRING, 0}, | ||
| 4465 | {"", 0}, | ||
| 4466 | }; | ||
| 4467 | |||
| 4468 | static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { | ||
| 4469 | { | ||
| 4470 | .notify = dock_notify, | ||
| 4471 | .handle = &dock_handle, | ||
| 4472 | .type = ACPI_SYSTEM_NOTIFY, | ||
| 4473 | }, | ||
| 4474 | { | ||
| 4475 | /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. | ||
| 4476 | * We just use it to get notifications of dock hotplug | ||
| 4477 | * in very old thinkpads */ | ||
| 4478 | .hid = ibm_pci_device_ids, | ||
| 4479 | .notify = dock_notify, | ||
| 4480 | .handle = &pci_handle, | ||
| 4481 | .type = ACPI_SYSTEM_NOTIFY, | ||
| 4482 | }, | ||
| 4483 | }; | ||
| 4484 | |||
| 4485 | static struct ibm_struct dock_driver_data[2] = { | ||
| 4486 | { | ||
| 4487 | .name = "dock", | ||
| 4488 | .read = dock_read, | ||
| 4489 | .write = dock_write, | ||
| 4490 | .acpi = &ibm_dock_acpidriver[0], | ||
| 4491 | }, | ||
| 4492 | { | ||
| 4493 | .name = "dock", | ||
| 4494 | .acpi = &ibm_dock_acpidriver[1], | ||
| 4495 | }, | ||
| 4496 | }; | ||
| 4497 | |||
| 4498 | #define dock_docked() (_sta(dock_handle) & 1) | ||
| 4499 | |||
| 4500 | static int __init dock_init(struct ibm_init_struct *iibm) | ||
| 4501 | { | ||
| 4502 | vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n"); | ||
| 4503 | |||
| 4504 | TPACPI_ACPIHANDLE_INIT(dock); | ||
| 4505 | |||
| 4506 | vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n", | ||
| 4507 | str_supported(dock_handle != NULL)); | ||
| 4508 | |||
| 4509 | return (dock_handle)? 0 : 1; | ||
| 4510 | } | ||
| 4511 | |||
| 4512 | static int __init dock_init2(struct ibm_init_struct *iibm) | ||
| 4513 | { | ||
| 4514 | int dock2_needed; | ||
| 4515 | |||
| 4516 | vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n"); | ||
| 4517 | |||
| 4518 | if (dock_driver_data[0].flags.acpi_driver_registered && | ||
| 4519 | dock_driver_data[0].flags.acpi_notify_installed) { | ||
| 4520 | TPACPI_ACPIHANDLE_INIT(pci); | ||
| 4521 | dock2_needed = (pci_handle != NULL); | ||
| 4522 | vdbg_printk(TPACPI_DBG_INIT, | ||
| 4523 | "dock PCI handler for the TP 570 is %s\n", | ||
| 4524 | str_supported(dock2_needed)); | ||
| 4525 | } else { | ||
| 4526 | vdbg_printk(TPACPI_DBG_INIT, | ||
| 4527 | "dock subdriver part 2 not required\n"); | ||
| 4528 | dock2_needed = 0; | ||
| 4529 | } | ||
| 4530 | |||
| 4531 | return (dock2_needed)? 0 : 1; | ||
| 4532 | } | ||
| 4533 | |||
| 4534 | static void dock_notify(struct ibm_struct *ibm, u32 event) | ||
| 4535 | { | ||
| 4536 | int docked = dock_docked(); | ||
| 4537 | int pci = ibm->acpi->hid && ibm->acpi->device && | ||
| 4538 | acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids); | ||
| 4539 | int data; | ||
| 4540 | |||
| 4541 | if (event == 1 && !pci) /* 570 */ | ||
| 4542 | data = 1; /* button */ | ||
| 4543 | else if (event == 1 && pci) /* 570 */ | ||
| 4544 | data = 3; /* dock */ | ||
| 4545 | else if (event == 3 && docked) | ||
| 4546 | data = 1; /* button */ | ||
| 4547 | else if (event == 3 && !docked) | ||
| 4548 | data = 2; /* undock */ | ||
| 4549 | else if (event == 0 && docked) | ||
| 4550 | data = 3; /* dock */ | ||
| 4551 | else { | ||
| 4552 | printk(TPACPI_ERR "unknown dock event %d, status %d\n", | ||
| 4553 | event, _sta(dock_handle)); | ||
| 4554 | data = 0; /* unknown */ | ||
| 4555 | } | ||
| 4556 | acpi_bus_generate_proc_event(ibm->acpi->device, event, data); | ||
| 4557 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
| 4558 | dev_name(&ibm->acpi->device->dev), | ||
| 4559 | event, data); | ||
| 4560 | } | ||
| 4561 | |||
| 4562 | static int dock_read(char *p) | ||
| 4563 | { | ||
| 4564 | int len = 0; | ||
| 4565 | int docked = dock_docked(); | ||
| 4566 | |||
| 4567 | if (!dock_handle) | ||
| 4568 | len += sprintf(p + len, "status:\t\tnot supported\n"); | ||
| 4569 | else if (!docked) | ||
| 4570 | len += sprintf(p + len, "status:\t\tundocked\n"); | ||
| 4571 | else { | ||
| 4572 | len += sprintf(p + len, "status:\t\tdocked\n"); | ||
| 4573 | len += sprintf(p + len, "commands:\tdock, undock\n"); | ||
| 4574 | } | ||
| 4575 | |||
| 4576 | return len; | ||
| 4577 | } | ||
| 4578 | |||
| 4579 | static int dock_write(char *buf) | ||
| 4580 | { | ||
| 4581 | char *cmd; | ||
| 4582 | |||
| 4583 | if (!dock_docked()) | ||
| 4584 | return -ENODEV; | ||
| 4585 | |||
| 4586 | while ((cmd = next_cmd(&buf))) { | ||
| 4587 | if (strlencmp(cmd, "undock") == 0) { | ||
| 4588 | if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) || | ||
| 4589 | !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1)) | ||
| 4590 | return -EIO; | ||
| 4591 | } else if (strlencmp(cmd, "dock") == 0) { | ||
| 4592 | if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1)) | ||
| 4593 | return -EIO; | ||
| 4594 | } else | ||
| 4595 | return -EINVAL; | ||
| 4596 | } | ||
| 4597 | |||
| 4598 | return 0; | ||
| 4599 | } | ||
| 4600 | |||
| 4601 | #endif /* CONFIG_THINKPAD_ACPI_DOCK */ | ||
| 4602 | |||
| 4603 | /************************************************************************* | ||
| 4604 | * Bay subdriver | ||
| 4605 | */ | ||
| 4606 | |||
| 4607 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
| 4608 | |||
| 4609 | TPACPI_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ | ||
| 4610 | "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ | ||
| 4611 | "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ | ||
| 4612 | "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ | ||
| 4613 | ); /* A21e, R30, R31 */ | ||
| 4614 | TPACPI_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */ | ||
| 4615 | "_EJ0", /* all others */ | ||
| 4616 | ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */ | ||
| 4617 | TPACPI_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ | ||
| 4618 | "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */ | ||
| 4619 | ); /* all others */ | ||
| 4620 | TPACPI_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ | ||
| 4621 | "_EJ0", /* 770x */ | ||
| 4622 | ); /* all others */ | ||
| 4623 | |||
| 4624 | static int __init bay_init(struct ibm_init_struct *iibm) | ||
| 4625 | { | ||
| 4626 | vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n"); | ||
| 4627 | |||
| 4628 | TPACPI_ACPIHANDLE_INIT(bay); | ||
| 4629 | if (bay_handle) | ||
| 4630 | TPACPI_ACPIHANDLE_INIT(bay_ej); | ||
| 4631 | TPACPI_ACPIHANDLE_INIT(bay2); | ||
| 4632 | if (bay2_handle) | ||
| 4633 | TPACPI_ACPIHANDLE_INIT(bay2_ej); | ||
| 4634 | |||
| 4635 | tp_features.bay_status = bay_handle && | ||
| 4636 | acpi_evalf(bay_handle, NULL, "_STA", "qv"); | ||
| 4637 | tp_features.bay_status2 = bay2_handle && | ||
| 4638 | acpi_evalf(bay2_handle, NULL, "_STA", "qv"); | ||
| 4639 | |||
| 4640 | tp_features.bay_eject = bay_handle && bay_ej_handle && | ||
| 4641 | (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental); | ||
| 4642 | tp_features.bay_eject2 = bay2_handle && bay2_ej_handle && | ||
| 4643 | (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental); | ||
| 4644 | |||
| 4645 | vdbg_printk(TPACPI_DBG_INIT, | ||
| 4646 | "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n", | ||
| 4647 | str_supported(tp_features.bay_status), | ||
| 4648 | str_supported(tp_features.bay_eject), | ||
| 4649 | str_supported(tp_features.bay_status2), | ||
| 4650 | str_supported(tp_features.bay_eject2)); | ||
| 4651 | |||
| 4652 | return (tp_features.bay_status || tp_features.bay_eject || | ||
| 4653 | tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1; | ||
| 4654 | } | ||
| 4655 | |||
| 4656 | static void bay_notify(struct ibm_struct *ibm, u32 event) | ||
| 4657 | { | ||
| 4658 | acpi_bus_generate_proc_event(ibm->acpi->device, event, 0); | ||
| 4659 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
| 4660 | dev_name(&ibm->acpi->device->dev), | ||
| 4661 | event, 0); | ||
| 4662 | } | ||
| 4663 | |||
| 4664 | #define bay_occupied(b) (_sta(b##_handle) & 1) | ||
| 4665 | |||
| 4666 | static int bay_read(char *p) | ||
| 4667 | { | ||
| 4668 | int len = 0; | ||
| 4669 | int occupied = bay_occupied(bay); | ||
| 4670 | int occupied2 = bay_occupied(bay2); | ||
| 4671 | int eject, eject2; | ||
| 4672 | |||
| 4673 | len += sprintf(p + len, "status:\t\t%s\n", | ||
| 4674 | tp_features.bay_status ? | ||
| 4675 | (occupied ? "occupied" : "unoccupied") : | ||
| 4676 | "not supported"); | ||
| 4677 | if (tp_features.bay_status2) | ||
| 4678 | len += sprintf(p + len, "status2:\t%s\n", occupied2 ? | ||
| 4679 | "occupied" : "unoccupied"); | ||
| 4680 | |||
| 4681 | eject = tp_features.bay_eject && occupied; | ||
| 4682 | eject2 = tp_features.bay_eject2 && occupied2; | ||
| 4683 | |||
| 4684 | if (eject && eject2) | ||
| 4685 | len += sprintf(p + len, "commands:\teject, eject2\n"); | ||
| 4686 | else if (eject) | ||
| 4687 | len += sprintf(p + len, "commands:\teject\n"); | ||
| 4688 | else if (eject2) | ||
| 4689 | len += sprintf(p + len, "commands:\teject2\n"); | ||
| 4690 | |||
| 4691 | return len; | ||
| 4692 | } | ||
| 4693 | |||
| 4694 | static int bay_write(char *buf) | ||
| 4695 | { | ||
| 4696 | char *cmd; | ||
| 4697 | |||
| 4698 | if (!tp_features.bay_eject && !tp_features.bay_eject2) | ||
| 4699 | return -ENODEV; | ||
| 4700 | |||
| 4701 | while ((cmd = next_cmd(&buf))) { | ||
| 4702 | if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) { | ||
| 4703 | if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1)) | ||
| 4704 | return -EIO; | ||
| 4705 | } else if (tp_features.bay_eject2 && | ||
| 4706 | strlencmp(cmd, "eject2") == 0) { | ||
| 4707 | if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1)) | ||
| 4708 | return -EIO; | ||
| 4709 | } else | ||
| 4710 | return -EINVAL; | ||
| 4711 | } | ||
| 4712 | |||
| 4713 | return 0; | ||
| 4714 | } | ||
| 4715 | |||
| 4716 | static struct tp_acpi_drv_struct ibm_bay_acpidriver = { | ||
| 4717 | .notify = bay_notify, | ||
| 4718 | .handle = &bay_handle, | ||
| 4719 | .type = ACPI_SYSTEM_NOTIFY, | ||
| 4720 | }; | ||
| 4721 | |||
| 4722 | static struct ibm_struct bay_driver_data = { | ||
| 4723 | .name = "bay", | ||
| 4724 | .read = bay_read, | ||
| 4725 | .write = bay_write, | ||
| 4726 | .acpi = &ibm_bay_acpidriver, | ||
| 4727 | }; | ||
| 4728 | |||
| 4729 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ | ||
| 4730 | |||
| 4731 | /************************************************************************* | ||
| 4732 | * CMOS subdriver | 4429 | * CMOS subdriver |
| 4733 | */ | 4430 | */ |
| 4734 | 4431 | ||
| @@ -5945,14 +5642,48 @@ static struct backlight_ops ibm_backlight_data = { | |||
| 5945 | 5642 | ||
| 5946 | /* --------------------------------------------------------------------- */ | 5643 | /* --------------------------------------------------------------------- */ |
| 5947 | 5644 | ||
| 5645 | /* | ||
| 5646 | * These are only useful for models that have only one possibility | ||
| 5647 | * of GPU. If the BIOS model handles both ATI and Intel, don't use | ||
| 5648 | * these quirks. | ||
| 5649 | */ | ||
| 5650 | #define TPACPI_BRGHT_Q_NOEC 0x0001 /* Must NOT use EC HBRV */ | ||
| 5651 | #define TPACPI_BRGHT_Q_EC 0x0002 /* Should or must use EC HBRV */ | ||
| 5652 | #define TPACPI_BRGHT_Q_ASK 0x8000 /* Ask for user report */ | ||
| 5653 | |||
| 5654 | static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { | ||
| 5655 | /* Models with ATI GPUs known to require ECNVRAM mode */ | ||
| 5656 | TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ | ||
| 5657 | |||
| 5658 | /* Models with ATI GPUs (waiting confirmation) */ | ||
| 5659 | TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
| 5660 | TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
| 5661 | TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
| 5662 | TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
| 5663 | |||
| 5664 | /* Models with Intel Extreme Graphics 2 (waiting confirmation) */ | ||
| 5665 | TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
| 5666 | TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
| 5667 | TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
| 5668 | |||
| 5669 | /* Models with Intel GMA900 */ | ||
| 5670 | TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ | ||
| 5671 | TPACPI_Q_IBM('7', '4', TPACPI_BRGHT_Q_NOEC), /* X41 */ | ||
| 5672 | TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */ | ||
| 5673 | }; | ||
| 5674 | |||
| 5948 | static int __init brightness_init(struct ibm_init_struct *iibm) | 5675 | static int __init brightness_init(struct ibm_init_struct *iibm) |
| 5949 | { | 5676 | { |
| 5950 | int b; | 5677 | int b; |
| 5678 | unsigned long quirks; | ||
| 5951 | 5679 | ||
| 5952 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); | 5680 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); |
| 5953 | 5681 | ||
| 5954 | mutex_init(&brightness_mutex); | 5682 | mutex_init(&brightness_mutex); |
| 5955 | 5683 | ||
| 5684 | quirks = tpacpi_check_quirks(brightness_quirk_table, | ||
| 5685 | ARRAY_SIZE(brightness_quirk_table)); | ||
| 5686 | |||
| 5956 | /* | 5687 | /* |
| 5957 | * We always attempt to detect acpi support, so as to switch | 5688 | * We always attempt to detect acpi support, so as to switch |
| 5958 | * Lenovo Vista BIOS to ACPI brightness mode even if we are not | 5689 | * Lenovo Vista BIOS to ACPI brightness mode even if we are not |
| @@ -6009,23 +5740,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
| 6009 | /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ | 5740 | /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ |
| 6010 | if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || | 5741 | if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || |
| 6011 | brightness_mode == TPACPI_BRGHT_MODE_MAX) { | 5742 | brightness_mode == TPACPI_BRGHT_MODE_MAX) { |
| 6012 | if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) { | 5743 | if (quirks & TPACPI_BRGHT_Q_EC) |
| 6013 | /* | 5744 | brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; |
| 6014 | * IBM models that define HBRV probably have | 5745 | else |
| 6015 | * EC-based backlight level control | ||
| 6016 | */ | ||
| 6017 | if (acpi_evalf(ec_handle, NULL, "HBRV", "qd")) | ||
| 6018 | /* T40-T43, R50-R52, R50e, R51e, X31-X41 */ | ||
| 6019 | brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; | ||
| 6020 | else | ||
| 6021 | /* all other IBM ThinkPads */ | ||
| 6022 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; | ||
| 6023 | } else | ||
| 6024 | /* All Lenovo ThinkPads */ | ||
| 6025 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; | 5746 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; |
| 6026 | 5747 | ||
| 6027 | dbg_printk(TPACPI_DBG_BRGHT, | 5748 | dbg_printk(TPACPI_DBG_BRGHT, |
| 6028 | "selected brightness_mode=%d\n", | 5749 | "driver auto-selected brightness_mode=%d\n", |
| 6029 | brightness_mode); | 5750 | brightness_mode); |
| 6030 | } | 5751 | } |
| 6031 | 5752 | ||
| @@ -6052,6 +5773,15 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
| 6052 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, | 5773 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, |
| 6053 | "brightness is supported\n"); | 5774 | "brightness is supported\n"); |
| 6054 | 5775 | ||
| 5776 | if (quirks & TPACPI_BRGHT_Q_ASK) { | ||
| 5777 | printk(TPACPI_NOTICE | ||
| 5778 | "brightness: will use unverified default: " | ||
| 5779 | "brightness_mode=%d\n", brightness_mode); | ||
| 5780 | printk(TPACPI_NOTICE | ||
| 5781 | "brightness: please report to %s whether it works well " | ||
| 5782 | "or not on your ThinkPad\n", TPACPI_MAIL); | ||
| 5783 | } | ||
| 5784 | |||
| 6055 | ibm_backlight_device->props.max_brightness = | 5785 | ibm_backlight_device->props.max_brightness = |
| 6056 | (tp_features.bright_16levels)? 15 : 7; | 5786 | (tp_features.bright_16levels)? 15 : 7; |
| 6057 | ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; | 5787 | ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; |
| @@ -7854,22 +7584,6 @@ static struct ibm_init_struct ibms_init[] __initdata = { | |||
| 7854 | .init = light_init, | 7584 | .init = light_init, |
| 7855 | .data = &light_driver_data, | 7585 | .data = &light_driver_data, |
| 7856 | }, | 7586 | }, |
| 7857 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
| 7858 | { | ||
| 7859 | .init = dock_init, | ||
| 7860 | .data = &dock_driver_data[0], | ||
| 7861 | }, | ||
| 7862 | { | ||
| 7863 | .init = dock_init2, | ||
| 7864 | .data = &dock_driver_data[1], | ||
| 7865 | }, | ||
| 7866 | #endif | ||
| 7867 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
| 7868 | { | ||
| 7869 | .init = bay_init, | ||
| 7870 | .data = &bay_driver_data, | ||
| 7871 | }, | ||
| 7872 | #endif | ||
| 7873 | { | 7587 | { |
| 7874 | .init = cmos_init, | 7588 | .init = cmos_init, |
| 7875 | .data = &cmos_driver_data, | 7589 | .data = &cmos_driver_data, |
| @@ -7968,12 +7682,6 @@ TPACPI_PARAM(hotkey); | |||
| 7968 | TPACPI_PARAM(bluetooth); | 7682 | TPACPI_PARAM(bluetooth); |
| 7969 | TPACPI_PARAM(video); | 7683 | TPACPI_PARAM(video); |
| 7970 | TPACPI_PARAM(light); | 7684 | TPACPI_PARAM(light); |
| 7971 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
| 7972 | TPACPI_PARAM(dock); | ||
| 7973 | #endif | ||
| 7974 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
| 7975 | TPACPI_PARAM(bay); | ||
| 7976 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ | ||
| 7977 | TPACPI_PARAM(cmos); | 7685 | TPACPI_PARAM(cmos); |
| 7978 | TPACPI_PARAM(led); | 7686 | TPACPI_PARAM(led); |
| 7979 | TPACPI_PARAM(beep); | 7687 | TPACPI_PARAM(beep); |
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 3e798593b17b..ab0b85cf21f3 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h | |||
| @@ -242,6 +242,10 @@ acpi_os_derive_pci_id(acpi_handle rhandle, | |||
| 242 | acpi_status acpi_os_validate_interface(char *interface); | 242 | acpi_status acpi_os_validate_interface(char *interface); |
| 243 | acpi_status acpi_osi_invalidate(char* interface); | 243 | acpi_status acpi_osi_invalidate(char* interface); |
| 244 | 244 | ||
| 245 | acpi_status | ||
| 246 | acpi_os_validate_address(u8 space_id, acpi_physical_address address, | ||
| 247 | acpi_size length, char *name); | ||
| 248 | |||
| 245 | u64 acpi_os_get_timer(void); | 249 | u64 acpi_os_get_timer(void); |
| 246 | 250 | ||
| 247 | acpi_status acpi_os_signal(u32 function, void *info); | 251 | acpi_status acpi_os_signal(u32 function, void *info); |
