1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2009 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
7 #include <linux/init.h>
8 #include <linux/module.h>
9 #include <linux/slab.h>
10 #include <linux/workqueue.h>
11 #include <linux/acpi.h>
12 #include <linux/backlight.h>
13 #include <linux/input.h>
14 #include <linux/rfkill.h>
16 MODULE_LICENSE("GPL");
24 #define CMPC_ACCEL_DEV_STATE_CLOSED 0
25 #define CMPC_ACCEL_DEV_STATE_OPEN 1
27 #define CMPC_ACCEL_SENSITIVITY_DEFAULT 5
28 #define CMPC_ACCEL_G_SELECT_DEFAULT 0
30 #define CMPC_ACCEL_HID "ACCE0000"
31 #define CMPC_ACCEL_HID_V4 "ACCE0001"
32 #define CMPC_TABLET_HID "TBLT0000"
33 #define CMPC_IPML_HID "IPML200"
34 #define CMPC_KEYS_HID "FNBT0000"
37 * Generic input device code.
40 typedef void (*input_device_init
)(struct input_dev
*dev
);
42 static int cmpc_add_acpi_notify_device(struct acpi_device
*acpi
, char *name
,
43 input_device_init idev_init
)
45 struct input_dev
*inputdev
;
48 inputdev
= input_allocate_device();
51 inputdev
->name
= name
;
52 inputdev
->dev
.parent
= &acpi
->dev
;
54 error
= input_register_device(inputdev
);
56 input_free_device(inputdev
);
59 dev_set_drvdata(&acpi
->dev
, inputdev
);
63 static int cmpc_remove_acpi_notify_device(struct acpi_device
*acpi
)
65 struct input_dev
*inputdev
= dev_get_drvdata(&acpi
->dev
);
66 input_unregister_device(inputdev
);
71 * Accelerometer code for Classmate V4
73 static acpi_status
cmpc_start_accel_v4(acpi_handle handle
)
75 union acpi_object param
[4];
76 struct acpi_object_list input
;
79 param
[0].type
= ACPI_TYPE_INTEGER
;
80 param
[0].integer
.value
= 0x3;
81 param
[1].type
= ACPI_TYPE_INTEGER
;
82 param
[1].integer
.value
= 0;
83 param
[2].type
= ACPI_TYPE_INTEGER
;
84 param
[2].integer
.value
= 0;
85 param
[3].type
= ACPI_TYPE_INTEGER
;
86 param
[3].integer
.value
= 0;
88 input
.pointer
= param
;
89 status
= acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
93 static acpi_status
cmpc_stop_accel_v4(acpi_handle handle
)
95 union acpi_object param
[4];
96 struct acpi_object_list input
;
99 param
[0].type
= ACPI_TYPE_INTEGER
;
100 param
[0].integer
.value
= 0x4;
101 param
[1].type
= ACPI_TYPE_INTEGER
;
102 param
[1].integer
.value
= 0;
103 param
[2].type
= ACPI_TYPE_INTEGER
;
104 param
[2].integer
.value
= 0;
105 param
[3].type
= ACPI_TYPE_INTEGER
;
106 param
[3].integer
.value
= 0;
108 input
.pointer
= param
;
109 status
= acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
113 static acpi_status
cmpc_accel_set_sensitivity_v4(acpi_handle handle
, int val
)
115 union acpi_object param
[4];
116 struct acpi_object_list input
;
118 param
[0].type
= ACPI_TYPE_INTEGER
;
119 param
[0].integer
.value
= 0x02;
120 param
[1].type
= ACPI_TYPE_INTEGER
;
121 param
[1].integer
.value
= val
;
122 param
[2].type
= ACPI_TYPE_INTEGER
;
123 param
[2].integer
.value
= 0;
124 param
[3].type
= ACPI_TYPE_INTEGER
;
125 param
[3].integer
.value
= 0;
127 input
.pointer
= param
;
128 return acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
131 static acpi_status
cmpc_accel_set_g_select_v4(acpi_handle handle
, int val
)
133 union acpi_object param
[4];
134 struct acpi_object_list input
;
136 param
[0].type
= ACPI_TYPE_INTEGER
;
137 param
[0].integer
.value
= 0x05;
138 param
[1].type
= ACPI_TYPE_INTEGER
;
139 param
[1].integer
.value
= val
;
140 param
[2].type
= ACPI_TYPE_INTEGER
;
141 param
[2].integer
.value
= 0;
142 param
[3].type
= ACPI_TYPE_INTEGER
;
143 param
[3].integer
.value
= 0;
145 input
.pointer
= param
;
146 return acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
149 static acpi_status
cmpc_get_accel_v4(acpi_handle handle
,
154 union acpi_object param
[4];
155 struct acpi_object_list input
;
156 struct acpi_buffer output
= { ACPI_ALLOCATE_BUFFER
, NULL
};
160 param
[0].type
= ACPI_TYPE_INTEGER
;
161 param
[0].integer
.value
= 0x01;
162 param
[1].type
= ACPI_TYPE_INTEGER
;
163 param
[1].integer
.value
= 0;
164 param
[2].type
= ACPI_TYPE_INTEGER
;
165 param
[2].integer
.value
= 0;
166 param
[3].type
= ACPI_TYPE_INTEGER
;
167 param
[3].integer
.value
= 0;
169 input
.pointer
= param
;
170 status
= acpi_evaluate_object(handle
, "ACMD", &input
, &output
);
171 if (ACPI_SUCCESS(status
)) {
172 union acpi_object
*obj
;
173 obj
= output
.pointer
;
174 locs
= (int16_t *) obj
->buffer
.pointer
;
178 kfree(output
.pointer
);
183 static void cmpc_accel_handler_v4(struct acpi_device
*dev
, u32 event
)
189 status
= cmpc_get_accel_v4(dev
->handle
, &x
, &y
, &z
);
190 if (ACPI_SUCCESS(status
)) {
191 struct input_dev
*inputdev
= dev_get_drvdata(&dev
->dev
);
193 input_report_abs(inputdev
, ABS_X
, x
);
194 input_report_abs(inputdev
, ABS_Y
, y
);
195 input_report_abs(inputdev
, ABS_Z
, z
);
196 input_sync(inputdev
);
201 static ssize_t
cmpc_accel_sensitivity_show_v4(struct device
*dev
,
202 struct device_attribute
*attr
,
205 struct acpi_device
*acpi
;
206 struct input_dev
*inputdev
;
207 struct cmpc_accel
*accel
;
209 acpi
= to_acpi_device(dev
);
210 inputdev
= dev_get_drvdata(&acpi
->dev
);
211 accel
= dev_get_drvdata(&inputdev
->dev
);
213 return sprintf(buf
, "%d\n", accel
->sensitivity
);
216 static ssize_t
cmpc_accel_sensitivity_store_v4(struct device
*dev
,
217 struct device_attribute
*attr
,
218 const char *buf
, size_t count
)
220 struct acpi_device
*acpi
;
221 struct input_dev
*inputdev
;
222 struct cmpc_accel
*accel
;
223 unsigned long sensitivity
;
226 acpi
= to_acpi_device(dev
);
227 inputdev
= dev_get_drvdata(&acpi
->dev
);
228 accel
= dev_get_drvdata(&inputdev
->dev
);
230 r
= kstrtoul(buf
, 0, &sensitivity
);
234 /* sensitivity must be between 1 and 127 */
235 if (sensitivity
< 1 || sensitivity
> 127)
238 accel
->sensitivity
= sensitivity
;
239 cmpc_accel_set_sensitivity_v4(acpi
->handle
, sensitivity
);
241 return strnlen(buf
, count
);
244 static struct device_attribute cmpc_accel_sensitivity_attr_v4
= {
245 .attr
= { .name
= "sensitivity", .mode
= 0660 },
246 .show
= cmpc_accel_sensitivity_show_v4
,
247 .store
= cmpc_accel_sensitivity_store_v4
250 static ssize_t
cmpc_accel_g_select_show_v4(struct device
*dev
,
251 struct device_attribute
*attr
,
254 struct acpi_device
*acpi
;
255 struct input_dev
*inputdev
;
256 struct cmpc_accel
*accel
;
258 acpi
= to_acpi_device(dev
);
259 inputdev
= dev_get_drvdata(&acpi
->dev
);
260 accel
= dev_get_drvdata(&inputdev
->dev
);
262 return sprintf(buf
, "%d\n", accel
->g_select
);
265 static ssize_t
cmpc_accel_g_select_store_v4(struct device
*dev
,
266 struct device_attribute
*attr
,
267 const char *buf
, size_t count
)
269 struct acpi_device
*acpi
;
270 struct input_dev
*inputdev
;
271 struct cmpc_accel
*accel
;
272 unsigned long g_select
;
275 acpi
= to_acpi_device(dev
);
276 inputdev
= dev_get_drvdata(&acpi
->dev
);
277 accel
= dev_get_drvdata(&inputdev
->dev
);
279 r
= kstrtoul(buf
, 0, &g_select
);
283 /* 0 means 1.5g, 1 means 6g, everything else is wrong */
284 if (g_select
!= 0 && g_select
!= 1)
287 accel
->g_select
= g_select
;
288 cmpc_accel_set_g_select_v4(acpi
->handle
, g_select
);
290 return strnlen(buf
, count
);
293 static struct device_attribute cmpc_accel_g_select_attr_v4
= {
294 .attr
= { .name
= "g_select", .mode
= 0660 },
295 .show
= cmpc_accel_g_select_show_v4
,
296 .store
= cmpc_accel_g_select_store_v4
299 static int cmpc_accel_open_v4(struct input_dev
*input
)
301 struct acpi_device
*acpi
;
302 struct cmpc_accel
*accel
;
304 acpi
= to_acpi_device(input
->dev
.parent
);
305 accel
= dev_get_drvdata(&input
->dev
);
307 cmpc_accel_set_sensitivity_v4(acpi
->handle
, accel
->sensitivity
);
308 cmpc_accel_set_g_select_v4(acpi
->handle
, accel
->g_select
);
310 if (ACPI_SUCCESS(cmpc_start_accel_v4(acpi
->handle
))) {
311 accel
->inputdev_state
= CMPC_ACCEL_DEV_STATE_OPEN
;
317 static void cmpc_accel_close_v4(struct input_dev
*input
)
319 struct acpi_device
*acpi
;
320 struct cmpc_accel
*accel
;
322 acpi
= to_acpi_device(input
->dev
.parent
);
323 accel
= dev_get_drvdata(&input
->dev
);
325 cmpc_stop_accel_v4(acpi
->handle
);
326 accel
->inputdev_state
= CMPC_ACCEL_DEV_STATE_CLOSED
;
329 static void cmpc_accel_idev_init_v4(struct input_dev
*inputdev
)
331 set_bit(EV_ABS
, inputdev
->evbit
);
332 input_set_abs_params(inputdev
, ABS_X
, -255, 255, 16, 0);
333 input_set_abs_params(inputdev
, ABS_Y
, -255, 255, 16, 0);
334 input_set_abs_params(inputdev
, ABS_Z
, -255, 255, 16, 0);
335 inputdev
->open
= cmpc_accel_open_v4
;
336 inputdev
->close
= cmpc_accel_close_v4
;
339 #ifdef CONFIG_PM_SLEEP
340 static int cmpc_accel_suspend_v4(struct device
*dev
)
342 struct input_dev
*inputdev
;
343 struct cmpc_accel
*accel
;
345 inputdev
= dev_get_drvdata(dev
);
346 accel
= dev_get_drvdata(&inputdev
->dev
);
348 if (accel
->inputdev_state
== CMPC_ACCEL_DEV_STATE_OPEN
)
349 return cmpc_stop_accel_v4(to_acpi_device(dev
)->handle
);
354 static int cmpc_accel_resume_v4(struct device
*dev
)
356 struct input_dev
*inputdev
;
357 struct cmpc_accel
*accel
;
359 inputdev
= dev_get_drvdata(dev
);
360 accel
= dev_get_drvdata(&inputdev
->dev
);
362 if (accel
->inputdev_state
== CMPC_ACCEL_DEV_STATE_OPEN
) {
363 cmpc_accel_set_sensitivity_v4(to_acpi_device(dev
)->handle
,
365 cmpc_accel_set_g_select_v4(to_acpi_device(dev
)->handle
,
368 if (ACPI_FAILURE(cmpc_start_accel_v4(to_acpi_device(dev
)->handle
)))
376 static int cmpc_accel_add_v4(struct acpi_device
*acpi
)
379 struct input_dev
*inputdev
;
380 struct cmpc_accel
*accel
;
382 accel
= kmalloc(sizeof(*accel
), GFP_KERNEL
);
386 accel
->inputdev_state
= CMPC_ACCEL_DEV_STATE_CLOSED
;
388 accel
->sensitivity
= CMPC_ACCEL_SENSITIVITY_DEFAULT
;
389 cmpc_accel_set_sensitivity_v4(acpi
->handle
, accel
->sensitivity
);
391 error
= device_create_file(&acpi
->dev
, &cmpc_accel_sensitivity_attr_v4
);
393 goto failed_sensitivity
;
395 accel
->g_select
= CMPC_ACCEL_G_SELECT_DEFAULT
;
396 cmpc_accel_set_g_select_v4(acpi
->handle
, accel
->g_select
);
398 error
= device_create_file(&acpi
->dev
, &cmpc_accel_g_select_attr_v4
);
400 goto failed_g_select
;
402 error
= cmpc_add_acpi_notify_device(acpi
, "cmpc_accel_v4",
403 cmpc_accel_idev_init_v4
);
407 inputdev
= dev_get_drvdata(&acpi
->dev
);
408 dev_set_drvdata(&inputdev
->dev
, accel
);
413 device_remove_file(&acpi
->dev
, &cmpc_accel_g_select_attr_v4
);
415 device_remove_file(&acpi
->dev
, &cmpc_accel_sensitivity_attr_v4
);
421 static int cmpc_accel_remove_v4(struct acpi_device
*acpi
)
423 struct input_dev
*inputdev
;
424 struct cmpc_accel
*accel
;
426 inputdev
= dev_get_drvdata(&acpi
->dev
);
427 accel
= dev_get_drvdata(&inputdev
->dev
);
429 device_remove_file(&acpi
->dev
, &cmpc_accel_sensitivity_attr_v4
);
430 device_remove_file(&acpi
->dev
, &cmpc_accel_g_select_attr_v4
);
431 return cmpc_remove_acpi_notify_device(acpi
);
434 static SIMPLE_DEV_PM_OPS(cmpc_accel_pm
, cmpc_accel_suspend_v4
,
435 cmpc_accel_resume_v4
);
437 static const struct acpi_device_id cmpc_accel_device_ids_v4
[] = {
438 {CMPC_ACCEL_HID_V4
, 0},
442 static struct acpi_driver cmpc_accel_acpi_driver_v4
= {
443 .owner
= THIS_MODULE
,
444 .name
= "cmpc_accel_v4",
445 .class = "cmpc_accel_v4",
446 .ids
= cmpc_accel_device_ids_v4
,
448 .add
= cmpc_accel_add_v4
,
449 .remove
= cmpc_accel_remove_v4
,
450 .notify
= cmpc_accel_handler_v4
,
452 .drv
.pm
= &cmpc_accel_pm
,
457 * Accelerometer code for Classmate versions prior to V4
459 static acpi_status
cmpc_start_accel(acpi_handle handle
)
461 union acpi_object param
[2];
462 struct acpi_object_list input
;
465 param
[0].type
= ACPI_TYPE_INTEGER
;
466 param
[0].integer
.value
= 0x3;
467 param
[1].type
= ACPI_TYPE_INTEGER
;
469 input
.pointer
= param
;
470 status
= acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
474 static acpi_status
cmpc_stop_accel(acpi_handle handle
)
476 union acpi_object param
[2];
477 struct acpi_object_list input
;
480 param
[0].type
= ACPI_TYPE_INTEGER
;
481 param
[0].integer
.value
= 0x4;
482 param
[1].type
= ACPI_TYPE_INTEGER
;
484 input
.pointer
= param
;
485 status
= acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
489 static acpi_status
cmpc_accel_set_sensitivity(acpi_handle handle
, int val
)
491 union acpi_object param
[2];
492 struct acpi_object_list input
;
494 param
[0].type
= ACPI_TYPE_INTEGER
;
495 param
[0].integer
.value
= 0x02;
496 param
[1].type
= ACPI_TYPE_INTEGER
;
497 param
[1].integer
.value
= val
;
499 input
.pointer
= param
;
500 return acpi_evaluate_object(handle
, "ACMD", &input
, NULL
);
503 static acpi_status
cmpc_get_accel(acpi_handle handle
,
508 union acpi_object param
[2];
509 struct acpi_object_list input
;
510 struct acpi_buffer output
= { ACPI_ALLOCATE_BUFFER
, NULL
};
514 param
[0].type
= ACPI_TYPE_INTEGER
;
515 param
[0].integer
.value
= 0x01;
516 param
[1].type
= ACPI_TYPE_INTEGER
;
518 input
.pointer
= param
;
519 status
= acpi_evaluate_object(handle
, "ACMD", &input
, &output
);
520 if (ACPI_SUCCESS(status
)) {
521 union acpi_object
*obj
;
522 obj
= output
.pointer
;
523 locs
= obj
->buffer
.pointer
;
527 kfree(output
.pointer
);
532 static void cmpc_accel_handler(struct acpi_device
*dev
, u32 event
)
535 unsigned char x
, y
, z
;
538 status
= cmpc_get_accel(dev
->handle
, &x
, &y
, &z
);
539 if (ACPI_SUCCESS(status
)) {
540 struct input_dev
*inputdev
= dev_get_drvdata(&dev
->dev
);
542 input_report_abs(inputdev
, ABS_X
, x
);
543 input_report_abs(inputdev
, ABS_Y
, y
);
544 input_report_abs(inputdev
, ABS_Z
, z
);
545 input_sync(inputdev
);
550 static ssize_t
cmpc_accel_sensitivity_show(struct device
*dev
,
551 struct device_attribute
*attr
,
554 struct acpi_device
*acpi
;
555 struct input_dev
*inputdev
;
556 struct cmpc_accel
*accel
;
558 acpi
= to_acpi_device(dev
);
559 inputdev
= dev_get_drvdata(&acpi
->dev
);
560 accel
= dev_get_drvdata(&inputdev
->dev
);
562 return sprintf(buf
, "%d\n", accel
->sensitivity
);
565 static ssize_t
cmpc_accel_sensitivity_store(struct device
*dev
,
566 struct device_attribute
*attr
,
567 const char *buf
, size_t count
)
569 struct acpi_device
*acpi
;
570 struct input_dev
*inputdev
;
571 struct cmpc_accel
*accel
;
572 unsigned long sensitivity
;
575 acpi
= to_acpi_device(dev
);
576 inputdev
= dev_get_drvdata(&acpi
->dev
);
577 accel
= dev_get_drvdata(&inputdev
->dev
);
579 r
= kstrtoul(buf
, 0, &sensitivity
);
583 accel
->sensitivity
= sensitivity
;
584 cmpc_accel_set_sensitivity(acpi
->handle
, sensitivity
);
586 return strnlen(buf
, count
);
589 static struct device_attribute cmpc_accel_sensitivity_attr
= {
590 .attr
= { .name
= "sensitivity", .mode
= 0660 },
591 .show
= cmpc_accel_sensitivity_show
,
592 .store
= cmpc_accel_sensitivity_store
595 static int cmpc_accel_open(struct input_dev
*input
)
597 struct acpi_device
*acpi
;
599 acpi
= to_acpi_device(input
->dev
.parent
);
600 if (ACPI_SUCCESS(cmpc_start_accel(acpi
->handle
)))
605 static void cmpc_accel_close(struct input_dev
*input
)
607 struct acpi_device
*acpi
;
609 acpi
= to_acpi_device(input
->dev
.parent
);
610 cmpc_stop_accel(acpi
->handle
);
613 static void cmpc_accel_idev_init(struct input_dev
*inputdev
)
615 set_bit(EV_ABS
, inputdev
->evbit
);
616 input_set_abs_params(inputdev
, ABS_X
, 0, 255, 8, 0);
617 input_set_abs_params(inputdev
, ABS_Y
, 0, 255, 8, 0);
618 input_set_abs_params(inputdev
, ABS_Z
, 0, 255, 8, 0);
619 inputdev
->open
= cmpc_accel_open
;
620 inputdev
->close
= cmpc_accel_close
;
623 static int cmpc_accel_add(struct acpi_device
*acpi
)
626 struct input_dev
*inputdev
;
627 struct cmpc_accel
*accel
;
629 accel
= kmalloc(sizeof(*accel
), GFP_KERNEL
);
633 accel
->sensitivity
= CMPC_ACCEL_SENSITIVITY_DEFAULT
;
634 cmpc_accel_set_sensitivity(acpi
->handle
, accel
->sensitivity
);
636 error
= device_create_file(&acpi
->dev
, &cmpc_accel_sensitivity_attr
);
640 error
= cmpc_add_acpi_notify_device(acpi
, "cmpc_accel",
641 cmpc_accel_idev_init
);
645 inputdev
= dev_get_drvdata(&acpi
->dev
);
646 dev_set_drvdata(&inputdev
->dev
, accel
);
651 device_remove_file(&acpi
->dev
, &cmpc_accel_sensitivity_attr
);
657 static int cmpc_accel_remove(struct acpi_device
*acpi
)
659 struct input_dev
*inputdev
;
660 struct cmpc_accel
*accel
;
662 inputdev
= dev_get_drvdata(&acpi
->dev
);
663 accel
= dev_get_drvdata(&inputdev
->dev
);
665 device_remove_file(&acpi
->dev
, &cmpc_accel_sensitivity_attr
);
666 return cmpc_remove_acpi_notify_device(acpi
);
669 static const struct acpi_device_id cmpc_accel_device_ids
[] = {
674 static struct acpi_driver cmpc_accel_acpi_driver
= {
675 .owner
= THIS_MODULE
,
676 .name
= "cmpc_accel",
677 .class = "cmpc_accel",
678 .ids
= cmpc_accel_device_ids
,
680 .add
= cmpc_accel_add
,
681 .remove
= cmpc_accel_remove
,
682 .notify
= cmpc_accel_handler
,
690 static acpi_status
cmpc_get_tablet(acpi_handle handle
,
691 unsigned long long *value
)
693 union acpi_object param
;
694 struct acpi_object_list input
;
695 unsigned long long output
;
698 param
.type
= ACPI_TYPE_INTEGER
;
699 param
.integer
.value
= 0x01;
701 input
.pointer
= ¶m
;
702 status
= acpi_evaluate_integer(handle
, "TCMD", &input
, &output
);
703 if (ACPI_SUCCESS(status
))
708 static void cmpc_tablet_handler(struct acpi_device
*dev
, u32 event
)
710 unsigned long long val
= 0;
711 struct input_dev
*inputdev
= dev_get_drvdata(&dev
->dev
);
714 if (ACPI_SUCCESS(cmpc_get_tablet(dev
->handle
, &val
))) {
715 input_report_switch(inputdev
, SW_TABLET_MODE
, !val
);
716 input_sync(inputdev
);
721 static void cmpc_tablet_idev_init(struct input_dev
*inputdev
)
723 unsigned long long val
= 0;
724 struct acpi_device
*acpi
;
726 set_bit(EV_SW
, inputdev
->evbit
);
727 set_bit(SW_TABLET_MODE
, inputdev
->swbit
);
729 acpi
= to_acpi_device(inputdev
->dev
.parent
);
730 if (ACPI_SUCCESS(cmpc_get_tablet(acpi
->handle
, &val
))) {
731 input_report_switch(inputdev
, SW_TABLET_MODE
, !val
);
732 input_sync(inputdev
);
736 static int cmpc_tablet_add(struct acpi_device
*acpi
)
738 return cmpc_add_acpi_notify_device(acpi
, "cmpc_tablet",
739 cmpc_tablet_idev_init
);
742 static int cmpc_tablet_remove(struct acpi_device
*acpi
)
744 return cmpc_remove_acpi_notify_device(acpi
);
747 #ifdef CONFIG_PM_SLEEP
748 static int cmpc_tablet_resume(struct device
*dev
)
750 struct input_dev
*inputdev
= dev_get_drvdata(dev
);
752 unsigned long long val
= 0;
753 if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev
)->handle
, &val
))) {
754 input_report_switch(inputdev
, SW_TABLET_MODE
, !val
);
755 input_sync(inputdev
);
761 static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm
, NULL
, cmpc_tablet_resume
);
763 static const struct acpi_device_id cmpc_tablet_device_ids
[] = {
764 {CMPC_TABLET_HID
, 0},
768 static struct acpi_driver cmpc_tablet_acpi_driver
= {
769 .owner
= THIS_MODULE
,
770 .name
= "cmpc_tablet",
771 .class = "cmpc_tablet",
772 .ids
= cmpc_tablet_device_ids
,
774 .add
= cmpc_tablet_add
,
775 .remove
= cmpc_tablet_remove
,
776 .notify
= cmpc_tablet_handler
,
778 .drv
.pm
= &cmpc_tablet_pm
,
786 static acpi_status
cmpc_get_brightness(acpi_handle handle
,
787 unsigned long long *value
)
789 union acpi_object param
;
790 struct acpi_object_list input
;
791 unsigned long long output
;
794 param
.type
= ACPI_TYPE_INTEGER
;
795 param
.integer
.value
= 0xC0;
797 input
.pointer
= ¶m
;
798 status
= acpi_evaluate_integer(handle
, "GRDI", &input
, &output
);
799 if (ACPI_SUCCESS(status
))
804 static acpi_status
cmpc_set_brightness(acpi_handle handle
,
805 unsigned long long value
)
807 union acpi_object param
[2];
808 struct acpi_object_list input
;
810 unsigned long long output
;
812 param
[0].type
= ACPI_TYPE_INTEGER
;
813 param
[0].integer
.value
= 0xC0;
814 param
[1].type
= ACPI_TYPE_INTEGER
;
815 param
[1].integer
.value
= value
;
817 input
.pointer
= param
;
818 status
= acpi_evaluate_integer(handle
, "GWRI", &input
, &output
);
822 static int cmpc_bl_get_brightness(struct backlight_device
*bd
)
826 unsigned long long brightness
;
828 handle
= bl_get_data(bd
);
829 status
= cmpc_get_brightness(handle
, &brightness
);
830 if (ACPI_SUCCESS(status
))
836 static int cmpc_bl_update_status(struct backlight_device
*bd
)
841 handle
= bl_get_data(bd
);
842 status
= cmpc_set_brightness(handle
, bd
->props
.brightness
);
843 if (ACPI_SUCCESS(status
))
849 static const struct backlight_ops cmpc_bl_ops
= {
850 .get_brightness
= cmpc_bl_get_brightness
,
851 .update_status
= cmpc_bl_update_status
858 static acpi_status
cmpc_get_rfkill_wlan(acpi_handle handle
,
859 unsigned long long *value
)
861 union acpi_object param
;
862 struct acpi_object_list input
;
863 unsigned long long output
;
866 param
.type
= ACPI_TYPE_INTEGER
;
867 param
.integer
.value
= 0xC1;
869 input
.pointer
= ¶m
;
870 status
= acpi_evaluate_integer(handle
, "GRDI", &input
, &output
);
871 if (ACPI_SUCCESS(status
))
876 static acpi_status
cmpc_set_rfkill_wlan(acpi_handle handle
,
877 unsigned long long value
)
879 union acpi_object param
[2];
880 struct acpi_object_list input
;
882 unsigned long long output
;
884 param
[0].type
= ACPI_TYPE_INTEGER
;
885 param
[0].integer
.value
= 0xC1;
886 param
[1].type
= ACPI_TYPE_INTEGER
;
887 param
[1].integer
.value
= value
;
889 input
.pointer
= param
;
890 status
= acpi_evaluate_integer(handle
, "GWRI", &input
, &output
);
894 static void cmpc_rfkill_query(struct rfkill
*rfkill
, void *data
)
898 unsigned long long state
;
902 status
= cmpc_get_rfkill_wlan(handle
, &state
);
903 if (ACPI_SUCCESS(status
)) {
904 blocked
= state
& 1 ? false : true;
905 rfkill_set_sw_state(rfkill
, blocked
);
909 static int cmpc_rfkill_block(void *data
, bool blocked
)
913 unsigned long long state
;
917 status
= cmpc_get_rfkill_wlan(handle
, &state
);
918 if (ACPI_FAILURE(status
))
920 /* Check if we really need to call cmpc_set_rfkill_wlan */
921 is_blocked
= state
& 1 ? false : true;
922 if (is_blocked
!= blocked
) {
923 state
= blocked
? 0 : 1;
924 status
= cmpc_set_rfkill_wlan(handle
, state
);
925 if (ACPI_FAILURE(status
))
931 static const struct rfkill_ops cmpc_rfkill_ops
= {
932 .query
= cmpc_rfkill_query
,
933 .set_block
= cmpc_rfkill_block
,
937 * Common backlight and rfkill code.
941 struct backlight_device
*bd
;
945 static int cmpc_ipml_add(struct acpi_device
*acpi
)
948 struct ipml200_dev
*ipml
;
949 struct backlight_properties props
;
951 ipml
= kmalloc(sizeof(*ipml
), GFP_KERNEL
);
955 memset(&props
, 0, sizeof(struct backlight_properties
));
956 props
.type
= BACKLIGHT_PLATFORM
;
957 props
.max_brightness
= 7;
958 ipml
->bd
= backlight_device_register("cmpc_bl", &acpi
->dev
,
959 acpi
->handle
, &cmpc_bl_ops
,
961 if (IS_ERR(ipml
->bd
)) {
962 retval
= PTR_ERR(ipml
->bd
);
966 ipml
->rf
= rfkill_alloc("cmpc_rfkill", &acpi
->dev
, RFKILL_TYPE_WLAN
,
967 &cmpc_rfkill_ops
, acpi
->handle
);
969 * If RFKILL is disabled, rfkill_alloc will return ERR_PTR(-ENODEV).
970 * This is OK, however, since all other uses of the device will not
974 retval
= rfkill_register(ipml
->rf
);
976 rfkill_destroy(ipml
->rf
);
981 dev_set_drvdata(&acpi
->dev
, ipml
);
989 static int cmpc_ipml_remove(struct acpi_device
*acpi
)
991 struct ipml200_dev
*ipml
;
993 ipml
= dev_get_drvdata(&acpi
->dev
);
995 backlight_device_unregister(ipml
->bd
);
998 rfkill_unregister(ipml
->rf
);
999 rfkill_destroy(ipml
->rf
);
1007 static const struct acpi_device_id cmpc_ipml_device_ids
[] = {
1012 static struct acpi_driver cmpc_ipml_acpi_driver
= {
1013 .owner
= THIS_MODULE
,
1016 .ids
= cmpc_ipml_device_ids
,
1018 .add
= cmpc_ipml_add
,
1019 .remove
= cmpc_ipml_remove
1027 static int cmpc_keys_codes
[] = {
1030 KEY_SWITCHVIDEOMODE
,
1041 static void cmpc_keys_handler(struct acpi_device
*dev
, u32 event
)
1043 struct input_dev
*inputdev
;
1046 if ((event
& 0x0F) < ARRAY_SIZE(cmpc_keys_codes
))
1047 code
= cmpc_keys_codes
[event
& 0x0F];
1048 inputdev
= dev_get_drvdata(&dev
->dev
);
1049 input_report_key(inputdev
, code
, !(event
& 0x10));
1050 input_sync(inputdev
);
1053 static void cmpc_keys_idev_init(struct input_dev
*inputdev
)
1057 set_bit(EV_KEY
, inputdev
->evbit
);
1058 for (i
= 0; cmpc_keys_codes
[i
] != KEY_MAX
; i
++)
1059 set_bit(cmpc_keys_codes
[i
], inputdev
->keybit
);
1062 static int cmpc_keys_add(struct acpi_device
*acpi
)
1064 return cmpc_add_acpi_notify_device(acpi
, "cmpc_keys",
1065 cmpc_keys_idev_init
);
1068 static int cmpc_keys_remove(struct acpi_device
*acpi
)
1070 return cmpc_remove_acpi_notify_device(acpi
);
1073 static const struct acpi_device_id cmpc_keys_device_ids
[] = {
1078 static struct acpi_driver cmpc_keys_acpi_driver
= {
1079 .owner
= THIS_MODULE
,
1080 .name
= "cmpc_keys",
1081 .class = "cmpc_keys",
1082 .ids
= cmpc_keys_device_ids
,
1084 .add
= cmpc_keys_add
,
1085 .remove
= cmpc_keys_remove
,
1086 .notify
= cmpc_keys_handler
,
1092 * General init/exit code.
1095 static int cmpc_init(void)
1099 r
= acpi_bus_register_driver(&cmpc_keys_acpi_driver
);
1103 r
= acpi_bus_register_driver(&cmpc_ipml_acpi_driver
);
1107 r
= acpi_bus_register_driver(&cmpc_tablet_acpi_driver
);
1111 r
= acpi_bus_register_driver(&cmpc_accel_acpi_driver
);
1115 r
= acpi_bus_register_driver(&cmpc_accel_acpi_driver_v4
);
1117 goto failed_accel_v4
;
1122 acpi_bus_unregister_driver(&cmpc_accel_acpi_driver
);
1125 acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver
);
1128 acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver
);
1131 acpi_bus_unregister_driver(&cmpc_keys_acpi_driver
);
1137 static void cmpc_exit(void)
1139 acpi_bus_unregister_driver(&cmpc_accel_acpi_driver_v4
);
1140 acpi_bus_unregister_driver(&cmpc_accel_acpi_driver
);
1141 acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver
);
1142 acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver
);
1143 acpi_bus_unregister_driver(&cmpc_keys_acpi_driver
);
1146 module_init(cmpc_init
);
1147 module_exit(cmpc_exit
);
1149 static const struct acpi_device_id cmpc_device_ids
[] = {
1150 {CMPC_ACCEL_HID
, 0},
1151 {CMPC_ACCEL_HID_V4
, 0},
1152 {CMPC_TABLET_HID
, 0},
1158 MODULE_DEVICE_TABLE(acpi
, cmpc_device_ids
);