diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/Kconfig | 25 | ||||
-rw-r--r-- | drivers/platform/x86/acer-wmi.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 9 | ||||
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 14 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 390 |
5 files changed, 64 insertions, 376 deletions
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/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index be2fd6f91639..fb45f5ee8df1 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -973,7 +973,7 @@ static int acer_rfkill_set(void *data, bool blocked) | |||
973 | { | 973 | { |
974 | acpi_status status; | 974 | acpi_status status; |
975 | u32 cap = (unsigned long)data; | 975 | u32 cap = (unsigned long)data; |
976 | status = set_u32(!!blocked, cap); | 976 | status = set_u32(!blocked, cap); |
977 | if (ACPI_FAILURE(status)) | 977 | if (ACPI_FAILURE(status)) |
978 | return -ENODEV; | 978 | return -ENODEV; |
979 | return 0; | 979 | return 0; |
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 4ac2311c00af..a2ad53e15874 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -171,7 +171,7 @@ static int hp_wmi_tablet_state(void) | |||
171 | static int hp_wmi_set_block(void *data, bool blocked) | 171 | static int hp_wmi_set_block(void *data, bool blocked) |
172 | { | 172 | { |
173 | unsigned long b = (unsigned long) data; | 173 | unsigned long b = (unsigned long) data; |
174 | int query = BIT(b + 8) | ((!!blocked) << b); | 174 | int query = BIT(b + 8) | ((!blocked) << b); |
175 | 175 | ||
176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); | 176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); |
177 | } | 177 | } |
@@ -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); |