23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25 #include <linux/kernel.h>
26 #include <linux/module.h>
28 #include <linux/types.h>
31 #include <linux/rfkill.h>
33 #include <linux/input.h>
41 #define IDEAPAD_RFKILL_DEV_NUM (3)
43 #define CFG_BT_BIT (16)
44 #define CFG_3G_BIT (17)
45 #define CFG_WIFI_BIT (18)
46 #define CFG_CAMERA_BIT (19)
86 static bool no_bt_rfkill;
93 #define IDEAPAD_EC_TIMEOUT (100)
113 unsigned long long result;
120 in_obj.integer.value =
cmd;
142 in_obj[0].integer.value =
cmd;
144 in_obj[1].integer.value =
data;
152 static int read_ec_data(
acpi_handle handle,
int cmd,
unsigned long *data)
155 unsigned long int end_jiffies;
157 if (method_vpcw(handle, 1, cmd))
163 if (method_vpcr(handle, 1, &val))
166 if (method_vpcr(handle, 0, &val))
172 pr_err(
"timeout in read_ec_cmd\n");
176 static int write_ec_cmd(
acpi_handle handle,
int cmd,
unsigned long data)
179 unsigned long int end_jiffies;
181 if (method_vpcw(handle, 0, data))
183 if (method_vpcw(handle, 1, cmd))
189 if (method_vpcr(handle, 1, &val))
194 pr_err(
"timeout in write_ec_cmd\n");
201 static int debugfs_status_show(
struct seq_file *
s,
void *data)
206 seq_printf(s,
"Backlight max:\t%lu\n", value);
207 if (!read_ec_data(ideapad_handle,
VPCCMD_R_BL, &value))
208 seq_printf(s,
"Backlight now:\t%lu\n", value);
210 seq_printf(s,
"BL power value:\t%s\n", value ?
"On" :
"Off");
213 if (!read_ec_data(ideapad_handle,
VPCCMD_R_RF, &value))
215 value ?
"On" :
"Off", value);
218 value ?
"On" :
"Off", value);
219 if (!read_ec_data(ideapad_handle,
VPCCMD_R_BT, &value))
221 value ?
"On" :
"Off", value);
222 if (!read_ec_data(ideapad_handle,
VPCCMD_R_3G, &value))
224 value ?
"On" :
"Off", value);
229 value ?
"On" :
"Off", value);
232 value ?
"On" :
"Off", value);
244 .open = debugfs_status_open,
250 static int debugfs_cfg_show(
struct seq_file *s,
void *data)
266 switch ((ideapad_priv->
cfg)&0x700) {
295 .open = debugfs_cfg_open,
307 pr_err(
"failed to create debugfs directory");
314 pr_err(
"failed to create cfg in debugfs");
319 &debugfs_status_fops);
321 pr_err(
"failed to create status in debugfs");
348 return sprintf(buf,
"%lu\n", result);
353 const char *buf,
size_t count)
359 if (
sscanf(buf,
"%i", &state) != 1)
367 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
375 if (read_ec_data(ideapad_handle,
VPCCMD_R_FAN, &result))
377 return sprintf(buf,
"%lu\n", result);
382 const char *buf,
size_t count)
388 if (
sscanf(buf,
"%i", &state) != 1)
392 ret = write_ec_cmd(ideapad_handle,
VPCCMD_W_FAN, state);
398 static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
400 static struct attribute *ideapad_attributes[] = {
401 &dev_attr_camera_power.attr,
402 &dev_attr_fan_mode.attr,
414 if (attr == &dev_attr_camera_power.attr)
416 else if (attr == &dev_attr_fan_mode.attr) {
418 supported = !read_ec_data(ideapad_handle,
VPCCMD_R_FAN, &value);
422 return supported ? attr->
mode : 0;
426 .is_visible = ideapad_is_visible,
427 .attrs = ideapad_attributes
446 static int ideapad_rfk_set(
void *data,
bool blocked)
450 return write_ec_cmd(ideapad_handle, opcode, !blocked);
454 .set_block = ideapad_rfk_set,
459 unsigned long hw_blocked;
462 if (read_ec_data(ideapad_handle,
VPCCMD_R_RF, &hw_blocked))
464 hw_blocked = !hw_blocked;
471 static int __devinit ideapad_register_rfkill(
struct acpi_device *adevice,
476 unsigned long sw_blocked;
481 write_ec_cmd(ideapad_handle,
482 ideapad_rfk_data[dev].
opcode, 1);
487 ideapad_rfk_data[dev].
type, &ideapad_rfk_ops,
492 if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].
opcode-1,
496 sw_blocked = !sw_blocked;
508 static void ideapad_unregister_rfkill(
struct acpi_device *adevice,
int dev)
533 goto fail_platform_device;
536 &ideapad_attribute_group);
543 fail_platform_device:
551 &ideapad_attribute_group);
558 static const struct key_entry ideapad_keymap[] = {
574 struct input_dev *inputdev;
577 inputdev = input_allocate_device();
579 pr_info(
"Unable to allocate input device\n");
583 inputdev->name =
"Ideapad extra buttons";
584 inputdev->phys =
"ideapad/input0";
588 error = sparse_keymap_setup(inputdev, ideapad_keymap,
NULL);
590 pr_err(
"Unable to setup input device keymap\n");
594 error = input_register_device(inputdev);
596 pr_err(
"Unable to register input device\n");
597 goto err_free_keymap;
604 sparse_keymap_free(inputdev);
606 input_free_device(inputdev);
613 input_unregister_device(priv->
inputdev);
618 unsigned long scancode)
620 sparse_keymap_report_event(priv->
inputdev, scancode, 1,
true);
625 unsigned long long_pressed;
627 if (read_ec_data(ideapad_handle,
VPCCMD_R_NOVO, &long_pressed))
630 ideapad_input_report(priv, 17);
632 ideapad_input_report(priv, 16);
635 static void ideapad_check_special_buttons(
struct ideapad_private *priv)
641 for (bit = 0; bit < 16; bit++) {
646 ideapad_input_report(priv, 65);
650 ideapad_input_report(priv, 64);
660 static int ideapad_backlight_get_brightness(
struct backlight_device *blightdev)
664 if (read_ec_data(ideapad_handle,
VPCCMD_R_BL, &now))
669 static int ideapad_backlight_update_status(
struct backlight_device *blightdev)
672 blightdev->
props.brightness))
682 .get_brightness = ideapad_backlight_get_brightness,
683 .update_status = ideapad_backlight_update_status,
694 if (read_ec_data(ideapad_handle,
VPCCMD_R_BL, &now))
700 props.max_brightness =
max;
705 &ideapad_backlight_ops,
707 if (IS_ERR(blightdev)) {
708 pr_err(
"Could not register backlight device\n");
709 return PTR_ERR(blightdev);
713 blightdev->
props.brightness = now;
715 backlight_update_status(blightdev);
727 static void ideapad_backlight_notify_power(
struct ideapad_private *priv)
739 static void ideapad_backlight_notify_brightness(
struct ideapad_private *priv)
761 static void ideapad_sync_touchpad_state(
struct acpi_device *adevice)
775 ideapad_input_report(priv, value ? 67 : 66);
779 static int __devinit ideapad_acpi_add(
struct acpi_device *adevice)
785 if (read_method_int(adevice->handle,
"_CFG", &cfg))
793 ideapad_handle = adevice->handle;
796 ret = ideapad_platform_init(priv);
798 goto platform_failed;
800 ret = ideapad_debugfs_init(priv);
804 ret = ideapad_input_init(priv);
809 if (
test_bit(ideapad_rfk_data[i].cfgbit, &priv->
cfg))
810 ideapad_register_rfkill(adevice, i);
814 ideapad_sync_rfk_state(priv);
815 ideapad_sync_touchpad_state(adevice);
818 ret = ideapad_backlight_init(priv);
819 if (ret && ret != -
ENODEV)
820 goto backlight_failed;
827 ideapad_unregister_rfkill(adevice, i);
828 ideapad_input_exit(priv);
830 ideapad_debugfs_exit(priv);
832 ideapad_platform_exit(priv);
838 static int __devexit ideapad_acpi_remove(
struct acpi_device *adevice,
int type)
843 ideapad_backlight_exit(priv);
845 ideapad_unregister_rfkill(adevice, i);
846 ideapad_input_exit(priv);
847 ideapad_debugfs_exit(priv);
848 ideapad_platform_exit(priv);
855 static void ideapad_acpi_notify(
struct acpi_device *adevice,
u32 event)
859 unsigned long vpc1, vpc2, vpc_bit;
866 vpc1 = (vpc2 << 8) | vpc1;
867 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
871 ideapad_sync_rfk_state(priv);
877 ideapad_input_report(priv, vpc_bit);
880 ideapad_sync_touchpad_state(adevice);
883 ideapad_backlight_notify_brightness(priv);
886 ideapad_input_novokey(priv);
889 ideapad_backlight_notify_power(priv);
892 ideapad_check_special_buttons(priv);
895 pr_info(
"Unknown event: %lu\n", vpc_bit);
903 ideapad_sync_rfk_state(ideapad_priv);
904 ideapad_sync_touchpad_state(to_acpi_device(device));
910 static struct acpi_driver ideapad_acpi_driver = {
911 .name =
"ideapad_acpi",
913 .ids = ideapad_device_ids,
914 .ops.add = ideapad_acpi_add,
915 .ops.remove = ideapad_acpi_remove,
916 .ops.notify = ideapad_acpi_notify,
917 .drv.pm = &ideapad_pm,