1529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
2529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  Copyright (C) 2009  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
3529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *
4529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  This program is free software; you can redistribute it and/or modify
5529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  it under the terms of the GNU General Public License as published by
6529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  the Free Software Foundation; either version 2 of the License, or
7529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  (at your option) any later version.
8529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *
9529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  This program is distributed in the hope that it will be useful,
10529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  GNU General Public License for more details.
13529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *
14529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  You should have received a copy of the GNU General Public License along
15529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  with this program; if not, write to the Free Software Foundation, Inc.,
16529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
18529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
19529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
20529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#include <linux/init.h>
21529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#include <linux/module.h>
225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
23529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#include <linux/workqueue.h>
24529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#include <acpi/acpi_drivers.h>
25529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#include <linux/backlight.h>
26529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#include <linux/input.h>
27d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo#include <linux/rfkill.h>
28529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
29529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza CascardoMODULE_LICENSE("GPL");
30529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
31529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
32529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostruct cmpc_accel {
33529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int sensitivity;
34529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
35529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
36529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo#define CMPC_ACCEL_SENSITIVITY_DEFAULT		5
37529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
38529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
3902e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo#define CMPC_ACCEL_HID		"ACCE0000"
4002e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo#define CMPC_TABLET_HID		"TBLT0000"
41d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo#define CMPC_IPML_HID	"IPML200"
4202e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo#define CMPC_KEYS_HID		"FnBT0000"
4302e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo
44529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
45529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo * Generic input device code.
46529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
47529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
48529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardotypedef void (*input_device_init)(struct input_dev *dev);
49529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
50529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_add_acpi_notify_device(struct acpi_device *acpi, char *name,
51529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				       input_device_init idev_init)
52529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
53529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev;
54529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int error;
55529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
56529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev = input_allocate_device();
57529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (!inputdev)
58529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return -ENOMEM;
59529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev->name = name;
60529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev->dev.parent = &acpi->dev;
61529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	idev_init(inputdev);
62529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	error = input_register_device(inputdev);
63529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (error) {
64529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		input_free_device(inputdev);
65529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return error;
66529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
67529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	dev_set_drvdata(&acpi->dev, inputdev);
68529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return 0;
69529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
70529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
71529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_remove_acpi_notify_device(struct acpi_device *acpi)
72529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
73529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
74529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input_unregister_device(inputdev);
75529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return 0;
76529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
77529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
78529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
79529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo * Accelerometer code.
80529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
81529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_start_accel(acpi_handle handle)
82529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
83529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param[2];
84529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
85529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
86529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
87529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].type = ACPI_TYPE_INTEGER;
88529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].integer.value = 0x3;
89529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].type = ACPI_TYPE_INTEGER;
90529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 2;
91529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = param;
92529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = acpi_evaluate_object(handle, "ACMD", &input, NULL);
93529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return status;
94529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
95529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
96529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_stop_accel(acpi_handle handle)
97529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
98529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param[2];
99529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
100529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
101529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
102529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].type = ACPI_TYPE_INTEGER;
103529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].integer.value = 0x4;
104529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].type = ACPI_TYPE_INTEGER;
105529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 2;
106529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = param;
107529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = acpi_evaluate_object(handle, "ACMD", &input, NULL);
108529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return status;
109529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
110529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
111529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_accel_set_sensitivity(acpi_handle handle, int val)
112529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
113529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param[2];
114529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
115529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
116529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].type = ACPI_TYPE_INTEGER;
117529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].integer.value = 0x02;
118529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].type = ACPI_TYPE_INTEGER;
119529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].integer.value = val;
120529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 2;
121529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = param;
122529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return acpi_evaluate_object(handle, "ACMD", &input, NULL);
123529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
124529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
125529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_get_accel(acpi_handle handle,
126529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				  unsigned char *x,
127529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				  unsigned char *y,
128529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				  unsigned char *z)
129529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
130529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param[2];
131529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
132529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, 0 };
133529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned char *locs;
134529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
135529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
136529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].type = ACPI_TYPE_INTEGER;
137529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].integer.value = 0x01;
138529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].type = ACPI_TYPE_INTEGER;
139529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 2;
140529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = param;
141529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = acpi_evaluate_object(handle, "ACMD", &input, &output);
142529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status)) {
143529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		union acpi_object *obj;
144529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		obj = output.pointer;
145529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		locs = obj->buffer.pointer;
146529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		*x = locs[0];
147529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		*y = locs[1];
148529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		*z = locs[2];
149529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		kfree(output.pointer);
150529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
151529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return status;
152529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
153529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
154529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_accel_handler(struct acpi_device *dev, u32 event)
155529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
156529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (event == 0x81) {
157529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		unsigned char x, y, z;
158529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		acpi_status status;
159529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
160529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		status = cmpc_get_accel(dev->handle, &x, &y, &z);
161529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		if (ACPI_SUCCESS(status)) {
162529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo			struct input_dev *inputdev = dev_get_drvdata(&dev->dev);
163529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
164529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo			input_report_abs(inputdev, ABS_X, x);
165529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo			input_report_abs(inputdev, ABS_Y, y);
166529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo			input_report_abs(inputdev, ABS_Z, z);
167529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo			input_sync(inputdev);
168529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		}
169529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
170529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
171529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
172529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic ssize_t cmpc_accel_sensitivity_show(struct device *dev,
173529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					   struct device_attribute *attr,
174529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					   char *buf)
175529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
176529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_device *acpi;
177529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev;
178529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct cmpc_accel *accel;
179529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
180529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi = to_acpi_device(dev);
181529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev = dev_get_drvdata(&acpi->dev);
182529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	accel = dev_get_drvdata(&inputdev->dev);
183529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
184529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return sprintf(buf, "%d\n", accel->sensitivity);
185529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
186529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
187529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic ssize_t cmpc_accel_sensitivity_store(struct device *dev,
188529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					    struct device_attribute *attr,
189529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					    const char *buf, size_t count)
190529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
191529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_device *acpi;
192529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev;
193529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct cmpc_accel *accel;
194529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long sensitivity;
195529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int r;
196529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
197529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi = to_acpi_device(dev);
198529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev = dev_get_drvdata(&acpi->dev);
199529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	accel = dev_get_drvdata(&inputdev->dev);
200529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
201529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	r = strict_strtoul(buf, 0, &sensitivity);
202529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (r)
203529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return r;
204529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
205529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	accel->sensitivity = sensitivity;
206529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	cmpc_accel_set_sensitivity(acpi->handle, sensitivity);
207529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
208529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return strnlen(buf, count);
209529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
210529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
211df92754dddc77003c6be9540ff91bf89fcfce890Axel Linstatic struct device_attribute cmpc_accel_sensitivity_attr = {
212529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.attr = { .name = "sensitivity", .mode = 0660 },
213529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.show = cmpc_accel_sensitivity_show,
214529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.store = cmpc_accel_sensitivity_store
215529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
216529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
217529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_accel_open(struct input_dev *input)
218529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
219529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_device *acpi;
220529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
221529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi = to_acpi_device(input->dev.parent);
222529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(cmpc_start_accel(acpi->handle)))
223529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return 0;
224529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return -EIO;
225529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
226529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
227529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_accel_close(struct input_dev *input)
228529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
229529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_device *acpi;
230529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
231529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi = to_acpi_device(input->dev.parent);
232529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	cmpc_stop_accel(acpi->handle);
233529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
234529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
235529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_accel_idev_init(struct input_dev *inputdev)
236529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
237529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	set_bit(EV_ABS, inputdev->evbit);
238529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input_set_abs_params(inputdev, ABS_X, 0, 255, 8, 0);
239529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input_set_abs_params(inputdev, ABS_Y, 0, 255, 8, 0);
240529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input_set_abs_params(inputdev, ABS_Z, 0, 255, 8, 0);
241529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev->open = cmpc_accel_open;
242529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev->close = cmpc_accel_close;
243529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
244529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
245529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_accel_add(struct acpi_device *acpi)
246529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
247529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int error;
248529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev;
249529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct cmpc_accel *accel;
250529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
251529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	accel = kmalloc(sizeof(*accel), GFP_KERNEL);
252529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (!accel)
253529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return -ENOMEM;
254529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
255529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT;
256529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	cmpc_accel_set_sensitivity(acpi->handle, accel->sensitivity);
257529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
258529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr);
259529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (error)
260529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		goto failed_file;
261529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
262529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel",
263529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					    cmpc_accel_idev_init);
264529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (error)
265529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		goto failed_input;
266529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
267529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev = dev_get_drvdata(&acpi->dev);
268529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	dev_set_drvdata(&inputdev->dev, accel);
269529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
270529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return 0;
271529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
272529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardofailed_input:
273529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr);
274529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardofailed_file:
275529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	kfree(accel);
276529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return error;
277529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
278529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
279529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_accel_remove(struct acpi_device *acpi, int type)
280529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
281529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev;
282529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct cmpc_accel *accel;
283529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
284529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	inputdev = dev_get_drvdata(&acpi->dev);
285529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	accel = dev_get_drvdata(&inputdev->dev);
286529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
287529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr);
288529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return cmpc_remove_acpi_notify_device(acpi);
289529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
290529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
291529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic const struct acpi_device_id cmpc_accel_device_ids[] = {
29202e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{CMPC_ACCEL_HID, 0},
293529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	{"", 0}
294529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
295529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
296529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic struct acpi_driver cmpc_accel_acpi_driver = {
297529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.owner = THIS_MODULE,
298529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.name = "cmpc_accel",
299529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.class = "cmpc_accel",
300529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ids = cmpc_accel_device_ids,
301529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ops = {
302529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.add = cmpc_accel_add,
303529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.remove = cmpc_accel_remove,
304529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.notify = cmpc_accel_handler,
305529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
306529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
307529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
308529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
309529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
310529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo * Tablet mode code.
311529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
312529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_get_tablet(acpi_handle handle,
313529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				   unsigned long long *value)
314529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
315529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param;
316529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
317529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long output;
318529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
319529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
320529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param.type = ACPI_TYPE_INTEGER;
321529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param.integer.value = 0x01;
322529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 1;
323529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = &param;
324529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = acpi_evaluate_integer(handle, "TCMD", &input, &output);
325529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status))
326529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		*value = output;
327529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return status;
328529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
329529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
330529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_tablet_handler(struct acpi_device *dev, u32 event)
331529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
332529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long val = 0;
333529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev = dev_get_drvdata(&dev->dev);
334529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
335529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (event == 0x81) {
336529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val)))
337529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo			input_report_switch(inputdev, SW_TABLET_MODE, !val);
338529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
339529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
340529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
341529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_tablet_idev_init(struct input_dev *inputdev)
342529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
343529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long val = 0;
344529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_device *acpi;
345529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
346529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	set_bit(EV_SW, inputdev->evbit);
347529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	set_bit(SW_TABLET_MODE, inputdev->swbit);
348529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
349529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi = to_acpi_device(inputdev->dev.parent);
350529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
351529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		input_report_switch(inputdev, SW_TABLET_MODE, !val);
352529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
353529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
354529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_tablet_add(struct acpi_device *acpi)
355529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
356529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return cmpc_add_acpi_notify_device(acpi, "cmpc_tablet",
357529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					   cmpc_tablet_idev_init);
358529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
359529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
360529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_tablet_remove(struct acpi_device *acpi, int type)
361529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
362529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return cmpc_remove_acpi_notify_device(acpi);
363529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
364529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
365529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_tablet_resume(struct acpi_device *acpi)
366529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
367529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
368529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long val = 0;
369529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
370529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		input_report_switch(inputdev, SW_TABLET_MODE, !val);
371529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return 0;
372529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
373529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
374529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic const struct acpi_device_id cmpc_tablet_device_ids[] = {
37502e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{CMPC_TABLET_HID, 0},
376529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	{"", 0}
377529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
378529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
379529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic struct acpi_driver cmpc_tablet_acpi_driver = {
380529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.owner = THIS_MODULE,
381529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.name = "cmpc_tablet",
382529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.class = "cmpc_tablet",
383529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ids = cmpc_tablet_device_ids,
384529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ops = {
385529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.add = cmpc_tablet_add,
386529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.remove = cmpc_tablet_remove,
387529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.resume = cmpc_tablet_resume,
388529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.notify = cmpc_tablet_handler,
389529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
390529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
391529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
392529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
393529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
394529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo * Backlight code.
395529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
396529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
397529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_get_brightness(acpi_handle handle,
398529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				       unsigned long long *value)
399529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
400529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param;
401529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
402529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long output;
403529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
404529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
405529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param.type = ACPI_TYPE_INTEGER;
406529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param.integer.value = 0xC0;
407529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 1;
408529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = &param;
409529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = acpi_evaluate_integer(handle, "GRDI", &input, &output);
410529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status))
411529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		*value = output;
412529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return status;
413529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
414529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
415529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic acpi_status cmpc_set_brightness(acpi_handle handle,
416529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo				       unsigned long long value)
417529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
418529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	union acpi_object param[2];
419529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct acpi_object_list input;
420529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
421529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long output;
422529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
423529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].type = ACPI_TYPE_INTEGER;
424529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[0].integer.value = 0xC0;
425529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].type = ACPI_TYPE_INTEGER;
426529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	param[1].integer.value = value;
427529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.count = 2;
428529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input.pointer = param;
429529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = acpi_evaluate_integer(handle, "GWRI", &input, &output);
430529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return status;
431529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
432529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
433529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_bl_get_brightness(struct backlight_device *bd)
434529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
435529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
436529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_handle handle;
437529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	unsigned long long brightness;
438529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
439529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	handle = bl_get_data(bd);
440529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = cmpc_get_brightness(handle, &brightness);
441529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status))
442529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return brightness;
443529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	else
444529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return -1;
445529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
446529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
447529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_bl_update_status(struct backlight_device *bd)
448529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
449529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_status status;
450529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_handle handle;
451529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
452529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	handle = bl_get_data(bd);
453529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	status = cmpc_set_brightness(handle, bd->props.brightness);
454529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status))
455529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return 0;
456529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	else
457529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		return -1;
458529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
459529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
460f0af78991363d704694a3618b638662c97d8a110Bruno Prémontstatic const struct backlight_ops cmpc_bl_ops = {
461529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.get_brightness = cmpc_bl_get_brightness,
462529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.update_status = cmpc_bl_update_status
463529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
464529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
465d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo/*
466d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo * RFKILL code.
467d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo */
468d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
469d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic acpi_status cmpc_get_rfkill_wlan(acpi_handle handle,
470d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo					unsigned long long *value)
471529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
472d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	union acpi_object param;
473d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	struct acpi_object_list input;
474d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	unsigned long long output;
475d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_status status;
476d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
477d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	param.type = ACPI_TYPE_INTEGER;
478d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	param.integer.value = 0xC1;
479d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	input.count = 1;
480d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	input.pointer = &param;
481d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	status = acpi_evaluate_integer(handle, "GRDI", &input, &output);
482d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status))
483d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		*value = output;
484d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	return status;
485d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo}
486d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
487d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic acpi_status cmpc_set_rfkill_wlan(acpi_handle handle,
488d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo					unsigned long long value)
489d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo{
490d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	union acpi_object param[2];
491d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	struct acpi_object_list input;
492d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_status status;
493d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	unsigned long long output;
494d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
495d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	param[0].type = ACPI_TYPE_INTEGER;
496d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	param[0].integer.value = 0xC1;
497d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	param[1].type = ACPI_TYPE_INTEGER;
498d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	param[1].integer.value = value;
499d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	input.count = 2;
500d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	input.pointer = param;
501d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	status = acpi_evaluate_integer(handle, "GWRI", &input, &output);
502d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	return status;
503d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo}
504d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
505d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic void cmpc_rfkill_query(struct rfkill *rfkill, void *data)
506d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo{
507d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_status status;
508d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_handle handle;
509d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	unsigned long long state;
510d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	bool blocked;
511d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
512d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	handle = data;
513d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	status = cmpc_get_rfkill_wlan(handle, &state);
514d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	if (ACPI_SUCCESS(status)) {
515d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		blocked = state & 1 ? false : true;
516d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		rfkill_set_sw_state(rfkill, blocked);
517d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	}
518d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo}
519d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
520d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic int cmpc_rfkill_block(void *data, bool blocked)
521d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo{
522d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_status status;
523d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_handle handle;
524d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	unsigned long long state;
525698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski	bool is_blocked;
526d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
527d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	handle = data;
528d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	status = cmpc_get_rfkill_wlan(handle, &state);
529d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	if (ACPI_FAILURE(status))
530d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		return -ENODEV;
531698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski	/* Check if we really need to call cmpc_set_rfkill_wlan */
532698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski	is_blocked = state & 1 ? false : true;
533698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski	if (is_blocked != blocked) {
534698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski		state = blocked ? 0 : 1;
535698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski		status = cmpc_set_rfkill_wlan(handle, state);
536698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski		if (ACPI_FAILURE(status))
537698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski			return -ENODEV;
538698e1641a37f833dd26ee2fde5eed426cd97880bHerton Ronaldo Krzesinski	}
539d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	return 0;
540d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo}
541d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
542d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic const struct rfkill_ops cmpc_rfkill_ops = {
543d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	.query = cmpc_rfkill_query,
544d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	.set_block = cmpc_rfkill_block,
545d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo};
546d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
547d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo/*
548d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo * Common backlight and rfkill code.
549d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo */
550d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
551d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostruct ipml200_dev {
552529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct backlight_device *bd;
553d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	struct rfkill *rf;
554d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo};
555d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
556d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic int cmpc_ipml_add(struct acpi_device *acpi)
557d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo{
558d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	int retval;
559d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	struct ipml200_dev *ipml;
560d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	struct backlight_properties props;
561d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
562d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	ipml = kmalloc(sizeof(*ipml), GFP_KERNEL);
563d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	if (ipml == NULL)
564d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		return -ENOMEM;
565529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
566a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett	memset(&props, 0, sizeof(struct backlight_properties));
567bb7ca747f8d6243b3943c5b133048652020f4a50Matthew Garrett	props.type = BACKLIGHT_PLATFORM;
568a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett	props.max_brightness = 7;
569d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
570d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo					     acpi->handle, &cmpc_bl_ops,
571d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo					     &props);
572d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	if (IS_ERR(ipml->bd)) {
573d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		retval = PTR_ERR(ipml->bd);
574d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		goto out_bd;
575d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	}
576d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
577d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	ipml->rf = rfkill_alloc("cmpc_rfkill", &acpi->dev, RFKILL_TYPE_WLAN,
578d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo				&cmpc_rfkill_ops, acpi->handle);
579b95d13eaf3d4ea093aba95c7f615f3b10708a2c4Thadeu Lima de Souza Cascardo	/*
580b95d13eaf3d4ea093aba95c7f615f3b10708a2c4Thadeu Lima de Souza Cascardo	 * If RFKILL is disabled, rfkill_alloc will return ERR_PTR(-ENODEV).
581b95d13eaf3d4ea093aba95c7f615f3b10708a2c4Thadeu Lima de Souza Cascardo	 * This is OK, however, since all other uses of the device will not
582b95d13eaf3d4ea093aba95c7f615f3b10708a2c4Thadeu Lima de Souza Cascardo	 * derefence it.
583b95d13eaf3d4ea093aba95c7f615f3b10708a2c4Thadeu Lima de Souza Cascardo	 */
584b95d13eaf3d4ea093aba95c7f615f3b10708a2c4Thadeu Lima de Souza Cascardo	if (ipml->rf) {
585d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		retval = rfkill_register(ipml->rf);
586d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		if (retval) {
587d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo			rfkill_destroy(ipml->rf);
588d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo			ipml->rf = NULL;
589d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		}
590d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	}
591d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
592d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	dev_set_drvdata(&acpi->dev, ipml);
593529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return 0;
594d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
595d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardoout_bd:
596d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	kfree(ipml);
597d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	return retval;
598529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
599529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
600d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic int cmpc_ipml_remove(struct acpi_device *acpi, int type)
601529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
602d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	struct ipml200_dev *ipml;
603d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
604d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	ipml = dev_get_drvdata(&acpi->dev);
605d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
606d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	backlight_device_unregister(ipml->bd);
607d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
608d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	if (ipml->rf) {
609d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		rfkill_unregister(ipml->rf);
610d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		rfkill_destroy(ipml->rf);
611d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	}
612d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo
613d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	kfree(ipml);
614529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
615529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return 0;
616529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
617529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
618d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic const struct acpi_device_id cmpc_ipml_device_ids[] = {
619d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	{CMPC_IPML_HID, 0},
620529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	{"", 0}
621529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
622529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
623d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardostatic struct acpi_driver cmpc_ipml_acpi_driver = {
624529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.owner = THIS_MODULE,
625529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.name = "cmpc",
626529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.class = "cmpc",
627d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	.ids = cmpc_ipml_device_ids,
628529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ops = {
629d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		.add = cmpc_ipml_add,
630d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo		.remove = cmpc_ipml_remove
631529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
632529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
633529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
634529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
635529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
636529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo * Extra keys code.
637529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
638529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_keys_codes[] = {
639529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_UNKNOWN,
640529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_WLAN,
641529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_SWITCHVIDEOMODE,
642529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_BRIGHTNESSDOWN,
643529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_BRIGHTNESSUP,
644529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_VENDOR,
645881a6c25a8453388e3190de94a5e105439a9f806Thadeu Lima de Souza Cascardo	KEY_UNKNOWN,
646881a6c25a8453388e3190de94a5e105439a9f806Thadeu Lima de Souza Cascardo	KEY_CAMERA,
647881a6c25a8453388e3190de94a5e105439a9f806Thadeu Lima de Souza Cascardo	KEY_BACK,
648881a6c25a8453388e3190de94a5e105439a9f806Thadeu Lima de Souza Cascardo	KEY_FORWARD,
649529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	KEY_MAX
650529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
651529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
652529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_keys_handler(struct acpi_device *dev, u32 event)
653529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
654529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	struct input_dev *inputdev;
655529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int code = KEY_MAX;
656529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
657529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes))
658529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		code = cmpc_keys_codes[event & 0x0F];
6593098064d3b4a9bf9d2855b2a89599ad77695e324Joe Perches	inputdev = dev_get_drvdata(&dev->dev);
660529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	input_report_key(inputdev, code, !(event & 0x10));
66172135d21b587debcbcc57e0dbcc8bcfa4dacb661Herton Ronaldo Krzesinski	input_sync(inputdev);
662529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
663529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
664529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_keys_idev_init(struct input_dev *inputdev)
665529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
666529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int i;
667529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
668529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	set_bit(EV_KEY, inputdev->evbit);
669529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	for (i = 0; cmpc_keys_codes[i] != KEY_MAX; i++)
670529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		set_bit(cmpc_keys_codes[i], inputdev->keybit);
671529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
672529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
673529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_keys_add(struct acpi_device *acpi)
674529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
675529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return cmpc_add_acpi_notify_device(acpi, "cmpc_keys",
676529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo					   cmpc_keys_idev_init);
677529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
678529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
679529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_keys_remove(struct acpi_device *acpi, int type)
680529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
681529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return cmpc_remove_acpi_notify_device(acpi);
682529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
683529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
684529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic const struct acpi_device_id cmpc_keys_device_ids[] = {
68502e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{CMPC_KEYS_HID, 0},
686529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	{"", 0}
687529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
688529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
689529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic struct acpi_driver cmpc_keys_acpi_driver = {
690529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.owner = THIS_MODULE,
691529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.name = "cmpc_keys",
692529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.class = "cmpc_keys",
693529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ids = cmpc_keys_device_ids,
694529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	.ops = {
695529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.add = cmpc_keys_add,
696529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.remove = cmpc_keys_remove,
697529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		.notify = cmpc_keys_handler,
698529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	}
699529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo};
700529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
701529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
702529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo/*
703529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo * General init/exit code.
704529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo */
705529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
706529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic int cmpc_init(void)
707529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
708529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	int r;
709529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
710529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	r = acpi_bus_register_driver(&cmpc_keys_acpi_driver);
711529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (r)
712529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		goto failed_keys;
713529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
714d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	r = acpi_bus_register_driver(&cmpc_ipml_acpi_driver);
715529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (r)
716529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		goto failed_bl;
717529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
718529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	r = acpi_bus_register_driver(&cmpc_tablet_acpi_driver);
719529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (r)
720529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		goto failed_tablet;
721529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
722529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	r = acpi_bus_register_driver(&cmpc_accel_acpi_driver);
723529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	if (r)
724529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo		goto failed_accel;
725529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
726529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return r;
727529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
728529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardofailed_accel:
729529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver);
730529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
731529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardofailed_tablet:
732d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver);
733529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
734529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardofailed_bl:
735529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_keys_acpi_driver);
736529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
737529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardofailed_keys:
738529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	return r;
739529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
740529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
741529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardostatic void cmpc_exit(void)
742529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo{
743529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_accel_acpi_driver);
744529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver);
745d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver);
746529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo	acpi_bus_unregister_driver(&cmpc_keys_acpi_driver);
747529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo}
748529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardo
749529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardomodule_init(cmpc_init);
750529aa8cb0a59367d08883f818e8c47028e819d0dThadeu Lima de Souza Cascardomodule_exit(cmpc_exit);
75102e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo
75202e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardostatic const struct acpi_device_id cmpc_device_ids[] = {
75302e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{CMPC_ACCEL_HID, 0},
75402e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{CMPC_TABLET_HID, 0},
755d5c051f1080e0eec55f3fc42c37d941681941628Thadeu Lima de Souza Cascardo	{CMPC_IPML_HID, 0},
75602e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{CMPC_KEYS_HID, 0},
75702e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo	{"", 0}
75802e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo};
75902e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza Cascardo
76002e77a55f7b7e36888e39c62439fedb90ae4e808Thadeu Lima de Souza CascardoMODULE_DEVICE_TABLE(acpi, cmpc_device_ids);
761