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 = ¶m; 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 = ¶m; 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 = ¶m; 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